From 87c7fc955841bd6e5ebe87ae2a510c5e39140e7d Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 27 Mar 2011 13:12:07 -0600 Subject: [PATCH] Add configuration to example plugin --- .../interface_demo/__init__.py | 30 +++++++++++++ .../plugin_examples/interface_demo/config.py | 42 +++++++++++++++++++ .../plugin_examples/interface_demo/main.py | 18 +++++++- .../plugin_examples/interface_demo/ui.py | 10 ++++- 4 files changed, 97 insertions(+), 3 deletions(-) create mode 100644 src/calibre/manual/plugin_examples/interface_demo/config.py diff --git a/src/calibre/manual/plugin_examples/interface_demo/__init__.py b/src/calibre/manual/plugin_examples/interface_demo/__init__.py index aa9420b5c4..2ad4a0245e 100644 --- a/src/calibre/manual/plugin_examples/interface_demo/__init__.py +++ b/src/calibre/manual/plugin_examples/interface_demo/__init__.py @@ -32,3 +32,33 @@ class InterfacePluginDemo(InterfaceActionBase): #: The specified class must be defined in the specified module. actual_plugin = 'calibre_plugins.interface_demo.ui:InterfacePlugin' + def config_widget(self): + ''' + Implement this method and :meth:`save_settings` in your plugin to + use a custom configuration dialog. + + This method, if implemented, must return a QWidget. The widget can have + an optional method validate() that takes no arguments and is called + immediately after the user clicks OK. Changes are applied if and only + if the method returns True. + + If for some reason you cannot perform the configuration at this time, + return a tuple of two strings (message, details), these will be + displayed as a warning dialog to the user and the process will be + aborted. + + The base class implementation of this method raises NotImplementedError + so by default no user configuration is possible. + ''' + from calibre_plugins.interface_demo.config import ConfigWidget + return ConfigWidget() + + def save_settings(self, config_widget): + ''' + Save the settings specified by the user with config_widget. + + :param config_widget: The widget returned by :meth:`config_widget`. + ''' + config_widget.save_settings() + + diff --git a/src/calibre/manual/plugin_examples/interface_demo/config.py b/src/calibre/manual/plugin_examples/interface_demo/config.py new file mode 100644 index 0000000000..24376ab916 --- /dev/null +++ b/src/calibre/manual/plugin_examples/interface_demo/config.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python +# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:ai +from __future__ import (unicode_literals, division, absolute_import, + print_function) + +__license__ = 'GPL v3' +__copyright__ = '2011, Kovid Goyal ' +__docformat__ = 'restructuredtext en' + +from PyQt4.Qt import QWidget, QHBoxLayout, QLabel, QLineEdit + +from calibre.utils.config import JSONConfig + +# This is where all preferences for this plugin will be stored +# Remember that this name is also ina global namespace, so make it as uniqie +# as possible. +# It is good etiquette, though not strictly required to always prefix your +# config file name with plugins/, so as to ensure you dont accidentally clobber +# a calibre config file +prefs = JSONConfig('plugins/interface_demo') + +# Set defaults +prefs.defaults['hello_world_msg'] = 'Hello, World!' + +class ConfigWidget(QWidget): + + def __init__(self): + QWidget.__init__(self) + self.l = QHBoxLayout() + self.setLayout(self.l) + + self.label = QLabel('Hello world &message:') + self.l.addWidget(self.label) + + self.msg = QLineEdit(self) + self.msg.setText(prefs['hello_world_msg']) + self.l.addWidget(self.msg) + self.label.setBuddy(self.msg) + + def save_settings(self): + prefs['hello_world_msg'] = unicode(self.msg.text()) + diff --git a/src/calibre/manual/plugin_examples/interface_demo/main.py b/src/calibre/manual/plugin_examples/interface_demo/main.py index 53c9ae68dc..f23664b1de 100644 --- a/src/calibre/manual/plugin_examples/interface_demo/main.py +++ b/src/calibre/manual/plugin_examples/interface_demo/main.py @@ -13,13 +13,16 @@ if False: # You do not need this code in your plugins get_icons = get_resources = None -from PyQt4.Qt import QDialog, QVBoxLayout, QPushButton, QMessageBox +from PyQt4.Qt import QDialog, QVBoxLayout, QPushButton, QMessageBox, QLabel + +from calibre_plugins.interface_demo.config import prefs class DemoDialog(QDialog): - def __init__(self, gui, icon): + def __init__(self, gui, icon, do_user_config): QDialog.__init__(self, gui) self.gui = gui + self.do_user_config = do_user_config # The current database shown in the GUI # db is an instance of the class LibraryDatabase2 from database.py @@ -30,6 +33,8 @@ class DemoDialog(QDialog): self.l = QVBoxLayout() self.setLayout(self.l) + self.label = QLabel(prefs['hello_world_msg']) + self.l.addWidget(self.label) self.setWindowTitle('Interface Plugin Demo') self.setWindowIcon(icon) @@ -48,6 +53,11 @@ class DemoDialog(QDialog): self.view_button.clicked.connect(self.view) self.l.addWidget(self.view_button) + self.conf_button = QPushButton( + 'Configure this plugin', self) + self.conf_button.clicked.connect(self.config) + self.l.addWidget(self.conf_button) + self.resize(self.sizeHint()) def about(self): @@ -99,4 +109,8 @@ class DemoDialog(QDialog): # Ask the view plugin to launch the viewer for row_number view_plugin._view_books([row_number]) + def config(self): + self.do_user_config(parent=self) + # Apply the changes + self.label.setText(prefs['hello_world_msg']) diff --git a/src/calibre/manual/plugin_examples/interface_demo/ui.py b/src/calibre/manual/plugin_examples/interface_demo/ui.py index 3980291cc4..9b60a66ed4 100644 --- a/src/calibre/manual/plugin_examples/interface_demo/ui.py +++ b/src/calibre/manual/plugin_examples/interface_demo/ui.py @@ -50,10 +50,18 @@ class InterfacePlugin(InterfaceAction): self.qaction.triggered.connect(self.show_dialog) def show_dialog(self): + # The base plugin object defined in __init__.py + base_plugin_object = self.interface_action_base_plugin + # Show the config dialog + # The config dialog can also be shown from within + # Preferences->Plugins, which is why the do_user_config + # method is defined on the base plugin class + do_user_config = base_plugin_object.do_user_config + # self.gui is the main calibre GUI. It acts as the gateway to access # all the elements of the calibre user interface, it should also be the # parent of the dialog - d = DemoDialog(self.gui, self.qaction.icon()) + d = DemoDialog(self.gui, self.qaction.icon(), do_user_config) d.show()