Loading...

A Simpler MRU for GTKMM C++

View: 117    Dowload: 0   Comment: 0   Post by: admin   Category: Web Development   Fields: Other

Sometimes you need a hammer for a job, not a bazooka

I guess I'm a glutton for punishment, or like the little bird who flies against the wind; I really enjoy developing desktop applications. Now it's all about apps for phones and web applications, but I still really enjoy using my desktop and writing applications for it.

The complaint I most often hear from people opposed to adopting Linux as their desktop OS is the lack of applications for it. Well, that won't change until people start writing those apps.

As far as desktop application design goes, everything should be as simple as possible, or so my philosophy goes. All components of application design should follow that simple rule where it makes sense, and I see no reason for that principal to not be included in the humble RUF, or Recently Used File list, also known as the MRU, or Most recent, so on...

The MRU (from now on) is a tradition, should be available on any mouse driven GUI, and should be easy to implement in any toolkit or framework. Imagine my surprise when I started doing the research on using the MRU object as implemented in GTKMM; it's pretty much the most complicated collection of classes I've ever seen. And to display only the recent files relevant to your application, you need to employ some sort of filter, and then there's all the complaints I read about those objects on the web, and after that, I stopped worrying about it and wrote my own class.

I have a lot of respect for Murry Cumming and the GTKMM team, and the whole GTK project, it's a huge effort to maintain a unified set of APIs and keep them working for a moving platform like GNU/Linux/Gnome, I am surely aware. I'm also aware that there are usually a huge number of underlying reasons as to why a developer or organization implements a feature set the way they do. But sometimes, you just want a thing to just work the way you want them to.

When I got a little deeper into how GTKMM's RecentChooser classes (there's the base class Widget, a dialog object, an action object, as well as a menu object, then the filter you need to employ, and on and on) I simply shrugged my shoulders and told myself “I'm not doing that”. I get all the variations, obviously the action object is so you can add a history option to an edit menu, whatever. I just wanted the user to click on a dynamic menu that contained an MRU.

So with the history out of the way, I bring you a simpler method using the STL and GTKMM's own menu API.

Using the Code

My current application for the gnome Desktop is a classic Model-View-Controller impl with a Menu Bar, and of course, under the File item is my MRU.

An MRU at the simplest level is a FIFO, and std::deque is perfect for that job. In my application's data class (a collections of structs, really) reference to a std::deque object.

I started by adding some file menu entries, file 1..4, and binding them to a dummy function. I knew I could change the menu label and bind them to an actual function later (from my application's Glib::ustring ui_info);

"<Menuitem action=<'FileOpen'/>"
"<separator/>"
"<menuitem action='file1'/>"
"<menuitem action='file2'/>"
"<menuitem action='file3'/>"
"<menuitem action='file4'/>"

(And from my app's Gtk::ActionGroup object):

m_refActionGroup->add(Gtk::Action::create("file1", "file1",
   "Reopen this file"), sigc::mem_fun(*this, &ExampleWindow::on_dummy));
m_refActionGroup->add(Gtk::Action::create("file2", "file1",
   "Reopen this file"), sigc::mem_fun(*this, &ExampleWindow::on_dummy));
m_refActionGroup->add(Gtk::Action::create("file3", "file1",
   "Reopen this file"), sigc::mem_fun(*this, &ExampleWindow::on_dummy));
m_refActionGroup->add(Gtk::Action::create("file4", "file1",
   "Reopen this file"), sigc::mem_fun(*this, &ExampleWindow::on_dummy));

The “on_dummy” method is just an empty method, we need that because the ActionGroup template demands it be filled in, we'll fill it in with the real method later. Those menu entries must be hidden on our application' initialization, OR filled in with the list generated from the last session;

Gtk::Widget* file1 = m_refUIManager->get_widget("/ui/MenuBar/FileMenu/file1");
Gtk::Widget* file2 = m_refUIManager->get_widget("/ui/MenuBar/FileMenu/file2");
Gtk::Widget* file3 = m_refUIManager->get_widget("/ui/MenuBar/FileMenu/file3");
Gtk::Widget* file4 = m_refUIManager->get_widget("/ui/MenuBar/FileMenu/file4");

file1->hide();
file2->hide();
file3->hide();
file4->hide();

My file open menu item, when activated, as well as opening a file, takes the path it got from a file picker and sends it to a method that inserts the file into the deque object, after checking the current size of the deque:

In a header file, we have these declarations (more on the signal array 'mru_sig' later):

std::deque<Glib::ustring> mru; // our deque object
sigc::connection mru_sig[4]; // dynamic menu signals

Then in the implementation file, in our “mru manager” method, app is just a pointer to an “application structure”, a struct with the deque object, among other things:

// If the deque is more than four, we need to pop one file off it
if(app->mru.size() >= 4)
   app->mru.pop_back();

// then add the new file
app->mru.push_front(str);

// may not be nessessary
app->mru.resize(4);

Pretty simple stuff. Now, every time a file is opened, it'll be placed in our deque object, and round robin rotated to the bottom of the list every time a new file is placed on it. In this case, I'm keeping the number of recent files at 4, but it would be simple enough to adjust that number or make it user configurable if one wanted by adding an integer class member and using it instead of the “4” constant above.

Then comes the re-assignment of the menu signals, earlier in the method code, I point to some empty Gtk::Widgets with a simple array of pointers:

Glib::RefPtr<Gtk::UIManager> m_refUIManager; // Typical GTKMM stuff
Gtk::Widget* file[4];

file[0] = m_refUIManager->get_widget("/ui/MenuBar/FileMenu/file1");
file[1] = m_refUIManager->get_widget("/ui/MenuBar/FileMenu/file2");
file[2] = m_refUIManager->get_widget("/ui/MenuBar/FileMenu/file3");
file[3] = m_refUIManager->get_widget("/ui/MenuBar/FileMenu/file4");

The paths refer to the UI file menus in the Gtk XML GUI, if you're familiar with Gtk desktop programming with GTKMM, you should be aware of how that works. We'll need these as references for the dynamic menus we'll be connecting the activation signals to. Speaking of which, here's how those signals are connected to our menu items:

int n = 0;

for(deque<Glib::ustring>::iterator it =
   app->mru.begin(); it < app->mru.end(); ++it) {
   const Glib::ustring& label =
      (*it).substr((*it).find_last_of("//") + 1, (*it).length());

   dynamic_cast<Gtk::MenuItem*>(file[n])->set_label(label.c_str());
   app->mru_sig[n].disconnect();

   app->mru_sig[n] = dynamic_cast<Gtk::MenuItem*>(file[n])->signal_activate().
      connect(sigc::bind(sigc::mem_fun(*this, &ExampleWindow::on_mru), label));

   if(dynamic_cast<Gtk::MenuItem*>(file[n])->get_label().length() > 0)
      file[n++]->show();

}

We iterate through our list of 4 file paths, take out the last bit for the name we display in the menus, and then we do a generic signal disconnect on the item. If we don't, signals will stack up on the item and we'd have several file paths flying at our “open file” method. We then connect a new signal bound with the path data we want the menu item to open.

The signal method is simplicity itself:

on_mru(Glib::ustring& label)
{
   deque<Glib::ustring>::iterator it = _app->mru.begin();
   for(; it < _app->mru.end(); ++it) {
      const Glib::ustring& text =
         (*it).substr((*it).find_last_of("//") + 1, (*it).length());

      if(text.find(label) != string::npos)
         // this is the file the user clicked on in the MRU
         cout << (*it).c_str() << endl;
   }
}

The bound text from the label is searched for in the deque object, if we have a match we have our full path to the recently processed file.

Points of Interest

I'm not sure that the dummy method in the initialization area of the dynamic menu's is entirely necessary, I need to play around with the code and use the actual "on_mru" method if possible, I think I used this technique because I didn't have any data to bind to the signal, but an empty string may have been able to serve just as well.

The "on_mru" method just takes the full path to the file from the deque object and displays it in the console, obviously you'll want to pass that off to the application's open file method.

The sample requires libgtkmm 2.4, and build with:

g++ -Wall -std=c++11 examplewindow.cc main.cc -o menu `pkg-config --cflags --libs gtkmm-2.4`

A Simpler MRU for GTKMM C++

I guess I'm a glutton for punishment, or like the little bird who flies against the wind; I really enjoy developing desktop applications. Now it's all about apps for phones and web applications, but I still really enjoy using my desktop and writing applications for it.

Posted on 29-03-2018 

Comment:

To comment you must be logged in members.

Files with category

  • Twitter-like Hashtag Function in PHP

    Twitter-like Hashtag Function in PHP

    View: 0    Download: 0   Comment: 0

    Category: Php&mySql     Fields: none

    If you ever want a function to hashtag and style words within a string which has '#' next to it like twitter. This piece of code will help

  • Mini Youtube Using ReactJS

    Mini Youtube Using ReactJS

    View: 25    Download: 2   Comment: 0

    Category: Javascript     Fields: none

    This is one the best starter for ReactJS. MiniYoutube as the name suggests is a youtube like website developed using reactJS and youtube API. This project actually let's you search , play and list youtube videos. Do check it out and start learning...

  • PSITS Automated Voting System

    PSITS Automated Voting System

    View: 24    Download: 3   Comment: 0

    Category: Php&mySql     Fields: none

    A free sourcecode for PSITS Automated Voting System develop in PHP programming language. The purposed of the system is to automate the process of voting and maintain the quality of data

  • Document Management System in VB.Net

    Document Management System in VB.Net

    View: 24    Download: 1   Comment: 0

    Category: Forum PHPBB, VBB     Fields: none

    This is a Client Server project entitled Document Management System written in Vb.net and SQL Server Management Studio R2 2008 database for Mines and Geosciences Bureau . There are three (3) sections in the Mines and Geosciences Bureau, namely: under...

  • PHP-University Application System

    PHP-University Application System

    View: 30    Download: 6   Comment: 0

    Category: Php&mySql     Fields: none

    Greeting from Malawi the warm heart of Africa. I developed this university registration system project just to share with the people who can make use of the project like this and at the same time for others like students who can learn from it. This...

  • School Event Management System in PHP/MSQLi

    School Event Management System in PHP/MSQLi

    View: 22    Download: 0   Comment: 0

    Category: Php&mySql     Fields: none

    This School Event Management System can create school events such as Volleyball games, Basketball, Cultural presentation, Election of school officers etc . During school election Instead of having a compile list of candidates and voters this system...

  • Resort Reservation System with PayPal/Credit Card/Debit Card Payment

    Resort Reservation System with PayPal/Credit Card/Debit Card Payment

    View: 27    Download: 0   Comment: 0

    Category: Php&mySql     Fields: none

    This reservation system has the ability to help its customers find available rooms, cottages and even function hall for their convenience . And in here, they will also have the idea of the room rates where they can quickly reserve for their family...

  • Activity log

    Activity log

    View: 20    Download: 0   Comment: 0

    Category: Php&mySql     Fields: none

    Simple program to track user's activity log-in time and online/offline status.

 
File suggestion for you
Loading...
File top downloads
Loading...
Loading...
Codetitle - library source code to share, download the file to the community
Copyright © 2018. All rights reserved. codetitle Develope by Vinagon .Ltd