Start implementing preferences window

This commit is contained in:
Kovid Goyal 2010-09-05 14:25:05 -06:00
parent 69b4202ad3
commit 2e99359763
3 changed files with 206 additions and 1 deletions

View File

@ -393,9 +393,16 @@ class PreferencesPlugin(Plugin): # {{{
#: The category name displayed to the user for this plugin
gui_category = None
#: The name displayed to the user for this plugin
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):
'''
Create and return the actual Qt widget used for setting this group of

View File

@ -678,138 +678,177 @@ plugins += [ActionAdd, ActionFetchAnnotations, ActionGenerateCatalog,
class LookAndFeel(PreferencesPlugin):
name = 'Look & Feel'
icon = I('lookfeel.png')
gui_name = _('Look and Feel')
category = 'Interface'
gui_category = _('Interface')
category_order = 1
name_order = 1
config_widget = 'calibre.gui2.preferences.look_feel'
description = _('Adjust the look and feel of the calibre interface'
' to suit your tastes')
class Behavior(PreferencesPlugin):
name = 'Behavior'
icon = I('config.png')
gui_name = _('Behavior')
category = 'Interface'
gui_category = _('Interface')
category_order = 1
name_order = 2
config_widget = 'calibre.gui2.preferences.behavior'
description = _('Change the way calibre behaves')
class Columns(PreferencesPlugin):
name = 'Custom Columns'
icon = I('column.png')
gui_name = _('Add your own columns')
category = 'Interface'
gui_category = _('Interface')
category_order = 1
name_order = 3
config_widget = 'calibre.gui2.preferences.columns'
description = _('Add/remove your own columns to the calibre book list')
class Toolbar(PreferencesPlugin):
name = 'Toolbar'
icon = I('wizard.png')
gui_name = _('Customize the toolbar')
category = 'Interface'
gui_category = _('Interface')
category_order = 1
name_order = 4
config_widget = 'calibre.gui2.preferences.toolbar'
description = _('Customize the toolbars and context menus, changing which'
' actions are available in each')
class InputOptions(PreferencesPlugin):
name = 'Input Options'
icon = I('arrow-down.png')
gui_name = _('Input Options')
category = 'Conversion'
gui_category = _('Conversion')
category_order = 2
name_order = 1
config_widget = 'calibre.gui2.preferences.conversion:InputOptions'
description = _('Set conversion options specific to each input format')
class CommonOptions(PreferencesPlugin):
name = 'Common Options'
icon = I('convert.png')
gui_name = _('Common Options')
category = 'Conversion'
gui_category = _('Conversion')
category_order = 2
name_order = 2
config_widget = 'calibre.gui2.preferences.conversion:CommonOptions'
description = _('Set conversion options common to all formats')
class OutputOptions(PreferencesPlugin):
name = 'Output Options'
icon = I('arrow-up.png')
gui_name = _('Output Options')
category = 'Conversion'
gui_category = _('Conversion')
category_order = 2
name_order = 3
config_widget = 'calibre.gui2.preferences.conversion:OutputOptions'
description = _('Set conversion options specific to each output format')
class Adding(PreferencesPlugin):
name = 'Adding'
icon = I('add_book.png')
gui_name = _('Adding books')
category = 'Import/Export'
gui_category = _('Import/Export')
category_order = 3
name_order = 1
config_widget = 'calibre.gui2.preferences.adding'
description = _('Control how calibre reads metadata from files when '
'adding books')
class Saving(PreferencesPlugin):
name = 'Saving'
icon = I('save.png')
gui_name = _('Saving books to disk')
category = 'Import/Export'
gui_category = _('Import/Export')
category_order = 3
name_order = 2
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):
name = 'Sending'
icon = I('sync.png')
gui_name = _('Sending books to devices')
category = 'Import/Export'
gui_category = _('Import/Export')
category_order = 3
name_order = 3
config_widget = 'calibre.gui2.preferences.sending'
description = _('Control how calibre transfers files to your '
'ebook reader')
class Email(PreferencesPlugin):
name = 'Email'
gui_name = _('Sending books by email')
icon = I('mail.png')
gui_name = _('Sharing books by email')
category = 'Sharing'
gui_category = _('Sharing')
category_order = 4
name_order = 1
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):
name = 'Server'
icon = I('network-server.png')
gui_name = _('Sharing over the net')
category = 'Sharing'
gui_category = _('Sharing')
category_order = 4
name_order = 2
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):
name = 'Plugins'
icon = I('plugins.png')
gui_name = _('Plugins')
category = 'Advanced'
gui_category = _('Advanced')
category_order = 5
name_order = 1
config_widget = 'calibre.gui2.preferences.plugins'
description = _('Add/remove/customize various bits of calibre '
'functionality')
class Tweaks(PreferencesPlugin):
name = 'Tweaks'
icon = I('drawer.png')
gui_name = _('Tweaks')
category = 'Advanced'
gui_category = _('Advanced')
category_order = 5
name_order = 2
config_widget = 'calibre.gui2.preferences.tweaks'
description = _('Fine tune how calibre behaves in various contexts')
class Misc(PreferencesPlugin):
name = 'Misc'
icon = I('exec.png')
gui_name = _('Miscellaneous')
category = 'Advanced'
gui_category = _('Advanced')
category_order = 5
name_order = 3
config_widget = 'calibre.gui2.preferences.misc'
description = _('Miscellaneous advanced configuration')
plugins += [LookAndFeel, Behavior, Columns, Toolbar, InputOptions,
CommonOptions, OutputOptions, Adding, Saving, Sending, Email, Server,

View 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()