mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
More removal anf QVariant. Also fix PyQt5 multiple inheritance problem with QMainWindow for main calibre gui
This commit is contained in:
parent
1c01665fe7
commit
a5dc23ae0f
@ -51,6 +51,8 @@ def detect_qvariant():
|
|||||||
pat = re.compile(b'|'.join(br'QVariant NONE toDateTime toDate toInt toBool toString\(\) toPyObject canConvert toBitArray toByteArray toHash toFloat toMap toLine toPoint toReal toRect toTime toUInt toUrl'.split())) # noqa
|
pat = re.compile(b'|'.join(br'QVariant NONE toDateTime toDate toInt toBool toString\(\) toPyObject canConvert toBitArray toByteArray toHash toFloat toMap toLine toPoint toReal toRect toTime toUInt toUrl'.split())) # noqa
|
||||||
exclusions = {
|
exclusions = {
|
||||||
'src/calibre/gui2/viewer/gestures.py': {'toPoint'},
|
'src/calibre/gui2/viewer/gestures.py': {'toPoint'},
|
||||||
|
'src/calibre/utils/serve_coffee.py': {'toString()'},
|
||||||
|
'src/calibre/gui2/job_indicator.py': {'toPoint'},
|
||||||
}
|
}
|
||||||
for path in all_py_files():
|
for path in all_py_files():
|
||||||
if os.path.basename(path) in {
|
if os.path.basename(path) in {
|
||||||
|
@ -146,7 +146,7 @@ def _config(): # {{{
|
|||||||
c.add_opt('confirm_delete', default=False,
|
c.add_opt('confirm_delete', default=False,
|
||||||
help=_('Confirm before deleting'))
|
help=_('Confirm before deleting'))
|
||||||
c.add_opt('main_window_geometry', default=None,
|
c.add_opt('main_window_geometry', default=None,
|
||||||
help=_('Main window geometry')) # value QVariant.toByteArray
|
help=_('Main window geometry'))
|
||||||
c.add_opt('new_version_notification', default=True,
|
c.add_opt('new_version_notification', default=True,
|
||||||
help=_('Notify when a new version is available'))
|
help=_('Notify when a new version is available'))
|
||||||
c.add_opt('use_roman_numerals_for_series_number', default=True,
|
c.add_opt('use_roman_numerals_for_series_number', default=True,
|
||||||
|
@ -325,7 +325,7 @@ class BookInfo(QWebView):
|
|||||||
self._link_clicked = True
|
self._link_clicked = True
|
||||||
if unicode(link.scheme()) in ('http', 'https'):
|
if unicode(link.scheme()) in ('http', 'https'):
|
||||||
return open_url(link)
|
return open_url(link)
|
||||||
link = unicode(link.toString())
|
link = unicode(link.toString(QUrl.None))
|
||||||
self.link_clicked.emit(link)
|
self.link_clicked.emit(link)
|
||||||
|
|
||||||
def turnoff_scrollbar(self, *args):
|
def turnoff_scrollbar(self, *args):
|
||||||
@ -349,7 +349,7 @@ class BookInfo(QWebView):
|
|||||||
p = self.page()
|
p = self.page()
|
||||||
mf = p.mainFrame()
|
mf = p.mainFrame()
|
||||||
r = mf.hitTestContent(ev.pos())
|
r = mf.hitTestContent(ev.pos())
|
||||||
url = unicode(r.linkUrl().toString()).strip()
|
url = unicode(r.linkUrl().toString(QUrl.None)).strip()
|
||||||
menu = p.createStandardContextMenu()
|
menu = p.createStandardContextMenu()
|
||||||
ca = self.pageAction(p.Copy)
|
ca = self.pageAction(p.Copy)
|
||||||
for action in list(menu.actions()):
|
for action in list(menu.actions()):
|
||||||
|
@ -211,7 +211,7 @@ class EditorWidget(QWebView): # {{{
|
|||||||
return
|
return
|
||||||
url = self.parse_link(link)
|
url = self.parse_link(link)
|
||||||
if url.isValid():
|
if url.isValid():
|
||||||
url = unicode(url.toString())
|
url = unicode(url.toString(QUrl.None))
|
||||||
self.setFocus(Qt.OtherFocusReason)
|
self.setFocus(Qt.OtherFocusReason)
|
||||||
if is_image:
|
if is_image:
|
||||||
self.exec_command('insertHTML',
|
self.exec_command('insertHTML',
|
||||||
|
@ -1,213 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
|
||||||
|
|
||||||
__license__ = 'GPL v3'
|
|
||||||
__copyright__ = '2011, Kovid Goyal <kovid@kovidgoyal.net>'
|
|
||||||
__docformat__ = 'restructuredtext en'
|
|
||||||
|
|
||||||
'''
|
|
||||||
WARNING: The code in this module is deprecated. Use complete2.py instead. This
|
|
||||||
code remains here for legacy plugin support.
|
|
||||||
'''
|
|
||||||
|
|
||||||
from PyQt5.Qt import (QLineEdit, QAbstractListModel, Qt,
|
|
||||||
QApplication, QCompleter)
|
|
||||||
|
|
||||||
from calibre.utils.icu import sort_key
|
|
||||||
from calibre.gui2 import NONE
|
|
||||||
from calibre.gui2.widgets import EnComboBox, LineEditECM
|
|
||||||
|
|
||||||
class CompleteModel(QAbstractListModel):
|
|
||||||
|
|
||||||
def __init__(self, parent=None):
|
|
||||||
QAbstractListModel.__init__(self, parent)
|
|
||||||
self.items = []
|
|
||||||
self.sorting = QCompleter.UnsortedModel
|
|
||||||
|
|
||||||
def set_items(self, items):
|
|
||||||
items = [unicode(x.strip()) for x in items]
|
|
||||||
self.beginResetModel()
|
|
||||||
if len(items) < 2500:
|
|
||||||
self.items = sorted(items, key=sort_key)
|
|
||||||
self.sorting = QCompleter.UnsortedModel
|
|
||||||
else:
|
|
||||||
self.items = sorted(items, key=lambda x:x.lower())
|
|
||||||
self.sorting = QCompleter.CaseInsensitivelySortedModel
|
|
||||||
self.endResetModel()
|
|
||||||
|
|
||||||
def rowCount(self, *args):
|
|
||||||
return len(self.items)
|
|
||||||
|
|
||||||
def data(self, index, role):
|
|
||||||
if role == Qt.DisplayRole:
|
|
||||||
r = index.row()
|
|
||||||
try:
|
|
||||||
return self.items[r]
|
|
||||||
except IndexError:
|
|
||||||
pass
|
|
||||||
return NONE
|
|
||||||
|
|
||||||
|
|
||||||
class MultiCompleteLineEdit(QLineEdit, LineEditECM):
|
|
||||||
'''
|
|
||||||
A line edit that completes on multiple items separated by a
|
|
||||||
separator. Use the :meth:`update_items_cache` to set the list of
|
|
||||||
all possible completions. Separator can be controlled with the
|
|
||||||
:meth:`set_separator` and :meth:`set_space_before_sep` methods.
|
|
||||||
|
|
||||||
A call to self.set_separator(None) will allow this widget to be used
|
|
||||||
to complete non multiple fields as well.
|
|
||||||
'''
|
|
||||||
|
|
||||||
def __init__(self, parent=None, completer_widget=None):
|
|
||||||
QLineEdit.__init__(self, parent)
|
|
||||||
|
|
||||||
self.sep = ','
|
|
||||||
self.space_before_sep = False
|
|
||||||
self.add_separator = True
|
|
||||||
self.original_cursor_pos = None
|
|
||||||
|
|
||||||
self._model = CompleteModel(parent=self)
|
|
||||||
self._completer = c = QCompleter(self._model, self)
|
|
||||||
c.setWidget(self if completer_widget is None else completer_widget)
|
|
||||||
c.setCompletionMode(QCompleter.PopupCompletion)
|
|
||||||
c.setCaseSensitivity(Qt.CaseInsensitive)
|
|
||||||
c.setModelSorting(self._model.sorting)
|
|
||||||
c.setCompletionRole(Qt.DisplayRole)
|
|
||||||
p = c.popup()
|
|
||||||
p.setMouseTracking(True)
|
|
||||||
p.entered.connect(self.item_entered)
|
|
||||||
c.popup().setAlternatingRowColors(True)
|
|
||||||
|
|
||||||
c.activated.connect(self.completion_selected,
|
|
||||||
type=Qt.QueuedConnection)
|
|
||||||
self.textEdited.connect(self.text_edited)
|
|
||||||
|
|
||||||
# Interface {{{
|
|
||||||
def update_items_cache(self, complete_items):
|
|
||||||
self.all_items = complete_items
|
|
||||||
|
|
||||||
def set_separator(self, sep):
|
|
||||||
self.sep = sep
|
|
||||||
|
|
||||||
def set_space_before_sep(self, space_before):
|
|
||||||
self.space_before_sep = space_before
|
|
||||||
|
|
||||||
def set_add_separator(self, what):
|
|
||||||
self.add_separator = bool(what)
|
|
||||||
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
def item_entered(self, idx):
|
|
||||||
self._completer.popup().setCurrentIndex(idx)
|
|
||||||
|
|
||||||
def text_edited(self, *args):
|
|
||||||
self.update_completions()
|
|
||||||
self._completer.complete()
|
|
||||||
|
|
||||||
def update_completions(self):
|
|
||||||
' Update the list of completions '
|
|
||||||
self.original_cursor_pos = cpos = self.cursorPosition()
|
|
||||||
text = unicode(self.text())
|
|
||||||
prefix = text[:cpos]
|
|
||||||
self.current_prefix = prefix
|
|
||||||
complete_prefix = prefix.lstrip()
|
|
||||||
if self.sep:
|
|
||||||
complete_prefix = prefix.split(self.sep)[-1].lstrip()
|
|
||||||
self._completer.setCompletionPrefix(complete_prefix)
|
|
||||||
|
|
||||||
def get_completed_text(self, text):
|
|
||||||
'Get completed text in before and after parts'
|
|
||||||
if self.sep is None:
|
|
||||||
return text, ''
|
|
||||||
else:
|
|
||||||
cursor_pos = self.original_cursor_pos
|
|
||||||
if cursor_pos is None:
|
|
||||||
cursor_pos = self.cursorPosition()
|
|
||||||
self.original_cursor_pos = None
|
|
||||||
# Split text
|
|
||||||
curtext = unicode(self.text())
|
|
||||||
before_text = curtext[:cursor_pos]
|
|
||||||
after_text = curtext[cursor_pos:].rstrip()
|
|
||||||
# Remove the completion prefix from the before text
|
|
||||||
before_text = self.sep.join(before_text.split(self.sep)[:-1]).rstrip()
|
|
||||||
if before_text:
|
|
||||||
# Add the separator to the end of before_text
|
|
||||||
if self.space_before_sep:
|
|
||||||
before_text += ' '
|
|
||||||
before_text += self.sep + ' '
|
|
||||||
if self.add_separator or after_text:
|
|
||||||
# Add separator to the end of completed text
|
|
||||||
if self.space_before_sep:
|
|
||||||
text = text.rstrip() + ' '
|
|
||||||
completed_text = text + self.sep + ' '
|
|
||||||
else:
|
|
||||||
completed_text = text
|
|
||||||
return before_text + completed_text, after_text
|
|
||||||
|
|
||||||
def completion_selected(self, text):
|
|
||||||
before_text, after_text = self.get_completed_text(unicode(text))
|
|
||||||
self.setText(before_text + after_text)
|
|
||||||
self.setCursorPosition(len(before_text))
|
|
||||||
|
|
||||||
@dynamic_property
|
|
||||||
def all_items(self):
|
|
||||||
def fget(self):
|
|
||||||
return self._model.items
|
|
||||||
def fset(self, items):
|
|
||||||
self._model.set_items(items)
|
|
||||||
self._completer.setModelSorting(self._model.sorting)
|
|
||||||
return property(fget=fget, fset=fset)
|
|
||||||
|
|
||||||
class MultiCompleteComboBox(EnComboBox):
|
|
||||||
|
|
||||||
def __init__(self, *args):
|
|
||||||
EnComboBox.__init__(self, *args)
|
|
||||||
self.le = MultiCompleteLineEdit(self, completer_widget=self)
|
|
||||||
self.setLineEdit(self.le)
|
|
||||||
|
|
||||||
def showPopup(self):
|
|
||||||
c = self.le._completer
|
|
||||||
v = c.currentCompletion()
|
|
||||||
c.setCompletionPrefix('')
|
|
||||||
c.complete()
|
|
||||||
cs = c.caseSensitivity()
|
|
||||||
i = 0
|
|
||||||
while c.setCurrentRow(i):
|
|
||||||
cr = c.currentIndex().data().toString()
|
|
||||||
if cr.startsWith(v, cs):
|
|
||||||
c.popup().setCurrentIndex(c.currentIndex())
|
|
||||||
return
|
|
||||||
i += 1
|
|
||||||
c.setCurrentRow(0)
|
|
||||||
|
|
||||||
def update_items_cache(self, complete_items):
|
|
||||||
self.lineEdit().update_items_cache(complete_items)
|
|
||||||
|
|
||||||
def set_separator(self, sep):
|
|
||||||
self.lineEdit().set_separator(sep)
|
|
||||||
|
|
||||||
def set_space_before_sep(self, space_before):
|
|
||||||
self.lineEdit().set_space_before_sep(space_before)
|
|
||||||
|
|
||||||
def set_add_separator(self, what):
|
|
||||||
self.lineEdit().set_add_separator(what)
|
|
||||||
|
|
||||||
def show_initial_value(self, what):
|
|
||||||
what = unicode(what) if what else u''
|
|
||||||
le = self.lineEdit()
|
|
||||||
self.setEditText(what)
|
|
||||||
le.selectAll()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
from PyQt5.Qt import QDialog, QVBoxLayout
|
|
||||||
app = QApplication([])
|
|
||||||
d = QDialog()
|
|
||||||
d.setLayout(QVBoxLayout())
|
|
||||||
le = MultiCompleteComboBox(d)
|
|
||||||
d.layout().addWidget(le)
|
|
||||||
items = ['one', 'otwo', 'othree', 'ooone', 'ootwo',
|
|
||||||
'oothree']
|
|
||||||
le.update_items_cache(items)
|
|
||||||
le.show_initial_value('')
|
|
||||||
d.exec_()
|
|
@ -6,11 +6,10 @@ __license__ = 'GPL v3'
|
|||||||
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
__copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
from PyQt5.Qt import Qt, QAbstractListModel, QVariant, QModelIndex
|
from PyQt5.Qt import Qt, QAbstractListModel, QModelIndex
|
||||||
|
|
||||||
from calibre.gui2.convert.page_setup_ui import Ui_Form
|
from calibre.gui2.convert.page_setup_ui import Ui_Form
|
||||||
from calibre.gui2.convert import Widget
|
from calibre.gui2.convert import Widget
|
||||||
from calibre.gui2 import NONE
|
|
||||||
from calibre.customize.ui import input_profiles, output_profiles
|
from calibre.customize.ui import input_profiles, output_profiles
|
||||||
|
|
||||||
class ProfileModel(QAbstractListModel):
|
class ProfileModel(QAbstractListModel):
|
||||||
@ -25,7 +24,7 @@ class ProfileModel(QAbstractListModel):
|
|||||||
def data(self, index, role):
|
def data(self, index, role):
|
||||||
profile = self.profiles[index.row()]
|
profile = self.profiles[index.row()]
|
||||||
if role == Qt.DisplayRole:
|
if role == Qt.DisplayRole:
|
||||||
return QVariant(profile.name)
|
return (profile.name)
|
||||||
if role in (Qt.ToolTipRole, Qt.StatusTipRole, Qt.WhatsThisRole):
|
if role in (Qt.ToolTipRole, Qt.StatusTipRole, Qt.WhatsThisRole):
|
||||||
w, h = profile.screen_size
|
w, h = profile.screen_size
|
||||||
if w >= 10000:
|
if w >= 10000:
|
||||||
@ -33,8 +32,8 @@ class ProfileModel(QAbstractListModel):
|
|||||||
else:
|
else:
|
||||||
ss = _('%(width)d x %(height)d pixels') % dict(width=w, height=h)
|
ss = _('%(width)d x %(height)d pixels') % dict(width=w, height=h)
|
||||||
ss = _('Screen size: %s') % ss
|
ss = _('Screen size: %s') % ss
|
||||||
return QVariant('%s [%s]' % (profile.description, ss))
|
return ('%s [%s]' % (profile.description, ss))
|
||||||
return NONE
|
return None
|
||||||
|
|
||||||
class PageSetupWidget(Widget, Ui_Form):
|
class PageSetupWidget(Widget, Ui_Form):
|
||||||
|
|
||||||
|
@ -8,9 +8,9 @@ __docformat__ = 'restructuredtext en'
|
|||||||
|
|
||||||
import cPickle, shutil
|
import cPickle, shutil
|
||||||
|
|
||||||
from PyQt5.Qt import QAbstractListModel, Qt, QVariant, QFont, QModelIndex
|
from PyQt5.Qt import QAbstractListModel, Qt, QFont, QModelIndex
|
||||||
|
|
||||||
from calibre.gui2 import ResizableDialog, NONE, gprefs
|
from calibre.gui2 import ResizableDialog, gprefs
|
||||||
from calibre.ebooks.conversion.config import (GuiRecommendations, save_specifics,
|
from calibre.ebooks.conversion.config import (GuiRecommendations, save_specifics,
|
||||||
load_specifics)
|
load_specifics)
|
||||||
from calibre.gui2.convert.single_ui import Ui_Dialog
|
from calibre.gui2.convert.single_ui import Ui_Dialog
|
||||||
@ -75,16 +75,16 @@ class GroupModel(QAbstractListModel):
|
|||||||
try:
|
try:
|
||||||
widget = self.widgets[index.row()]
|
widget = self.widgets[index.row()]
|
||||||
except:
|
except:
|
||||||
return NONE
|
return None
|
||||||
if role == Qt.DisplayRole:
|
if role == Qt.DisplayRole:
|
||||||
return QVariant(widget.config_title())
|
return (widget.config_title())
|
||||||
if role == Qt.DecorationRole:
|
if role == Qt.DecorationRole:
|
||||||
return QVariant(widget.config_icon())
|
return (widget.config_icon())
|
||||||
if role == Qt.FontRole:
|
if role == Qt.FontRole:
|
||||||
f = QFont()
|
f = QFont()
|
||||||
f.setBold(True)
|
f.setBold(True)
|
||||||
return QVariant(f)
|
return (f)
|
||||||
return NONE
|
return None
|
||||||
|
|
||||||
def get_preferred_input_format_for_book(db, book_id):
|
def get_preferred_input_format_for_book(db, book_id):
|
||||||
recs = load_specifics(db, book_id)
|
recs = load_specifics(db, book_id)
|
||||||
|
@ -237,7 +237,10 @@ class CBDialog(QDialog):
|
|||||||
|
|
||||||
class CoverFlowMixin(object):
|
class CoverFlowMixin(object):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def init_cover_flow_mixin(self):
|
||||||
self.cover_flow = None
|
self.cover_flow = None
|
||||||
if CoverFlow is not None:
|
if CoverFlow is not None:
|
||||||
self.cf_last_updated_at = None
|
self.cf_last_updated_at = None
|
||||||
|
@ -861,7 +861,10 @@ device_signals = DeviceSignals()
|
|||||||
|
|
||||||
class DeviceMixin(object): # {{{
|
class DeviceMixin(object): # {{{
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def init_device_mixin(self):
|
||||||
self.device_error_dialog = error_dialog(self, _('Error'),
|
self.device_error_dialog = error_dialog(self, _('Error'),
|
||||||
_('Error communicating with device'), ' ')
|
_('Error communicating with device'), ' ')
|
||||||
self.device_error_dialog.setModal(Qt.NonModal)
|
self.device_error_dialog.setModal(Qt.NonModal)
|
||||||
|
@ -11,7 +11,7 @@ import re, datetime, traceback
|
|||||||
from lxml import html
|
from lxml import html
|
||||||
from PyQt5.Qt import (Qt, QUrl, QFrame, QVBoxLayout, QLabel, QBrush, QTextEdit,
|
from PyQt5.Qt import (Qt, QUrl, QFrame, QVBoxLayout, QLabel, QBrush, QTextEdit,
|
||||||
QComboBox, QAbstractItemView, QHBoxLayout, QDialogButtonBox,
|
QComboBox, QAbstractItemView, QHBoxLayout, QDialogButtonBox,
|
||||||
QAbstractTableModel, QVariant, QTableView, QModelIndex,
|
QAbstractTableModel, QTableView, QModelIndex,
|
||||||
QSortFilterProxyModel, QAction, QIcon, QDialog,
|
QSortFilterProxyModel, QAction, QIcon, QDialog,
|
||||||
QFont, QPixmap, QSize, QLineEdit)
|
QFont, QPixmap, QSize, QLineEdit)
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ from calibre.constants import numeric_version, iswindows, isosx, DEBUG, __appnam
|
|||||||
from calibre.customize.ui import (
|
from calibre.customize.ui import (
|
||||||
initialized_plugins, is_disabled, remove_plugin, add_plugin, enable_plugin, disable_plugin,
|
initialized_plugins, is_disabled, remove_plugin, add_plugin, enable_plugin, disable_plugin,
|
||||||
NameConflict, has_external_plugins)
|
NameConflict, has_external_plugins)
|
||||||
from calibre.gui2 import error_dialog, question_dialog, info_dialog, NONE, open_url, gprefs
|
from calibre.gui2 import error_dialog, question_dialog, info_dialog, open_url, gprefs
|
||||||
from calibre.gui2.preferences.plugins import ConfigWidget
|
from calibre.gui2.preferences.plugins import ConfigWidget
|
||||||
from calibre.utils.date import UNDEFINED_DATE, format_date
|
from calibre.utils.date import UNDEFINED_DATE, format_date
|
||||||
|
|
||||||
@ -270,7 +270,7 @@ class DisplayPluginModel(QAbstractTableModel):
|
|||||||
def __init__(self, display_plugins):
|
def __init__(self, display_plugins):
|
||||||
QAbstractTableModel.__init__(self)
|
QAbstractTableModel.__init__(self)
|
||||||
self.display_plugins = display_plugins
|
self.display_plugins = display_plugins
|
||||||
self.headers = map(QVariant, [_('Plugin Name'), _('Donate'), _('Status'), _('Installed'),
|
self.headers = map(unicode, [_('Plugin Name'), _('Donate'), _('Status'), _('Installed'),
|
||||||
_('Available'), _('Released'), _('Calibre'), _('Author')])
|
_('Available'), _('Released'), _('Calibre'), _('Author')])
|
||||||
|
|
||||||
def rowCount(self, *args):
|
def rowCount(self, *args):
|
||||||
@ -282,36 +282,36 @@ class DisplayPluginModel(QAbstractTableModel):
|
|||||||
def headerData(self, section, orientation, role):
|
def headerData(self, section, orientation, role):
|
||||||
if role == Qt.DisplayRole and orientation == Qt.Horizontal:
|
if role == Qt.DisplayRole and orientation == Qt.Horizontal:
|
||||||
return self.headers[section]
|
return self.headers[section]
|
||||||
return NONE
|
return None
|
||||||
|
|
||||||
def data(self, index, role):
|
def data(self, index, role):
|
||||||
if not index.isValid():
|
if not index.isValid():
|
||||||
return NONE
|
return None
|
||||||
row, col = index.row(), index.column()
|
row, col = index.row(), index.column()
|
||||||
if row < 0 or row >= self.rowCount():
|
if row < 0 or row >= self.rowCount():
|
||||||
return NONE
|
return None
|
||||||
display_plugin = self.display_plugins[row]
|
display_plugin = self.display_plugins[row]
|
||||||
if role in [Qt.DisplayRole, Qt.UserRole]:
|
if role in [Qt.DisplayRole, Qt.UserRole]:
|
||||||
if col == 0:
|
if col == 0:
|
||||||
return QVariant(display_plugin.name)
|
return display_plugin.name
|
||||||
if col == 1:
|
if col == 1:
|
||||||
if display_plugin.donation_link:
|
if display_plugin.donation_link:
|
||||||
return QVariant(_('PayPal'))
|
return _('PayPal')
|
||||||
if col == 2:
|
if col == 2:
|
||||||
return self._get_status(display_plugin)
|
return self._get_status(display_plugin)
|
||||||
if col == 3:
|
if col == 3:
|
||||||
return QVariant(self._get_display_version(display_plugin.installed_version))
|
return self._get_display_version(display_plugin.installed_version)
|
||||||
if col == 4:
|
if col == 4:
|
||||||
return QVariant(self._get_display_version(display_plugin.available_version))
|
return self._get_display_version(display_plugin.available_version)
|
||||||
if col == 5:
|
if col == 5:
|
||||||
if role == Qt.UserRole:
|
if role == Qt.UserRole:
|
||||||
return self._get_display_release_date(display_plugin.release_date, 'yyyyMMdd')
|
return self._get_display_release_date(display_plugin.release_date, 'yyyyMMdd')
|
||||||
else:
|
else:
|
||||||
return self._get_display_release_date(display_plugin.release_date)
|
return self._get_display_release_date(display_plugin.release_date)
|
||||||
if col == 6:
|
if col == 6:
|
||||||
return QVariant(self._get_display_version(display_plugin.calibre_required_version))
|
return self._get_display_version(display_plugin.calibre_required_version)
|
||||||
if col == 7:
|
if col == 7:
|
||||||
return QVariant(display_plugin.author)
|
return display_plugin.author
|
||||||
elif role == Qt.DecorationRole:
|
elif role == Qt.DecorationRole:
|
||||||
if col == 0:
|
if col == 0:
|
||||||
return self._get_status_icon(display_plugin)
|
return self._get_status_icon(display_plugin)
|
||||||
@ -320,18 +320,18 @@ class DisplayPluginModel(QAbstractTableModel):
|
|||||||
return QIcon(I('donate.png'))
|
return QIcon(I('donate.png'))
|
||||||
elif role == Qt.ToolTipRole:
|
elif role == Qt.ToolTipRole:
|
||||||
if col == 1 and display_plugin.donation_link:
|
if col == 1 and display_plugin.donation_link:
|
||||||
return QVariant(_('This plugin is FREE but you can reward the developer for their effort\n'
|
return _('This plugin is FREE but you can reward the developer for their effort\n'
|
||||||
'by donating to them via PayPal.\n\n'
|
'by donating to them via PayPal.\n\n'
|
||||||
'Right-click and choose Donate to reward: ')+display_plugin.author)
|
'Right-click and choose Donate to reward: ')+display_plugin.author
|
||||||
else:
|
else:
|
||||||
return self._get_status_tooltip(display_plugin)
|
return self._get_status_tooltip(display_plugin)
|
||||||
elif role == Qt.ForegroundRole:
|
elif role == Qt.ForegroundRole:
|
||||||
if col != 1: # Never change colour of the donation column
|
if col != 1: # Never change colour of the donation column
|
||||||
if display_plugin.is_deprecated:
|
if display_plugin.is_deprecated:
|
||||||
return QVariant(QBrush(Qt.blue))
|
return QBrush(Qt.blue)
|
||||||
if display_plugin.is_disabled():
|
if display_plugin.is_disabled():
|
||||||
return QVariant(QBrush(Qt.gray))
|
return QBrush(Qt.gray)
|
||||||
return NONE
|
return None
|
||||||
|
|
||||||
def plugin_to_index(self, display_plugin):
|
def plugin_to_index(self, display_plugin):
|
||||||
for i, p in enumerate(self.display_plugins):
|
for i, p in enumerate(self.display_plugins):
|
||||||
@ -345,8 +345,8 @@ class DisplayPluginModel(QAbstractTableModel):
|
|||||||
|
|
||||||
def _get_display_release_date(self, date_value, format='dd MMM yyyy'):
|
def _get_display_release_date(self, date_value, format='dd MMM yyyy'):
|
||||||
if date_value and date_value != UNDEFINED_DATE:
|
if date_value and date_value != UNDEFINED_DATE:
|
||||||
return QVariant(format_date(date_value, format))
|
return format_date(date_value, format)
|
||||||
return NONE
|
return None
|
||||||
|
|
||||||
def _get_display_version(self, version):
|
def _get_display_version(self, version):
|
||||||
if version is None:
|
if version is None:
|
||||||
@ -395,24 +395,24 @@ class DisplayPluginModel(QAbstractTableModel):
|
|||||||
|
|
||||||
def _get_status_tooltip(self, display_plugin):
|
def _get_status_tooltip(self, display_plugin):
|
||||||
if display_plugin.is_deprecated:
|
if display_plugin.is_deprecated:
|
||||||
return QVariant(_('This plugin has been deprecated and should be uninstalled')+'\n\n'+
|
return (_('This plugin has been deprecated and should be uninstalled')+'\n\n'+
|
||||||
_('Right-click to see more options'))
|
_('Right-click to see more options'))
|
||||||
if not display_plugin.is_valid_platform():
|
if not display_plugin.is_valid_platform():
|
||||||
return QVariant(_('This plugin can only be installed on: %s') %
|
return (_('This plugin can only be installed on: %s') %
|
||||||
', '.join(display_plugin.platforms)+'\n\n'+
|
', '.join(display_plugin.platforms)+'\n\n'+
|
||||||
_('Right-click to see more options'))
|
_('Right-click to see more options'))
|
||||||
if numeric_version < display_plugin.calibre_required_version:
|
if numeric_version < display_plugin.calibre_required_version:
|
||||||
return QVariant(_('You must upgrade to at least Calibre %s before installing this plugin') %
|
return (_('You must upgrade to at least Calibre %s before installing this plugin') %
|
||||||
self._get_display_version(display_plugin.calibre_required_version)+'\n\n'+
|
self._get_display_version(display_plugin.calibre_required_version)+'\n\n'+
|
||||||
_('Right-click to see more options'))
|
_('Right-click to see more options'))
|
||||||
if display_plugin.installed_version < display_plugin.available_version:
|
if display_plugin.installed_version < display_plugin.available_version:
|
||||||
if display_plugin.installed_version is None:
|
if display_plugin.installed_version is None:
|
||||||
return QVariant(_('You can install this plugin')+'\n\n'+
|
return (_('You can install this plugin')+'\n\n'+
|
||||||
_('Right-click to see more options'))
|
_('Right-click to see more options'))
|
||||||
else:
|
else:
|
||||||
return QVariant(_('A new version of this plugin is available')+'\n\n'+
|
return (_('A new version of this plugin is available')+'\n\n'+
|
||||||
_('Right-click to see more options'))
|
_('Right-click to see more options'))
|
||||||
return QVariant(_('This plugin is installed and up-to-date')+'\n\n'+
|
return (_('This plugin is installed and up-to-date')+'\n\n'+
|
||||||
_('Right-click to see more options'))
|
_('Right-click to see more options'))
|
||||||
|
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ from threading import Thread
|
|||||||
from Queue import Queue, Empty
|
from Queue import Queue, Empty
|
||||||
|
|
||||||
from PyQt5.Qt import QPixmap, Qt, QDialog, QLabel, QVBoxLayout, \
|
from PyQt5.Qt import QPixmap, Qt, QDialog, QLabel, QVBoxLayout, \
|
||||||
QDialogButtonBox, QProgressBar, QTimer
|
QDialogButtonBox, QProgressBar, QTimer, QUrl
|
||||||
|
|
||||||
from calibre.constants import DEBUG, iswindows
|
from calibre.constants import DEBUG, iswindows
|
||||||
from calibre.ptempfile import PersistentTemporaryFile
|
from calibre.ptempfile import PersistentTemporaryFile
|
||||||
@ -145,7 +145,7 @@ def dnd_has_extension(md, extensions):
|
|||||||
if has_firefox_ext(md, extensions):
|
if has_firefox_ext(md, extensions):
|
||||||
return True
|
return True
|
||||||
if md.hasUrls():
|
if md.hasUrls():
|
||||||
urls = [unicode(u.toString()) for u in
|
urls = [unicode(u.toString(QUrl.None)) for u in
|
||||||
md.urls()]
|
md.urls()]
|
||||||
paths = [path_from_qurl(u) for u in md.urls()]
|
paths = [path_from_qurl(u) for u in md.urls()]
|
||||||
exts = frozenset([posixpath.splitext(u)[1][1:].lower() for u in
|
exts = frozenset([posixpath.splitext(u)[1][1:].lower() for u in
|
||||||
@ -196,7 +196,7 @@ def dnd_get_image(md, image_exts=IMAGE_EXTENSIONS):
|
|||||||
|
|
||||||
# No image, look for a URL pointing to an image
|
# No image, look for a URL pointing to an image
|
||||||
if md.hasUrls():
|
if md.hasUrls():
|
||||||
urls = [unicode(u.toString()) for u in
|
urls = [unicode(u.toString(QUrl.None)) for u in
|
||||||
md.urls()]
|
md.urls()]
|
||||||
purls = [urlparse(u) for u in urls]
|
purls = [urlparse(u) for u in urls]
|
||||||
# First look for a local file
|
# First look for a local file
|
||||||
@ -243,7 +243,7 @@ def dnd_get_files(md, exts):
|
|||||||
'''
|
'''
|
||||||
# Look for a URL pointing to a file
|
# Look for a URL pointing to a file
|
||||||
if md.hasUrls():
|
if md.hasUrls():
|
||||||
urls = [unicode(u.toString()) for u in
|
urls = [unicode(u.toString(QUrl.None)) for u in
|
||||||
md.urls()]
|
md.urls()]
|
||||||
purls = [urlparse(u) for u in urls]
|
purls = [urlparse(u) for u in urls]
|
||||||
# First look for a local file
|
# First look for a local file
|
||||||
|
@ -96,6 +96,9 @@ def start_ebook_download(callback, job_manager, gui, cookie_file=None, url='', f
|
|||||||
|
|
||||||
class EbookDownloadMixin(object):
|
class EbookDownloadMixin(object):
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
def download_ebook(self, url='', cookie_file=None, filename='', save_loc='', add_to_lib=True, tags=[]):
|
def download_ebook(self, url='', cookie_file=None, filename='', save_loc='', add_to_lib=True, tags=[]):
|
||||||
if tags:
|
if tags:
|
||||||
if isinstance(tags, basestring):
|
if isinstance(tags, basestring):
|
||||||
|
@ -270,7 +270,7 @@ class SelectRecipients(QDialog): # {{{
|
|||||||
ans = []
|
ans = []
|
||||||
for i in self.items:
|
for i in self.items:
|
||||||
if i.checkState() == Qt.Checked:
|
if i.checkState() == Qt.Checked:
|
||||||
to = unicode(i.data(Qt.UserRole).toString())
|
to = unicode(i.data(Qt.UserRole) or '')
|
||||||
fmts = tuple(x.strip().upper() for x in (opts.accounts[to][0] or '').split(','))
|
fmts = tuple(x.strip().upper() for x in (opts.accounts[to][0] or '').split(','))
|
||||||
subject = opts.subjects.get(to, '')
|
subject = opts.subjects.get(to, '')
|
||||||
ans.append((to, fmts, subject))
|
ans.append((to, fmts, subject))
|
||||||
@ -285,6 +285,9 @@ def select_recipients(parent=None):
|
|||||||
|
|
||||||
class EmailMixin(object): # {{{
|
class EmailMixin(object): # {{{
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
def send_multiple_by_mail(self, recipients, delete_from_library):
|
def send_multiple_by_mail(self, recipients, delete_from_library):
|
||||||
ids = set(self.library_view.model().id(r) for r in self.library_view.selectionModel().selectedRows())
|
ids = set(self.library_view.model().id(r) for r in self.library_view.selectionModel().selectedRows())
|
||||||
if not ids:
|
if not ids:
|
||||||
|
@ -66,7 +66,7 @@ class FontFamilyDelegate(QStyledItemDelegate):
|
|||||||
return QSize(300, 50)
|
return QSize(300, 50)
|
||||||
|
|
||||||
def do_size_hint(self, option, index):
|
def do_size_hint(self, option, index):
|
||||||
text = index.data(Qt.DisplayRole).toString()
|
text = index.data(Qt.DisplayRole) or ''
|
||||||
font = QFont(option.font)
|
font = QFont(option.font)
|
||||||
font.setPointSize(QFontInfo(font).pointSize() * 1.5)
|
font.setPointSize(QFontInfo(font).pointSize() * 1.5)
|
||||||
m = QFontMetrics(font)
|
m = QFontMetrics(font)
|
||||||
@ -82,7 +82,7 @@ class FontFamilyDelegate(QStyledItemDelegate):
|
|||||||
painter.restore()
|
painter.restore()
|
||||||
|
|
||||||
def do_paint(self, painter, option, index):
|
def do_paint(self, painter, option, index):
|
||||||
text = unicode(index.data(Qt.DisplayRole).toString())
|
text = unicode(index.data(Qt.DisplayRole) or '')
|
||||||
font = QFont(option.font)
|
font = QFont(option.font)
|
||||||
font.setPointSize(QFontInfo(font).pointSize() * 1.5)
|
font.setPointSize(QFontInfo(font).pointSize() * 1.5)
|
||||||
font2 = QFont(font)
|
font2 = QFont(font)
|
||||||
|
@ -31,7 +31,10 @@ def partial(*args, **kwargs):
|
|||||||
|
|
||||||
class LibraryViewMixin(object): # {{{
|
class LibraryViewMixin(object): # {{{
|
||||||
|
|
||||||
def __init__(self, db):
|
def __init__(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def init_library_view_mixin(self, db):
|
||||||
self.library_view.files_dropped.connect(self.iactions['Add Books'].files_dropped, type=Qt.QueuedConnection)
|
self.library_view.files_dropped.connect(self.iactions['Add Books'].files_dropped, type=Qt.QueuedConnection)
|
||||||
self.library_view.add_column_signal.connect(partial(self.iactions['Preferences'].do_config,
|
self.library_view.add_column_signal.connect(partial(self.iactions['Preferences'].do_config,
|
||||||
initial_plugin=('Interface', 'Custom Columns')),
|
initial_plugin=('Interface', 'Custom Columns')),
|
||||||
@ -294,14 +297,14 @@ class VLTabs(QTabBar): # {{{
|
|||||||
self.setVisible(False)
|
self.setVisible(False)
|
||||||
|
|
||||||
def tab_changed(self, idx):
|
def tab_changed(self, idx):
|
||||||
vl = unicode(self.tabData(idx).toString()).strip() or None
|
vl = unicode(self.tabData(idx) or '').strip() or None
|
||||||
self.gui.apply_virtual_library(vl)
|
self.gui.apply_virtual_library(vl)
|
||||||
|
|
||||||
def tab_moved(self, from_, to):
|
def tab_moved(self, from_, to):
|
||||||
self.current_db.prefs['virt_libs_order'] = [unicode(self.tabData(i).toString()) for i in range(self.count())]
|
self.current_db.prefs['virt_libs_order'] = [unicode(self.tabData(i) or '') for i in range(self.count())]
|
||||||
|
|
||||||
def tab_close(self, index):
|
def tab_close(self, index):
|
||||||
vl = unicode(self.tabData(index).toString())
|
vl = unicode(self.tabData(index) or '')
|
||||||
if vl: # Dont allow closing the All Books tab
|
if vl: # Dont allow closing the All Books tab
|
||||||
self.current_db.prefs['virt_libs_hidden'] = list(
|
self.current_db.prefs['virt_libs_hidden'] = list(
|
||||||
self.current_db.prefs['virt_libs_hidden']) + [vl]
|
self.current_db.prefs['virt_libs_hidden']) + [vl]
|
||||||
@ -381,7 +384,10 @@ class VLTabs(QTabBar): # {{{
|
|||||||
|
|
||||||
class LayoutMixin(object): # {{{
|
class LayoutMixin(object): # {{{
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def init_layout_mixin(self):
|
||||||
self.vl_tabs = VLTabs(self)
|
self.vl_tabs = VLTabs(self)
|
||||||
self.centralwidget.layout().addWidget(self.vl_tabs)
|
self.centralwidget.layout().addWidget(self.vl_tabs)
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ Job management.
|
|||||||
import re, time
|
import re, time
|
||||||
from Queue import Empty, Queue
|
from Queue import Empty, Queue
|
||||||
|
|
||||||
from PyQt5.Qt import (QAbstractTableModel, QVariant, QModelIndex, Qt,
|
from PyQt5.Qt import (QAbstractTableModel, QModelIndex, Qt,
|
||||||
QTimer, pyqtSignal, QIcon, QDialog, QAbstractItemDelegate, QApplication,
|
QTimer, pyqtSignal, QIcon, QDialog, QAbstractItemDelegate, QApplication,
|
||||||
QSize, QStyleOptionProgressBar, QStyle, QToolTip, QFrame,
|
QSize, QStyleOptionProgressBar, QStyle, QToolTip, QFrame,
|
||||||
QHBoxLayout, QVBoxLayout, QSizePolicy, QLabel, QCoreApplication, QAction,
|
QHBoxLayout, QVBoxLayout, QSizePolicy, QLabel, QCoreApplication, QAction,
|
||||||
@ -18,7 +18,7 @@ from PyQt5.Qt import (QAbstractTableModel, QVariant, QModelIndex, Qt,
|
|||||||
|
|
||||||
from calibre.utils.ipc.server import Server
|
from calibre.utils.ipc.server import Server
|
||||||
from calibre.utils.ipc.job import ParallelJob
|
from calibre.utils.ipc.job import ParallelJob
|
||||||
from calibre.gui2 import (Dispatcher, error_dialog, question_dialog, NONE,
|
from calibre.gui2 import (Dispatcher, error_dialog, question_dialog,
|
||||||
config, gprefs)
|
config, gprefs)
|
||||||
from calibre.gui2.device import DeviceJob
|
from calibre.gui2.device import DeviceJob
|
||||||
from calibre.gui2.dialogs.jobs_ui import Ui_JobsDialog
|
from calibre.gui2.dialogs.jobs_ui import Ui_JobsDialog
|
||||||
@ -38,10 +38,10 @@ class JobManager(QAbstractTableModel, SearchQueryParser): # {{{
|
|||||||
QAbstractTableModel.__init__(self)
|
QAbstractTableModel.__init__(self)
|
||||||
SearchQueryParser.__init__(self, ['all'])
|
SearchQueryParser.__init__(self, ['all'])
|
||||||
|
|
||||||
self.wait_icon = QVariant(QIcon(I('jobs.png')))
|
self.wait_icon = (QIcon(I('jobs.png')))
|
||||||
self.running_icon = QVariant(QIcon(I('exec.png')))
|
self.running_icon = (QIcon(I('exec.png')))
|
||||||
self.error_icon = QVariant(QIcon(I('dialog_error.png')))
|
self.error_icon = (QIcon(I('dialog_error.png')))
|
||||||
self.done_icon = QVariant(QIcon(I('ok.png')))
|
self.done_icon = (QIcon(I('ok.png')))
|
||||||
|
|
||||||
self.jobs = []
|
self.jobs = []
|
||||||
self.add_job = Dispatcher(self._add_job)
|
self.add_job = Dispatcher(self._add_job)
|
||||||
@ -62,9 +62,9 @@ class JobManager(QAbstractTableModel, SearchQueryParser): # {{{
|
|||||||
|
|
||||||
def headerData(self, section, orientation, role):
|
def headerData(self, section, orientation, role):
|
||||||
if role != Qt.DisplayRole:
|
if role != Qt.DisplayRole:
|
||||||
return NONE
|
return None
|
||||||
if orientation == Qt.Horizontal:
|
if orientation == Qt.Horizontal:
|
||||||
return QVariant({
|
return ({
|
||||||
0: _('Job'),
|
0: _('Job'),
|
||||||
1: _('Status'),
|
1: _('Status'),
|
||||||
2: _('Progress'),
|
2: _('Progress'),
|
||||||
@ -72,7 +72,7 @@ class JobManager(QAbstractTableModel, SearchQueryParser): # {{{
|
|||||||
4: _('Start time'),
|
4: _('Start time'),
|
||||||
}.get(section, ''))
|
}.get(section, ''))
|
||||||
else:
|
else:
|
||||||
return QVariant(section+1)
|
return (section+1)
|
||||||
|
|
||||||
def show_tooltip(self, arg):
|
def show_tooltip(self, arg):
|
||||||
widget, pos = arg
|
widget, pos = arg
|
||||||
@ -99,7 +99,7 @@ class JobManager(QAbstractTableModel, SearchQueryParser): # {{{
|
|||||||
def data(self, index, role):
|
def data(self, index, role):
|
||||||
try:
|
try:
|
||||||
if role not in (Qt.DisplayRole, Qt.DecorationRole):
|
if role not in (Qt.DisplayRole, Qt.DecorationRole):
|
||||||
return NONE
|
return None
|
||||||
row, col = index.row(), index.column()
|
row, col = index.row(), index.column()
|
||||||
job = self.jobs[row]
|
job = self.jobs[row]
|
||||||
|
|
||||||
@ -108,19 +108,19 @@ class JobManager(QAbstractTableModel, SearchQueryParser): # {{{
|
|||||||
desc = job.description
|
desc = job.description
|
||||||
if not desc:
|
if not desc:
|
||||||
desc = _('Unknown job')
|
desc = _('Unknown job')
|
||||||
return QVariant(desc)
|
return (desc)
|
||||||
if col == 1:
|
if col == 1:
|
||||||
return QVariant(job.status_text)
|
return (job.status_text)
|
||||||
if col == 2:
|
if col == 2:
|
||||||
p = 100. if job.is_finished else job.percent
|
p = 100. if job.is_finished else job.percent
|
||||||
return QVariant(p)
|
return (p)
|
||||||
if col == 3:
|
if col == 3:
|
||||||
rtime = job.running_time
|
rtime = job.running_time
|
||||||
if rtime is None:
|
if rtime is None:
|
||||||
return NONE
|
return None
|
||||||
return QVariant('%dm %ds'%(int(rtime)//60, int(rtime)%60))
|
return ('%dm %ds'%(int(rtime)//60, int(rtime)%60))
|
||||||
if col == 4 and job.start_time is not None:
|
if col == 4 and job.start_time is not None:
|
||||||
return QVariant(time.strftime('%H:%M -- %d %b', time.localtime(job.start_time)))
|
return (time.strftime('%H:%M -- %d %b', time.localtime(job.start_time)))
|
||||||
if role == Qt.DecorationRole and col == 0:
|
if role == Qt.DecorationRole and col == 0:
|
||||||
state = job.run_state
|
state = job.run_state
|
||||||
if state == job.WAITING:
|
if state == job.WAITING:
|
||||||
@ -133,7 +133,7 @@ class JobManager(QAbstractTableModel, SearchQueryParser): # {{{
|
|||||||
except:
|
except:
|
||||||
import traceback
|
import traceback
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
return NONE
|
return None
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
try:
|
try:
|
||||||
@ -392,8 +392,9 @@ class ProgressBarDelegate(QAbstractItemDelegate): # {{{
|
|||||||
opts.minimum = 1
|
opts.minimum = 1
|
||||||
opts.maximum = 100
|
opts.maximum = 100
|
||||||
opts.textVisible = True
|
opts.textVisible = True
|
||||||
percent, ok = index.model().data(index, Qt.DisplayRole).toInt()
|
try:
|
||||||
if not ok:
|
percent = int(index.model().data(index, Qt.DisplayRole))
|
||||||
|
except (TypeError, ValueError):
|
||||||
percent = 0
|
percent = 0
|
||||||
opts.progress = percent
|
opts.progress = percent
|
||||||
opts.text = (_('Unavailable') if percent == 0 else '%d%%'%percent)
|
opts.text = (_('Unavailable') if percent == 0 else '%d%%'%percent)
|
||||||
|
@ -267,7 +267,10 @@ class Spacer(QWidget): # {{{
|
|||||||
|
|
||||||
class MainWindowMixin(object): # {{{
|
class MainWindowMixin(object): # {{{
|
||||||
|
|
||||||
def __init__(self, db):
|
def __init__(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def init_main_window_mixin(self, db):
|
||||||
self.setObjectName('MainWindow')
|
self.setObjectName('MainWindow')
|
||||||
self.setWindowIcon(QIcon(I('lt.png')))
|
self.setWindowIcon(QIcon(I('lt.png')))
|
||||||
self.setWindowTitle(__appname__)
|
self.setWindowTitle(__appname__)
|
||||||
|
@ -9,9 +9,9 @@ import functools, re, os, traceback, errno, time
|
|||||||
from collections import defaultdict, namedtuple
|
from collections import defaultdict, namedtuple
|
||||||
|
|
||||||
from PyQt5.Qt import (QAbstractTableModel, Qt, pyqtSignal, QIcon, QImage,
|
from PyQt5.Qt import (QAbstractTableModel, Qt, pyqtSignal, QIcon, QImage,
|
||||||
QModelIndex, QVariant, QDateTime, QColor, QPixmap, QPainter)
|
QModelIndex, QDateTime, QColor, QPixmap, QPainter)
|
||||||
|
|
||||||
from calibre.gui2 import NONE, error_dialog
|
from calibre.gui2 import error_dialog
|
||||||
from calibre.utils.search_query_parser import ParseException
|
from calibre.utils.search_query_parser import ParseException
|
||||||
from calibre.ebooks.metadata import fmt_sidx, authors_to_string, string_to_authors
|
from calibre.ebooks.metadata import fmt_sidx, authors_to_string, string_to_authors
|
||||||
from calibre.ebooks.metadata.book.formatter import SafeFormat
|
from calibre.ebooks.metadata.book.formatter import SafeFormat
|
||||||
@ -60,7 +60,7 @@ class ColumnColor(object): # {{{
|
|||||||
self.mi = None
|
self.mi = None
|
||||||
color = color_cache[id_][key]
|
color = color_cache[id_][key]
|
||||||
if color.isValid():
|
if color.isValid():
|
||||||
return QVariant(color)
|
return color
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
if self.mi is None:
|
if self.mi is None:
|
||||||
@ -70,7 +70,6 @@ class ColumnColor(object): # {{{
|
|||||||
template_cache=template_cache))
|
template_cache=template_cache))
|
||||||
color_cache[id_][key] = color
|
color_cache[id_][key] = color
|
||||||
if color.isValid():
|
if color.isValid():
|
||||||
color = QVariant(color)
|
|
||||||
self.mi = None
|
self.mi = None
|
||||||
return color
|
return color
|
||||||
except:
|
except:
|
||||||
@ -199,7 +198,7 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
self.bool_no_icon = QIcon(I('list_remove.png'))
|
self.bool_no_icon = QIcon(I('list_remove.png'))
|
||||||
self.bool_blank_icon = QIcon(I('blank.png'))
|
self.bool_blank_icon = QIcon(I('blank.png'))
|
||||||
self.marked_icon = QIcon(I('marked.png'))
|
self.marked_icon = QIcon(I('marked.png'))
|
||||||
self.row_decoration = NONE
|
self.row_decoration = None
|
||||||
self.device_connected = False
|
self.device_connected = False
|
||||||
self.ids_to_highlight = []
|
self.ids_to_highlight = []
|
||||||
self.ids_to_highlight_set = set()
|
self.ids_to_highlight_set = set()
|
||||||
@ -712,19 +711,19 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
def func(idx):
|
def func(idx):
|
||||||
val = force_to_bool(fffunc(field_obj, idfunc(idx)))
|
val = force_to_bool(fffunc(field_obj, idfunc(idx)))
|
||||||
if val is None:
|
if val is None:
|
||||||
return NONE if bt else bn
|
return None if bt else bn
|
||||||
return by if val else bn
|
return by if val else bn
|
||||||
elif field == 'size':
|
elif field == 'size':
|
||||||
sz_mult = 1.0/(1024**2)
|
sz_mult = 1.0/(1024**2)
|
||||||
def func(idx):
|
def func(idx):
|
||||||
val = fffunc(field_obj, idfunc(idx), default_value=0) or 0
|
val = fffunc(field_obj, idfunc(idx), default_value=0) or 0
|
||||||
if val is 0:
|
if val is 0:
|
||||||
return NONE
|
return None
|
||||||
ans = u'%.1f' % (val * sz_mult)
|
ans = u'%.1f' % (val * sz_mult)
|
||||||
return QVariant(u'<0.1' if ans == u'0.0' else ans)
|
return (u'<0.1' if ans == u'0.0' else ans)
|
||||||
elif field == 'languages':
|
elif field == 'languages':
|
||||||
def func(idx):
|
def func(idx):
|
||||||
return QVariant(', '.join(calibre_langcode_to_name(x) for x in fffunc(field_obj, idfunc(idx))))
|
return (', '.join(calibre_langcode_to_name(x) for x in fffunc(field_obj, idfunc(idx))))
|
||||||
elif field == 'ondevice' and decorator:
|
elif field == 'ondevice' and decorator:
|
||||||
by = self.bool_yes_icon
|
by = self.bool_yes_icon
|
||||||
bb = self.bool_blank_icon
|
bb = self.bool_blank_icon
|
||||||
@ -739,54 +738,54 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
sv = m['is_multiple']['cache_to_list']
|
sv = m['is_multiple']['cache_to_list']
|
||||||
def func(idx):
|
def func(idx):
|
||||||
val = fffunc(field_obj, idfunc(idx), default_value='') or ''
|
val = fffunc(field_obj, idfunc(idx), default_value='') or ''
|
||||||
return QVariant(jv.join(sorted((x.strip() for x in val.split(sv)), key=sort_key)))
|
return (jv.join(sorted((x.strip() for x in val.split(sv)), key=sort_key)))
|
||||||
else:
|
else:
|
||||||
def func(idx):
|
def func(idx):
|
||||||
return QVariant(fffunc(field_obj, idfunc(idx), default_value=''))
|
return (fffunc(field_obj, idfunc(idx), default_value=''))
|
||||||
else:
|
else:
|
||||||
if do_sort:
|
if do_sort:
|
||||||
def func(idx):
|
def func(idx):
|
||||||
return QVariant(jv.join(sorted(fffunc(field_obj, idfunc(idx), default_value=()), key=sort_key)))
|
return (jv.join(sorted(fffunc(field_obj, idfunc(idx), default_value=()), key=sort_key)))
|
||||||
else:
|
else:
|
||||||
def func(idx):
|
def func(idx):
|
||||||
return QVariant(jv.join(fffunc(field_obj, idfunc(idx), default_value=())))
|
return (jv.join(fffunc(field_obj, idfunc(idx), default_value=())))
|
||||||
else:
|
else:
|
||||||
if dt in {'text', 'composite', 'enumeration'} and m['display'].get('use_decorations', False):
|
if dt in {'text', 'composite', 'enumeration'} and m['display'].get('use_decorations', False):
|
||||||
def func(idx):
|
def func(idx):
|
||||||
text = fffunc(field_obj, idfunc(idx))
|
text = fffunc(field_obj, idfunc(idx))
|
||||||
return QVariant(text) if force_to_bool(text) is None else NONE
|
return (text) if force_to_bool(text) is None else None
|
||||||
else:
|
else:
|
||||||
def func(idx):
|
def func(idx):
|
||||||
return QVariant(fffunc(field_obj, idfunc(idx), default_value=''))
|
return (fffunc(field_obj, idfunc(idx), default_value=''))
|
||||||
elif dt == 'datetime':
|
elif dt == 'datetime':
|
||||||
def func(idx):
|
def func(idx):
|
||||||
return QVariant(QDateTime(as_local_time(fffunc(field_obj, idfunc(idx), default_value=UNDEFINED_DATE))))
|
return (QDateTime(as_local_time(fffunc(field_obj, idfunc(idx), default_value=UNDEFINED_DATE))))
|
||||||
elif dt == 'rating':
|
elif dt == 'rating':
|
||||||
def func(idx):
|
def func(idx):
|
||||||
return QVariant(int(fffunc(field_obj, idfunc(idx), default_value=0)/2.0))
|
return (int(fffunc(field_obj, idfunc(idx), default_value=0)/2.0))
|
||||||
elif dt == 'series':
|
elif dt == 'series':
|
||||||
sidx_field = self.db.new_api.fields[field + '_index']
|
sidx_field = self.db.new_api.fields[field + '_index']
|
||||||
def func(idx):
|
def func(idx):
|
||||||
book_id = idfunc(idx)
|
book_id = idfunc(idx)
|
||||||
series = fffunc(field_obj, book_id, default_value=False)
|
series = fffunc(field_obj, book_id, default_value=False)
|
||||||
if series:
|
if series:
|
||||||
return QVariant('%s [%s]' % (series, fmt_sidx(fffunc(sidx_field, book_id, default_value=1.0))))
|
return ('%s [%s]' % (series, fmt_sidx(fffunc(sidx_field, book_id, default_value=1.0))))
|
||||||
return NONE
|
return None
|
||||||
elif dt in {'int', 'float'}:
|
elif dt in {'int', 'float'}:
|
||||||
fmt = m['display'].get('number_format', None)
|
fmt = m['display'].get('number_format', None)
|
||||||
def func(idx):
|
def func(idx):
|
||||||
val = fffunc(field_obj, idfunc(idx))
|
val = fffunc(field_obj, idfunc(idx))
|
||||||
if val is None:
|
if val is None:
|
||||||
return NONE
|
return None
|
||||||
if fmt:
|
if fmt:
|
||||||
try:
|
try:
|
||||||
return QVariant(fmt.format(val))
|
return (fmt.format(val))
|
||||||
except (TypeError, ValueError, AttributeError, IndexError, KeyError):
|
except (TypeError, ValueError, AttributeError, IndexError, KeyError):
|
||||||
pass
|
pass
|
||||||
return QVariant(val)
|
return (val)
|
||||||
else:
|
else:
|
||||||
def func(idx):
|
def func(idx):
|
||||||
return NONE
|
return None
|
||||||
|
|
||||||
return func
|
return func
|
||||||
|
|
||||||
@ -813,7 +812,7 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
# the column map does not accurately represent the screen. In these cases,
|
# the column map does not accurately represent the screen. In these cases,
|
||||||
# we will get asked to display columns we don't know about. Must test for this.
|
# we will get asked to display columns we don't know about. Must test for this.
|
||||||
if col >= len(self.column_to_dc_map):
|
if col >= len(self.column_to_dc_map):
|
||||||
return NONE
|
return None
|
||||||
if role == Qt.DisplayRole:
|
if role == Qt.DisplayRole:
|
||||||
rules = self.db.prefs['column_icon_rules']
|
rules = self.db.prefs['column_icon_rules']
|
||||||
if rules:
|
if rules:
|
||||||
@ -833,14 +832,14 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
self.icon_cache, self.icon_bitmap_cache,
|
self.icon_cache, self.icon_bitmap_cache,
|
||||||
self.icon_template_cache)
|
self.icon_template_cache)
|
||||||
if ccicon is not None:
|
if ccicon is not None:
|
||||||
return NONE
|
return None
|
||||||
self.icon_cache[id_][cache_index] = None
|
self.icon_cache[id_][cache_index] = None
|
||||||
return self.column_to_dc_map[col](index.row())
|
return self.column_to_dc_map[col](index.row())
|
||||||
elif role in (Qt.EditRole, Qt.ToolTipRole):
|
elif role in (Qt.EditRole, Qt.ToolTipRole):
|
||||||
return self.column_to_dc_map[col](index.row())
|
return self.column_to_dc_map[col](index.row())
|
||||||
elif role == Qt.BackgroundRole:
|
elif role == Qt.BackgroundRole:
|
||||||
if self.id(index) in self.ids_to_highlight_set:
|
if self.id(index) in self.ids_to_highlight_set:
|
||||||
return QVariant(QColor('lightgreen'))
|
return (QColor('lightgreen'))
|
||||||
elif role == Qt.ForegroundRole:
|
elif role == Qt.ForegroundRole:
|
||||||
key = self.column_map[col]
|
key = self.column_map[col]
|
||||||
id_ = self.id(index)
|
id_ = self.id(index)
|
||||||
@ -862,13 +861,13 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
cc = self.custom_columns[self.column_map[col]]['display']
|
cc = self.custom_columns[self.column_map[col]]['display']
|
||||||
colors = cc.get('enum_colors', [])
|
colors = cc.get('enum_colors', [])
|
||||||
values = cc.get('enum_values', [])
|
values = cc.get('enum_values', [])
|
||||||
txt = unicode(index.data(Qt.DisplayRole).toString())
|
txt = unicode(index.data(Qt.DisplayRole) or '')
|
||||||
if len(colors) > 0 and txt in values:
|
if len(colors) > 0 and txt in values:
|
||||||
try:
|
try:
|
||||||
color = QColor(colors[values.index(txt)])
|
color = QColor(colors[values.index(txt)])
|
||||||
if color.isValid():
|
if color.isValid():
|
||||||
self.column_color.mi = None
|
self.column_color.mi = None
|
||||||
return QVariant(color)
|
return (color)
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -879,11 +878,11 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
return ccol
|
return ccol
|
||||||
|
|
||||||
self.column_color.mi = None
|
self.column_color.mi = None
|
||||||
return NONE
|
return None
|
||||||
elif role == Qt.DecorationRole:
|
elif role == Qt.DecorationRole:
|
||||||
if self.column_to_dc_decorator_map[col] is not None:
|
if self.column_to_dc_decorator_map[col] is not None:
|
||||||
ccicon = self.column_to_dc_decorator_map[index.column()](index.row())
|
ccicon = self.column_to_dc_decorator_map[index.column()](index.row())
|
||||||
if ccicon != NONE:
|
if ccicon is not None:
|
||||||
return ccicon
|
return ccicon
|
||||||
|
|
||||||
rules = self.db.prefs['column_icon_rules']
|
rules = self.db.prefs['column_icon_rules']
|
||||||
@ -915,11 +914,11 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
cname = self.column_map[index.column()]
|
cname = self.column_map[index.column()]
|
||||||
ans = Qt.AlignVCenter | ALIGNMENT_MAP[self.alignment_map.get(cname,
|
ans = Qt.AlignVCenter | ALIGNMENT_MAP[self.alignment_map.get(cname,
|
||||||
'left')]
|
'left')]
|
||||||
return QVariant(ans)
|
return (ans)
|
||||||
# elif role == Qt.ToolTipRole and index.isValid():
|
# elif role == Qt.ToolTipRole and index.isValid():
|
||||||
# if self.column_map[index.column()] in self.editable_cols:
|
# if self.column_map[index.column()] in self.editable_cols:
|
||||||
# return QVariant(_("Double click to <b>edit</b> me<br><br>"))
|
# return (_("Double click to <b>edit</b> me<br><br>"))
|
||||||
return NONE
|
return None
|
||||||
|
|
||||||
def headerData(self, section, orientation, role):
|
def headerData(self, section, orientation, role):
|
||||||
if orientation == Qt.Horizontal:
|
if orientation == Qt.Horizontal:
|
||||||
@ -933,22 +932,22 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
is_cat = '.\n\n' + _('Click in this column and press Q to Quickview books with the same %s') % ht
|
is_cat = '.\n\n' + _('Click in this column and press Q to Quickview books with the same %s') % ht
|
||||||
else:
|
else:
|
||||||
is_cat = ''
|
is_cat = ''
|
||||||
return QVariant(_('The lookup/search name is "{0}"{1}').format(ht, is_cat))
|
return (_('The lookup/search name is "{0}"{1}').format(ht, is_cat))
|
||||||
if role == Qt.DisplayRole:
|
if role == Qt.DisplayRole:
|
||||||
return QVariant(self.headers[self.column_map[section]])
|
return (self.headers[self.column_map[section]])
|
||||||
return NONE
|
return None
|
||||||
if DEBUG and role == Qt.ToolTipRole and orientation == Qt.Vertical:
|
if DEBUG and role == Qt.ToolTipRole and orientation == Qt.Vertical:
|
||||||
col = self.db.field_metadata['uuid']['rec_index']
|
col = self.db.field_metadata['uuid']['rec_index']
|
||||||
return QVariant(_('This book\'s UUID is "{0}"').format(self.db.data[section][col]))
|
return (_('This book\'s UUID is "{0}"').format(self.db.data[section][col]))
|
||||||
|
|
||||||
if role == Qt.DisplayRole: # orientation is vertical
|
if role == Qt.DisplayRole: # orientation is vertical
|
||||||
return QVariant(section+1)
|
return (section+1)
|
||||||
if role == Qt.DecorationRole:
|
if role == Qt.DecorationRole:
|
||||||
try:
|
try:
|
||||||
return self.marked_icon if self.db.data.get_marked(self.db.data.index_to_id(section)) else self.row_decoration
|
return self.marked_icon if self.db.data.get_marked(self.db.data.index_to_id(section)) else self.row_decoration
|
||||||
except (ValueError, IndexError):
|
except (ValueError, IndexError):
|
||||||
pass
|
pass
|
||||||
return NONE
|
return None
|
||||||
|
|
||||||
def flags(self, index):
|
def flags(self, index):
|
||||||
flags = QAbstractTableModel.flags(self, index)
|
flags = QAbstractTableModel.flags(self, index)
|
||||||
@ -967,24 +966,24 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
label=self.db.field_metadata.key_to_label(colhead)
|
label=self.db.field_metadata.key_to_label(colhead)
|
||||||
s_index = None
|
s_index = None
|
||||||
if typ in ('text', 'comments'):
|
if typ in ('text', 'comments'):
|
||||||
val = unicode(value.toString()).strip()
|
val = unicode(value or '').strip()
|
||||||
val = val if val else None
|
val = val if val else None
|
||||||
elif typ == 'enumeration':
|
elif typ == 'enumeration':
|
||||||
val = unicode(value.toString()).strip()
|
val = unicode(value or '').strip()
|
||||||
if not val:
|
if not val:
|
||||||
val = None
|
val = None
|
||||||
elif typ == 'bool':
|
elif typ == 'bool':
|
||||||
val = value.toPyObject()
|
val = bool(value)
|
||||||
elif typ == 'rating':
|
elif typ == 'rating':
|
||||||
val = value.toInt()[0]
|
val = int(value)
|
||||||
val = 0 if val < 0 else 5 if val > 5 else val
|
val = 0 if val < 0 else 5 if val > 5 else val
|
||||||
val *= 2
|
val *= 2
|
||||||
elif typ in ('int', 'float'):
|
elif typ in ('int', 'float'):
|
||||||
val = unicode(value.toString()).strip()
|
val = unicode(value or '').strip()
|
||||||
if not val:
|
if not val:
|
||||||
val = None
|
val = None
|
||||||
elif typ == 'datetime':
|
elif typ == 'datetime':
|
||||||
val = value.toDateTime()
|
val = value
|
||||||
if val.isNull():
|
if val.isNull():
|
||||||
val = None
|
val = None
|
||||||
else:
|
else:
|
||||||
@ -992,7 +991,7 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
return False
|
return False
|
||||||
val = qt_to_dt(val, as_utc=False)
|
val = qt_to_dt(val, as_utc=False)
|
||||||
elif typ == 'series':
|
elif typ == 'series':
|
||||||
val = unicode(value.toString()).strip()
|
val = unicode(value or '').strip()
|
||||||
if val:
|
if val:
|
||||||
pat = re.compile(r'\[([.0-9]+)\]')
|
pat = re.compile(r'\[([.0-9]+)\]')
|
||||||
match = pat.search(val)
|
match = pat.search(val)
|
||||||
@ -1006,7 +1005,7 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
s_index = self.db.get_next_cc_series_num_for(val,
|
s_index = self.db.get_next_cc_series_num_for(val,
|
||||||
label=label, num=None)
|
label=label, num=None)
|
||||||
elif typ == 'composite':
|
elif typ == 'composite':
|
||||||
tmpl = unicode(value.toString()).strip()
|
tmpl = unicode(value or '').strip()
|
||||||
disp = cc['display']
|
disp = cc['display']
|
||||||
disp['composite_template'] = tmpl
|
disp['composite_template'] = tmpl
|
||||||
self.db.set_custom_column_metadata(cc['colnum'], display=disp,
|
self.db.set_custom_column_metadata(cc['colnum'], display=disp,
|
||||||
@ -1057,9 +1056,9 @@ class BooksModel(QAbstractTableModel): # {{{
|
|||||||
else:
|
else:
|
||||||
if column not in self.editable_cols:
|
if column not in self.editable_cols:
|
||||||
return False
|
return False
|
||||||
val = (int(value.toInt()[0]) if column == 'rating' else
|
val = (int(value) if column == 'rating' else
|
||||||
value.toDateTime() if column in ('timestamp', 'pubdate')
|
value if column in ('timestamp', 'pubdate')
|
||||||
else re.sub(ur'\s', u' ', unicode(value.toString()).strip()))
|
else re.sub(ur'\s', u' ', unicode(value or '').strip()))
|
||||||
id = self.db.id(row)
|
id = self.db.id(row)
|
||||||
books_to_refresh = set([id])
|
books_to_refresh = set([id])
|
||||||
if column == 'rating':
|
if column == 'rating':
|
||||||
@ -1543,17 +1542,17 @@ class DeviceBooksModel(BooksModel): # {{{
|
|||||||
text = self.db[self.map[row]].title
|
text = self.db[self.map[row]].title
|
||||||
if not text:
|
if not text:
|
||||||
text = self.unknown
|
text = self.unknown
|
||||||
return QVariant(text)
|
return (text)
|
||||||
elif cname == 'authors':
|
elif cname == 'authors':
|
||||||
au = self.db[self.map[row]].authors
|
au = self.db[self.map[row]].authors
|
||||||
if not au:
|
if not au:
|
||||||
au = [_('Unknown')]
|
au = [_('Unknown')]
|
||||||
return QVariant(authors_to_string(au))
|
return (authors_to_string(au))
|
||||||
elif cname == 'size':
|
elif cname == 'size':
|
||||||
size = self.db[self.map[row]].size
|
size = self.db[self.map[row]].size
|
||||||
if not isinstance(size, (float, int)):
|
if not isinstance(size, (float, int)):
|
||||||
size = 0
|
size = 0
|
||||||
return QVariant(human_readable(size))
|
return (human_readable(size))
|
||||||
elif cname == 'timestamp':
|
elif cname == 'timestamp':
|
||||||
dt = self.db[self.map[row]].datetime
|
dt = self.db[self.map[row]].datetime
|
||||||
try:
|
try:
|
||||||
@ -1561,49 +1560,49 @@ class DeviceBooksModel(BooksModel): # {{{
|
|||||||
except OverflowError:
|
except OverflowError:
|
||||||
dt = dt_factory(time.gmtime(), assume_utc=True,
|
dt = dt_factory(time.gmtime(), assume_utc=True,
|
||||||
as_utc=False)
|
as_utc=False)
|
||||||
return QVariant(strftime(TIME_FMT, dt.timetuple()))
|
return (strftime(TIME_FMT, dt.timetuple()))
|
||||||
elif cname == 'collections':
|
elif cname == 'collections':
|
||||||
tags = self.db[self.map[row]].device_collections
|
tags = self.db[self.map[row]].device_collections
|
||||||
if tags:
|
if tags:
|
||||||
tags.sort(key=sort_key)
|
tags.sort(key=sort_key)
|
||||||
return QVariant(', '.join(tags))
|
return (', '.join(tags))
|
||||||
elif DEBUG and cname == 'inlibrary':
|
elif DEBUG and cname == 'inlibrary':
|
||||||
return QVariant(self.db[self.map[row]].in_library)
|
return (self.db[self.map[row]].in_library)
|
||||||
elif role == Qt.ToolTipRole and index.isValid():
|
elif role == Qt.ToolTipRole and index.isValid():
|
||||||
if col == 0 and hasattr(self.db[self.map[row]], 'in_library_waiting'):
|
if col == 0 and hasattr(self.db[self.map[row]], 'in_library_waiting'):
|
||||||
return QVariant(_('Waiting for metadata to be updated'))
|
return (_('Waiting for metadata to be updated'))
|
||||||
if self.is_row_marked_for_deletion(row):
|
if self.is_row_marked_for_deletion(row):
|
||||||
return QVariant(_('Marked for deletion'))
|
return (_('Marked for deletion'))
|
||||||
if cname in ['title', 'authors'] or (cname == 'collections' and
|
if cname in ['title', 'authors'] or (cname == 'collections' and
|
||||||
self.db.supports_collections()):
|
self.db.supports_collections()):
|
||||||
return QVariant(_("Double click to <b>edit</b> me<br><br>"))
|
return (_("Double click to <b>edit</b> me<br><br>"))
|
||||||
elif role == Qt.DecorationRole and cname == 'inlibrary':
|
elif role == Qt.DecorationRole and cname == 'inlibrary':
|
||||||
if hasattr(self.db[self.map[row]], 'in_library_waiting'):
|
if hasattr(self.db[self.map[row]], 'in_library_waiting'):
|
||||||
return QVariant(self.sync_icon)
|
return (self.sync_icon)
|
||||||
elif self.db[self.map[row]].in_library:
|
elif self.db[self.map[row]].in_library:
|
||||||
return QVariant(self.bool_yes_icon)
|
return (self.bool_yes_icon)
|
||||||
elif self.db[self.map[row]].in_library is not None:
|
elif self.db[self.map[row]].in_library is not None:
|
||||||
return QVariant(self.bool_no_icon)
|
return (self.bool_no_icon)
|
||||||
elif role == Qt.TextAlignmentRole:
|
elif role == Qt.TextAlignmentRole:
|
||||||
cname = self.column_map[index.column()]
|
cname = self.column_map[index.column()]
|
||||||
ans = Qt.AlignVCenter | ALIGNMENT_MAP[self.alignment_map.get(cname,
|
ans = Qt.AlignVCenter | ALIGNMENT_MAP[self.alignment_map.get(cname,
|
||||||
'left')]
|
'left')]
|
||||||
return QVariant(ans)
|
return (ans)
|
||||||
return NONE
|
return None
|
||||||
|
|
||||||
def headerData(self, section, orientation, role):
|
def headerData(self, section, orientation, role):
|
||||||
if role == Qt.ToolTipRole and orientation == Qt.Horizontal:
|
if role == Qt.ToolTipRole and orientation == Qt.Horizontal:
|
||||||
return QVariant(_('The lookup/search name is "{0}"').format(self.column_map[section]))
|
return (_('The lookup/search name is "{0}"').format(self.column_map[section]))
|
||||||
if DEBUG and role == Qt.ToolTipRole and orientation == Qt.Vertical:
|
if DEBUG and role == Qt.ToolTipRole and orientation == Qt.Vertical:
|
||||||
return QVariant(_('This book\'s UUID is "{0}"').format(self.db[self.map[section]].uuid))
|
return (_('This book\'s UUID is "{0}"').format(self.db[self.map[section]].uuid))
|
||||||
if role != Qt.DisplayRole:
|
if role != Qt.DisplayRole:
|
||||||
return NONE
|
return None
|
||||||
if orientation == Qt.Horizontal:
|
if orientation == Qt.Horizontal:
|
||||||
cname = self.column_map[section]
|
cname = self.column_map[section]
|
||||||
text = self.headers[cname]
|
text = self.headers[cname]
|
||||||
return QVariant(text)
|
return (text)
|
||||||
else:
|
else:
|
||||||
return QVariant(section+1)
|
return (section+1)
|
||||||
|
|
||||||
def setData(self, index, value, role):
|
def setData(self, index, value, role):
|
||||||
done = False
|
done = False
|
||||||
@ -1612,7 +1611,7 @@ class DeviceBooksModel(BooksModel): # {{{
|
|||||||
cname = self.column_map[col]
|
cname = self.column_map[col]
|
||||||
if cname in ('size', 'timestamp', 'inlibrary'):
|
if cname in ('size', 'timestamp', 'inlibrary'):
|
||||||
return False
|
return False
|
||||||
val = unicode(value.toString()).strip()
|
val = unicode(value or '').strip()
|
||||||
idx = self.map[row]
|
idx = self.map[row]
|
||||||
if cname == 'collections':
|
if cname == 'collections':
|
||||||
tags = [i.strip() for i in val.split(',')]
|
tags = [i.strip() for i in val.split(',')]
|
||||||
|
@ -8,7 +8,7 @@ __docformat__ = 'restructuredtext en'
|
|||||||
import textwrap, os
|
import textwrap, os
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from PyQt5.Qt import (Qt, QModelIndex, QAbstractItemModel, QVariant, QIcon,
|
from PyQt5.Qt import (Qt, QModelIndex, QAbstractItemModel, QIcon,
|
||||||
QBrush)
|
QBrush)
|
||||||
|
|
||||||
from calibre.gui2.preferences import ConfigWidgetBase, test_widget
|
from calibre.gui2.preferences import ConfigWidgetBase, test_widget
|
||||||
@ -16,7 +16,7 @@ from calibre.gui2.preferences.plugins_ui import Ui_Form
|
|||||||
from calibre.customize.ui import (initialized_plugins, is_disabled, enable_plugin,
|
from calibre.customize.ui import (initialized_plugins, is_disabled, enable_plugin,
|
||||||
disable_plugin, plugin_customization, add_plugin,
|
disable_plugin, plugin_customization, add_plugin,
|
||||||
remove_plugin, NameConflict)
|
remove_plugin, NameConflict)
|
||||||
from calibre.gui2 import (NONE, error_dialog, info_dialog, choose_files,
|
from calibre.gui2 import (error_dialog, info_dialog, choose_files,
|
||||||
question_dialog, gprefs)
|
question_dialog, gprefs)
|
||||||
from calibre.gui2.dialogs.confirm_delete import confirm
|
from calibre.gui2.dialogs.confirm_delete import confirm
|
||||||
from calibre.utils.search_query_parser import SearchQueryParser
|
from calibre.utils.search_query_parser import SearchQueryParser
|
||||||
@ -29,9 +29,9 @@ class PluginModel(QAbstractItemModel, SearchQueryParser): # {{{
|
|||||||
QAbstractItemModel.__init__(self)
|
QAbstractItemModel.__init__(self)
|
||||||
SearchQueryParser.__init__(self, ['all'])
|
SearchQueryParser.__init__(self, ['all'])
|
||||||
self.show_only_user_plugins = show_only_user_plugins
|
self.show_only_user_plugins = show_only_user_plugins
|
||||||
self.icon = QVariant(QIcon(I('plugins.png')))
|
self.icon = QIcon(I('plugins.png'))
|
||||||
p = QIcon(self.icon).pixmap(64, 64, QIcon.Disabled, QIcon.On)
|
p = QIcon(self.icon).pixmap(64, 64, QIcon.Disabled, QIcon.On)
|
||||||
self.disabled_icon = QVariant(QIcon(p))
|
self.disabled_icon = QIcon(p)
|
||||||
self._p = p
|
self._p = p
|
||||||
self.populate()
|
self.populate()
|
||||||
|
|
||||||
@ -187,11 +187,11 @@ class PluginModel(QAbstractItemModel, SearchQueryParser): # {{{
|
|||||||
|
|
||||||
def data(self, index, role):
|
def data(self, index, role):
|
||||||
if not index.isValid():
|
if not index.isValid():
|
||||||
return NONE
|
return None
|
||||||
if index.internalId() == 0:
|
if index.internalId() == 0:
|
||||||
if role == Qt.DisplayRole:
|
if role == Qt.DisplayRole:
|
||||||
category = self.categories[index.row()]
|
category = self.categories[index.row()]
|
||||||
return QVariant(_("%(plugin_type)s %(plugins)s")%
|
return (_("%(plugin_type)s %(plugins)s")%
|
||||||
dict(plugin_type=category, plugins=_('plugins')))
|
dict(plugin_type=category, plugins=_('plugins')))
|
||||||
else:
|
else:
|
||||||
plugin = self.index_to_plugin(index)
|
plugin = self.index_to_plugin(index)
|
||||||
@ -205,14 +205,14 @@ class PluginModel(QAbstractItemModel, SearchQueryParser): # {{{
|
|||||||
ans += _('\nCustomization: ')+c
|
ans += _('\nCustomization: ')+c
|
||||||
if disabled:
|
if disabled:
|
||||||
ans += _('\n\nThis plugin has been disabled')
|
ans += _('\n\nThis plugin has been disabled')
|
||||||
return QVariant(ans)
|
return (ans)
|
||||||
if role == Qt.DecorationRole:
|
if role == Qt.DecorationRole:
|
||||||
return self.disabled_icon if disabled else self.icon
|
return self.disabled_icon if disabled else self.icon
|
||||||
if role == Qt.ForegroundRole and disabled:
|
if role == Qt.ForegroundRole and disabled:
|
||||||
return QVariant(QBrush(Qt.gray))
|
return (QBrush(Qt.gray))
|
||||||
if role == Qt.UserRole:
|
if role == Qt.UserRole:
|
||||||
return plugin
|
return plugin
|
||||||
return NONE
|
return None
|
||||||
|
|
||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
@ -333,7 +333,7 @@ class ConfigWidget(ConfigWidgetBase, Ui_Form):
|
|||||||
index = self.plugin_view.currentIndex()
|
index = self.plugin_view.currentIndex()
|
||||||
if index.isValid():
|
if index.isValid():
|
||||||
if not index.parent().isValid():
|
if not index.parent().isValid():
|
||||||
name = unicode(index.data().toString())
|
name = unicode(index.data() or '')
|
||||||
return error_dialog(self, _('Error'), '<p>'+
|
return error_dialog(self, _('Error'), '<p>'+
|
||||||
_('Select an actual plugin under <b>%s</b> to customize')%name,
|
_('Select an actual plugin under <b>%s</b> to customize')%name,
|
||||||
show=True, show_copy_button=False)
|
show=True, show_copy_button=False)
|
||||||
|
@ -398,7 +398,10 @@ class SavedSearchBox(QComboBox): # {{{
|
|||||||
|
|
||||||
class SearchBoxMixin(object): # {{{
|
class SearchBoxMixin(object): # {{{
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def init_search_box_mixin(self):
|
||||||
self.search.initialize('main_search_history', colorize=True,
|
self.search.initialize('main_search_history', colorize=True,
|
||||||
help_text=_('Search (For Advanced Search click the button to the left)'))
|
help_text=_('Search (For Advanced Search click the button to the left)'))
|
||||||
self.search.cleared.connect(self.search_box_cleared)
|
self.search.cleared.connect(self.search_box_cleared)
|
||||||
@ -413,7 +416,7 @@ class SearchBoxMixin(object): # {{{
|
|||||||
self.search.setMaximumWidth(self.width()-150)
|
self.search.setMaximumWidth(self.width()-150)
|
||||||
self.action_focus_search = QAction(self)
|
self.action_focus_search = QAction(self)
|
||||||
shortcuts = list(
|
shortcuts = list(
|
||||||
map(lambda x:unicode(x.toString()),
|
map(lambda x:unicode(x.toString(QKeySequence.PortableText)),
|
||||||
QKeySequence.keyBindings(QKeySequence.Find)))
|
QKeySequence.keyBindings(QKeySequence.Find)))
|
||||||
shortcuts += ['/', 'Alt+S']
|
shortcuts += ['/', 'Alt+S']
|
||||||
self.keyboard.register_shortcut('start search', _('Start search'),
|
self.keyboard.register_shortcut('start search', _('Start search'),
|
||||||
@ -478,7 +481,10 @@ class SearchBoxMixin(object): # {{{
|
|||||||
|
|
||||||
class SavedSearchBoxMixin(object): # {{{
|
class SavedSearchBoxMixin(object): # {{{
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def init_saved_seach_box_mixin(self):
|
||||||
self.saved_search.changed.connect(self.saved_searches_changed)
|
self.saved_search.changed.connect(self.saved_searches_changed)
|
||||||
self.clear_button.clicked.connect(self.saved_search.clear)
|
self.clear_button.clicked.connect(self.saved_search.clear)
|
||||||
self.save_search_button.clicked.connect(
|
self.save_search_button.clicked.connect(
|
||||||
|
@ -50,7 +50,7 @@ class SelectNames(QDialog): # {{{
|
|||||||
@property
|
@property
|
||||||
def names(self):
|
def names(self):
|
||||||
for item in self._names.selectedItems():
|
for item in self._names.selectedItems():
|
||||||
yield unicode(item.data(Qt.DisplayRole).toString())
|
yield unicode(item.data(Qt.DisplayRole) or '')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def match_type(self):
|
def match_type(self):
|
||||||
@ -231,7 +231,7 @@ class CreateVirtualLibrary(QDialog): # {{{
|
|||||||
return
|
return
|
||||||
self.new_name = self.editing = self.vl_name.currentText()
|
self.new_name = self.editing = self.vl_name.currentText()
|
||||||
self.original_index = dex
|
self.original_index = dex
|
||||||
self.original_search = unicode(self.vl_name.itemData(dex).toString())
|
self.original_search = unicode(self.vl_name.itemData(dex) or '')
|
||||||
self.vl_text.setText(self.original_search)
|
self.vl_text.setText(self.original_search)
|
||||||
|
|
||||||
def link_activated(self, url):
|
def link_activated(self, url):
|
||||||
@ -308,7 +308,10 @@ class SearchRestrictionMixin(object):
|
|||||||
|
|
||||||
no_restriction = _('<None>')
|
no_restriction = _('<None>')
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def init_search_restirction_mixin(self):
|
||||||
self.checked = QIcon(I('ok.png'))
|
self.checked = QIcon(I('ok.png'))
|
||||||
self.empty = QIcon(I('blank.png'))
|
self.empty = QIcon(I('blank.png'))
|
||||||
self.current_search_action = QAction(self.empty, _('*current search'), self)
|
self.current_search_action = QAction(self.empty, _('*current search'), self)
|
||||||
|
@ -8,9 +8,8 @@ __docformat__ = 'restructuredtext en'
|
|||||||
|
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
|
|
||||||
from PyQt5.Qt import (Qt, QAbstractItemModel, QModelIndex, QVariant, pyqtSignal)
|
from PyQt5.Qt import (Qt, QAbstractItemModel, QModelIndex, pyqtSignal)
|
||||||
|
|
||||||
from calibre.gui2 import NONE
|
|
||||||
from calibre.db.search import _match, CONTAINS_MATCH, EQUALS_MATCH, REGEXP_MATCH
|
from calibre.db.search import _match, CONTAINS_MATCH, EQUALS_MATCH, REGEXP_MATCH
|
||||||
from calibre.utils.config_base import prefs
|
from calibre.utils.config_base import prefs
|
||||||
from calibre.utils.icu import sort_key
|
from calibre.utils.icu import sort_key
|
||||||
@ -67,26 +66,26 @@ class BooksModel(QAbstractItemModel):
|
|||||||
|
|
||||||
def headerData(self, section, orientation, role):
|
def headerData(self, section, orientation, role):
|
||||||
if role != Qt.DisplayRole:
|
if role != Qt.DisplayRole:
|
||||||
return NONE
|
return None
|
||||||
text = ''
|
text = ''
|
||||||
if orientation == Qt.Horizontal:
|
if orientation == Qt.Horizontal:
|
||||||
if section < len(self.HEADERS):
|
if section < len(self.HEADERS):
|
||||||
text = self.HEADERS[section]
|
text = self.HEADERS[section]
|
||||||
return QVariant(text)
|
return (text)
|
||||||
else:
|
else:
|
||||||
return QVariant(section+1)
|
return (section+1)
|
||||||
|
|
||||||
def data(self, index, role):
|
def data(self, index, role):
|
||||||
row, col = index.row(), index.column()
|
row, col = index.row(), index.column()
|
||||||
result = self.books[row]
|
result = self.books[row]
|
||||||
if role == Qt.DisplayRole:
|
if role == Qt.DisplayRole:
|
||||||
if col == 0:
|
if col == 0:
|
||||||
return QVariant(result.title)
|
return (result.title)
|
||||||
elif col == 1:
|
elif col == 1:
|
||||||
return QVariant(result.author)
|
return (result.author)
|
||||||
elif col == 2:
|
elif col == 2:
|
||||||
return QVariant(result.formats)
|
return (result.formats)
|
||||||
return NONE
|
return None
|
||||||
|
|
||||||
def data_as_text(self, result, col):
|
def data_as_text(self, result, col):
|
||||||
text = ''
|
text = ''
|
||||||
|
@ -10,11 +10,11 @@ __docformat__ = 'restructuredtext en'
|
|||||||
|
|
||||||
import traceback, cPickle, copy, os
|
import traceback, cPickle, copy, os
|
||||||
|
|
||||||
from PyQt5.Qt import (QAbstractItemModel, QIcon, QVariant, QFont, Qt,
|
from PyQt5.Qt import (QAbstractItemModel, QIcon, QFont, Qt,
|
||||||
QMimeData, QModelIndex, pyqtSignal, QObject)
|
QMimeData, QModelIndex, pyqtSignal, QObject)
|
||||||
|
|
||||||
from calibre.constants import config_dir
|
from calibre.constants import config_dir
|
||||||
from calibre.gui2 import NONE, gprefs, config, error_dialog
|
from calibre.gui2 import gprefs, config, error_dialog
|
||||||
from calibre.db.categories import Tag
|
from calibre.db.categories import Tag
|
||||||
from calibre.utils.config import tweaks
|
from calibre.utils.config import tweaks
|
||||||
from calibre.utils.icu import sort_key, lower, strcmp, collation_order
|
from calibre.utils.icu import sort_key, lower, strcmp, collation_order
|
||||||
@ -31,7 +31,7 @@ def bf():
|
|||||||
if _bf is None:
|
if _bf is None:
|
||||||
_bf = QFont()
|
_bf = QFont()
|
||||||
_bf.setBold(True)
|
_bf.setBold(True)
|
||||||
_bf = QVariant(_bf)
|
_bf = (_bf)
|
||||||
return _bf
|
return _bf
|
||||||
|
|
||||||
class TagTreeItem(object): # {{{
|
class TagTreeItem(object): # {{{
|
||||||
@ -48,7 +48,7 @@ class TagTreeItem(object): # {{{
|
|||||||
self.id_set = set()
|
self.id_set = set()
|
||||||
self.is_gst = False
|
self.is_gst = False
|
||||||
self.boxed = False
|
self.boxed = False
|
||||||
self.icon_state_map = list(map(QVariant, icon_map))
|
self.icon_state_map = list(icon_map)
|
||||||
if self.parent is not None:
|
if self.parent is not None:
|
||||||
self.parent.append(self)
|
self.parent.append(self)
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ class TagTreeItem(object): # {{{
|
|||||||
self.type = self.TAG if category_icon is None else self.CATEGORY
|
self.type = self.TAG if category_icon is None else self.CATEGORY
|
||||||
|
|
||||||
if self.type == self.CATEGORY:
|
if self.type == self.CATEGORY:
|
||||||
self.name, self.icon = map(QVariant, (data, category_icon))
|
self.name, self.icon = data, category_icon
|
||||||
self.py_name = data
|
self.py_name = data
|
||||||
self.category_key = category_key
|
self.category_key = category_key
|
||||||
self.temporary = temporary
|
self.temporary = temporary
|
||||||
@ -67,7 +67,7 @@ class TagTreeItem(object): # {{{
|
|||||||
['news', 'search', 'identifiers', 'languages'],
|
['news', 'search', 'identifiers', 'languages'],
|
||||||
is_searchable=category_key not in ['search'])
|
is_searchable=category_key not in ['search'])
|
||||||
elif self.type == self.TAG:
|
elif self.type == self.TAG:
|
||||||
self.icon_state_map[0] = QVariant(data.icon)
|
self.icon_state_map[0] = (data.icon)
|
||||||
self.tag = data
|
self.tag = data
|
||||||
|
|
||||||
self.tooltip = (tooltip + ' ') if tooltip else ''
|
self.tooltip = (tooltip + ' ') if tooltip else ''
|
||||||
@ -80,8 +80,8 @@ class TagTreeItem(object): # {{{
|
|||||||
if self.type == self.ROOT:
|
if self.type == self.ROOT:
|
||||||
return 'ROOT'
|
return 'ROOT'
|
||||||
if self.type == self.CATEGORY:
|
if self.type == self.CATEGORY:
|
||||||
return 'CATEGORY:'+str(QVariant.toString(
|
return 'CATEGORY:'+str(
|
||||||
self.name))+':%d'%len(getattr(self,
|
self.name)+':%d'%len(getattr(self,
|
||||||
'children', []))
|
'children', []))
|
||||||
return 'TAG: %s'%self.tag.name
|
return 'TAG: %s'%self.tag.name
|
||||||
|
|
||||||
@ -101,13 +101,13 @@ class TagTreeItem(object): # {{{
|
|||||||
return self.tag_data(role)
|
return self.tag_data(role)
|
||||||
if self.type == self.CATEGORY:
|
if self.type == self.CATEGORY:
|
||||||
return self.category_data(role)
|
return self.category_data(role)
|
||||||
return NONE
|
return None
|
||||||
|
|
||||||
def category_data(self, role):
|
def category_data(self, role):
|
||||||
if role == Qt.DisplayRole:
|
if role == Qt.DisplayRole:
|
||||||
return QVariant(self.py_name + ' [%d]'%len(self.child_tags()))
|
return (self.py_name + ' [%d]'%len(self.child_tags()))
|
||||||
if role == Qt.EditRole:
|
if role == Qt.EditRole:
|
||||||
return QVariant(self.py_name)
|
return (self.py_name)
|
||||||
if role == Qt.DecorationRole:
|
if role == Qt.DecorationRole:
|
||||||
if self.tag.state:
|
if self.tag.state:
|
||||||
return self.icon_state_map[self.tag.state]
|
return self.icon_state_map[self.tag.state]
|
||||||
@ -115,8 +115,8 @@ class TagTreeItem(object): # {{{
|
|||||||
if role == Qt.FontRole:
|
if role == Qt.FontRole:
|
||||||
return bf()
|
return bf()
|
||||||
if role == Qt.ToolTipRole and self.tooltip is not None:
|
if role == Qt.ToolTipRole and self.tooltip is not None:
|
||||||
return QVariant(self.tooltip)
|
return (self.tooltip)
|
||||||
return NONE
|
return None
|
||||||
|
|
||||||
def tag_data(self, role):
|
def tag_data(self, role):
|
||||||
tag = self.tag
|
tag = self.tag
|
||||||
@ -136,24 +136,24 @@ class TagTreeItem(object): # {{{
|
|||||||
count = len(self.id_set)
|
count = len(self.id_set)
|
||||||
count = count if count > 0 else tag.count
|
count = count if count > 0 else tag.count
|
||||||
if count == 0:
|
if count == 0:
|
||||||
return QVariant('%s'%(name))
|
return ('%s'%(name))
|
||||||
else:
|
else:
|
||||||
return QVariant('[%d] %s'%(count, name))
|
return ('[%d] %s'%(count, name))
|
||||||
if role == Qt.EditRole:
|
if role == Qt.EditRole:
|
||||||
return QVariant(tag.original_name)
|
return (tag.original_name)
|
||||||
if role == Qt.DecorationRole:
|
if role == Qt.DecorationRole:
|
||||||
return self.icon_state_map[tag.state]
|
return self.icon_state_map[tag.state]
|
||||||
if role == Qt.ToolTipRole:
|
if role == Qt.ToolTipRole:
|
||||||
if tt_author:
|
if tt_author:
|
||||||
if tag.tooltip is not None:
|
if tag.tooltip is not None:
|
||||||
return QVariant('(%s) %s'%(tag.name, tag.tooltip))
|
return ('(%s) %s'%(tag.name, tag.tooltip))
|
||||||
else:
|
else:
|
||||||
return QVariant(tag.name)
|
return (tag.name)
|
||||||
if tag.tooltip:
|
if tag.tooltip:
|
||||||
return QVariant(self.tooltip + tag.tooltip)
|
return (self.tooltip + tag.tooltip)
|
||||||
else:
|
else:
|
||||||
return QVariant(self.tooltip)
|
return (self.tooltip)
|
||||||
return NONE
|
return None
|
||||||
|
|
||||||
def toggle(self, set_to=None):
|
def toggle(self, set_to=None):
|
||||||
'''
|
'''
|
||||||
@ -940,7 +940,7 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
|
|
||||||
def data(self, index, role):
|
def data(self, index, role):
|
||||||
if not index.isValid():
|
if not index.isValid():
|
||||||
return NONE
|
return None
|
||||||
item = self.get_node(index)
|
item = self.get_node(index)
|
||||||
return item.data(role)
|
return item.data(role)
|
||||||
|
|
||||||
@ -950,7 +950,7 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
# set up to reposition at the same item. We can do this except if
|
# set up to reposition at the same item. We can do this except if
|
||||||
# working with the last item and that item is deleted, in which case
|
# working with the last item and that item is deleted, in which case
|
||||||
# we position at the parent label
|
# we position at the parent label
|
||||||
val = unicode(value.toString()).strip()
|
val = unicode(value or '').strip()
|
||||||
if not val:
|
if not val:
|
||||||
error_dialog(self.gui_parent, _('Item is blank'),
|
error_dialog(self.gui_parent, _('Item is blank'),
|
||||||
_('An item cannot be set to nothing. Delete it instead.')).exec_()
|
_('An item cannot be set to nothing. Delete it instead.')).exec_()
|
||||||
@ -1014,7 +1014,7 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
error_dialog(self.gui_parent, _('Duplicate search name'),
|
error_dialog(self.gui_parent, _('Duplicate search name'),
|
||||||
_('The saved search name %s is already used.')%val).exec_()
|
_('The saved search name %s is already used.')%val).exec_()
|
||||||
return False
|
return False
|
||||||
self.db.saved_search_rename(unicode(item.data(role).toString()), val)
|
self.db.saved_search_rename(unicode(item.data(role) or ''), val)
|
||||||
item.tag.name = val
|
item.tag.name = val
|
||||||
self.search_item_renamed.emit() # Does a refresh
|
self.search_item_renamed.emit() # Does a refresh
|
||||||
else:
|
else:
|
||||||
@ -1079,7 +1079,7 @@ class TagsModel(QAbstractItemModel): # {{{
|
|||||||
self.db.prefs.set('user_categories', user_cats)
|
self.db.prefs.set('user_categories', user_cats)
|
||||||
|
|
||||||
def headerData(self, *args):
|
def headerData(self, *args):
|
||||||
return NONE
|
return None
|
||||||
|
|
||||||
def flags(self, index, *args):
|
def flags(self, index, *args):
|
||||||
ans = Qt.ItemIsEnabled|Qt.ItemIsEditable
|
ans = Qt.ItemIsEnabled|Qt.ItemIsEditable
|
||||||
|
@ -25,7 +25,10 @@ from calibre.gui2.dialogs.edit_authors_dialog import EditAuthorsDialog
|
|||||||
|
|
||||||
class TagBrowserMixin(object): # {{{
|
class TagBrowserMixin(object): # {{{
|
||||||
|
|
||||||
def __init__(self, db):
|
def __init__(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def init_tag_browser_mixin(self, db):
|
||||||
self.library_view.model().count_changed_signal.connect(self.tags_view.recount)
|
self.library_view.model().count_changed_signal.connect(self.tags_view.recount)
|
||||||
self.tags_view.set_database(db, self.alter_tb)
|
self.tags_view.set_database(db, self.alter_tb)
|
||||||
self.tags_view.tags_marked.connect(self.search.set_search_string)
|
self.tags_view.tags_marked.connect(self.search.set_search_string)
|
||||||
|
@ -245,7 +245,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
|||||||
_('&Donate to support calibre'), self)
|
_('&Donate to support calibre'), self)
|
||||||
for st in self.istores.values():
|
for st in self.istores.values():
|
||||||
st.do_genesis()
|
st.do_genesis()
|
||||||
MainWindowMixin.__init__(self, db)
|
MainWindowMixin.init_main_window_mixin(self, db)
|
||||||
|
|
||||||
# Jobs Button {{{
|
# Jobs Button {{{
|
||||||
self.job_manager = JobManager()
|
self.job_manager = JobManager()
|
||||||
@ -254,10 +254,8 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
|||||||
self.jobs_button.initialize(self.jobs_dialog, self.job_manager)
|
self.jobs_button.initialize(self.jobs_dialog, self.job_manager)
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
LayoutMixin.__init__(self)
|
LayoutMixin.init_layout_mixin(self)
|
||||||
EmailMixin.__init__(self)
|
DeviceMixin.init_device_mixin(self)
|
||||||
EbookDownloadMixin.__init__(self)
|
|
||||||
DeviceMixin.__init__(self)
|
|
||||||
|
|
||||||
self.progress_indicator = ProgressIndicator(self)
|
self.progress_indicator = ProgressIndicator(self)
|
||||||
self.progress_indicator.pos = (0, 20)
|
self.progress_indicator.pos = (0, 20)
|
||||||
@ -335,15 +333,15 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
|||||||
self.eject_action.triggered.connect(self.device_manager.umount_device)
|
self.eject_action.triggered.connect(self.device_manager.umount_device)
|
||||||
|
|
||||||
#################### Update notification ###################
|
#################### Update notification ###################
|
||||||
UpdateMixin.__init__(self, opts)
|
UpdateMixin.init_update_mixin(self, opts)
|
||||||
|
|
||||||
####################### Search boxes ########################
|
####################### Search boxes ########################
|
||||||
SearchRestrictionMixin.__init__(self)
|
SearchRestrictionMixin.init_search_restirction_mixin(self)
|
||||||
SavedSearchBoxMixin.__init__(self)
|
SavedSearchBoxMixin.init_saved_seach_box_mixin(self)
|
||||||
|
|
||||||
####################### Library view ########################
|
####################### Library view ########################
|
||||||
LibraryViewMixin.__init__(self, db)
|
LibraryViewMixin.init_library_view_mixin(self, db)
|
||||||
SearchBoxMixin.__init__(self) # Requires current_db
|
SearchBoxMixin.init_search_box_mixin(self) # Requires current_db
|
||||||
|
|
||||||
if show_gui:
|
if show_gui:
|
||||||
self.show()
|
self.show()
|
||||||
@ -369,7 +367,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
|||||||
type=Qt.QueuedConnection)
|
type=Qt.QueuedConnection)
|
||||||
|
|
||||||
########################### Tags Browser ##############################
|
########################### Tags Browser ##############################
|
||||||
TagBrowserMixin.__init__(self, db)
|
TagBrowserMixin.init_tag_browser_mixin(self, db)
|
||||||
|
|
||||||
######################### Search Restriction ##########################
|
######################### Search Restriction ##########################
|
||||||
if db.prefs['virtual_lib_on_startup']:
|
if db.prefs['virtual_lib_on_startup']:
|
||||||
@ -378,7 +376,7 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{
|
|||||||
|
|
||||||
########################### Cover Flow ################################
|
########################### Cover Flow ################################
|
||||||
|
|
||||||
CoverFlowMixin.__init__(self)
|
CoverFlowMixin.init_cover_flow_mixin(self)
|
||||||
|
|
||||||
self._calculated_available_height = min(max_available_height()-15,
|
self._calculated_available_height = min(max_available_height()-15,
|
||||||
self.height())
|
self.height())
|
||||||
|
@ -134,7 +134,10 @@ class UpdateNotification(QDialog):
|
|||||||
|
|
||||||
class UpdateMixin(object):
|
class UpdateMixin(object):
|
||||||
|
|
||||||
def __init__(self, opts):
|
def __init__(self, *args, **kw):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def init_update_mixin(self, opts):
|
||||||
self.last_newest_calibre_version = NO_CALIBRE_UPDATE
|
self.last_newest_calibre_version = NO_CALIBRE_UPDATE
|
||||||
if not opts.no_update_check:
|
if not opts.no_update_check:
|
||||||
self.update_checker = CheckForUpdates(self)
|
self.update_checker = CheckForUpdates(self)
|
||||||
|
@ -8,11 +8,10 @@ __docformat__ = 'restructuredtext en'
|
|||||||
|
|
||||||
import copy, zipfile
|
import copy, zipfile
|
||||||
|
|
||||||
from PyQt5.Qt import QAbstractItemModel, QVariant, Qt, QColor, QFont, QIcon, \
|
from PyQt5.Qt import QAbstractItemModel, Qt, QColor, QFont, QIcon, \
|
||||||
QModelIndex, pyqtSignal, QPixmap
|
QModelIndex, pyqtSignal, QPixmap
|
||||||
|
|
||||||
from calibre.utils.search_query_parser import SearchQueryParser
|
from calibre.utils.search_query_parser import SearchQueryParser
|
||||||
from calibre.gui2 import NONE
|
|
||||||
from calibre.utils.localization import get_language
|
from calibre.utils.localization import get_language
|
||||||
from calibre.web.feeds.recipes.collection import \
|
from calibre.web.feeds.recipes.collection import \
|
||||||
get_builtin_recipe_collection, get_custom_recipe_collection, \
|
get_builtin_recipe_collection, get_custom_recipe_collection, \
|
||||||
@ -41,7 +40,7 @@ class NewsTreeItem(object):
|
|||||||
self.children.append(child)
|
self.children.append(child)
|
||||||
|
|
||||||
def data(self, role):
|
def data(self, role):
|
||||||
return NONE
|
return None
|
||||||
|
|
||||||
def flags(self):
|
def flags(self):
|
||||||
return Qt.ItemIsEnabled|Qt.ItemIsSelectable
|
return Qt.ItemIsEnabled|Qt.ItemIsSelectable
|
||||||
@ -65,16 +64,16 @@ class NewsCategory(NewsTreeItem):
|
|||||||
self.cdata = get_language(self.category)
|
self.cdata = get_language(self.category)
|
||||||
self.bold_font = QFont()
|
self.bold_font = QFont()
|
||||||
self.bold_font.setBold(True)
|
self.bold_font.setBold(True)
|
||||||
self.bold_font = QVariant(self.bold_font)
|
self.bold_font = (self.bold_font)
|
||||||
|
|
||||||
def data(self, role):
|
def data(self, role):
|
||||||
if role == Qt.DisplayRole:
|
if role == Qt.DisplayRole:
|
||||||
return QVariant(self.cdata + ' [%d]'%len(self.children))
|
return (self.cdata + ' [%d]'%len(self.children))
|
||||||
elif role == Qt.FontRole:
|
elif role == Qt.FontRole:
|
||||||
return self.bold_font
|
return self.bold_font
|
||||||
elif role == Qt.ForegroundRole and self.category == _('Scheduled'):
|
elif role == Qt.ForegroundRole and self.category == _('Scheduled'):
|
||||||
return QVariant(QColor(0, 255, 0))
|
return (QColor(0, 255, 0))
|
||||||
return NONE
|
return None
|
||||||
|
|
||||||
def flags(self):
|
def flags(self):
|
||||||
return Qt.ItemIsEnabled
|
return Qt.ItemIsEnabled
|
||||||
@ -106,7 +105,7 @@ class NewsItem(NewsTreeItem):
|
|||||||
|
|
||||||
def data(self, role):
|
def data(self, role):
|
||||||
if role == Qt.DisplayRole:
|
if role == Qt.DisplayRole:
|
||||||
return QVariant(self.title)
|
return (self.title)
|
||||||
if role == Qt.DecorationRole:
|
if role == Qt.DecorationRole:
|
||||||
if self.icon is None:
|
if self.icon is None:
|
||||||
icon = '%s.png'%self.urn[8:]
|
icon = '%s.png'%self.urn[8:]
|
||||||
@ -118,11 +117,11 @@ class NewsItem(NewsTreeItem):
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
if not p.isNull():
|
if not p.isNull():
|
||||||
self.icon = QVariant(QIcon(p))
|
self.icon = (QIcon(p))
|
||||||
else:
|
else:
|
||||||
self.icon = self.default_icon
|
self.icon = self.default_icon
|
||||||
return self.icon
|
return self.icon
|
||||||
return NONE
|
return None
|
||||||
|
|
||||||
def __cmp__(self, other):
|
def __cmp__(self, other):
|
||||||
return cmp(self.title.lower(), getattr(other, 'title', '').lower())
|
return cmp(self.title.lower(), getattr(other, 'title', '').lower())
|
||||||
@ -135,8 +134,8 @@ class RecipeModel(QAbstractItemModel, SearchQueryParser):
|
|||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
QAbstractItemModel.__init__(self, *args)
|
QAbstractItemModel.__init__(self, *args)
|
||||||
SearchQueryParser.__init__(self, locations=['all'])
|
SearchQueryParser.__init__(self, locations=['all'])
|
||||||
self.default_icon = QVariant(QIcon(I('news.png')))
|
self.default_icon = (QIcon(I('news.png')))
|
||||||
self.custom_icon = QVariant(QIcon(I('user_profile.png')))
|
self.custom_icon = (QIcon(I('user_profile.png')))
|
||||||
self.builtin_recipe_collection = get_builtin_recipe_collection()
|
self.builtin_recipe_collection = get_builtin_recipe_collection()
|
||||||
self.scheduler_config = SchedulerConfig()
|
self.scheduler_config = SchedulerConfig()
|
||||||
try:
|
try:
|
||||||
@ -300,12 +299,12 @@ class RecipeModel(QAbstractItemModel, SearchQueryParser):
|
|||||||
|
|
||||||
def data(self, index, role):
|
def data(self, index, role):
|
||||||
if not index.isValid():
|
if not index.isValid():
|
||||||
return NONE
|
return None
|
||||||
item = index.internalPointer()
|
item = index.internalPointer()
|
||||||
return item.data(role)
|
return item.data(role)
|
||||||
|
|
||||||
def headerData(self, *args):
|
def headerData(self, *args):
|
||||||
return NONE
|
return None
|
||||||
|
|
||||||
def flags(self, index):
|
def flags(self, index):
|
||||||
if not index.isValid():
|
if not index.isValid():
|
||||||
|
Loading…
x
Reference in New Issue
Block a user