mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Sync to trunk.
This commit is contained in:
commit
f747483f3d
@ -12,6 +12,7 @@ from Queue import Empty
|
||||
|
||||
from calibre.customize.conversion import InputFormatPlugin, OptionRecommendation
|
||||
from calibre import extract, CurrentDir, prints
|
||||
from calibre.constants import filesystem_encoding
|
||||
from calibre.ptempfile import PersistentTemporaryDirectory
|
||||
from calibre.utils.ipc.server import Server
|
||||
from calibre.utils.ipc.job import ParallelJob
|
||||
@ -21,6 +22,10 @@ def extract_comic(path_to_comic_file):
|
||||
Un-archive the comic file.
|
||||
'''
|
||||
tdir = PersistentTemporaryDirectory(suffix='_comic_extract')
|
||||
if not isinstance(tdir, unicode):
|
||||
# Needed in case the zip file has wrongly encoded unicode file/dir
|
||||
# names
|
||||
tdir = tdir.decode(filesystem_encoding)
|
||||
extract(path_to_comic_file, tdir)
|
||||
return tdir
|
||||
|
||||
|
@ -716,6 +716,7 @@ class MobiReader(object):
|
||||
ent_pat = re.compile(r'&(\S+?);')
|
||||
if elems:
|
||||
tocobj = TOC()
|
||||
found = False
|
||||
reached = False
|
||||
for x in root.iter():
|
||||
if x == elems[-1]:
|
||||
@ -732,7 +733,8 @@ class MobiReader(object):
|
||||
text = ent_pat.sub(entity_to_unicode, text)
|
||||
tocobj.add_item(toc.partition('#')[0], href[1:],
|
||||
text)
|
||||
if reached and x.get('class', None) == 'mbp_pagebreak':
|
||||
found = True
|
||||
if reached and found and x.get('class', None) == 'mbp_pagebreak':
|
||||
break
|
||||
if tocobj is not None:
|
||||
opf.set_toc(tocobj)
|
||||
|
@ -8,14 +8,14 @@ __docformat__ = 'restructuredtext en'
|
||||
|
||||
from functools import partial
|
||||
|
||||
from PyQt4.Qt import Qt, QMenu, QToolButton, QDialog, QVBoxLayout
|
||||
from PyQt4.Qt import QMenu
|
||||
|
||||
from calibre.gui2.actions import InterfaceAction
|
||||
|
||||
class StoreAction(InterfaceAction):
|
||||
|
||||
name = 'Store'
|
||||
action_spec = (_('Store'), 'store.png', None, None)
|
||||
action_spec = (_('Get books'), 'store.png', None, None)
|
||||
|
||||
def genesis(self):
|
||||
self.qaction.triggered.connect(self.search)
|
||||
|
@ -68,7 +68,7 @@ class DaysOfWeek(Base):
|
||||
def initialize(self, typ=None, val=None):
|
||||
if typ is None:
|
||||
typ = 'day/time'
|
||||
val = (-1, 9, 0)
|
||||
val = (-1, 6, 0)
|
||||
if typ == 'day/time':
|
||||
val = convert_day_time_schedule(val)
|
||||
|
||||
@ -118,7 +118,7 @@ class DaysOfMonth(Base):
|
||||
|
||||
def initialize(self, typ=None, val=None):
|
||||
if val is None:
|
||||
val = ((1,), 9, 0)
|
||||
val = ((1,), 6, 0)
|
||||
days_of_month, hour, minute = val
|
||||
self.days.setText(', '.join(map(str, map(int, days_of_month))))
|
||||
self.time.setTime(QTime(hour, minute))
|
||||
@ -380,7 +380,7 @@ class SchedulerDialog(QDialog, Ui_Dialog):
|
||||
if d < timedelta(days=366):
|
||||
ld_text = tm
|
||||
else:
|
||||
typ, sch = 'day/time', (-1, 9, 0)
|
||||
typ, sch = 'day/time', (-1, 6, 0)
|
||||
sch_widget = {'day/time': 0, 'days_of_week': 0, 'days_of_month':1,
|
||||
'interval':2}[typ]
|
||||
rb = getattr(self, list(self.SCHEDULE_TYPES)[sch_widget])
|
||||
|
@ -200,13 +200,6 @@ class SearchBar(QWidget): # {{{
|
||||
x.setIcon(QIcon(I('arrow-down.png')))
|
||||
l.addWidget(x)
|
||||
|
||||
x = parent.search_options_button = QToolButton(self)
|
||||
x.setIcon(QIcon(I('config.png')))
|
||||
x.setObjectName("search_option_button")
|
||||
l.addWidget(x)
|
||||
x.setToolTip(_("Change the way searching for books works"))
|
||||
x.setVisible(False)
|
||||
|
||||
x = parent.saved_search = SavedSearchBox(self)
|
||||
x.setMaximumSize(QSize(150, 16777215))
|
||||
x.setMinimumContentsLength(15)
|
||||
@ -324,6 +317,8 @@ class BaseToolBar(QToolBar): # {{{
|
||||
QToolBar.resizeEvent(self, ev)
|
||||
style = self.get_text_style()
|
||||
self.setToolButtonStyle(style)
|
||||
if hasattr(self, 'd_widget'):
|
||||
self.d_widget.filler.setVisible(style != Qt.ToolButtonIconOnly)
|
||||
|
||||
def get_text_style(self):
|
||||
style = Qt.ToolButtonTextUnderIcon
|
||||
@ -406,7 +401,8 @@ class ToolBar(BaseToolBar): # {{{
|
||||
self.d_widget.layout().addWidget(self.donate_button)
|
||||
if isosx:
|
||||
self.d_widget.setStyleSheet('QWidget, QToolButton {background-color: none; border: none; }')
|
||||
self.d_widget.layout().addWidget(QLabel(u'\u00a0'))
|
||||
self.d_widget.filler = QLabel(u'\u00a0')
|
||||
self.d_widget.layout().addWidget(self.d_widget.filler)
|
||||
bar.addWidget(self.d_widget)
|
||||
self.showing_donate = True
|
||||
elif what in self.gui.iactions:
|
||||
|
@ -743,6 +743,8 @@ class BooksView(QTableView): # {{{
|
||||
id_to_select = self._model.get_current_highlighted_id()
|
||||
if id_to_select is not None:
|
||||
self.select_rows([id_to_select], using_ids=True)
|
||||
elif self._model.highlight_only:
|
||||
self.clearSelection()
|
||||
self.setFocus(Qt.OtherFocusReason)
|
||||
|
||||
def connect_to_search_box(self, sb, search_done):
|
||||
|
@ -222,7 +222,8 @@ class AuthorSortEdit(EnLineEdit):
|
||||
'red, then the authors and this text do not match.')
|
||||
LABEL = _('Author s&ort:')
|
||||
|
||||
def __init__(self, parent, authors_edit, autogen_button, db):
|
||||
def __init__(self, parent, authors_edit, autogen_button, db,
|
||||
copy_a_to_as_action, copy_as_to_a_action):
|
||||
EnLineEdit.__init__(self, parent)
|
||||
self.authors_edit = authors_edit
|
||||
self.db = db
|
||||
@ -241,6 +242,8 @@ class AuthorSortEdit(EnLineEdit):
|
||||
self.textChanged.connect(self.update_state)
|
||||
|
||||
autogen_button.clicked.connect(self.auto_generate)
|
||||
copy_a_to_as_action.triggered.connect(self.auto_generate)
|
||||
copy_as_to_a_action.triggered.connect(self.copy_to_authors)
|
||||
self.update_state()
|
||||
|
||||
@dynamic_property
|
||||
@ -273,6 +276,14 @@ class AuthorSortEdit(EnLineEdit):
|
||||
self.setToolTip(tt)
|
||||
self.setWhatsThis(tt)
|
||||
|
||||
def copy_to_authors(self):
|
||||
aus = self.current_val
|
||||
if aus:
|
||||
ln, _, rest = aus.partition(',')
|
||||
if rest:
|
||||
au = rest.strip() + ' ' + ln.strip()
|
||||
self.authors_edit.current_val = [au]
|
||||
|
||||
def auto_generate(self, *args):
|
||||
au = unicode(self.authors_edit.text())
|
||||
au = re.sub(r'\s+et al\.$', '', au)
|
||||
|
@ -13,7 +13,7 @@ from functools import partial
|
||||
from PyQt4.Qt import (Qt, QVBoxLayout, QHBoxLayout, QWidget, QPushButton,
|
||||
QGridLayout, pyqtSignal, QDialogButtonBox, QScrollArea, QFont,
|
||||
QTabWidget, QIcon, QToolButton, QSplitter, QGroupBox, QSpacerItem,
|
||||
QSizePolicy, QPalette, QFrame, QSize, QKeySequence)
|
||||
QSizePolicy, QPalette, QFrame, QSize, QKeySequence, QMenu)
|
||||
|
||||
from calibre.ebooks.metadata import authors_to_string, string_to_authors
|
||||
from calibre.gui2 import ResizableDialog, error_dialog, gprefs, pixmap_to_data
|
||||
@ -102,15 +102,19 @@ class MetadataSingleDialogBase(ResizableDialog):
|
||||
self.deduce_title_sort_button)
|
||||
self.basic_metadata_widgets.extend([self.title, self.title_sort])
|
||||
|
||||
self.authors = AuthorsEdit(self)
|
||||
self.deduce_author_sort_button = QToolButton(self)
|
||||
self.deduce_author_sort_button.setToolTip(_(
|
||||
self.deduce_author_sort_button = b = QToolButton(self)
|
||||
b.setToolTip(_(
|
||||
'Automatically create the author sort entry based on the current'
|
||||
' author entry.\n'
|
||||
'Using this button to create author sort will change author sort from'
|
||||
' red to green.'))
|
||||
self.author_sort = AuthorSortEdit(self, self.authors,
|
||||
self.deduce_author_sort_button, self.db)
|
||||
b.m = m = QMenu()
|
||||
ac = m.addAction(QIcon(I('forward.png')), _('Set author sort from author'))
|
||||
ac2 = m.addAction(QIcon(I('back.png')), _('Set author from author sort'))
|
||||
b.setMenu(m)
|
||||
self.authors = AuthorsEdit(self)
|
||||
self.author_sort = AuthorSortEdit(self, self.authors, b, self.db, ac,
|
||||
ac2)
|
||||
self.basic_metadata_widgets.extend([self.authors, self.author_sort])
|
||||
|
||||
self.swap_title_author_button = QToolButton(self)
|
||||
|
@ -319,9 +319,12 @@ def show_config_widget(category, name, gui=None, show_restart_msg=False,
|
||||
:return: True iff a restart is required for the changes made by the user to
|
||||
take effect
|
||||
'''
|
||||
from calibre.gui2 import gprefs
|
||||
pl = get_plugin(category, name)
|
||||
d = ConfigDialog(parent)
|
||||
d.resize(750, 550)
|
||||
conf_name = 'config_widget_dialog_geometry_%s_%s'%(category, name)
|
||||
geom = gprefs.get(conf_name, None)
|
||||
d.setWindowTitle(_('Configure ') + name)
|
||||
d.setWindowIcon(QIcon(I('config.png')))
|
||||
bb = QDialogButtonBox(d)
|
||||
@ -345,7 +348,11 @@ def show_config_widget(category, name, gui=None, show_restart_msg=False,
|
||||
mygui = True
|
||||
w.genesis(gui)
|
||||
w.initialize()
|
||||
if geom is not None:
|
||||
d.restoreGeometry(geom)
|
||||
d.exec_()
|
||||
geom = bytearray(d.saveGeometry())
|
||||
gprefs[conf_name] = geom
|
||||
rr = getattr(d, 'restart_required', False)
|
||||
if show_restart_msg and rr:
|
||||
from calibre.gui2 import warning_dialog
|
||||
|
@ -364,7 +364,6 @@ class SearchBoxMixin(object): # {{{
|
||||
unicode(self.search.toolTip())))
|
||||
self.advanced_search_button.setStatusTip(self.advanced_search_button.toolTip())
|
||||
self.clear_button.setStatusTip(self.clear_button.toolTip())
|
||||
self.search_options_button.clicked.connect(self.search_options_button_clicked)
|
||||
self.set_highlight_only_button_icon()
|
||||
self.highlight_only_button.clicked.connect(self.highlight_only_clicked)
|
||||
tt = _('Enable or disable search highlighting.') + '<br><br>'
|
||||
@ -374,6 +373,8 @@ class SearchBoxMixin(object): # {{{
|
||||
def highlight_only_clicked(self, state):
|
||||
config['highlight_search_matches'] = not config['highlight_search_matches']
|
||||
self.set_highlight_only_button_icon()
|
||||
self.search.do_search()
|
||||
self.focus_to_library()
|
||||
|
||||
def set_highlight_only_button_icon(self):
|
||||
if config['highlight_search_matches']:
|
||||
@ -404,10 +405,6 @@ class SearchBoxMixin(object): # {{{
|
||||
self.search.do_search()
|
||||
self.focus_to_library()
|
||||
|
||||
def search_options_button_clicked(self):
|
||||
self.iactions['Preferences'].do_config(initial_plugin=('Interface',
|
||||
'Search'), close_after_initial=True)
|
||||
|
||||
def focus_to_library(self):
|
||||
self.current_view().setFocus(Qt.OtherFocusReason)
|
||||
|
||||
|
@ -6,7 +6,6 @@ __license__ = 'GPL 3'
|
||||
__copyright__ = '2011, John Schember <john@nachtimwald.com>'
|
||||
__docformat__ = 'restructuredtext en'
|
||||
|
||||
import re
|
||||
import urllib2
|
||||
from contextlib import closing
|
||||
|
||||
|
@ -13,9 +13,8 @@ from random import shuffle
|
||||
from threading import Thread
|
||||
from Queue import Queue
|
||||
|
||||
from PyQt4.Qt import Qt, QAbstractItemModel, QDialog, QTimer, QVariant, \
|
||||
QModelIndex, QPixmap, QSize, QCheckBox, QVBoxLayout, QHBoxLayout, \
|
||||
QPushButton, QString, QByteArray
|
||||
from PyQt4.Qt import (Qt, QAbstractItemModel, QDialog, QTimer, QVariant,
|
||||
QModelIndex, QPixmap, QSize, QCheckBox, QVBoxLayout)
|
||||
|
||||
from calibre import browser
|
||||
from calibre.gui2 import NONE
|
||||
|
@ -9,8 +9,8 @@ __docformat__ = 'restructuredtext en'
|
||||
import os
|
||||
from urlparse import urlparse
|
||||
|
||||
from PyQt4.Qt import QWebView, QWebPage, QNetworkCookieJar, QNetworkRequest, QString, \
|
||||
QFileDialog, QNetworkProxy
|
||||
from PyQt4.Qt import (QWebView, QWebPage, QNetworkCookieJar,
|
||||
QFileDialog, QNetworkProxy)
|
||||
|
||||
from calibre import USER_AGENT, get_proxies, get_download_filename
|
||||
from calibre.ebooks import BOOK_EXTENSIONS
|
||||
|
@ -15,7 +15,7 @@ from functools import partial
|
||||
from PyQt4.Qt import (Qt, QTreeView, QApplication, pyqtSignal, QFont, QSize,
|
||||
QIcon, QPoint, QVBoxLayout, QHBoxLayout, QComboBox, QTimer,
|
||||
QAbstractItemModel, QVariant, QModelIndex, QMenu, QFrame,
|
||||
QWidget, QItemDelegate, QString, QLabel,
|
||||
QWidget, QItemDelegate, QString, QLabel, QPushButton,
|
||||
QShortcut, QKeySequence, SIGNAL, QMimeData, QToolButton)
|
||||
|
||||
from calibre.ebooks.metadata import title_sort
|
||||
@ -1809,9 +1809,6 @@ class TagsModel(QAbstractItemModel): # {{{
|
||||
|
||||
# }}}
|
||||
|
||||
category_managers = (
|
||||
)
|
||||
|
||||
class TagBrowserMixin(object): # {{{
|
||||
|
||||
def __init__(self, db):
|
||||
@ -1833,20 +1830,23 @@ class TagBrowserMixin(object): # {{{
|
||||
self.tags_view.restriction_error.connect(self.do_restriction_error,
|
||||
type=Qt.QueuedConnection)
|
||||
|
||||
for text, func, args in (
|
||||
(_('Manage Authors'), self.do_author_sort_edit, (self,
|
||||
None)),
|
||||
(_('Manage Series'), self.do_tags_list_edit, (None,
|
||||
'series')),
|
||||
(_('Manage Publishers'), self.do_tags_list_edit, (None,
|
||||
'publisher')),
|
||||
(_('Manage Tags'), self.do_tags_list_edit, (None, 'tags')),
|
||||
for text, func, args, cat_name in (
|
||||
(_('Manage Authors'),
|
||||
self.do_author_sort_edit, (self, None), 'authors'),
|
||||
(_('Manage Series'),
|
||||
self.do_tags_list_edit, (None, 'series'), 'series'),
|
||||
(_('Manage Publishers'),
|
||||
self.do_tags_list_edit, (None, 'publisher'), 'publisher'),
|
||||
(_('Manage Tags'),
|
||||
self.do_tags_list_edit, (None, 'tags'), 'tags'),
|
||||
(_('Manage User Categories'),
|
||||
self.do_edit_user_categories, (None,)),
|
||||
(_('Manage Saved Searches'), self.do_saved_search_edit,
|
||||
(None,))
|
||||
self.do_edit_user_categories, (None,), 'user:'),
|
||||
(_('Manage Saved Searches'),
|
||||
self.do_saved_search_edit, (None,), 'search')
|
||||
):
|
||||
self.manage_items_button.menu().addAction(text, partial(func, *args))
|
||||
self.manage_items_button.menu().addAction(
|
||||
QIcon(I(category_icon_map[cat_name])),
|
||||
text, partial(func, *args))
|
||||
|
||||
def do_restriction_error(self):
|
||||
error_dialog(self.tags_view, _('Invalid search restriction'),
|
||||
@ -2166,11 +2166,9 @@ class TagBrowserWidget(QWidget): # {{{
|
||||
parent.tag_match.setStatusTip(parent.tag_match.toolTip())
|
||||
|
||||
|
||||
l = parent.manage_items_button = QToolButton(self)
|
||||
l.setIcon(QIcon(I('tags.png')))
|
||||
l = parent.manage_items_button = QPushButton(self)
|
||||
l.setStyleSheet('QPushButton {text-align: left; }')
|
||||
l.setText(_('Manage authors, tags, etc'))
|
||||
l.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
|
||||
l.setPopupMode(l.InstantPopup)
|
||||
l.setToolTip(_('All of these category_managers are available by right-clicking '
|
||||
'on items in the tag browser above'))
|
||||
l.m = QMenu()
|
||||
|
@ -529,10 +529,10 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
||||
action.location_selected(location)
|
||||
if location == 'library':
|
||||
self.search_restriction.setEnabled(True)
|
||||
self.search_options_button.setEnabled(True)
|
||||
self.highlight_only_button.setEnabled(True)
|
||||
else:
|
||||
self.search_restriction.setEnabled(False)
|
||||
self.search_options_button.setEnabled(False)
|
||||
self.highlight_only_button.setEnabled(False)
|
||||
# Reset the view in case something changed while it was invisible
|
||||
self.current_view().reset()
|
||||
self.set_number_of_books_shown()
|
||||
|
@ -426,7 +426,7 @@ def do_show_metadata(db, id, as_opf):
|
||||
mi = OPFCreator(os.getcwd(), mi)
|
||||
mi.render(sys.stdout)
|
||||
else:
|
||||
print unicode(mi).encode(preferred_encoding)
|
||||
prints(unicode(mi))
|
||||
|
||||
def show_metadata_option_parser():
|
||||
parser = get_parser(_(
|
||||
|
@ -854,7 +854,6 @@ class LibraryDatabase2(LibraryDatabase, SchemaUpgrade, CustomColumns):
|
||||
mi.uuid = row[fm['uuid']]
|
||||
mi.title_sort = row[fm['sort']]
|
||||
mi.last_modified = row[fm['last_modified']]
|
||||
mi.size = row[fm['size']]
|
||||
formats = row[fm['formats']]
|
||||
if not formats:
|
||||
formats = None
|
||||
|
Loading…
x
Reference in New Issue
Block a user