Compare commits
22 Commits
1.1.12-bet
...
1.1.14-bet
Author | SHA1 | Date | |
---|---|---|---|
f97a1653d9 | |||
d9dbab301a | |||
3d93197101 | |||
752a1d8923 | |||
68002daffa | |||
ad5062c582 | |||
2680468f34 | |||
6156fc296a | |||
0feed294d4 | |||
e57736b955 | |||
70fcdc0129 | |||
9a64195ebd | |||
b0f229f851 | |||
877a5ccd85 | |||
c0f2e2f771 | |||
0adfc9beb3 | |||
d0bc41d7ee | |||
fa46a065a4 | |||
8fcd5ba7d6 | |||
759cdc6b40 | |||
1405d9ff0e | |||
d8fcbbad0a |
1
Makefile
1
Makefile
@ -53,6 +53,7 @@ upload:
|
||||
#$(UPLOAD_TOOL) -p comictagger -s "ComicTagger $(VERSION_STR) Mac OS X" -l Featured,Type-Archive -u beville -w $(PASSWORD) "release/ComicTagger-$(VERSION_STR).dmg"
|
||||
#$(UPLOAD_TOOL) -p comictagger -s "ComicTagger $(VERSION_STR) Windows" -l Featured,Type-Installer -u beville -w $(PASSWORD) "release/ComicTagger v$(VERSION_STR).exe"
|
||||
python setup.py register
|
||||
python setup.py sdist --formats=zip upload
|
||||
|
||||
svn_tag:
|
||||
svn copy https://comictagger.googlecode.com/svn/trunk \
|
||||
|
@ -48,6 +48,17 @@ class AutoTagStartWindow(QtGui.QDialog):
|
||||
self.cbxSpecifySearchString.setCheckState( QtCore.Qt.Unchecked )
|
||||
self.leNameLengthMatchTolerance.setText( str(self.settings.id_length_delta_thresh) )
|
||||
self.leSearchString.setEnabled( False )
|
||||
|
||||
if self.settings.save_on_low_confidence:
|
||||
self.cbxSaveOnLowConfidence.setCheckState( QtCore.Qt.Checked)
|
||||
if self.settings.dont_use_year_when_identifying:
|
||||
self.cbxDontUseYear.setCheckState( QtCore.Qt.Checked)
|
||||
if self.settings.assume_1_if_no_issue_num:
|
||||
self.cbxAssumeIssueOne.setCheckState( QtCore.Qt.Checked)
|
||||
if self.settings.ignore_leading_numbers_in_filename:
|
||||
self.cbxIgnoreLeadingDigitsInFilename.setCheckState( QtCore.Qt.Checked)
|
||||
if self.settings.remove_archive_after_successful_match:
|
||||
self.cbxRemoveAfterSuccess.setCheckState( QtCore.Qt.Checked)
|
||||
|
||||
nlmtTip = (
|
||||
""" <html>The <b>Name Length Match Tolerance</b> is for eliminating automatic
|
||||
@ -97,6 +108,13 @@ class AutoTagStartWindow(QtGui.QDialog):
|
||||
self.removeAfterSuccess = self.cbxRemoveAfterSuccess.isChecked()
|
||||
self.nameLengthMatchTolerance = int(self.leNameLengthMatchTolerance.text())
|
||||
|
||||
#persist some settings
|
||||
self.settings.save_on_low_confidence = self.autoSaveOnLow
|
||||
self.settings.dont_use_year_when_identifying = self.dontUseYear
|
||||
self.settings.assume_1_if_no_issue_num = self.assumeIssueOne
|
||||
self.settings.ignore_leading_numbers_in_filename = self.ignoreLeadingDigitsInFilename
|
||||
self.settings.remove_archive_after_successful_match = self.removeAfterSuccess
|
||||
|
||||
if self.cbxSpecifySearchString.isChecked():
|
||||
self.searchString = unicode(self.leSearchString.text())
|
||||
if len(self.searchString) == 0:
|
||||
|
@ -74,6 +74,9 @@ class CBLTransformer:
|
||||
|
||||
if self.settings.copy_locations_to_tags:
|
||||
add_string_list_to_tags( self.metadata.locations )
|
||||
|
||||
if self.settings.copy_storyarcs_to_tags:
|
||||
add_string_list_to_tags( self.metadata.storyArc )
|
||||
|
||||
if self.settings.copy_notes_to_comments:
|
||||
if self.metadata.notes is not None:
|
||||
|
@ -115,7 +115,7 @@ def display_match_set_for_choice( label, match_set, opts, settings ):
|
||||
i = int(i) - 1
|
||||
# save the data!
|
||||
# we know at this point, that the file is all good to go
|
||||
ca = ComicArchive( match_set.filename, settings )
|
||||
ca = ComicArchive( match_set.filename, settings.rar_exe_path )
|
||||
md = create_local_metadata( opts, ca, ca.hasMetadata(opts.data_style) )
|
||||
cv_md = actual_issue_data_fetch(match_set.matches[int(i)], settings)
|
||||
md.overlay( cv_md )
|
||||
@ -209,7 +209,7 @@ def process_file_cli( filename, opts, settings, match_results ):
|
||||
|
||||
batch_mode = len( opts.file_list ) > 1
|
||||
|
||||
ca = ComicArchive(filename, settings)
|
||||
ca = ComicArchive(filename, settings.rar_exe_path)
|
||||
|
||||
if not os.path.lexists( filename ):
|
||||
print >> sys.stderr,"Cannot find "+ filename
|
||||
|
@ -42,12 +42,12 @@ sys.path.insert(0, os.path.abspath(".") )
|
||||
import UnRAR2
|
||||
from UnRAR2.rar_exceptions import *
|
||||
|
||||
from settings import ComicTaggerSettings
|
||||
from comicinfoxml import ComicInfoXml
|
||||
from comicbookinfo import ComicBookInfo
|
||||
from comet import CoMet
|
||||
from genericmetadata import GenericMetadata, PageType
|
||||
from filenameparser import FileNameParser
|
||||
from settings import ComicTaggerSettings
|
||||
|
||||
class MetaDataStyle:
|
||||
CBI = 0
|
||||
@ -239,9 +239,9 @@ class ZipArchiver:
|
||||
class RarArchiver:
|
||||
|
||||
devnull = None
|
||||
def __init__( self, path, settings ):
|
||||
def __init__( self, path, rar_exe_path ):
|
||||
self.path = path
|
||||
self.settings = settings
|
||||
self.rar_exe_path = rar_exe_path
|
||||
|
||||
if RarArchiver.devnull is None:
|
||||
RarArchiver.devnull = open(os.devnull, "w")
|
||||
@ -264,7 +264,7 @@ class RarArchiver:
|
||||
|
||||
def setArchiveComment( self, comment ):
|
||||
|
||||
if self.settings.rar_exe_path is not None:
|
||||
if self.rar_exe_path is not None:
|
||||
try:
|
||||
# write comment to temp file
|
||||
tmp_fd, tmp_name = tempfile.mkstemp()
|
||||
@ -275,7 +275,7 @@ class RarArchiver:
|
||||
working_dir = os.path.dirname( os.path.abspath( self.path ) )
|
||||
|
||||
# use external program to write comment to Rar archive
|
||||
subprocess.call([self.settings.rar_exe_path, 'c', '-w' + working_dir , '-c-', '-z' + tmp_name, self.path],
|
||||
subprocess.call([self.rar_exe_path, 'c', '-w' + working_dir , '-c-', '-z' + tmp_name, self.path],
|
||||
startupinfo=self.startupinfo,
|
||||
stdout=RarArchiver.devnull)
|
||||
|
||||
@ -333,7 +333,7 @@ class RarArchiver:
|
||||
|
||||
def writeArchiveFile( self, archive_file, data ):
|
||||
|
||||
if self.settings.rar_exe_path is not None:
|
||||
if self.rar_exe_path is not None:
|
||||
try:
|
||||
tmp_folder = tempfile.mkdtemp()
|
||||
|
||||
@ -348,7 +348,7 @@ class RarArchiver:
|
||||
f.close()
|
||||
|
||||
# use external program to write file to Rar archive
|
||||
subprocess.call([self.settings.rar_exe_path, 'a', '-w' + working_dir ,'-c-', '-ep', self.path, tmp_file],
|
||||
subprocess.call([self.rar_exe_path, 'a', '-w' + working_dir ,'-c-', '-ep', self.path, tmp_file],
|
||||
startupinfo=self.startupinfo,
|
||||
stdout=RarArchiver.devnull)
|
||||
|
||||
@ -364,10 +364,10 @@ class RarArchiver:
|
||||
return False
|
||||
|
||||
def removeArchiveFile( self, archive_file ):
|
||||
if self.settings.rar_exe_path is not None:
|
||||
if self.rar_exe_path is not None:
|
||||
try:
|
||||
# use external program to remove file from Rar archive
|
||||
subprocess.call([self.settings.rar_exe_path, 'd','-c-', self.path, archive_file],
|
||||
subprocess.call([self.rar_exe_path, 'd','-c-', self.path, archive_file],
|
||||
startupinfo=self.startupinfo,
|
||||
stdout=RarArchiver.devnull)
|
||||
|
||||
@ -515,17 +515,17 @@ class ComicArchive:
|
||||
class ArchiveType:
|
||||
Zip, Rar, Folder, Unknown = range(4)
|
||||
|
||||
def __init__( self, path, settings ):
|
||||
def __init__( self, path, rar_exe_path=None ):
|
||||
self.path = path
|
||||
|
||||
self.rar_exe_path = rar_exe_path
|
||||
self.ci_xml_filename = 'ComicInfo.xml'
|
||||
self.comet_default_filename = 'CoMet.xml'
|
||||
self.resetCache()
|
||||
self.settings = settings
|
||||
|
||||
if self.rarTest():
|
||||
self.archive_type = self.ArchiveType.Rar
|
||||
self.archiver = RarArchiver( self.path, settings )
|
||||
self.archiver = RarArchiver( self.path, rar_exe_path=self.rar_exe_path )
|
||||
|
||||
elif self.zipTest():
|
||||
self.archive_type = self.ArchiveType.Zip
|
||||
@ -588,7 +588,7 @@ class ComicArchive:
|
||||
if self.archive_type == self.ArchiveType.Unknown :
|
||||
return False
|
||||
|
||||
elif check_rar_status and self.isRar() and self.settings.rar_exe_path is None:
|
||||
elif check_rar_status and self.isRar() and self.rar_exe_path is None:
|
||||
return False
|
||||
|
||||
elif not os.access(self.path, os.W_OK):
|
||||
@ -1016,7 +1016,7 @@ class ComicArchive:
|
||||
|
||||
|
||||
|
||||
def metadataFromFilename( self ):
|
||||
def metadataFromFilename( self , parse_scan_info=True):
|
||||
|
||||
metadata = GenericMetadata()
|
||||
|
||||
@ -1033,7 +1033,7 @@ class ComicArchive:
|
||||
metadata.year = fnp.year
|
||||
if fnp.issue_count != "":
|
||||
metadata.issueCount = fnp.issue_count
|
||||
if self.settings.parse_scan_info:
|
||||
if parse_scan_info:
|
||||
if fnp.remainder != "":
|
||||
metadata.scanInfo = fnp.remainder
|
||||
|
||||
|
@ -412,7 +412,7 @@ class ComicVineTalker(QObject):
|
||||
metadata.day, metadata.month, metadata.year = self.parseDateStr( issue_results['cover_date'] )
|
||||
|
||||
#metadata.issueCount = volume_results['count_of_issues']
|
||||
metadata.comments = self.cleanup_html(issue_results['description'])
|
||||
metadata.comments = self.cleanup_html(issue_results['description'], settings.remove_html_tables)
|
||||
if settings.use_series_start_as_volume:
|
||||
metadata.volume = volume_results['start_year']
|
||||
|
||||
@ -458,11 +458,25 @@ class ComicVineTalker(QObject):
|
||||
metadata.storyArc = utils.listToString(arc_list)
|
||||
|
||||
return metadata
|
||||
|
||||
def cleanup_html( self, string):
|
||||
def cleanup_html( self, string, remove_html_tables):
|
||||
"""
|
||||
converter = html2text.HTML2Text()
|
||||
#converter.emphasis_mark = '*'
|
||||
#converter.ignore_links = True
|
||||
converter.body_width = 0
|
||||
|
||||
print html2text.html2text(string)
|
||||
return string
|
||||
#return converter.handle(string)
|
||||
"""
|
||||
|
||||
|
||||
if string is None:
|
||||
return ""
|
||||
# find any tables
|
||||
soup = BeautifulSoup(string)
|
||||
tables = soup.findAll('table')
|
||||
|
||||
# remove all newlines first
|
||||
string = string.replace("\n", "")
|
||||
|
||||
@ -471,6 +485,14 @@ class ComicVineTalker(QObject):
|
||||
string = string.replace("</p>", "\n\n")
|
||||
string = string.replace("<h4>", "*")
|
||||
string = string.replace("</h4>", "*\n")
|
||||
|
||||
#remove the tables
|
||||
p = re.compile(r'<table[^<]*?>.*?<\/table>')
|
||||
if remove_html_tables:
|
||||
string = p.sub('',string)
|
||||
string = string.replace("*List of covers and their creators:*","")
|
||||
else:
|
||||
string = p.sub('{}',string)
|
||||
|
||||
# now strip all other tags
|
||||
p = re.compile(r'<[^<]*?>')
|
||||
@ -480,6 +502,57 @@ class ComicVineTalker(QObject):
|
||||
newstring = newstring.replace('&','&')
|
||||
|
||||
newstring = newstring.strip()
|
||||
|
||||
if not remove_html_tables:
|
||||
# now rebuild the tables into text from BSoup
|
||||
try:
|
||||
table_strings = []
|
||||
for table in tables:
|
||||
rows = []
|
||||
hdrs = []
|
||||
col_widths = []
|
||||
for hdr in table.findAll('th'):
|
||||
item = hdr.string.strip()
|
||||
hdrs.append(item)
|
||||
col_widths.append(len(item))
|
||||
rows.append(hdrs)
|
||||
|
||||
for row in table.findAll('tr'):
|
||||
cols = []
|
||||
col = row.findAll('td')
|
||||
i = 0
|
||||
for c in col:
|
||||
item = c.string.strip()
|
||||
cols.append(item)
|
||||
if len(item) > col_widths[i]:
|
||||
col_widths[i] = len(item)
|
||||
i += 1
|
||||
if len(cols) != 0:
|
||||
rows.append(cols)
|
||||
# now we have the data, make it into text
|
||||
fmtstr =""
|
||||
for w in col_widths:
|
||||
fmtstr += " {{:{}}}|".format(w+1)
|
||||
width = sum(col_widths) + len(col_widths)*2
|
||||
print "width=" , width
|
||||
table_text = ""
|
||||
counter = 0
|
||||
for row in rows:
|
||||
table_text += fmtstr.format(*row) + "\n"
|
||||
if counter == 0 and len(hdrs)!= 0:
|
||||
table_text += "-" * width + "\n"
|
||||
counter += 1
|
||||
|
||||
table_strings.append(table_text)
|
||||
|
||||
newstring = newstring.format(*table_strings)
|
||||
except:
|
||||
# we caught an error rebuilding the table.
|
||||
# just bail and remove the formatting
|
||||
print "table parse error"
|
||||
newstring.replace("{}", "")
|
||||
|
||||
|
||||
return newstring
|
||||
|
||||
def fetchIssueDate( self, issue_id ):
|
||||
@ -665,4 +738,4 @@ class ComicVineTalker(QObject):
|
||||
issue['image'] = dict()
|
||||
issue['image']['super_url'] = ComicVineTalker.logo_url
|
||||
issue['image']['thumb_url'] = ComicVineTalker.logo_url
|
||||
|
||||
|
||||
|
@ -1,3 +1,3 @@
|
||||
# This file should contan only these comments, and the line below.
|
||||
# Used by packaging makefiles and app
|
||||
version="1.1.12-beta"
|
||||
version="1.1.14-beta"
|
||||
|
@ -31,7 +31,10 @@ from settings import ComicTaggerSettings
|
||||
from comicarchive import ComicArchive
|
||||
from comicarchive import MetaDataStyle
|
||||
from genericmetadata import GenericMetadata, PageType
|
||||
from optionalmsgdialog import OptionalMessageDialog
|
||||
import utils
|
||||
import platform
|
||||
import os
|
||||
|
||||
class FileTableWidget( QTableWidget ):
|
||||
|
||||
@ -172,7 +175,6 @@ class FileSelectionList(QWidget):
|
||||
def addPathList( self, pathlist ):
|
||||
|
||||
filelist = utils.get_recursive_filelist( pathlist )
|
||||
|
||||
# we now have a list of files to add
|
||||
|
||||
progdialog = QProgressDialog("", "Cancel", 0, len(filelist), self)
|
||||
@ -196,6 +198,24 @@ class FileSelectionList(QWidget):
|
||||
firstAdded = row
|
||||
|
||||
progdialog.close()
|
||||
if ( self.settings.show_no_unrar_warning and
|
||||
self.settings.unrar_exe_path == "" and
|
||||
self.settings.rar_exe_path == "" and
|
||||
platform.system() != "Windows"):
|
||||
for f in filelist:
|
||||
ext = os.path.splitext(f)[1].lower()
|
||||
if ext == ".rar" or ext ==".cbr":
|
||||
checked = OptionalMessageDialog.msg( self, "No unrar tool",
|
||||
"""
|
||||
It looks like you've tried to open at least one CBR or RAR file.<br><br>
|
||||
In order for ComicTagger to read this kind of file, you will have to configure
|
||||
the location of the unrar tool in the settings. Until then, ComicTagger
|
||||
will not be able recognize these kind of files.
|
||||
"""
|
||||
)
|
||||
self.settings.show_no_unrar_warning = not checked
|
||||
break
|
||||
|
||||
if firstAdded is not None:
|
||||
self.twList.selectRow(firstAdded)
|
||||
else:
|
||||
@ -226,7 +246,17 @@ class FileSelectionList(QWidget):
|
||||
return True
|
||||
r = r + 1
|
||||
|
||||
return False
|
||||
return False
|
||||
|
||||
def getCurrentListRow( self, path ):
|
||||
r = 0
|
||||
while r < self.twList.rowCount():
|
||||
ca = self.getArchiveByRow( r )
|
||||
if ca.path == path:
|
||||
return r
|
||||
r = r + 1
|
||||
|
||||
return -1
|
||||
|
||||
def addPathItem( self, path):
|
||||
path = unicode( path )
|
||||
@ -234,9 +264,9 @@ class FileSelectionList(QWidget):
|
||||
#print "processing", path
|
||||
|
||||
if self.isListDupe(path):
|
||||
return None
|
||||
return self.getCurrentListRow(path)
|
||||
|
||||
ca = ComicArchive( path, self.settings )
|
||||
ca = ComicArchive( path, self.settings.rar_exe_path )
|
||||
|
||||
if ca.seemsToBeAComicArchive() :
|
||||
row = self.twList.rowCount()
|
||||
|
@ -31,7 +31,7 @@ class PageType:
|
||||
InnerCover = "InnerCover"
|
||||
Roundup = "Roundup"
|
||||
Story = "Story"
|
||||
Advertisment = "Advertisement"
|
||||
Advertisement = "Advertisement"
|
||||
Editorial = "Editorial"
|
||||
Letters = "Letters"
|
||||
Preview = "Preview"
|
||||
|
@ -43,6 +43,12 @@ class IssueString:
|
||||
|
||||
if text is None:
|
||||
return
|
||||
|
||||
if type(text) == int:
|
||||
text = str(text)
|
||||
|
||||
if len(text) == 0:
|
||||
return
|
||||
|
||||
text = unicode(text)
|
||||
|
||||
|
@ -64,7 +64,7 @@ def ctmain():
|
||||
app.processEvents()
|
||||
|
||||
try:
|
||||
tagger_window = TaggerWindow( opts.file_list, settings )
|
||||
tagger_window = TaggerWindow( opts.file_list, settings, opts=opts )
|
||||
tagger_window.show()
|
||||
|
||||
if platform.system() != "Linux":
|
||||
|
@ -60,7 +60,7 @@ class OptionalMessageDialog(QDialog):
|
||||
if style == StyleQuestion:
|
||||
check_text = "Remember this answer"
|
||||
else:
|
||||
check_text = "Don't show this dialog again"
|
||||
check_text = "Don't show this message again"
|
||||
|
||||
self.theCheckBox = QCheckBox(check_text)
|
||||
|
||||
|
@ -64,7 +64,7 @@ class PageListEditor(QWidget):
|
||||
pageTypeNames = {
|
||||
PageType.FrontCover: "Front Cover",
|
||||
PageType.InnerCover: "Inner Cover",
|
||||
PageType.Advertisment: "Advertisment",
|
||||
PageType.Advertisement: "Advertisement",
|
||||
PageType.Roundup: "Roundup",
|
||||
PageType.Story: "Story",
|
||||
PageType.Editorial: "Editorial",
|
||||
@ -92,7 +92,7 @@ class PageListEditor(QWidget):
|
||||
self.comboBox.addItem( "", "" )
|
||||
self.comboBox.addItem( self.pageTypeNames[ PageType.FrontCover], PageType.FrontCover )
|
||||
self.comboBox.addItem( self.pageTypeNames[ PageType.InnerCover], PageType.InnerCover )
|
||||
self.comboBox.addItem( self.pageTypeNames[ PageType.Advertisment], PageType.Advertisment )
|
||||
self.comboBox.addItem( self.pageTypeNames[ PageType.Advertisement], PageType.Advertisement )
|
||||
self.comboBox.addItem( self.pageTypeNames[ PageType.Roundup], PageType.Roundup )
|
||||
self.comboBox.addItem( self.pageTypeNames[ PageType.Story], PageType.Story )
|
||||
self.comboBox.addItem( self.pageTypeNames[ PageType.Editorial], PageType.Editorial )
|
||||
|
@ -72,7 +72,7 @@ class RenameWindow(QtGui.QDialog):
|
||||
|
||||
md = ca.readMetadata(self.data_style)
|
||||
if md.isEmpty:
|
||||
md = ca.metadataFromFilename()
|
||||
md = ca.metadataFromFilename(self.settings.parse_scan_info)
|
||||
self.renamer.setMetadata( md )
|
||||
new_name = self.renamer.determineName( ca.path, ext=new_ext )
|
||||
|
||||
|
@ -32,11 +32,15 @@ class ComicTaggerSettings:
|
||||
|
||||
@staticmethod
|
||||
def getSettingsFolder():
|
||||
filename_encoding = sys.getfilesystemencoding()
|
||||
if platform.system() == "Windows":
|
||||
return os.path.join( os.environ['APPDATA'], 'ComicTagger' )
|
||||
folder = os.path.join( os.environ['APPDATA'], 'ComicTagger' )
|
||||
else:
|
||||
return os.path.join( os.path.expanduser('~') , '.ComicTagger')
|
||||
|
||||
folder = os.path.join( os.path.expanduser('~') , '.ComicTagger')
|
||||
if folder is not None:
|
||||
folder = folder.decode(filename_encoding)
|
||||
return folder
|
||||
|
||||
frozen_win_exe_path = None
|
||||
|
||||
@staticmethod
|
||||
@ -94,12 +98,15 @@ class ComicTaggerSettings:
|
||||
self.show_disclaimer = True
|
||||
self.dont_notify_about_this_version = ""
|
||||
self.ask_about_usage_stats = True
|
||||
self.show_no_unrar_warning = True
|
||||
|
||||
#filename parsing settings
|
||||
self.parse_scan_info = True
|
||||
|
||||
# Comic Vine settings
|
||||
self.use_series_start_as_volume = False
|
||||
self.clear_form_before_populating_from_cv = False
|
||||
self.remove_html_tables = False
|
||||
|
||||
# CBL Tranform settings
|
||||
|
||||
@ -107,6 +114,7 @@ class ComicTaggerSettings:
|
||||
self.copy_characters_to_tags = False
|
||||
self.copy_teams_to_tags = False
|
||||
self.copy_locations_to_tags = False
|
||||
self.copy_storyarcs_to_tags = False
|
||||
self.copy_notes_to_comments = False
|
||||
self.copy_weblink_to_comments = False
|
||||
self.apply_cbl_transform_on_cv_import = False
|
||||
@ -117,6 +125,13 @@ class ComicTaggerSettings:
|
||||
self.rename_issue_number_padding = 3
|
||||
self.rename_use_smart_string_cleanup = True
|
||||
self.rename_extension_based_on_archive = True
|
||||
|
||||
#Auto-tag stickies
|
||||
self.save_on_low_confidence = False
|
||||
self.dont_use_year_when_identifying = False
|
||||
self.assume_1_if_no_issue_num = False
|
||||
self.ignore_leading_numbers_in_filename = False
|
||||
self.remove_archive_after_successful_match = False
|
||||
|
||||
def __init__(self):
|
||||
|
||||
@ -228,9 +243,16 @@ class ComicTaggerSettings:
|
||||
self.dont_notify_about_this_version = self.config.get( 'dialogflags', 'dont_notify_about_this_version' )
|
||||
if self.config.has_option('dialogflags', 'ask_about_usage_stats'):
|
||||
self.ask_about_usage_stats = self.config.getboolean( 'dialogflags', 'ask_about_usage_stats' )
|
||||
if self.config.has_option('dialogflags', 'show_no_unrar_warning'):
|
||||
self.show_no_unrar_warning = self.config.getboolean( 'dialogflags', 'show_no_unrar_warning' )
|
||||
|
||||
if self.config.has_option('comicvine', 'use_series_start_as_volume'):
|
||||
self.use_series_start_as_volume = self.config.getboolean( 'comicvine', 'use_series_start_as_volume' )
|
||||
if self.config.has_option('comicvine', 'clear_form_before_populating_from_cv'):
|
||||
self.clear_form_before_populating_from_cv = self.config.getboolean( 'comicvine', 'clear_form_before_populating_from_cv' )
|
||||
if self.config.has_option('comicvine', 'remove_html_tables'):
|
||||
self.remove_html_tables = self.config.getboolean( 'comicvine', 'remove_html_tables' )
|
||||
|
||||
|
||||
if self.config.has_option('cbl_transform', 'assume_lone_credit_is_primary'):
|
||||
self.assume_lone_credit_is_primary = self.config.getboolean( 'cbl_transform', 'assume_lone_credit_is_primary' )
|
||||
@ -241,7 +263,9 @@ class ComicTaggerSettings:
|
||||
if self.config.has_option('cbl_transform', 'copy_locations_to_tags'):
|
||||
self.copy_locations_to_tags = self.config.getboolean( 'cbl_transform', 'copy_locations_to_tags' )
|
||||
if self.config.has_option('cbl_transform', 'copy_notes_to_comments'):
|
||||
self.copy_notes_to_comments = self.config.getboolean( 'cbl_transform', 'copy_notes_to_comments' )
|
||||
self.copy_notes_to_comments = self.config.getboolean( 'cbl_transform', 'copy_notes_to_comments' )
|
||||
if self.config.has_option('cbl_transform', 'copy_storyarcs_to_tags'):
|
||||
self.copy_storyarcs_to_tags = self.config.getboolean( 'cbl_transform', 'copy_storyarcs_to_tags' )
|
||||
if self.config.has_option('cbl_transform', 'copy_weblink_to_comments'):
|
||||
self.copy_weblink_to_comments = self.config.getboolean( 'cbl_transform', 'copy_weblink_to_comments' )
|
||||
if self.config.has_option('cbl_transform', 'apply_cbl_transform_on_cv_import'):
|
||||
@ -257,7 +281,18 @@ class ComicTaggerSettings:
|
||||
self.rename_use_smart_string_cleanup = self.config.getboolean( 'rename', 'rename_use_smart_string_cleanup' )
|
||||
if self.config.has_option('rename', 'rename_extension_based_on_archive'):
|
||||
self.rename_extension_based_on_archive = self.config.getboolean( 'rename', 'rename_extension_based_on_archive' )
|
||||
|
||||
|
||||
if self.config.has_option('autotag', 'save_on_low_confidence'):
|
||||
self.save_on_low_confidence = self.config.getboolean( 'autotag', 'save_on_low_confidence' )
|
||||
if self.config.has_option('autotag', 'dont_use_year_when_identifying'):
|
||||
self.dont_use_year_when_identifying = self.config.getboolean( 'autotag', 'dont_use_year_when_identifying' )
|
||||
if self.config.has_option('autotag', 'assume_1_if_no_issue_num'):
|
||||
self.assume_1_if_no_issue_num = self.config.getboolean( 'autotag', 'assume_1_if_no_issue_num' )
|
||||
if self.config.has_option('autotag', 'ignore_leading_numbers_in_filename'):
|
||||
self.ignore_leading_numbers_in_filename = self.config.getboolean( 'autotag', 'ignore_leading_numbers_in_filename' )
|
||||
if self.config.has_option('autotag', 'remove_archive_after_successful_match'):
|
||||
self.remove_archive_after_successful_match = self.config.getboolean( 'autotag', 'remove_archive_after_successful_match' )
|
||||
|
||||
def save( self ):
|
||||
|
||||
if not self.config.has_section( 'settings' ):
|
||||
@ -297,6 +332,7 @@ class ComicTaggerSettings:
|
||||
self.config.set( 'dialogflags', 'show_disclaimer', self.show_disclaimer )
|
||||
self.config.set( 'dialogflags', 'dont_notify_about_this_version', self.dont_notify_about_this_version )
|
||||
self.config.set( 'dialogflags', 'ask_about_usage_stats', self.ask_about_usage_stats )
|
||||
self.config.set( 'dialogflags', 'show_no_unrar_warning', self.show_no_unrar_warning )
|
||||
|
||||
if not self.config.has_section( 'filenameparser' ):
|
||||
self.config.add_section( 'filenameparser' )
|
||||
@ -307,6 +343,8 @@ class ComicTaggerSettings:
|
||||
self.config.add_section( 'comicvine' )
|
||||
|
||||
self.config.set( 'comicvine', 'use_series_start_as_volume', self.use_series_start_as_volume )
|
||||
self.config.set( 'comicvine', 'clear_form_before_populating_from_cv', self.clear_form_before_populating_from_cv )
|
||||
self.config.set( 'comicvine', 'remove_html_tables', self.remove_html_tables )
|
||||
|
||||
if not self.config.has_section( 'cbl_transform' ):
|
||||
self.config.add_section( 'cbl_transform' )
|
||||
@ -315,6 +353,7 @@ class ComicTaggerSettings:
|
||||
self.config.set( 'cbl_transform', 'copy_characters_to_tags', self.copy_characters_to_tags )
|
||||
self.config.set( 'cbl_transform', 'copy_teams_to_tags', self.copy_teams_to_tags )
|
||||
self.config.set( 'cbl_transform', 'copy_locations_to_tags', self.copy_locations_to_tags )
|
||||
self.config.set( 'cbl_transform', 'copy_storyarcs_to_tags', self.copy_storyarcs_to_tags )
|
||||
self.config.set( 'cbl_transform', 'copy_notes_to_comments', self.copy_notes_to_comments )
|
||||
self.config.set( 'cbl_transform', 'copy_weblink_to_comments', self.copy_weblink_to_comments )
|
||||
self.config.set( 'cbl_transform', 'apply_cbl_transform_on_cv_import', self.apply_cbl_transform_on_cv_import )
|
||||
@ -327,6 +366,14 @@ class ComicTaggerSettings:
|
||||
self.config.set( 'rename', 'rename_issue_number_padding', self.rename_issue_number_padding )
|
||||
self.config.set( 'rename', 'rename_use_smart_string_cleanup', self.rename_use_smart_string_cleanup )
|
||||
self.config.set( 'rename', 'rename_extension_based_on_archive', self.rename_extension_based_on_archive )
|
||||
|
||||
if not self.config.has_section( 'autotag' ):
|
||||
self.config.add_section( 'autotag' )
|
||||
self.config.set( 'autotag', 'save_on_low_confidence', self.save_on_low_confidence )
|
||||
self.config.set( 'autotag', 'dont_use_year_when_identifying', self.dont_use_year_when_identifying )
|
||||
self.config.set( 'autotag', 'assume_1_if_no_issue_num', self.assume_1_if_no_issue_num )
|
||||
self.config.set( 'autotag', 'ignore_leading_numbers_in_filename', self.ignore_leading_numbers_in_filename )
|
||||
self.config.set( 'autotag', 'remove_archive_after_successful_match', self.remove_archive_after_successful_match )
|
||||
|
||||
with codecs.open( self.settings_file, 'wb', 'utf8') as configfile:
|
||||
self.config.write(configfile)
|
||||
|
@ -127,6 +127,10 @@ class SettingsWindow(QtGui.QDialog):
|
||||
|
||||
if self.settings.use_series_start_as_volume:
|
||||
self.cbxUseSeriesStartAsVolume.setCheckState( QtCore.Qt.Checked)
|
||||
if self.settings.clear_form_before_populating_from_cv:
|
||||
self.cbxClearFormBeforePopulating.setCheckState( QtCore.Qt.Checked)
|
||||
if self.settings.remove_html_tables:
|
||||
self.cbxRemoveHtmlTables.setCheckState( QtCore.Qt.Checked)
|
||||
|
||||
if self.settings.assume_lone_credit_is_primary:
|
||||
self.cbxAssumeLoneCreditIsPrimary.setCheckState( QtCore.Qt.Checked)
|
||||
@ -136,6 +140,8 @@ class SettingsWindow(QtGui.QDialog):
|
||||
self.cbxCopyTeamsToTags.setCheckState( QtCore.Qt.Checked)
|
||||
if self.settings.copy_locations_to_tags:
|
||||
self.cbxCopyLocationsToTags.setCheckState( QtCore.Qt.Checked)
|
||||
if self.settings.copy_storyarcs_to_tags:
|
||||
self.cbxCopyStoryArcsToTags.setCheckState( QtCore.Qt.Checked)
|
||||
if self.settings.copy_notes_to_comments:
|
||||
self.cbxCopyNotesToComments.setCheckState( QtCore.Qt.Checked)
|
||||
if self.settings.copy_weblink_to_comments:
|
||||
@ -177,11 +183,14 @@ class SettingsWindow(QtGui.QDialog):
|
||||
self.settings.parse_scan_info = self.cbxParseScanInfo.isChecked()
|
||||
|
||||
self.settings.use_series_start_as_volume = self.cbxUseSeriesStartAsVolume.isChecked()
|
||||
self.settings.clear_form_before_populating_from_cv = self.cbxClearFormBeforePopulating.isChecked()
|
||||
self.settings.remove_html_tables = self.cbxRemoveHtmlTables.isChecked()
|
||||
|
||||
self.settings.assume_lone_credit_is_primary = self.cbxAssumeLoneCreditIsPrimary.isChecked()
|
||||
self.settings.copy_characters_to_tags = self.cbxCopyCharactersToTags.isChecked()
|
||||
self.settings.copy_teams_to_tags = self.cbxCopyTeamsToTags.isChecked()
|
||||
self.settings.copy_locations_to_tags = self.cbxCopyLocationsToTags.isChecked()
|
||||
self.settings.copy_storyarcs_to_tags = self.cbxCopyStoryArcsToTags.isChecked()
|
||||
self.settings.copy_notes_to_comments = self.cbxCopyNotesToComments.isChecked()
|
||||
self.settings.copy_weblink_to_comments = self.cbxCopyWebLinkToComments.isChecked()
|
||||
self.settings.apply_cbl_transform_on_cv_import = self.cbxApplyCBLTransformOnCVIMport.isChecked()
|
||||
|
@ -21,7 +21,9 @@ limitations under the License.
|
||||
|
||||
from PyQt4 import QtCore, QtGui, uic
|
||||
from PyQt4.QtCore import QUrl,pyqtSignal
|
||||
from PyQt4 import QtNetwork
|
||||
|
||||
import sys
|
||||
import signal
|
||||
import locale
|
||||
import platform
|
||||
@ -30,6 +32,7 @@ import pprint
|
||||
import json
|
||||
import webbrowser
|
||||
import re
|
||||
import pickle
|
||||
|
||||
from volumeselectionwindow import VolumeSelectionWindow
|
||||
from comicarchive import MetaDataStyle
|
||||
@ -79,12 +82,43 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
appName = "ComicTagger"
|
||||
version = ctversion.version
|
||||
|
||||
def __init__(self, file_list, settings, parent = None):
|
||||
def __init__(self, file_list, settings, parent = None, opts=None):
|
||||
super(TaggerWindow, self).__init__(parent)
|
||||
|
||||
uic.loadUi(ComicTaggerSettings.getUIFile('taggerwindow.ui' ), self)
|
||||
self.settings = settings
|
||||
|
||||
#----------------------------------
|
||||
# prevent multiple instances
|
||||
socket = QtNetwork.QLocalSocket(self)
|
||||
socket.connectToServer(settings.install_id)
|
||||
alive = socket.waitForConnected(3000)
|
||||
if alive:
|
||||
print "Another application with key [{}] is already running".format( settings.install_id)
|
||||
# send file list to other instance
|
||||
if len(file_list) > 0:
|
||||
socket.write(pickle.dumps(file_list))
|
||||
if not socket.waitForBytesWritten(3000):
|
||||
print socket.errorString().toLatin1()
|
||||
socket.disconnectFromServer()
|
||||
sys.exit()
|
||||
else:
|
||||
# listen on a socket to prevent multiple instances
|
||||
self.socketServer = QtNetwork.QLocalServer(self)
|
||||
self.socketServer.newConnection.connect(self.onIncomingSocketConnection)
|
||||
ok = self.socketServer.listen(settings.install_id)
|
||||
if not ok:
|
||||
if self.socketServer.serverError() == QtNetwork.QAbstractSocket.AddressInUseError:
|
||||
#print "Resetting unresponsive socket with key [{}]".format(settings.install_id)
|
||||
self.socketServer.removeServer(settings.install_id)
|
||||
ok = self.socketServer.listen(settings.install_id)
|
||||
if not ok:
|
||||
print "Cannot start local socket with key [{}]. Reason: %s ".format(settings.install_id, self.socketServer.errorString())
|
||||
sys.exit()
|
||||
#print "Registering as single instance with key [{}]".format(settings.install_id)
|
||||
#----------------------------------
|
||||
|
||||
|
||||
self.archiveCoverWidget = CoverImageWidget( self.coverImageContainer, CoverImageWidget.ArchiveMode )
|
||||
gridlayout = QtGui.QGridLayout( self.coverImageContainer )
|
||||
gridlayout.addWidget( self.archiveCoverWidget )
|
||||
@ -119,6 +153,11 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
|
||||
self.setWindowIcon(QtGui.QIcon( ComicTaggerSettings.getGraphic('app.png')))
|
||||
|
||||
if opts is not None and opts.data_style is not None and opts.data_style != MetaDataStyle.COMET:
|
||||
#respect the command line option tag type
|
||||
settings.last_selected_save_data_style = opts.data_style
|
||||
settings.last_selected_load_data_style = opts.data_style
|
||||
|
||||
self.save_data_style = settings.last_selected_save_data_style
|
||||
self.load_data_style = settings.last_selected_load_data_style
|
||||
|
||||
@ -477,7 +516,7 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
+ "<a href='{0}'>{0}</a><br><br>".format(website)
|
||||
+ "<a href='mailto:{0}'>{0}</a><br><br>".format(email)
|
||||
+ "License: <a href='{0}'>{1}</a>".format(license_link, license_name) )
|
||||
|
||||
|
||||
msgBox.setStandardButtons( QtGui.QMessageBox.Ok )
|
||||
msgBox.exec_()
|
||||
|
||||
@ -503,7 +542,7 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
|
||||
def actualLoadCurrentArchive( self ):
|
||||
if self.metadata.isEmpty:
|
||||
self.metadata = self.comic_archive.metadataFromFilename( )
|
||||
self.metadata = self.comic_archive.metadataFromFilename( self.settings.parse_scan_info)
|
||||
if len(self.metadata.pages) == 0:
|
||||
self.metadata.setDefaultPageList( self.comic_archive.getNumberOfPages() )
|
||||
|
||||
@ -869,7 +908,7 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
if self.comic_archive is not None:
|
||||
#copy the form onto metadata object
|
||||
self.formToMetadata()
|
||||
new_metadata = self.comic_archive.metadataFromFilename( )
|
||||
new_metadata = self.comic_archive.metadataFromFilename(self.settings.parse_scan_info)
|
||||
if new_metadata is not None:
|
||||
self.metadata.overlay( new_metadata )
|
||||
self.metadataToForm()
|
||||
@ -964,6 +1003,9 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
|
||||
if self.settings.apply_cbl_transform_on_cv_import:
|
||||
new_metadata = CBLTransformer( new_metadata, self.settings ).apply()
|
||||
|
||||
if self.settings.clear_form_before_populating_from_cv:
|
||||
self.clearForm()
|
||||
|
||||
self.metadata.overlay( new_metadata )
|
||||
# Now push the new combined data into the edit controls
|
||||
@ -1540,7 +1582,7 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
# read in metadata, and parse file name if not there
|
||||
md = ca.readMetadata( self.save_data_style )
|
||||
if md.isEmpty:
|
||||
md = ca.metadataFromFilename()
|
||||
md = ca.metadataFromFilename(self.settings.parse_scan_info)
|
||||
if dlg.ignoreLeadingDigitsInFilename and md.series is not None:
|
||||
#remove all leading numbers
|
||||
md.series = re.sub( "([\d.]*)(.*)", "\\2", md.series)
|
||||
@ -1875,4 +1917,53 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
"Don't tell me about this version again")
|
||||
if checked:
|
||||
self.settings.dont_notify_about_this_version = new_version
|
||||
|
||||
|
||||
def onIncomingSocketConnection(self):
|
||||
# accept connection from other instance.
|
||||
# read in the file list if they're giving it,
|
||||
# and add to our own list
|
||||
localSocket = self.socketServer.nextPendingConnection()
|
||||
if localSocket.waitForReadyRead(3000):
|
||||
byteArray = localSocket.readAll()
|
||||
if len(byteArray) > 0:
|
||||
obj = pickle.loads(byteArray)
|
||||
localSocket.disconnectFromServer()
|
||||
if type(obj) is list:
|
||||
self.fileSelectionList.addPathList( obj )
|
||||
else:
|
||||
#print localSocket.errorString().toLatin1()
|
||||
pass
|
||||
|
||||
self.bringToTop()
|
||||
|
||||
def bringToTop(self):
|
||||
if platform.system() == "Windows":
|
||||
self.showNormal()
|
||||
self.raise_()
|
||||
self.activateWindow()
|
||||
try:
|
||||
import win32con
|
||||
import win32gui
|
||||
hwnd = self.effectiveWinId()
|
||||
rect = win32gui.GetWindowRect(hwnd)
|
||||
x = rect[0]
|
||||
y = rect[1]
|
||||
w = rect[2] - x
|
||||
h = rect[3] - y
|
||||
# mark it "always on top", just for a moment, to force it to the top
|
||||
win32gui.SetWindowPos(hwnd,win32con.HWND_TOPMOST, x, y, w, h, 0)
|
||||
win32gui.SetWindowPos(hwnd,win32con.HWND_NOTOPMOST, x, y, w, h, 0)
|
||||
except Exception as e:
|
||||
print "Whoops", e
|
||||
elif platform.system() == "Darwin":
|
||||
self.raise_()
|
||||
self.showNormal()
|
||||
self.activateWindow()
|
||||
else:
|
||||
flags = self.windowFlags()
|
||||
self.setWindowFlags( flags | QtCore.Qt.WindowStaysOnTopHint | QtCore.Qt.X11BypassWindowManagerHint)
|
||||
QtCore.QCoreApplication.processEvents()
|
||||
#self.show()
|
||||
self.setWindowFlags( flags )
|
||||
self.show()
|
||||
|
@ -341,7 +341,7 @@
|
||||
<rect>
|
||||
<x>30</x>
|
||||
<y>30</y>
|
||||
<width>240</width>
|
||||
<width>251</width>
|
||||
<height>25</height>
|
||||
</rect>
|
||||
</property>
|
||||
@ -349,6 +349,32 @@
|
||||
<string>Use Series Start Date as Volume</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="cbxClearFormBeforePopulating">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>30</x>
|
||||
<y>50</y>
|
||||
<width>341</width>
|
||||
<height>25</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clear Form Before Importing Comic Vine data</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="cbxRemoveHtmlTables">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>30</x>
|
||||
<y>70</y>
|
||||
<width>351</width>
|
||||
<height>25</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Remove HTML tables from CV summary field</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_4">
|
||||
<attribute name="title">
|
||||
@ -385,11 +411,18 @@
|
||||
<rect>
|
||||
<x>11</x>
|
||||
<y>21</y>
|
||||
<width>246</width>
|
||||
<height>182</height>
|
||||
<width>251</width>
|
||||
<height>192</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_7">
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="cbxCopyLocationsToTags">
|
||||
<property name="text">
|
||||
<string>Copy Locations to Generic Tags</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="cbxAssumeLoneCreditIsPrimary">
|
||||
<property name="text">
|
||||
@ -411,27 +444,27 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="cbxCopyLocationsToTags">
|
||||
<property name="text">
|
||||
<string>Copy Locations to Generic Tags</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="cbxCopyNotesToComments">
|
||||
<property name="text">
|
||||
<string>Copy Notes to Comments</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="6" column="0">
|
||||
<widget class="QCheckBox" name="cbxCopyWebLinkToComments">
|
||||
<property name="text">
|
||||
<string>Copy Web Link to Comments</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="cbxCopyStoryArcsToTags">
|
||||
<property name="text">
|
||||
<string>Copy Story Arcs to Generic Tags</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
|
@ -1,191 +1,209 @@
|
||||
---------------------------------
|
||||
1.1.12-beta - 23-Mar-2014
|
||||
---------------------------------
|
||||
* Fixed noisy version update error
|
||||
|
||||
---------------------------------
|
||||
1.1.11-beta - 23-Mar-2014
|
||||
---------------------------------
|
||||
* Updated unrar library to hand Rar tools 5.0 and greater
|
||||
* Other misc bug fixes
|
||||
|
||||
---------------------------------
|
||||
1.1.10-beta - 30-Jan-2014
|
||||
---------------------------------
|
||||
* Updated series query to match changes on Comic Vine side
|
||||
* Added a message when not able to open a file or folder
|
||||
* Fixed an issue where series names with periods would fail on search
|
||||
* Other misc bug fixes
|
||||
|
||||
---------------------------------
|
||||
1.1.9-beta - 8-May-2013
|
||||
---------------------------------
|
||||
* Filename parser and identification enhancements
|
||||
* Misc bug fixes
|
||||
|
||||
---------------------------------
|
||||
1.1.8-beta - 21-Apr-2013
|
||||
---------------------------------
|
||||
* Handle occasional error 500 from Comic Vine by retrying a few times
|
||||
* Nicer handling of colon (":") in file rename
|
||||
* Fixed command-line option parsing issue for add-on scripts
|
||||
* Misc bug fixes
|
||||
|
||||
---------------------------------
|
||||
1.1.7-beta - 12-Apr-2013
|
||||
---------------------------------
|
||||
* Added description and cover date to issue selection dialogs
|
||||
* Added notification of new version
|
||||
* Added setting to attempt to parse scan info from file name
|
||||
* Last sorted column in the file list is now remembered
|
||||
* Added CLI option ('-1') to assume issue #1 if not found/parsed
|
||||
* Misc bug fixes
|
||||
|
||||
---------------------------------
|
||||
1.1.6-beta - 3-Apr-2013
|
||||
---------------------------------
|
||||
* More ComicVine API-related fixes
|
||||
* More efficient automated search using new CV API issue filters
|
||||
---------------------------------
|
||||
1.1.14-beta - 13-Apr-2014
|
||||
---------------------------------
|
||||
* Make sure app gets raised when enforcing single instance
|
||||
* Added warning dialog for when opening rar files, and no (un)rar tool
|
||||
* remove pil from python package requirements
|
||||
|
||||
---------------------------------
|
||||
1.1.13-beta - 9-Apr-2014
|
||||
---------------------------------
|
||||
* Handle non-ascii usernames properly
|
||||
* better parsing of html table in summary text, and optional removal
|
||||
* Python package should auto-install requirements
|
||||
* Specify default GUI tag style on command-line
|
||||
* enforce single GUI instance
|
||||
* new CBL tranform to copy story arcs to generic tags
|
||||
* Persist some auto-tag settings
|
||||
|
||||
---------------------------------
|
||||
1.1.12-beta - 23-Mar-2014
|
||||
---------------------------------
|
||||
* Fixed noisy version update error
|
||||
|
||||
---------------------------------
|
||||
1.1.11-beta - 23-Mar-2014
|
||||
---------------------------------
|
||||
* Updated unrar library to hand Rar tools 5.0 and greater
|
||||
* Other misc bug fixes
|
||||
|
||||
---------------------------------
|
||||
1.1.10-beta - 30-Jan-2014
|
||||
---------------------------------
|
||||
* Updated series query to match changes on Comic Vine side
|
||||
* Added a message when not able to open a file or folder
|
||||
* Fixed an issue where series names with periods would fail on search
|
||||
* Other misc bug fixes
|
||||
|
||||
---------------------------------
|
||||
1.1.9-beta - 8-May-2013
|
||||
---------------------------------
|
||||
* Filename parser and identification enhancements
|
||||
* Misc bug fixes
|
||||
|
||||
---------------------------------
|
||||
1.1.8-beta - 21-Apr-2013
|
||||
---------------------------------
|
||||
* Handle occasional error 500 from Comic Vine by retrying a few times
|
||||
* Nicer handling of colon (":") in file rename
|
||||
* Fixed command-line option parsing issue for add-on scripts
|
||||
* Misc bug fixes
|
||||
|
||||
---------------------------------
|
||||
1.1.7-beta - 12-Apr-2013
|
||||
---------------------------------
|
||||
* Added description and cover date to issue selection dialogs
|
||||
* Added notification of new version
|
||||
* Added setting to attempt to parse scan info from file name
|
||||
* Last sorted column in the file list is now remembered
|
||||
* Added CLI option ('-1') to assume issue #1 if not found/parsed
|
||||
* Misc bug fixes
|
||||
|
||||
---------------------------------
|
||||
1.1.6-beta - 3-Apr-2013
|
||||
---------------------------------
|
||||
* More ComicVine API-related fixes
|
||||
* More efficient automated search using new CV API issue filters
|
||||
* Minor bug fixes
|
||||
|
||||
---------------------------------
|
||||
1.1.5-beta - 30-Mar-2013
|
||||
---------------------------------
|
||||
* More updates for handling changes to ComicVine API and result sets
|
||||
* Even better handling of non-numeric issue "numbers" ("½", "X")
|
||||
|
||||
---------------------------------
|
||||
1.1.4-beta - 27-Mar-2013
|
||||
---------------------------------
|
||||
* Updated to match the changes to the ComicVine API and result sets
|
||||
* Better handling of weird issue numbers ("0.1", "6au")
|
||||
|
||||
---------------------------------
|
||||
1.1.3-beta - 25-Feb-2013
|
||||
---------------------------------
|
||||
Bug Fixes:
|
||||
* Fixed a bug when renaming on non-English systems
|
||||
* Fixed issue when saving settings on non-English systems
|
||||
* Fixed a bug when comic contains non-RGB images
|
||||
* Fixed a rare crash when comic image is not-RGB format
|
||||
* Fixed sequence order of ComicInfo.xml items
|
||||
|
||||
Note:
|
||||
New requirement for users of the python package: "configparser"
|
||||
|
||||
---------------------------------
|
||||
1.1.2-beta - 14-Feb-2013
|
||||
---------------------------------
|
||||
Changes:
|
||||
* Source is now packaged using Python distutils
|
||||
* Recursive mode for CLI
|
||||
* Run custom add-on scripts from CLI
|
||||
* Minor UI tweaks
|
||||
* Misc bug fixes
|
||||
|
||||
---------------------------------
|
||||
1.1.0-beta - 06-Feb-2013
|
||||
---------------------------------
|
||||
Changes:
|
||||
* Enhanced identification process to use alternative covers from ComicVine
|
||||
* Post auto-tag manual matching now includes single low-confidence matches (CLI & GUI)
|
||||
* Page and cover view mini-browser available throughout app. Most images can be
|
||||
double-clicked for embiggened view
|
||||
* Export-to-zip in CLI (very handy in scripts!)
|
||||
* More rename template variables
|
||||
* Misc GUI & CLI Tweaks
|
||||
|
||||
---------------------------------
|
||||
1.0.3-beta - 31-Jan-2013
|
||||
---------------------------------
|
||||
Changes:
|
||||
Misc bug fixes and enhancements
|
||||
|
||||
---------------------------------
|
||||
1.0.2-beta - 25-Jan-2013
|
||||
---------------------------------
|
||||
Changes:
|
||||
More verbose logging during auto-tag
|
||||
Added %month% and %month_name% for renaming
|
||||
Better parsing of volume numbers in file name
|
||||
Bugs:
|
||||
Better exception handling with corrupted image data
|
||||
Fixed issues with RAR reading on OS X
|
||||
Other minor bug fixes
|
||||
|
||||
---------------------------------
|
||||
1.0.1-beta - 24-Jan-2013
|
||||
---------------------------------
|
||||
Bug Fix:
|
||||
Fixed an issue where unicode strings can't be printed to OS X Console
|
||||
|
||||
---------------------------------
|
||||
1.0.0-beta - 23-Jan-2013
|
||||
---------------------------------
|
||||
Version 1! New multi-file processing in GUI!
|
||||
|
||||
GUI Changes:
|
||||
Open multiple files and/or folders via drag/drop or file dialog
|
||||
File management list for easy viewing and selection
|
||||
Batch tag remove
|
||||
Batch export as zip
|
||||
Batch rename
|
||||
Batch tag copy
|
||||
Batch auto-tag (automatic identification and save!)
|
||||
|
||||
---------------------------------
|
||||
0.9.5-beta - 16-Jan-2013
|
||||
---------------------------------
|
||||
Changes:
|
||||
Added CLI option to search by comicvine issue ID
|
||||
Some image loading optimizations
|
||||
Bug Fix: Some CBL fields that should have been ints were written as strings
|
||||
|
||||
---------------------------------
|
||||
0.9.4-beta - 7-Jan-2013
|
||||
---------------------------------
|
||||
Changes:
|
||||
Better handling of non-ascii characters in filenames and data
|
||||
Add CBL Transform to copy Web Link and Notes to comments
|
||||
Minor bug fixes
|
||||
|
||||
---------------------------------
|
||||
0.9.3-beta - 19-Dec-2012
|
||||
---------------------------------
|
||||
Changes:
|
||||
File rename in GUI
|
||||
Setting for file rename
|
||||
Option to use series start year as volume
|
||||
Added "CBL Transform" to handle primary credits copying data into the generic tags field
|
||||
Bug Fix: unicode characters in credits caused crash
|
||||
Bug Fix: bad or non-image data in file caused crash
|
||||
|
||||
Note:
|
||||
The user should clear the cache and delete the existing settings when first running this version.
|
||||
|
||||
---------------------------------
|
||||
0.9.2-beta - 13-Dec-2012
|
||||
---------------------------------
|
||||
Page List/Type editing in GUI
|
||||
File globbing for windows CLI (i.e. use of wildcards like '*.cbz')
|
||||
Fixed RAR writing bug on windows
|
||||
Minor bug and crash fixes
|
||||
|
||||
---------------------------------
|
||||
0.9.1-beta - 07-Dec-2012
|
||||
---------------------------------
|
||||
Export as ZIP Archive
|
||||
Added help menu option for websites
|
||||
Added Primary Credit Flag editing
|
||||
Menu enhancements
|
||||
CLI Enhancements:
|
||||
Interactive selection of matches
|
||||
Tag copy
|
||||
Better output
|
||||
CoMet support
|
||||
Minor bug and crash fixes
|
||||
|
||||
---------------------------------
|
||||
0.9.0-beta - 30-Nov-2012
|
||||
---------------------------------
|
||||
Initial beta release
|
||||
|
||||
---------------------------------
|
||||
1.1.5-beta - 30-Mar-2013
|
||||
---------------------------------
|
||||
* More updates for handling changes to ComicVine API and result sets
|
||||
* Even better handling of non-numeric issue "numbers" ("½", "X")
|
||||
|
||||
---------------------------------
|
||||
1.1.4-beta - 27-Mar-2013
|
||||
---------------------------------
|
||||
* Updated to match the changes to the ComicVine API and result sets
|
||||
* Better handling of weird issue numbers ("0.1", "6au")
|
||||
|
||||
---------------------------------
|
||||
1.1.3-beta - 25-Feb-2013
|
||||
---------------------------------
|
||||
Bug Fixes:
|
||||
* Fixed a bug when renaming on non-English systems
|
||||
* Fixed issue when saving settings on non-English systems
|
||||
* Fixed a bug when comic contains non-RGB images
|
||||
* Fixed a rare crash when comic image is not-RGB format
|
||||
* Fixed sequence order of ComicInfo.xml items
|
||||
|
||||
Note:
|
||||
New requirement for users of the python package: "configparser"
|
||||
|
||||
---------------------------------
|
||||
1.1.2-beta - 14-Feb-2013
|
||||
---------------------------------
|
||||
Changes:
|
||||
* Source is now packaged using Python distutils
|
||||
* Recursive mode for CLI
|
||||
* Run custom add-on scripts from CLI
|
||||
* Minor UI tweaks
|
||||
* Misc bug fixes
|
||||
|
||||
---------------------------------
|
||||
1.1.0-beta - 06-Feb-2013
|
||||
---------------------------------
|
||||
Changes:
|
||||
* Enhanced identification process to use alternative covers from ComicVine
|
||||
* Post auto-tag manual matching now includes single low-confidence matches (CLI & GUI)
|
||||
* Page and cover view mini-browser available throughout app. Most images can be
|
||||
double-clicked for embiggened view
|
||||
* Export-to-zip in CLI (very handy in scripts!)
|
||||
* More rename template variables
|
||||
* Misc GUI & CLI Tweaks
|
||||
|
||||
---------------------------------
|
||||
1.0.3-beta - 31-Jan-2013
|
||||
---------------------------------
|
||||
Changes:
|
||||
Misc bug fixes and enhancements
|
||||
|
||||
---------------------------------
|
||||
1.0.2-beta - 25-Jan-2013
|
||||
---------------------------------
|
||||
Changes:
|
||||
More verbose logging during auto-tag
|
||||
Added %month% and %month_name% for renaming
|
||||
Better parsing of volume numbers in file name
|
||||
Bugs:
|
||||
Better exception handling with corrupted image data
|
||||
Fixed issues with RAR reading on OS X
|
||||
Other minor bug fixes
|
||||
|
||||
---------------------------------
|
||||
1.0.1-beta - 24-Jan-2013
|
||||
---------------------------------
|
||||
Bug Fix:
|
||||
Fixed an issue where unicode strings can't be printed to OS X Console
|
||||
|
||||
---------------------------------
|
||||
1.0.0-beta - 23-Jan-2013
|
||||
---------------------------------
|
||||
Version 1! New multi-file processing in GUI!
|
||||
|
||||
GUI Changes:
|
||||
Open multiple files and/or folders via drag/drop or file dialog
|
||||
File management list for easy viewing and selection
|
||||
Batch tag remove
|
||||
Batch export as zip
|
||||
Batch rename
|
||||
Batch tag copy
|
||||
Batch auto-tag (automatic identification and save!)
|
||||
|
||||
---------------------------------
|
||||
0.9.5-beta - 16-Jan-2013
|
||||
---------------------------------
|
||||
Changes:
|
||||
Added CLI option to search by comicvine issue ID
|
||||
Some image loading optimizations
|
||||
Bug Fix: Some CBL fields that should have been ints were written as strings
|
||||
|
||||
---------------------------------
|
||||
0.9.4-beta - 7-Jan-2013
|
||||
---------------------------------
|
||||
Changes:
|
||||
Better handling of non-ascii characters in filenames and data
|
||||
Add CBL Transform to copy Web Link and Notes to comments
|
||||
Minor bug fixes
|
||||
|
||||
---------------------------------
|
||||
0.9.3-beta - 19-Dec-2012
|
||||
---------------------------------
|
||||
Changes:
|
||||
File rename in GUI
|
||||
Setting for file rename
|
||||
Option to use series start year as volume
|
||||
Added "CBL Transform" to handle primary credits copying data into the generic tags field
|
||||
Bug Fix: unicode characters in credits caused crash
|
||||
Bug Fix: bad or non-image data in file caused crash
|
||||
|
||||
Note:
|
||||
The user should clear the cache and delete the existing settings when first running this version.
|
||||
|
||||
---------------------------------
|
||||
0.9.2-beta - 13-Dec-2012
|
||||
---------------------------------
|
||||
Page List/Type editing in GUI
|
||||
File globbing for windows CLI (i.e. use of wildcards like '*.cbz')
|
||||
Fixed RAR writing bug on windows
|
||||
Minor bug and crash fixes
|
||||
|
||||
---------------------------------
|
||||
0.9.1-beta - 07-Dec-2012
|
||||
---------------------------------
|
||||
Export as ZIP Archive
|
||||
Added help menu option for websites
|
||||
Added Primary Credit Flag editing
|
||||
Menu enhancements
|
||||
CLI Enhancements:
|
||||
Interactive selection of matches
|
||||
Tag copy
|
||||
Better output
|
||||
CoMet support
|
||||
Minor bug and crash fixes
|
||||
|
||||
---------------------------------
|
||||
0.9.0-beta - 30-Nov-2012
|
||||
---------------------------------
|
||||
Initial beta release
|
||||
|
@ -1,3 +1,2 @@
|
||||
configparser
|
||||
beautifulsoup4 >= 4.1
|
||||
PIL >= 1.1.6
|
||||
|
@ -28,7 +28,7 @@ def main():
|
||||
comic_list = []
|
||||
max_name_len = 2
|
||||
for filename in filelist:
|
||||
ca = ComicArchive(filename, settings )
|
||||
ca = ComicArchive(filename, settings.rar_exe_path )
|
||||
if ca.seemsToBeAComicArchive() and ca.hasMetadata( style ):
|
||||
max_name_len = max ( max_name_len, len(filename))
|
||||
fmt_str = u"{{0:{0}}}".format(max_name_len)
|
||||
@ -74,7 +74,7 @@ def main():
|
||||
print "Found {0} duplicate sets".format( len(dupe_set_list))
|
||||
|
||||
for dupe_set in dupe_set_list:
|
||||
ca = ComicArchive(dupe_set[0], settings )
|
||||
ca = ComicArchive(dupe_set[0], settings.rar_exe_path )
|
||||
md = ca.readMetadata( style )
|
||||
print "{0} #{1} ({2})".format( md.series, md.issue, md.year )
|
||||
for filename in dupe_set:
|
||||
|
@ -43,7 +43,7 @@ def main():
|
||||
metadata_list = []
|
||||
max_name_len = 2
|
||||
for filename in filelist:
|
||||
ca = ComicArchive(filename, settings )
|
||||
ca = ComicArchive(filename, settings.rar_exe_path )
|
||||
if ca.hasMetadata( style ):
|
||||
#make a list of paired filenames and metadata objects
|
||||
metadata_list.append((filename, ca.readMetadata( style )))
|
||||
|
@ -66,7 +66,7 @@ def main():
|
||||
comic_list = []
|
||||
max_name_len = 2
|
||||
for filename in filelist:
|
||||
ca = ComicArchive(filename, settings )
|
||||
ca = ComicArchive(filename, settings.rar_exe_path )
|
||||
if ca.seemsToBeAComicArchive() and ca.hasMetadata( style ):
|
||||
|
||||
comic_list.append((filename, ca.readMetadata( style )))
|
||||
|
@ -99,7 +99,7 @@ def main():
|
||||
max_name_len = 2
|
||||
fmt_str = ""
|
||||
for filename in filelist:
|
||||
ca = ComicArchive(filename, settings )
|
||||
ca = ComicArchive(filename, settings.rar_exe_path )
|
||||
# do we care if it already has metadata?
|
||||
if ca.seemsToBeAComicArchive() and not ca.hasMetadata( style ):
|
||||
|
||||
|
@ -51,7 +51,7 @@ def main():
|
||||
modify_list = []
|
||||
for filename in filelist:
|
||||
|
||||
ca = ComicArchive(filename, settings )
|
||||
ca = ComicArchive(filename, settings.rar_exe_path )
|
||||
if (ca.isZip or ca.isRar()) and ca.hasMetadata( style ):
|
||||
md = ca.readMetadata( style )
|
||||
if len(md.pages) != 0:
|
||||
@ -63,7 +63,7 @@ def main():
|
||||
|
||||
#now actually process those files
|
||||
for filename,md in modify_list:
|
||||
ca = ComicArchive(filename, settings )
|
||||
ca = ComicArchive(filename, settings.rar_exe_path )
|
||||
curr_folder = os.path.dirname( filename )
|
||||
curr_subfolder = os.path.join( curr_folder, subfolder_name )
|
||||
|
||||
@ -140,7 +140,7 @@ def main():
|
||||
print "Done!".format(filename)
|
||||
|
||||
# Create a new archive object for the new file, and write the old CIX data, with new page info
|
||||
ca = ComicArchive( filename, settings )
|
||||
ca = ComicArchive( filename, settings.rar_exe_path )
|
||||
md.pages = new_pages
|
||||
ca.writeMetadata( style, md )
|
||||
|
||||
|
@ -52,7 +52,7 @@ def main():
|
||||
fmt_str = u"{{0:{0}}}".format(max_name_len)
|
||||
for filename in filelist:
|
||||
|
||||
ca = ComicArchive(filename, settings )
|
||||
ca = ComicArchive(filename, settings.rar_exe_path )
|
||||
if (ca.seemsToBeAComicArchive()):
|
||||
# Check the images in the file, see if we need to reduce any
|
||||
|
||||
@ -180,7 +180,7 @@ def main():
|
||||
|
||||
# Create a new archive object for the new file, and write the old CIX data, w/o page info
|
||||
if cix_md is not None:
|
||||
ca = ComicArchive( filename, settings )
|
||||
ca = ComicArchive( filename, settings.rar_exe_path )
|
||||
cix_md.pages = []
|
||||
ca.writeCIX( cix_md )
|
||||
|
||||
|
@ -44,7 +44,7 @@ def main():
|
||||
print >> sys.stderr, filename + ": not found!"
|
||||
return
|
||||
|
||||
ca = ComicArchive(filename, settings )
|
||||
ca = ComicArchive(filename, settings.rar_exe_path )
|
||||
if not ca.seemsToBeAComicArchive():
|
||||
print >> sys.stderr, "Sorry, but "+ filename + " is not a comic archive!"
|
||||
return
|
||||
|
13
setup.py
13
setup.py
@ -1,16 +1,19 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
from distutils.core import setup
|
||||
from setuptools import setup
|
||||
import comictaggerlib.ctversion
|
||||
|
||||
with open('requirements.txt') as f:
|
||||
required = f.read().splitlines()
|
||||
|
||||
setup(name = "comictagger",
|
||||
install_requires=required,
|
||||
version = comictaggerlib.ctversion.version,
|
||||
description = "A cross-platform GUI/CLI app for writing metadata to comic archives",
|
||||
author = "Anthony Beville",
|
||||
author_email = "comictagger@gmail.com",
|
||||
url = "http://code.google.com/p/comictagger/",
|
||||
#download_url = "http://comictagger.googlecode.com/files/comictagger-{0}.zip".format(comictaggerlib.ctversion.version),
|
||||
download_url = "https://drive.google.com/uc?export=download&id=0Bw4IursaqWhhTjZ6UDB1aEx1am8",
|
||||
download_url = "https://pypi.python.org/packages/source/c/comictagger/comictagger-{0}.zip".format(comictaggerlib.ctversion.version),
|
||||
packages = [ "comictaggerlib", "comictaggerlib/UnRAR2" ] ,
|
||||
package_data = {
|
||||
'comictaggerlib': ['ui/*.ui', 'graphics/*'] ,
|
||||
@ -37,7 +40,7 @@ setup(name = "comictagger",
|
||||
license = "Apache License 2.0",
|
||||
|
||||
long_description = """
|
||||
ComicTagger is a multi-platform app for writing metadata to comic archives, written in Python and PyQt.
|
||||
ComicTagger is a multi-platform app for writing metadata to digital comics, written in Python and PyQt.
|
||||
|
||||
Features:
|
||||
|
||||
@ -52,7 +55,7 @@ Features:
|
||||
Requires:
|
||||
|
||||
* python 2.6 or 2.7
|
||||
* configparser
|
||||
* configparser
|
||||
* python imaging (PIL) >= 1.1.6
|
||||
* beautifulsoup > 4.1
|
||||
|
||||
|
11
todo.txt
11
todo.txt
@ -1,3 +1,7 @@
|
||||
TOP!:
|
||||
Does utils.get_actual_preferred_encoding() work on Mac python source version??
|
||||
(And does it matter?)
|
||||
|
||||
-----------------------------------------------------
|
||||
Features
|
||||
-----------------------------------------------------
|
||||
@ -11,12 +15,10 @@ Feature Requests:
|
||||
Move CBR to other folder after conversion to ZIP
|
||||
Pre-process series name before identification
|
||||
(using a list of regex transforms)
|
||||
(GC #28) Save auto-tag options
|
||||
(GC #24) Multiple options for -t i.e. "-t cr,cbl"
|
||||
(GC #18 ) Option for handling colon in rename
|
||||
(GC #31 ) Specify CV Series ID for auto-tag
|
||||
Re-org - move to new folder based on template
|
||||
repair incorrect extension
|
||||
|
||||
Denied Requests (for now):
|
||||
Auto-rename on auto-tag
|
||||
@ -89,9 +91,8 @@ Release Process
|
||||
Tag the repository
|
||||
Manually upload release packages to Google Drive
|
||||
Update the Downloads wiki page with direct links
|
||||
Edit setup.py to add direct link to zip
|
||||
"make upload"
|
||||
Announce on Forum and Main Page and Twitter
|
||||
"make upload" to the pypi site
|
||||
Announce on Forum and Main Page and Twitter and Facebook
|
||||
MacUpdate
|
||||
Update appspot value
|
||||
|
||||
|
Reference in New Issue
Block a user