I'm following your second proposal and attached the source files, hoping
you can make a patch out of them. You can also see the files in
http://jkleber.homepage.t-online.de/c
++/menu_appwin_builder_app/index.html .

Jürgen

Am Mittwoch, den 19.11.2014, 16:35 +0100 schrieb Kjell Ahlstedt:
> If you file a bug in Bugzilla and attach a patch, I can push it to the
> git repository.
> If you haven't installed git, and don't want to do it, you can attach
> the new and the modified files. I can make a patch out of them.
> Third alternative: File a bug without attachments, and hope for the
> best. Someone will probably fix it some day, but it will be fixed
> quicker if you do most of the job yourself.
> 
> Kjell
> 
> Den 2014-11-13 18:48, Jürgen Kleber skrev:
> 
> > Hi,
> > 
> > quite a lot of Gnome applications have an application menu allowing for
> > menu items covering the application as a whole to place into the top bar
> > of Gnome-shell. I should appreciate this feature being reflected in the
> > menu-example of the gtkmm-tutorial. This could easily be done by
> > deriving ExampleWindow from Gtk::ApplicationWindow instead from
> > Gtk::Window and adding a new class ExampleApplication derived from
> > Gtk::Application using this example
> > https://git.gnome.org/browse/gtkmm-documentation/tree/examples/book/application/app_and_win_menus
> > as a guideline.
> > 
> > Best regards,
> > Jürgen
> > 
> > 
> 

/*
 * Enhancing the main menu example of gtkmm-tutorial/unstable presented in
 * https://developer.gnome.org/gtkmm-tutorial/unstable/\
 *       sec-menus-examples.html.de#menu-example-main
 * to show an application menu as suggested in
 * https://wiki.gnome.org/ThreePointThree/Features/ApplicationMenu,
 * described in
 * https://wiki.gnome.org/HowDoI/ApplicationMenu
 * and realised using gtkmm in
 * https://git.gnome.org/browse/gtkmm-documentation/tree/examples/book/\
 *       application/app_and_win_menus
 *
 * Started on 2014-11-10
 * Current version: 2014-11-10
 * Performed by: Jürgen Kleber (jkleber2...@t-online.de)
 *
 * Original file downloaded on Sunday, 9th of November, 2014 from
 * https://git.gnome.org/browse/gtkmm-documentation/tree/examples/book/\
 *       application/app_and_win_menus/exampleapplication.cc
 */

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

ExampleApplication::ExampleApplication() :
      Gtk::Application("org.gtkmm.examples.application") {
   Glib::set_application_name("Gtk::Application Example");
   win = 0;
}

Glib::RefPtr<ExampleApplication> ExampleApplication::create() {
   return Glib::RefPtr<ExampleApplication>(new ExampleApplication());
}

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

   //File|New sub menu:
   newstandard_action = add_action("newstandard",
         sigc::mem_fun(*this, &ExampleApplication::on_menu_file_new_generic));

   newfoo_action = add_action("newfoo",
         sigc::mem_fun(*this, &ExampleApplication::on_menu_file_new_generic));

   newgoo_action = add_action("newgoo",
         sigc::mem_fun(*this, &ExampleApplication::on_menu_file_new_generic));

   //File menu:
   quit_action = add_action("quit",
         sigc::mem_fun(*this, &ExampleApplication::on_menu_file_quit));

   //Help menu:
   about_action = add_action("about",
         sigc::mem_fun(*this, &ExampleApplication::on_menu_others));

   m_refBuilder = Gtk::Builder::create();

   //Layout the actions in a menubar and toolbar:
   Glib::ustring ui_info =
      "<interface>"
      "  <menu id='menu-example'>"
      "    <submenu>"
      "      <attribute name='label' translatable='yes'>_File</attribute>"
      "      <section>"
      "        <item>"
      "          <attribute name='label' translatable='yes'>New _Standard</attribute>"
      "          <attribute name='action'>app.newstandard</attribute>"
      "          <attribute name='accel'>&lt;Primary&gt;n</attribute>"
      "        </item>"
      "        <item>"
      "          <attribute name='label' translatable='yes'>New _Foo</attribute>"
      "          <attribute name='action'>app.newfoo</attribute>"
      "        </item>"
      "        <item>"
      "          <attribute name='label' translatable='yes'>New _Goo</attribute>"
      "          <attribute name='action'>app.newgoo</attribute>"
      "        </item>"
      "      </section>"
      "      <section>"
      "        <item>"
      "          <attribute name='label' translatable='yes'>_Quit</attribute>"
      "          <attribute name='action'>app.quit</attribute>"
      "          <attribute name='accel'>&lt;Primary&gt;q</attribute>"
      "        </item>"
      "      </section>"
      "    </submenu>"
      "    <submenu>"
      "      <attribute name='label' translatable='yes'>_Edit</attribute>"
      "      <section>"
      "        <item>"
      "          <attribute name='label' translatable='yes'>_Copy</attribute>"
      "          <attribute name='action'>win.copy</attribute>"
      "          <attribute name='accel'>&lt;Primary&gt;c</attribute>"
      "        </item>"
      "        <item>"
      "          <attribute name='label' translatable='yes'>_Paste</attribute>"
      "          <attribute name='action'>win.paste</attribute>"
      "          <attribute name='accel'>&lt;Primary&gt;v</attribute>"
      "        </item>"
      "        <item>"
      "          <attribute name='label' translatable='yes'>_Something</attribute>"
      "          <attribute name='action'>win.something</attribute>"
      "        </item>"
      "      </section>"
      "    </submenu>"
      "    <submenu>"
      "      <attribute name='label' translatable='yes'>_Choices</attribute>"
      "      <section>"
      "        <item>"
      "          <attribute name='label' translatable='yes'>Choice _A</attribute>"
      "          <attribute name='action'>win.choice</attribute>"
      "          <attribute name='target'>a</attribute>"
      "        </item>"
      "        <item>"
      "          <attribute name='label' translatable='yes'>Choice _B</attribute>"
      "          <attribute name='action'>win.choice</attribute>"
      "          <attribute name='target'>b</attribute>"
      "        </item>"
      "      </section>"
      "    </submenu>"
      "    <submenu>"
      "      <attribute name='label' translatable='yes'>_Other Choices</attribute>"
      "      <section>"
      "        <item>"
      "          <attribute name='label' translatable='yes'>Choice 1</attribute>"
      "          <attribute name='action'>win.choiceother</attribute>"
      "          <attribute name='target' type='i'>1</attribute>"
      "        </item>"
      "        <item>"
      "          <attribute name='label' translatable='yes'>Choice 2</attribute>"
      "          <attribute name='action'>win.choiceother</attribute>"
      "          <attribute name='target' type='i'>2</attribute>"
      "        </item>"
      "      </section>"
      "      <section>"
      "        <item>"
      "          <attribute name='label' translatable='yes'>Some Toggle</attribute>"
      "          <attribute name='action'>win.sometoggle</attribute>"
      "        </item>"
      "      </section>"
      "    </submenu>"
      "    <submenu>"
      "      <attribute name='label' translatable='yes'>_Help</attribute>"
      "      <section>"
      "        <item>"
      "          <attribute name='label' translatable='yes'>_About</attribute>"
      "          <attribute name='action'>app.about</attribute>"
      "        </item>"
      "      </section>"
      "    </submenu>"
      "  </menu>"
      "  <menu id='appmenu'>"
      "    <submenu>"
      "      <attribute name='label' translatable='yes'>_File</attribute>"
      "      <section>"
      "        <item>"
      "          <attribute name='label' translatable='yes'>New _Standard</attribute>"
      "          <attribute name='action'>app.newstandard</attribute>"
      "          <attribute name='accel'>&lt;Primary&gt;n</attribute>"
      "        </item>"
      "        <item>"
      "          <attribute name='label' translatable='yes'>New _Foo</attribute>"
      "          <attribute name='action'>app.newfoo</attribute>"
      "        </item>"
      "        <item>"
      "          <attribute name='label' translatable='yes'>New _Goo</attribute>"
      "          <attribute name='action'>app.newgoo</attribute>"
      "        </item>"
      "      </section>"
      "      <section>"
      "        <item>"
      "          <attribute name='label' translatable='yes'>_Quit</attribute>"
      "          <attribute name='action'>app.quit</attribute>"
      "          <attribute name='accel'>&lt;Primary&gt;q</attribute>"
      "        </item>"
      "      </section>"
      "    </submenu>"
      "    <submenu>"
      "      <attribute name='label' translatable='yes'>_Help</attribute>"
      "      <section>"
      "        <item>"
      "          <attribute name='label' translatable='yes'>_About</attribute>"
      "          <attribute name='action'>app.about</attribute>"
      "        </item>"
      "      </section>"
      "    </submenu>"
      "  </menu>"
      "</interface>";

   try {
      m_refBuilder->add_from_string(ui_info);
   } catch (const Glib::Error& ex) {
      std::cerr << "building menus failed: " << ex.what();
   }

   //Get the menubar and add it to a container widget:
   Glib::RefPtr<Glib::Object> object = m_refBuilder->get_object("menu-example");
   Glib::RefPtr<Gio::Menu> gmenu = Glib::RefPtr<Gio::Menu>::cast_dynamic(
         object);
   object = m_refBuilder->get_object("appmenu");
   Glib::RefPtr<Gio::Menu> appMenu = Glib::RefPtr<Gio::Menu>::cast_dynamic(
         object);
   if (!(gmenu && appMenu)) {
      g_warning("GMenu or AppMenu not found");
   } else {
      set_app_menu(appMenu);
      set_menubar(gmenu);
   }
}

void ExampleApplication::create_window() {
   win = new ExampleWindow();

   //Make sure that the application runs for as long this window is still open:
   add_window(*win);

   //Delete the window when it is hidden.
   //That's enough for this simple example.
   win->signal_hide().connect(
         sigc::bind<Gtk::Window*>(
               sigc::mem_fun(*this, &ExampleApplication::on_window_hide), win));

   win->show_all();
}

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

void ExampleApplication::on_activate() {
   //std::cout << "debug1: " << G_STRFUNC << std::endl;
   // The application has been started, so let's show a window.
   // A real application might want to reuse this "empty" window in on_open(),
   // when asked to open a file, if no changes have been made yet.
   create_window();
}

void ExampleApplication::on_menu_file_new_generic() {
   std::cout << "A File|New menu item was selected." << std::endl;
}

void ExampleApplication::on_menu_file_quit() {
   std::cout << G_STRFUNC << std::endl;
   quit(); // Not really necessary, when Gtk::Widget::hide() is called.

   // 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.
   std::vector<Gtk::Window*> windows = get_windows();
   if (windows.size() > 0)
      windows[0]->hide(); // In this simple case, we know there is only one window.
}

void ExampleApplication::on_menu_others() {
   std::cout << "A menu item was selected." << std::endl;
}

/*
 * Enhancing the main menu example of gtkmm-tutorial/unstable presented in
 * https://developer.gnome.org/gtkmm-tutorial/unstable/\
 *       sec-menus-examples.html.de#menu-example-main
 * to show an application menu as suggested in
 * https://wiki.gnome.org/ThreePointThree/Features/ApplicationMenu,
 * described in
 * https://wiki.gnome.org/HowDoI/ApplicationMenu
 * and realised using gtkmm in
 * https://git.gnome.org/browse/gtkmm-documentation/tree/examples/book/\
 *       application/app_and_win_menus
 *
 * Started on 2014-11-10
 * Current version: 2014-11-10
 * Performed by: Jürgen Kleber (jkleber2...@t-online.de)
 *
 * Original file downloaded on Sunday, 9th of November, 2014 from
 * https://git.gnome.org/browse/gtkmm-documentation/tree/examples/book/\
 *       application/app_and_win_menus/exampleapplication.h
 */

#ifndef GTKMM_EXAMPLEAPPLICATION_H
#define GTKMM_EXAMPLEAPPLICATION_H

#include <gtkmm/application.h>
#include <gtkmm/builder.h>
#include <gtkmm/window.h>

#include "examplewindow.h"

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

public:
  static Glib::RefPtr<ExampleApplication> create();

protected:
  //Overrides of default signal handlers:
  virtual void on_activate();
  virtual void on_startup();

private:
  Glib::RefPtr<Gio::SimpleAction> newstandard_action;
  Glib::RefPtr<Gio::SimpleAction> newfoo_action;
  Glib::RefPtr<Gio::SimpleAction> newgoo_action;
  Glib::RefPtr<Gio::SimpleAction> quit_action;
  Glib::RefPtr<Gio::SimpleAction> about_action;
  Glib::RefPtr<Gtk::Builder> m_refBuilder;

  ExampleWindow* win;

  void on_menu_file_new_generic();
  void on_menu_file_quit();
  void on_menu_others();
  void create_window();

  void on_window_hide(Gtk::Window* window);
};

#endif /* GTKMM_EXAMPLEAPPLICATION_H */

/*
 * Enhancing the main menu example of gtkmm-tutorial/unstable presented in
 * https://developer.gnome.org/gtkmm-tutorial/unstable/\
 *       sec-menus-examples.html.de#menu-example-main
 * to show an application menu as suggested in
 * https://wiki.gnome.org/ThreePointThree/Features/ApplicationMenu,
 * described in
 * https://wiki.gnome.org/HowDoI/ApplicationMenu
 * and realised using gtkmm in
 * https://git.gnome.org/browse/gtkmm-documentation/tree/examples/book/\
 *       application/app_and_win_menus
 *
 * Started on 2014-11-10
 * Current version: 2014-11-10
 * Performed by: Jürgen Kleber (jkleber2...@t-online.de)
 *
 * Original file downloaded on Sunday, 9th of November, 2014 from
 * https://git.gnome.org/browse/gtkmm-documentation/tree/examples/book/menus/\
 *       main_menu/examplewindow.cc
 */

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

ExampleWindow::ExampleWindow() : Gtk::ApplicationWindow(),
      m_Box(Gtk::ORIENTATION_VERTICAL) {
   set_title("main menu example");
   set_default_size(300, 100);

   add(m_Box); // put a MenuBar at the top of the box and other stuff below it.

   //Create actions for menus and toolbars:
   Glib::RefPtr<Gio::SimpleActionGroup> refActionGroup =
         Gio::SimpleActionGroup::create();
   //Edit menu:
   refActionGroup->add_action("copy",
         sigc::mem_fun(*this, &ExampleWindow::on_menu_others));
   refActionGroup->add_action("paste",
         sigc::mem_fun(*this, &ExampleWindow::on_menu_others));
   refActionGroup->add_action("something",
         sigc::mem_fun(*this, &ExampleWindow::on_menu_others));

   //Choices menus, to demonstrate Radio items,
   //using our convenience methods for string and int radio values:
   m_refChoice = refActionGroup->add_action_radio_string("choice",
         sigc::mem_fun(*this, &ExampleWindow::on_menu_choices), "a");

   m_refChoiceOther = refActionGroup->add_action_radio_integer("choiceother",
         sigc::mem_fun(*this, &ExampleWindow::on_menu_choices_other), 1);

   m_refToggle = refActionGroup->add_action_bool("sometoggle",
         sigc::mem_fun(*this, &ExampleWindow::on_menu_toggle), false);

   //Help menu:
   refActionGroup->add_action("about",
         sigc::mem_fun(*this, &ExampleWindow::on_menu_others));

   // Add a prefix to the actions declared in the .xml file
   insert_action_group("win", refActionGroup);

   //Create the toolbar and add it to a container widget:
   Gtk::Toolbar* toolbar = Gtk::manage(new Gtk::Toolbar());
   Gtk::ToolButton* button = Gtk::manage(new Gtk::ToolButton());
   button->set_icon_name("document-new");
   // We can't do this until we can break the ToolButton ABI:
   //    button->set_detailed_action_name("example.new");
   gtk_actionable_set_detailed_action_name(GTK_ACTIONABLE(button->gobj()),
         "app.newstandard");
   toolbar->add(*button);

   button = Gtk::manage(new Gtk::ToolButton());
   button->set_icon_name("application-exit");
   // We can't do this until we can break the ToolButton ABI:
   //    button->set_detailed_action_name("example.quit");
   gtk_actionable_set_detailed_action_name(GTK_ACTIONABLE(button->gobj()),
         "app.quit");
   toolbar->add(*button);

   m_Box.pack_start(*toolbar, Gtk::PACK_SHRINK);

}

ExampleWindow::~ExampleWindow() {
}

void ExampleWindow::on_menu_others() {
   std::cout << "A menu item was selected." << std::endl;
}

void ExampleWindow::on_menu_choices(const Glib::ustring& parameter) {
   //The radio action's state does not change automatically:
   m_refChoice->change_state(parameter);

   Glib::ustring message;
   if (parameter == "a")
      message = "Choice a was selected.";
   else
      message = "Choice b was selected";

   std::cout << message << std::endl;
}

void ExampleWindow::on_menu_choices_other(int parameter) {
   //The radio action's state does not change automatically:
   m_refChoiceOther->change_state(parameter);

   Glib::ustring message;
   if (parameter == 1)
      message = "Choice 1 was selected.";
   else
      message = "Choice 2 was selected";

   std::cout << message << std::endl;
}

void ExampleWindow::on_menu_toggle() {
   bool active = false;
   m_refToggle->get_state(active);

   //The toggle action's state does not change automatically:
   m_refToggle->change_state(!active);
   active = !active;

   Glib::ustring message;
   if (active)
      message = "Toggle is active.";
   else
      message = "Toggle is not active";

   std::cout << message << std::endl;
}

/*
 * Enhancing the main menu example of gtkmm-tutorial/unstable presented in
 * https://developer.gnome.org/gtkmm-tutorial/unstable/\
 *       sec-menus-examples.html.de#menu-example-main
 * to show an application menu as suggested in
 * https://wiki.gnome.org/ThreePointThree/Features/ApplicationMenu,
 * described in
 * https://wiki.gnome.org/HowDoI/ApplicationMenu
 * and realised using gtkmm in
 * https://git.gnome.org/browse/gtkmm-documentation/tree/examples/book/\
 *       application/app_and_win_menus
 *
 * Started on 2014-11-10
 * Current version: 2014-11-10
 * Performed by: Jürgen Kleber (jkleber2...@t-online.de)
 *
 * Original file downloaded on Sunday, 9th of November, 2014 from
 * https://git.gnome.org/browse/gtkmm-documentation/tree/examples/book/menus/\
 *       main_menu/examplewindow.h
 */

#ifndef GTKMM_EXAMPLEWINDOW_H
#define GTKMM_EXAMPLEWINDOW_H

#include <gtkmm.h>

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

protected:
   //Signal handlers:
   void on_menu_others();

   void on_menu_choices(const Glib::ustring& parameter);
   void on_menu_choices_other(int parameter);
   void on_menu_toggle();

   //Child widgets:
   Gtk::Box m_Box;

   //Two sets of choices:
   Glib::RefPtr<Gio::SimpleAction> m_refChoice, m_refChoiceOther;

   Glib::RefPtr<Gio::SimpleAction> m_refToggle;
};

#endif //GTKMM_EXAMPLEWINDOW_H

/*
 * Enhancing the main menu example of gtkmm-tutorial/unstable presented in
 * https://developer.gnome.org/gtkmm-tutorial/unstable/\
 *       sec-menus-examples.html.de#menu-example-main
 * to show an application menu as suggested in
 * https://wiki.gnome.org/ThreePointThree/Features/ApplicationMenu,
 * described in
 * https://wiki.gnome.org/HowDoI/ApplicationMenu
 * and realised using gtkmm in
 * https://git.gnome.org/browse/gtkmm-documentation/tree/examples/book/\
 *       application/app_and_win_menus
 *
 * Started on 2014-11-10
 * Current version: 2014-11-10
 * Performed by: Jürgen Kleber (jkleber2...@t-online.de)
 *
 * Original file downloaded on Sunday, 9th of November, 2014 from
 * https://git.gnome.org/browse/gtkmm-documentation/tree/examples/book/\
 *       application/app_and_win_menus/main.cc
 */

#include <iostream>

#include "exampleapplication.h"

int main(int argc, char *argv[]) {
   Glib::RefPtr<ExampleApplication> application = ExampleApplication::create();

   // Start the application, showing the initial window,
   // and opening extra windows 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 by the user.
   const int status = application->run(argc, argv);
   return status;
}
_______________________________________________
gtkmm-list mailing list
gtkmm-list@gnome.org
https://mail.gnome.org/mailman/listinfo/gtkmm-list

Reply via email to