mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Merge from trunk
This commit is contained in:
commit
067964a5a2
@ -24,6 +24,8 @@ class PreferencesAction(InterfaceAction):
|
|||||||
pm.addAction(QIcon(I('config.png')), _('Change calibre behavior'), self.do_config)
|
pm.addAction(QIcon(I('config.png')), _('Change calibre behavior'), self.do_config)
|
||||||
pm.addAction(QIcon(I('wizard.png')), _('Run welcome wizard'),
|
pm.addAction(QIcon(I('wizard.png')), _('Run welcome wizard'),
|
||||||
self.gui.run_wizard)
|
self.gui.run_wizard)
|
||||||
|
pm.addAction(QIcon(I('plugins/plugin_updater.png')),
|
||||||
|
_('Get plugins to enhance calibre'), self.get_plugins)
|
||||||
if not DEBUG:
|
if not DEBUG:
|
||||||
pm.addSeparator()
|
pm.addSeparator()
|
||||||
ac = pm.addAction(QIcon(I('debug.png')), _('Restart in debug mode'),
|
ac = pm.addAction(QIcon(I('debug.png')), _('Restart in debug mode'),
|
||||||
@ -36,6 +38,12 @@ class PreferencesAction(InterfaceAction):
|
|||||||
for x in (self.gui.preferences_action, self.qaction):
|
for x in (self.gui.preferences_action, self.qaction):
|
||||||
x.triggered.connect(self.do_config)
|
x.triggered.connect(self.do_config)
|
||||||
|
|
||||||
|
def get_plugins(self):
|
||||||
|
from calibre.gui2.dialogs.plugin_updater import (PluginUpdaterDialog,
|
||||||
|
FILTER_NOT_INSTALLED)
|
||||||
|
d = PluginUpdaterDialog(self.gui,
|
||||||
|
initial_filter=FILTER_NOT_INSTALLED)
|
||||||
|
d.exec_()
|
||||||
|
|
||||||
def do_config(self, checked=False, initial_plugin=None,
|
def do_config(self, checked=False, initial_plugin=None,
|
||||||
close_after_initial=False):
|
close_after_initial=False):
|
||||||
|
@ -13,7 +13,7 @@ from PyQt4.Qt import (Qt, QUrl, QFrame, QVBoxLayout, QLabel, QBrush, QTextEdit,
|
|||||||
QComboBox, QAbstractItemView, QHBoxLayout, QDialogButtonBox,
|
QComboBox, QAbstractItemView, QHBoxLayout, QDialogButtonBox,
|
||||||
QAbstractTableModel, QVariant, QTableView, QModelIndex,
|
QAbstractTableModel, QVariant, QTableView, QModelIndex,
|
||||||
QSortFilterProxyModel, pyqtSignal, QAction, QIcon, QDialog,
|
QSortFilterProxyModel, pyqtSignal, QAction, QIcon, QDialog,
|
||||||
QFont, QPixmap)
|
QFont, QPixmap, QSize)
|
||||||
from PyQt4 import QtCore
|
from PyQt4 import QtCore
|
||||||
from calibre import browser, prints
|
from calibre import browser, prints
|
||||||
from calibre.constants import numeric_version, iswindows, isosx, DEBUG
|
from calibre.constants import numeric_version, iswindows, isosx, DEBUG
|
||||||
@ -135,6 +135,9 @@ class SizePersistedDialog(QDialog):
|
|||||||
This dialog is a base class for any dialogs that want their size/position
|
This dialog is a base class for any dialogs that want their size/position
|
||||||
restored when they are next opened.
|
restored when they are next opened.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
initial_extra_size = QSize(0, 0)
|
||||||
|
|
||||||
def __init__(self, parent, unique_pref_name):
|
def __init__(self, parent, unique_pref_name):
|
||||||
QDialog.__init__(self, parent)
|
QDialog.__init__(self, parent)
|
||||||
self.unique_pref_name = unique_pref_name
|
self.unique_pref_name = unique_pref_name
|
||||||
@ -143,7 +146,7 @@ class SizePersistedDialog(QDialog):
|
|||||||
|
|
||||||
def resize_dialog(self):
|
def resize_dialog(self):
|
||||||
if self.geom is None:
|
if self.geom is None:
|
||||||
self.resize(self.sizeHint())
|
self.resize(self.sizeHint()+self.initial_extra_size)
|
||||||
else:
|
else:
|
||||||
self.restoreGeometry(self.geom)
|
self.restoreGeometry(self.geom)
|
||||||
|
|
||||||
@ -181,6 +184,7 @@ class PluginFilterComboBox(QComboBox):
|
|||||||
|
|
||||||
|
|
||||||
class DisplayPlugin(object):
|
class DisplayPlugin(object):
|
||||||
|
|
||||||
def __init__(self, list_node):
|
def __init__(self, list_node):
|
||||||
# The html from the index web page looks like this:
|
# The html from the index web page looks like this:
|
||||||
'''
|
'''
|
||||||
@ -264,6 +268,7 @@ Platforms: Windows, OSX, Linux; History: Yes;</span></i></li>
|
|||||||
|
|
||||||
|
|
||||||
class DisplayPluginSortFilterModel(QSortFilterProxyModel):
|
class DisplayPluginSortFilterModel(QSortFilterProxyModel):
|
||||||
|
|
||||||
def __init__(self, parent):
|
def __init__(self, parent):
|
||||||
QSortFilterProxyModel.__init__(self, parent)
|
QSortFilterProxyModel.__init__(self, parent)
|
||||||
self.setSortRole(Qt.UserRole)
|
self.setSortRole(Qt.UserRole)
|
||||||
@ -288,6 +293,7 @@ class DisplayPluginSortFilterModel(QSortFilterProxyModel):
|
|||||||
|
|
||||||
|
|
||||||
class DisplayPluginModel(QAbstractTableModel):
|
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
|
||||||
@ -440,6 +446,7 @@ class DisplayPluginModel(QAbstractTableModel):
|
|||||||
class PluginUpdaterDialog(SizePersistedDialog):
|
class PluginUpdaterDialog(SizePersistedDialog):
|
||||||
|
|
||||||
update_found = pyqtSignal(object)
|
update_found = pyqtSignal(object)
|
||||||
|
initial_extra_size = QSize(350, 100)
|
||||||
|
|
||||||
def __init__(self, gui, initial_filter=FILTER_UPDATE_AVAILABLE):
|
def __init__(self, gui, initial_filter=FILTER_UPDATE_AVAILABLE):
|
||||||
SizePersistedDialog.__init__(self, gui, 'Plugin Updater plugin:plugin updater dialog')
|
SizePersistedDialog.__init__(self, gui, 'Plugin Updater plugin:plugin updater dialog')
|
||||||
@ -473,7 +480,7 @@ class PluginUpdaterDialog(SizePersistedDialog):
|
|||||||
self.setWindowTitle(_('Check for user plugin updates'))
|
self.setWindowTitle(_('Check for user plugin updates'))
|
||||||
layout = QVBoxLayout(self)
|
layout = QVBoxLayout(self)
|
||||||
self.setLayout(layout)
|
self.setLayout(layout)
|
||||||
title_layout = ImageTitleLayout(self, 'images/plugin_updater.png', _('User Plugin Status'))
|
title_layout = ImageTitleLayout(self, 'plugins/plugin_updater.png', _('User Plugin Status'))
|
||||||
layout.addLayout(title_layout)
|
layout.addLayout(title_layout)
|
||||||
|
|
||||||
header_layout = QHBoxLayout()
|
header_layout = QHBoxLayout()
|
||||||
@ -856,4 +863,4 @@ class PluginUpdaterDialog(SizePersistedDialog):
|
|||||||
pt = PersistentTemporaryFile('.zip')
|
pt = PersistentTemporaryFile('.zip')
|
||||||
pt.write(raw)
|
pt.write(raw)
|
||||||
pt.close()
|
pt.close()
|
||||||
return pt.name
|
return pt.name
|
||||||
|
@ -5,15 +5,15 @@ Miscellaneous widgets used in the GUI
|
|||||||
'''
|
'''
|
||||||
import re, traceback
|
import re, traceback
|
||||||
|
|
||||||
from PyQt4.Qt import QIcon, QFont, QLabel, QListWidget, QAction, \
|
from PyQt4.Qt import (QIcon, QFont, QLabel, QListWidget, QAction,
|
||||||
QListWidgetItem, QTextCharFormat, QApplication, \
|
QListWidgetItem, QTextCharFormat, QApplication,
|
||||||
QSyntaxHighlighter, QCursor, QColor, QWidget, \
|
QSyntaxHighlighter, QCursor, QColor, QWidget,
|
||||||
QPixmap, QSplitterHandle, QToolButton, \
|
QPixmap, QSplitterHandle, QToolButton,
|
||||||
QAbstractListModel, QVariant, Qt, SIGNAL, pyqtSignal, \
|
QAbstractListModel, QVariant, Qt, SIGNAL, pyqtSignal,
|
||||||
QRegExp, QSettings, QSize, QSplitter, \
|
QRegExp, QSettings, QSize, QSplitter,
|
||||||
QPainter, QLineEdit, QComboBox, QPen, QGraphicsScene, \
|
QPainter, QLineEdit, QComboBox, QPen, QGraphicsScene,
|
||||||
QMenu, QStringListModel, QCompleter, QStringList, \
|
QMenu, QStringListModel, QCompleter, QStringList,
|
||||||
QTimer, QRect, QFontDatabase, QGraphicsView
|
QTimer, QRect, QFontDatabase, QGraphicsView)
|
||||||
|
|
||||||
from calibre.gui2 import NONE, error_dialog, pixmap_to_data, gprefs
|
from calibre.gui2 import NONE, error_dialog, pixmap_to_data, gprefs
|
||||||
from calibre.gui2.filename_pattern_ui import Ui_Form
|
from calibre.gui2.filename_pattern_ui import Ui_Form
|
||||||
@ -21,12 +21,12 @@ from calibre import fit_image
|
|||||||
from calibre.ebooks import BOOK_EXTENSIONS
|
from calibre.ebooks import BOOK_EXTENSIONS
|
||||||
from calibre.utils.config import prefs, XMLConfig, tweaks
|
from calibre.utils.config import prefs, XMLConfig, tweaks
|
||||||
from calibre.gui2.progress_indicator import ProgressIndicator as _ProgressIndicator
|
from calibre.gui2.progress_indicator import ProgressIndicator as _ProgressIndicator
|
||||||
from calibre.gui2.dnd import dnd_has_image, dnd_get_image, dnd_get_files, \
|
from calibre.gui2.dnd import (dnd_has_image, dnd_get_image, dnd_get_files,
|
||||||
IMAGE_EXTENSIONS, dnd_has_extension, DownloadDialog
|
IMAGE_EXTENSIONS, dnd_has_extension, DownloadDialog)
|
||||||
|
|
||||||
history = XMLConfig('history')
|
history = XMLConfig('history')
|
||||||
|
|
||||||
class ProgressIndicator(QWidget):
|
class ProgressIndicator(QWidget): # {{{
|
||||||
|
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
QWidget.__init__(self, *args)
|
QWidget.__init__(self, *args)
|
||||||
@ -57,8 +57,9 @@ class ProgressIndicator(QWidget):
|
|||||||
def stop(self):
|
def stop(self):
|
||||||
self.pi.stopAnimation()
|
self.pi.stopAnimation()
|
||||||
self.setVisible(False)
|
self.setVisible(False)
|
||||||
|
# }}}
|
||||||
|
|
||||||
class FilenamePattern(QWidget, Ui_Form):
|
class FilenamePattern(QWidget, Ui_Form): # {{{
|
||||||
|
|
||||||
changed_signal = pyqtSignal()
|
changed_signal = pyqtSignal()
|
||||||
|
|
||||||
@ -148,8 +149,9 @@ class FilenamePattern(QWidget, Ui_Form):
|
|||||||
|
|
||||||
return pat
|
return pat
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
class FormatList(QListWidget):
|
class FormatList(QListWidget): # {{{
|
||||||
DROPABBLE_EXTENSIONS = BOOK_EXTENSIONS
|
DROPABBLE_EXTENSIONS = BOOK_EXTENSIONS
|
||||||
formats_dropped = pyqtSignal(object, object)
|
formats_dropped = pyqtSignal(object, object)
|
||||||
delete_format = pyqtSignal()
|
delete_format = pyqtSignal()
|
||||||
@ -188,6 +190,8 @@ class FormatList(QListWidget):
|
|||||||
else:
|
else:
|
||||||
return QListWidget.keyPressEvent(self, event)
|
return QListWidget.keyPressEvent(self, event)
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
class ImageDropMixin(object): # {{{
|
class ImageDropMixin(object): # {{{
|
||||||
'''
|
'''
|
||||||
Adds support for dropping images onto widgets and a context menu for
|
Adds support for dropping images onto widgets and a context menu for
|
||||||
@ -262,7 +266,7 @@ class ImageDropMixin(object): # {{{
|
|||||||
pixmap_to_data(pmap))
|
pixmap_to_data(pmap))
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
class ImageView(QWidget, ImageDropMixin):
|
class ImageView(QWidget, ImageDropMixin): # {{{
|
||||||
|
|
||||||
BORDER_WIDTH = 1
|
BORDER_WIDTH = 1
|
||||||
cover_changed = pyqtSignal(object)
|
cover_changed = pyqtSignal(object)
|
||||||
@ -314,8 +318,9 @@ class ImageView(QWidget, ImageDropMixin):
|
|||||||
p.drawRect(target)
|
p.drawRect(target)
|
||||||
#p.drawRect(self.rect())
|
#p.drawRect(self.rect())
|
||||||
p.end()
|
p.end()
|
||||||
|
# }}}
|
||||||
|
|
||||||
class CoverView(QGraphicsView, ImageDropMixin):
|
class CoverView(QGraphicsView, ImageDropMixin): # {{{
|
||||||
|
|
||||||
cover_changed = pyqtSignal(object)
|
cover_changed = pyqtSignal(object)
|
||||||
|
|
||||||
@ -333,7 +338,9 @@ class CoverView(QGraphicsView, ImageDropMixin):
|
|||||||
self.scene.addPixmap(pmap)
|
self.scene.addPixmap(pmap)
|
||||||
self.setScene(self.scene)
|
self.setScene(self.scene)
|
||||||
|
|
||||||
class FontFamilyModel(QAbstractListModel):
|
# }}}
|
||||||
|
|
||||||
|
class FontFamilyModel(QAbstractListModel): # {{{
|
||||||
|
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
QAbstractListModel.__init__(self, *args)
|
QAbstractListModel.__init__(self, *args)
|
||||||
@ -371,7 +378,9 @@ class FontFamilyModel(QAbstractListModel):
|
|||||||
|
|
||||||
def index_of(self, family):
|
def index_of(self, family):
|
||||||
return self.families.index(family.strip())
|
return self.families.index(family.strip())
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
# BasicList {{{
|
||||||
class BasicListItem(QListWidgetItem):
|
class BasicListItem(QListWidgetItem):
|
||||||
|
|
||||||
def __init__(self, text, user_data=None):
|
def __init__(self, text, user_data=None):
|
||||||
@ -404,9 +413,9 @@ class BasicList(QListWidget):
|
|||||||
def items(self):
|
def items(self):
|
||||||
for i in range(self.count()):
|
for i in range(self.count()):
|
||||||
yield self.item(i)
|
yield self.item(i)
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
class LineEditECM(object): # {{{
|
||||||
class LineEditECM(object):
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Extend the context menu of a QLineEdit to include more actions.
|
Extend the context menu of a QLineEdit to include more actions.
|
||||||
@ -449,8 +458,9 @@ class LineEditECM(object):
|
|||||||
from calibre.utils.icu import capitalize
|
from calibre.utils.icu import capitalize
|
||||||
self.setText(capitalize(unicode(self.text())))
|
self.setText(capitalize(unicode(self.text())))
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
class EnLineEdit(LineEditECM, QLineEdit):
|
class EnLineEdit(LineEditECM, QLineEdit): # {{{
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Enhanced QLineEdit.
|
Enhanced QLineEdit.
|
||||||
@ -459,9 +469,9 @@ class EnLineEdit(LineEditECM, QLineEdit):
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
class ItemsCompleter(QCompleter): # {{{
|
||||||
class ItemsCompleter(QCompleter):
|
|
||||||
|
|
||||||
'''
|
'''
|
||||||
A completer object that completes a list of tags. It is used in conjunction
|
A completer object that completes a list of tags. It is used in conjunction
|
||||||
@ -486,8 +496,9 @@ class ItemsCompleter(QCompleter):
|
|||||||
model = QStringListModel(items, self)
|
model = QStringListModel(items, self)
|
||||||
self.setModel(model)
|
self.setModel(model)
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
class CompleteLineEdit(EnLineEdit):
|
class CompleteLineEdit(EnLineEdit): # {{{
|
||||||
|
|
||||||
'''
|
'''
|
||||||
A QLineEdit that can complete parts of text separated by separator.
|
A QLineEdit that can complete parts of text separated by separator.
|
||||||
@ -550,8 +561,9 @@ class CompleteLineEdit(EnLineEdit):
|
|||||||
self.setText(complete_text_pat % (before_text[:cursor_pos - prefix_len], text, self.separator, after_text))
|
self.setText(complete_text_pat % (before_text[:cursor_pos - prefix_len], text, self.separator, after_text))
|
||||||
self.setCursorPosition(cursor_pos - prefix_len + len(text) + len_extra)
|
self.setCursorPosition(cursor_pos - prefix_len + len(text) + len_extra)
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
class EnComboBox(QComboBox):
|
class EnComboBox(QComboBox): # {{{
|
||||||
|
|
||||||
'''
|
'''
|
||||||
Enhanced QComboBox.
|
Enhanced QComboBox.
|
||||||
@ -575,7 +587,9 @@ class EnComboBox(QComboBox):
|
|||||||
idx = 0
|
idx = 0
|
||||||
self.setCurrentIndex(idx)
|
self.setCurrentIndex(idx)
|
||||||
|
|
||||||
class CompleteComboBox(EnComboBox):
|
# }}}
|
||||||
|
|
||||||
|
class CompleteComboBox(EnComboBox): # {{{
|
||||||
|
|
||||||
def __init__(self, *args):
|
def __init__(self, *args):
|
||||||
EnComboBox.__init__(self, *args)
|
EnComboBox.__init__(self, *args)
|
||||||
@ -590,8 +604,9 @@ class CompleteComboBox(EnComboBox):
|
|||||||
def set_space_before_sep(self, space_before):
|
def set_space_before_sep(self, space_before):
|
||||||
self.lineEdit().set_space_before_sep(space_before)
|
self.lineEdit().set_space_before_sep(space_before)
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
class HistoryLineEdit(QComboBox):
|
class HistoryLineEdit(QComboBox): # {{{
|
||||||
|
|
||||||
lost_focus = pyqtSignal()
|
lost_focus = pyqtSignal()
|
||||||
|
|
||||||
@ -638,7 +653,9 @@ class HistoryLineEdit(QComboBox):
|
|||||||
QComboBox.focusOutEvent(self, e)
|
QComboBox.focusOutEvent(self, e)
|
||||||
self.lost_focus.emit()
|
self.lost_focus.emit()
|
||||||
|
|
||||||
class ComboBoxWithHelp(QComboBox):
|
# }}}
|
||||||
|
|
||||||
|
class ComboBoxWithHelp(QComboBox): # {{{
|
||||||
'''
|
'''
|
||||||
A combobox where item 0 is help text. CurrentText will return '' for item 0.
|
A combobox where item 0 is help text. CurrentText will return '' for item 0.
|
||||||
Be sure to always fetch the text with currentText. Don't use the signals
|
Be sure to always fetch the text with currentText. Don't use the signals
|
||||||
@ -685,8 +702,9 @@ class ComboBoxWithHelp(QComboBox):
|
|||||||
QComboBox.hidePopup(self)
|
QComboBox.hidePopup(self)
|
||||||
self.set_state()
|
self.set_state()
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
class EncodingComboBox(QComboBox):
|
class EncodingComboBox(QComboBox): # {{{
|
||||||
'''
|
'''
|
||||||
A combobox that holds text encodings support
|
A combobox that holds text encodings support
|
||||||
by Python. This is only populated with the most
|
by Python. This is only populated with the most
|
||||||
@ -709,8 +727,9 @@ class EncodingComboBox(QComboBox):
|
|||||||
for item in self.ENCODINGS:
|
for item in self.ENCODINGS:
|
||||||
self.addItem(item)
|
self.addItem(item)
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
class PythonHighlighter(QSyntaxHighlighter):
|
class PythonHighlighter(QSyntaxHighlighter): # {{{
|
||||||
|
|
||||||
Rules = []
|
Rules = []
|
||||||
Formats = {}
|
Formats = {}
|
||||||
@ -948,6 +967,9 @@ class PythonHighlighter(QSyntaxHighlighter):
|
|||||||
QSyntaxHighlighter.rehighlight(self)
|
QSyntaxHighlighter.rehighlight(self)
|
||||||
QApplication.restoreOverrideCursor()
|
QApplication.restoreOverrideCursor()
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
# Splitter {{{
|
||||||
class SplitterHandle(QSplitterHandle):
|
class SplitterHandle(QSplitterHandle):
|
||||||
|
|
||||||
double_clicked = pyqtSignal(object)
|
double_clicked = pyqtSignal(object)
|
||||||
@ -1179,3 +1201,5 @@ class Splitter(QSplitter):
|
|||||||
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user