A trivial application

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.

Gio::Application Reference

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:

Figure 31-1A trivial application

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.

Source Code

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: 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: 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: 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