Combining Qt with GTK only one problem!

I am using this code:

g_signal_connect(showapp_option, "activate", G_CALLBACK(&MainWindow::show_app), appindicator);

so as to connect my indicator menu item to the function show_app(), and it works just fine, irregardless the fact that I get the following warning:

warning: converting from 'void (MainWindow::*)()' to 'GCallback {aka void (*)()}' [-Wpmf-conversions]

I don't understand the warning as I've never worked with the gtk libs before... Anyway, this isn't the real reason I'm posting here, but it is maybe related to it.

The problem is that I cannot use 'this' (which stands for the MainWindow's call) from inside show_app() function, because the program crashes!

Why I cannot use 'this' inside the function? And, more importantly, how do I make it work?:confused:

We need to see more context.

Ok, here it is:

void MainWindow::show_app(){
    //crash here:
    this->show();
    //this works fine:
    app_indicator_set_status(appindicator, APP_INDICATOR_STATUS_PASSIVE);

}

void MainWindow::make_indicator()
{
    if(appindicator){
        //appindicator has already been created
        return;
    }
    appindicator = app_indicator_new("Format Junkie Indicator", "formatjunkie", APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
    GtkWidget* showapp_option;
    GtkWidget* add_audio_option;
    //GtkWidget* subitem3;
    GtkWidget* indicatormenu = gtk_menu_new();
    GtkWidget* item = gtk_menu_item_new_with_label("Format Junkie main menu");
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), indicatormenu);

    showapp_option = gtk_menu_item_new_with_label("Show App!");
    g_signal_connect(showapp_option, "activate", G_CALLBACK(&MainWindow::show_app), appindicator);
    gtk_menu_shell_append(GTK_MENU_SHELL(indicatormenu), showapp_option);

    add_audio_option = gtk_menu_item_new_with_label("Add audio files");
    g_signal_connect(add_audio_option, "activate", G_CALLBACK(&MainWindow::add_audio_files), appindicator);
    gtk_menu_shell_append(GTK_MENU_SHELL(indicatormenu), add_audio_option);
/*
    subitem3 = gtk_menu_item_new_with_label("Quit");
    g_signal_connect(subitem3, "activate", G_CALLBACK(quit_from_indicator), appindicator);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), subitem3);*/
    gtk_widget_show_all(indicatormenu);
    app_indicator_set_status(appindicator, APP_INDICATOR_STATUS_ACTIVE);
    app_indicator_set_attention_icon(appindicator, "dialog-warning");

    app_indicator_set_menu(appindicator, GTK_MENU (indicatormenu));
}
1 Like

You are forcing a conversion from a class member to a function call. Class members have this, function calls don't. So it crashes.

If you make the member function static, you'll be able to call it, since static member functions don't have 'this'. So you won't have this but you can make do -- that's what the data parameter in a GTK callback is for instead. You can pass a long a pointer for data you need later. Pass in the class itself and you can go datapointer->whatever.

// You'll have to change the definition in the header file too, if any
static void MainWindow::show_app(MainWindow *data){
    data->show();
    //crash here:
//    this->show();
    //this works fine:
    app_indicator_set_status(appindicator, APP_INDICATOR_STATUS_PASSIVE);
}

void MainWindow::make_indicator()
{
    if(appindicator){
        //appindicator has already been created
        return;
    }
    appindicator = app_indicator_new("Format Junkie Indicator", "formatjunkie", APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
    GtkWidget* showapp_option;
    GtkWidget* add_audio_option;
    //GtkWidget* subitem3;
    GtkWidget* indicatormenu = gtk_menu_new();
    GtkWidget* item = gtk_menu_item_new_with_label("Format Junkie main menu");
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), indicatormenu);

    showapp_option = gtk_menu_item_new_with_label("Show App!");
    g_signal_connect(showapp_option, "activate", G_CALLBACK(&MainWindow::show_app), this);
    gtk_menu_shell_append(GTK_MENU_SHELL(indicatormenu), showapp_option);

    add_audio_option = gtk_menu_item_new_with_label("Add audio files");
    g_signal_connect(add_audio_option, "activate", G_CALLBACK(&MainWindow::add_audio_files), this);
    gtk_menu_shell_append(GTK_MENU_SHELL(indicatormenu), add_audio_option);
/*
    subitem3 = gtk_menu_item_new_with_label("Quit");
    g_signal_connect(subitem3, "activate", G_CALLBACK(quit_from_indicator), appindicator);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), subitem3);*/
    gtk_widget_show_all(indicatormenu);
    app_indicator_set_status(appindicator, APP_INDICATOR_STATUS_ACTIVE);
    app_indicator_set_attention_icon(appindicator, "dialog-warning");

    app_indicator_set_menu(appindicator, GTK_MENU (indicatormenu));
}

You'll have to do the same with add_audio_files, too.

1 Like

Thanks for this! Still, it doesn't work!
This is my code:

void MainWindow::show_app(MainWindow *data){
    data->show();
    app_indicator_set_status(appindicator, APP_INDICATOR_STATUS_PASSIVE);
}

void MainWindow::make_indicator()
{
    if(appindicator){
        //appindicator has already been created
        return;
    }
    appindicator = app_indicator_new("Format Junkie Indicator", "formatjunkie", APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
    GtkWidget* showapp_option;
    GtkWidget* add_audio_option;
    //GtkWidget* subitem3;
    GtkWidget* indicatormenu = gtk_menu_new();
    GtkWidget* item = gtk_menu_item_new_with_label("Format Junkie main menu");
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), indicatormenu);

    showapp_option = gtk_menu_item_new_with_label("Show App!");
    g_signal_connect(showapp_option, "activate", G_CALLBACK(&MainWindow::show_app), this);
    gtk_menu_shell_append(GTK_MENU_SHELL(indicatormenu), showapp_option);

    add_audio_option = gtk_menu_item_new_with_label("Add audio files");
    g_signal_connect(add_audio_option, "activate", G_CALLBACK(&MainWindow::add_audio_files), this);
    gtk_menu_shell_append(GTK_MENU_SHELL(indicatormenu), add_audio_option);

    gtk_widget_show_all(indicatormenu);
    app_indicator_set_status(appindicator, APP_INDICATOR_STATUS_ACTIVE);
    app_indicator_set_attention_icon(appindicator, "dialog-warning");

    app_indicator_set_menu(appindicator, GTK_MENU (indicatormenu));
}

In the header file:

private slots:
    static void show_app(MainWindow *data);

It doesn't let me add 'static' in front of the function in the .cpp file, because of

error: cannot declare member function 'static void MainWindow::show_app(MainWindow*)' to have static linkage [-fpermissive]

Also, the warning didn't go.

Thanks!

The warning is a warning. If you know why it's there and what you're doing, you can ignore it.

It's saying -fpermissive might allow you to follow that suggestion but it might not be a good idea. I think that used to be perfectly valid, but standards are changing, so let's follow its suggestion and do that another way. Let's make global functions instead of static ones...

// Completely outside the class
void show_app_stub(MainWindow *data)
{
        data->show_app();
}

...

// in make_indicator
g_signal_connect(showapp_option, "activate", G_CALLBACK(show_app_stub), this);
1 Like

Thanks again. The warning's gone but the crush is still there...

Show your updated code please.

1 Like

Here you are:

void show_app(MainWindow *data)
{
    qDebug() << "1";
    data->show();
    qDebug() << "2";
}


void MainWindow::make_indicator()
{
    if(appindicator){
        //appindicator has already been created
        return;
    }
    appindicator = app_indicator_new("Format Junkie Indicator", "formatjunkie", APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
    GtkWidget* showapp_option;
    GtkWidget* indicatormenu = gtk_menu_new();
    GtkWidget* item = gtk_menu_item_new_with_label("Format Junkie main menu");
    gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), indicatormenu);

    showapp_option = gtk_menu_item_new_with_label("Show App!");
    g_signal_connect(showapp_option, "activate", G_CALLBACK(show_app), this);
    gtk_menu_shell_append(GTK_MENU_SHELL(indicatormenu), showapp_option);

    gtk_widget_show_all(indicatormenu);
    app_indicator_set_status(appindicator, APP_INDICATOR_STATUS_ACTIVE);
    app_indicator_set_attention_icon(appindicator, "dialog-warning");

    app_indicator_set_menu(appindicator, GTK_MENU (indicatormenu));
}

I don't get any warning with the above code... The qDebug() calls in show_app() function is so as to be sure that the crash happens when data->show() is called. With the above code, only '1' is outputed and not '2' (this is a little quicker way to see what's wrong, without debugging the application step by step)

Anyone :D:D:D:D:DD:D:D:D ?

Does it crash when you comment out data->show() ?

No!
I have found a solution, though: GTK app: How do I create a working indicator with Qt/C++? - Stack Overflow

1 Like