[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