Take the 2-minute tour ×
Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free, no registration required.

I want to make my application use dynamic unity quicklists. For building my application I am using C++ and the QtCreator IDE. When a menu action is triggered I want to be able to have access to a non-static function of my MainWindow class so as to be able to update the Graphical User Interface which can be accessed from inside 'normal' MainWindow's functions.

So, I am building up my quicklist like this (mainwindow.cpp):

void MainWindow::enable_unity_quicklist(){
    Unity_Menu = dbusmenu_menuitem_new();

    dbusmenu_menuitem_property_set_bool (Unity_Menu, DBUSMENU_MENUITEM_PROP_VISIBLE, FALSE);

    Unity_Stop = dbusmenu_menuitem_new();
    dbusmenu_menuitem_property_set(Unity_Stop, DBUSMENU_MENUITEM_PROP_LABEL, "Stop");

    dbusmenu_menuitem_child_append (Unity_Menu, Unity_Stop);

    g_signal_connect (Unity_Stop, DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED, G_CALLBACK(&fake_callback), (gpointer)this);

    if(!unity_entry)
        unity_entry = unity_launcher_entry_get_for_desktop_id("myapp.desktop");

    unity_launcher_entry_set_quicklist(unity_entry, Unity_Menu);

    dbusmenu_menuitem_property_set_bool(Unity_Menu, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
    dbusmenu_menuitem_property_set_bool(Unity_Stop, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
}

void MainWindow::fake_callback(gpointer data){
    MainWindow* m = (MainWindow*)data;
    m->on_stopButton_clicked();
}

void MainWindow::on_stopButton_clicked(){
   //stopping the process...
}

mainwindow.h:

private slots:
   void enable_unity_quicklist();
   void on_stopButton_clicked();
public slots:
   static void fake_callback(gpointer data);

This suggestion was taken from http://old.nabble.com/Using-g_signal_connect-in-class-td18461823.html

The program crashes immediately after I choose the 'Stop' action from the Unity Quicklist. Debugging the program shows that I am not able to access anything MainWindow related inside the on_stopButton_clicked() without crashing. For example, it crashes when doing this check (which is the first 2 lines of code inside this function):

if (!ui->stopButton->isEnabled())
        return;

I have also tested lots of other things that I found at the internet, but nothing of them worked. One interesting solution would be to use gtkmm (http://developer.gnome.org/gtkmm-tutorial/stable/sec-connecting-signal-handlers.html.en) but I am not used at all working on GTK applications (I work solely in Qt) and I don't know if this even suits to my occasion.

share|improve this question
    
Try changing MainWindow* m = (MainWindow*)data; to MainWindow* m = dynamic_cast<MainWindow*>(data); and checking the value of m to see if it is non-NULL. This will tell you whether the pointer is being passed along alright. –  Nathan Osman Aug 27 '12 at 23:52
    
Thanks for the comment. I get the following error message: error: cannot dynamic_cast 'data' (of type 'gpointer {aka void*}') to type 'class MainWindow*' (source is not a pointer to class). If you want I can provide you with a simple compilable example indicating the problem so as not to suggest by guessing. Please tell me if you want so. –  hakermania Aug 28 '12 at 5:25

1 Answer 1

up vote 3 down vote accepted
+500

Edit: okay, after a fair amount of investigation (which involved running valgrind), I have finally managed to figure out what's going on here. Your callback's signature isn't correct.

The signature for the static method should be:

void MainWindow::fake_callback(DbusmenuMenuitem *, guint, gpointer data)
{
    //...
}

Notice the addition of DbusmenuMenuitem * and guint. The first is a pointer to the DBus menu item emitting the signal and the second is a timestamp. Both must be present in the signature even if you don't use them.

g_signal_connect is invoked at runtime and has no way of knowing what parameters your function accepts and blindly just pushes the parameters on the stack assuming that the signatures match. (This differs from what you are probably used to in Qt where the MOC (Meta Object Compiler) generates enough information to know when you are trying to connect a signal to a slot with an incompatible signature.)

share|improve this answer
    
I don't really understand what you ask me to do. How should I call the fake_callback function through the g_signal_connect function? Can you provide me with sample code as I did? Thanks! –  hakermania Aug 28 '12 at 20:48
    
@hakermania: I am asking you to change MainWindow::fake_callback(...) to the following contents: paste.ubuntu.com/1172579 –  Nathan Osman Aug 28 '12 at 21:05
    
That crashed the program as well. Please see my edited question so as to find a compilable example. Sorry I didn't provide one earlier. –  hakermania Aug 28 '12 at 21:34
    
@hakermania: Thanks for including the source code. I was able to actually get the sample to run after making some modifications. However, I haven't yet figured out why it works now - I'm still working on that. I'll let you know once I figure it out. –  Nathan Osman Aug 28 '12 at 22:37
1  
Thanks more than a lot :) I guess here lays the only solution to this problem on the whole internet :P –  hakermania Aug 29 '12 at 2:16

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.