[kupfer] preferences: Allow configuring toplevel sources



commit e73c5a094dcc81593db2bbe17e4418ab37301666
Author: Ulrik Sverdrup <ulrik sverdrup gmail com>
Date:   Sun May 9 16:25:25 2010 +0100

    preferences: Allow configuring toplevel sources
    
    Add preferences configuration to decide which sources export their
    objects to the top level.

 data/preferences.ui      |  100 ++++++++++++++++++++++++++++++++-------
 kupfer/core/data.py      |    1 +
 kupfer/core/sources.py   |    8 +++
 kupfer/ui/preferences.py |  117 ++++++++++++++++++++++++++++++++++++++++++---
 4 files changed, 201 insertions(+), 25 deletions(-)
---
diff --git a/data/preferences.ui b/data/preferences.ui
index 5ef7da2..342741a 100644
--- a/data/preferences.ui
+++ b/data/preferences.ui
@@ -370,12 +370,12 @@
                   </packing>
                 </child>
                 <child type="tab">
-                  <object class="GtkLabel" id="label2">
+                  <object class="GtkLabel" id="label9">
                     <property name="visible">True</property>
                     <property name="label" translatable="yes">Keyboard</property>
                   </object>
                   <packing>
-                    <property name="position">2</property>
+                    <property name="position">1</property>
                     <property name="tab_fill">False</property>
                   </packing>
                 </child>
@@ -418,21 +418,77 @@
                             <property name="position">1</property>
                           </packing>
                         </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="position">0</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkScrolledWindow" id="plugin_about_parent">
+                        <property name="width_request">320</property>
+                        <property name="can_focus">True</property>
+                        <property name="hscrollbar_policy">never</property>
+                        <property name="vscrollbar_policy">never</property>
+                        <child>
+                          <placeholder/>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="position">2</property>
+                  </packing>
+                </child>
+                <child type="tab">
+                  <object class="GtkLabel" id="label2">
+                    <property name="visible">True</property>
+                    <property name="label" translatable="yes">Plugins</property>
+                  </object>
+                  <packing>
+                    <property name="position">2</property>
+                    <property name="tab_fill">False</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkHBox" id="hbox3">
+                    <property name="visible">True</property>
+                    <property name="spacing">10</property>
+                    <child>
+                      <object class="GtkVBox" id="vbox6">
+                        <property name="visible">True</property>
+                        <property name="orientation">vertical</property>
                         <child>
-                          <object class="GtkLabel" id="labelplugininstructions">
+                          <object class="GtkAlignment" id="alignment3">
                             <property name="visible">True</property>
-                            <property name="label" translatable="yes">&lt;i&gt;Plugins may not be unloaded at runtime&lt;/i&gt;</property>
-                            <property name="use_markup">True</property>
-                            <property name="wrap">True</property>
-                            <property name="width_chars">30</property>
+                            <property name="top_padding">6</property>
+                            <property name="left_padding">6</property>
+                            <child>
+                              <object class="GtkLabel" id="labelplugininstructions1">
+                                <property name="visible">True</property>
+                                <property name="label" translatable="yes">Tick the box next to a source to make sure its objects are exported to the top level of the catalog. An unticked source's contents are only available by locating its subcatalog and entering it.
+
+Note: Kupfer is an integrator, not an indexer itself. Kupfer is not designed to carry a catalog larger than a couple of thousand objects, and may become slow if overly large subcatalogs are included in the top level.</property>
+                                <property name="use_markup">True</property>
+                                <property name="wrap">True</property>
+                                <property name="width_chars">30</property>
+                              </object>
+                            </child>
                           </object>
                           <packing>
                             <property name="expand">False</property>
                             <property name="fill">False</property>
                             <property name="padding">2</property>
-                            <property name="position">2</property>
+                            <property name="position">0</property>
                           </packing>
                         </child>
+                        <child>
+                          <placeholder/>
+                        </child>
                       </object>
                       <packing>
                         <property name="expand">False</property>
@@ -440,29 +496,39 @@
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkScrolledWindow" id="plugin_about_parent">
-                        <property name="width_request">320</property>
-                        <property name="can_focus">True</property>
-                        <property name="hscrollbar_policy">never</property>
-                        <property name="vscrollbar_policy">never</property>
+                      <object class="GtkVBox" id="source_list_container">
+                        <property name="height_request">350</property>
+                        <property name="visible">True</property>
+                        <property name="orientation">vertical</property>
                         <child>
-                          <placeholder/>
+                          <object class="GtkScrolledWindow" id="source_list_parent">
+                            <property name="visible">True</property>
+                            <property name="can_focus">True</property>
+                            <property name="hscrollbar_policy">never</property>
+                            <property name="vscrollbar_policy">automatic</property>
+                            <property name="shadow_type">in</property>
+                            <child>
+                              <placeholder/>
+                            </child>
+                          </object>
+                          <packing>
+                            <property name="position">0</property>
+                          </packing>
                         </child>
                       </object>
                       <packing>
-                        <property name="expand">False</property>
                         <property name="position">1</property>
                       </packing>
                     </child>
                   </object>
                   <packing>
-                    <property name="position">2</property>
+                    <property name="position">3</property>
                   </packing>
                 </child>
                 <child type="tab">
                   <object class="GtkLabel" id="label3">
                     <property name="visible">True</property>
-                    <property name="label" translatable="yes">Plugins</property>
+                    <property name="label" translatable="yes">Catalog</property>
                   </object>
                   <packing>
                     <property name="position">2</property>
diff --git a/kupfer/core/data.py b/kupfer/core/data.py
index c384034..c4ee1e2 100644
--- a/kupfer/core/data.py
+++ b/kupfer/core/data.py
@@ -485,6 +485,7 @@ class DataController (gobject.GObject, pretty.OutputMixin):
 		"""Load data from persistent store"""
 		setctl = settings.GetSettingsController()
 		setctl.connect("plugin-enabled-changed", self._plugin_enabled)
+		setctl.connect("plugin-toplevel-changed", self._plugin_catalog_changed)
 
 		self._load_all_plugins()
 		D_s, d_s = self._get_directory_sources()
diff --git a/kupfer/core/sources.py b/kupfer/core/sources.py
index 6f5ffff..8471e91 100644
--- a/kupfer/core/sources.py
+++ b/kupfer/core/sources.py
@@ -274,6 +274,14 @@ class SourceController (pretty.OutputMixin):
 		if plugin_id:
 			self._register_plugin_objects(plugin_id, *sources)
 
+	def set_toplevel(self, src, toplevel):
+		assert src in self.sources, "Source is not tracked in SourceController"
+		self._invalidate_root()
+		if toplevel:
+			self.toplevel_sources.add(src)
+		else:
+			self.toplevel_sources.discard(src)
+
 	def _register_plugin_objects(self, plugin_id, *objects):
 		"Register a plugin id mapping for @objects"
 		for obj in objects:
diff --git a/kupfer/ui/preferences.py b/kupfer/ui/preferences.py
index d743e28..a12797c 100644
--- a/kupfer/ui/preferences.py
+++ b/kupfer/ui/preferences.py
@@ -11,11 +11,17 @@ from xdg import DesktopEntry as desktop
 
 from kupfer import config, pretty, utils, icons, version
 from kupfer import scheduler, kupferstring
-from kupfer.core import settings, plugins, relevance
+from kupfer.core import settings, plugins, relevance, sources
 from kupfer.ui import keybindings
 from kupfer.ui.credentials_dialog import ask_user_credentials
 from kupfer.ui import getkey_dialog
 
+# index in GtkNotebook
+PLUGIN_LIST_PAGE = 2
+
+# List icon pixel size
+LIST_ICON_SIZE = 18
+
 # A major HACK
 # http://tadeboro.blogspot.com/2009/05/wrapping-adn-resizing-gtklabel.html
 def _cb_allocate(label, allocation, maxwid):
@@ -30,6 +36,18 @@ def wrapped_label(text=None, maxwid=-1):
 	label.connect("size-allocate", _cb_allocate, maxwid)
 	return label
 
+def kobject_should_show(obj):
+	try:
+		leaf_repr = obj.get_leaf_repr()
+	except AttributeError:
+		pass
+	else:
+		if leaf_repr is None:
+			return True
+		if hasattr(leaf_repr, "is_valid") and not leaf_repr.is_valid():
+			return False
+	return True
+
 class PreferencesWindowController (pretty.OutputMixin):
 
 	KEYBINDING_NAMES = {
@@ -89,6 +107,8 @@ class PreferencesWindowController (pretty.OutputMixin):
 		self.entry_plugins_filter = builder.get_object('entry_plugins_filter')
 		self.keybindings_list_parent = builder.get_object('keybindings_list_parent')
 		self.gkeybindings_list_parent = builder.get_object('gkeybindings_list_parent')
+		source_list_parent = builder.get_object("source_list_parent")
+		self.sources_list_ctrl = SourceListController(source_list_parent)
 
 		setctl = settings.GetSettingsController()
 		checkautostart.set_active(self._get_should_autostart())
@@ -120,8 +140,8 @@ class PreferencesWindowController (pretty.OutputMixin):
 		checkcell.connect("toggled", self.on_checkplugin_toggled)
 
 		icon_cell = gtk.CellRendererPixbuf()
-		icon_cell.set_property("height", 18)
-		icon_cell.set_property("width", 18)
+		icon_cell.set_property("height", LIST_ICON_SIZE)
+		icon_cell.set_property("width", LIST_ICON_SIZE)
 
 		icon_col = gtk.TreeViewColumn("icon", icon_cell)
 		icon_col.add_attribute(icon_cell, "icon-name",
@@ -485,14 +505,14 @@ class PreferencesWindowController (pretty.OutputMixin):
 				hbox.pack_start(label, False)
 				objvbox.pack_start(hbox)
 				# Display information for application content-sources.
+				if not kobject_should_show(obj):
+					continue
 				try:
 					leaf_repr = obj.get_leaf_repr()
 				except AttributeError:
 					continue
 				if leaf_repr is None:
 					continue
-				if hasattr(leaf_repr, "is_valid") and not leaf_repr.is_valid():
-					continue
 				hbox = gtk.HBox()
 				hbox.set_property("spacing", 3)
 				gicon = leaf_repr.get_icon()
@@ -732,9 +752,7 @@ class PreferencesWindowController (pretty.OutputMixin):
 			table_path = self._table_path_for_id(plugin_id)
 		self.table.set_cursor(table_path)
 		self.table.scroll_to_cell(table_path)
-		# FIXME: Revisit if we add new pages to the GtkNotebook
-		self.preferences_notebook.next_page()
-		self.preferences_notebook.next_page()
+		self.preferences_notebook.set_current_page(PLUGIN_LIST_PAGE)
 		self.window.present()
 
 	def hide(self):
@@ -780,3 +798,86 @@ def GetPreferencesWindowController():
 	if _preferences_window is None:
 		_preferences_window = PreferencesWindowController()
 	return _preferences_window
+
+class SourceListController (object):
+	def __init__(self, parent_widget):
+		columns = [
+			{"key": "source", "type": gobject.TYPE_PYOBJECT },
+			{"key": "plugin_id", "type": str },
+			{"key": "toplevel", "type": bool },
+			{"key": "icon", "type": gio.Icon },
+			{"key": "markup", "type": str },
+		]
+		# setup plugin list table
+		column_types = [c["type"] for c in columns]
+		self.columns = [c["key"] for c in columns]
+		self.store = gtk.ListStore(*column_types)
+		self.table = gtk.TreeView(self.store)
+		self.table.set_headers_visible(False)
+		self.table.set_property("enable-search", False)
+		self.table.set_rules_hint(True)
+		#self.table.connect("cursor-changed", self.plugin_table_cursor_changed)
+		self.table.get_selection().set_mode(gtk.SELECTION_NONE)
+
+		checkcell = gtk.CellRendererToggle()
+		checkcol = gtk.TreeViewColumn("item", checkcell)
+		checkcol.add_attribute(checkcell, "active",
+				self.columns.index("toplevel"))
+		checkcell.connect("toggled", self.on_checktoplevel_enabled)
+
+		icon_cell = gtk.CellRendererPixbuf()
+		icon_cell.set_property("height", LIST_ICON_SIZE)
+		icon_cell.set_property("width", LIST_ICON_SIZE)
+
+		icon_col = gtk.TreeViewColumn("icon", icon_cell)
+		icon_col.add_attribute(icon_cell, "gicon",
+				self.columns.index("icon"))
+
+		cell = gtk.CellRendererText()
+		col = gtk.TreeViewColumn("item", cell)
+		col.add_attribute(cell, "markup", self.columns.index("markup"))
+
+		self.table.append_column(checkcol)
+		self.table.append_column(icon_col)
+		self.table.append_column(col)
+
+		self._refresh()
+		self.table.show()
+		parent_widget.add(self.table)
+
+		setctl = settings.GetSettingsController()
+		setctl.connect("plugin-enabled-changed", self._refresh)
+
+	def _refresh(self, *ignored):
+		self.store.clear()
+		setctl = settings.GetSettingsController()
+		sc = sources.GetSourceController()
+		srcs = sorted(sc.get_sources(), key=unicode)
+
+		for src in srcs:
+			name = unicode(src)
+			plugin_id = sc.get_plugin_id_for_object(src)
+			if not plugin_id or setctl.get_plugin_is_hidden(plugin_id):
+				continue
+			if not kobject_should_show(src):
+				continue
+			gicon = src.get_icon()
+			toplevel = setctl.get_source_is_toplevel(plugin_id, src)
+
+			self.store.append((src, plugin_id, toplevel, gicon, name))
+
+	def on_checktoplevel_enabled(self, cell, path):
+		it = self.store.get_iter(path)
+		checkcol = self.columns.index("toplevel")
+		idcol = self.columns.index("plugin_id")
+		srccol = self.columns.index("source")
+		is_toplevel = not self.store.get_value(it, checkcol)
+		plugin_id = self.store.get_value(it, idcol)
+		src = self.store.get_value(it, srccol)
+
+		sc = sources.GetSourceController()
+		sc.set_toplevel(src, is_toplevel)
+
+		setctl = settings.GetSettingsController()
+		setctl.set_source_is_toplevel(plugin_id, src, is_toplevel)
+		self.store.set_value(it, checkcol, is_toplevel)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]