Merge from trunk

This commit is contained in:
Charles Haley 2011-04-28 18:46:34 +01:00
commit 2053ffb22c
8 changed files with 61 additions and 38 deletions

View File

@ -2,6 +2,11 @@ a {
text-decoration: none;
color: blue
}
a:hover {
color: red
}
.comments {
margin-top: 0;
padding-top: 0;

View File

@ -156,17 +156,17 @@ class HeuristicProcessor(object):
]
ITALICIZE_STYLE_PATS = [
r'(?msu)(?<=[\s>])_(?P<words>[^_]+)_',
r'(?msu)(?<=[\s>])/(?P<words>[^/\*>]+)/',
r'(?msu)(?<=[\s>])~~(?P<words>[^~]+)~~',
r'(?msu)(?<=[\s>])\*(?P<words>[^\*]+)\*',
r'(?msu)(?<=[\s>])~(?P<words>[^~]+)~',
r'(?msu)(?<=[\s>])_/(?P<words>[^/_]+)/_',
r'(?msu)(?<=[\s>])_\*(?P<words>[^\*_]+)\*_',
r'(?msu)(?<=[\s>])\*/(?P<words>[^/\*]+)/\*',
r'(?msu)(?<=[\s>])_\*/(?P<words>[^\*_]+)/\*_',
r'(?msu)(?<=[\s>])/:(?P<words>[^:/]+):/',
r'(?msu)(?<=[\s>])\|:(?P<words>[^:\|]+):\|',
ur'(?msu)(?<=[\s>"\'])_(?P<words>[^_]+)_',
ur'(?msu)(?<=[\s>"\'])/(?P<words>[^/\*>]+)/',
ur'(?msu)(?<=[\s>"\'])~~(?P<words>[^~]+)~~',
ur'(?msu)(?<=[\s>"\'])\*(?P<words>[^\*]+)\*',
ur'(?msu)(?<=[\s>"\'])~(?P<words>[^~]+)~',
ur'(?msu)(?<=[\s>"\'])_/(?P<words>[^/_]+)/_',
ur'(?msu)(?<=[\s>"\'])_\*(?P<words>[^\*_]+)\*_',
ur'(?msu)(?<=[\s>"\'])\*/(?P<words>[^/\*]+)/\*',
ur'(?msu)(?<=[\s>"\'])_\*/(?P<words>[^\*_]+)/\*_',
ur'(?msu)(?<=[\s>"\'])/:(?P<words>[^:/]+):/',
ur'(?msu)(?<=[\s>"\'])\|:(?P<words>[^:\|]+):\|',
]
for word in ITALICIZE_WORDS:
@ -518,13 +518,13 @@ class HeuristicProcessor(object):
if re.findall('(<|>)', replacement_break):
if re.match('^<hr', replacement_break):
if replacement_break.find('width') != -1:
width = int(re.sub('.*?width(:|=)(?P<wnum>\d+).*', '\g<wnum>', replacement_break))
replacement_break = re.sub('(?i)(width=\d+\%?|width:\s*\d+(\%|px|pt|em)?;?)', '', replacement_break)
divpercent = (100 - width) / 2
hr_open = re.sub('45', str(divpercent), hr_open)
scene_break = hr_open+replacement_break+'</div>'
width = int(re.sub('.*?width(:|=)(?P<wnum>\d+).*', '\g<wnum>', replacement_break))
replacement_break = re.sub('(?i)(width=\d+\%?|width:\s*\d+(\%|px|pt|em)?;?)', '', replacement_break)
divpercent = (100 - width) / 2
hr_open = re.sub('45', str(divpercent), hr_open)
scene_break = hr_open+replacement_break+'</div>'
else:
scene_break = hr_open+'<hr style="height: 3px; background:#505050" /></div>'
scene_break = hr_open+'<hr style="height: 3px; background:#505050" /></div>'
elif re.match('^<img', replacement_break):
scene_break = self.scene_break_open+replacement_break+'</p>'
else:
@ -584,10 +584,10 @@ class HeuristicProcessor(object):
#print "styles for this line are: "+str(styles)
split_styles = []
for style in styles:
#print "style is: "+str(style)
newstyle = style.split(':')
#print "newstyle is: "+str(newstyle)
split_styles.append(newstyle)
#print "style is: "+str(style)
newstyle = style.split(':')
#print "newstyle is: "+str(newstyle)
split_styles.append(newstyle)
styles = split_styles
for style, setting in styles:
if style == 'text-align' and setting != 'left':

View File

@ -563,10 +563,12 @@ class Metadata(object):
def format_tags(self):
return u', '.join([unicode(t) for t in sorted(self.tags, key=sort_key)])
def format_rating(self, v = None):
def format_rating(self, v=None, divide_by=1.0):
if v is None:
return unicode(self.rating/2)
return unicode(v/2)
if self.rating is not None:
return unicode(self.rating/divide_by)
return u'None'
return unicode(v/divide_by)
def format_field(self, key, series_with_index=True):
'''

View File

@ -40,6 +40,11 @@ path_to_ebook to the database.
parser.add_option('--ignore-plugins', default=False, action='store_true',
help=_('Ignore custom plugins, useful if you installed a plugin'
' that is preventing calibre from starting'))
parser.add_option('-s', '--shutdown-running-calibre', default=False,
action='store_true',
help=_('Cause a running calibre instance, if any, to be'
' shutdown. Note that if there are running jobs, they '
'will be silently aborted, so use with care.'))
return parser
def init_qt(args):
@ -339,7 +344,7 @@ def cant_start(msg=_('If you are sure it is not running')+', ',
raise SystemExit(1)
def communicate(args):
def communicate(opts, args):
t = RC()
t.start()
time.sleep(3)
@ -348,9 +353,12 @@ def communicate(args):
cant_start(what=_('try deleting the file')+': '+f)
raise SystemExit(1)
if len(args) > 1:
args[1] = os.path.abspath(args[1])
t.conn.send('launched:'+repr(args))
if opts.shutdown_running_calibre:
t.conn.send('shutdown:')
else:
if len(args) > 1:
args[1] = os.path.abspath(args[1])
t.conn.send('launched:'+repr(args))
t.conn.close()
raise SystemExit(0)
@ -365,6 +373,8 @@ def main(args=sys.argv):
from calibre.utils.lock import singleinstance
from multiprocessing.connection import Listener
si = singleinstance('calibre GUI')
if si and opts.shutdown_running_calibre:
return 0
if si:
try:
listener = Listener(address=ADDRESS)
@ -390,10 +400,10 @@ def main(args=sys.argv):
else:
# On windows only singleinstance can be trusted
otherinstance = True if iswindows else False
if not otherinstance:
if not otherinstance and not opts.shutdown_running_calibre:
return run_gui(opts, args, actions, listener, app, gui_debug=gui_debug)
communicate(args)
communicate(opts, args)
return 0

View File

@ -100,7 +100,8 @@ class ThreadedJob(BaseJob):
try:
self.consolidate_log()
except:
self.log.exception('Log consolidation failed')
if self.log is not None:
self.log.exception('Log consolidation failed')
# No need to keep references to these around anymore
self.func = self.args = self.kwargs = self.notifications = None
@ -112,7 +113,7 @@ class ThreadedJob(BaseJob):
self.start_time = time.time()
self.duration = 0.0001
else:
self.duration = time.time() - self.start_time()
self.duration = time.time() - self.start_time
self.abort.set()
self.log('Aborted job:', self.description)

View File

@ -446,6 +446,8 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
self.library_view.model().refresh()
self.library_view.model().research()
self.tags_view.recount()
elif msg.startswith('shutdown:'):
self.quit(confirm_quit=False)
else:
print msg
@ -599,8 +601,9 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
dynamic.set('sort_history', self.library_view.model().sort_history)
self.save_layout_state()
def quit(self, checked=True, restart=False, debug_on_restart=False):
if not self.confirm_quit():
def quit(self, checked=True, restart=False, debug_on_restart=False,
confirm_quit=True):
if confirm_quit and not self.confirm_quit():
return
try:
self.shutdown()

View File

@ -189,7 +189,7 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250,
else:
template = re.sub(r'\{series_index[^}]*?\}', '', template)
if mi.rating is not None:
format_args['rating'] = mi.format_rating()
format_args['rating'] = mi.format_rating(divide_by=2.0)
if hasattr(mi.timestamp, 'timetuple'):
format_args['timestamp'] = strftime(timefmt, mi.timestamp.timetuple())
if hasattr(mi.pubdate, 'timetuple'):
@ -212,7 +212,8 @@ def get_components(template, mi, id, timefmt='%b %Y', length=250,
elif cm['datatype'] == 'bool':
format_args[key] = _('yes') if format_args[key] else _('no')
elif cm['datatype'] == 'rating':
format_args[key] = mi.format_rating(format_args[key])
format_args[key] = mi.format_rating(format_args[key],
divide_by=2.0)
elif cm['datatype'] in ['int', 'float']:
if format_args[key] != 0:
format_args[key] = unicode(format_args[key])

View File

@ -195,9 +195,10 @@ It can get tiresome to keep re-adding a plugin to calibre to test small changes.
Once you've located the zip file of your plugin you can then directly update it with your changes instead of re-adding it each time. To do so from the command line, in the directory that contains your plugin source code, use::
zip -R /path/to/plugin/zip/file.zip *
calibre -s; sleep 4s; zip -R /path/to/plugin/zip/file.zip *; calibre
This will update all changed files. It relies on the freely available zip command line tool. Note that you should quit calibre before running this command.
This will shutdown a running calibre. Wait for the shutdown to complete, then update your plugin files and relaunch calibre.
It relies on the freely available zip command line tool.
More plugin examples
----------------------