summaryrefslogtreecommitdiff
path: root/kberylsettings
diff options
context:
space:
mode:
authornatural <natural>2006-12-17 10:06:18 +0000
committernatural <natural>2006-12-17 10:06:18 +0000
commit99b44818d60794aae11dca5f67722ab32c98f137 (patch)
tree8e54863077d35d0cbb88925c3fd012827d328a80 /kberylsettings
parentfcfa23f8e1b16bc68329c9e9aa3cb31d906ee572 (diff)
downloadkberylsettings-99b44818d60794aae11dca5f67722ab32c98f137.tar.gz
kberylsettings-99b44818d60794aae11dca5f67722ab32c98f137.tar.bz2
Implemented search -- search for plugin settings by keyword.
Refactored views and content frames. Many docstrings.
Diffstat (limited to 'kberylsettings')
-rw-r--r--kberylsettings/__init__.py3
-rw-r--r--kberylsettings/about.py11
-rw-r--r--kberylsettings/beryl.py75
-rw-r--r--kberylsettings/contentframe.py158
-rw-r--r--kberylsettings/lib.py90
-rw-r--r--kberylsettings/main.py343
-rw-r--r--kberylsettings/plugindialog.py69
-rw-r--r--kberylsettings/pluginframe.py283
-rw-r--r--kberylsettings/settingframe.py61
-rw-r--r--kberylsettings/widget.py55
10 files changed, 804 insertions, 344 deletions
diff --git a/kberylsettings/__init__.py b/kberylsettings/__init__.py
index e69de29..c3790ef 100644
--- a/kberylsettings/__init__.py
+++ b/kberylsettings/__init__.py
@@ -0,0 +1,3 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# package marker
diff --git a/kberylsettings/about.py b/kberylsettings/about.py
index 854f148..0940395 100644
--- a/kberylsettings/about.py
+++ b/kberylsettings/about.py
@@ -1,5 +1,9 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
+""" kberylsettings.about -> defines KAboutData and attributes for the package.
+
+See the 'about' function below.
+"""
from kdecore import KAboutData
@@ -11,11 +15,16 @@ version = '0.1'
shortDescription = 'KDE Beryl Settings'
licenseType = KAboutData.License_GPL_V2
copyrightStatement = '(c) 2006, %s' % (authorName, )
-homePageAddress = 'http://www.riverbankcomputing.co.uk/pykde/'
+homePageAddress = \
+ 'http://bugs.beryl-project.org/trac/browser/branches/kberylsettings/'
aboutText = ("The Beryl Settings Manager for KDE.")
def about():
+ """ returns an instance of KAboutData for this application
+
+ @return KAboutData instance
+ """
data = KAboutData(
appName,
progName,
diff --git a/kberylsettings/beryl.py b/kberylsettings/beryl.py
index ed0f5ae..ba8a791 100644
--- a/kberylsettings/beryl.py
+++ b/kberylsettings/beryl.py
@@ -1,16 +1,25 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
+""" kberylsettings.beryl -> wrappers around berylsettings objects.
+
+"""
import berylsettings
-import re
+
from os.path import abspath, exists
+from re import sub
+
from qt import QImage, QPixmap, QObject
from kdecore import KIcon
-from kberylsettings.lib import appDebug, appBase, iconCache, icon, Signals
+from kberylsettings.lib import App, Signals, icon
class Context(QObject):
+ """ Context -> wraps berylsetting.Context instances with extra
+ methods and properties.
+
+ """
activePluginsSettingName = 'active_plugins'
-
+
def __init__(self, context=None):
QObject.__init__(self)
if context is None:
@@ -18,43 +27,67 @@ class Context(QObject):
context.read()
self.context = context
+ def getPlugins(self):
+ """ sorted plugin sequence
- def plugins(self):
+ @return sequence of Plugin wrapper instances
+ """
seq = [Plugin(p) for p in self.context.Plugins]
seq.sort(reverse=True)
return iter(seq)
- plugins = property(plugins)
-
+ plugins = property(getPlugins)
def plugin(self, value):
+ """ locates plugin by name, description, or index
+
+ @param value plugin name, short description, or index
+ @return Plugin wrapper instance
+ """
try:
value + 0
except (TypeError, ):
for plugin in self.plugins:
if value == plugin.ShortDesc:
return plugin
+ if value == plugin.Name:
+ return plugin
else:
return list(self.plugins)[value]
-
def getActive(self):
+ """ sequence of active plugin names
+
+ @return sequence of active plugin names
+ """
act = self.general.Setting(self.activePluginsSettingName).Value
return act + [Plugin.generalName, ]
def setActive(self, active):
+ """ sets active plugins
+
+ @param active sequence of plugin names to set as active
+ @return None
+ """
self.general.Setting(self.activePluginsSettingName).Value = active
active = property(getActive, setActive)
+ def getGeneral(self):
+ """ general plugin instance
- def general(self):
- return self.context.Plugin(Plugin.generalName)
-
- general = property(general)
+ @return Plugin wrapper instance
+ """
+ return Plugin(self.context.Plugin(Plugin.generalName))
+ general = property(getGeneral)
def write(self):
+ """ saves the beryl context and messages the extension to
+ reload the new settings.
+
+ @return None
+ """
self.emit(Signals.statusMessage, ('Saving Beryl settings....', ))
self.context.write()
berylsettings.send_reload()
@@ -63,44 +96,40 @@ class Context(QObject):
class Plugin:
generalName = '_'
+ iconCache = {}
def __init__(self, plugin):
self.plugin = plugin
-
def __getattr__(self, value):
return getattr(self.plugin, value)
-
def __cmp__(self, other):
if self.isGeneral:
return -1
return cmp(self.plugin.ShortDesc,
getattr(other.plugin, 'ShortDesc', None))
-
def isGeneral(self):
return self.plugin.Name == self.generalName
isGeneral = property(isGeneral)
-
def icon(self, size, loader):
- if appDebug:
+ if App.debug:
return loader.loadIcon('empty', KIcon.NoGroup, size)
name = self.plugin.Name
try:
- pix = iconCache[(name, size)]
+ pix = self.iconCache[(name, size)]
except (KeyError, ):
- path = abspath(appBase + '/pixmaps/beryl-settings-section-%s.svg' % name)
+ path = abspath(App.basedir + '/pixmaps/beryl-settings-section-%s.svg' % name)
if not exists(path):
path = 'unknown'
ico = loader.loadIcon(path, KIcon.NoGroup)
img = ico.convertToImage()
- pix = iconCache[(name, size)] = QPixmap()
+ pix = self.iconCache[(name, size)] = QPixmap()
pix.convertFromImage(img.smoothScale(size, size, QImage.ScaleMin))
return pix
-
def nativeSettingsGroups(self):
settingsMap = {}
for setting in self.plugin.Settings:
@@ -108,7 +137,6 @@ class Plugin:
seq.append(setting)
return settingsMap
-
def regroupSettings(self):
mapping = self.nativeSettingsGroups()
remap = {}
@@ -119,7 +147,6 @@ class Plugin:
seq.extend(values)
return remap
-
def alternateGroup(self, typ, val, mapping):
if typ in ('Int', 'Float'):
return 'Numeric Values'
@@ -187,7 +214,7 @@ class Setting:
value = self.ShortDesc
value = value.title()
for pattern, repl in self.fixes:
- value = re.sub(pattern, repl, value)
+ value = sub(pattern, repl, value)
return value
return settingLabelMap.get(value, value)
label = property(label)
@@ -205,5 +232,3 @@ class Setting:
(' Svg', ' SVG'),
(' Vblank', ' VBlank'),
]
-
-
diff --git a/kberylsettings/contentframe.py b/kberylsettings/contentframe.py
new file mode 100644
index 0000000..72155b3
--- /dev/null
+++ b/kberylsettings/contentframe.py
@@ -0,0 +1,158 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+""" kberylsettings.contentframe -> defines the right side about/setting views.
+
+"""
+from os.path import abspath
+
+from qt import Qt, QFrame, QLabel, QHBoxLayout, QScrollView, QVBoxLayout
+from kdecore import KIcon, KIconLoader
+from kdeui import KStdGuiItem, KPushButton
+
+from kberylsettings.lib import App, Signals, buildPart
+from kberylsettings.settingframe import SettingFrame
+from kberylsettings.widget import Frame, WidgetStack
+
+
+class ContentFrame(WidgetStack):
+ """ ContentFrame -> stack with About page, Settings Page.
+
+ """
+ aboutPageId = 0
+ settingsPageId = 1
+
+ def __init__(self, parent):
+ WidgetStack.__init__(self, parent)
+ self.loader = KIconLoader(self.__class__.__name__)
+ self.buildAboutPage()
+ self.buildSettingsPage()
+ self.buildConnections()
+
+ def buildAboutPage(self):
+ """ builds the About Plugin page
+
+ @return None
+ """
+ self.aboutPage = Frame(self, margin=6, spacing=10)
+ self.infoHtml = buildPart(self.aboutPage, 'text/html',
+ "Type == 'Service'", True)
+ self.addWidget(self.aboutPage, self.aboutPageId)
+
+ def buildSettingsPage(self):
+ """ builds page for displaying one or more settings
+
+ @return None
+ """
+ self.settingsPage = Frame(self, margin=6, spacing=10)
+ self.pluginHeader = QFrame(self.settingsPage)
+ self.pluginIconLabel = QLabel(self.pluginHeader)
+ self.pluginNameLabel = QLabel(self.pluginHeader)
+ layout = QHBoxLayout(self.pluginHeader)
+ layout.addWidget(self.pluginIconLabel)
+ layout.addWidget(self.pluginNameLabel, 100)
+
+ self.settingsMain = QFrame(self)
+ self.settingsMain.settingsWidgets = []
+ layout = QVBoxLayout(self.settingsMain)
+
+ self.settingsScroller = ContentScroll(self.settingsPage, self.settingsMain)
+ if not App.debug:
+ self.settingsScroller.setFrameShape(Frame.NoFrame)
+ self.settingsFooter = QFrame(self.settingsPage)
+ layout = QHBoxLayout(self.settingsFooter)
+
+ def contentButton(name):
+ gui = getattr(KStdGuiItem, name)()
+ button = KPushButton(gui.iconSet(), gui.text(), self.settingsFooter)
+ layout.addWidget(button)
+ return button
+
+ self.helpButton = contentButton('help')
+ self.defaultsButton = contentButton('defaults')
+ layout.addStretch(100)
+ self.applyButton = contentButton('apply')
+ self.resetButton = contentButton('reset')
+ self.addWidget(self.settingsPage, self.settingsPageId)
+
+ def buildConnections(self):
+ """ build the connections for this instance
+
+ @return None
+ """
+ self.connect(self.helpButton, Signals.clicked, self.settingHelp)
+ self.connect(self.defaultsButton, Signals.clicked, self.settingDefaults)
+ self.connect(self.applyButton, Signals.clicked, self.settingApply)
+
+ def showAbout(self, plugin):
+ """ displays the About Plugin page with information from the plugin
+
+ @param plugin berylsettings Plugin instance
+ @return None
+ """
+ logofile = 'file://%s' % (abspath(App.basedir + '/html/beryl-manager.png'), )
+ htmlsrc = open(abspath(App.basedir + '/html/plugin.html')).read()
+ if plugin is None:
+ pluginname = 'Beryl Settings'
+ plugindesc = 'Beryl Settings - Get Your Effects On!'
+ else:
+ pluginname = plugin.ShortDesc
+ plugindesc = plugin.LongDesc
+ self.infoHtml.begin()
+ self.infoHtml.write(htmlsrc % locals())
+ self.infoHtml.end()
+ self.raiseWidget(self.aboutPageId)
+
+ def showSettings(self, plugin, arg):
+ """ displays the settings page with individual setting frames
+
+ @param plugin berylsettings Plugin instance
+ @param arg setting name or setting section name
+ @return None
+ """
+ self.settingsMain.hide()
+ for widget in self.settingsMain.settingsWidgets:
+ widget.close()
+ layout = self.settingsMain.layout()
+ layout.deleteAllItems()
+ if arg in plugin.settings:
+ settings = plugin.settings[arg]
+ extra = ' - %s' % (arg, )
+ else:
+ settings = [arg, ]
+ extra = ''
+ ico = plugin.icon(KIcon.SizeLarge, self.loader)
+ self.pluginIconLabel.setPixmap(ico)
+ self.pluginNameLabel.setText('<b>%s%s</b>' % (plugin.ShortDesc, extra))
+ for setting in settings:
+ frame = SettingFrame(self.settingsMain, setting)
+ self.settingsMain.settingsWidgets.append(frame)
+ layout.addWidget(frame, 0, Qt.AlignTop)
+ frame.show()
+ layout.addStretch(100)
+ self.settingsMain.show()
+ self.raiseWidget(self.settingsPageId)
+
+ def settingHelp(self):
+ """ not implemented
+
+ """
+
+ def settingDefaults(self):
+ """ not implemented
+
+ """
+
+ def settingApply(self):
+ """ not implemented
+
+ """
+
+
+class ContentScroll(QScrollView):
+ """ ContentScroll -> a scroll view fitted to a single child
+
+ """
+ def __init__(self, parent, child):
+ QScrollView.__init__(self, parent)
+ self.addChild(child)
+ self.setResizePolicy(QScrollView.AutoOneFit)
diff --git a/kberylsettings/lib.py b/kberylsettings/lib.py
index 5f2e484..8a2d795 100644
--- a/kberylsettings/lib.py
+++ b/kberylsettings/lib.py
@@ -1,24 +1,37 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
+""" kberylsettings.lib -> library classes, functions, and attributes.
+
+"""
from os import environ
from os.path import abspath, dirname
-from qt import SIGNAL, PYSIGNAL, QPixmap, QImage
-from qt import QSizePolicy
+from qt import PYSIGNAL, SIGNAL, SLOT, QPixmap, QImage
from kdecore import KGlobal, KIcon, KShortcut, i18n
from kdeui import KAction, KStdAction
from kio import KTrader
-from khtml import KHTMLPart # without this, the part isn't created correctly. :(
+from khtml import KHTMLPart # without this, the KHTMLParts aren't created.
from kparts import createReadOnlyPart, createReadWritePart
-appDebug = environ.get('DEBUG', False)
-appBase = abspath(dirname(__file__))
+##
+# a cache for already-created icons
iconCache = {}
+class App:
+ """ class for application-wide settings
+
+ """
+ debug = environ.get('DEBUG')
+ basedir = abspath(dirname(__file__))
+
+
class Signals:
+ """ class with SIGNAL and PYSIGNAL attributes
+
+ """
viewModeChanged = PYSIGNAL('viewModeChanged')
iconSizeChanged = PYSIGNAL('iconSizeChanged')
berylContextChanged = PYSIGNAL('berylContextChanged')
@@ -32,15 +45,34 @@ class Signals:
itemSelected = SIGNAL('selectionChanged(QListViewItem *)')
okClicked = SIGNAL('okClicked()')
activated = SIGNAL('activated()')
+ textChanged = SIGNAL('textChanged(const QString&)')
contextMenuRequest = \
SIGNAL('contextMenuRequested(QListViewItem*,const QPoint&,int)')
-def minSizePolicy():
- return QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
+class Slots:
+ """ class with SLOT attributes
+
+ """
+ close = SLOT('close()')
def icon(name, group=KIcon.NoGroup, size=KIcon.SizeSmall):
+ """ loads pixmap by name
+
+ This function could return the icon directly from the loadIcon
+ call, but that method (for some reason) doesn't apply any icon
+ effects.
+
+ @param name icon name
+ @param group KIcon group
+ @param size KIcon size
+ @return icon as QPixmap instance
+ """
+ try:
+ return iconCache[(name, size)]
+ except (KeyError, ):
+ pass
ico = KGlobal.instance().iconLoader().loadIcon(name, group)
img = ico.convertToImage()
pix = iconCache[(name, size)] = QPixmap()
@@ -49,11 +81,29 @@ def icon(name, group=KIcon.NoGroup, size=KIcon.SizeSmall):
def iconSet(name, group=KIcon.NoGroup, size=KIcon.SizeSmall):
+ """ load icon set by name
+
+ @param name icon set name
+ @param group KIcon group
+ @param size KIcon size
+ @return icon as QIconSet instance
+ """
return KGlobal.instance().iconLoader().loadIconSet(name, group, size)
-def action(name, label, icon, accel, tip, collection, pluggable):
- obj = KAction(collection, name)
+def action(text, label, icon, accel, tip, collection, pluggable):
+ """ creates and configures a KAction instance
+
+ @param text display value for action
+ @param label value associated with action
+ @param icon pixmap for action
+ @param accel constructor parameter for KAccel
+ @param tip tooltip text for actin
+ @param collection KActionCollection instance
+ @param pluggable any object with plug method
+ @return KAction instance
+ """
+ obj = KAction(text)
obj.setShortcut(KShortcut(accel))
obj.setIconSet(iconSet(icon))
obj.setIcon(icon)
@@ -66,14 +116,32 @@ def action(name, label, icon, accel, tip, collection, pluggable):
def stdAction(parent, name, slot, collection, pluggable):
+ """ creates a named KStdAction instance
+
+ @param parent receiver of action
+ @param name attribute of KStdAction class
+ @param slot slot for KStdAction instance
+ @param collection KActionCollection instance
+ @param pluggable any object with plug method
+ @return KStdAction instance
+ """
typ = getattr(KStdAction, name)
obj = typ(parent, slot, collection)
obj.plug(pluggable)
return obj
-def buildPart(parent, query, constraint, writable=False):
- offers = KTrader.self().query(query, constraint)
+def buildPart(parent, servicetype, constraint, writable=False):
+ """ build a KDE part
+
+ @param parent parent object of created part
+ @param servicetype mime type as string, or other service name
+ @param constraint value to limit KTrader query
+ @keyparam writable=False if True, creates read-write part
+ @return KParts.ReadOnlyPart or KParts.ReadWritePart instance
+ """
+ offers = KTrader.self().query(servicetype, constraint)
+ part = None
for ptr in offers:
if writable:
builder = createReadWritePart
diff --git a/kberylsettings/main.py b/kberylsettings/main.py
index 1d26493..4b928ce 100644
--- a/kberylsettings/main.py
+++ b/kberylsettings/main.py
@@ -1,23 +1,27 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
+""" kberylsettings.main -> defines KBerylSettings main window.
+
+"""
from sys import argv
-from os.path import abspath
-from qt import Qt, QFrame, QWidget, QHBoxLayout, QLabel, SLOT, QScrollView
-from kdecore import KCmdLineArgs, KApplication, KIconLoader, KWin, i18n, KIcon, KGlobal
-from kdeui import KMainWindow, KStdGuiItem, KLineEdit, KPushButton
+from qt import Qt, QWidget, QHBoxLayout, QLabel
+from kdecore import KApplication, KCmdLineArgs, KIcon, KGlobal, KWin, i18n
+from kdeui import KMainWindow, KStdGuiItem, KLineEdit
from kberylsettings.about import about
from kberylsettings.beryl import Context
-from kberylsettings.lib import action, stdAction, Signals, buildPart, minSizePolicy
-from kberylsettings.lib import appDebug, appBase, icon
+from kberylsettings.contentframe import ContentFrame
+from kberylsettings.lib import Signals, Slots, action, stdAction, icon
from kberylsettings.plugindialog import PluginDialog
from kberylsettings.pluginframe import PluginFrame
-from kberylsettings.settingframe import SettingFrame
from kberylsettings.widget import Frame, Popup, SmallPushButton, Splitter
class KBerylSetttings(KMainWindow):
+ """ The main window.
+
+ """
viewMode = 0
iconSize = 16
@@ -26,58 +30,101 @@ class KBerylSetttings(KMainWindow):
self.buildWidgets()
self.buildMenus()
self.buildConnections()
- self.buildContentFrame()
self.buildFinal()
-
def buildWidgets(self):
- self.loader = KIconLoader(self.__class__.__name__)
+ """ builds widgets on this instance
+
+ @return None
+ """
+ self.loader = KGlobal.iconLoader()
self.mainSplitter = Splitter(self, Qt.Horizontal)
self.leftFrame = Frame(self.mainSplitter)
self.rightFrame = Frame(self.mainSplitter)
self.searchWidget = search = QWidget(self.leftFrame)
searchLayout = QHBoxLayout(search, 6, 6)
searchLayout.setAutoAdd(True)
-
clear = KStdGuiItem.clear()
self.clearSearch = SmallPushButton(clear.iconSet(), '', search)
self.labelSearch = QLabel(i18n('Search: '), search)
self.inputSearch = KLineEdit(search)
self.pluginList = PluginFrame(self.leftFrame)
self.setCentralWidget(self.mainSplitter)
+ self.contentFrame = ContentFrame(self.rightFrame)
statusBar = self.statusBar()
+ def buildMenus(self):
+ """ builds the menus for this instance
- def showMessage(self, text):
- self.statusBar().message(text, 3000)
-
+ @return None
+ """
+ menu = self.menuBar()
+ menu.insertItem(i18n('&File'), self.fileMenu())
+ menu.insertItem(i18n('&View'), self.viewMenu())
+ menu.insertItem(i18n('&Settings'), self.settingsMenu())
+ menu.insertItem(i18n('&Help'), self.helpMenu())
def buildConnections(self):
+ """ builds the connections for this instance
+
+ @return None
+ """
connect = self.connect
- connect(self, Signals.viewModeChanged, self.setViewMode)
- connect(self, Signals.iconSizeChanged, self.setIconSize)
- connect(self.pluginList, Signals.showSettings, self.showPluginHeader)
- connect(self.pluginList, Signals.showSettings, self.showPluginSettings)
+ connect(self, Signals.viewModeChanged, self.onMode)
+ connect(self, Signals.iconSizeChanged, self.onIconSize)
+ connect(self, Signals.pluginAbout, self.contentFrame.showAbout)
+ connect(self.pluginList, Signals.showSettings, self.contentFrame.showSettings)
+ connect(self.inputSearch, Signals.textChanged, self.pluginList.showSearch)
+ connect(self.clearSearch, Signals.clicked, self.onClearSearch)
statusBar = self.statusBar()
actions = self.actionCollection()
actions.setHighlightingEnabled(True)
-
## broken!
#connect(actions, SIGNAL('actionStatusText(const QString &)'),
# self.statusBar(), SLOT('message( const QString & )'))
#connect(actions, SIGNAL('clearStatusText()'),
# self.statusBar(), SLOT('clear()'))
+ def buildFinal(self):
+ """ do everything else needed to create the widget
- def buildMenus(self):
- menu = self.menuBar()
- menu.insertItem(i18n('&File'), self.fileMenu())
- menu.insertItem(i18n('&View'), self.viewMenu())
- menu.insertItem(i18n('&Settings'), self.settingsMenu())
- menu.insertItem(i18n('&Help'), self.helpMenu())
+ @return None
+ """
+ self.context = context = Context()
+ self.emit(Signals.berylContextChanged, (context, ))
+ connect = self.connect
+ connect(context, Signals.statusMessage, self.showMessage)
+ KWin.setIcons(self.winId(),
+ icon('configure', size=KIcon.SizeLarge),
+ icon('configure', size=KIcon.SizeSmall))
+ config = self.config('mainwindow')
+ self.restoreWindowSize(config)
+ self.mainSplitter.setSizes([self.width()*0.35, self.width()*0.65])
+ config = self.config('mainview')
+ self.emit(Signals.iconSizeChanged,
+ (config.readNumEntry('iconsize', self.iconSize), ))
+ self.emit(Signals.viewModeChanged,
+ (config.readNumEntry('viewmode', self.viewMode), ))
+ ## done after initial emit to prevent spurious context update
+ connect(self, Signals.berylContextChanged, self.onContextChanged)
+ self.contentFrame.showAbout(None)
+
+ def config(self, group=None):
+ """ loads the general configuration object
+ @keyparam group=None if provided, config group set to this value
+ @return KConfig instance
+ """
+ config = KGlobal.instance().config()
+ if group is not None:
+ config.setGroup(group)
+ return config
def fileMenu(self):
+ """ creates a new File menu
+
+ @return KPopupMenu instance
+ """
pop = Popup(self)
actions = self.actionCollection()
self.importAction = action('import', 'Import', '', 'Import settings',
@@ -85,45 +132,36 @@ class KBerylSetttings(KMainWindow):
self.exportAction = action('export', 'Export', '', 'Export current settings',
'Export profile', actions, pop)
pop.insertSeparator()
- self.quitAction = stdAction(self, 'quit', SLOT('close()'),
- actions, pop)
+ self.quitAction = stdAction(self, 'quit', Slots.close, actions, pop)
return pop
-
def viewMenu(self):
+ """ creates a new View menu
+
+ @return KPopupMenu instance
+ """
pop = Popup(self)
pop.insertItem(i18n('&Mode'), self.modeMenu())
pop.insertItem(i18n('Icon &Size'), self.iconSizeMenu())
return pop
-
def settingsMenu(self):
+ """ creates a new Settings menu
+
+ @return KPopupMenu instance
+ """
pop = Popup(self)
self.pluginsAction = action('plugins', 'Select Plugins...', '',
'Select plugins', 'Select plugins',
self.actionCollection(), pop)
- self.connect(self.pluginsAction, Signals.activated, self.selectPlugins)
+ self.connect(self.pluginsAction, Signals.activated, self.onSelectPlugins)
return pop
-
- def selectPlugins(self):
- self.pluginDialog = PluginDialog(self, self.context)
- self.connect(self.pluginDialog, Signals.okClicked, self.updatePlugins)
- self.pluginDialog.exec_loop()
-
-
- def updatePlugins(self):
- active = [n for n, on in self.pluginDialog.pluginMap.items() if on]
- context = self.context
-
- for p in context.plugins:
- self.emit(Signals.berylPluginEnabled, (p, p.Name in active))
-
- context.active = active
- self.emit(Signals.berylContextChanged, (context, ))
-
-
def modeMenu(self):
+ """ creates a new View Mode menu
+
+ @return KPopupMenu instance
+ """
pop = self.modePopup = Popup(self)
ids = self.modePopupIds = {}
for value, label in ((0, '&Icon View'), (1, '&Tree View')):
@@ -132,171 +170,124 @@ class KBerylSetttings(KMainWindow):
pop.connectItem(modeid, self, Signals.viewModeChanged)
return pop
-
def iconSizeMenu(self):
+ """ creates a new View Icon Size menu
+
+ @return KPopupMenu instance
+ """
pop = self.iconSizePopup = Popup(self)
ids = self.iconSizePopupIds = {}
- sizelabels = self.iconSizeMap()
- for size, label in sizelabels:
+ for size, label in iconSizes():
sizeid = ids[size] = pop.insertItem(i18n(label))
pop.setItemParameter(sizeid, size)
pop.connectItem(sizeid, self, Signals.iconSizeChanged)
pop.setItemChecked(sizeid, True)
return pop
+ def queryClose(self):
+ """ abuse the queryClose method because other close methods are goofy
- def buildContentFrame(self):
- self.aboutFrame = Frame(self.rightFrame, margin=6, spacing=10)
- self.aboutFrame.hide()
- self.aboutHtml = buildPart(self.aboutFrame, 'text/html', "Type == 'Service'", True)
- self.contentFrame = Frame(self.rightFrame, margin=6, spacing=10)
- self.buildContentHeader()
- self.contentMain = Frame(self.contentFrame)
- self.contentMain.setSizePolicy(minSizePolicy())
- self.contentScroll = QScrollView(self.contentFrame)
- self.contentScroll.addChild(self.contentMain)
- self.contentScroll.setResizePolicy(QScrollView.AutoOneFit)
- if not appDebug:
- self.contentScroll.setFrameShape(QFrame.NoFrame)
- self.buildContentFooter()
-
-
- def buildContentHeader(self):
- self.contentHeader = header = QFrame(self.contentFrame)
- self.contentIcon = QLabel(header)
- self.contentLabel = QLabel(header)
- layout = QHBoxLayout(header)
- layout.addWidget(self.contentIcon)
- layout.addWidget(self.contentLabel, 100)
-
-
- def buildContentFooter(self):
- self.contentFooter = QFrame(self.contentFrame)
- layout = QHBoxLayout(self.contentFooter)
+ This method may grow in the future to prompt the user for
+ unsaved changes.
- def contentButton(name):
- gui = getattr(KStdGuiItem, name)()
- button = KPushButton(gui.iconSet(), gui.text(), self.contentFooter)
- layout.addWidget(button)
- return button
-
- self.helpButton = contentButton('help')
- self.defaultsButton = contentButton('defaults')
- layout.addStretch(100)
- self.applyButton = contentButton('apply')
- self.resetButton = contentButton('reset')
-
-
- def buildFinal(self):
- self.context = context = Context()
- self.emit(Signals.berylContextChanged, (context, ))
- connect = self.connect
- connect(context, Signals.statusMessage, self.showMessage)
- KWin.setIcons(self.winId(),
- icon('configure', size=KIcon.SizeLarge),
- icon('configure', size=KIcon.SizeSmall))
- config = self.config('mainwindow')
- self.restoreWindowSize(config)
- self.mainSplitter.setSizes([self.width()*0.35, self.width()*0.65])
+ @return True
+ """
+ self.saveMainWindowSettings(self.config())
+ self.saveWindowSize(self.config('mainwindow'))
config = self.config('mainview')
- self.emit(Signals.iconSizeChanged,
- (config.readNumEntry('iconsize', self.iconSize), ))
- self.emit(Signals.viewModeChanged,
- (config.readNumEntry('viewmode', self.viewMode), ))
-
- ## done after initial emit to prevent spurious context update
- connect(self, Signals.berylContextChanged, self.settingsChanged)
- self.showAboutPlugin(None)
+ config.writeEntry('iconsize', self.iconSize)
+ config.writeEntry('viewmode', self.viewMode)
+ return True
+ def onClearSearch(self):
+ """ clears the search input, emits signal to set view mode
- def config(self, group=None):
- config = KGlobal.instance().config()
- if group is not None:
- config.setGroup(group)
- return config
+ @return None
+ """
+ self.inputSearch.clear()
+ self.emit(Signals.viewModeChanged, (self.viewMode, ))
+ def onContextChanged(self):
+ """ writes the beryl context
- def setViewMode(self, value):
- self.viewMode = value
- for menuid in self.iconSizePopupIds.values():
- self.iconSizePopup.setItemEnabled(menuid, not value)
- for mode, menuid in self.modePopupIds.items():
- self.modePopup.setItemChecked(menuid, mode==value)
+ @return None
+ """
+ self.context.write()
+ def onIconSize(self, value):
+ """ changes the View Icon Size menu
- def setIconSize(self, value):
+ @param value new icon size
+ @return None
+ """
self.iconSize = value
for size, menuid in self.iconSizePopupIds.items():
self.iconSizePopup.setItemChecked(menuid, size==value)
+ def onPluginDialogOk(self):
+ """ sets current context active plugins
- def queryClose(self):
- self.saveMainWindowSettings(self.config())
- self.saveWindowSize(self.config('mainwindow'))
- config = self.config('mainview')
- config.writeEntry('iconsize', self.iconSize)
- config.writeEntry('viewmode', self.viewMode)
- return True
-
-
- def showPluginHeader(self, plugin, section):
- self.aboutFrame.hide()
- ico = plugin.icon(KIcon.SizeLarge, self.loader)
- self.contentIcon.setPixmap(ico)
- self.contentLabel.setText('<b>%s</b>' % (plugin.ShortDesc, ))
- self.contentFrame.show()
-
+ @return None
+ """
+ items = self.pluginDialog.pluginMap.items()
+ active = [name for name, enabled in items if enabled]
+ context = self.context
+ for p in context.plugins:
+ self.emit(Signals.berylPluginEnabled, (p, p.Name in active))
+ context.active = active
+ self.emit(Signals.berylContextChanged, (context, ))
- def showPluginSettings(self, plugin, section):
- parent = self.contentMain
- parent.hide()
- for widget in parent.queryList('QFrame'):
- widget.close()
+ def onSelectPlugins(self):
+ """ shows dialog to select/deselect active plugins
- settings = plugin.settings[section]
- for setting in settings:
- frame = SettingFrame(parent, setting)
- parent.show()
+ @return None
+ """
+ self.pluginDialog = PluginDialog(self, self.context)
+ self.connect(self.pluginDialog, Signals.okClicked,
+ self.onPluginDialogOk)
+ self.pluginDialog.exec_loop()
- def settingsChanged(self):
- self.context.write()
+ def onMode(self, value):
+ """ changes the View Mode menu, enables/disables Icon Size menu items
+ @param value new view mode
+ @return None
+ """
+ self.viewMode = value
+ for menuid in self.iconSizePopupIds.values():
+ self.iconSizePopup.setItemEnabled(menuid, not value)
+ for mode, menuid in self.modePopupIds.items():
+ self.modePopup.setItemChecked(menuid, mode==value)
- def showAboutPlugin(self, plugin):
- self.contentFrame.hide()
- for widget in self.aboutFrame.queryList('QWidget'):
- widget.close()
- logofile = 'file://%s' % (abspath(appBase + '/html/beryl-manager.png'), )
- htmlsrc = open(abspath(appBase + '/html/plugin.html')).read()
- if plugin is None:
- pluginname = 'Beryl Settings'
- plugindesc = 'Beryl Settings - Get Your Effects On!'
- else:
- pluginname = plugin.ShortDesc
- plugindesc = plugin.LongDesc
- self.aboutHtml.begin()
- self.aboutHtml.write(htmlsrc % locals())
- self.aboutHtml.end()
- self.aboutFrame.show()
+ def showMessage(self, text):
+ self.statusBar().message(text, 3000)
- def iconSizeMap(self):
- okay = lambda x:x.startswith('Size') and x != 'SizeSmallMedium'
- labels = [a for a in dir(KIcon) if okay(a)]
- sizes = [getattr(KIcon, a) for a in labels]
- labels = [l.replace('Size', '') for l in labels]
- sizelabels = zip(sizes, labels)
- sizelabels.sort()
- return sizelabels
+def iconSizes():
+ """ creates list of KIcon sizes and their names
+ @return sequence of two-tuples in the form of (size, name)
+ """
+ def sizeOk(attr):
+ return attr.startswith('Size') and attr != 'SizeSmallMedium'
+ names = [a for a in dir(KIcon) if sizeOk(a)]
+ sizes = [getattr(KIcon, a) for a in names]
+ names = [l.replace('Size', '') for l in names]
+ sizenames = zip(sizes, names)
+ sizenames.sort()
+ return sizenames
def main():
+ """ runs the KBerylSettings window with a KApplication
+
+ @return None
+ """
aboutdata = about()
KCmdLineArgs.init(argv, aboutdata)
app = KApplication()
- mainWindow = KBerylSetttings()
- mainWindow.show()
+ obj = KBerylSetttings()
+ obj.show()
app.exec_loop()
diff --git a/kberylsettings/plugindialog.py b/kberylsettings/plugindialog.py
index 5c395a2..dc97831 100644
--- a/kberylsettings/plugindialog.py
+++ b/kberylsettings/plugindialog.py
@@ -1,8 +1,11 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
+""" kberylsettings.plugindialog -> defines a dialog box for selecting plugins.
+
+"""
from qt import QCheckListItem, QLabel
from kdecore import i18n
-from kdeui import KDialogBase, KListView
+from kdeui import KDialogBase, KListView, KMessageBox
from kberylsettings.lib import Signals
@@ -51,7 +54,7 @@ class PluginList(KListView):
"""
height = count * self.fontMetrics().height()
self.setMinimumHeight(height * 0.5)
- width = maxlen * self.fontMetrics().maxWidth() * 0.25
+ width = maxlen * self.fontMetrics().maxWidth() * 0.2
self.setMinimumWidth(width)
@@ -69,13 +72,69 @@ class PluginDialog(KDialogBase):
self.connect(self.listView, Signals.itemClicked, self.changePlugin)
self.pluginMap = self.listView.addPlugins(context, parent.loader)
-
def changePlugin(self, item):
+ """ handle a possible change to the plugins checkbox
+
+ @param item QCheckListItem instance
+ @return None
+ """
if not item:
return
- state = item.state()
plugin = self.context.plugin(item.text(0))
+ state = item.state()
if state == item.On:
self.pluginMap[plugin.Name] = 1
+ self.satisfy(plugin)
elif state == item.Off:
- self.pluginMap[plugin.Name] = 0
+ remaining = self.needs(plugin)
+ if remaining:
+ item.setState(item.On)
+ text = 'Cannot remove plugin "%s" required by %s.'
+ need = ['"%s"' % r.ShortDesc for r in remaining]
+ text %= (plugin.ShortDesc, str.join(', ', need))
+ KMessageBox.sorry(self, text)
+ else:
+ self.pluginMap[plugin.Name] = 0
+
+ def satisfy(self, plugin):
+ """ enable requirement for plugin if necessary
+
+ @param plugin berylsettings Plugin instance
+ @return None
+ """
+ for requirement in plugin.Requires:
+ for p in self.context.plugins:
+ if requirement in p.Provides:
+ if not self.pluginMap[p.Name]:
+ self.pluginMap[p.Name] = 1
+ item = self.listView.findItem(p.ShortDesc, 0)
+ if item:
+ item.setState(item.On)
+ for req in p.Requires:
+ self.satisfy(p)
+
+ def needs(self, plugin):
+ """ check that all requirements for plugin are met
+
+ @param plugin berylsettings Plugin instance
+ @return sequence of required plugins
+ """
+ pending = self.pending(plugin)
+ allProvided = []
+ for p in pending:
+ allProvided.extend(p.Provides)
+ notMet = []
+ for p in pending:
+ for req in p.Requires:
+ if req not in allProvided:
+ notMet.append(p)
+ return notMet
+
+ def pending(self, exclude):
+ """ generates a sequence of enabled plugins, based on current selections
+
+ @param exclude plugin to exclude from returned list
+ @return list of berylsetting Plugin instances
+ """
+ names = [name for name, enabled in self.pluginMap.items() if enabled]
+ return [self.context.plugin(n) for n in names if n != exclude.Name]
diff --git a/kberylsettings/pluginframe.py b/kberylsettings/pluginframe.py
index 306a883..e3116e8 100644
--- a/kberylsettings/pluginframe.py
+++ b/kberylsettings/pluginframe.py
@@ -1,83 +1,172 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-from qt import Qt, QFrame, QListViewItem, QListViewItemIterator, QVBoxLayout
+""" kberylsettings.pluginframe -> defines the left side plugin views.
+and search view.
+
+"""
+from re import sub
+
+from qt import QLabel, QListViewItem
from kdecore import KIconLoader, i18n
-from kdeui import KListView
from kberylsettings.beryl import Setting
from kberylsettings.lib import Signals, icon
-from kberylsettings.widget import Popup
+from kberylsettings.widget import Frame, ListView, ValueListViewItem, \
+ WidgetStack
-class PluginFrame(QFrame):
- """ PluginFrame -> encapsulates an icon ListView and a tree
- ListView and swaps between them.
+class PluginFrame(WidgetStack):
+ """ PluginFrame -> stack with Icon View, Tree View, and Search widget.
"""
+ iconPageId, treePageId, searchPageId = range(3)
+
def __init__(self, parent):
- QFrame.__init__(self, parent)
- layout = QVBoxLayout(self)
- layout.setAutoAdd(True)
+ WidgetStack.__init__(self, parent)
+ self.buildWidgets()
+ self.buildConnections()
+
+ def buildWidgets(self):
+ """ builds widgets on this instance
+
+ @return None
+ """
self.iconView = PluginIconView(self)
self.treeView = PluginTreeView(self)
+ self.searchView = SearchView(self)
+ self.addWidget(self.iconView, self.iconPageId)
+ self.addWidget(self.treeView, self.treePageId)
+ self.addWidget(self.searchView, self.searchPageId)
+ def buildConnections(self):
+ """ build the connections for this instance
+
+ @return None
+ """
root = self.topLevelWidget()
connect = self.connect
- connect(root, Signals.viewModeChanged, self.onViewMode)
+ connect(root, Signals.viewModeChanged, self.raiseWidget)
connect(root, Signals.iconSizeChanged, self.iconView.onIconSize)
-
- views = (self.iconView, self.treeView)
- for view in views:
+ connect(root, Signals.berylContextChanged, self.searchView.rebuildIndex)
+ connect(self.searchView, Signals.pluginAbout, root, Signals.pluginAbout)
+ connect(self.searchView, Signals.showSettings, Signals.showSettings)
+ for view in (self.iconView, self.treeView):
connect(view, Signals.showSettings, Signals.showSettings)
- connect(view, Signals.berylSettingChanged, root.settingsChanged)
- connect(view, Signals.pluginAbout, root.showAboutPlugin)
+ connect(view, Signals.berylSettingChanged, root.onContextChanged)
+ connect(view, Signals.pluginAbout, root, Signals.pluginAbout)
connect(view, Signals.statusMessage, root.showMessage)
connect(root, Signals.berylContextChanged, view.onBerylContext)
connect(root, Signals.berylPluginEnabled, view.enablePluginItem)
- for receiver in views:
- connect(view, Signals.berylPluginEnabled,
- receiver.enablePluginItem)
- def onViewMode(self, value):
- """ user requested view mode change
+ def showSearch(self, value):
+ """ displays the search page and tickles it with the search value
- @param value view mode; 0 or 1
@return None
"""
- items = [self.treeView, self.iconView, ]
- if value:
- items.reverse()
+ self.raiseWidget(self.searchPageId)
+ self.searchView.showKeywords(value)
- last = items[0].selectedItem()
- if last:
- for item in items[1]:
- item.setSelected(item.text(0) == last.text(0))
- items[0].hide()
- items[1].show()
-
-class PluginView(KListView):
- """ PluginView -> mixin for shared view functionality
+class SearchView(Frame):
+ """ SearchView -> a frame to display found keywords and their results
"""
def __init__(self, parent):
- KListView.__init__(self, parent)
- self.addColumn('')
- self.setSorting(-1)
- self.header().hide()
+ Frame.__init__(self, parent)
+ self.index = {}
self.loader = KIconLoader(self.__class__.__name__)
- self.connect(self, Signals.contextMenuRequest, self.onContextMenu)
+ self.keywordLabel = QLabel(i18n('Keywords:'), self)
+ self.keywordsList = ListView(self)
+ configList(self.keywordsList)
+ self.resultsLabel = QLabel(i18n('Results:'), self)
+ self.resultsList = ListView(self)
+ configList(self.resultsList)
+ self.connect(self.keywordsList, Signals.itemSelected, self.showResults)
+ self.connect(self.resultsList, Signals.itemSelected, self.emitResult)
+
+
+ def rebuildIndex(self, context):
+ """ reconstructs the search 'index' given a berylsetting context
+
+ This might look slow at first glance, but my machine, this
+ function takes less than 0.1 second.
+
+ @param context berylsetting.Context instance
+ @return None
+ """
+ index = self.index
+ index.clear()
+ for p in context.plugins:
+ for key in itemKeywords(p):
+ seq = index.setdefault(key, [])
+ seq.append((p, None))
+ for s in p.Settings:
+ for key in itemKeywords(s):
+ seq = index.setdefault(key, [])
+ seq.append((p, s))
+
+ def showKeywords(self, text):
+ """ displays keywords from the index that match the given text
+
+ @param text search value
+ @return None
+ """
+ text = str(text)
+ if not text:
+ return
+ searchtext = text.lower()
+ index = self.index
+ parent = self.keywordsList
+ parent.clear()
+ for keyword in self.index:
+ if searchtext in keyword.lower():
+ item = ValueListViewItem(parent, keyword, index[keyword])
- def __iter__(self):
- """ iterate over QListView items
+ def showResults(self, item):
+ """ displays plugin/setting items from the selected keyword
+ @return None
"""
- it = QListViewItemIterator(self)
- item = it.current()
- while item:
- yield item
- it += 1
- item = it.current()
+ parent = self.resultsList
+ parent.clear()
+ cache = {}
+ for plugin, setting in item.value:
+ desc = plugin.ShortDesc
+ item = cache.get(plugin)
+ if item is None:
+ value = (plugin, None)
+ item = cache[plugin] = ValueListViewItem(parent, desc, value)
+ item.setPixmap(0, plugin.icon(16, self.loader))
+ if setting:
+ desc = setting.ShortDesc
+ sub = cache.get((plugin, setting))
+ if sub is None:
+ sub = cache[(plugin, setting)] = \
+ ValueListViewItem(item, desc, (plugin, setting))
+ item.setOpen(True)
+
+ def emitResult(self, item):
+ """ emits signal to show a plugin or a setting
+
+ @param item result list view item
+ @return None
+ """
+ plugin, setting = item.value
+ if setting is None:
+ self.emit(Signals.pluginAbout, (plugin, ))
+ else:
+ self.emit(Signals.showSettings, (plugin, Setting(setting), ))
+
+
+class PluginView(ListView):
+ """ PluginView -> mixin for shared view functionality
+
+ """
+ def __init__(self, parent):
+ ListView.__init__(self, parent)
+ configList(self)
+ self.loader = KIconLoader(self.__class__.__name__)
+ self.connect(self, Signals.itemSelected, self.onSelected)
def addPlugins(self):
""" adds list view items for every plugin in context
@@ -99,7 +188,6 @@ class PluginView(KListView):
if not item:
item = QListViewItem(self, plugin.ShortDesc)
item.setVisible(True)
- ##item.setEnabled(plugin.Name in active or plugin.isGeneral)
item.setVisible(plugin.Name in active)
item.setPixmap(0, plugin.icon(self.iconSize, self.loader))
item.setText(0, plugin.ShortDesc)
@@ -114,63 +202,14 @@ class PluginView(KListView):
self.context = context
self.addPlugins()
- def onContextMenu(self, item, point, value):
- """ display a context menu
-
- @param item QListViewItem instance
- @param point QPoint at click
- @param value ignored
- @return None
- """
- if not item:
- return
-
- plugins = list(self.context.plugins)
- plugin = [p for p in plugins if p.ShortDesc==item.text(0)]
- if not plugin:
- return
- else:
- plugin = plugin[0]
-
- pop = Popup(self)
- pop.insertItem(plugin.ShortDesc)
- pop.insertSeparator()
- if plugin.Name in self.context.active:
- menuid = pop.insertItem(i18n('&Disable'))
- else:
- menuid = pop.insertItem(i18n('&Enable'))
- pop.setItemEnabled(menuid, not plugin.isGeneral)
- pop.setItemParameter(menuid, plugins.index(plugin))
- pop.connectItem(menuid, self.enablePlugin)
- pop.popup(point)
-
- def enablePlugin(self, index):
- """ toggle the active state of a plugin
-
- @param index position of plugin within plugins list
- @return None
- """
- plugin = self.context.plugin(index)
- active = self.context.active
- if plugin.Name in active:
- active.remove(plugin.Name)
- else:
- active.append(plugin.Name)
- self.context.active = active
- self.emit(Signals.berylPluginEnabled, (plugin, plugin.Name in active))
- self.emit(Signals.berylSettingChanged, ())
-
def enablePluginItem(self, plugin, enable):
""" toggle the enabled state of a plugin list view item
@param index position of plugin within plugins list
@return None
"""
- for item in self:
- if item.text(0) == plugin.ShortDesc:
- #item.setOpen(enable)
- #item.setEnabled(enable)
- item.setVisible(enable)
+ for item in [i for i in self if i.text(0)==plugin.ShortDesc]:
+ item.setVisible(enable)
class PluginIconView(PluginView):
@@ -181,8 +220,7 @@ class PluginIconView(PluginView):
def __init__(self, parent):
PluginView.__init__(self, parent)
- self.connect(self, Signals.itemClicked, self.onSelected)
- self.selectedPlugin = self.selectedSetting = None
+ self.selectedPlugin = None
def onIconSize(self, size):
""" update the icon size
@@ -216,26 +254,19 @@ class PluginIconView(PluginView):
item.setVisible(True)
else:
item.setVisible(False)
- elif self.selectedSetting != text:
- self.selectedSetting = text
- plugin = self.selectedPlugin
- name = str(text)
- print '***', name
- self.emit(Signals.showSettings, (plugin, name))
+ else:
+ args = (self.selectedPlugin, str(text), )
+ self.emit(Signals.showSettings, args)
def navToSettings(self, plugin):
+ """ needs to be renamed and reworked
+
+ """
self.emit(Signals.statusMessage, ('%s.navToSettings(%r)' % (self.__class__.__name__, plugin), ))
self.selectedPlugin = plugin
groups = plugin.settings
-
- for k, v in groups.items():
- print k
- for a in v:
- print ' ', a.ShortDesc
-
keys = groups.keys()
keys.sort()
-
for key in keys:
label = key #Setting.label(key)
sub = self.findItem(label, 0)
@@ -265,7 +296,6 @@ class PluginTreeView(PluginView):
def __init__(self, parent):
PluginView.__init__(self, parent)
self.setRootIsDecorated(True)
- self.connect(self, Signals.itemSelected, self.onSelected)
def listItem(self, plugin, active):
""" create an item for the plugin and sub items for its settings
@@ -297,3 +327,28 @@ class PluginTreeView(PluginView):
plugin = self.context.plugin(item.parent().text(0))
name = str(item.text(0))
self.emit(Signals.showSettings, (plugin, name))
+
+
+def configList(obj):
+ """ configures a ListView with a single column, no sorting, hidden
+ header and no horizontal scrollbar.
+
+ @param obj KListView or QListView instance
+ @return None
+ """
+ obj.addColumn('')
+ obj.setSorting(-1)
+ obj.header().hide()
+ obj.setHScrollBarMode(obj.AlwaysOff)
+
+
+def itemKeywords(obj):
+ """ creates a list of keywords for the given berylsettings object
+
+ @param obj berylsettings Plugin or Setting instance
+ @return list of keywords
+ """
+ values = [obj.ShortDesc, obj.LongDesc, ] + \
+ obj.ShortDesc.split() + \
+ obj.LongDesc.split()
+ return [sub('\W|_', ' ', v) for v in values]
diff --git a/kberylsettings/settingframe.py b/kberylsettings/settingframe.py
index c9673c4..7ead0a3 100644
--- a/kberylsettings/settingframe.py
+++ b/kberylsettings/settingframe.py
@@ -1,15 +1,26 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
+""" kberylsettings.settingframe -> defines SettingFrame for displaying
+berylsettings.Setting instances.
+
+"""
+from qt import Qt, QFrame, QHBoxLayout, QSizePolicy, QLabel, QVBoxLayout, \
+ QCheckBox, QColor, qRgba, QToolTip
-from qt import QFrame, QHBoxLayout, QSizePolicy, QLabel, Qt, QVBoxLayout, QCheckBox, QColor, qRgba, QToolTip
from kdecore import KShortcut, KKey
-from kdeui import KIntNumInput, KDoubleNumInput, KComboBox, KLineEdit, KKeyButton, KColorButton
+from kdeui import KIntNumInput, KDoubleNumInput, KComboBox, KLineEdit, \
+ KKeyButton, KColorButton
-from kberylsettings.lib import appDebug, iconSet, Signals
+from kberylsettings.lib import App, Signals, iconSet
from kberylsettings.widget import SmallPushButton
def numberInput(cls):
+ """ returns closure to display indicated class
+
+ @param cls KIntNumInput or KDoubleNumInput
+ @return function for displaying cls
+ """
def builder(self):
layout = QVBoxLayout()
try:
@@ -27,18 +38,25 @@ def numberInput(cls):
class SettingFrame(QFrame):
+ """ SettingFrame -> displays editing widgets for a single Setting instance.
+
+ """
def __init__(self, parent, setting):
QFrame.__init__(self, parent)
layout = QHBoxLayout(self, 3, 3)
self.setting = setting
- if appDebug:
+ if App.debug:
self.setFrameStyle(QFrame.Box|QFrame.Plain)
- self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Minimum))
+ self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding,
+ QSizePolicy.Minimum))
self.buildWidgets()
def buildWidgets(self):
+ """ builds widgets on this instance
+
+ @return None
+ """
layout = self.layout()
- print '*****', self.setting.label
self.label = QLabel(self.setting.label, self)
self.infoButton = SmallPushButton(iconSet('help'), '', self)
tooltip = QToolTip.add(self.infoButton, self.setting.LongDesc or '')
@@ -50,8 +68,14 @@ class SettingFrame(QFrame):
nextlayout = builder()
layout.addLayout(nextlayout, 100)
+ buildInt = numberInput(KIntNumInput)
+ buildFloat = numberInput(KDoubleNumInput)
def buildBool(self):
+ """ builds widget for a boolean setting
+
+ @return layout instance
+ """
layout = QHBoxLayout()
self.cb = QCheckBox(self)
self.cb.setChecked(self.setting.Value)
@@ -59,10 +83,11 @@ class SettingFrame(QFrame):
layout.addWidget(self.label, 100)
return layout
- buildInt = numberInput(KIntNumInput)
- buildFloat = numberInput(KDoubleNumInput)
-
def buildString(self):
+ """ builds widget for a string setting
+
+ @return layout instance
+ """
layout = QVBoxLayout()
try:
s = self.setting.Value
@@ -84,6 +109,10 @@ class SettingFrame(QFrame):
return layout
def buildColor(self):
+ """ builds widget for a color setting
+
+ @return layout instance
+ """
layout = QHBoxLayout()
self.color = QColor(qRgba(*[a/256 for a in self.setting.Value]))
self.colorButton = KColorButton(self)
@@ -93,6 +122,10 @@ class SettingFrame(QFrame):
return layout
def buildUnknown(self):
+ """ builds widget for an unknown setting
+
+ @return layout instance
+ """
layout = QHBoxLayout()
text = '%s (Unknown Type %s)' % (self.setting.ShortDesc, self.setting.Type, )
self.label.setText(text)
@@ -109,6 +142,10 @@ class SettingFrame(QFrame):
##
def buildBinding(self):
+ """ builds widget for a binding setting
+
+ @return layout instance
+ """
layout = QHBoxLayout()
self.line = KLineEdit('%s || %s' % (self.setting.Value, self.setting.Restrictions, ), self)
self.keybutton = KKeyButton(self)
@@ -121,8 +158,12 @@ class SettingFrame(QFrame):
def toKKey(v):
+ """ creates a KKey instance from a key setting
+
+ @param v key setting as string
+ @return KKey instance
+ """
v = v.replace("Control", "ctrl")
v = v.replace('<', '')
v = v.replace('>', '+')
return KKey(v)
-
diff --git a/kberylsettings/widget.py b/kberylsettings/widget.py
index 5b2dc29..246c29d 100644
--- a/kberylsettings/widget.py
+++ b/kberylsettings/widget.py
@@ -1,10 +1,17 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-from qt import Qt, QFrame, QSizePolicy, QSplitter, QVBoxLayout
-from kdeui import KPopupMenu, KPushButton
+""" kberylsettings.widget -> various common widgets.
+
+"""
+from qt import Qt, QFrame, QListViewItem, QListViewItemIterator, QSizePolicy, \
+ QSplitter, QVBoxLayout, QWidgetStack
+from kdeui import KListView, KPopupMenu, KPushButton
class Frame(QFrame):
+ """ Frame -> QFrame with QVBoxLayout
+
+ """
def __init__(self, parent, margin=0, spacing=-1):
QFrame.__init__(self, parent)
layout = QVBoxLayout(self, margin, spacing)
@@ -13,21 +20,65 @@ class Frame(QFrame):
class Popup(KPopupMenu):
+ """ Popup -> KPopupMenu always set to checkable
+
+ """
def __init__(self, parent):
KPopupMenu.__init__(self, parent)
self.setCheckable(True)
class Splitter(QSplitter):
+ """ Splitter -> QSplitter always set to opaque resize
+
+ """
def __init__(self, parent, style):
QSplitter.__init__(self, style, parent)
self.setOpaqueResize(True)
class SmallPushButton(KPushButton):
+ """ SmallPushButton -> KPushButton with fixed sizes
+
+ """
def __init__(self, icon, text, parent):
KPushButton.__init__(self, icon, text, parent)
self.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed))
+class ValueListViewItem(QListViewItem):
+ """ ValueListViewItem -> QListViewItem with extra 'value' attribute
+
+ """
+ def __init__(self, parent, text, value=None):
+ QListViewItem.__init__(self, parent, text)
+ self.value = value
+
+
+class ListView(KListView):
+ """ ListView -> KListView that is directly iterable
+ """
+ def __init__(self, parent):
+ KListView.__init__(self, parent)
+
+ def __iter__(self):
+ """ iterate over QListView items
+
+ """
+ it = QListViewItemIterator(self)
+ item = it.current()
+ while item:
+ yield item
+ it += 1
+ item = it.current()
+
+
+class WidgetStack(QWidgetStack):
+ """ WidgetStack -> QWidgetStack with QVBoxLayout
+
+ """
+ def __init__(self, parent):
+ QWidgetStack.__init__(self, parent)
+ layout = QVBoxLayout(self)
+ layout.setAutoAdd(True)