diff --git a/comet.py b/comet.py
index 7baca54..128be43 100644
--- a/comet.py
+++ b/comet.py
@@ -101,8 +101,8 @@ class CoMet:
if md.characters is not None:
char_list = [ c.strip() for c in md.characters.split(',') ]
- for c in char_list:
- assign( 'character', c )
+ for c in char_list:
+ assign( 'character', c )
if md.manga is not None and md.manga == "YesAndRightToLeft":
assign( 'readingDirection', "rtl")
@@ -114,7 +114,7 @@ class CoMet:
date_str += "-" + str(md.month).zfill(2)
assign( 'date', date_str )
- #assign( 'coverImage', md.??? ) #TODO Need to use pages list, eventually...
+ assign( 'coverImage', md.coverImage )
# need to specially process the credits, since they are structured differently than CIX
credit_writer_list = list()
@@ -202,7 +202,7 @@ class CoMet:
if len( parts) > 1:
md.month = parts[1]
- coverImage = xlate( 'coverImage' ) # TODO - do something with this!
+ md.coverImage = xlate( 'coverImage' )
readingDirection = xlate( 'readingDirection' )
if readingDirection is not None and readingDirection == "rtl":
diff --git a/comicarchive.py b/comicarchive.py
index 8a75b1e..527532e 100644
--- a/comicarchive.py
+++ b/comicarchive.py
@@ -29,6 +29,13 @@ if platform.system() == "Windows":
import _subprocess
import time
+import StringIO
+try:
+ import Image
+ pil_available = True
+except ImportError:
+ pil_available = False
+
sys.path.insert(0, os.path.abspath(".") )
import UnRAR2
from UnRAR2.rar_exceptions import *
@@ -37,7 +44,7 @@ from options import Options, MetaDataStyle
from comicinfoxml import ComicInfoXml
from comicbookinfo import ComicBookInfo
from comet import CoMet
-from genericmetadata import GenericMetadata
+from genericmetadata import GenericMetadata, PageType
from filenameparser import FileNameParser
@@ -524,11 +531,6 @@ class ComicArchive:
return self.removeCBI()
elif style == MetaDataStyle.COMET:
return self.removeCoMet()
-
- def getCoverPage(self):
-
- # assume first page is the cover (for now)
- return self.getPage( 0 )
def getPage( self, index ):
@@ -575,9 +577,13 @@ class ComicArchive:
def readCBI( self ):
raw_cbi = self.readRawCBI()
if raw_cbi is None:
- return GenericMetadata()
+ md =GenericMetadata()
+ else:
+ md = ComicBookInfo().metadataFromString( raw_cbi )
- return ComicBookInfo().metadataFromString( raw_cbi )
+ md.setDefaultPageList( self.getNumberOfPages() )
+
+ return md
def readRawCBI( self ):
if ( not self.hasCBI() ):
@@ -594,6 +600,7 @@ class ComicArchive:
return ComicBookInfo().validateString( comment )
def writeCBI( self, metadata ):
+ self.applyArchiveInfoToMetadata( metadata )
cbi_string = ComicBookInfo().stringFromMetadata( metadata )
return self.archiver.setArchiveComment( cbi_string )
@@ -603,9 +610,20 @@ class ComicArchive:
def readCIX( self ):
raw_cix = self.readRawCIX()
if raw_cix is None:
- return GenericMetadata()
+ md = GenericMetadata()
+ else:
+ 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 = []
- return ComicInfoXml().metadataFromString( raw_cix )
+ if len( md.pages ) == 0:
+ md.setDefaultPageList( self.getNumberOfPages() )
+ return md
def readRawCIX( self ):
if not self.hasCIX():
@@ -617,7 +635,7 @@ class ComicArchive:
def writeCIX(self, metadata):
if metadata is not None:
- metadata.pageCount = self.getNumberOfPages()
+ self.applyArchiveInfoToMetadata( metadata, calc_page_sizes=True )
cix_string = ComicInfoXml().stringFromMetadata( metadata )
return self.archiver.writeArchiveFile( self.ci_xml_filename, cix_string )
else:
@@ -639,9 +657,26 @@ class ComicArchive:
def readCoMet( self ):
raw_comet = self.readRawCoMet()
if raw_comet is None:
- return GenericMetadata()
-
- return CoMet().metadataFromString( raw_comet )
+ 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
def readRawCoMet( self ):
if not self.hasCoMet():
@@ -656,7 +691,12 @@ class ComicArchive:
if not self.hasCoMet():
self.comet_filename = self.comet_default_filename
- metadata.pageCount = self.getNumberOfPages()
+ self.applyArchiveInfoToMetadata( metadata )
+ # Set the coverImage value, if it's not the first page
+ cover_idx = int(metadata.getCoverPageIndexList()[0])
+ if cover_idx != 0:
+ metadata.coverImage = self.getPageName( cover_idx )
+
comet_string = CoMet().stringFromMetadata( metadata )
return self.archiver.writeArchiveFile( self.comet_filename, comet_string )
else:
@@ -691,7 +731,29 @@ class ComicArchive:
else:
return True
+ def applyArchiveInfoToMetadata( self, md, calc_page_sizes=False):
+ md.pageCount = self.getNumberOfPages()
+
+ if calc_page_sizes:
+ for p in md.pages:
+ idx = int( p['Image'] )
+ if pil_available:
+ if 'ImageSize' not in p or 'ImageHeight' not in p or 'ImageWidth' not in p:
+ data = self.getPage( idx )
+
+ im = Image.open(StringIO.StringIO(data))
+ w,h = im.size
+
+ p['ImageSize'] = str(len(data))
+ p['ImageHeight'] = str(h)
+ p['ImageWidth'] = str(w)
+ else:
+ if 'ImageSize' not in p:
+ data = self.getPage( idx )
+ p['ImageSize'] = str(len(data))
+
+
def metadataFromFilename( self ):
metadata = GenericMetadata()
diff --git a/comicinfoxml.py b/comicinfoxml.py
index b9c8a1a..1ba0c48 100644
--- a/comicinfoxml.py
+++ b/comicinfoxml.py
@@ -270,6 +270,7 @@ class ComicInfoXml:
if pages_node is not None:
for page in pages_node:
metadata.pages.append( page.attrib )
+ print page.attrib
metadata.isEmpty = False
diff --git a/comictagger.py b/comictagger.py
index 535b2f4..49ddab8 100755
--- a/comictagger.py
+++ b/comictagger.py
@@ -162,7 +162,8 @@ def cli_mode( opts, settings ):
def create_local_metadata( opts, ca, has_desired_tags ):
md = GenericMetadata()
-
+ md.setDefaultPageList( ca.getNumberOfPages() )
+
if has_desired_tags:
md = ca.readMetadata( opts.data_style )
@@ -235,7 +236,7 @@ def process_file_cli( filename, opts, settings, match_results ):
if has[ MetaDataStyle.CIX ]:
print "------ComicRack tags--------"
if opts.raw:
- print u"{0}".format(ca.readRawCIX())
+ print u"{0}".format(unicode(ca.readRawCIX(), errors='ignore'))
else:
print u"{0}".format(ca.readCIX())
@@ -307,7 +308,7 @@ def process_file_cli( filename, opts, settings, match_results ):
if opts.search_online:
ii = IssueIdentifier( ca, settings )
-
+
if md is None or md.isEmpty:
print "No metadata given to search online with!"
return
@@ -320,6 +321,7 @@ def process_file_cli( filename, opts, settings, match_results ):
ii.setAdditionalMetadata( md )
ii.onlyUseAdditionalMetaData = True
ii.setOutputFunction( myoutput )
+ ii.cover_page_index = md.getCoverPageIndexList()[0]
matches = ii.search()
result = ii.search_result
diff --git a/genericmetadata.py b/genericmetadata.py
index 145942c..e888861 100644
--- a/genericmetadata.py
+++ b/genericmetadata.py
@@ -104,7 +104,7 @@ class GenericMetadata:
self.rights = None
self.identifier = None
self.lastMark = None
-
+ self.coverImage = None
def overlay( self, new_md ):
# Overlay a metadata object on this one
@@ -167,7 +167,9 @@ class GenericMetadata:
# For now, go the easy route, where any overlay
# value wipes out the whole list
if len(new_md.tags) > 0:
- assign( "tags", new_md.tags )
+ assign( "tags", new_md.tags )
+
+ print "MD overlay len of old pages = {0} len of new pages = {1}".format(len(self.pages), len(new_md.pages))
if len(new_md.pages) > 0:
assign( "pages", new_md.pages )
@@ -187,7 +189,35 @@ class GenericMetadata:
# otherwise, add it!
else:
self.addCredit( c['person'], c['role'], primary )
-
+
+ def setDefaultPageList( self, count ):
+ # generate a default page list, with the first page marked as the cover
+ for i in range(count):
+ page_dict = dict()
+ page_dict['Image'] = str(i)
+ if i == 0:
+ page_dict['Type'] = PageType.FrontCover
+ self.pages.append( page_dict )
+
+ def getArchivePageIndex( self, pagenum ):
+ # convert the displayed page number to the page index of the file in the archive
+ if pagenum < len( self.pages ):
+ return int( self.pages[pagenum]['Image'] )
+ else:
+ return 0
+
+ def getCoverPageIndexList( self ):
+ # return a list of archive page indices of cover pages
+ coverlist = []
+ for p in self.pages:
+ if 'Type' in p and p['Type'] == PageType.FrontCover:
+ coverlist.append( int(p['Image']))
+
+ if len(coverlist) == 0:
+ coverlist.append( 0 )
+
+ return coverlist
+
def addCredit( self, person, role, primary = False ):
credit = dict()
diff --git a/issueidentifier.py b/issueidentifier.py
index 1749fba..53c525c 100644
--- a/issueidentifier.py
+++ b/issueidentifier.py
@@ -73,7 +73,8 @@ class IssueIdentifier:
self.output_function = IssueIdentifier.defaultWriteOutput
self.callback = None
self.search_result = self.ResultNoMatches
-
+ self.cover_page_index = 0
+
def setScoreMinThreshold( self, thresh ):
self.min_score_thresh = thresh
@@ -218,7 +219,7 @@ class IssueIdentifier:
self.log_msg( "Sorry, but "+ opts.filename + " is not a comic archive!")
return self.match_list
- cover_image_data = ca.getCoverPage()
+ cover_image_data = ca.getPage( self.cover_page_index )
cover_hash = self.calculateHash( cover_image_data )
#check the apect ratio
diff --git a/options.py b/options.py
index 0932bae..5a17653 100644
--- a/options.py
+++ b/options.py
@@ -23,6 +23,7 @@ import getopt
import platform
import os
+import ctversion
from genericmetadata import GenericMetadata
class Enum(set):
@@ -55,7 +56,7 @@ If no options are given, {0} will run in windowed mode
specified via via -t (potentially lossy operation)
-s, --save Save out tags as specified type (via -t)
Must specify also at least -o, -p, or -m
- --nooverwrite Don't modify tag block if it already exists ( relevent for -s or -c )
+ --nooverwrite Don't modify tag block if it already exists ( relevent for -s or -c )
-n, --dryrun Don't actually modify file (only relevent for -d, -s, or -r)
-t, --type=TYPE Specify TYPE as either "CR", "CBL", or "COMET" (as either
ComicRack, ComicBookLover, or CoMet style tags, respectivly)
@@ -79,6 +80,7 @@ If no options are given, {0} will run in windowed mode
--noabort Don't abort save operation when online match is of low confidence
-v, --verbose Be noisy when doing what it does
--terse Don't say much (for print mode)
+ --version Display version
-h, --help Display this message
"""
@@ -175,7 +177,7 @@ If no options are given, {0} will run in windowed mode
"hpdt:fm:vonsrc:i",
[ "help", "print", "delete", "type=", "copy=", "parsefilename", "metadata=", "verbose",
"online", "dryrun", "save", "rename" , "raw", "noabort", "terse", "nooverwrite",
- "interactive", "nosummary" ])
+ "interactive", "nosummary", "version" ])
except getopt.GetoptError as err:
self.display_help_and_quit( str(err), 2 )
@@ -224,6 +226,9 @@ If no options are given, {0} will run in windowed mode
self.show_save_summary = False
if o == "--nooverwrite":
self.no_overwrite = True
+ if o == "--version":
+ print "ComicTagger version: ", ctversion.version
+ quit()
if o in ("-t", "--type"):
if a.lower() == "cr":
self.data_style = MetaDataStyle.CIX
diff --git a/pagebrowser.py b/pagebrowser.py
index 3797638..c772714 100644
--- a/pagebrowser.py
+++ b/pagebrowser.py
@@ -26,7 +26,7 @@ from settings import ComicTaggerSettings
class PageBrowserWindow(QtGui.QDialog):
- def __init__(self, parent):
+ def __init__(self, parent, metadata):
super(PageBrowserWindow, self).__init__(parent)
uic.loadUi(os.path.join(ComicTaggerSettings.baseDir(), 'pagebrowser.ui' ), self)
@@ -37,6 +37,7 @@ class PageBrowserWindow(QtGui.QDialog):
self.current_pixmap = None
self.page_count = 0
self.current_page_num = 0
+ self.metadata = metadata
self.btnNext.clicked.connect( self.nextPage )
self.btnPrev.clicked.connect( self.prevPage )
@@ -66,7 +67,8 @@ class PageBrowserWindow(QtGui.QDialog):
self.setPage()
def setPage( self ):
- image_data = self.comic_archive.getPage( self.current_page_num )
+ archive_page_index = self.metadata.getArchivePageIndex( self.current_page_num )
+ image_data = self.comic_archive.getPage( archive_page_index )
if image_data is not None:
self.setCurrentPixmap( image_data )
diff --git a/pagelisteditor.py b/pagelisteditor.py
new file mode 100644
index 0000000..3036f0e
--- /dev/null
+++ b/pagelisteditor.py
@@ -0,0 +1,36 @@
+"""
+A PyQt4 widget for editing the page list info
+"""
+
+"""
+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 os
+
+from PyQt4.QtCore import *
+from PyQt4.QtGui import *
+from PyQt4 import uic
+
+from settings import ComicTaggerSettings
+
+class PageListEditor(QWidget):
+
+ def __init__(self, parent ):
+ super(PageListEditor, self).__init__(parent)
+
+ uic.loadUi(os.path.join(ComicTaggerSettings.baseDir(), 'pagelisteditor.ui' ), self )
+
+
diff --git a/pagelisteditor.ui b/pagelisteditor.ui
new file mode 100644
index 0000000..4a818f0
--- /dev/null
+++ b/pagelisteditor.ui
@@ -0,0 +1,103 @@
+
+
+ pageListEditor
+
+
+
+ 0
+ 0
+ 514
+ 328
+
+
+
+ Form
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+
+ 50
+ 16777215
+
+
+
+ ^
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 50
+ 16777215
+
+
+
+ v
+
+
+
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ QFrame::Panel
+
+
+ QFrame::Sunken
+
+
+ TextLabel
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
diff --git a/taggerwindow.py b/taggerwindow.py
index 4bde6fb..eda8079 100644
--- a/taggerwindow.py
+++ b/taggerwindow.py
@@ -43,6 +43,7 @@ from pagebrowser import PageBrowserWindow
from filenameparser import FileNameParser
from logwindow import LogWindow
from optionalmsgdialog import OptionalMessageDialog
+from pagelisteditor import PageListEditor
import utils
import ctversion
@@ -88,6 +89,11 @@ class TaggerWindow( QtGui.QMainWindow):
#signal.signal(signal.SIGINT, self.sigint_handler)
uic.loadUi(os.path.join(ComicTaggerSettings.baseDir(), 'taggerwindow.ui' ), self)
+
+ self.pageListEditor = PageListEditor( self.tabPages )
+ gridlayout = QtGui.QGridLayout( self.tabPages )
+ gridlayout.addWidget( self.pageListEditor )
+
self.setWindowIcon(QtGui.QIcon(os.path.join(ComicTaggerSettings.baseDir(), 'graphics/app.png' )))
self.lblCover.setPixmap(QtGui.QPixmap(os.path.join(ComicTaggerSettings.baseDir(), 'graphics/nocover.png' )))
@@ -339,8 +345,6 @@ class TaggerWindow( QtGui.QMainWindow):
msgBox.exec_()
-
-
def dragEnterEvent(self, event):
self.droppedFile=None
if event.mimeData().hasUrls():
@@ -382,6 +386,7 @@ class TaggerWindow( QtGui.QMainWindow):
# 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
@@ -410,8 +415,10 @@ class TaggerWindow( QtGui.QMainWindow):
if self.metadata.isEmpty:
self.metadata = self.comic_archive.metadataFromFilename( )
-
- image_data = self.comic_archive.getCoverPage()
+ self.metadata.setDefaultPageList( self.comic_archive.getNumberOfPages() )
+
+ cover_idx = self.metadata.getCoverPageIndexList()[0]
+ image_data = self.comic_archive.getPage( cover_idx )
if not image_data is None:
img = QtGui.QImage()
img.loadFromData( image_data )
@@ -420,6 +427,7 @@ class TaggerWindow( QtGui.QMainWindow):
if self.page_browser is not None:
self.page_browser.setComicArchive( self.comic_archive )
+ self.page_browser.metadata = self.metadata
self.metadataToForm()
self.clearDirtyFlag() # also updates the app title
@@ -574,6 +582,8 @@ class TaggerWindow( QtGui.QMainWindow):
# get a minty fresh metadata object
self.metadata = GenericMetadata()
+ if self.comic_archive is not None:
+ self.metadata.setDefaultPageList( self.comic_archive.getNumberOfPages() )
# recursivly clear the tab form
self.clearChildren( self.tabWidget )
@@ -789,11 +799,14 @@ class TaggerWindow( QtGui.QMainWindow):
md.addCredit( name, role, bool(primary_flag) )
row += 1
-
def useFilename( self ):
if self.comic_archive is not None:
- self.metadata = self.comic_archive.metadataFromFilename( )
- self.metadataToForm()
+ #copy the form onto metadata object
+ self.formToMetadata()
+ new_metadata = self.comic_archive.metadataFromFilename( )
+ if new_metadata is not None:
+ self.metadata.overlay( new_metadata )
+ self.metadataToForm()
def selectFile( self ):
@@ -850,7 +863,8 @@ class TaggerWindow( QtGui.QMainWindow):
if year == "":
year = None
- selector = VolumeSelectionWindow( self, series_name, issue_number, year, self.comic_archive, self.settings, autoselect )
+ cover_index_list = self.metadata.getCoverPageIndexList()
+ selector = VolumeSelectionWindow( self, series_name, issue_number, year, cover_index_list, self.comic_archive, self.settings, autoselect )
title = "Search: '" + series_name + "' - "
selector.setWindowTitle( title + "Select Series")
@@ -1318,7 +1332,7 @@ class TaggerWindow( QtGui.QMainWindow):
def showPageBrowser( self ):
if self.page_browser is None:
- self.page_browser = PageBrowserWindow( self )
+ self.page_browser = PageBrowserWindow( self, self.metadata )
if self.comic_archive is not None:
self.page_browser.setComicArchive( self.comic_archive )
self.page_browser.finished.connect(self.pageBrowserClosed)
diff --git a/taggerwindow.ui b/taggerwindow.ui
index 9f421d8..2fba210 100644
--- a/taggerwindow.ui
+++ b/taggerwindow.ui
@@ -1028,6 +1028,11 @@
+
+
+ Pages
+
+
diff --git a/volumeselectionwindow.py b/volumeselectionwindow.py
index c877213..32bfa4f 100644
--- a/volumeselectionwindow.py
+++ b/volumeselectionwindow.py
@@ -85,7 +85,7 @@ class IdentifyThread( QtCore.QThread):
class VolumeSelectionWindow(QtGui.QDialog):
- def __init__(self, parent, series_name, issue_number, year, comic_archive, settings, autoselect=False):
+ def __init__(self, parent, series_name, issue_number, year, cover_index_list, comic_archive, settings, autoselect=False):
super(VolumeSelectionWindow, self).__init__(parent)
uic.loadUi(os.path.join(ComicTaggerSettings.baseDir(), 'volumeselectionwindow.ui' ), self)
@@ -97,7 +97,8 @@ class VolumeSelectionWindow(QtGui.QDialog):
self.volume_id = 0
self.comic_archive = comic_archive
self.immediate_autoselect = autoselect
-
+ self.cover_index_list = cover_index_list
+
self.twList.resizeColumnsToContents()
self.twList.currentItemChanged.connect(self.currentItemChanged)
self.twList.cellDoubleClicked.connect(self.cellDoubleClicked)
@@ -136,6 +137,8 @@ class VolumeSelectionWindow(QtGui.QDialog):
self.ii.setAdditionalMetadata( md )
self.ii.onlyUseAdditionalMetaData = True
+ print self.cover_index_list
+ self.ii.cover_page_index = int(self.cover_index_list[0])
self.id_thread = IdentifyThread( self.ii )
self.id_thread.identifyComplete.connect( self.identifyComplete )