summaryrefslogtreecommitdiff
path: root/kberylsettings/pluginframe.py
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/pluginframe.py
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/pluginframe.py')
-rw-r--r--kberylsettings/pluginframe.py283
1 files changed, 169 insertions, 114 deletions
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]