Что корректный путь состоит в том, чтобы использовать g_signal_connect () в C++ для динамической единицы quicklists?

Я хочу подать свою заявку использовать динамическую единицу quicklists. Для того, чтобы создать мое приложение я использую C++ и QtCreator IDE. Когда действие меню инициировано, я хочу смочь иметь доступ к нестатической функции моего MainWindow класс, чтобы смочь обновить Графический интерфейс пользователя, к которому можно получить доступ из функций 'нормального' MainWindow.

Так, я создаю свой quicklist как этот (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);

Это предложение было взято из http://old.nabble.com/Using-g_signal_connect-in-class-td18461823.html

Программа сразу отказывает после того, как я выберу действие 'Stop' из Единицы Quicklist. Отладка программы показывает, что я не могу получить доступ к чему-либо связанному с MainWindow в on_stopButton_clicked () без катастрофического отказа. Например, это отказывает при выполнении этой проверки (который является первыми 2 строками кода в этой функции):

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

Я также протестировал много других вещей, которые я нашел в Интернете, но ничто из них не работало. Одно интересное решение состояло бы в том, чтобы использовать gtkmm (http://developer.gnome.org/gtkmm-tutorial/stable/sec-connecting-signal-handlers.html.en), но я не используюсь при всей работе над приложениями GTK (я работаю только в QT), и я не знаю, подходит ли это даже к моему случаю.

6
задан 14 June 2014 в 05:41

1 ответ

Редактирование: хорошо, после изрядного количества расследования (который включил выполнение valgrind), мне наконец удалось выяснить то, что продолжается здесь. Подпись Вашего обратного вызова не корректна.

подпись для статического метода должна быть:

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

Уведомление добавление DbusmenuMenuitem * и guint. Первым является указатель на пункт меню DBus, испускающий сигнал, и второй является метка времени. Оба должны присутствовать в подписи, даже если Вы не используете их.

g_signal_connect вызывается во времени выполнения и не имеет никакого способа знать, какие параметры Ваша функция принимает и вслепую просто продвигает параметры на стеке, предполагающем, что подписи соответствуют. (Это отличается от того, к чему Вы, вероятно, привыкли в QT, где MOC (Компилятор Метаобъекта) генерирует достаточно информации для знания, когда Вы пытаетесь подключить сигнал к слоту с несовместимой подписью.)

3
ответ дан 23 November 2019 в 08:06

Другие вопросы по тегам:

Похожие вопросы: