Completed initial multi-file management, before implementing batch features
git-svn-id: http://comictagger.googlecode.com/svn/trunk@311 6c5673fe-1810-88d6-992b-cd32ca31540c
This commit is contained in:
parent
cfca394bcb
commit
2bf9b9ed7c
188
comicarchive.py
188
comicarchive.py
@ -440,9 +440,17 @@ class ComicArchive:
|
||||
def resetCache( self ):
|
||||
self.has_cix = None
|
||||
self.has_cbi = None
|
||||
self.has_comet = None
|
||||
self.comet_filename = None
|
||||
self.page_count = None
|
||||
self.page_list = None
|
||||
self.cix_md = None
|
||||
self.cbi_md = None
|
||||
self.comet_md = None
|
||||
|
||||
def rename( self, path ):
|
||||
self.path = path
|
||||
self.archiver.path = path
|
||||
|
||||
def setExternalRarProgram( self, rar_exe_path ):
|
||||
if self.isRar():
|
||||
@ -527,7 +535,6 @@ class ComicArchive:
|
||||
retcode = self.writeCBI( metadata )
|
||||
elif style == MetaDataStyle.COMET:
|
||||
retcode = self.writeCoMet( metadata )
|
||||
self.resetCache()
|
||||
return retcode
|
||||
|
||||
|
||||
@ -550,7 +557,6 @@ class ComicArchive:
|
||||
retcode = self.removeCBI()
|
||||
elif style == MetaDataStyle.COMET:
|
||||
retcode = self.removeCoMet()
|
||||
self.resetCache()
|
||||
return retcode
|
||||
|
||||
def getPage( self, index ):
|
||||
@ -599,15 +605,16 @@ class ComicArchive:
|
||||
return self.page_count
|
||||
|
||||
def readCBI( self ):
|
||||
raw_cbi = self.readRawCBI()
|
||||
if raw_cbi is None:
|
||||
md = GenericMetadata()
|
||||
else:
|
||||
md = ComicBookInfo().metadataFromString( raw_cbi )
|
||||
|
||||
md.setDefaultPageList( self.getNumberOfPages() )
|
||||
if self.cbi_md is None:
|
||||
raw_cbi = self.readRawCBI()
|
||||
if raw_cbi is None:
|
||||
self.cbi_md = GenericMetadata()
|
||||
else:
|
||||
self.cbi_md = ComicBookInfo().metadataFromString( raw_cbi )
|
||||
|
||||
self.cbi_md.setDefaultPageList( self.getNumberOfPages() )
|
||||
|
||||
return md
|
||||
return self.cbi_md
|
||||
|
||||
def readRawCBI( self ):
|
||||
if ( not self.hasCBI() ):
|
||||
@ -628,30 +635,49 @@ class ComicArchive:
|
||||
return self.has_cbi
|
||||
|
||||
def writeCBI( self, metadata ):
|
||||
self.applyArchiveInfoToMetadata( metadata )
|
||||
cbi_string = ComicBookInfo().stringFromMetadata( metadata )
|
||||
return self.archiver.setArchiveComment( cbi_string )
|
||||
if metadata is not None:
|
||||
self.applyArchiveInfoToMetadata( metadata )
|
||||
cbi_string = ComicBookInfo().stringFromMetadata( metadata )
|
||||
write_success = self.archiver.setArchiveComment( cbi_string )
|
||||
if write_success:
|
||||
self.has_cbi = True
|
||||
self.cbi_md = metadata
|
||||
else:
|
||||
self.resetCache()
|
||||
return write_success
|
||||
else:
|
||||
return False
|
||||
|
||||
def removeCBI( self ):
|
||||
return self.archiver.setArchiveComment( "" )
|
||||
if self.hasCBI():
|
||||
write_success = self.archiver.setArchiveComment( "" )
|
||||
if write_success:
|
||||
self.has_cbi = False
|
||||
self.cbi_md = None
|
||||
else:
|
||||
self.resetCache()
|
||||
return write_success
|
||||
return True
|
||||
|
||||
def readCIX( self ):
|
||||
raw_cix = self.readRawCIX()
|
||||
if raw_cix is None:
|
||||
md = GenericMetadata()
|
||||
else:
|
||||
md = ComicInfoXml().metadataFromString( raw_cix )
|
||||
if self.cix_md is None:
|
||||
raw_cix = self.readRawCIX()
|
||||
if raw_cix is None:
|
||||
self.cix_md = GenericMetadata()
|
||||
else:
|
||||
self.cix_md = ComicInfoXml().metadataFromString( raw_cix )
|
||||
|
||||
#validate the existing page list (make sure count is correct)
|
||||
if len ( md.pages ) != 0 :
|
||||
if len ( md.pages ) != self.getNumberOfPages():
|
||||
# pages array doesn't match the actual number of images we're seeing
|
||||
# in the archive, so discard the data
|
||||
md.pages = []
|
||||
#validate the existing page list (make sure count is correct)
|
||||
if len ( self.cix_md.pages ) != 0 :
|
||||
if len ( self.cix_md.pages ) != self.getNumberOfPages():
|
||||
# pages array doesn't match the actual number of images we're seeing
|
||||
# in the archive, so discard the data
|
||||
self.cix_md.pages = []
|
||||
|
||||
if len( self.cix_md.pages ) == 0:
|
||||
self.cix_md.setDefaultPageList( self.getNumberOfPages() )
|
||||
|
||||
if len( md.pages ) == 0:
|
||||
md.setDefaultPageList( self.getNumberOfPages() )
|
||||
return md
|
||||
return self.cix_md
|
||||
|
||||
def readRawCIX( self ):
|
||||
if not self.hasCIX():
|
||||
@ -664,13 +690,27 @@ class ComicArchive:
|
||||
if metadata is not None:
|
||||
self.applyArchiveInfoToMetadata( metadata, calc_page_sizes=True )
|
||||
cix_string = ComicInfoXml().stringFromMetadata( metadata )
|
||||
return self.archiver.writeArchiveFile( self.ci_xml_filename, cix_string )
|
||||
write_success = self.archiver.writeArchiveFile( self.ci_xml_filename, cix_string )
|
||||
if write_success:
|
||||
self.has_cix = True
|
||||
self.cix_md = metadata
|
||||
else:
|
||||
self.resetCache()
|
||||
return write_success
|
||||
else:
|
||||
return False
|
||||
|
||||
def removeCIX( self ):
|
||||
|
||||
return self.archiver.removeArchiveFile( self.ci_xml_filename )
|
||||
if self.hasCIX():
|
||||
write_success = self.archiver.removeArchiveFile( self.ci_xml_filename )
|
||||
if write_success:
|
||||
self.has_cix = False
|
||||
self.cix_md = None
|
||||
else:
|
||||
self.resetCache()
|
||||
return write_success
|
||||
return True
|
||||
|
||||
|
||||
def hasCIX(self):
|
||||
if self.has_cix is None:
|
||||
@ -685,28 +725,28 @@ class ComicArchive:
|
||||
|
||||
|
||||
def readCoMet( self ):
|
||||
raw_comet = self.readRawCoMet()
|
||||
if raw_comet is None:
|
||||
md = GenericMetadata()
|
||||
else:
|
||||
md = CoMet().metadataFromString( raw_comet )
|
||||
|
||||
md.setDefaultPageList( self.getNumberOfPages() )
|
||||
#use the coverImage value from the comet_data to mark the cover in this struct
|
||||
# walk through list of images in file, and find the matching one for md.coverImage
|
||||
# need to remove the existing one in the default
|
||||
if md.coverImage is not None:
|
||||
cover_idx = 0
|
||||
for idx,f in enumerate(self.getPageNameList()):
|
||||
if md.coverImage == f:
|
||||
cover_idx = idx
|
||||
break
|
||||
if cover_idx != 0:
|
||||
del (md.pages[0]['Type'] )
|
||||
md.pages[ cover_idx ]['Type'] = PageType.FrontCover
|
||||
|
||||
|
||||
return md
|
||||
if self.comet_md is None:
|
||||
raw_comet = self.readRawCoMet()
|
||||
if raw_comet is None:
|
||||
self.comet_md = GenericMetadata()
|
||||
else:
|
||||
self.comet_md = CoMet().metadataFromString( raw_comet )
|
||||
|
||||
self.comet_md.setDefaultPageList( self.getNumberOfPages() )
|
||||
#use the coverImage value from the comet_data to mark the cover in this struct
|
||||
# walk through list of images in file, and find the matching one for md.coverImage
|
||||
# need to remove the existing one in the default
|
||||
if self.comet_md.coverImage is not None:
|
||||
cover_idx = 0
|
||||
for idx,f in enumerate(self.getPageNameList()):
|
||||
if self.comet_md.coverImage == f:
|
||||
cover_idx = idx
|
||||
break
|
||||
if cover_idx != 0:
|
||||
del (self.comet_md.pages[0]['Type'] )
|
||||
self.comet_md.pages[ cover_idx ]['Type'] = PageType.FrontCover
|
||||
|
||||
return self.comet_md
|
||||
|
||||
def readRawCoMet( self ):
|
||||
if not self.hasCoMet():
|
||||
@ -728,24 +768,34 @@ class ComicArchive:
|
||||
metadata.coverImage = self.getPageName( cover_idx )
|
||||
|
||||
comet_string = CoMet().stringFromMetadata( metadata )
|
||||
return self.archiver.writeArchiveFile( self.comet_filename, comet_string )
|
||||
write_success = self.archiver.writeArchiveFile( self.comet_filename, comet_string )
|
||||
if write_success:
|
||||
self.has_comet = True
|
||||
self.comet_md = metadata
|
||||
else:
|
||||
self.resetCache()
|
||||
return write_success
|
||||
else:
|
||||
return False
|
||||
|
||||
def removeCoMet( self ):
|
||||
if self.hasCoMet():
|
||||
retcode = self.archiver.removeArchiveFile( self.comet_filename )
|
||||
self.comet_filename = None
|
||||
return retcode
|
||||
write_success = self.archiver.removeArchiveFile( self.comet_filename )
|
||||
if write_success:
|
||||
self.has_comet = False
|
||||
self.comet_md = None
|
||||
else:
|
||||
self.resetCache()
|
||||
return write_success
|
||||
return True
|
||||
|
||||
def hasCoMet(self):
|
||||
if not self.seemsToBeAComicArchive():
|
||||
return False
|
||||
|
||||
#Use the existence of self.comet_filename as a cue that the tag block exists
|
||||
if self.comet_filename is None:
|
||||
#TODO look at all xml files in root, and search for CoMet data, get first
|
||||
if self.has_comet is None:
|
||||
self.has_comet = False
|
||||
if not self.seemsToBeAComicArchive():
|
||||
return self.has_comet
|
||||
|
||||
#look at all xml files in root, and search for CoMet data, get first
|
||||
for n in self.archiver.getArchiveFilenameList():
|
||||
if ( os.path.dirname(n) == "" and
|
||||
os.path.splitext(n)[1].lower() == '.xml'):
|
||||
@ -754,12 +804,12 @@ class ComicArchive:
|
||||
if CoMet().validateString( data ):
|
||||
# since we found it, save it!
|
||||
self.comet_filename = n
|
||||
return True
|
||||
# if we made it through the loop, no CoMet here...
|
||||
return False
|
||||
|
||||
else:
|
||||
return True
|
||||
self.has_comet = True
|
||||
break
|
||||
|
||||
return self.has_comet
|
||||
|
||||
|
||||
|
||||
def applyArchiveInfoToMetadata( self, md, calc_page_sizes=False):
|
||||
md.pageCount = self.getNumberOfPages()
|
||||
|
@ -49,10 +49,7 @@ class FileTableWidgetItem(QTableWidgetItem):
|
||||
|
||||
|
||||
class FileInfo( ):
|
||||
def __init__(self, path, ca, cix_md, cbi_md ):
|
||||
self.path = path
|
||||
self.cix_md = cix_md
|
||||
self.cbi_md = cbi_md
|
||||
def __init__(self, ca ):
|
||||
self.ca = ca
|
||||
|
||||
class FileSelectionList(QWidget):
|
||||
@ -70,9 +67,12 @@ class FileSelectionList(QWidget):
|
||||
#gridlayout = QGridLayout( self )
|
||||
#gridlayout.addWidget( self.twList )
|
||||
|
||||
self.twList.itemSelectionChanged.connect( self.itemSelectionChangedCB )
|
||||
#self.twList.itemSelectionChanged.connect( self.itemSelectionChangedCB )
|
||||
self.twList.currentItemChanged.connect( self.currentItemChangedCB )
|
||||
|
||||
self.currentItem = None
|
||||
self.setContextMenuPolicy(Qt.ActionsContextMenu)
|
||||
self.modifiedFlag = False
|
||||
|
||||
selectAllAction = QAction("Select All", self)
|
||||
invertSelectionAction = QAction("Invert Selection", self)
|
||||
@ -84,8 +84,14 @@ class FileSelectionList(QWidget):
|
||||
self.addAction(selectAllAction)
|
||||
self.addAction(removeAction)
|
||||
|
||||
def setModifiedFlag( self, modified ):
|
||||
self.modifiedFlag = modified
|
||||
|
||||
def selectAll( self ):
|
||||
self.twList.setRangeSelected( QTableWidgetSelectionRange ( 0, 0, self.twList.rowCount()-1, 1 ), True )
|
||||
|
||||
def deselectAll( self ):
|
||||
self.twList.setRangeSelected( QTableWidgetSelectionRange ( 0, 0, self.twList.rowCount()-1, 1 ), False )
|
||||
|
||||
def removeSelection( self ):
|
||||
row_list = []
|
||||
@ -96,6 +102,11 @@ class FileSelectionList(QWidget):
|
||||
if len(row_list) == 0:
|
||||
return
|
||||
|
||||
if self.twList.currentRow() in row_list:
|
||||
if not self.modifiedFlagVerification( "Remove Archive",
|
||||
"If you close this archive, data in the form will be lost. Are you sure?"):
|
||||
return
|
||||
|
||||
row_list.sort()
|
||||
row_list.reverse()
|
||||
|
||||
@ -153,7 +164,7 @@ class FileSelectionList(QWidget):
|
||||
r = 0
|
||||
while r < self.twList.rowCount():
|
||||
fi = self.twList.item(r, 0).data( Qt.UserRole ).toPyObject()
|
||||
if fi.path == path:
|
||||
if fi.ca.path == path:
|
||||
return True
|
||||
r = r + 1
|
||||
|
||||
@ -175,71 +186,119 @@ class FileSelectionList(QWidget):
|
||||
row = self.twList.rowCount()
|
||||
self.twList.insertRow( row )
|
||||
|
||||
cix_md = None
|
||||
cbi_md = None
|
||||
fi = FileInfo( ca )
|
||||
|
||||
has_cix = ca.hasCIX()
|
||||
if has_cix:
|
||||
cix_md = ca.readCIX()
|
||||
filename_item = QTableWidgetItem()
|
||||
folder_item = QTableWidgetItem()
|
||||
cix_item = QTableWidgetItem()
|
||||
cbi_item = QTableWidgetItem()
|
||||
|
||||
has_cbi = ca.hasCBI()
|
||||
if has_cbi:
|
||||
cbi_md = ca.readCBI()
|
||||
|
||||
fi = FileInfo( path, ca, cix_md, cbi_md )
|
||||
|
||||
item_text = os.path.split(path)[1]
|
||||
item = QTableWidgetItem(item_text)
|
||||
item.setFlags(Qt.ItemIsSelectable| Qt.ItemIsEnabled)
|
||||
item.setData( Qt.UserRole , fi )
|
||||
item.setData( Qt.ToolTipRole ,item_text)
|
||||
self.twList.setItem(row, 0, item)
|
||||
|
||||
item_text = os.path.split(path)[0]
|
||||
item = QTableWidgetItem(item_text)
|
||||
item.setFlags(Qt.ItemIsSelectable| Qt.ItemIsEnabled)
|
||||
item.setData( Qt.ToolTipRole ,item_text)
|
||||
self.twList.setItem(row, 1, item)
|
||||
filename_item.setFlags(Qt.ItemIsSelectable| Qt.ItemIsEnabled)
|
||||
filename_item.setData( Qt.UserRole , fi )
|
||||
self.twList.setItem(row, 0, filename_item)
|
||||
|
||||
folder_item.setFlags(Qt.ItemIsSelectable| Qt.ItemIsEnabled)
|
||||
self.twList.setItem(row, 1, folder_item)
|
||||
|
||||
# Attempt to use a special checkbox widget in the cell.
|
||||
# Couldn't figure out how to disable it with "enabled" colors
|
||||
#w = QWidget()
|
||||
#cb = QCheckBox(w)
|
||||
#cb.setCheckState(Qt.Checked)
|
||||
#layout = QHBoxLayout()
|
||||
#layout.addWidget( cb )
|
||||
#layout.setAlignment(Qt.AlignHCenter)
|
||||
#layout.setMargin(2)
|
||||
#w.setLayout(layout)
|
||||
#self.twList.setCellWidget( row, 2, w )
|
||||
cix_item.setFlags(Qt.ItemIsSelectable| Qt.ItemIsEnabled)
|
||||
cix_item.setTextAlignment(Qt.AlignHCenter)
|
||||
self.twList.setItem(row, 2, cix_item)
|
||||
|
||||
item = FileTableWidgetItem()
|
||||
item.setFlags(Qt.ItemIsSelectable| Qt.ItemIsEnabled)
|
||||
item.setTextAlignment(Qt.AlignHCenter)
|
||||
if has_cix:
|
||||
item.setCheckState(Qt.Checked)
|
||||
item.setData(Qt.UserRole, True)
|
||||
else:
|
||||
item.setData(Qt.UserRole, False)
|
||||
self.twList.setItem(row, 2, item)
|
||||
|
||||
item = FileTableWidgetItem()
|
||||
item.setFlags(Qt.ItemIsSelectable| Qt.ItemIsEnabled)
|
||||
item.setTextAlignment(Qt.AlignHCenter)
|
||||
if has_cbi:
|
||||
item.setCheckState(Qt.Checked)
|
||||
item.setData(Qt.UserRole, True)
|
||||
else:
|
||||
item.setData(Qt.UserRole, False)
|
||||
self.twList.setItem(row, 3, item)
|
||||
cbi_item.setFlags(Qt.ItemIsSelectable| Qt.ItemIsEnabled)
|
||||
cbi_item.setTextAlignment(Qt.AlignHCenter)
|
||||
self.twList.setItem(row, 3, cbi_item)
|
||||
|
||||
self.updateRow( row )
|
||||
|
||||
return row
|
||||
|
||||
def updateRow( self, row ):
|
||||
fi = self.twList.item( row, 0 ).data( Qt.UserRole ).toPyObject()
|
||||
|
||||
filename_item = self.twList.item( row, 0 )
|
||||
folder_item = self.twList.item( row, 1 )
|
||||
cix_item = self.twList.item( row, 2 )
|
||||
cbi_item = self.twList.item( row, 3 )
|
||||
|
||||
item_text = os.path.split(fi.ca.path)[0]
|
||||
folder_item.setText( item_text )
|
||||
folder_item.setData( Qt.ToolTipRole, item_text )
|
||||
|
||||
item_text = os.path.split(fi.ca.path)[1]
|
||||
filename_item.setText( item_text )
|
||||
filename_item.setData( Qt.ToolTipRole, item_text )
|
||||
|
||||
if fi.ca.hasCIX():
|
||||
cix_item.setCheckState(Qt.Checked)
|
||||
cix_item.setData(Qt.UserRole, True)
|
||||
else:
|
||||
cix_item.setData(Qt.UserRole, False)
|
||||
cix_item.setCheckState(Qt.Unchecked)
|
||||
|
||||
if fi.ca.hasCBI():
|
||||
cbi_item.setCheckState(Qt.Checked)
|
||||
cbi_item.setData(Qt.UserRole, True)
|
||||
else:
|
||||
cbi_item.setData(Qt.UserRole, False)
|
||||
cbi_item.setCheckState(Qt.Unchecked)
|
||||
|
||||
def itemSelectionChangedCB( self ):
|
||||
idx = self.twList.currentRow()
|
||||
|
||||
fi = self.twList.item(idx, 0).data( Qt.UserRole ).toPyObject()
|
||||
|
||||
#if fi.cix_md is not None:
|
||||
# print u"{0}".format(fi.cix_md)
|
||||
# Reading these will force them into the ComicArchive's cache
|
||||
fi.ca.readCIX()
|
||||
fi.ca.hasCBI()
|
||||
|
||||
|
||||
def updateCurrentRow( self ):
|
||||
self.updateRow( self.twList.currentRow() )
|
||||
|
||||
def currentItemChangedCB( self, curr, prev ):
|
||||
|
||||
new_idx = curr.row()
|
||||
old_idx = -1
|
||||
if prev is not None:
|
||||
old_idx = prev.row()
|
||||
#print "old {0} new {1}".format(old_idx, new_idx)
|
||||
|
||||
if old_idx == new_idx:
|
||||
return
|
||||
|
||||
# don't allow change if modified
|
||||
if prev is not None and new_idx != old_idx:
|
||||
if not self.modifiedFlagVerification( "Change Archive",
|
||||
"If you change archives now, data in the form will be lost. Are you sure?"):
|
||||
self.twList.currentItemChanged.disconnect( self.currentItemChangedCB )
|
||||
self.twList.setCurrentItem( prev )
|
||||
self.twList.currentItemChanged.connect( self.currentItemChangedCB )
|
||||
# Need to defer this revert selection, for some reason
|
||||
QTimer.singleShot(1, self.revertSelection)
|
||||
return
|
||||
|
||||
fi = self.twList.item( new_idx, 0 ).data( Qt.UserRole ).toPyObject()
|
||||
self.selectionChanged.emit( QVariant(fi))
|
||||
|
||||
def revertSelection( self ):
|
||||
self.twList.selectRow( self.twList.currentRow() )
|
||||
|
||||
|
||||
def modifiedFlagVerification( self, title, desc):
|
||||
if self.modifiedFlag:
|
||||
reply = QMessageBox.question(self,
|
||||
self.tr(title),
|
||||
self.tr(desc),
|
||||
QMessageBox.Yes, QMessageBox.No )
|
||||
|
||||
if reply != QMessageBox.Yes:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
# Attempt to use a special checkbox widget in the cell.
|
||||
# Couldn't figure out how to disable it with "enabled" colors
|
||||
#w = QWidget()
|
||||
#cb = QCheckBox(w)
|
||||
#cb.setCheckState(Qt.Checked)
|
||||
#layout = QHBoxLayout()
|
||||
#layout.addWidget( cb )
|
||||
#layout.setAlignment(Qt.AlignHCenter)
|
||||
#layout.setMargin(2)
|
||||
#w.setLayout(layout)
|
||||
#self.twList.setCellWidget( row, 2, w )
|
@ -75,5 +75,5 @@ class RenameWindow(QtGui.QDialog):
|
||||
os.rename( self.comic_archive.path, new_abs_path )
|
||||
|
||||
self.new_name = new_abs_path
|
||||
|
||||
self.comic_archive.rename( new_abs_path )
|
||||
|
14
settings.py
14
settings.py
@ -51,7 +51,8 @@ class ComicTaggerSettings:
|
||||
self.allow_cbi_in_rar = True
|
||||
|
||||
# automatic settings
|
||||
self.last_selected_data_style = 0
|
||||
self.last_selected_save_data_style = 0
|
||||
self.last_selected_load_data_style = 0
|
||||
self.last_opened_folder = ""
|
||||
self.last_main_window_width = 0
|
||||
self.last_main_window_height = 0
|
||||
@ -139,9 +140,11 @@ class ComicTaggerSettings:
|
||||
|
||||
self.rar_exe_path = self.config.get( 'settings', 'rar_exe_path' )
|
||||
self.unrar_exe_path = self.config.get( 'settings', 'unrar_exe_path' )
|
||||
|
||||
if self.config.has_option('auto', 'last_selected_data_style'):
|
||||
self.last_selected_data_style = self.config.getint( 'auto', 'last_selected_data_style' )
|
||||
|
||||
if self.config.has_option('auto', 'last_selected_load_data_style'):
|
||||
self.last_selected_load_data_style = self.config.getint( 'auto', 'last_selected_load_data_style' )
|
||||
if self.config.has_option('auto', 'last_selected_save_data_style'):
|
||||
self.last_selected_save_data_style = self.config.getint( 'auto', 'last_selected_save_data_style' )
|
||||
if self.config.has_option('auto', 'last_opened_folder'):
|
||||
self.last_opened_folder = self.config.get( 'auto', 'last_opened_folder' )
|
||||
if self.config.has_option('auto', 'last_main_window_width'):
|
||||
@ -202,7 +205,8 @@ class ComicTaggerSettings:
|
||||
if not self.config.has_section( 'auto' ):
|
||||
self.config.add_section( 'auto' )
|
||||
|
||||
self.config.set( 'auto', 'last_selected_data_style', self.last_selected_data_style )
|
||||
self.config.set( 'auto', 'last_selected_load_data_style', self.last_selected_load_data_style )
|
||||
self.config.set( 'auto', 'last_selected_save_data_style', self.last_selected_save_data_style )
|
||||
self.config.set( 'auto', 'last_opened_folder', self.last_opened_folder )
|
||||
self.config.set( 'auto', 'last_main_window_width', self.last_main_window_width )
|
||||
self.config.set( 'auto', 'last_main_window_height', self.last_main_window_height )
|
||||
|
207
taggerwindow.py
207
taggerwindow.py
@ -111,7 +111,8 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
|
||||
self.lblCover.setPixmap(QtGui.QPixmap(os.path.join(ComicTaggerSettings.baseDir(), 'graphics/nocover.png' )))
|
||||
|
||||
self.data_style = settings.last_selected_data_style
|
||||
self.save_data_style = settings.last_selected_save_data_style
|
||||
self.load_data_style = settings.last_selected_load_data_style
|
||||
|
||||
self.setAcceptDrops(True)
|
||||
self.configMenus()
|
||||
@ -142,7 +143,8 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
self.cbMaturityRating.lineEdit().setAcceptDrops(False)
|
||||
|
||||
# hook up the callbacks
|
||||
self.cbDataStyle.currentIndexChanged.connect(self.setDataStyle)
|
||||
self.cbLoadDataStyle.currentIndexChanged.connect(self.setLoadDataStyle)
|
||||
self.cbSaveDataStyle.currentIndexChanged.connect(self.setSaveDataStyle)
|
||||
self.btnEditCredit.clicked.connect(self.editCredit)
|
||||
self.btnAddCredit.clicked.connect(self.addCredit)
|
||||
self.btnRemoveCredit.clicked.connect(self.removeCredit)
|
||||
@ -246,16 +248,6 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
|
||||
self.actionRemoveCRTags.setStatusTip( 'Remove ComicRack tags from comic archive' )
|
||||
self.actionRemoveCRTags.triggered.connect( self.removeCRTags )
|
||||
|
||||
self.actionReloadAuto.setShortcut( 'Ctrl+R' )
|
||||
self.actionReloadAuto.setStatusTip( 'Reload selected style tags from archive' )
|
||||
self.actionReloadAuto.triggered.connect( self.reloadAuto )
|
||||
|
||||
self.actionReloadCBLTags.setStatusTip( 'Reload ComicBookLover tags' )
|
||||
self.actionReloadCBLTags.triggered.connect( self.reloadCBLTags )
|
||||
|
||||
self.actionReloadCRTags.setStatusTip( 'Reload ComicRack tags' )
|
||||
self.actionReloadCRTags.triggered.connect( self.reloadCRTags )
|
||||
|
||||
self.actionViewRawCRTags.setStatusTip( 'View raw ComicRack tag block from file' )
|
||||
self.actionViewRawCRTags.triggered.connect( self.viewRawCRTags )
|
||||
@ -403,72 +395,12 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
event.accept()
|
||||
|
||||
def dropEvent(self, event):
|
||||
if self.dirtyFlagVerification( "Open Archive",
|
||||
"If you open a new archive now, data in the form will be lost. Are you sure?"):
|
||||
#self.openArchive( unicode(self.droppedFile))
|
||||
self.fileSelectionList.addPathList( self.droppedFiles )
|
||||
event.accept()
|
||||
|
||||
def openArchive( self, path, explicit_style=None, clear_form=True ):
|
||||
|
||||
if path is None or path == "":
|
||||
return
|
||||
|
||||
ca = ComicArchive( path )
|
||||
if self.settings.rar_exe_path != "":
|
||||
ca.setExternalRarProgram( self.settings.rar_exe_path )
|
||||
|
||||
if ca is not None and ca.seemsToBeAComicArchive():
|
||||
#if self.dirtyFlagVerification( "Open Archive",
|
||||
# "If you open a new archive now, data in the form will be lost. Are you sure?"):
|
||||
self.fileSelectionList.addPathList( self.droppedFiles )
|
||||
event.accept()
|
||||
|
||||
self.settings.last_opened_folder = os.path.dirname( os.path.abspath(path) )
|
||||
|
||||
# clear form and current metadata, we're all in!
|
||||
if clear_form:
|
||||
self.clearForm()
|
||||
|
||||
self.comic_archive = ca
|
||||
|
||||
if explicit_style is None:
|
||||
hasCBI = ca.hasCBI()
|
||||
hasCIX = ca.hasCIX()
|
||||
hasNeither = not hasCIX and not hasCBI
|
||||
|
||||
# no style indicated, so try to choose
|
||||
if hasNeither:
|
||||
self.metadata = self.comic_archive.metadataFromFilename( )
|
||||
self.metadata.setDefaultPageList( self.comic_archive.getNumberOfPages() )
|
||||
else:
|
||||
if hasCBI and not hasCIX:
|
||||
self.data_style = MetaDataStyle.CBI
|
||||
elif hasCIX and not hasCBI:
|
||||
self.data_style = MetaDataStyle.CIX
|
||||
else: #both
|
||||
reply = QtGui.QMessageBox.question(self,
|
||||
self.tr("Multiple Tag Types!"),
|
||||
self.tr("This archive has both ComicBookLover and ComicRack type tags. Which do you want to load?"),
|
||||
self.tr("ComicBookLover"), self.tr("ComicRack" ))
|
||||
|
||||
if reply == 0:
|
||||
# ComicBookLover
|
||||
self.data_style = MetaDataStyle.CBI
|
||||
else:
|
||||
self.data_style = MetaDataStyle.CIX
|
||||
self.adjustStyleCombo()
|
||||
self.metadata = self.comic_archive.readMetadata( self.data_style )
|
||||
else:
|
||||
if ca.hasMetadata( explicit_style ):
|
||||
self.data_style = explicit_style
|
||||
self.adjustStyleCombo()
|
||||
self.metadata = self.comic_archive.readMetadata( self.data_style )
|
||||
else:
|
||||
return
|
||||
|
||||
self.loadCurrentArchive()
|
||||
|
||||
else:
|
||||
QtGui.QMessageBox.information(self, self.tr("Whoops!"), self.tr("That file doesn't appear to be a comic archive!"))
|
||||
|
||||
def loadCurrentArchive( self ):
|
||||
def actualLoadCurrentArchive( self ):
|
||||
if self.metadata.isEmpty:
|
||||
self.metadata = self.comic_archive.metadataFromFilename( )
|
||||
self.metadata.setDefaultPageList( self.comic_archive.getNumberOfPages() )
|
||||
@ -511,9 +443,6 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
self.actionRepackage.setEnabled(False)
|
||||
self.actionViewRawCBLTags.setEnabled( False )
|
||||
self.actionViewRawCRTags.setEnabled( False )
|
||||
self.actionReloadCRTags.setEnabled( False )
|
||||
self.actionReloadCBLTags.setEnabled( False )
|
||||
self.actionReloadAuto.setEnabled( False )
|
||||
self.actionParse_Filename.setEnabled( False )
|
||||
self.actionAutoSearch.setEnabled( False )
|
||||
self.actionRename.setEnabled( False )
|
||||
@ -532,13 +461,9 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
if not self.comic_archive.isZip():
|
||||
self.actionRepackage.setEnabled(True)
|
||||
|
||||
if has_cix or has_cbi:
|
||||
self.actionReloadAuto.setEnabled( True )
|
||||
if has_cix:
|
||||
self.actionReloadCRTags.setEnabled( True )
|
||||
self.actionViewRawCRTags.setEnabled( True )
|
||||
if has_cbi:
|
||||
self.actionReloadCBLTags.setEnabled( True )
|
||||
self.actionViewRawCBLTags.setEnabled( True )
|
||||
|
||||
if self.comic_archive.isWritable():
|
||||
@ -592,11 +517,13 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
def setDirtyFlag( self, param1=None, param2=None, param3=None ):
|
||||
if not self.dirtyFlag:
|
||||
self.dirtyFlag = True
|
||||
self.fileSelectionList.setModifiedFlag( True )
|
||||
self.updateAppTitle()
|
||||
|
||||
def clearDirtyFlag( self ):
|
||||
if self.dirtyFlag:
|
||||
self.dirtyFlag = False
|
||||
self.fileSelectionList.setModifiedFlag( False )
|
||||
self.updateAppTitle()
|
||||
|
||||
def connectDirtyFlagSignals( self ):
|
||||
@ -881,9 +808,9 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
|
||||
if (dialog.exec_()):
|
||||
fileList = dialog.selectedFiles()
|
||||
if self.dirtyFlagVerification( "Open Archive",
|
||||
"If you open a new archive now, data in the form will be lost. Are you sure?"):
|
||||
self.fileSelectionList.addPathList( fileList )
|
||||
#if self.dirtyFlagVerification( "Open Archive",
|
||||
# "If you open a new archive now, data in the form will be lost. Are you sure?"):
|
||||
self.fileSelectionList.addPathList( fileList )
|
||||
|
||||
def autoSelectSearch(self):
|
||||
if self.comic_archive is None:
|
||||
@ -952,7 +879,7 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
|
||||
if ( self.metadata is not None and self.comic_archive is not None):
|
||||
|
||||
if self.comic_archive.isRar() and self.data_style == MetaDataStyle.CBI:
|
||||
if self.comic_archive.isRar() and self.save_data_style == MetaDataStyle.CBI:
|
||||
if self.settings.ask_about_cbi_in_rar:
|
||||
checked = OptionalMessageDialog.msg( self, "RAR and ComicBookLover",
|
||||
"""
|
||||
@ -972,14 +899,14 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
|
||||
reply = QtGui.QMessageBox.question(self,
|
||||
self.tr("Save Tags"),
|
||||
self.tr("Are you sure you wish to save " + MetaDataStyle.name[self.data_style] + " tags to this archive?"),
|
||||
self.tr("Are you sure you wish to save " + MetaDataStyle.name[self.save_data_style] + " tags to this archive?"),
|
||||
QtGui.QMessageBox.Yes, QtGui.QMessageBox.No )
|
||||
|
||||
if reply == QtGui.QMessageBox.Yes:
|
||||
QtGui.QApplication.setOverrideCursor(QtGui.QCursor(QtCore.Qt.WaitCursor))
|
||||
self.formToMetadata()
|
||||
|
||||
success = self.comic_archive.writeMetadata( self.metadata, self.data_style )
|
||||
success = self.comic_archive.writeMetadata( self.metadata, self.save_data_style )
|
||||
QtGui.QApplication.restoreOverrideCursor()
|
||||
|
||||
if not success:
|
||||
@ -989,15 +916,29 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
self.updateInfoBox()
|
||||
self.updateMenus()
|
||||
#QtGui.QMessageBox.information(self, self.tr("Yeah!"), self.tr("File written."))
|
||||
self.fileSelectionList.updateCurrentRow()
|
||||
|
||||
else:
|
||||
QtGui.QMessageBox.information(self, self.tr("Whoops!"), self.tr("No data to commit!"))
|
||||
|
||||
|
||||
def setDataStyle(self, s):
|
||||
self.data_style, b = self.cbDataStyle.itemData(s).toInt()
|
||||
def setLoadDataStyle(self, s):
|
||||
if self.dirtyFlagVerification( "Change Tag Read Style",
|
||||
"If you change tag style now, data in the form will be lost. Are you sure?"):
|
||||
self.load_data_style, b = self.cbLoadDataStyle.itemData(s).toInt()
|
||||
self.settings.last_selected_load_data_style = self.load_data_style
|
||||
self.updateMenus()
|
||||
if self.comic_archive is not None:
|
||||
self.loadArchive( self.comic_archive )
|
||||
else:
|
||||
self.cbLoadDataStyle.currentIndexChanged.disconnect(self.setLoadDataStyle)
|
||||
self.adjustLoadStyleCombo()
|
||||
self.cbLoadDataStyle.currentIndexChanged.connect(self.setLoadDataStyle)
|
||||
|
||||
self.settings.last_selected_data_style = self.data_style
|
||||
def setSaveDataStyle(self, s):
|
||||
self.save_data_style, b = self.cbSaveDataStyle.itemData(s).toInt()
|
||||
|
||||
self.settings.last_selected_save_data_style = self.save_data_style
|
||||
self.updateStyleTweaks()
|
||||
self.updateMenus()
|
||||
|
||||
@ -1008,7 +949,7 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
|
||||
cix_credits = ComicInfoXml().getParseableCredits()
|
||||
|
||||
if self.data_style == MetaDataStyle.CIX:
|
||||
if self.save_data_style == MetaDataStyle.CIX:
|
||||
#loop over credit table, mark selected rows
|
||||
r = 0
|
||||
while r < self.twCredits.rowCount():
|
||||
@ -1020,7 +961,7 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
self.twCredits.item(r, 0).setBackgroundColor( inactive_color )
|
||||
r = r + 1
|
||||
|
||||
if self.data_style == MetaDataStyle.CBI:
|
||||
if self.save_data_style == MetaDataStyle.CBI:
|
||||
#loop over credit table, make all active color
|
||||
r = 0
|
||||
while r < self.twCredits.rowCount():
|
||||
@ -1083,20 +1024,20 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
self.teLocations, self.cbMaturityRating, self.cbFormat
|
||||
]
|
||||
|
||||
if self.data_style == MetaDataStyle.CIX:
|
||||
if self.save_data_style == MetaDataStyle.CIX:
|
||||
for item in cix_only:
|
||||
enableWidget( item, True )
|
||||
for item in cbi_only:
|
||||
enableWidget(item, False )
|
||||
|
||||
if self.data_style == MetaDataStyle.CBI:
|
||||
if self.save_data_style == MetaDataStyle.CBI:
|
||||
for item in cbi_only:
|
||||
enableWidget( item, True )
|
||||
for item in cix_only:
|
||||
enableWidget(item, False )
|
||||
|
||||
self.updateCreditColors()
|
||||
self.pageListEditor.setMetadataStyle( self.data_style )
|
||||
self.pageListEditor.setMetadataStyle( self.save_data_style )
|
||||
|
||||
def cellDoubleClicked( self, r, c ):
|
||||
self.editCredit()
|
||||
@ -1211,21 +1152,32 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
self.move((screen.width()-size.width())/2, (screen.height()-size.height())/2)
|
||||
|
||||
|
||||
def adjustStyleCombo( self ):
|
||||
def adjustLoadStyleCombo( self ):
|
||||
# select the current style
|
||||
if ( self.data_style == MetaDataStyle.CBI ):
|
||||
self.cbDataStyle.setCurrentIndex ( 0 )
|
||||
elif ( self.data_style == MetaDataStyle.CIX ):
|
||||
self.cbDataStyle.setCurrentIndex ( 1 )
|
||||
if ( self.load_data_style == MetaDataStyle.CBI ):
|
||||
self.cbLoadDataStyle.setCurrentIndex ( 0 )
|
||||
elif ( self.load_data_style == MetaDataStyle.CIX ):
|
||||
self.cbLoadDataStyle.setCurrentIndex ( 1 )
|
||||
|
||||
def adjustSaveStyleCombo( self ):
|
||||
# select the current style
|
||||
if ( self.save_data_style == MetaDataStyle.CBI ):
|
||||
self.cbSaveDataStyle.setCurrentIndex ( 0 )
|
||||
elif ( self.save_data_style == MetaDataStyle.CIX ):
|
||||
self.cbSaveDataStyle.setCurrentIndex ( 1 )
|
||||
self.updateStyleTweaks()
|
||||
|
||||
|
||||
def populateComboBoxes( self ):
|
||||
|
||||
# Add the entries to the tag style combobox
|
||||
self.cbDataStyle.addItem( "ComicBookLover", MetaDataStyle.CBI )
|
||||
self.cbDataStyle.addItem( "ComicRack", MetaDataStyle.CIX )
|
||||
self.adjustStyleCombo()
|
||||
self.cbLoadDataStyle.addItem( "ComicBookLover", MetaDataStyle.CBI )
|
||||
self.cbLoadDataStyle.addItem( "ComicRack", MetaDataStyle.CIX )
|
||||
self.adjustLoadStyleCombo()
|
||||
|
||||
self.cbSaveDataStyle.addItem( "ComicBookLover", MetaDataStyle.CBI )
|
||||
self.cbSaveDataStyle.addItem( "ComicRack", MetaDataStyle.CIX )
|
||||
self.adjustSaveStyleCombo()
|
||||
|
||||
# Add the entries to the country combobox
|
||||
self.cbCountry.addItem( "", "" )
|
||||
@ -1317,7 +1269,7 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
self.cbFormat.addItem("Year One")
|
||||
|
||||
def removeAuto( self ):
|
||||
self.removeTags( self.data_style )
|
||||
self.removeTags( self.save_data_style )
|
||||
|
||||
def removeCBLTags( self ):
|
||||
self.removeTags( MetaDataStyle.CBI )
|
||||
@ -1341,24 +1293,8 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
else:
|
||||
self.updateInfoBox()
|
||||
self.updateMenus()
|
||||
|
||||
self.fileSelectionList.updateCurrentRow()
|
||||
|
||||
def reloadAuto( self ):
|
||||
self.actualReload( self.data_style )
|
||||
|
||||
def reloadCBLTags( self ):
|
||||
self.actualReload( MetaDataStyle.CBI )
|
||||
|
||||
def reloadCRTags( self ):
|
||||
self.actualReload( MetaDataStyle.CIX )
|
||||
|
||||
def actualReload( self, style ):
|
||||
if self.comic_archive is not None and self.comic_archive.hasMetadata( style ):
|
||||
if self.dirtyFlagVerification( "Load Tags",
|
||||
"If you load tags now, data in the form will be lost. Are you sure?"):
|
||||
self.openArchive( self.comic_archive.path, explicit_style=style )
|
||||
|
||||
|
||||
def dirtyFlagVerification( self, title, desc):
|
||||
if self.dirtyFlag:
|
||||
reply = QtGui.QMessageBox.question(self,
|
||||
@ -1436,27 +1372,24 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
dlg = RenameWindow( self, self.comic_archive, self.metadata, self.settings )
|
||||
dlg.setModal( True )
|
||||
if dlg.exec_():
|
||||
#reopen the archive, since the filename changed
|
||||
print dlg.new_name
|
||||
self.comic_archive = None
|
||||
self.openArchive( dlg.new_name )
|
||||
self.fileSelectionList.updateCurrentRow()
|
||||
self.loadArchive( self.comic_archive )
|
||||
|
||||
|
||||
def fileListSelectionChanged( self, qvarFI ):
|
||||
fi = qvarFI.toPyObject()
|
||||
#if fi.cix_md is not None:
|
||||
# print u"{0}".format(fi.cix_md)
|
||||
self.loadArchive( fi.ca )
|
||||
|
||||
def loadArchive( self, comic_archive ):
|
||||
self.comic_archive = None
|
||||
self.clearForm()
|
||||
|
||||
self.comic_archive = fi.ca
|
||||
if self.data_style == MetaDataStyle.CIX:
|
||||
self.metadata = fi.cix_md
|
||||
else:
|
||||
self.metadata = fi.cbi_md
|
||||
self.comic_archive = comic_archive
|
||||
self.metadata = self.comic_archive.readMetadata(self.load_data_style)
|
||||
if self.metadata is None:
|
||||
self.metadata = GenericMetadata()
|
||||
|
||||
self.loadCurrentArchive()
|
||||
|
||||
self.actualLoadCurrentArchive()
|
||||
|
||||
def fileListCleared( self ):
|
||||
self.resetApp()
|
@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>968</width>
|
||||
<height>547</height>
|
||||
<height>575</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
@ -62,12 +62,22 @@
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Tag Style:</string>
|
||||
<string>Read Style</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="cbDataStyle"/>
|
||||
<widget class="QComboBox" name="cbLoadDataStyle"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="saveStyleLabel">
|
||||
<property name="text">
|
||||
<string>Write Style</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="cbSaveDataStyle"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
@ -1181,14 +1191,6 @@
|
||||
<addaction name="actionRemoveCBLTags"/>
|
||||
<addaction name="actionRemoveCRTags"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuReload">
|
||||
<property name="title">
|
||||
<string>Reload</string>
|
||||
</property>
|
||||
<addaction name="actionReloadAuto"/>
|
||||
<addaction name="actionReloadCBLTags"/>
|
||||
<addaction name="actionReloadCRTags"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuViewRawTags">
|
||||
<property name="title">
|
||||
<string>View Raw Tags</string>
|
||||
@ -1199,7 +1201,6 @@
|
||||
<addaction name="actionLoad"/>
|
||||
<addaction name="actionLoadFolder"/>
|
||||
<addaction name="actionWrite_Tags"/>
|
||||
<addaction name="menuReload"/>
|
||||
<addaction name="menuRemove"/>
|
||||
<addaction name="menuViewRawTags"/>
|
||||
<addaction name="actionRepackage"/>
|
||||
|
14
todo.txt
14
todo.txt
@ -3,20 +3,14 @@ Features
|
||||
-----------------------------------------------------
|
||||
|
||||
Multi-file:
|
||||
Does the main UI need to have "View/Read Tag Style" and "Write Tag style" concept?
|
||||
|
||||
Select first dropped Item into list
|
||||
Turn off drop accept for edit lines/boxes
|
||||
Drop on app goes to list and selects it
|
||||
Accept multiple files on file open dialog
|
||||
Warn on moving selection list away from modified form
|
||||
ComicArchive: cache each metadata block? Need to make sure cache is cleared on file modify
|
||||
|
||||
Batch Functions:
|
||||
Auto-Select
|
||||
Start/Options Dialog
|
||||
Progress Dialog - maybe reuse
|
||||
Interactive dialog at end
|
||||
Interactive dialog at end
|
||||
Summary Dialog
|
||||
|
||||
Rename
|
||||
Start dialog with preview
|
||||
maybe table with checkboxes?
|
||||
@ -24,7 +18,7 @@ Multi-file:
|
||||
Copy Block
|
||||
Verify overwrites
|
||||
Delete
|
||||
|
||||
Export to CBZ?
|
||||
|
||||
-----------------------------------------------------
|
||||
Bugs
|
||||
|
Loading…
Reference in New Issue
Block a user