Non-modal AboutDialog

The AboutDialog offers a simple way to display information about a program, like its logo, name, copyright, website and license.

Most dialogs in this chapter are modal, that is, they freeze the rest of the application while they are shown. It's also possible to create a non-modal dialog, which does not freeze other windows in the application. The following example shows a non-modal AboutDialog. This is perhaps not the kind of dialog you would normally make non-modal, but non-modal dialogs can be useful in other cases. E.g. gedit's search-and-replace dialog is non-modal.

Reference

Example

Figure 16.5. AboutDialog

AboutDialog

Source Code

File: examplewindow.h (For use with gtkmm 3, not gtkmm 2)

#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H

#include <gtkmm.h>

class ExampleWindow : public Gtk::Window
{
public:
  ExampleWindow();
  virtual ~ExampleWindow();

protected:
  //Signal handlers:
  void on_button_clicked();
  void on_about_dialog_response(int response_id);

  //Child widgets:
  Gtk::Box m_VBox;
  Gtk::Label m_Label;
  Gtk::ButtonBox m_ButtonBox;
  Gtk::Button m_Button;
  Gtk::AboutDialog m_Dialog;
};

#endif //GTKMM_EXAMPLEWINDOW_H

File: main.cc (For use with gtkmm 3, not gtkmm 2)

#include "examplewindow.h"
#include <gtkmm/application.h>

int main(int argc, char *argv[])
{
  auto app = Gtk::Application::create(argc, argv, "org.gtkmm.example");

  ExampleWindow window;

  //Shows the window and returns when it is closed.
  return app->run(window);
}

File: examplewindow.cc (For use with gtkmm 3, not gtkmm 2)

#include "examplewindow.h"
#include <iostream>

ExampleWindow::ExampleWindow()
: m_VBox(Gtk::ORIENTATION_VERTICAL),
  m_Label("The AboutDialog is non-modal. "
    "You can select parts of this text while the AboutDialog is shown."),
  m_ButtonBox(Gtk::ORIENTATION_VERTICAL),
  m_Button("Show AboutDialog")
{
  set_title("Gtk::AboutDialog example");

  add(m_VBox);

  m_VBox.pack_start(m_Label);
  m_Label.set_line_wrap(true);
  m_Label.set_selectable(true);

  m_VBox.pack_start(m_ButtonBox);
  m_ButtonBox.pack_start(m_Button);
  m_Button.signal_clicked().connect(sigc::mem_fun(*this,
              &ExampleWindow::on_button_clicked) );

  m_Dialog.set_transient_for(*this);

  m_Dialog.set_logo(Gdk::Pixbuf::create_from_resource("/about/gtkmm_logo.gif", -1, 40, true));
  m_Dialog.set_program_name("Example application");
  m_Dialog.set_version("1.0.0");
  m_Dialog.set_copyright("Murray Cumming");
  m_Dialog.set_comments("This is just an example application.");
  m_Dialog.set_license("LGPL");

  m_Dialog.set_website("http://www.gtkmm.org");
  m_Dialog.set_website_label("gtkmm website");

  std::vector<Glib::ustring> list_authors;
  list_authors.push_back("Murray Cumming");
  list_authors.push_back("Somebody Else");
  list_authors.push_back("AN Other");
  m_Dialog.set_authors(list_authors);

  m_Dialog.signal_response().connect(
    sigc::mem_fun(*this, &ExampleWindow::on_about_dialog_response) );

  show_all_children();

  // The widget must be realized and mapped before grab_focus() is called.
  // That's why it's called after show_all_children().
  m_Button.grab_focus();
}

ExampleWindow::~ExampleWindow()
{

}

void ExampleWindow::on_about_dialog_response(int response_id)
{
  std::cout << response_id
    << ", close=" << Gtk::RESPONSE_CLOSE
    << ", cancel=" << Gtk::RESPONSE_CANCEL
    << ", delete_event=" << Gtk::RESPONSE_DELETE_EVENT
    << std::endl;

  switch (response_id)
  {
  case Gtk::RESPONSE_CLOSE:
  case Gtk::RESPONSE_CANCEL:
  case Gtk::RESPONSE_DELETE_EVENT:
    m_Dialog.hide();
    break;
  default:
    std::cout << "Unexpected response!" << std::endl;
    break;
  }
}

void ExampleWindow::on_button_clicked()
{
  m_Dialog.show();

  //Bring it to the front, in case it was already shown:
  m_Dialog.present();
}

File: aboutdialog.gresource.xml (For use with gtkmm 3, not gtkmm 2)

<?xml version="1.0" encoding="UTF-8"?>
<gresources>
  <gresource prefix="/about">
    <file>gtkmm_logo.gif</file>
  </gresource>
</gresources>