[Xfce4-commits] [panel-plugins/xfce4-whiskermenu-plugin] 218/473: Defer loading applications until window is shown.

noreply at xfce.org noreply at xfce.org
Mon Feb 16 23:56:28 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 88b811937ace62cb7d35f1f202d5003042b79e68
Author: Graeme Gott <graeme at gottcode.org>
Date:   Sun Nov 3 18:48:22 2013 -0500

    Defer loading applications until window is shown.
---
 panel-plugin/applications-page.cpp |  172 +++++++++++++++++++++++-------------
 panel-plugin/applications-page.h   |   19 +++-
 panel-plugin/window.cpp            |   47 +++++++---
 panel-plugin/window.h              |    6 ++
 4 files changed, 172 insertions(+), 72 deletions(-)

diff --git a/panel-plugin/applications-page.cpp b/panel-plugin/applications-page.cpp
index 275d86b..36ea47e 100644
--- a/panel-plugin/applications-page.cpp
+++ b/panel-plugin/applications-page.cpp
@@ -30,10 +30,20 @@ using namespace WhiskerMenu;
 
 //-----------------------------------------------------------------------------
 
+enum
+{
+	STATUS_INVALID,
+	STATUS_LOADING,
+	STATUS_LOADED
+};
+
+//-----------------------------------------------------------------------------
+
 ApplicationsPage::ApplicationsPage(Window* window) :
 	Page(window),
 	m_garcon_menu(NULL),
-	m_loaded(false)
+	m_load_thread(NULL),
+	m_load_status(STATUS_INVALID)
 {
 	// Set desktop environment for applications
 	const gchar* desktop = g_getenv("XDG_CURRENT_DESKTOP");
@@ -52,6 +62,12 @@ ApplicationsPage::ApplicationsPage(Window* window) :
 
 ApplicationsPage::~ApplicationsPage()
 {
+	if (m_load_thread)
+	{
+		g_thread_join(m_load_thread);
+		m_load_thread = NULL;
+	}
+
 	clear_applications();
 }
 
@@ -98,62 +114,40 @@ void ApplicationsPage::apply_filter(GtkToggleButton* togglebutton)
 
 void ApplicationsPage::invalidate_applications()
 {
-	m_loaded = false;
+	m_load_status = STATUS_INVALID;
 }
 
 //-----------------------------------------------------------------------------
 
-void ApplicationsPage::load_applications()
+bool ApplicationsPage::load_applications()
 {
-	if (m_loaded)
+	// Check if already loaded
+	if (m_load_status == STATUS_LOADED)
 	{
-		return;
+		return false;
 	}
-
-	// Remove previous menu data
-	clear_applications();
-
-	// Populate map of menu data
-	m_garcon_menu = garcon_menu_new_applications();
-	if (garcon_menu_load(m_garcon_menu, NULL, NULL))
+	// Check if currently loading
+	else if (m_load_status == STATUS_LOADING)
 	{
-		g_signal_connect_swapped(m_garcon_menu, "reload-required", G_CALLBACK(ApplicationsPage::invalidate_applications_slot), this);
-		load_menu(m_garcon_menu, NULL);
+		return true;
 	}
-	else
+	// Check if loading garcon
+	else if (m_load_thread)
 	{
-		return;
+		return true;
 	}
+	m_load_status = STATUS_LOADING;
 
-	// Sort items and categories
-	if (!wm_settings->load_hierarchy)
-	{
-		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);
-	}
+	clear_applications();
 
-	// Create all items category
-	Category* category = new Category(NULL);
-	for (std::map<std::string, Launcher*>::const_iterator i = m_items.begin(), end = m_items.end(); i != end; ++i)
+	// Load garcon menu in thread if possible
+	m_load_thread = g_thread_try_new(NULL, (GThreadFunc)&ApplicationsPage::load_garcon_menu_slot, this, NULL);
+	if (!m_load_thread)
 	{
-		category->append_item(i->second);
+		load_garcon_menu();
 	}
-	category->sort();
-	m_categories.insert(m_categories.begin(), category);
-
-	get_view()->set_fixed_height_mode(true);
-	get_view()->set_model(category->get_model());
-
-	// Update filters
-	load_categories();
-
-	// Update menu items of other panels
-	get_window()->set_items();
 
-	m_loaded = true;
+	return true;
 }
 
 //-----------------------------------------------------------------------------
@@ -197,6 +191,84 @@ void ApplicationsPage::clear_applications()
 
 //-----------------------------------------------------------------------------
 
+void ApplicationsPage::load_garcon_menu()
+{
+	m_garcon_menu = garcon_menu_new_applications();
+
+	if (!garcon_menu_load(m_garcon_menu, NULL, NULL))
+	{
+		g_object_unref(m_garcon_menu);
+		m_garcon_menu = NULL;
+	}
+
+	g_idle_add((GSourceFunc)&ApplicationsPage::load_contents_slot, this);
+}
+
+//-----------------------------------------------------------------------------
+
+bool ApplicationsPage::load_contents()
+{
+	if (!m_garcon_menu)
+	{
+		get_window()->set_loaded();
+
+		m_load_status = STATUS_INVALID;
+		m_load_thread = NULL;
+
+		return false;
+	}
+
+	// Populate map of menu data
+	g_signal_connect_swapped(m_garcon_menu, "reload-required", G_CALLBACK(ApplicationsPage::invalidate_applications_slot), this);
+	load_menu(m_garcon_menu, NULL);
+
+	// Sort items and categories
+	if (!wm_settings->load_hierarchy)
+	{
+		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);
+	}
+
+	// Create all items category
+	Category* category = new Category(NULL);
+	for (std::map<std::string, Launcher*>::const_iterator i = m_items.begin(), end = m_items.end(); i != end; ++i)
+	{
+		category->append_item(i->second);
+	}
+	category->sort();
+	m_categories.insert(m_categories.begin(), category);
+
+	// Set all applications category
+	get_view()->set_fixed_height_mode(true);
+	get_view()->set_model(category->get_model());
+
+	// Add buttons for categories
+	std::vector<SectionButton*> category_buttons;
+	for (std::vector<Category*>::const_iterator i = m_categories.begin(), end = m_categories.end(); i != end; ++i)
+	{
+		SectionButton* category_button = (*i)->get_button();
+		g_signal_connect(category_button->get_button(), "toggled", G_CALLBACK(ApplicationsPage::apply_filter_slot), this);
+		category_buttons.push_back(category_button);
+	}
+
+	// Add category buttons to window
+	get_window()->set_categories(category_buttons);
+
+	// Update menu items of other panels
+	get_window()->set_items();
+	get_window()->set_loaded();
+
+	m_load_status = STATUS_LOADED;
+	m_load_thread = NULL;
+
+	return false;
+}
+
+//-----------------------------------------------------------------------------
+
 void ApplicationsPage::load_menu(GarconMenu* menu, Category* parent_category)
 {
 	GarconMenuDirectory* directory = garcon_menu_get_directory(menu);
@@ -287,21 +359,3 @@ void ApplicationsPage::load_menu_item(GarconMenuItem* menu_item, Category* categ
 }
 
 //-----------------------------------------------------------------------------
-
-void ApplicationsPage::load_categories()
-{
-	std::vector<SectionButton*> category_buttons;
-
-	// Add buttons for categories
-	for (std::vector<Category*>::const_iterator i = m_categories.begin(), end = m_categories.end(); i != end; ++i)
-	{
-		SectionButton* category_button = (*i)->get_button();
-		g_signal_connect(category_button->get_button(), "toggled", G_CALLBACK(ApplicationsPage::apply_filter_slot), this);
-		category_buttons.push_back(category_button);
-	}
-
-	// Add category buttons to window
-	get_window()->set_categories(category_buttons);
-}
-
-//-----------------------------------------------------------------------------
diff --git a/panel-plugin/applications-page.h b/panel-plugin/applications-page.h
index 5559508..7bcb0cb 100644
--- a/panel-plugin/applications-page.h
+++ b/panel-plugin/applications-page.h
@@ -47,22 +47,24 @@ public:
 	Launcher* get_application(const std::string& desktop_id) const;
 
 	void invalidate_applications();
-	void load_applications();
+	bool load_applications();
 	void reload_category_icon_size();
 
 private:
 	void apply_filter(GtkToggleButton* togglebutton);
 	bool on_filter(GtkTreeModel* model, GtkTreeIter* iter);
 	void clear_applications();
+	void load_garcon_menu();
+	bool load_contents();
 	void load_menu(GarconMenu* menu, Category* parent_category);
 	void load_menu_item(GarconMenuItem* menu_item, Category* category);
-	void load_categories();
 
 private:
 	GarconMenu* m_garcon_menu;
 	std::vector<Category*> m_categories;
 	std::map<std::string, Launcher*> m_items;
-	bool m_loaded;
+	GThread* m_load_thread;
+	gint m_load_status;
 
 
 private:
@@ -75,6 +77,17 @@ private:
 	{
 		obj->apply_filter(togglebutton);
 	}
+
+	static gpointer load_garcon_menu_slot(ApplicationsPage *obj)
+	{
+		obj->load_garcon_menu();
+		return NULL;
+	}
+
+	static gboolean load_contents_slot(ApplicationsPage* obj)
+	{
+		return obj->load_contents();
+	}
 };
 
 }
diff --git a/panel-plugin/window.cpp b/panel-plugin/window.cpp
index 01e5011..520166c 100644
--- a/panel-plugin/window.cpp
+++ b/panel-plugin/window.cpp
@@ -71,10 +71,25 @@ Window::Window() :
 	g_signal_connect(m_window, "map-event", G_CALLBACK(Window::on_map_event_slot), this);
 	g_signal_connect(m_window, "configure-event", G_CALLBACK(Window::on_configure_event_slot), this);
 
+	m_window_box = GTK_BOX(gtk_vbox_new(false, 0));
+	gtk_container_add(GTK_CONTAINER(m_window), GTK_WIDGET(m_window_box));
+
+	// Create loading message
+	m_window_load_contents = gtk_frame_new(NULL);
+	gtk_frame_set_shadow_type(GTK_FRAME(m_window_load_contents), GTK_SHADOW_OUT);
+	gtk_box_pack_start(m_window_box, m_window_load_contents, true, true, 0);
+
+	m_window_load_spinner = GTK_SPINNER(gtk_spinner_new());
+
+	GtkAlignment* alignment = GTK_ALIGNMENT(gtk_alignment_new(0.5, 0.5, 0.1, 0.1));
+	gtk_container_add(GTK_CONTAINER(alignment), GTK_WIDGET(m_window_load_spinner));
+
+	gtk_container_add(GTK_CONTAINER(m_window_load_contents), GTK_WIDGET(alignment));
+
 	// Create the border of the window
-	GtkWidget* frame = gtk_frame_new(NULL);
-	gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_OUT);
-	gtk_container_add(GTK_CONTAINER(m_window), frame);
+	m_window_contents = gtk_frame_new(NULL);
+	gtk_frame_set_shadow_type(GTK_FRAME(m_window_contents), GTK_SHADOW_OUT);
+	gtk_box_pack_start(m_window_box, m_window_contents, true, true, 0);
 
 	// Create the username label
 	const gchar* name = g_get_real_name();
@@ -142,7 +157,7 @@ Window::Window() :
 
 	// Create box for packing children
 	m_vbox = GTK_BOX(gtk_vbox_new(false, 6));
-	gtk_container_add(GTK_CONTAINER(frame), GTK_WIDGET(m_vbox));
+	gtk_container_add(GTK_CONTAINER(m_window_contents), GTK_WIDGET(m_vbox));
 	gtk_container_set_border_width(GTK_CONTAINER(m_vbox), 2);
 
 	// Create box for packing commands
@@ -198,17 +213,14 @@ Window::Window() :
 	gtk_size_group_add_widget(sidebar_size_group, GTK_WIDGET(m_sidebar));
 	gtk_size_group_add_widget(sidebar_size_group, GTK_WIDGET(m_commands_align));
 
-	// Populate app menu
-	m_applications->load_applications();
-
 	// Show widgets
-	gtk_widget_show_all(GTK_WIDGET(m_vbox));
+	gtk_widget_show_all(GTK_WIDGET(m_window_box));
 	gtk_widget_hide(m_favorites->get_widget());
 	gtk_widget_hide(m_recent->get_widget());
 	gtk_widget_hide(m_applications->get_widget());
 	gtk_widget_hide(m_search_results->get_widget());
 	m_default_button->set_active(true);
-	gtk_widget_show(frame);
+	gtk_widget_hide(m_window_contents);
 
 	// Resize to last known size
 	gtk_window_set_default_size(m_window, m_geometry.width, m_geometry.height);
@@ -269,7 +281,12 @@ void Window::show(GtkWidget* parent, bool horizontal)
 	m_logout_button->check();
 
 	// Make sure applications list is current; does nothing unless list has changed
-	m_applications->load_applications();
+	if (m_applications->load_applications())
+	{
+		gtk_widget_hide(m_window_contents);
+		gtk_widget_show(m_window_load_contents);
+		gtk_spinner_start(m_window_load_spinner);
+	}
 
 	// Reset mouse cursor by forcing default page to hide
 	gtk_widget_show(m_default_page->get_widget());
@@ -572,6 +589,16 @@ void Window::set_items()
 
 //-----------------------------------------------------------------------------
 
+void Window::set_loaded()
+{
+	gtk_spinner_stop(m_window_load_spinner);
+	gtk_widget_hide(m_window_load_contents);
+	gtk_widget_show(m_window_contents);
+	gtk_widget_grab_focus(GTK_WIDGET(m_search_entry));
+}
+
+//-----------------------------------------------------------------------------
+
 void Window::set_modified()
 {
 	m_modified = true;
diff --git a/panel-plugin/window.h b/panel-plugin/window.h
index 45be561..da3200e 100644
--- a/panel-plugin/window.h
+++ b/panel-plugin/window.h
@@ -81,6 +81,7 @@ public:
 	void save();
 	void set_categories(const std::vector<SectionButton*>& categories);
 	void set_items();
+	void set_loaded();
 	void set_modified();
 	void unset_items();
 
@@ -103,6 +104,11 @@ private:
 private:
 	GtkWindow* m_window;
 
+	GtkBox* m_window_box;
+	GtkWidget* m_window_contents;
+	GtkSpinner* m_window_load_spinner;
+	GtkWidget* m_window_load_contents;
+
 	GtkBox* m_vbox;
 	GtkBox* m_title_box;
 	GtkBox* m_commands_box;

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


More information about the Xfce4-commits mailing list