Sophie

Sophie

distrib > Mageia > 7 > i586 > by-pkgid > e40b0b2b839eccdb3c85993a7b738115 > files > 149

gtkmm-documentation-3.24.0-1.mga7.noarch.rpm

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>An application menu</title>
<link rel="stylesheet" type="text/css" href="style.css">
<meta name="generator" content="DocBook XSL Stylesheets V1.79.1">
<link rel="home" href="index.html" title="Programming with gtkmm 3">
<link rel="up" href="chapter-building-applications.html" title="Chapter 31. Building applications">
<link rel="prev" href="sec-buildapp-opening-files.html" title="Opening files">
<link rel="next" href="sec-buildapp-pref-dialog.html" title="A preference dialog">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr><th colspan="3" align="center">An application menu</th></tr>
<tr>
<td width="20%" align="left">
<a accesskey="p" href="sec-buildapp-opening-files.html"><img src="icons/prev.png" alt="Prev"></a> </td>
<th width="60%" align="center">Chapter 31. Building applications</th>
<td width="20%" align="right"> <a accesskey="n" href="sec-buildapp-pref-dialog.html"><img src="icons/next.png" alt="Next"></a>
</td>
</tr>
</table>
<hr>
</div>
<div class="sect1">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="sec-buildapp-app-menu"></a>An application menu</h2></div></div></div>
<p>
An application menu is shown by GNOME shell at the top of the screen. It is meant
to collect infrequently used actions that affect the whole application.
The application menu is shown either at the top of the screen, or at the top of
the application's window, depending on which desktop shell you use.
</p>
<p>
Just like the application window, we specify our application menu in a ui file,
and add it as a resource to our binary.
</p>
<p>
To associate the app menu with the application, we have to call
<code class="methodname">Gtk::Application::set_app_menu()</code>. Since app menus work by
activating <code class="classname">Gio::Action</code>s, we also have to add a suitable set of
actions to our application.
</p>
<p>
Both of these tasks are best done in the <code class="methodname">on_startup()</code> default
signal handler, which is guaranteed to be called once for each primary application instance.
</p>
<p>
Our preferences menu item does not do anything yet, but the Quit menu item is fully
functional. It can also be activated by the usual Ctrl-Q shortcut. The shortcut
is added with <code class="methodname">Gtk::Application::set_accel_for_action()</code>.
</p>
<p>
The application menu looks like this:
</p>
<div class="figure">
<a name="figure-buildapp-app-menu"></a><p class="title"><b>Figure 31.4. An application menu</b></p>
<div class="figure-contents"><div class="screenshot"><div><img src="figures/buildapp_app_menu.png" alt="An application menu"></div></div></div>
</div>
<br class="figure-break"><p><a class="ulink" href="http://git.gnome.org/browse/gtkmm-documentation/tree/examples/book/buildapp/step4?h=gtkmm-3-24" target="_top">Source Code</a></p>
<p>File: <code class="filename">exampleappwindow.h</code> (For use with gtkmm 3, not gtkmm 2)
</p>
<pre class="programlisting">
#include "../step3/exampleappwindow.h"
// Equal to the corresponding file in step3
</pre>
<p>File: <code class="filename">exampleapplication.h</code> (For use with gtkmm 3, not gtkmm 2)
</p>
<pre class="programlisting">
#ifndef GTKMM_EXAMPLEAPPLICATION_H
#define GTKMM_EXAMPLEAPPLICATION_H

#include &lt;gtkmm.h&gt;

class ExampleAppWindow;

class ExampleApplication: public Gtk::Application
{
protected:
  ExampleApplication();

public:
  static Glib::RefPtr&lt;ExampleApplication&gt; create();

protected:
  // Override default signal handlers:
  void on_startup() override;
  void on_activate() override;
  void on_open(const Gio::Application::type_vec_files&amp; files,
    const Glib::ustring&amp; hint) override;

private:
  ExampleAppWindow* create_appwindow();
  void on_hide_window(Gtk::Window* window);
  void on_action_preferences();
  void on_action_quit();
};

#endif /* GTKMM_EXAMPLEAPPLICATION_H */
</pre>
<p>File: <code class="filename">exampleapplication.cc</code> (For use with gtkmm 3, not gtkmm 2)
</p>
<pre class="programlisting">
#include "exampleapplication.h"
#include "exampleappwindow.h"
#include &lt;iostream&gt;
#include &lt;exception&gt;

ExampleApplication::ExampleApplication()
: Gtk::Application("org.gtkmm.examples.application", Gio::APPLICATION_HANDLES_OPEN)
{
}

Glib::RefPtr&lt;ExampleApplication&gt; ExampleApplication::create()
{
  return Glib::RefPtr&lt;ExampleApplication&gt;(new ExampleApplication());
}

ExampleAppWindow* ExampleApplication::create_appwindow()
{
  auto appwindow = ExampleAppWindow::create();

  // 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-&gt;signal_hide().connect(sigc::bind&lt;Gtk::Window*&gt;(sigc::mem_fun(*this,
    &amp;ExampleApplication::on_hide_window), appwindow));

  return appwindow;
}

void ExampleApplication::on_startup()
{
  // Call the base class's implementation.
  Gtk::Application::on_startup();

  // Add actions and keyboard accelerators for the application menu.
  add_action("preferences", sigc::mem_fun(*this, &amp;ExampleApplication::on_action_preferences));
  add_action("quit", sigc::mem_fun(*this, &amp;ExampleApplication::on_action_quit));
  set_accel_for_action("app.quit", "&lt;Ctrl&gt;Q");

  auto refBuilder = Gtk::Builder::create();
  try
  {
    refBuilder-&gt;add_from_resource("/org/gtkmm/exampleapp/app_menu.ui");
  }
  catch (const Glib::Error&amp; ex)
  {
    std::cerr &lt;&lt; "ExampleApplication::on_startup(): " &lt;&lt; ex.what() &lt;&lt; std::endl;
    return;
  }

  auto object = refBuilder-&gt;get_object("appmenu");
  auto app_menu = Glib::RefPtr&lt;Gio::MenuModel&gt;::cast_dynamic(object);
  if (app_menu)
    set_app_menu(app_menu);
  else
    std::cerr &lt;&lt; "ExampleApplication::on_startup(): No \"appmenu\" object in app_menu.ui"
              &lt;&lt; std::endl;
}

void ExampleApplication::on_activate()
{
  try
  {
    // The application has been started, so let's show a window.
    auto appwindow = create_appwindow();
    appwindow-&gt;present();
  }
  // If create_appwindow() throws an exception (perhaps from Gtk::Builder),
  // no window has been created, no window has been added to the application,
  // and therefore the application will stop running.
  catch (const Glib::Error&amp; ex)
  {
    std::cerr &lt;&lt; "ExampleApplication::on_activate(): " &lt;&lt; ex.what() &lt;&lt; std::endl;
  }
  catch (const std::exception&amp; ex)
  {
    std::cerr &lt;&lt; "ExampleApplication::on_activate(): " &lt;&lt; ex.what() &lt;&lt; std::endl;
  }
}

void ExampleApplication::on_open(const Gio::Application::type_vec_files&amp; files,
  const Glib::ustring&amp; /* 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() &gt; 0)
    appwindow = dynamic_cast&lt;ExampleAppWindow*&gt;(windows[0]);

  try
  {
    if (!appwindow)
      appwindow = create_appwindow();

    for (const auto&amp; file : files)
      appwindow-&gt;open_file_view(file);

    appwindow-&gt;present();
  }
  catch (const Glib::Error&amp; ex)
  {
    std::cerr &lt;&lt; "ExampleApplication::on_open(): " &lt;&lt; ex.what() &lt;&lt; std::endl;
  }
  catch (const std::exception&amp; ex)
  {
    std::cerr &lt;&lt; "ExampleApplication::on_open(): " &lt;&lt; ex.what() &lt;&lt; std::endl;
  }
}

void ExampleApplication::on_hide_window(Gtk::Window* window)
{
  delete window;
}

void ExampleApplication::on_action_preferences()
{

}

void ExampleApplication::on_action_quit()
{
  // Gio::Application::quit() will make Gio::Application::run() return,
  // but it's a crude way of ending the program. The window is not removed
  // from the application. Neither the window's nor the application's
  // destructors will be called, because there will be remaining reference
  // counts in both of them. If we want the destructors to be called, we
  // must remove the window from the application. One way of doing this
  // is to hide the window. See comment in create_appwindow().
  auto windows = get_windows();
  for (auto window : windows)
    window-&gt;hide();

  // Not really necessary, when Gtk::Widget::hide() is called, unless
  // Gio::Application::hold() has been called without a corresponding call
  // to Gio::Application::release().
  quit();
}
</pre>
<p>File: <code class="filename">main.cc</code> (For use with gtkmm 3, not gtkmm 2)
</p>
<pre class="programlisting">
#include "../step1/main.cc"
// Equal to the corresponding file in step1
</pre>
<p>File: <code class="filename">exampleappwindow.cc</code> (For use with gtkmm 3, not gtkmm 2)
</p>
<pre class="programlisting">
#include "../step3/exampleappwindow.cc"
// Equal to the corresponding file in step3
</pre>
<p>File: <code class="filename">exampleapp.gresource.xml</code> (For use with gtkmm 3, not gtkmm 2)
</p>
<pre class="programlisting">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;gresources&gt;
  &lt;gresource prefix="/org/gtkmm/exampleapp"&gt;
    &lt;file preprocess="xml-stripblanks"&gt;window.ui&lt;/file&gt;
    &lt;file preprocess="xml-stripblanks"&gt;app_menu.ui&lt;/file&gt;
  &lt;/gresource&gt;
&lt;/gresources&gt;
</pre>
<p>File: <code class="filename">app_menu.ui</code> (For use with gtkmm 3, not gtkmm 2)
</p>
<pre class="programlisting">
&lt;?xml version="1.0"?&gt;
&lt;interface&gt;
  &lt;!-- interface-requires gtk+ 3.0 --&gt;
  &lt;menu id="appmenu"&gt;
    &lt;section&gt;
      &lt;item&gt;
        &lt;attribute name="label" translatable="yes"&gt;_Preferences&lt;/attribute&gt;
        &lt;attribute name="action"&gt;app.preferences&lt;/attribute&gt;
      &lt;/item&gt;
    &lt;/section&gt;
    &lt;section&gt;
      &lt;item&gt;
        &lt;attribute name="label" translatable="yes"&gt;_Quit&lt;/attribute&gt;
        &lt;attribute name="action"&gt;app.quit&lt;/attribute&gt;
      &lt;/item&gt;
    &lt;/section&gt;
  &lt;/menu&gt;
&lt;/interface&gt;
</pre>
</div>
<div class="navfooter">
<hr>
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left">
<a accesskey="p" href="sec-buildapp-opening-files.html"><img src="icons/prev.png" alt="Prev"></a> </td>
<td width="20%" align="center"><a accesskey="u" href="chapter-building-applications.html"><img src="icons/up.png" alt="Up"></a></td>
<td width="40%" align="right"> <a accesskey="n" href="sec-buildapp-pref-dialog.html"><img src="icons/next.png" alt="Next"></a>
</td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Opening files </td>
<td width="20%" align="center"><a accesskey="h" href="index.html"><img src="icons/home.png" alt="Home"></a></td>
<td width="40%" align="right" valign="top"> A preference dialog</td>
</tr>
</table>
</div>
</body>
</html>