Table of Contents
This chapter is similar to the "Building applications" chapter in the GTK+ 3 Reference Manual. The same application is built, but gtkmm is used instead of GTK+.
An application consists of a number of files:
This gets installed in /usr/bin
.
The desktop file provides important information about the application
to the desktop shell, such as its name, icon, D-Bus name, commandline to launch it,
etc. It is installed in /usr/share/applications
.
The icon gets installed in /usr/share/icons/hicolor/48x48/apps
,
where it will be found regardless of the current theme.
If the application uses Gio::Settings
,
it will install its schema in /usr/share/glib-2.0/schemas
,
so that tools like dconf-editor can find it.
Other files, such as Gtk::Builder
ui files,
are best loaded from resources stored in the application binary itself. This
eliminates the need for most of the files that would traditionally be installed
in an application-specific location in /usr/share
.
gtkmm includes application support that is built on top of Gio::Application
.
In this chapter we'll build a simple application by starting from scratch, adding more
and more pieces over time. Along the way, we'll learn about Gtk::Application
,
Gtk::Builder
, resources, application menus, settings,
Gtk::HeaderBar
, Gtk::Stack
,
Gtk::SearchBar
, Gtk::ListBox
, and more.
The full, buildable sources for these examples can be found in the
examples/book/buildapp
directory of the
gtkmm-documentation source distribution, or online in the
gtkmm-documentation
git repository. You can build each example separately by using make with the
Makefile.example
file. For more information, see the
README
included in the buildapp
directory.
When using Gtk::Application
, the main()
function
can be very simple. We just call Gio::Application::run()
on an
instance of our application class.
All the application logic is in the application class, which is a subclass of
Gtk::Application
. Our example does not yet have any interesting
functionality. All it does is open a window when it is activated without arguments,
and open the files it is given, if it is started with arguments. (Or rather, our
application class tries to open the files, but our subclassed application window
does not yet do what it's told to do.)
To handle these two cases, we override signal_activate()
's
default handler, which gets called when the application is launched without commandline
arguments, and signal_open()
's default handler, which gets
called when the application is launched with commandline arguments.
Another important class that is part of the application support in gtkmm is
Gtk::ApplicationWindow
. It is typically subclassed as well.
Our subclass does not do anything yet, so we will just get an empty window.
As part of the initial setup of our application, we also create an icon and a desktop file. Note that @bindir@ in the desktop file needs to be replaced with the actual path to the binary before this desktop file can be used.
Here is what we've achieved so far:
This does not look very impressive yet, but our application is already presenting itself on the session bus, it has single-instance semantics, and it accepts files as commandline arguments.
File: exampleappwindow.h
(For use with gtkmm 3, not gtkmm 2)
#ifndef GTKMM_EXAMPLEAPPWINDOW_H_ #define GTKMM_EXAMPLEAPPWINDOW_H_ #include <gtkmm.h> class ExampleAppWindow : public Gtk::ApplicationWindow { public: ExampleAppWindow(); void open_file_view(const Glib::RefPtr<Gio::File>& file); }; #endif /* GTKMM_EXAMPLEAPPWINDOW_H */
File: exampleapplication.h
(For use with gtkmm 3, not gtkmm 2)
#ifndef GTKMM_EXAMPLEAPPLICATION_H #define GTKMM_EXAMPLEAPPLICATION_H #include <gtkmm.h> class ExampleAppWindow; class ExampleApplication: public Gtk::Application { protected: ExampleApplication(); public: static Glib::RefPtr<ExampleApplication> create(); protected: // Override default signal handlers: void on_activate() override; void on_open(const Gio::Application::type_vec_files& files, const Glib::ustring& hint) override; private: ExampleAppWindow* create_appwindow(); void on_hide_window(Gtk::Window* window); }; #endif /* GTKMM_EXAMPLEAPPLICATION_H */
File: exampleapplication.cc
(For use with gtkmm 3, not gtkmm 2)
#include "exampleapplication.h" #include "exampleappwindow.h" ExampleApplication::ExampleApplication() : Gtk::Application("org.gtkmm.examples.application", Gio::APPLICATION_HANDLES_OPEN) { } Glib::RefPtr<ExampleApplication> ExampleApplication::create() { return Glib::RefPtr<ExampleApplication>(new ExampleApplication()); } ExampleAppWindow* ExampleApplication::create_appwindow() { auto appwindow = new ExampleAppWindow(); // Make sure that the application runs for as long this window is still open. add_window(*appwindow); // Gtk::Application::add_window() connects a signal handler to the window's // signal_hide(). That handler removes the window from the application. // If it's the last window to be removed, the application stops running. // Gtk::Window::set_application() does not connect a signal handler, but is // otherwise equivalent to Gtk::Application::add_window(). // Delete the window when it is hidden. appwindow->signal_hide().connect(sigc::bind<Gtk::Window*>(sigc::mem_fun(*this, &ExampleApplication::on_hide_window), appwindow)); return appwindow; } void ExampleApplication::on_activate() { // The application has been started, so let's show a window. auto appwindow = create_appwindow(); appwindow->present(); } void ExampleApplication::on_open(const Gio::Application::type_vec_files& files, const Glib::ustring& /* hint */) { // The application has been asked to open some files, // so let's open a new view for each one. ExampleAppWindow* appwindow = nullptr; auto windows = get_windows(); if (windows.size() > 0) appwindow = dynamic_cast<ExampleAppWindow*>(windows[0]); if (!appwindow) appwindow = create_appwindow(); for (const auto& file : files) appwindow->open_file_view(file); appwindow->present(); } void ExampleApplication::on_hide_window(Gtk::Window* window) { delete window; }
File: main.cc
(For use with gtkmm 3, not gtkmm 2)
#include "exampleapplication.h" int main(int argc, char* argv[]) { auto application = ExampleApplication::create(); // Start the application, showing the initial window, // and opening extra views for any files that it is asked to open, // for instance as a command-line parameter. // run() will return when the last window has been closed. return application->run(argc, argv); }
File: exampleappwindow.cc
(For use with gtkmm 3, not gtkmm 2)
#include "exampleappwindow.h" ExampleAppWindow::ExampleAppWindow() : Gtk::ApplicationWindow() { } void ExampleAppWindow::open_file_view(const Glib::RefPtr<Gio::File>& /* file */) { }
File: exampleapp.desktop
(For use with gtkmm 3, not gtkmm 2)
[Desktop Entry] Type=Application Name=Gtkmm example GenericName=Example Comment=From the "Programming with gtkmm 3" tutorial Icon=exampleapp StartupNotify=true Exec=@bindir@/exampleapp %U Categories=GNOME;GTK;Utility