[gtkmm: 1/2] Demos: Add listview application launcher demo
- From: Kjell Ahlstedt <kjellahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtkmm: 1/2] Demos: Add listview application launcher demo
- Date: Sun, 6 Sep 2020 17:13:20 +0000 (UTC)
commit b021fea80d982bb1a9104c91e022286b07fdaa25
Author: Andreas Persson <andreasp56 outlook com>
Date: Sat Sep 5 19:23:05 2020 +0200
Demos: Add listview application launcher demo
demos/Makefile.am | 1 +
demos/gtk-demo/demo.gresource.xml | 1 +
demos/gtk-demo/demos.h | 7 +
demos/gtk-demo/example_listview_applauncher.cc | 186 +++++++++++++++++++++++++
demos/gtk-demo/meson.build | 1 +
5 files changed, 196 insertions(+)
---
diff --git a/demos/Makefile.am b/demos/Makefile.am
index 483bd777..23494c40 100644
--- a/demos/Makefile.am
+++ b/demos/Makefile.am
@@ -48,6 +48,7 @@ GTK_DEMOS = \
gtk-demo/example_iconbrowser.cc \
gtk-demo/example_iconview.cc \
gtk-demo/example_images.cc \
+ gtk-demo/example_listview_applauncher.cc \
gtk-demo/example_overlay.cc \
gtk-demo/example_panes.cc \
gtk-demo/example_pixbufs.cc \
diff --git a/demos/gtk-demo/demo.gresource.xml b/demos/gtk-demo/demo.gresource.xml
index a55e0be4..8d24adf1 100644
--- a/demos/gtk-demo/demo.gresource.xml
+++ b/demos/gtk-demo/demo.gresource.xml
@@ -49,6 +49,7 @@
<file>example_iconbrowser.cc</file>
<file>example_iconview.cc</file>
<file>example_images.cc</file>
+ <file>example_listview_applauncher.cc</file>
<file>example_overlay.cc</file>
<file>example_panes.cc</file>
<file>example_pixbufs.cc</file>
diff --git a/demos/gtk-demo/demos.h b/demos/gtk-demo/demos.h
index 12bab82a..1a55eacd 100644
--- a/demos/gtk-demo/demos.h
+++ b/demos/gtk-demo/demos.h
@@ -25,6 +25,7 @@ Gtk::Window* do_headerbar();
Gtk::Window* do_iconbrowser();
Gtk::Window* do_iconview();
Gtk::Window* do_images();
+Gtk::Window* do_listview_applauncher();
Gtk::Window* do_overlay();
Gtk::Window* do_panes();
Gtk::Window* do_pixbufs();
@@ -46,6 +47,11 @@ Demo child0[] =
{ nullptr, nullptr, type_slotDo(), nullptr }
};
+Demo child1[] =
+{
+ { "Application launcher", "example_listview_applauncher.cc", sigc::ptr_fun(&do_listview_applauncher),
nullptr }
+};
+
Demo testgtk_demos[] =
{
{ "Application main window", "example_appwindow.cc", sigc::ptr_fun(&do_appwindow), nullptr },
@@ -59,6 +65,7 @@ Demo testgtk_demos[] =
{ "Icon Browser", "example_iconbrowser.cc", sigc::ptr_fun(&do_iconbrowser), nullptr },
{ "Icon View", "example_iconview.cc", sigc::ptr_fun(&do_iconview), nullptr },
{ "Images", "example_images.cc", sigc::ptr_fun(&do_images), nullptr },
+ { "Lists", "", type_slotDo(), child1 },
{ "OpenGL Area", "example_glarea.cc", sigc::ptr_fun(&do_glarea), nullptr },
{ "Overlay", "example_overlay.cc", sigc::ptr_fun(&do_overlay), nullptr },
{ "Paned Widgets", "example_panes.cc", sigc::ptr_fun(&do_panes), nullptr },
diff --git a/demos/gtk-demo/example_listview_applauncher.cc b/demos/gtk-demo/example_listview_applauncher.cc
new file mode 100644
index 00000000..9a2b9bbc
--- /dev/null
+++ b/demos/gtk-demo/example_listview_applauncher.cc
@@ -0,0 +1,186 @@
+/* Lists/Application launcher
+ *
+ * This demo uses the Gtk::ListView widget as a fancy application launcher.
+ *
+ * It is also a very small introduction to listviews.
+ */
+
+#include <gtkmm.h>
+#include <giomm/appinfo.h>
+#include <giomm/liststore.h>
+
+class Example_ListView_AppLauncher : public Gtk::Window
+{
+public:
+ Example_ListView_AppLauncher();
+ ~Example_ListView_AppLauncher() override;
+
+protected:
+ Glib::RefPtr<Gio::ListModel> create_application_list();
+ void setup_listitem(const Glib::RefPtr<Gtk::ListItem>& list_item);
+ void bind_listitem(const Glib::RefPtr<Gtk::ListItem>& list_item);
+ void activate(guint position);
+
+ Gtk::ListView* m_list;
+ std::unique_ptr<Gtk::MessageDialog> m_error_dialog;
+};
+
+Gtk::Window* do_listview_applauncher()
+{
+ return new Example_ListView_AppLauncher();
+}
+
+
+/* This is the function that creates the Gio::ListModel that we need.
+ * GTK list widgets need a Gio::ListModel to display, as models support change
+ * notifications.
+ * Unfortunately various older APIs do not provide list models, so we create
+ * our own.
+ */
+Glib::RefPtr<Gio::ListModel> Example_ListView_AppLauncher::create_application_list()
+{
+ /* We use a Gio::ListStore here, which is a simple array-like list implementation
+ * for manual management.
+ * List models need to know what type of data they provide, so we need to
+ * provide the type here. As we want to do a list of applications, Gio::AppInfo
+ * is the object we provide.
+ */
+ auto store = Gio::ListStore<Gio::AppInfo>::create();
+
+ for (auto app : Gio::AppInfo::get_all())
+ store->append(app);
+
+ return store;
+}
+
+/* This is the function we use for setting up new listitems to display.
+ * We add just an Gtk::Image and a Gtk::Label here to display the application's
+ * icon and name, as this is just a simple demo.
+ */
+void Example_ListView_AppLauncher::setup_listitem(const Glib::RefPtr<Gtk::ListItem>& list_item)
+{
+ auto box = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::HORIZONTAL, 12);
+ auto image = Gtk::make_managed<Gtk::Image>();
+ image->set_icon_size(Gtk::IconSize::LARGE);
+ box->append(*image);
+ auto label = Gtk::make_managed<Gtk::Label>();
+ box->append(*label);
+ list_item->set_child(*box);
+}
+
+/* Here we need to prepare the listitem for displaying its item. We get the
+ * listitem already set up from the previous function, so we can reuse the
+ * Gtk::Image widget we set up above.
+ * We get the item - which we know is a Gio::AppInfo because it comes out of
+ * the model we set up above, grab its icon and display it.
+ */
+void Example_ListView_AppLauncher::bind_listitem(const Glib::RefPtr<Gtk::ListItem>& list_item)
+{
+ if (auto image = dynamic_cast<Gtk::Image*>(list_item->get_child()->get_first_child()))
+ if (auto label = dynamic_cast<Gtk::Label*>(image->get_next_sibling()))
+ if (auto app_info = std::dynamic_pointer_cast<Gio::AppInfo>(list_item->get_item()))
+ {
+ image->set(app_info->get_icon());
+ label->set_label(app_info->get_display_name());
+ }
+}
+
+/* In more complex code, we would also need functions to unbind and teardown
+ * the listitem, but this is simple code, so the default implementations are
+ * enough. If we had connected signals, this step would have been necessary.
+ *
+ * The Gtk::SignalListItemFactory documentation contains more information about
+ * this step.
+ */
+
+/* This function is called whenever an item in the list is activated. This is
+ * the simple way to allow reacting to the Enter key or double-clicking on a
+ * listitem.
+ * Of course, it is possible to use far more complex interactions by turning
+ * off activation and adding buttons or other widgets in the setup function
+ * above, but this is a simple demo, so we'll use the simple way.
+ */
+void Example_ListView_AppLauncher::activate(guint position)
+{
+ auto item = std::dynamic_pointer_cast<Gio::ListModel>(m_list->get_model())->get_object(position);
+ if (auto app_info = std::dynamic_pointer_cast<Gio::AppInfo>(item))
+ {
+ /* Prepare the context for launching the application and launch it. This
+ * code is explained in detail in the documentation for Gdk::AppLaunchContext
+ * and Gio::AppInfo.
+ */
+ auto context = m_list->get_display()->get_app_launch_context();
+ try
+ {
+ app_info->launch(std::vector<Glib::RefPtr<Gio::File>>(), context);
+ }
+ catch (const Glib::Error& error)
+ {
+ /* And because error handling is important, even a simple demo has it:
+ * We display an error dialog that something went wrong.
+ */
+ if (!m_error_dialog)
+ {
+ m_error_dialog.reset(new Gtk::MessageDialog(
+ *this, "", false, Gtk::MessageType::ERROR, Gtk::ButtonsType::CLOSE, true));
+ m_error_dialog->set_hide_on_close();
+ m_error_dialog->signal_response().connect(
+ sigc::hide(sigc::mem_fun(*m_error_dialog, &Gtk::Widget::hide)));
+ }
+ m_error_dialog->set_message(
+ Glib::ustring::sprintf("Could not launch %s", app_info->get_display_name()));
+ m_error_dialog->set_secondary_text(error.what());
+ m_error_dialog->show();
+ }
+ }
+}
+
+Example_ListView_AppLauncher::Example_ListView_AppLauncher()
+{
+ set_default_size(640, 320);
+ set_title("Application Launcher");
+
+ /* The Gtk::ListItemFactory is what is used to create Gtk::ListItems
+ * to display the data from the model. So it is absolutely necessary
+ * to create one.
+ * We will use a Gtk::SignalListItemFactory because it is the simplest
+ * one to use. Different ones are available for different use cases.
+ * The most powerful one is Gtk::BuilderListItemFactory which uses
+ * Gtk::Builder .ui files, so it requires little code.
+ */
+ auto factory = Gtk::SignalListItemFactory::create();
+ factory->signal_setup().connect(
+ sigc::mem_fun(*this, &Example_ListView_AppLauncher::setup_listitem));
+ factory->signal_bind().connect(
+ sigc::mem_fun(*this, &Example_ListView_AppLauncher::bind_listitem));
+
+ /* And of course we need to set the data model. Here we call the function
+ * we wrote above that gives us the list of applications. Then we set
+ * it on the list widget.
+ * The list will now take items from the model and use the factory
+ * to create as many listitems as it needs to show itself to the user.
+ */
+ auto model = create_application_list();
+
+ /* Create the list widget here.
+ */
+ m_list = Gtk::make_managed<Gtk::ListView>(Gtk::SingleSelection::create(model), factory);
+
+ /* We connect the activate signal here. It's the function we defined
+ * above for launching the selected application.
+ */
+ m_list->signal_activate().connect(
+ sigc::mem_fun(*this, &Example_ListView_AppLauncher::activate));
+
+ /* List widgets should always be contained in a Gtk::ScrolledWindow,
+ * because otherwise they might get too large or they might not
+ * be scrollable.
+ */
+ auto sw = Gtk::make_managed<Gtk::ScrolledWindow>();
+ set_child(*sw);
+ sw->set_child(*m_list);
+}
+
+Example_ListView_AppLauncher::~Example_ListView_AppLauncher()
+{
+}
diff --git a/demos/gtk-demo/meson.build b/demos/gtk-demo/meson.build
index 6e60c2b3..4a5093b1 100644
--- a/demos/gtk-demo/meson.build
+++ b/demos/gtk-demo/meson.build
@@ -19,6 +19,7 @@ gtkmm_demo_cc_files = [
'example_iconbrowser.cc',
'example_iconview.cc',
'example_images.cc',
+ 'example_listview_applauncher.cc',
'example_overlay.cc',
'example_panes.cc',
'example_pixbufs.cc',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]