mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Start implementing preferences window
This commit is contained in:
parent
69b4202ad3
commit
2e99359763
@ -393,9 +393,16 @@ class PreferencesPlugin(Plugin): # {{{
|
|||||||
|
|
||||||
#: The category name displayed to the user for this plugin
|
#: The category name displayed to the user for this plugin
|
||||||
gui_category = None
|
gui_category = None
|
||||||
|
|
||||||
#: The name displayed to the user for this plugin
|
#: The name displayed to the user for this plugin
|
||||||
gui_name = None
|
gui_name = None
|
||||||
|
|
||||||
|
#: The icon for this plugin, should be an absolute path
|
||||||
|
icon = None
|
||||||
|
|
||||||
|
#: The description used for tooltips and the like
|
||||||
|
description = None
|
||||||
|
|
||||||
def create_widget(self, parent=None):
|
def create_widget(self, parent=None):
|
||||||
'''
|
'''
|
||||||
Create and return the actual Qt widget used for setting this group of
|
Create and return the actual Qt widget used for setting this group of
|
||||||
|
@ -678,138 +678,177 @@ plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog,
|
|||||||
|
|
||||||
class LookAndFeel(PreferencesPlugin):
|
class LookAndFeel(PreferencesPlugin):
|
||||||
name = 'Look & Feel'
|
name = 'Look & Feel'
|
||||||
|
icon = I('lookfeel.png')
|
||||||
gui_name = _('Look and Feel')
|
gui_name = _('Look and Feel')
|
||||||
category = 'Interface'
|
category = 'Interface'
|
||||||
gui_category = _('Interface')
|
gui_category = _('Interface')
|
||||||
category_order = 1
|
category_order = 1
|
||||||
name_order = 1
|
name_order = 1
|
||||||
config_widget = 'calibre.gui2.preferences.look_feel'
|
config_widget = 'calibre.gui2.preferences.look_feel'
|
||||||
|
description = _('Adjust the look and feel of the calibre interface'
|
||||||
|
' to suit your tastes')
|
||||||
|
|
||||||
class Behavior(PreferencesPlugin):
|
class Behavior(PreferencesPlugin):
|
||||||
name = 'Behavior'
|
name = 'Behavior'
|
||||||
|
icon = I('config.png')
|
||||||
gui_name = _('Behavior')
|
gui_name = _('Behavior')
|
||||||
category = 'Interface'
|
category = 'Interface'
|
||||||
gui_category = _('Interface')
|
gui_category = _('Interface')
|
||||||
category_order = 1
|
category_order = 1
|
||||||
name_order = 2
|
name_order = 2
|
||||||
config_widget = 'calibre.gui2.preferences.behavior'
|
config_widget = 'calibre.gui2.preferences.behavior'
|
||||||
|
description = _('Change the way calibre behaves')
|
||||||
|
|
||||||
class Columns(PreferencesPlugin):
|
class Columns(PreferencesPlugin):
|
||||||
name = 'Custom Columns'
|
name = 'Custom Columns'
|
||||||
|
icon = I('column.png')
|
||||||
gui_name = _('Add your own columns')
|
gui_name = _('Add your own columns')
|
||||||
category = 'Interface'
|
category = 'Interface'
|
||||||
gui_category = _('Interface')
|
gui_category = _('Interface')
|
||||||
category_order = 1
|
category_order = 1
|
||||||
name_order = 3
|
name_order = 3
|
||||||
config_widget = 'calibre.gui2.preferences.columns'
|
config_widget = 'calibre.gui2.preferences.columns'
|
||||||
|
description = _('Add/remove your own columns to the calibre book list')
|
||||||
|
|
||||||
class Toolbar(PreferencesPlugin):
|
class Toolbar(PreferencesPlugin):
|
||||||
name = 'Toolbar'
|
name = 'Toolbar'
|
||||||
|
icon = I('wizard.png')
|
||||||
gui_name = _('Customize the toolbar')
|
gui_name = _('Customize the toolbar')
|
||||||
category = 'Interface'
|
category = 'Interface'
|
||||||
gui_category = _('Interface')
|
gui_category = _('Interface')
|
||||||
category_order = 1
|
category_order = 1
|
||||||
name_order = 4
|
name_order = 4
|
||||||
config_widget = 'calibre.gui2.preferences.toolbar'
|
config_widget = 'calibre.gui2.preferences.toolbar'
|
||||||
|
description = _('Customize the toolbars and context menus, changing which'
|
||||||
|
' actions are available in each')
|
||||||
|
|
||||||
class InputOptions(PreferencesPlugin):
|
class InputOptions(PreferencesPlugin):
|
||||||
name = 'Input Options'
|
name = 'Input Options'
|
||||||
|
icon = I('arrow-down.png')
|
||||||
gui_name = _('Input Options')
|
gui_name = _('Input Options')
|
||||||
category = 'Conversion'
|
category = 'Conversion'
|
||||||
gui_category = _('Conversion')
|
gui_category = _('Conversion')
|
||||||
category_order = 2
|
category_order = 2
|
||||||
name_order = 1
|
name_order = 1
|
||||||
config_widget = 'calibre.gui2.preferences.conversion:InputOptions'
|
config_widget = 'calibre.gui2.preferences.conversion:InputOptions'
|
||||||
|
description = _('Set conversion options specific to each input format')
|
||||||
|
|
||||||
class CommonOptions(PreferencesPlugin):
|
class CommonOptions(PreferencesPlugin):
|
||||||
name = 'Common Options'
|
name = 'Common Options'
|
||||||
|
icon = I('convert.png')
|
||||||
gui_name = _('Common Options')
|
gui_name = _('Common Options')
|
||||||
category = 'Conversion'
|
category = 'Conversion'
|
||||||
gui_category = _('Conversion')
|
gui_category = _('Conversion')
|
||||||
category_order = 2
|
category_order = 2
|
||||||
name_order = 2
|
name_order = 2
|
||||||
config_widget = 'calibre.gui2.preferences.conversion:CommonOptions'
|
config_widget = 'calibre.gui2.preferences.conversion:CommonOptions'
|
||||||
|
description = _('Set conversion options common to all formats')
|
||||||
|
|
||||||
class OutputOptions(PreferencesPlugin):
|
class OutputOptions(PreferencesPlugin):
|
||||||
name = 'Output Options'
|
name = 'Output Options'
|
||||||
|
icon = I('arrow-up.png')
|
||||||
gui_name = _('Output Options')
|
gui_name = _('Output Options')
|
||||||
category = 'Conversion'
|
category = 'Conversion'
|
||||||
gui_category = _('Conversion')
|
gui_category = _('Conversion')
|
||||||
category_order = 2
|
category_order = 2
|
||||||
name_order = 3
|
name_order = 3
|
||||||
config_widget = 'calibre.gui2.preferences.conversion:OutputOptions'
|
config_widget = 'calibre.gui2.preferences.conversion:OutputOptions'
|
||||||
|
description = _('Set conversion options specific to each output format')
|
||||||
|
|
||||||
class Adding(PreferencesPlugin):
|
class Adding(PreferencesPlugin):
|
||||||
name = 'Adding'
|
name = 'Adding'
|
||||||
|
icon = I('add_book.png')
|
||||||
gui_name = _('Adding books')
|
gui_name = _('Adding books')
|
||||||
category = 'Import/Export'
|
category = 'Import/Export'
|
||||||
gui_category = _('Import/Export')
|
gui_category = _('Import/Export')
|
||||||
category_order = 3
|
category_order = 3
|
||||||
name_order = 1
|
name_order = 1
|
||||||
config_widget = 'calibre.gui2.preferences.adding'
|
config_widget = 'calibre.gui2.preferences.adding'
|
||||||
|
description = _('Control how calibre reads metadata from files when '
|
||||||
|
'adding books')
|
||||||
|
|
||||||
class Saving(PreferencesPlugin):
|
class Saving(PreferencesPlugin):
|
||||||
name = 'Saving'
|
name = 'Saving'
|
||||||
|
icon = I('save.png')
|
||||||
gui_name = _('Saving books to disk')
|
gui_name = _('Saving books to disk')
|
||||||
category = 'Import/Export'
|
category = 'Import/Export'
|
||||||
gui_category = _('Import/Export')
|
gui_category = _('Import/Export')
|
||||||
category_order = 3
|
category_order = 3
|
||||||
name_order = 2
|
name_order = 2
|
||||||
config_widget = 'calibre.gui2.preferences.saving'
|
config_widget = 'calibre.gui2.preferences.saving'
|
||||||
|
description = _('Control how calibre exports files from its database '
|
||||||
|
'to disk when using Save to disk')
|
||||||
|
|
||||||
class Sending(PreferencesPlugin):
|
class Sending(PreferencesPlugin):
|
||||||
name = 'Sending'
|
name = 'Sending'
|
||||||
|
icon = I('sync.png')
|
||||||
gui_name = _('Sending books to devices')
|
gui_name = _('Sending books to devices')
|
||||||
category = 'Import/Export'
|
category = 'Import/Export'
|
||||||
gui_category = _('Import/Export')
|
gui_category = _('Import/Export')
|
||||||
category_order = 3
|
category_order = 3
|
||||||
name_order = 3
|
name_order = 3
|
||||||
config_widget = 'calibre.gui2.preferences.sending'
|
config_widget = 'calibre.gui2.preferences.sending'
|
||||||
|
description = _('Control how calibre transfers files to your '
|
||||||
|
'ebook reader')
|
||||||
|
|
||||||
class Email(PreferencesPlugin):
|
class Email(PreferencesPlugin):
|
||||||
name = 'Email'
|
name = 'Email'
|
||||||
gui_name = _('Sending books by email')
|
icon = I('mail.png')
|
||||||
|
gui_name = _('Sharing books by email')
|
||||||
category = 'Sharing'
|
category = 'Sharing'
|
||||||
gui_category = _('Sharing')
|
gui_category = _('Sharing')
|
||||||
category_order = 4
|
category_order = 4
|
||||||
name_order = 1
|
name_order = 1
|
||||||
config_widget = 'calibre.gui2.preferences.emailp'
|
config_widget = 'calibre.gui2.preferences.emailp'
|
||||||
|
description = _('Setup sharing of books via email. Can be used '
|
||||||
|
'for automatic sending of downloaded news to your devices')
|
||||||
|
|
||||||
class Server(PreferencesPlugin):
|
class Server(PreferencesPlugin):
|
||||||
name = 'Server'
|
name = 'Server'
|
||||||
|
icon = I('network-server.png')
|
||||||
gui_name = _('Sharing over the net')
|
gui_name = _('Sharing over the net')
|
||||||
category = 'Sharing'
|
category = 'Sharing'
|
||||||
gui_category = _('Sharing')
|
gui_category = _('Sharing')
|
||||||
category_order = 4
|
category_order = 4
|
||||||
name_order = 2
|
name_order = 2
|
||||||
config_widget = 'calibre.gui2.preferences.server'
|
config_widget = 'calibre.gui2.preferences.server'
|
||||||
|
description = _('Setup the calibre Content Server which will '
|
||||||
|
'give you access to your calibre library from anywhere, '
|
||||||
|
'on any device, over the internet')
|
||||||
|
|
||||||
class Plugins(PreferencesPlugin):
|
class Plugins(PreferencesPlugin):
|
||||||
name = 'Plugins'
|
name = 'Plugins'
|
||||||
|
icon = I('plugins.png')
|
||||||
gui_name = _('Plugins')
|
gui_name = _('Plugins')
|
||||||
category = 'Advanced'
|
category = 'Advanced'
|
||||||
gui_category = _('Advanced')
|
gui_category = _('Advanced')
|
||||||
category_order = 5
|
category_order = 5
|
||||||
name_order = 1
|
name_order = 1
|
||||||
config_widget = 'calibre.gui2.preferences.plugins'
|
config_widget = 'calibre.gui2.preferences.plugins'
|
||||||
|
description = _('Add/remove/customize various bits of calibre '
|
||||||
|
'functionality')
|
||||||
|
|
||||||
class Tweaks(PreferencesPlugin):
|
class Tweaks(PreferencesPlugin):
|
||||||
name = 'Tweaks'
|
name = 'Tweaks'
|
||||||
|
icon = I('drawer.png')
|
||||||
gui_name = _('Tweaks')
|
gui_name = _('Tweaks')
|
||||||
category = 'Advanced'
|
category = 'Advanced'
|
||||||
gui_category = _('Advanced')
|
gui_category = _('Advanced')
|
||||||
category_order = 5
|
category_order = 5
|
||||||
name_order = 2
|
name_order = 2
|
||||||
config_widget = 'calibre.gui2.preferences.tweaks'
|
config_widget = 'calibre.gui2.preferences.tweaks'
|
||||||
|
description = _('Fine tune how calibre behaves in various contexts')
|
||||||
|
|
||||||
class Misc(PreferencesPlugin):
|
class Misc(PreferencesPlugin):
|
||||||
name = 'Misc'
|
name = 'Misc'
|
||||||
|
icon = I('exec.png')
|
||||||
gui_name = _('Miscellaneous')
|
gui_name = _('Miscellaneous')
|
||||||
category = 'Advanced'
|
category = 'Advanced'
|
||||||
gui_category = _('Advanced')
|
gui_category = _('Advanced')
|
||||||
category_order = 5
|
category_order = 5
|
||||||
name_order = 3
|
name_order = 3
|
||||||
config_widget = 'calibre.gui2.preferences.misc'
|
config_widget = 'calibre.gui2.preferences.misc'
|
||||||
|
description = _('Miscellaneous advanced configuration')
|
||||||
|
|
||||||
plugins += [LookAndFeel, Behavior, Columns, Toolbar, InputOptions,
|
plugins += [LookAndFeel, Behavior, Columns, Toolbar, InputOptions,
|
||||||
CommonOptions, OutputOptions, Adding, Saving, Sending, Email, Server,
|
CommonOptions, OutputOptions, Adding, Saving, Sending, Email, Server,
|
||||||
|
159
src/calibre/gui2/preferences/main.py
Normal file
159
src/calibre/gui2/preferences/main.py
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai
|
||||||
|
|
||||||
|
__license__ = 'GPL v3'
|
||||||
|
__copyright__ = '2010, Kovid Goyal <kovid@kovidgoyal.net>'
|
||||||
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|
||||||
|
from functools import partial
|
||||||
|
|
||||||
|
from PyQt4.Qt import QMainWindow, Qt, QIcon, QStatusBar, QFont, QWidget, \
|
||||||
|
QScrollArea, QStackedWidget, QVBoxLayout, QLabel, QFrame, \
|
||||||
|
QToolBar, QSize, pyqtSignal
|
||||||
|
|
||||||
|
from calibre.constants import __appname__, __version__
|
||||||
|
from calibre.gui2 import gprefs
|
||||||
|
from calibre.gui2.preferences import init_gui
|
||||||
|
from calibre.customize.ui import preferences_plugins
|
||||||
|
from calibre.utils.ordered_dict import OrderedDict
|
||||||
|
|
||||||
|
class StatusBar(QStatusBar): # {{{
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
QStatusBar.__init__(self, parent)
|
||||||
|
self.default_message = __appname__ + ' ' + _('version') + ' ' + \
|
||||||
|
__version__ + ' ' + _('created by Kovid Goyal')
|
||||||
|
self.device_string = ''
|
||||||
|
self._font = QFont()
|
||||||
|
self._font.setBold(True)
|
||||||
|
self.setFont(self._font)
|
||||||
|
|
||||||
|
self.messageChanged.connect(self.message_changed,
|
||||||
|
type=Qt.QueuedConnection)
|
||||||
|
self.message_changed('')
|
||||||
|
|
||||||
|
def message_changed(self, msg):
|
||||||
|
if not msg or msg.isEmpty() or msg.isNull() or \
|
||||||
|
not unicode(msg).strip():
|
||||||
|
self.showMessage(self.default_message)
|
||||||
|
|
||||||
|
# }}}
|
||||||
|
|
||||||
|
class Category(QWidget):
|
||||||
|
|
||||||
|
plugin_activated = pyqtSignal(object)
|
||||||
|
|
||||||
|
def __init__(self, name, plugins, parent=None):
|
||||||
|
QWidget.__init__(self, parent)
|
||||||
|
self._layout = QVBoxLayout()
|
||||||
|
self.setLayout(self._layout)
|
||||||
|
self.label = QLabel(name)
|
||||||
|
self.sep = QFrame(self)
|
||||||
|
self.bf = QFont()
|
||||||
|
self.bf.setBold(True)
|
||||||
|
self.label.setFont(self.bf)
|
||||||
|
self.sep.setFrameShape(QFrame.HLine)
|
||||||
|
self._layout.addWidget(self.label)
|
||||||
|
self._layout.addWidget(self.sep)
|
||||||
|
|
||||||
|
self.plugins = plugins
|
||||||
|
|
||||||
|
self.bar = QToolBar(self)
|
||||||
|
self.bar.setIconSize(QSize(48, 48))
|
||||||
|
self.bar.setMovable(False)
|
||||||
|
self.bar.setFloatable(False)
|
||||||
|
self.bar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
|
||||||
|
self._layout.addWidget(self.bar)
|
||||||
|
self.actions = []
|
||||||
|
for p in plugins:
|
||||||
|
target = partial(self.triggered, p)
|
||||||
|
ac = self.bar.addAction(QIcon(p.icon), p.gui_name, target)
|
||||||
|
ac.setToolTip(p.description)
|
||||||
|
ac.setWhatsThis(p.description)
|
||||||
|
ac.setStatusTip(p.description)
|
||||||
|
self.actions.append(ac)
|
||||||
|
|
||||||
|
def triggered(self, plugin, *args):
|
||||||
|
self.plugin_activated.emit(plugin)
|
||||||
|
|
||||||
|
|
||||||
|
class Browser(QScrollArea):
|
||||||
|
|
||||||
|
def __init__(self, parent=None):
|
||||||
|
QScrollArea.__init__(self, parent)
|
||||||
|
self.setWidgetResizable(True)
|
||||||
|
|
||||||
|
category_map = {}
|
||||||
|
for plugin in preferences_plugins():
|
||||||
|
if plugin.category not in category_map:
|
||||||
|
category_map[plugin.category] = plugin.category_order
|
||||||
|
if category_map[plugin.category] < plugin.category_order:
|
||||||
|
category_map[plugin.category] = plugin.category_order
|
||||||
|
|
||||||
|
categories = list(category_map.keys())
|
||||||
|
categories.sort(cmp=lambda x, y: cmp(category_map[x], category_map[y]))
|
||||||
|
|
||||||
|
self.category_map = OrderedDict()
|
||||||
|
for c in categories:
|
||||||
|
self.category_map[c] = []
|
||||||
|
|
||||||
|
for plugin in preferences_plugins():
|
||||||
|
self.category_map[plugin.category].append(plugin)
|
||||||
|
|
||||||
|
for plugins in self.category_map.values():
|
||||||
|
plugins.sort(cmp=lambda x, y: cmp(x.name_order, y.name_order))
|
||||||
|
|
||||||
|
self.widgets = []
|
||||||
|
self._layout = QVBoxLayout()
|
||||||
|
self.container = QWidget(self)
|
||||||
|
self.container.setLayout(self._layout)
|
||||||
|
self.setWidget(self.container)
|
||||||
|
for name, plugins in self.category_map.items():
|
||||||
|
w = Category(name, plugins, self)
|
||||||
|
self.widgets.append(w)
|
||||||
|
self._layout.addWidget(w)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Preferences(QMainWindow):
|
||||||
|
|
||||||
|
def __init__(self, gui):
|
||||||
|
QMainWindow.__init__(self, gui)
|
||||||
|
|
||||||
|
self.resize(780, 665)
|
||||||
|
geom = gprefs.get('preferences_window_geometry', None)
|
||||||
|
if geom is not None:
|
||||||
|
self.restoreGeometry(geom)
|
||||||
|
|
||||||
|
self.setWindowModality(Qt.WindowModal)
|
||||||
|
self.setWindowTitle(__appname__ + ' - ' + _('Preferences'))
|
||||||
|
self.setWindowIcon(QIcon(I('config.png')))
|
||||||
|
|
||||||
|
self.status_bar = StatusBar(self)
|
||||||
|
self.setStatusBar(self.status_bar)
|
||||||
|
|
||||||
|
self.stack = QStackedWidget(self)
|
||||||
|
self.setCentralWidget(self.stack)
|
||||||
|
self.browser = Browser(self)
|
||||||
|
self.stack.addWidget(self.browser)
|
||||||
|
self.scroll_area = QScrollArea(self)
|
||||||
|
self.stack.addWidget(self.scroll_area)
|
||||||
|
self.scroll_area.setWidgetResizable(True)
|
||||||
|
|
||||||
|
self.stack.setCurrentIndex(0)
|
||||||
|
|
||||||
|
def closeEvent(self, *args):
|
||||||
|
gprefs.set('preferences_window_geometry',
|
||||||
|
bytearray(self.saveGeometry()))
|
||||||
|
return QMainWindow.closeEvent(self, *args)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
from PyQt4.Qt import QApplication
|
||||||
|
app = QApplication([])
|
||||||
|
app
|
||||||
|
gui = init_gui()
|
||||||
|
|
||||||
|
p = Preferences(gui)
|
||||||
|
p.show()
|
||||||
|
app.exec_()
|
||||||
|
gui.shutdown()
|
Loading…
x
Reference in New Issue
Block a user