Auto-Tag progress window added

More auto-tag and other stuff

git-svn-id: http://comictagger.googlecode.com/svn/trunk@322 6c5673fe-1810-88d6-992b-cd32ca31540c
This commit is contained in:
beville 2013-01-22 04:09:08 +00:00
parent b712226b1e
commit 221923607a
12 changed files with 333 additions and 44 deletions

60
autotagprogresswindow.py Normal file
View File

@ -0,0 +1,60 @@
"""
A PyQT4 dialog to show ID log and progress
"""
"""
Copyright 2012 Anthony Beville
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
import sys
from PyQt4 import QtCore, QtGui, uic
import os
from settings import ComicTaggerSettings
class AutoTagProgressWindow(QtGui.QDialog):
def __init__(self, parent):
super(AutoTagProgressWindow, self).__init__(parent)
uic.loadUi(os.path.join(ComicTaggerSettings.baseDir(), 'autotagprogresswindow.ui' ), self)
self.lblTest.setPixmap(QtGui.QPixmap(os.path.join(ComicTaggerSettings.baseDir(), 'graphics/nocover.png' )))
self.lblArchive.setPixmap(QtGui.QPixmap(os.path.join(ComicTaggerSettings.baseDir(), 'graphics/nocover.png' )))
self.isdone = False
def setArchiveImage( self, img_data):
self.setCoverImage( img_data, self.lblArchive )
def setTestImage( self, img_data):
self.setCoverImage( img_data, self.lblTest )
def setCoverImage( self, img_data , label):
if img_data is not None:
img = QtGui.QImage()
img.loadFromData( img_data )
label.setPixmap(QtGui.QPixmap(img))
label.setScaledContents(True)
else:
label.setPixmap(QtGui.QPixmap(os.path.join(ComicTaggerSettings.baseDir(), 'graphics/nocover.png' )))
label.setScaledContents(True)
QtCore.QCoreApplication.processEvents()
QtCore.QCoreApplication.processEvents()
def reject(self):
QtGui.QDialog.reject(self)
self.isdone = True

152
autotagprogresswindow.ui Normal file
View File

@ -0,0 +1,152 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>dialogIssueSelect</class>
<widget class="QDialog" name="dialogIssueSelect">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>865</width>
<height>413</height>
</rect>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="windowTitle">
<string>Issue Identification Progress</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QProgressBar" name="progressBar">
<property name="value">
<number>0</number>
</property>
<property name="invertedAppearance">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label">
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<widget class="QTextEdit" name="textEdit">
<property name="font">
<font>
<family>Courier New</family>
<weight>75</weight>
<bold>true</bold>
</font>
</property>
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel</set>
</property>
<property name="centerButtons">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QLabel" name="lblArchive">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>110</width>
<height>165</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>110</width>
<height>165</height>
</size>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="lblTest">
<property name="minimumSize">
<size>
<width>110</width>
<height>165</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>110</width>
<height>165</height>
</size>
</property>
<property name="text">
<string>TextLabel</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>dialogIssueSelect</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>dialogIssueSelect</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -38,12 +38,15 @@ class AutoTagStartWindow(QtGui.QDialog):
self.settings = settings
self.cbxNoAutoSaveOnLow.setCheckState( QtCore.Qt.Unchecked )
self.cbxDontUseYear.setCheckState( QtCore.Qt.Unchecked )
self.noAutoSaveOnLow = False
self.dontUseYear = False
def accept( self ):
QtGui.QDialog.accept(self)
self.noAutoSaveOnLow = self.cbxNoAutoSaveOnLow.isChecked()
self.dontUseYear = self.cbxDontUseYear.isChecked()

View File

@ -50,6 +50,13 @@
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="cbxDontUseYear">
<property name="text">
<string>Don't use publication year in indentification process</string>
</property>
</widget>
</item>
</layout>
</item>
<item>

View File

@ -294,7 +294,7 @@ def process_file_cli( filename, opts, settings, match_results ):
if not opts.dryrun:
md = ca.readMetadata( opts.copy_source )
if settings.apply_cbl_transform_on_bulk_operation:
if settings.apply_cbl_transform_on_bulk_operation and opts.data_style == MetaDataStyle.CBI:
md = CBLTransformer( md, settings ).apply()
if not ca.writeMetadata( md, opts.data_style ):

View File

@ -106,7 +106,10 @@ class FileRenamer:
new_name += ext
# some tweaks to keep various filesystems happy
new_name = new_name.replace("/", "-")
new_name = new_name.replace(":", "-")
return new_name

View File

@ -41,13 +41,19 @@
<property name="text">
<string>File</string>
</property>
<property name="toolTip">
<string>File Name</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</column>
<column>
<property name="text">
<string>CR</string>
</property>
<property name="toolTip">
<string/>
<string>Has ComicRack Tags</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
@ -57,6 +63,9 @@
<property name="text">
<string>CBL</string>
</property>
<property name="toolTip">
<string>Has ComicBookLover Tags</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
@ -65,16 +74,34 @@
<property name="text">
<string>Type</string>
</property>
<property name="toolTip">
<string>Archive Type</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</column>
<column>
<property name="text">
<string>R/O</string>
</property>
<property name="toolTip">
<string>Read-Only</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</column>
<column>
<property name="text">
<string>Folder</string>
</property>
<property name="toolTip">
<string>File Location</string>
</property>
<property name="textAlignment">
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
</property>
</column>
</widget>
</item>

View File

@ -72,6 +72,7 @@ class IssueIdentifier:
self.additional_metadata = GenericMetadata()
self.output_function = IssueIdentifier.defaultWriteOutput
self.callback = None
self.coverUrlCallback = None
self.search_result = self.ResultNoMatches
self.cover_page_index = 0
@ -97,7 +98,7 @@ class IssueIdentifier:
def setOutputFunction( self, func ):
self.output_function = func
pass
def calculateHash( self, image_data ):
if self.image_hasher == '3':
return ImageHasher( data=image_data ).dct_average_hash()
@ -130,6 +131,9 @@ class IssueIdentifier:
def setProgressCallback( self, cb_func ):
self.callback = cb_func
def setCoverURLCallback( self, cb_func ):
self.coverUrlCallback = cb_func
def getSearchKeys( self ):
@ -306,7 +310,6 @@ class IssueIdentifier:
if self.callback is not None:
self.callback( 0, len(series_shortlist))
# now sort the list by name length
series_shortlist.sort(key=lambda x: len(x['name']), reverse=False)
@ -358,6 +361,9 @@ class IssueIdentifier:
self.match_list = []
return self.match_list
if self.coverUrlCallback is not None:
self.coverUrlCallback( url_image_data )
url_image_hash = self.calculateHash( url_image_data )
score = ImageHasher.hamming_distance(cover_hash, url_image_hash)
@ -387,7 +393,6 @@ class IssueIdentifier:
break
self.log_msg( "" )
if len(self.match_list) == 0:
self.log_msg( ":-( no matches!" )

View File

@ -23,6 +23,8 @@ from PyQt4 import QtCore, QtGui, uic
from settings import ComicTaggerSettings
from settingswindow import SettingsWindow
from filerenamer import FileRenamer
from options import MetaDataStyle
import os
import utils
@ -32,6 +34,7 @@ class RenameWindow(QtGui.QDialog):
super(RenameWindow, self).__init__(parent)
uic.loadUi(os.path.join(ComicTaggerSettings.baseDir(), 'renamewindow.ui' ), self)
self.label.setText("Preview (based on {0} tags):".format(MetaDataStyle.name[data_style]))
self.settings = settings
self.comic_archive_list = comic_archive_list

View File

@ -334,7 +334,7 @@
<item row="1" column="0">
<widget class="QCheckBox" name="cbxApplyCBLTransformOnBatchOperation">
<property name="text">
<string>Apply CBL Transforms on Batch/CLI Operations</string>
<string>Apply CBL Transforms on Batch Copy Operations to CBL Tags</string>
</property>
</widget>
</item>

View File

@ -51,6 +51,7 @@ from exportwindow import ExportWindow, ExportConflictOpts
from pageloader import PageLoader
from issueidentifier import IssueIdentifier
from autotagstartwindow import AutoTagStartWindow
from autotagprogresswindow import AutoTagProgressWindow
import utils
import ctversion
@ -489,7 +490,6 @@ class TaggerWindow( QtGui.QMainWindow):
self.lblCover.setPixmap(QtGui.QPixmap(img))
self.lblCover.setScaledContents(True)
def updateMenus( self ):
# First just disable all the questionable items
@ -1468,7 +1468,7 @@ class TaggerWindow( QtGui.QMainWindow):
print "Network error while getting issue details. Save aborted"
if cv_md is not None:
if self.settings.apply_cbl_transform_on_bulk_operation:
if self.settings.apply_cbl_transform_on_cv_import:
cv_md = CBLTransformer( cv_md, self.settings ).apply()
QtGui.QApplication.restoreOverrideCursor()
@ -1476,7 +1476,7 @@ class TaggerWindow( QtGui.QMainWindow):
return cv_md
def identifyAndTagSingleArchive( self, ca, match_results, abortOnLowConfidence ):
def identifyAndTagSingleArchive( self, ca, match_results, abortOnLowConfidence, dontUseYear ):
success = False
ii = IssueIdentifier( ca, self.settings )
@ -1491,14 +1491,20 @@ class TaggerWindow( QtGui.QMainWindow):
def myoutput( text ):
IssueIdentifier.defaultWriteOutput( text )
self.atprogdialog.textEdit.ensureCursorVisible()
self.atprogdialog.textEdit.insertPlainText(text)
QtCore.QCoreApplication.processEvents()
QtCore.QCoreApplication.processEvents()
QtCore.QCoreApplication.processEvents()
if dontUseYear:
md.year = None
ii.setAdditionalMetadata( md )
ii.onlyUseAdditionalMetaData = True
ii.setOutputFunction( myoutput )
ii.cover_page_index = md.getCoverPageIndexList()[0]
ii.setCoverURLCallback( self.atprogdialog.setTestImage )
matches = ii.search()
result = ii.search_result
@ -1569,41 +1575,66 @@ class TaggerWindow( QtGui.QMainWindow):
dlg.setModal( True )
if not dlg.exec_():
return
progdialog = QtGui.QProgressDialog("", "Cancel", 0, len(ca_list), self)
progdialog.setWindowTitle( "Auto-Tagging" )
progdialog.setWindowModality(QtCore.Qt.WindowModal)
progdialog.show()
self.atprogdialog = AutoTagProgressWindow( self)
self.atprogdialog.setModal(True)
#self.progdialog.rejected.connect( self.identifyCancel )
self.atprogdialog.show()
self.atprogdialog.progressBar.setMaximum( len(ca_list) )
self.atprogdialog.setWindowTitle( "Auto-Tagging" )
prog_idx = 0
match_results = OnlineMatchResults()
for ca in ca_list:
cover_idx = ca.readMetadata(style).getCoverPageIndexList()[0]
image_data = ca.getPage( cover_idx )
self.atprogdialog.setArchiveImage( image_data )
self.atprogdialog.setTestImage( None )
QtCore.QCoreApplication.processEvents()
if progdialog.wasCanceled():
if self.atprogdialog.isdone:
break
progdialog.setValue(prog_idx)
self.atprogdialog.progressBar.setValue( prog_idx )
prog_idx += 1
progdialog.setLabelText( ca.path )
progdialog.setAutoClose( False )
self.atprogdialog.label.setText( ca.path )
QtCore.QCoreApplication.processEvents()
if ca.isWritable():
success, match_results = self.identifyAndTagSingleArchive( ca, match_results, dlg.noAutoSaveOnLow )
success, match_results = self.identifyAndTagSingleArchive( ca, match_results, dlg.noAutoSaveOnLow, dlg.dontUseYear )
#if not success:
# QtGui.QMessageBox.warning(self, self.tr("Auto-Tag failed"),
# self.tr("The tagging operation seemed to fail for {0} Operation aborted!".format(ca.path)))
# break
print "Good", match_results.goodMatches
print "multipleMatches", match_results.multipleMatches
print "noMatches", match_results.noMatches
print "fetchDataFailures", match_results.fetchDataFailures
print "writeFailures", match_results.writeFailures
progdialog.close()
self.atprogdialog.close()
self.fileSelectionList.updateSelectedRows()
self.loadArchive( self.fileSelectionList.getCurrentArchive() )
self.atprogdialog = None
summary = ""
summary += "Successfully tagged archives: {0}\n".format( len(match_results.goodMatches))
if len ( match_results.multipleMatches ) > 0:
summary += "Archives with multiple matches: {0}\n".format( len(match_results.multipleMatches))
if len ( match_results.noMatches ) > 0:
summary += "Archives with no matches: {0}\n".format( len(match_results.noMatches))
if len ( match_results.fetchDataFailures ) > 0:
summary += "Archives that failed due to data fetch errors: {0}\n".format( len(match_results.fetchDataFailures))
if len ( match_results.writeFailures ) > 0:
summary += "Archives that failed due to file writing errors: {0}\n".format( len(match_results.writeFailures))
if len ( match_results.multipleMatches ) > 0:
summary += "\n\nDo you want to manually select the ones with multiple matches now?"
reply = QtGui.QMessageBox.question(self,
self.tr("Auto-Tag Summary"),
self.tr(summary),
QtGui.QMessageBox.Yes, QtGui.QMessageBox.No )
if reply == QtGui.QMessageBox.Yes:
print "TBD"
else:
QtGui.QMessageBox.information(self, self.tr("Auto-Tag Summary"), self.tr(summary))

View File

@ -2,36 +2,34 @@
Features
-----------------------------------------------------
Re-arrange main form layout
New menu graphics
auto tag
open folder vs file
Multi-file:
File list:
Delete archive function??
change menu order
Batch Functions:
Batch Auto-Select
Start/Options Dialog
Progress Dialog - maybe reuse
-Show compared images to show progress in a sexy way
Auto-Tag
Interactive dialog at end
Summary Dialog
Rename
check-box for rows?
Batch Tag Copy
Disallow overwrites?
manual edit the preview?
-----------------------------------------------------
Bugs
-----------------------------------------------------
Ultimate Spider-Man files can't be read
square bracket in folder name
(python:4401): GLib-ERROR **: Creating pipes for GWakeup: Too many open files
-----------------------------------------------------
Big Future Features
-----------------------------------------------------