Compare commits
30 Commits
1.1.6-beta
...
1.1.8-beta
Author | SHA1 | Date | |
---|---|---|---|
47d8da0e80 | |||
0f7e88e58c | |||
65902a15b1 | |||
a68b2babeb | |||
4098802e43 | |||
9c14258e9f | |||
33bdbe8be8 | |||
a76864c109 | |||
cb68d07751 | |||
8e9fccdbbc | |||
39990fc2b4 | |||
e8c315d834 | |||
f8a06a8746 | |||
9415087da7 | |||
9aee5c32eb | |||
fcdb4a3889 | |||
534a326258 | |||
0390ff5919 | |||
b800ae1751 | |||
a2c17982d3 | |||
0347befae6 | |||
af54b79790 | |||
dd04ae98a0 | |||
31b76fba92 | |||
9f4a4b0eb0 | |||
575a23c6bf | |||
5d84f09359 | |||
3072583482 | |||
8d867cf78a | |||
36c79b5a2a |
@ -38,7 +38,7 @@ class AutoTagMatchWindow(QtGui.QDialog):
|
||||
def __init__(self, parent, match_set_list, style, fetch_func):
|
||||
super(AutoTagMatchWindow, self).__init__(parent)
|
||||
|
||||
uic.loadUi(ComicTaggerSettings.getUIFile('autotagmatchwindow.ui' ), self)
|
||||
uic.loadUi(ComicTaggerSettings.getUIFile('matchselectionwindow.ui' ), self)
|
||||
|
||||
self.altCoverWidget = CoverImageWidget( self.altCoverContainer, CoverImageWidget.AltCoverMode )
|
||||
gridlayout = QtGui.QGridLayout( self.altCoverContainer )
|
||||
@ -51,6 +51,7 @@ class AutoTagMatchWindow(QtGui.QDialog):
|
||||
gridlayout.setContentsMargins(0,0,0,0)
|
||||
|
||||
utils.reduceWidgetFontSize( self.twList )
|
||||
utils.reduceWidgetFontSize( self.teDescription, 1 )
|
||||
|
||||
self.setWindowFlags(self.windowFlags() |
|
||||
QtCore.Qt.WindowSystemMenuHint |
|
||||
@ -161,6 +162,10 @@ class AutoTagMatchWindow(QtGui.QDialog):
|
||||
return
|
||||
|
||||
self.altCoverWidget.setIssueID( self.currentMatch()['issue_id'] )
|
||||
if self.currentMatch()['description'] is None:
|
||||
self.teDescription.setText ( "" )
|
||||
else:
|
||||
self.teDescription.setText ( self.currentMatch()['description'] )
|
||||
|
||||
def setCoverImage( self ):
|
||||
ca = self.current_match_set.ca
|
||||
|
@ -337,7 +337,10 @@ def process_file_cli( filename, opts, settings, match_results ):
|
||||
print u"Processing {0}...".format(filename)
|
||||
|
||||
md = create_local_metadata( opts, ca, has[ opts.data_style ] )
|
||||
|
||||
if md.issue is None or md.issue == "":
|
||||
if opts.assume_issue_is_one_if_not_set:
|
||||
md.issue = "1"
|
||||
|
||||
# now, search online
|
||||
if opts.search_online:
|
||||
if opts.issue_id is not None:
|
||||
|
@ -1027,6 +1027,9 @@ class ComicArchive:
|
||||
metadata.year = fnp.year
|
||||
if fnp.issue_count != "":
|
||||
metadata.issueCount = fnp.issue_count
|
||||
if self.settings.parse_scan_info:
|
||||
if fnp.remainder != "":
|
||||
metadata.scanInfo = fnp.remainder
|
||||
|
||||
metadata.isEmpty = False
|
||||
|
||||
|
@ -114,6 +114,7 @@ class ComicVineCacher:
|
||||
"thumb_url TEXT," +
|
||||
"cover_date TEXT," +
|
||||
"site_detail_url TEXT," +
|
||||
"description TEXT," +
|
||||
"timestamp DATE DEFAULT (datetime('now','localtime')), " +
|
||||
"PRIMARY KEY (id ) )"
|
||||
)
|
||||
@ -283,6 +284,7 @@ class ComicVineCacher:
|
||||
"cover_date": issue['cover_date'],
|
||||
"super_url": issue['image']['super_url'],
|
||||
"thumb_url": issue['image']['thumb_url'],
|
||||
"description": issue['description'],
|
||||
"timestamp": timestamp
|
||||
}
|
||||
self.upsert( cur, "issues" , "id", issue['id'], data)
|
||||
@ -338,7 +340,7 @@ class ComicVineCacher:
|
||||
# fetch
|
||||
results = list()
|
||||
|
||||
cur.execute("SELECT id,name,issue_number,site_detail_url,cover_date,super_url,thumb_url FROM Issues WHERE volume_id = ?", [ volume_id ] )
|
||||
cur.execute("SELECT id,name,issue_number,site_detail_url,cover_date,super_url,thumb_url,description FROM Issues WHERE volume_id = ?", [ volume_id ] )
|
||||
rows = cur.fetchall()
|
||||
|
||||
# now process the results
|
||||
@ -353,6 +355,7 @@ class ComicVineCacher:
|
||||
record['image'] = dict()
|
||||
record['image']['super_url'] = row[5]
|
||||
record['image']['thumb_url'] = row[6]
|
||||
record['description'] = row[7]
|
||||
|
||||
results.append(record)
|
||||
|
||||
|
@ -24,6 +24,7 @@ from pprint import pprint
|
||||
import urllib2, urllib
|
||||
import math
|
||||
import re
|
||||
import time
|
||||
import datetime
|
||||
import ctversion
|
||||
import sys
|
||||
@ -58,6 +59,8 @@ class ComicVineTalkerException(Exception):
|
||||
|
||||
class ComicVineTalker(QObject):
|
||||
|
||||
logo_url = "http://static.comicvine.com/bundles/comicvinesite/images/logo.png"
|
||||
|
||||
def __init__(self, api_key=""):
|
||||
QObject.__init__(self)
|
||||
|
||||
@ -104,12 +107,28 @@ class ComicVineTalker(QObject):
|
||||
return cv_response[ 'status_code' ] != 100
|
||||
|
||||
def getUrlContent( self, url ):
|
||||
try:
|
||||
resp = urllib2.urlopen( url )
|
||||
return resp.read()
|
||||
except Exception as e:
|
||||
self.writeLog( str(e) )
|
||||
raise ComicVineTalkerException("Network Error!")
|
||||
# connect to server:
|
||||
# if there is a 500 error, try a few more times before giving up
|
||||
# any other error, just bail
|
||||
|
||||
for tries in range(3):
|
||||
try:
|
||||
resp = urllib2.urlopen( url )
|
||||
return resp.read()
|
||||
except urllib2.HTTPError as e:
|
||||
if e.getcode() == 500:
|
||||
self.writeLog( "Try #{0}: ".format(tries+1) )
|
||||
time.sleep(1)
|
||||
self.writeLog( str(e) + "\n" )
|
||||
|
||||
if e.getcode() != 500:
|
||||
break
|
||||
|
||||
except Exception as e:
|
||||
self.writeLog( str(e) + "\n" )
|
||||
raise ComicVineTalkerException("Network Error!")
|
||||
|
||||
raise ComicVineTalkerException("Error on Comic Vine server")
|
||||
|
||||
def searchForSeries( self, series_name , callback=None, refresh_cache=False ):
|
||||
|
||||
@ -222,7 +241,7 @@ class ComicVineTalker(QObject):
|
||||
return cached_volume_issues_result
|
||||
|
||||
#---------------------------------
|
||||
issues_url = self.api_base_url + "/issues/" + "?api_key=" + self.api_key + "&filter=volume:" + str(series_id) + "&field_list=id,volume,issue_number,name,image,cover_date,site_detail_url&format=json"
|
||||
issues_url = self.api_base_url + "/issues/" + "?api_key=" + self.api_key + "&filter=volume:" + str(series_id) + "&field_list=id,volume,issue_number,name,image,cover_date,site_detail_url,description&format=json"
|
||||
content = self.getUrlContent(issues_url)
|
||||
cv_response = json.loads(content)
|
||||
|
||||
@ -236,14 +255,14 @@ class ComicVineTalker(QObject):
|
||||
total_result_count = cv_response['number_of_total_results']
|
||||
#print "ATB total_result_count", total_result_count
|
||||
|
||||
#print "ATB Found {0} of {1} results\n".format( cv_response['number_of_page_results'], cv_response['number_of_total_results'])
|
||||
#print "ATB Found {0} of {1} results".format( cv_response['number_of_page_results'], cv_response['number_of_total_results'])
|
||||
volume_issues_result = cv_response['results']
|
||||
page = 1
|
||||
offset = 0
|
||||
|
||||
# see if we need to keep asking for more pages...
|
||||
while ( current_result_count < total_result_count ):
|
||||
#print "ATB getting another page of issue results {0} of {1}...\n".format( current_result_count, total_result_count)
|
||||
#print "ATB getting another page of issue results {0} of {1}...".format( current_result_count, total_result_count)
|
||||
page += 1
|
||||
offset += cv_response['number_of_page_results']
|
||||
|
||||
@ -257,7 +276,8 @@ class ComicVineTalker(QObject):
|
||||
volume_issues_result.extend( cv_response['results'])
|
||||
current_result_count += cv_response['number_of_page_results']
|
||||
|
||||
|
||||
self.repairUrls( volume_issues_result )
|
||||
|
||||
cvc.add_volume_issues_info( series_id, volume_issues_result )
|
||||
|
||||
return volume_issues_result
|
||||
@ -276,7 +296,7 @@ class ComicVineTalker(QObject):
|
||||
|
||||
filter = "&filter=" + volume_filter + year_filter + ",issue_number:" + issue_number
|
||||
|
||||
issues_url = self.api_base_url + "/issues/" + "?api_key=" + self.api_key + filter + "&field_list=id,volume,issue_number,name,image,cover_date,site_detail_url&format=json"
|
||||
issues_url = self.api_base_url + "/issues/" + "?api_key=" + self.api_key + filter + "&field_list=id,volume,issue_number,name,image,cover_date,site_detail_url,description&format=json"
|
||||
|
||||
content = self.getUrlContent(issues_url)
|
||||
cv_response = json.loads(content)
|
||||
@ -312,6 +332,8 @@ class ComicVineTalker(QObject):
|
||||
filtered_issues_result.extend( cv_response['results'])
|
||||
current_result_count += cv_response['number_of_page_results']
|
||||
|
||||
self.repairUrls( filtered_issues_result )
|
||||
|
||||
return filtered_issues_result
|
||||
|
||||
|
||||
@ -624,3 +646,11 @@ class ComicVineTalker(QObject):
|
||||
|
||||
self.altUrlListFetchComplete.emit( alt_cover_url_list, int(self.issue_id) )
|
||||
|
||||
def repairUrls(self, issue_list):
|
||||
#make sure there are URLs for the image fields
|
||||
for issue in issue_list:
|
||||
if issue['image'] is None:
|
||||
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.6-beta"
|
||||
version="1.1.8-beta"
|
||||
|
@ -81,7 +81,7 @@ class FileNameParser:
|
||||
found = False
|
||||
issue = ''
|
||||
|
||||
# first, look for multiple "--", this mean's it's formatted differently from most:
|
||||
# first, look for multiple "--", this means it's formatted differently from most:
|
||||
if "--" in filename:
|
||||
# the pattern seems to be that anything to left of the first "--" is the series name followed by issue
|
||||
filename = filename.split("--")[0]
|
||||
@ -191,6 +191,28 @@ class FileNameParser:
|
||||
year = re.sub("[^0-9]", "", year)
|
||||
return year
|
||||
|
||||
def getRemainder( self, filename, year, count ):
|
||||
#make a guess at where the the non-interesting stuff begins
|
||||
|
||||
remainder = ""
|
||||
|
||||
if "--" in filename:
|
||||
remainder = filename.split("--",1)[1]
|
||||
elif "__" in filename:
|
||||
remainder = filename.split("__",1)[1]
|
||||
elif "(" in filename:
|
||||
remainder = "(" + filename.split("(",1)[1]
|
||||
|
||||
remainder = self.fixSpaces(remainder, remove_dashes=False)
|
||||
if year != "":
|
||||
remainder = remainder.replace(year,"",1)
|
||||
if count != "":
|
||||
remainder = remainder.replace("of "+count,"",1)
|
||||
|
||||
remainder = remainder.replace("()","")
|
||||
|
||||
return remainder.strip()
|
||||
|
||||
def parseFilename( self, filename ):
|
||||
|
||||
# remove the path
|
||||
@ -208,20 +230,12 @@ class FileNameParser:
|
||||
if filename.count("_28") > 1 and filename.count("_29") > 1:
|
||||
filename = filename.replace("_28", "(")
|
||||
filename = filename.replace("_29", ")")
|
||||
|
||||
# ----HACK
|
||||
# remove the first word that word is a 3 digit number.
|
||||
# some story arcs collection packs do this, but it's ugly
|
||||
# this will probably break something, i.e. "100 bullets"
|
||||
#word = filename.split(' ')[0]
|
||||
#if len(word) == 3 and word[0] =='0' and word.isdigit():
|
||||
# filename = filename[4:]
|
||||
# ----HACK -
|
||||
|
||||
self.issue = self.getIssueNumber(filename)
|
||||
self.series, self.volume = self.getSeriesName(filename, self.issue)
|
||||
self.year = self.getYear(filename)
|
||||
self.issue_count = self.getIssueCount(filename)
|
||||
self.remainder = self.getRemainder( filename, self.year, self.issue_count )
|
||||
|
||||
if self.issue != "":
|
||||
# strip off leading zeros
|
||||
|
@ -132,7 +132,9 @@ class FileRenamer:
|
||||
|
||||
# some tweaks to keep various filesystems happy
|
||||
new_name = new_name.replace("/", "-")
|
||||
new_name = new_name.replace(":", "-")
|
||||
new_name = new_name.replace(" :", " -")
|
||||
new_name = new_name.replace(": ", " - ")
|
||||
new_name = new_name.replace(":", "-")
|
||||
new_name = new_name.replace("?", "")
|
||||
|
||||
return new_name
|
||||
|
@ -98,6 +98,14 @@ class FileSelectionList(QWidget):
|
||||
self.addAction(removeAction)
|
||||
self.addAction(self.separator)
|
||||
|
||||
def getSorting(self):
|
||||
col = self.twList.horizontalHeader().sortIndicatorSection()
|
||||
order = self.twList.horizontalHeader().sortIndicatorOrder()
|
||||
return col, order
|
||||
|
||||
def setSorting(self, col, order):
|
||||
col = self.twList.horizontalHeader().setSortIndicator( col, order)
|
||||
|
||||
def addAppAction( self, action ):
|
||||
self.insertAction( None , action )
|
||||
|
||||
|
@ -348,6 +348,8 @@ class IssueIdentifier:
|
||||
#self.log_msg( "Cover hash = {0:016x}".format(cover_hash) )
|
||||
|
||||
keys = self.getSearchKeys()
|
||||
#normalize the issue number
|
||||
keys['issue_number'] = IssueString(keys['issue_number']).asString()
|
||||
|
||||
# we need, at minimum, a series and issue number
|
||||
if keys['series'] is None or keys['issue_number'] is None:
|
||||
@ -409,9 +411,9 @@ class IssueIdentifier:
|
||||
series_second_round_list.append(item)
|
||||
|
||||
# if we don't think it's an issue number 1, remove any series' that are one-shots
|
||||
if keys['issue_number'] not in [ '1', '0', '0.1' ]:
|
||||
#self.log_msg( "Removing one-shots" )
|
||||
series_second_round_list[:] = [x for x in series_second_round_list if not x['count_of_issues'] == 1]
|
||||
#if keys['issue_number'] not in [ '1', '0', '0.1' ]:
|
||||
# #self.log_msg( "Removing one-shots" )
|
||||
# series_second_round_list[:] = [x for x in series_second_round_list if not x['count_of_issues'] == 1]
|
||||
|
||||
self.log_msg( "Searching in " + str(len(series_second_round_list)) +" series" )
|
||||
|
||||
@ -538,6 +540,7 @@ class IssueIdentifier:
|
||||
match['image_url'] = image_url
|
||||
match['thumb_url'] = thumb_url
|
||||
match['page_url'] = page_url
|
||||
match['description'] = issue['description']
|
||||
|
||||
self.match_list.append(match)
|
||||
|
||||
|
@ -55,6 +55,7 @@ class IssueSelectionWindow(QtGui.QDialog):
|
||||
gridlayout.setContentsMargins(0,0,0,0)
|
||||
|
||||
utils.reduceWidgetFontSize( self.twList )
|
||||
utils.reduceWidgetFontSize( self.teDescription, 1 )
|
||||
|
||||
self.setWindowFlags(self.windowFlags() |
|
||||
QtCore.Qt.WindowSystemMenuHint |
|
||||
@ -116,14 +117,26 @@ class IssueSelectionWindow(QtGui.QDialog):
|
||||
item.setFlags(QtCore.Qt.ItemIsSelectable| QtCore.Qt.ItemIsEnabled)
|
||||
self.twList.setItem(row, 0, item)
|
||||
|
||||
item_text = record['name']
|
||||
item_text = record['cover_date']
|
||||
if item_text is None:
|
||||
item_text = ""
|
||||
#remove the day of "YYYY-MM-DD"
|
||||
parts = item_text.split("-")
|
||||
if len(parts) > 1:
|
||||
item_text = parts[0] + "-" + parts[1]
|
||||
|
||||
item = QtGui.QTableWidgetItem(item_text)
|
||||
item.setData( QtCore.Qt.ToolTipRole, item_text )
|
||||
item.setFlags(QtCore.Qt.ItemIsSelectable| QtCore.Qt.ItemIsEnabled)
|
||||
self.twList.setItem(row, 1, item)
|
||||
|
||||
item_text = record['name']
|
||||
if item_text is None:
|
||||
item_text = ""
|
||||
item = QtGui.QTableWidgetItem(item_text)
|
||||
item.setData( QtCore.Qt.ToolTipRole, item_text )
|
||||
item.setFlags(QtCore.Qt.ItemIsSelectable| QtCore.Qt.ItemIsEnabled)
|
||||
self.twList.setItem(row, 2, item)
|
||||
|
||||
if IssueString(record['issue_number']).asString().lower() == IssueString(self.issue_number).asString().lower():
|
||||
self.initial_id = record['id']
|
||||
@ -152,5 +165,10 @@ class IssueSelectionWindow(QtGui.QDialog):
|
||||
if record['id'] == self.issue_id:
|
||||
self.issue_number = record['issue_number']
|
||||
self.coverWidget.setIssueID( int(self.issue_id) )
|
||||
if record['description'] is None:
|
||||
self.teDescription.setText ( "" )
|
||||
else:
|
||||
self.teDescription.setText ( record['description'] )
|
||||
|
||||
break
|
||||
|
||||
|
@ -51,6 +51,7 @@ class MatchSelectionWindow(QtGui.QDialog):
|
||||
gridlayout.setContentsMargins(0,0,0,0)
|
||||
|
||||
utils.reduceWidgetFontSize( self.twList )
|
||||
utils.reduceWidgetFontSize( self.teDescription, 1 )
|
||||
|
||||
self.setWindowFlags(self.windowFlags() |
|
||||
QtCore.Qt.WindowSystemMenuHint |
|
||||
@ -144,7 +145,11 @@ class MatchSelectionWindow(QtGui.QDialog):
|
||||
return
|
||||
|
||||
self.altCoverWidget.setIssueID( self.currentMatch()['issue_id'] )
|
||||
|
||||
if self.currentMatch()['description'] is None:
|
||||
self.teDescription.setText ( "" )
|
||||
else:
|
||||
self.teDescription.setText ( self.currentMatch()['description'] )
|
||||
|
||||
def setCoverImage( self ):
|
||||
self.archiveCoverWidget.setArchive( self.comic_archive)
|
||||
|
||||
|
@ -25,8 +25,14 @@ import os
|
||||
import traceback
|
||||
import ctversion
|
||||
import utils
|
||||
try:
|
||||
import argparse
|
||||
except:
|
||||
pass
|
||||
|
||||
from genericmetadata import GenericMetadata
|
||||
from comicarchive import MetaDataStyle
|
||||
from versionchecker import VersionChecker
|
||||
|
||||
class Options:
|
||||
help_text = """
|
||||
@ -46,6 +52,7 @@ If no options are given, {0} will run in windowed mode
|
||||
-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 )
|
||||
-1, --assume-issue-one Assume issue number is 1 if not found ( relevent for -s )
|
||||
-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)
|
||||
@ -111,6 +118,7 @@ For more help visit the wiki at: http://code.google.com/p/comictagger/
|
||||
self.recursive = False
|
||||
self.run_script = False
|
||||
self.script = None
|
||||
self.assume_issue_is_one_if_not_set = False
|
||||
self.file_list = []
|
||||
|
||||
def display_msg_and_quit( self, msg, code, show_help=False ):
|
||||
@ -172,6 +180,41 @@ For more help visit the wiki at: http://code.google.com/p/comictagger/
|
||||
#print md
|
||||
return md
|
||||
|
||||
def launch_script(self, scriptfile):
|
||||
# we were given a script. special case for the args:
|
||||
# 1. ignore everthing before the -S,
|
||||
# 2. pass all the ones that follow (including script name) to the script
|
||||
script_args = list()
|
||||
for idx, arg in enumerate(sys.argv):
|
||||
if arg in [ '-S', '--script']:
|
||||
#found script!
|
||||
script_args = sys.argv[idx+1:]
|
||||
break
|
||||
sys.argv = script_args
|
||||
if not os.path.exists(scriptfile):
|
||||
print "Can't find {0}".format( scriptfile )
|
||||
else:
|
||||
# I *think* this makes sense:
|
||||
# assume the base name of the file is the module name
|
||||
# add the folder of the given file to the python path
|
||||
# import module
|
||||
dirname = os.path.dirname(scriptfile)
|
||||
module_name = os.path.splitext(os.path.basename(scriptfile))[0]
|
||||
sys.path = [dirname] + sys.path
|
||||
try:
|
||||
script = __import__(module_name)
|
||||
|
||||
# Determine if the entry point exists before trying to run it
|
||||
if "main" in dir(script):
|
||||
script.main()
|
||||
else:
|
||||
print "Can't find entry point \"main()\" in module \"{0}\"".format( module_name )
|
||||
except Exception as e:
|
||||
print "Script raised an unhandled exception: ", e
|
||||
print traceback.format_exc()
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
def parseCmdLineArgs(self):
|
||||
|
||||
if platform.system() == "Darwin" and hasattr(sys, "frozen") and sys.frozen == 1:
|
||||
@ -180,14 +223,23 @@ For more help visit the wiki at: http://code.google.com/p/comictagger/
|
||||
else:
|
||||
input_args = sys.argv[1:]
|
||||
|
||||
# first check if we're launching a script:
|
||||
for n in range(len(input_args)):
|
||||
if ( input_args[n] in [ "-S", "--script" ] and
|
||||
n+1 < len(input_args)):
|
||||
# insert a "--" which will cause getopt to ignore the remaining args
|
||||
# so they will be passed to the script
|
||||
input_args.insert(n+2, "--")
|
||||
break
|
||||
|
||||
# parse command line options
|
||||
try:
|
||||
opts, args = getopt.getopt( input_args,
|
||||
"hpdt:fm:vonsrc:ieRS:",
|
||||
"hpdt:fm:vonsrc:ieRS:1",
|
||||
[ "help", "print", "delete", "type=", "copy=", "parsefilename", "metadata=", "verbose",
|
||||
"online", "dryrun", "save", "rename" , "raw", "noabort", "terse", "nooverwrite",
|
||||
"interactive", "nosummary", "version", "id=" , "recursive", "script=",
|
||||
"export-to-zip", "delete-rar", "abort-on-conflict" ] )
|
||||
"export-to-zip", "delete-rar", "abort-on-conflict", "assume-issue-one" ] )
|
||||
|
||||
except getopt.GetoptError as err:
|
||||
self.display_msg_and_quit( str(err), 2 )
|
||||
@ -247,11 +299,18 @@ For more help visit the wiki at: http://code.google.com/p/comictagger/
|
||||
self.terse = True
|
||||
if o == "--nosummary":
|
||||
self.show_save_summary = False
|
||||
if o in ("-1", "--assume-issue-one"):
|
||||
self.assume_issue_is_one_if_not_set = True
|
||||
if o == "--nooverwrite":
|
||||
self.no_overwrite = True
|
||||
if o == "--version":
|
||||
print "ComicTagger {0}: Copyright (c) 2012-2013 Anthony Beville".format(ctversion.version)
|
||||
print "Distributed under Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)"
|
||||
print "Distributed under Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)"
|
||||
new_version = VersionChecker().getLatestVersion("", False)
|
||||
if new_version is not None and new_version != ctversion.version:
|
||||
print "----------------------------------------"
|
||||
print "New version available online: {0}".format(new_version)
|
||||
print "----------------------------------------"
|
||||
sys.exit(0)
|
||||
if o in ("-t", "--type"):
|
||||
if a.lower() == "cr":
|
||||
@ -279,40 +338,8 @@ For more help visit the wiki at: http://code.google.com/p/comictagger/
|
||||
self.display_msg_and_quit( "Must choose only one action of print, delete, save, copy, rename, export, or run script", 1 )
|
||||
|
||||
if self.script is not None:
|
||||
# we were given a script. special case for the args:
|
||||
# 1. ignore everthing before the -S,
|
||||
# 2. pass all the ones that follow (including script name) to the script
|
||||
script_args = list()
|
||||
for idx, arg in enumerate(sys.argv):
|
||||
if arg in [ '-S', '--script']:
|
||||
#found script!
|
||||
script_args = sys.argv[idx+1:]
|
||||
break
|
||||
sys.argv = script_args
|
||||
if not os.path.exists(self.script):
|
||||
print "Can't find {0}".format( self.script )
|
||||
else:
|
||||
# I *think* this makes sense:
|
||||
# assume the base name of the file is the module name
|
||||
# add the folder of the given file to the python path
|
||||
# import module
|
||||
dirname = os.path.dirname(self.script)
|
||||
module_name = os.path.splitext(os.path.basename(self.script))[0]
|
||||
sys.path = [dirname] + sys.path
|
||||
try:
|
||||
script = __import__(module_name)
|
||||
|
||||
# Determine if the entry point exists before trying to run it
|
||||
if "main" in dir(script):
|
||||
script.main()
|
||||
else:
|
||||
print "Can't find entry point \"main()\" in module \"{0}\"".format( module_name )
|
||||
except Exception as e:
|
||||
print "Script raised an unhandled exception: ", e
|
||||
print traceback.format_exc()
|
||||
|
||||
sys.exit(0)
|
||||
|
||||
self.launch_script( self.script )
|
||||
|
||||
if len(args) > 0:
|
||||
if platform.system() == "Windows":
|
||||
# no globbing on windows shell, so do it for them
|
||||
|
@ -24,6 +24,7 @@ import sys
|
||||
import configparser
|
||||
import platform
|
||||
import codecs
|
||||
import uuid
|
||||
|
||||
import utils
|
||||
|
||||
@ -67,8 +68,11 @@ class ComicTaggerSettings:
|
||||
self.rar_exe_path = ""
|
||||
self.unrar_exe_path = ""
|
||||
self.allow_cbi_in_rar = True
|
||||
self.check_for_new_version = True
|
||||
self.send_usage_stats = False
|
||||
|
||||
# automatic settings
|
||||
self.install_id = uuid.uuid4().hex
|
||||
self.last_selected_save_data_style = 0
|
||||
self.last_selected_load_data_style = 0
|
||||
self.last_opened_folder = ""
|
||||
@ -78,6 +82,8 @@ class ComicTaggerSettings:
|
||||
self.last_main_window_y = 0
|
||||
self.last_form_side_width = -1
|
||||
self.last_list_side_width = -1
|
||||
self.last_filelist_sorted_column = -1
|
||||
self.last_filelist_sorted_order = 0
|
||||
|
||||
# identifier settings
|
||||
self.id_length_delta_thresh = 5
|
||||
@ -86,6 +92,11 @@ class ComicTaggerSettings:
|
||||
# Show/ask dialog flags
|
||||
self.ask_about_cbi_in_rar = True
|
||||
self.show_disclaimer = True
|
||||
self.dont_notify_about_this_version = ""
|
||||
self.ask_about_usage_stats = True
|
||||
|
||||
#filename parsing settings
|
||||
self.parse_scan_info = True
|
||||
|
||||
# Comic Vine settings
|
||||
self.use_series_start_as_volume = False
|
||||
@ -159,12 +170,25 @@ class ComicTaggerSettings:
|
||||
self.__init__()
|
||||
|
||||
def load(self):
|
||||
|
||||
self.config.readfp(codecs.open(self.settings_file, "r", "utf8"))
|
||||
|
||||
def readline_generator(f):
|
||||
line = f.readline()
|
||||
while line:
|
||||
yield line
|
||||
line = f.readline()
|
||||
|
||||
#self.config.readfp(codecs.open(self.settings_file, "r", "utf8"))
|
||||
self.config.read_file(readline_generator(codecs.open(self.settings_file, "r", "utf8")))
|
||||
|
||||
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('settings', 'check_for_new_version'):
|
||||
self.check_for_new_version = self.config.getboolean( 'settings', 'check_for_new_version' )
|
||||
if self.config.has_option('settings', 'send_usage_stats'):
|
||||
self.send_usage_stats = self.config.getboolean( 'settings', 'send_usage_stats' )
|
||||
|
||||
if self.config.has_option('auto', 'install_id'):
|
||||
self.install_id = self.config.get( 'auto', 'install_id' )
|
||||
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'):
|
||||
@ -183,17 +207,28 @@ class ComicTaggerSettings:
|
||||
self.last_form_side_width = self.config.getint( 'auto', 'last_form_side_width' )
|
||||
if self.config.has_option('auto', 'last_list_side_width'):
|
||||
self.last_list_side_width = self.config.getint( 'auto', 'last_list_side_width' )
|
||||
if self.config.has_option('auto', 'last_filelist_sorted_column'):
|
||||
self.last_filelist_sorted_column = self.config.getint( 'auto', 'last_filelist_sorted_column' )
|
||||
if self.config.has_option('auto', 'last_filelist_sorted_order'):
|
||||
self.last_filelist_sorted_order = self.config.getint( 'auto', 'last_filelist_sorted_order' )
|
||||
|
||||
if self.config.has_option('identifier', 'id_length_delta_thresh'):
|
||||
self.id_length_delta_thresh = self.config.getint( 'identifier', 'id_length_delta_thresh' )
|
||||
if self.config.has_option('identifier', 'id_publisher_blacklist'):
|
||||
self.id_publisher_blacklist = self.config.get( 'identifier', 'id_publisher_blacklist' )
|
||||
|
||||
if self.config.has_option('filenameparser', 'parse_scan_info'):
|
||||
self.parse_scan_info = self.config.getboolean( 'filenameparser', 'parse_scan_info' )
|
||||
|
||||
if self.config.has_option('dialogflags', 'ask_about_cbi_in_rar'):
|
||||
self.ask_about_cbi_in_rar = self.config.getboolean( 'dialogflags', 'ask_about_cbi_in_rar' )
|
||||
if self.config.has_option('dialogflags', 'show_disclaimer'):
|
||||
self.show_disclaimer = self.config.getboolean( 'dialogflags', 'show_disclaimer' )
|
||||
|
||||
if self.config.has_option('dialogflags', 'dont_notify_about_this_version'):
|
||||
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('comicvine', 'use_series_start_as_volume'):
|
||||
self.use_series_start_as_volume = self.config.getboolean( 'comicvine', 'use_series_start_as_volume' )
|
||||
|
||||
@ -227,13 +262,16 @@ class ComicTaggerSettings:
|
||||
|
||||
if not self.config.has_section( 'settings' ):
|
||||
self.config.add_section( 'settings' )
|
||||
|
||||
|
||||
self.config.set( 'settings', 'check_for_new_version', self.check_for_new_version )
|
||||
self.config.set( 'settings', 'rar_exe_path', self.rar_exe_path )
|
||||
self.config.set( 'settings', 'unrar_exe_path', self.unrar_exe_path )
|
||||
self.config.set( 'settings', 'send_usage_stats', self.send_usage_stats )
|
||||
|
||||
if not self.config.has_section( 'auto' ):
|
||||
self.config.add_section( 'auto' )
|
||||
|
||||
self.config.set( 'auto', 'install_id', self.install_id )
|
||||
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 )
|
||||
@ -243,6 +281,8 @@ class ComicTaggerSettings:
|
||||
self.config.set( 'auto', 'last_main_window_y', self.last_main_window_y )
|
||||
self.config.set( 'auto', 'last_form_side_width', self.last_form_side_width )
|
||||
self.config.set( 'auto', 'last_list_side_width', self.last_list_side_width )
|
||||
self.config.set( 'auto', 'last_filelist_sorted_column', self.last_filelist_sorted_column )
|
||||
self.config.set( 'auto', 'last_filelist_sorted_order', self.last_filelist_sorted_order )
|
||||
|
||||
if not self.config.has_section( 'identifier' ):
|
||||
self.config.add_section( 'identifier' )
|
||||
@ -255,7 +295,14 @@ class ComicTaggerSettings:
|
||||
|
||||
self.config.set( 'dialogflags', 'ask_about_cbi_in_rar', self.ask_about_cbi_in_rar )
|
||||
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 )
|
||||
|
||||
if not self.config.has_section( 'filenameparser' ):
|
||||
self.config.add_section( 'filenameparser' )
|
||||
|
||||
self.config.set( 'filenameparser', 'parse_scan_info', self.parse_scan_info )
|
||||
|
||||
if not self.config.has_section( 'comicvine' ):
|
||||
self.config.add_section( 'comicvine' )
|
||||
|
||||
|
@ -119,6 +119,12 @@ class SettingsWindow(QtGui.QDialog):
|
||||
self.leNameLengthDeltaThresh.setText( str(self.settings.id_length_delta_thresh) )
|
||||
self.tePublisherBlacklist.setPlainText( self.settings.id_publisher_blacklist )
|
||||
|
||||
if self.settings.check_for_new_version:
|
||||
self.cbxCheckForNewVersion.setCheckState( QtCore.Qt.Checked)
|
||||
|
||||
if self.settings.parse_scan_info:
|
||||
self.cbxParseScanInfo.setCheckState( QtCore.Qt.Checked)
|
||||
|
||||
if self.settings.use_series_start_as_volume:
|
||||
self.cbxUseSeriesStartAsVolume.setCheckState( QtCore.Qt.Checked)
|
||||
|
||||
@ -162,10 +168,14 @@ class SettingsWindow(QtGui.QDialog):
|
||||
|
||||
if not str(self.leIssueNumPadding.text()).isdigit():
|
||||
self.leIssueNumPadding.setText("0")
|
||||
|
||||
self.settings.check_for_new_version = self.cbxCheckForNewVersion.isChecked()
|
||||
|
||||
self.settings.id_length_delta_thresh = int(self.leNameLengthDeltaThresh.text())
|
||||
self.settings.id_publisher_blacklist = str(self.tePublisherBlacklist.toPlainText())
|
||||
|
||||
|
||||
self.settings.parse_scan_info = self.cbxParseScanInfo.isChecked()
|
||||
|
||||
self.settings.use_series_start_as_volume = self.cbxUseSeriesStartAsVolume.isChecked()
|
||||
|
||||
self.settings.assume_lone_credit_is_primary = self.cbxAssumeLoneCreditIsPrimary.isChecked()
|
||||
@ -185,7 +195,6 @@ class SettingsWindow(QtGui.QDialog):
|
||||
self.settings.save()
|
||||
QtGui.QDialog.accept(self)
|
||||
|
||||
|
||||
def selectRar( self ):
|
||||
self.selectFile( self.leRarExePath, "RAR" )
|
||||
|
||||
@ -226,5 +235,5 @@ class SettingsWindow(QtGui.QDialog):
|
||||
control.setText( str(fileList[0]) )
|
||||
|
||||
def showRenameTab( self ):
|
||||
self.tabWidget.setCurrentIndex(4)
|
||||
self.tabWidget.setCurrentIndex(5)
|
||||
|
||||
|
@ -55,6 +55,7 @@ from autotagstartwindow import AutoTagStartWindow
|
||||
from autotagprogresswindow import AutoTagProgressWindow
|
||||
from autotagmatchwindow import AutoTagMatchWindow
|
||||
from coverimagewidget import CoverImageWidget
|
||||
from versionchecker import VersionChecker
|
||||
|
||||
import utils
|
||||
import ctversion
|
||||
@ -100,6 +101,8 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
|
||||
self.fileSelectionList.selectionChanged.connect( self.fileListSelectionChanged )
|
||||
self.fileSelectionList.listCleared.connect( self.fileListCleared )
|
||||
self.fileSelectionList.setSorting(self.settings.last_filelist_sorted_column,
|
||||
self.settings.last_filelist_sorted_order)
|
||||
|
||||
# we can't specify relative font sizes in the UI designer, so
|
||||
# walk through all the lablels in the main form, and make them
|
||||
@ -203,7 +206,23 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
"""
|
||||
)
|
||||
self.settings.show_disclaimer = not checked
|
||||
|
||||
|
||||
if self.settings.ask_about_usage_stats:
|
||||
reply = QtGui.QMessageBox.question(self,
|
||||
self.tr("Anonymous Stats"),
|
||||
self.tr(
|
||||
"Is it okay if ComicTagger occasionally sends some anonymous usage statistics? Nothing nefarious, "
|
||||
"just trying to get a better idea of how the app is being used.\n\nThanks for your support!"
|
||||
),
|
||||
QtGui.QMessageBox.Yes|QtGui.QMessageBox.Default, QtGui.QMessageBox.No )
|
||||
|
||||
if reply == QtGui.QMessageBox.Yes:
|
||||
self.settings.send_usage_stats = True
|
||||
self.settings.ask_about_usage_stats = False
|
||||
|
||||
if self.settings.check_for_new_version:
|
||||
self.checkLatestVersionOnline()
|
||||
|
||||
def sigint_handler(self, *args):
|
||||
# defer the actual close in the app loop thread
|
||||
QtCore.QTimer.singleShot(200, self.close)
|
||||
@ -1731,6 +1750,7 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
self.settings.last_main_window_y = self.y()
|
||||
self.settings.last_form_side_width = self.splitter.sizes()[0]
|
||||
self.settings.last_list_side_width = self.splitter.sizes()[1]
|
||||
self.settings.last_filelist_sorted_column, self.settings.last_filelist_sorted_order = self.fileSelectionList.getSorting()
|
||||
self.settings.save()
|
||||
|
||||
|
||||
@ -1835,4 +1855,21 @@ class TaggerWindow( QtGui.QMainWindow):
|
||||
def tabChanged( self, idx ):
|
||||
if idx == 0:
|
||||
self.splitterMovedEvent( 0, 0)
|
||||
|
||||
|
||||
def checkLatestVersionOnline( self ):
|
||||
self.versionChecker = VersionChecker()
|
||||
self.versionChecker.versionRequestComplete.connect( self.versionCheckComplete )
|
||||
self.versionChecker.asyncGetLatestVersion( self.settings.install_id, self.settings.send_usage_stats )
|
||||
|
||||
def versionCheckComplete( self, new_version ):
|
||||
if ( new_version != self.version and
|
||||
new_version != self.settings.dont_notify_about_this_version):
|
||||
website = "http://code.google.com/p/comictagger"
|
||||
checked = OptionalMessageDialog.msg( self, "New version available!",
|
||||
"New version ({0}) available!<br>(You are currently running {1})<br><br>".format( new_version, self.version) +
|
||||
"Visit <a href='{0}'>{0}</a> for more info.<br><br>".format(website),
|
||||
QtCore.Qt.Unchecked,
|
||||
"Don't tell me about this version again")
|
||||
if checked:
|
||||
self.settings.dont_notify_about_this_version = new_version
|
||||
|
||||
|
@ -6,21 +6,18 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>907</width>
|
||||
<height>507</height>
|
||||
<width>943</width>
|
||||
<height>467</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Select Match</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="1">
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="archiveCoverContainer" native="true">
|
||||
<property name="minimumSize">
|
||||
@ -38,45 +35,73 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="twList">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="rowCount">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<property name="childrenCollapsible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Series</string>
|
||||
</property>
|
||||
<widget class="QTableWidget" name="twList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>7</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Publisher</string>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Date</string>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Title</string>
|
||||
<property name="rowCount">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</column>
|
||||
<property name="columnCount">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Series</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Publisher</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Date</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Title</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
<widget class="QTextEdit" name="teDescription">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>3</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -6,51 +6,90 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>657</width>
|
||||
<height>400</height>
|
||||
<width>872</width>
|
||||
<height>550</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Select Issue</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="twList">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="rowCount">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<property name="childrenCollapsible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Issue</string>
|
||||
</property>
|
||||
<widget class="QTableWidget" name="twList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>7</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Title</string>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="textAlignment">
|
||||
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
</column>
|
||||
<property name="rowCount">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Issue</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Date</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Title</string>
|
||||
</property>
|
||||
<property name="textAlignment">
|
||||
<set>AlignHCenter|AlignVCenter|AlignCenter</set>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
<widget class="QTextEdit" name="teDescription">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>3</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -6,21 +6,18 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>907</width>
|
||||
<height>507</height>
|
||||
<width>943</width>
|
||||
<height>467</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Select Match</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="1">
|
||||
<item row="0" column="0">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="archiveCoverContainer" native="true">
|
||||
<property name="minimumSize">
|
||||
@ -38,45 +35,73 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="twList">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="rowCount">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="columnCount">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<property name="childrenCollapsible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Series</string>
|
||||
</property>
|
||||
<widget class="QTableWidget" name="twList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>7</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Publisher</string>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Date</string>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Title</string>
|
||||
<property name="rowCount">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</column>
|
||||
<property name="columnCount">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Series</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Publisher</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Date</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>Title</string>
|
||||
</property>
|
||||
</column>
|
||||
</widget>
|
||||
<widget class="QTextEdit" name="teDescription">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>3</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
|
@ -35,7 +35,7 @@
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="btnResetSettings">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
@ -48,7 +48,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="lblDefaultSettings">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
@ -64,7 +64,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<item row="2" column="0">
|
||||
<widget class="QPushButton" name="btnClearCache">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
|
||||
@ -77,7 +77,7 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
@ -93,6 +93,13 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="cbxCheckForNewVersion">
|
||||
<property name="text">
|
||||
<string>Check for new version on startup</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
@ -307,6 +314,24 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_6">
|
||||
<attribute name="title">
|
||||
<string>Filename Parser</string>
|
||||
</attribute>
|
||||
<widget class="QCheckBox" name="cbxParseScanInfo">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>30</x>
|
||||
<y>30</y>
|
||||
<width>421</width>
|
||||
<height>25</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Parse Scan Info From Filename (Experimental)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_3">
|
||||
<attribute name="title">
|
||||
<string>Comic Vine</string>
|
||||
|
@ -42,17 +42,20 @@
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="childrenCollapsible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="QTableWidget" name="twList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
<verstretch>7</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>250</height>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
@ -102,15 +105,15 @@
|
||||
</widget>
|
||||
<widget class="QTextEdit" name="teDetails">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Maximum">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
<verstretch>3</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>200</height>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
|
91
comictaggerlib/versionchecker.py
Normal file
91
comictaggerlib/versionchecker.py
Normal file
@ -0,0 +1,91 @@
|
||||
"""
|
||||
Version checker
|
||||
"""
|
||||
|
||||
"""
|
||||
Copyright 2013 Anthony Beville
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
import platform
|
||||
import urllib,urllib2
|
||||
import ctversion
|
||||
|
||||
try:
|
||||
from PyQt4.QtNetwork import QNetworkAccessManager, QNetworkRequest
|
||||
from PyQt4.QtCore import QUrl, pyqtSignal, QObject, QByteArray
|
||||
except ImportError:
|
||||
# No Qt, so define a few dummy QObjects to help us compile
|
||||
class QObject():
|
||||
def __init__(self,*args):
|
||||
pass
|
||||
class pyqtSignal():
|
||||
def __init__(self,*args):
|
||||
pass
|
||||
def emit(a,b,c):
|
||||
pass
|
||||
|
||||
class VersionChecker(QObject):
|
||||
|
||||
def getRequestUrl( self, uuid, use_stats ):
|
||||
|
||||
base_url = "http://comictagger1.appspot.com/latest"
|
||||
args = ""
|
||||
|
||||
if use_stats:
|
||||
if platform.system() == "Windows":
|
||||
plat = "win"
|
||||
elif platform.system() == "Linux":
|
||||
plat = "lin"
|
||||
elif platform.system() == "Darwin":
|
||||
plat = "mac"
|
||||
else:
|
||||
plat = "other"
|
||||
args = "?uuid={0}&platform={1}&version={2}".format(uuid, plat, ctversion.version)
|
||||
if not getattr(sys, 'frozen', None):
|
||||
args += "&src=T"
|
||||
|
||||
return base_url+args
|
||||
|
||||
def getLatestVersion( self, uuid, use_stats=True):
|
||||
|
||||
try:
|
||||
resp = urllib2.urlopen( self.getRequestUrl(uuid, use_stats ))
|
||||
new_version = resp.read()
|
||||
except Exception as e:
|
||||
return None
|
||||
|
||||
if new_version is None or new_version == "":
|
||||
return None
|
||||
return new_version.strip()
|
||||
|
||||
versionRequestComplete = pyqtSignal( str )
|
||||
|
||||
def asyncGetLatestVersion( self, uuid, use_stats ):
|
||||
|
||||
url = self.getRequestUrl( uuid, use_stats )
|
||||
|
||||
self.nam = QNetworkAccessManager()
|
||||
self.nam.finished.connect( self.asyncGetLatestVersionComplete )
|
||||
self.nam.get(QNetworkRequest(QUrl(str(url))))
|
||||
|
||||
def asyncGetLatestVersionComplete( self, reply ):
|
||||
# read in the response
|
||||
new_version = str(reply.readAll())
|
||||
|
||||
if new_version is None or new_version == "":
|
||||
return
|
||||
|
||||
self.versionRequestComplete.emit( new_version.strip() )
|
1
current_version.txt
Normal file
1
current_version.txt
Normal file
@ -0,0 +1 @@
|
||||
1.1.7-beta
|
11
google/gadgets/social.xml
Normal file
11
google/gadgets/social.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<Module>
|
||||
<ModulePrefs title="mygaget" />
|
||||
<Content type="html">
|
||||
<![CDATA[
|
||||
<a href="https://twitter.com/ComicTagger" class="twitter-follow-button" data-show-count="false" data-size="large">Follow @ComicTagger</a>
|
||||
<script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0];if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src="//platform.twitter.com/widgets.js";fjs.parentNode.insertBefore(js,fjs);}}(document,"script","twitter-wjs");</script>
|
||||
<iframe allowtransparency="true" frameborder="0" scrolling="no" src="http://www.facebook.com/plugins/likebox.php?href=http%3A%2F%2Fwww.facebook.com%2Fpages%2FComictagger/139615369550787&width=292&colorscheme=light&show_faces =false&border_color&stream=false&header=false&height=62" style="background-color: white; border-bottom-style: none; border-color: initial; border-left-style: none; border-right-style: none; border-top-style: none; border-width: initial; color: #333333; font-family: Verdana; font-size: 12px; height: 62px; line-height: 19px; overflow-x: hidden; overflow-y: hidden; text-align: -webkit-auto; width: 292px;"></iframe>
|
||||
]]>
|
||||
</Content>
|
||||
</Module>
|
@ -1,8 +1,26 @@
|
||||
---------------------------------
|
||||
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 efficent automated search using new CV API issue filters
|
||||
* More efficient automated search using new CV API issue filters
|
||||
* Minor bug fixes
|
||||
|
||||
---------------------------------
|
||||
|
151
scripts/name_fixer.py
Executable file
151
scripts/name_fixer.py
Executable file
@ -0,0 +1,151 @@
|
||||
#!/usr/bin/python
|
||||
"""
|
||||
fix the comic file names using a list of transforms
|
||||
"""
|
||||
|
||||
"""
|
||||
Copyright 2013 Anthony Beville
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import re
|
||||
import argparse
|
||||
import json
|
||||
|
||||
from comictaggerlib.comicarchive import *
|
||||
from comictaggerlib.settings import *
|
||||
from comictaggerlib.filerenamer import *
|
||||
import comictaggerlib.utils
|
||||
|
||||
def parse_args():
|
||||
|
||||
input_args = sys.argv[1:]
|
||||
|
||||
parser = argparse.ArgumentParser(description='a script to rename comic files')
|
||||
parser.add_argument('-t', '--transforms', metavar='xformfile', help="the file with transforms")
|
||||
parser.add_argument('-n', '--noconfirm', action='store_true', help="don't confirm before rename")
|
||||
parser.add_argument('paths', metavar='PATH', type=str, nargs='+', help='path to look for comic files')
|
||||
parsed_args = parser.parse_args(input_args)
|
||||
|
||||
return parsed_args
|
||||
|
||||
def caclulate_rename(ca, md, settings):
|
||||
|
||||
new_ext = None # default
|
||||
if settings.rename_extension_based_on_archive:
|
||||
if ca.isZip():
|
||||
new_ext = ".cbz"
|
||||
elif ca.isRar():
|
||||
new_ext = ".cbr"
|
||||
|
||||
renamer = FileRenamer( md )
|
||||
renamer.setTemplate( "%series% V%volume% #%issue% (of %issuecount%) (%year%) %scaninfo%" )
|
||||
renamer.setIssueZeroPadding( 0 )
|
||||
renamer.setSmartCleanup( settings.rename_use_smart_string_cleanup )
|
||||
|
||||
return renamer.determineName( ca.path, ext=new_ext )
|
||||
|
||||
def perform_rename(filelist):
|
||||
for old_name,new_name in filelist:
|
||||
folder = os.path.dirname( os.path.abspath( old_name ) )
|
||||
new_abs_path = utils.unique_file( os.path.join( folder, new_name ) )
|
||||
|
||||
os.rename( old_name, new_abs_path )
|
||||
print u"renamed '{0}' -> '{1}'".format(os.path.basename(old_name), new_name)
|
||||
|
||||
def main():
|
||||
|
||||
default_xform_list = [
|
||||
[ "^2000AD$", "2000 AD" ],
|
||||
[ "^G\.{0,1}I\.{0,1}Joe$", "G.I. Joe" ],
|
||||
]
|
||||
|
||||
utils.fix_output_encoding()
|
||||
settings = ComicTaggerSettings()
|
||||
|
||||
style = MetaDataStyle.CIX
|
||||
|
||||
parsed_args = parse_args()
|
||||
|
||||
#parsed_args.noconfirm
|
||||
if parsed_args.transforms is not None:
|
||||
print "Reading in transforms from:", parsed_args.transforms
|
||||
json_data=open(parsed_args.transforms).read()
|
||||
data = json.loads(json_data)
|
||||
xform_list = data['xforms']
|
||||
else:
|
||||
xform_list = default_xform_list
|
||||
|
||||
#pprint( xform_list, indent=4)
|
||||
|
||||
filelist = utils.get_recursive_filelist( parsed_args.paths )
|
||||
|
||||
#first find all comics
|
||||
print "reading in all comics..."
|
||||
comic_list = []
|
||||
max_name_len = 2
|
||||
fmt_str = ""
|
||||
for filename in filelist:
|
||||
ca = ComicArchive(filename, settings )
|
||||
# do we care if it already has metadata?
|
||||
if ca.seemsToBeAComicArchive() and not ca.hasMetadata( style ):
|
||||
|
||||
comic_list.append(ca)
|
||||
|
||||
max_name_len = max ( max_name_len, len(filename))
|
||||
fmt_str = u"{{0:{0}}}".format(max_name_len)
|
||||
print >> sys.stderr, fmt_str.format( filename ) + "\r",
|
||||
sys.stderr.flush()
|
||||
|
||||
print >> sys.stderr, fmt_str.format( "" )
|
||||
print "Found {0} comics.".format( len(comic_list))
|
||||
|
||||
modify_list = list()
|
||||
# walk through the comic list fix the filenames
|
||||
for ca in comic_list:
|
||||
|
||||
# 1. parse the filename into a MD object
|
||||
md = ca.metadataFromFilename()
|
||||
# 2. walk thru list of transforms
|
||||
if md.series is not None and md.series != "":
|
||||
for pattern, replacement in xform_list:
|
||||
# apply each transform
|
||||
new_series = re.sub( pattern, replacement, md.series )
|
||||
if new_series != md.series:
|
||||
md.series = new_series
|
||||
new_name = caclulate_rename(ca, md, settings)
|
||||
|
||||
#found a match. add to proposed list, and bail on this file
|
||||
modify_list.append( (ca.path, new_name ) )
|
||||
break
|
||||
|
||||
print "{0} filenames to modify".format(len(modify_list))
|
||||
if len(modify_list) > 0:
|
||||
if parsed_args.noconfirm:
|
||||
print "Not confirming before rename"
|
||||
else:
|
||||
for old_name, new_name in modify_list:
|
||||
print u"'{0}' -> '{1}'".format(os.path.basename(old_name), new_name)
|
||||
|
||||
i = raw_input("Do you want to proceed with rename? [y/N] ")
|
||||
if i.lower() not in ('y', 'yes'):
|
||||
print "exiting without rename."
|
||||
sys.exit(0)
|
||||
|
||||
perform_rename(modify_list)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -125,6 +125,7 @@ def main():
|
||||
for idx in range(ca.getNumberOfPages()):
|
||||
name = ca.getPageName( idx )
|
||||
in_data = ca.getPage( idx )
|
||||
out_data = in_data
|
||||
if in_data is not None:
|
||||
try:
|
||||
im = Image.open(StringIO.StringIO(in_data))
|
||||
@ -143,7 +144,7 @@ def main():
|
||||
|
||||
except IOError:
|
||||
#doesn't appear to be an image
|
||||
out_data = in_data
|
||||
pass
|
||||
|
||||
else:
|
||||
#page is empty?? nothing to write
|
||||
@ -152,7 +153,7 @@ def main():
|
||||
sys.stdout.write('.')
|
||||
sys.stdout.flush()
|
||||
|
||||
#Generate a new name for the page file
|
||||
#write out the new resized image
|
||||
zout.writestr(name, out_data)
|
||||
|
||||
|
||||
|
8
scripts/xforms
Normal file
8
scripts/xforms
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"_comment": "This file contains JSON data. Any backslashes should be escaped with another backslash",
|
||||
"xforms":
|
||||
[
|
||||
[ "^2000AD$", "2000 AD" ],
|
||||
[ "^G\\.{0,1}I\\.{0,1}Joe$", "G.I. Joe" ]
|
||||
]
|
||||
}
|
20
todo.txt
20
todo.txt
@ -4,23 +4,24 @@ Features
|
||||
Rename dialog:
|
||||
check-box for rows?
|
||||
manual edit the preview?
|
||||
|
||||
Feature Requests:
|
||||
Move CBR to other folder after conversion to ZIP
|
||||
|
||||
NO - AUto-rename on auto-tag
|
||||
NO- Re-zip (to remove compression)
|
||||
|
||||
|
||||
Docs:
|
||||
Auto-Tagging Tips:
|
||||
Multiple Passes with different options
|
||||
|
||||
Feature Requests:
|
||||
Remember last sorted column in file list
|
||||
Re-zip (to remove compression)
|
||||
Move CBR to other folder after conversion to ZIP
|
||||
AUto-rename on auto-tag
|
||||
Multiple Passes with different options
|
||||
|
||||
-----------------------------------------------------
|
||||
Bugs
|
||||
-----------------------------------------------------
|
||||
|
||||
Non-numeric issues?? Filename parsing... can we only rely on '#'??
|
||||
Unicode search on mac doesn't work
|
||||
|
||||
|
||||
Zip flakes out when filename differs from index (or whatever) i.e "\" vs "/". Python issue
|
||||
|
||||
@ -57,7 +58,7 @@ Google App engine to store hashes
|
||||
|
||||
Filename parsing:
|
||||
Rework how series name is separated from issue
|
||||
s
|
||||
|
||||
Internal GenericMetadata - Make Characters, Genre into lists?
|
||||
|
||||
-----------------------------------------------------
|
||||
@ -76,6 +77,7 @@ Release Process
|
||||
Upload packages
|
||||
Announce on Forum and Main Page and Twitter
|
||||
MacUpdate
|
||||
Update appspot value
|
||||
|
||||
----------------------------------------------
|
||||
|
||||
|
Reference in New Issue
Block a user