[Xfce4-commits] [panel-plugins/xfce4-whiskermenu-plugin] 151/473: Add option to load menu hierarchy.

noreply at xfce.org noreply at xfce.org
Mon Feb 16 23:55:21 CET 2015


This is an automated email from the git hooks/post-receive script.

gottcode pushed a commit to branch master
in repository panel-plugins/xfce4-whiskermenu-plugin.

commit 413eb752a7098aecbfe2f9dbcf0f48cfa4a624c7
Author: Graeme Gott <graeme at gottcode.org>
Date:   Thu Aug 1 08:34:11 2013 -0400

    Add option to load menu hierarchy.
---
 src/applications_page.cpp    |   77 ++++++++++++--------
 src/applications_page.hpp    |    8 ++-
 src/category.cpp             |  160 ++++++++++++++++++++++++++++++++++++++++--
 src/category.hpp             |   13 ++--
 src/configuration_dialog.cpp |   15 ++++
 src/configuration_dialog.hpp |    7 ++
 src/panel_plugin.cpp         |    2 +
 7 files changed, 238 insertions(+), 44 deletions(-)

diff --git a/src/applications_page.cpp b/src/applications_page.cpp
index 4232983..72f48be 100644
--- a/src/applications_page.cpp
+++ b/src/applications_page.cpp
@@ -34,10 +34,13 @@ using namespace WhiskerMenu;
 
 //-----------------------------------------------------------------------------
 
+static bool f_load_hierarchy = false;
+
+//-----------------------------------------------------------------------------
+
 ApplicationsPage::ApplicationsPage(Menu* menu) :
 	Page(menu),
 	m_garcon_menu(NULL),
-	m_current_category(NULL),
 	m_all_button(NULL),
 	m_model(NULL),
 	m_loaded(false)
@@ -131,15 +134,18 @@ void ApplicationsPage::load_applications()
 	if (garcon_menu_load(m_garcon_menu, NULL, NULL))
 	{
 		g_signal_connect_swapped(m_garcon_menu, "reload-required", G_CALLBACK(ApplicationsPage::invalidate_applications_slot), this);
-		load_menu(m_garcon_menu);
+		load_menu(m_garcon_menu, NULL);
 	}
 
 	// Sort items and categories
-	for (std::vector<Category*>::const_iterator i = m_categories.begin(), end = m_categories.end(); i != end; ++i)
+	if (!f_load_hierarchy)
 	{
-		(*i)->sort();
+		for (std::vector<Category*>::const_iterator i = m_categories.begin(), end = m_categories.end(); i != end; ++i)
+		{
+			(*i)->sort();
+		}
+		std::sort(m_categories.begin(), m_categories.end(), &Element::less_than);
 	}
-	std::sort(m_categories.begin(), m_categories.end(), &Element::less_than);
 
 	// Create sorted list of menu items
 	std::vector<Launcher*> sorted_items;
@@ -209,7 +215,7 @@ void ApplicationsPage::clear_applications()
 
 //-----------------------------------------------------------------------------
 
-void ApplicationsPage::load_menu(GarconMenu* menu)
+void ApplicationsPage::load_menu(GarconMenu* menu, Category* parent_category)
 {
 	GarconMenuDirectory* directory = garcon_menu_get_directory(menu);
 
@@ -220,15 +226,20 @@ void ApplicationsPage::load_menu(GarconMenu* menu)
 		return;
 	}
 
-	// Only track single level of categories
+	// Track categories
 	bool first_level = directory && (garcon_menu_get_parent(menu) == m_garcon_menu);
-	if (first_level)
-	{
-		m_current_category = new Category(directory);
-		m_categories.push_back(m_current_category);
-	}
+	Category* category = NULL;
 	if (directory)
 	{
+		if (first_level)
+		{
+			category = new Category(directory);
+			m_categories.push_back(category);
+		}
+		else if (parent_category)
+		{
+			category = parent_category->append_menu(directory);
+		}
 		g_object_unref(directory);
 	}
 
@@ -238,29 +249,25 @@ void ApplicationsPage::load_menu(GarconMenu* menu)
 	{
 		if (GARCON_IS_MENU_ITEM(li->data))
 		{
-			load_menu_item(GARCON_MENU_ITEM(li->data));
+			load_menu_item(GARCON_MENU_ITEM(li->data), category);
 		}
 		else if (GARCON_IS_MENU(li->data))
 		{
-			load_menu(GARCON_MENU(li->data));
+			load_menu(GARCON_MENU(li->data), category);
 		}
-		else if (GARCON_IS_MENU_SEPARATOR(li->data) && m_current_category)
+		else if (GARCON_IS_MENU_SEPARATOR(li->data) && f_load_hierarchy && category)
 		{
-			m_current_category->append_separator();
+			category->append_separator();
 		}
 	}
 	g_list_free(elements);
 
-	// Only track single level of categories
-	if (first_level)
+	// Free unused top-level categories
+	if (first_level && category->empty())
 	{
-		// Free unused categories
-		if (m_current_category->empty())
-		{
-			m_categories.erase(std::find(m_categories.begin(), m_categories.end(), m_current_category));
-			delete m_current_category;
-		}
-		m_current_category = NULL;
+		m_categories.erase(std::find(m_categories.begin(), m_categories.end(), category));
+		delete category;
+		category = NULL;
 	}
 
 	// Listen for menu changes
@@ -269,7 +276,7 @@ void ApplicationsPage::load_menu(GarconMenu* menu)
 
 //-----------------------------------------------------------------------------
 
-void ApplicationsPage::load_menu_item(GarconMenuItem* menu_item)
+void ApplicationsPage::load_menu_item(GarconMenuItem* menu_item, Category* category)
 {
 	// Skip hidden items
 	if (!garcon_menu_element_get_visible(GARCON_MENU_ELEMENT(menu_item)))
@@ -286,9 +293,9 @@ void ApplicationsPage::load_menu_item(GarconMenuItem* menu_item)
 	}
 
 	// Add menu item to current category
-	if (m_current_category)
+	if (category)
 	{
-		m_current_category->append_item(iter->second);
+		category->append_item(iter->second);
 	}
 
 	// Listen for menu changes
@@ -330,3 +337,17 @@ void ApplicationsPage::unset_model()
 }
 
 //-----------------------------------------------------------------------------
+
+bool ApplicationsPage::get_load_hierarchy()
+{
+	return f_load_hierarchy;
+}
+
+//-----------------------------------------------------------------------------
+
+void ApplicationsPage::set_load_hierarchy(bool load)
+{
+	f_load_hierarchy = load;
+}
+
+//-----------------------------------------------------------------------------
diff --git a/src/applications_page.hpp b/src/applications_page.hpp
index 2d8ce7c..00a010c 100644
--- a/src/applications_page.hpp
+++ b/src/applications_page.hpp
@@ -54,18 +54,20 @@ public:
 	void invalidate_applications();
 	void load_applications();
 
+	static bool get_load_hierarchy();
+	static void set_load_hierarchy(bool load);
+
 private:
 	void apply_filter(GtkToggleButton* togglebutton);
 	bool on_filter(GtkTreeModel* model, GtkTreeIter* iter);
 	void clear_applications();
-	void load_menu(GarconMenu* menu);
-	void load_menu_item(GarconMenuItem* menu_item);
+	void load_menu(GarconMenu* menu, Category* parent_category);
+	void load_menu_item(GarconMenuItem* menu_item, Category* category);
 	void load_categories();
 	void unset_model();
 
 private:
 	GarconMenu* m_garcon_menu;
-	Category* m_current_category;
 	SectionButton* m_all_button;
 	std::vector<Category*> m_categories;
 	std::map<std::string, Launcher*> m_items;
diff --git a/src/category.cpp b/src/category.cpp
index 298360c..379ef83 100644
--- a/src/category.cpp
+++ b/src/category.cpp
@@ -16,7 +16,6 @@
 
 #include "category.hpp"
 
-#include "launcher.hpp"
 #include "launcher_model.hpp"
 #include "section_button.hpp"
 
@@ -26,6 +25,18 @@ using namespace WhiskerMenu;
 
 //-----------------------------------------------------------------------------
 
+static bool is_category(const Element* element)
+{
+	return element && (element->get_type() == Category::Type);
+}
+
+static bool is_null(const Element* element)
+{
+	return !element;
+}
+
+//-----------------------------------------------------------------------------
+
 Category::Category(GarconMenuDirectory* directory) :
 	m_button(NULL),
 	m_model(NULL),
@@ -55,6 +66,14 @@ Category::~Category()
 	unset_model();
 
 	delete m_button;
+
+	for (std::vector<Element*>::const_iterator i = m_items.begin(), end = m_items.end(); i != end; ++i)
+	{
+		if (is_category(*i))
+		{
+			delete *i;
+		}
+	}
 }
 
 //-----------------------------------------------------------------------------
@@ -75,16 +94,41 @@ GtkTreeModel* Category::get_model()
 {
 	if (!m_model)
 	{
-		LauncherModel model;
-		for (std::vector<Launcher*>::const_iterator i = m_items.begin(), end = m_items.end(); i != end; ++i)
+		GtkTreeStore* model = gtk_tree_store_new(
+				LauncherModel::N_COLUMNS,
+				G_TYPE_STRING,
+				G_TYPE_STRING,
+				G_TYPE_POINTER);
+		insert_items(model, NULL, get_icon());
+		m_model = GTK_TREE_MODEL(model);
+	}
+
+	return m_model;
+}
+
+//-----------------------------------------------------------------------------
+
+bool Category::empty() const
+{
+	for (std::vector<Element*>::const_iterator i = m_items.begin(), end = m_items.end(); i != end; ++i)
+	{
+		if (*i && (!is_category(*i) || !static_cast<Category*>(*i)->empty()))
 		{
-			model.append_item(*i);
+			return false;
 		}
-		m_model = model.get_model();
-		g_object_ref(m_model);
 	}
 
-	return m_model;
+	return true;
+}
+
+//-----------------------------------------------------------------------------
+
+Category* Category::append_menu(GarconMenuDirectory* directory)
+{
+	unset_model();
+	Category* category = new Category(directory);
+	m_items.push_back(category);
+	return category;
 }
 
 //-----------------------------------------------------------------------------
@@ -104,11 +148,113 @@ void Category::append_separator()
 void Category::sort()
 {
 	unset_model();
+	merge();
 	std::sort(m_items.begin(), m_items.end(), &Element::less_than);
 }
 
 //-----------------------------------------------------------------------------
 
+void Category::insert_items(GtkTreeStore* model, GtkTreeIter* parent, const gchar* fallback_icon)
+{
+	for (std::vector<Element*>::size_type i = 0, end = m_items.size(); i < end; ++i)
+	{
+		Element* element = m_items.at(i);
+		if (is_category(element))
+		{
+			Category* category = static_cast<Category*>(element);
+			if (category->empty())
+			{
+				continue;
+			}
+
+			const gchar* icon = category->get_icon();
+			if (!gtk_icon_theme_has_icon(gtk_icon_theme_get_default(), icon))
+			{
+				icon = fallback_icon;
+			}
+			gchar* text = g_markup_escape_text(category->get_text(), -1);
+
+			GtkTreeIter iter;
+			gtk_tree_store_insert_with_values(model,
+					&iter, parent, INT_MAX,
+					LauncherModel::COLUMN_ICON, icon,
+					LauncherModel::COLUMN_TEXT, text,
+					LauncherModel::COLUMN_LAUNCHER, NULL,
+					-1);
+			g_free(text);
+			category->insert_items(model, &iter, icon);
+		}
+		else if (element)
+		{
+			Launcher* launcher = static_cast<Launcher*>(element);
+			gtk_tree_store_insert_with_values(model,
+					NULL, parent, INT_MAX,
+					LauncherModel::COLUMN_ICON, launcher->get_icon(),
+					LauncherModel::COLUMN_TEXT, launcher->get_text(),
+					LauncherModel::COLUMN_LAUNCHER, launcher,
+					-1);
+		}
+		else if ((i + 1) < end)
+		{
+			gtk_tree_store_insert_with_values(model,
+					NULL, parent, INT_MAX,
+					LauncherModel::COLUMN_ICON, NULL,
+					LauncherModel::COLUMN_TEXT, NULL,
+					LauncherModel::COLUMN_LAUNCHER, NULL,
+					-1);
+		}
+	}
+}
+
+//-----------------------------------------------------------------------------
+
+void Category::merge()
+{
+	// Find subcategories
+	std::vector<Category*> items;
+	items.push_back(this);
+	std::vector<Element*>::size_type count = 0;
+	for (std::vector<Category*>::size_type i = 0; i < items.size(); ++i)
+	{
+		Category* category = items.at(i);
+		count += category->m_items.size();
+
+		for (std::vector<Element*>::const_iterator j = category->m_items.begin(), end = category->m_items.end(); j != end; ++j)
+		{
+			if (is_category(*j))
+			{
+				items.push_back(static_cast<Category*>(*j));
+			}
+		}
+	}
+
+	// Stop if there is nothing to merge
+	if (items.size() == 1)
+	{
+		return;
+	}
+
+	// Append items
+	m_items.reserve(count);
+	for (std::vector<Category*>::const_iterator i = items.begin() + 1, end = items.end(); i != end; ++i)
+	{
+		m_items.insert(m_items.end(), (*i)->m_items.begin(), (*i)->m_items.end());
+	}
+
+	// Remove subcategories and separators
+	for (std::vector<Element*>::iterator i = m_items.begin(), end = m_items.end(); i != end; ++i)
+	{
+		if (is_category(*i))
+		{
+			delete *i;
+			*i = NULL;
+		}
+	}
+	m_items.erase(std::remove_if(m_items.begin(), m_items.end(), is_null), m_items.end());
+}
+
+//-----------------------------------------------------------------------------
+
 void Category::unset_model()
 {
 	if (m_model)
diff --git a/src/category.hpp b/src/category.hpp
index 6768af8..5dc77aa 100644
--- a/src/category.hpp
+++ b/src/category.hpp
@@ -17,7 +17,7 @@
 #ifndef WHISKERMENU_CATEGORY_HPP
 #define WHISKERMENU_CATEGORY_HPP
 
-#include "element.hpp"
+#include "launcher.hpp"
 
 #include <vector>
 
@@ -51,10 +51,7 @@ public:
 
 	GtkTreeModel* get_model();
 
-	bool empty() const
-	{
-		return m_items.empty();
-	}
+	bool empty() const;
 
 	bool has_separators() const
 	{
@@ -67,16 +64,20 @@ public:
 		m_items.push_back(launcher);
 	}
 
+	Category* append_menu(GarconMenuDirectory* directory);
+
 	void append_separator();
 
 	void sort();
 
 private:
+	void insert_items(GtkTreeStore* model, GtkTreeIter* parent, const gchar* fallback_icon);
+	void merge();
 	void unset_model();
 
 private:
 	SectionButton* m_button;
-	std::vector<Launcher*> m_items;
+	std::vector<Element*> m_items;
 	GtkTreeModel* m_model;
 	bool m_has_separators;
 };
diff --git a/src/configuration_dialog.cpp b/src/configuration_dialog.cpp
index 3d8e385..c45e445 100644
--- a/src/configuration_dialog.cpp
+++ b/src/configuration_dialog.cpp
@@ -16,6 +16,7 @@
 
 #include "configuration_dialog.hpp"
 
+#include "applications_page.hpp"
 #include "icon_size.hpp"
 #include "launcher.hpp"
 #include "launcher_view.hpp"
@@ -189,6 +190,12 @@ ConfigurationDialog::ConfigurationDialog(PanelPlugin* plugin) :
 	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_hover_switch_category), SectionButton::get_hover_activate());
 	g_signal_connect(m_hover_switch_category, "toggled", G_CALLBACK(ConfigurationDialog::toggle_hover_switch_category_slot), this);
 
+	// Add option to load menu hierarchy
+	m_load_hierarchy = gtk_check_button_new_with_mnemonic(_("Load menu hie_rarchy"));
+	gtk_box_pack_start(behavior_vbox, m_load_hierarchy, true, true, 0);
+	gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(m_load_hierarchy), ApplicationsPage::get_load_hierarchy());
+	g_signal_connect(m_load_hierarchy, "toggled", G_CALLBACK(ConfigurationDialog::toggle_load_hierarchy_slot), this);
+
 	// Show GTK window
 	gtk_widget_show_all(m_window);
 
@@ -285,6 +292,14 @@ void ConfigurationDialog::toggle_show_description(GtkToggleButton* button)
 
 //-----------------------------------------------------------------------------
 
+void ConfigurationDialog::toggle_load_hierarchy(GtkToggleButton* button)
+{
+	ApplicationsPage::set_load_hierarchy(gtk_toggle_button_get_active(button));
+	m_plugin->reload();
+}
+
+//-----------------------------------------------------------------------------
+
 void ConfigurationDialog::response(int response_id)
 {
 	if ((m_plugin->get_button_style() == PanelPlugin::ShowText) && m_plugin->get_button_title().empty())
diff --git a/src/configuration_dialog.hpp b/src/configuration_dialog.hpp
index 51f7dbc..86f5d72 100644
--- a/src/configuration_dialog.hpp
+++ b/src/configuration_dialog.hpp
@@ -47,6 +47,7 @@ private:
 	void toggle_hover_switch_category(GtkToggleButton* button);
 	void toggle_show_name(GtkToggleButton* button);
 	void toggle_show_description(GtkToggleButton* button);
+	void toggle_load_hierarchy(GtkToggleButton* button);
 	void response(int response_id);
 
 private:
@@ -62,6 +63,7 @@ private:
 	GtkWidget* m_show_names;
 	GtkWidget* m_show_descriptions;
 	GtkWidget* m_hover_switch_category;
+	GtkWidget* m_load_hierarchy;
 
 
 private:
@@ -105,6 +107,11 @@ private:
 		obj->toggle_show_description(button);
 	}
 
+	static void toggle_load_hierarchy_slot(GtkToggleButton* button, ConfigurationDialog* obj)
+	{
+		obj->toggle_load_hierarchy(button);
+	}
+
 	static void response_slot(GtkDialog*, gint response_id, ConfigurationDialog* obj)
 	{
 		obj->response(response_id);
diff --git a/src/panel_plugin.cpp b/src/panel_plugin.cpp
index 91bed49..d2857ce 100644
--- a/src/panel_plugin.cpp
+++ b/src/panel_plugin.cpp
@@ -66,6 +66,7 @@ PanelPlugin::PanelPlugin(XfcePanelPlugin* plugin) :
 		SectionButton::set_hover_activate(xfce_rc_read_bool_entry(settings, "hover-switch-category", SectionButton::get_hover_activate()));
 		SectionButton::set_icon_size(xfce_rc_read_int_entry(settings, "category-icon-size", SectionButton::get_icon_size()));
 		LauncherView::set_icon_size(xfce_rc_read_int_entry(settings, "item-icon-size", LauncherView::get_icon_size()));
+		ApplicationsPage::set_load_hierarchy(xfce_rc_read_bool_entry(settings, "load-hierarchy", ApplicationsPage::get_load_hierarchy()));
 		m_menu = new Menu(settings);
 
 		xfce_rc_close(settings);
@@ -309,6 +310,7 @@ void PanelPlugin::save()
 	xfce_rc_write_bool_entry(settings, "hover-switch-category", SectionButton::get_hover_activate());
 	xfce_rc_write_int_entry(settings, "category-icon-size", SectionButton::get_icon_size());
 	xfce_rc_write_int_entry(settings, "item-icon-size", LauncherView::get_icon_size());
+	xfce_rc_write_bool_entry(settings, "load-hierarchy", ApplicationsPage::get_load_hierarchy());
 	m_menu->save(settings);
 
 	xfce_rc_close(settings);

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Xfce4-commits mailing list