QMetaObject::Connection gtk_combo_box_set_qmodel(GtkComboBox *box, QAbstractItemModel *qmodel, QItemSelectionModel *selection_model) { QMetaObject::Connection connection; GtkTreeModel *model; model = (GtkTreeModel *)gtk_q_tree_model_new( qmodel, 1, 0, Qt::DisplayRole, G_TYPE_STRING); /* use a filter model to remove disabled items */ GtkTreeModel *filter_model = gtk_tree_model_filter_new(model, NULL); gtk_tree_model_filter_set_visible_func(GTK_TREE_MODEL_FILTER(filter_model), (GtkTreeModelFilterVisibleFunc)filter_disabled_items, NULL, NULL); gtk_combo_box_set_model(box, GTK_TREE_MODEL(filter_model)); GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(box), renderer, FALSE); gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(box), renderer, "text", 0, NULL); if (!selection_model) return connection; /* sync the initial selection */ gtk_combo_box_set_active_index(box, selection_model->currentIndex()); /* connect signals to and from the selection model */ connection = QObject::connect( selection_model, &QItemSelectionModel::currentChanged, [=](const QModelIndex current, G_GNUC_UNUSED const QModelIndex & previous) { gtk_combo_box_set_active_index(box, current); } ); g_signal_connect(box, "changed", G_CALLBACK(update_selection), selection_model); return connection; }
static void build_tab_view(AccountDevicesTab *view) { g_return_if_fail(IS_ACCOUNT_DEVICES_TAB(view)); AccountDevicesTabPrivate *priv = ACCOUNT_DEVICES_TAB_GET_PRIVATE(view); g_signal_connect_swapped(priv->button_add_device, "clicked", G_CALLBACK(show_add_device_view), view); g_signal_connect_swapped(priv->button_add_device_cancel, "clicked", G_CALLBACK(show_manage_devices_view), view); g_signal_connect(priv->button_export_on_the_ring, "clicked", G_CALLBACK(export_on_the_ring_clicked), view); g_signal_connect_swapped(priv->button_generated_pin_ok, "clicked", G_CALLBACK(show_manage_devices_view), view); g_signal_connect_swapped(priv->button_export_on_ring_error_ok, "clicked", G_CALLBACK(show_add_device_view), view); gtk_label_set_text(GTK_LABEL(priv->label_device_id), priv->account->deviceId().toUtf8().constData()); /* treeview_devices */ auto *devices_model = gtk_q_tree_model_new( (QAbstractItemModel*) priv->account->ringDeviceModel(), 2, RingDevice::Column::Name, Qt::DisplayRole, G_TYPE_STRING, RingDevice::Column::Id, Qt::DisplayRole, G_TYPE_STRING); gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview_devices), GTK_TREE_MODEL(devices_model)); GtkCellRenderer* renderer; GtkTreeViewColumn* column; renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes(C_("Device Name Column", "Name"), renderer, "text", 0, NULL); gtk_tree_view_column_set_expand(column, TRUE); gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_devices), column); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes(C_("Device ID Column", "ID"), renderer, "text", 1, NULL); gtk_tree_view_column_set_expand(column, TRUE); gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_devices), column); /* Show manage-devices view */ gtk_stack_set_visible_child(GTK_STACK(priv->stack_account_devices), priv->manage_devices); }
static void build_tab_view(AccountSecurityTab *self) { g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self)); AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self); gboolean not_ring = priv->account->protocol() != Account::Protocol::RING; /* SRTP */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_srtp), priv->account->isSrtpEnabled()); /* disable options if SRTP is off or if its a RING account */ gtk_widget_set_sensitive(priv->checkbutton_use_srtp, not_ring); gtk_widget_set_sensitive(priv->box_key_exchange, priv->account->isSrtpEnabled() && not_ring); gtk_widget_set_sensitive(priv->checkbutton_srtp_fallback, priv->account->isSrtpEnabled() && not_ring); g_signal_connect(priv->checkbutton_use_srtp, "toggled", G_CALLBACK(use_srtp_toggled), self); /* encryption key exchange type */ priv->key_exchange_selection = gtk_combo_box_set_qmodel( GTK_COMBO_BOX(priv->combobox_key_exchange), (QAbstractItemModel *)priv->account->keyExchangeModel(), priv->account->keyExchangeModel()->selectionModel()); /* SRTP fallback */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_srtp_fallback), priv->account->isSrtpRtpFallback()); g_signal_connect(priv->checkbutton_srtp_fallback, "toggled", G_CALLBACK(use_rtp_fallback_toggled), self); /* use TLS */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_tls), priv->account->isTlsEnabled()); /* disable certain options if TLS is off, or if its a RING account*/ gtk_widget_set_sensitive(priv->checkbutton_use_tls, not_ring); gtk_widget_set_sensitive(priv->grid_tls_settings_0, priv->account->isTlsEnabled()); gtk_widget_set_sensitive(priv->grid_tls_settings_1, priv->account->isTlsEnabled() && not_ring); gtk_widget_set_sensitive(priv->buttonbox_cipher_list, priv->account->isTlsEnabled() && not_ring); gtk_widget_set_sensitive(priv->treeview_cipher_list, priv->account->isTlsEnabled() && not_ring); gtk_widget_set_sensitive(priv->checkbutton_verify_certs_server, priv->account->isTlsEnabled() && not_ring); gtk_widget_set_sensitive(priv->checkbutton_verify_certs_client, priv->account->isTlsEnabled() && not_ring); gtk_widget_set_sensitive(priv->checkbutton_require_incoming_tls_certs, priv->account->isTlsEnabled() && not_ring); g_signal_connect(priv->checkbutton_use_tls, "toggled", G_CALLBACK(use_tls_toggled), self); /* CA certificate */ Certificate *ca_cert = priv->account->tlsCaListCertificate(); if (ca_cert) { gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->filechooserbutton_ca_list), ca_cert->path().toUtf8().constData()); } g_signal_connect(priv->filechooserbutton_ca_list, "file-set", G_CALLBACK(ca_cert_file_set), self); /* user certificate */ if ( (priv->user_cert = priv->account->tlsCertificate()) ) { gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->filechooserbutton_certificate), priv->user_cert->path().toUtf8().constData() ); } g_signal_connect(priv->filechooserbutton_certificate, "file-set", G_CALLBACK(user_cert_file_set), self); /* private key */ if (!priv->account->tlsPrivateKey().isEmpty()) { gtk_file_chooser_set_filename( GTK_FILE_CHOOSER(priv->filechooserbutton_private_key), priv->account->tlsPrivateKey().toUtf8().constData() ); } g_signal_connect(priv->filechooserbutton_private_key, "file-set", G_CALLBACK(private_key_file_set), self); /* password */ check_tlspassword_valid(self); if (priv->user_cert && priv->user_cert->requirePrivateKeyPassword()) { gtk_entry_set_text( GTK_ENTRY(priv->entry_password), priv->account->tlsPassword().toUtf8().constData() ); gtk_widget_set_sensitive(priv->entry_password, TRUE); gtk_widget_set_sensitive(priv->label_private_key_password, TRUE); } else { /* private key not chosen, or password not required, so disactivate the entry */ gtk_widget_set_sensitive(priv->entry_password, FALSE); gtk_widget_set_sensitive(priv->label_private_key_password, FALSE); } g_signal_connect(priv->entry_password, "changed", G_CALLBACK(private_key_password_changed), self); /* TLS protocol method */ priv->tls_method_selection = gtk_combo_box_set_qmodel(GTK_COMBO_BOX(priv->combobox_tls_protocol_method), (QAbstractItemModel *)priv->account->tlsMethodModel(), priv->account->tlsMethodModel()->selectionModel()); /* outgoing TLS server */ gtk_entry_set_text(GTK_ENTRY(priv->entry_tls_server_name), priv->account->tlsServerName().toUtf8().constData()); g_signal_connect(priv->entry_tls_server_name, "changed", G_CALLBACK(tls_server_name_changed), self); /* TLS nego timeout */ gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_tls_timeout), priv->account->tlsNegotiationTimeoutSec()); g_signal_connect(priv->adjustment_tls_timeout, "value-changed", G_CALLBACK(tls_timeout_changed), self); /* cipher default or custom */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->radiobutton_use_default_ciphers), priv->account->cipherModel()->useDefault()); /* hide the cipher list if we're using the default ones */ gtk_revealer_set_reveal_child(GTK_REVEALER(priv->revealer_cipher_list), !priv->account->cipherModel()->useDefault()); g_signal_connect(priv->radiobutton_use_default_ciphers, "toggled", G_CALLBACK(use_default_ciphers_toggled), self); /* cipher list */ GtkQTreeModel *cipher_model = gtk_q_tree_model_new( (QAbstractItemModel *)priv->account->cipherModel(), 2, Qt::CheckStateRole, G_TYPE_BOOLEAN, Qt::DisplayRole, G_TYPE_STRING); gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview_cipher_list), GTK_TREE_MODEL(cipher_model)); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(priv->treeview_cipher_list), FALSE); GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new(); GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes( "Enabled", renderer, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_cipher_list), column); /* we have to use a custom data function here because Qt::Checked and Qt::Unchecked * are not the same as true/false as there is an intermediate state */ gtk_tree_view_column_set_cell_data_func(column, renderer, (GtkTreeCellDataFunc)render_check_state, NULL, NULL); g_signal_connect(renderer, "toggled", G_CALLBACK(cipher_enable_toggled), self); renderer = gtk_cell_renderer_text_new(); column = gtk_tree_view_column_new_with_attributes("Cipher", renderer, "text", 1, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_cipher_list), column); /* server certs */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_verify_certs_server), priv->account->isTlsVerifyServer()); g_signal_connect(priv->checkbutton_verify_certs_server, "toggled", G_CALLBACK(verify_certs_server_toggled), self); /* client certs */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_verify_certs_client), priv->account->isTlsVerifyClient()); g_signal_connect(priv->checkbutton_verify_certs_client, "toggled", G_CALLBACK(verify_certs_client_toggled), self); /* incoming certs */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_require_incoming_tls_certs), priv->account->isTlsRequireClientCertificate()); g_signal_connect(priv->checkbutton_require_incoming_tls_certs, "toggled", G_CALLBACK(require_incoming_certs_toggled), self); /* update account UI if model is updated */ priv->account_updated = QObject::connect( priv->account, &Account::changed, [=] () { /* SRTP */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_srtp), priv->account->isSrtpEnabled()); /* SRTP fallback */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_srtp_fallback), priv->account->isSrtpRtpFallback()); /* use TLS */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_tls), priv->account->isTlsEnabled()); /* CA certificate */ Certificate *ca_cert = priv->account->tlsCaListCertificate(); if (ca_cert) { gtk_file_chooser_set_filename( GTK_FILE_CHOOSER(priv->filechooserbutton_ca_list), ca_cert->path().toUtf8().constData() ); } else { /* make sure nothing is selected */ gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(priv->filechooserbutton_ca_list)); } /* user certificate */ QObject::disconnect(priv->cert_changed); if ( (priv->user_cert = priv->account->tlsCertificate()) ) { gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->filechooserbutton_certificate), priv->user_cert->path().toUtf8().constData() ); } else { /* make sure nothing is selected */ gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(priv->filechooserbutton_certificate)); } /* private key */ if (!priv->account->tlsPrivateKey().isEmpty()) { gtk_file_chooser_set_filename( GTK_FILE_CHOOSER(priv->filechooserbutton_private_key), priv->account->tlsPrivateKey().toUtf8().constData() ); } else { /* make sure nothing is selected */ gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(priv->filechooserbutton_private_key)); } /* password */ check_tlspassword_valid(self); if (priv->user_cert && priv->user_cert->requirePrivateKeyPassword()) { gtk_entry_set_text( GTK_ENTRY(priv->entry_password), priv->account->tlsPassword().toUtf8().constData() ); gtk_widget_set_sensitive(priv->entry_password, TRUE); gtk_widget_set_sensitive(priv->label_private_key_password, TRUE); } else { /* private key not chosen, or password not required, so disactivate the entry */ gtk_widget_set_sensitive(priv->entry_password, FALSE); gtk_widget_set_sensitive(priv->label_private_key_password, FALSE); } /* outgoing TLS server */ gtk_entry_set_text(GTK_ENTRY(priv->entry_tls_server_name), priv->account->tlsServerName().toUtf8().constData()); /* TLS nego timeout */ gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_tls_timeout), priv->account->tlsNegotiationTimeoutSec()); /* cipher default or custom */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->radiobutton_use_default_ciphers), priv->account->cipherModel()->useDefault()); /* server certs */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_verify_certs_server), priv->account->isTlsVerifyServer()); /* client certs */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_verify_certs_client), priv->account->isTlsVerifyClient()); /* incoming certs */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_require_incoming_tls_certs), priv->account->isTlsRequireClientCertificate()); } ); }
static void ring_main_window_init(RingMainWindow *win) { RingMainWindowPrivate *priv = RING_MAIN_WINDOW_GET_PRIVATE(win); gtk_widget_init_template(GTK_WIDGET(win)); /* set window icon */ GError *error = NULL; GdkPixbuf* icon = gdk_pixbuf_new_from_resource("/cx/ring/RingGnome/ring-symbol-blue", &error); if (icon == NULL) { g_debug("Could not load icon: %s", error->message); g_clear_error(&error); } else gtk_window_set_icon(GTK_WINDOW(win), icon); /* set menu icon */ GdkPixbuf* image_ring = gdk_pixbuf_new_from_resource_at_scale("/cx/ring/RingGnome/ring-symbol-blue", -1, 24, TRUE, &error); if (image_ring == NULL) { g_debug("Could not load icon: %s", error->message); g_clear_error(&error); } else gtk_image_set_from_pixbuf(GTK_IMAGE(priv->image_ring), image_ring); /* ring menu */ GtkBuilder *builder = gtk_builder_new_from_resource("/cx/ring/RingGnome/ringgearsmenu.ui"); GMenuModel *menu = G_MENU_MODEL(gtk_builder_get_object(builder, "menu")); gtk_menu_button_set_menu_model(GTK_MENU_BUTTON(priv->ring_menu), menu); g_object_unref(builder); /* settings icon */ gtk_image_set_from_icon_name(GTK_IMAGE(priv->image_settings), "emblem-system-symbolic", GTK_ICON_SIZE_LARGE_TOOLBAR); /* connect settings button signal */ g_signal_connect(priv->ring_settings, "clicked", G_CALLBACK(settings_clicked), win); /* add the call view to the main stack */ gtk_stack_add_named(GTK_STACK(priv->stack_main_view), priv->vbox_call_view, CALL_VIEW_NAME); if (has_ring_account()) { /* user has ring account, so show the call view right away */ gtk_stack_set_visible_child(GTK_STACK(priv->stack_main_view), priv->vbox_call_view); } else { /* user has to create the ring account */ show_account_creation(win); } /* init the settings views */ priv->account_settings_view = account_view_new(); gtk_stack_add_named(GTK_STACK(priv->stack_main_view), priv->account_settings_view, ACCOUNT_SETTINGS_VIEW_NAME); priv->media_settings_view = media_settings_view_new(); gtk_stack_add_named(GTK_STACK(priv->stack_main_view), priv->media_settings_view, MEDIA_SETTINGS_VIEW_NAME); priv->general_settings_view = general_settings_view_new(); gtk_stack_add_named(GTK_STACK(priv->stack_main_view), priv->general_settings_view, GENERAL_SETTINGS_VIEW_NAME); /* make the setting we will show first the active one */ gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->radiobutton_general_settings), TRUE); priv->last_settings_view = priv->general_settings_view; /* connect the settings button signals to switch settings views */ g_signal_connect(priv->radiobutton_media_settings, "toggled", G_CALLBACK(show_media_settings), win); g_signal_connect(priv->radiobutton_account_settings, "toggled", G_CALLBACK(show_account_settings), win); g_signal_connect(priv->radiobutton_general_settings, "toggled", G_CALLBACK(show_general_settings), win); /* populate the notebook */ auto smart_view = recent_contacts_view_new(); gtk_container_add(GTK_CONTAINER(priv->scrolled_window_smartview), smart_view); auto contacts_view = contacts_view_new(); gtk_container_add(GTK_CONTAINER(priv->scrolled_window_contacts), contacts_view); auto history_view = history_view_new(); gtk_container_add(GTK_CONTAINER(priv->scrolled_window_history), history_view); /* welcome/default view */ priv->welcome_view = ring_welcome_view_new(); g_object_ref(priv->welcome_view); // gtk_stack_add_named(GTK_STACK(priv->stack_call_view), welcome_view, DEFAULT_VIEW_NAME); gtk_container_add(GTK_CONTAINER(priv->frame_call), priv->welcome_view); gtk_widget_show(priv->welcome_view); /* call/chat selection */ QObject::connect( RecentModel::instance().selectionModel(), &QItemSelectionModel::currentChanged, [win](const QModelIndex current, G_GNUC_UNUSED const QModelIndex & previous) { if (auto call = RecentModel::instance().getActiveCall(current)) { /* if the call is on hold, we want to put it off hold automatically * when switching to it */ if (call->state() == Call::State::HOLD) call << Call::Action::HOLD; } selection_changed(current, win); } ); /* connect to dataChanged of the RecentModel to see if we need to change the view */ QObject::connect( &RecentModel::instance(), &RecentModel::dataChanged, [win](const QModelIndex & topLeft, G_GNUC_UNUSED const QModelIndex & bottomRight, G_GNUC_UNUSED const QVector<int> & roles) { /* it is possible for dataChanged to be emitted inside of a dataChanged handler or * some other signal; since the connection is via a lambda, Qt would cause the * handler to be called directly. This is not behaviour we usually want, so we call our * function via g_idle so that it gets called after the initial handler is done. */ if (topLeft == RecentModel::instance().selectionModel()->currentIndex()) g_idle_add((GSourceFunc)selected_item_changed, win); } ); g_signal_connect(priv->button_placecall, "clicked", G_CALLBACK(search_entry_placecall), win); g_signal_connect(priv->search_entry, "activate", G_CALLBACK(search_entry_placecall), win); /* autocompletion */ priv->q_completion_model = new NumberCompletionModel(); /* autocompletion renderers */ GtkCellArea *completion_area = gtk_cell_area_box_new(); /* photo renderer */ GtkCellRenderer *renderer = gtk_cell_renderer_pixbuf_new(); gtk_cell_area_box_pack_start(GTK_CELL_AREA_BOX(completion_area), renderer, TRUE, /* expand */ TRUE, /* align */ TRUE); /* fixed size */ gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(completion_area), renderer, (GtkCellLayoutDataFunc)autocompletion_photo_render, NULL, NULL); /* name renderer */ renderer = gtk_cell_renderer_text_new(); g_object_set(G_OBJECT(renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL); gtk_cell_area_box_pack_start(GTK_CELL_AREA_BOX(completion_area), renderer, TRUE, /* expand */ TRUE, /* align */ TRUE); /* fixed size */ gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(completion_area), renderer, (GtkCellLayoutDataFunc)autocompletion_name_render, NULL, NULL); /* number renderer */ renderer = gtk_cell_renderer_text_new(); g_object_set(G_OBJECT(renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL); gtk_cell_area_box_pack_start(GTK_CELL_AREA_BOX(completion_area), renderer, TRUE, /* expand */ TRUE, /* align */ TRUE); /* fixed size */ gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(completion_area), renderer, (GtkCellLayoutDataFunc)autocompletion_number_render, NULL, NULL); /* account renderer */ renderer = gtk_cell_renderer_text_new(); g_object_set(G_OBJECT(renderer), "ellipsize", PANGO_ELLIPSIZE_END, NULL); gtk_cell_area_box_pack_start(GTK_CELL_AREA_BOX(completion_area), renderer, TRUE, /* expand */ TRUE, /* align */ TRUE); /* fixed size */ gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(completion_area), renderer, (GtkCellLayoutDataFunc)autocompletion_account_render, NULL, NULL); GtkEntryCompletion *entry_completion = gtk_entry_completion_new_with_area(completion_area); GtkQTreeModel *completion_model = gtk_q_tree_model_new( (QAbstractItemModel *)priv->q_completion_model, 1, Qt::DisplayRole, G_TYPE_STRING); gtk_entry_completion_set_model(entry_completion, GTK_TREE_MODEL(completion_model)); gtk_entry_set_completion(GTK_ENTRY(priv->search_entry), entry_completion); gtk_entry_completion_set_match_func( entry_completion, (GtkEntryCompletionMatchFunc) completion_match_func, NULL, NULL); /* connect signal to when text is entered in the entry */ g_signal_connect(priv->search_entry, "changed", G_CALLBACK(search_entry_text_changed), win); g_signal_connect(entry_completion, "match-selected", G_CALLBACK(select_autocompletion), win); /* connect to incoming call and focus */ QObject::connect( &CallModel::instance(), &CallModel::incomingCall, [=](Call* call) { CallModel::instance().selectionModel()->setCurrentIndex( CallModel::instance().getIndex(call), QItemSelectionModel::ClearAndSelect); } ); /* react to digit key press events */ g_signal_connect(win, "key-press-event", G_CALLBACK(dtmf_pressed), NULL); /* set the search entry placeholder text */ gtk_entry_set_placeholder_text(GTK_ENTRY(priv->search_entry), C_("Please try to make the translation 50 chars or less so that it fits into the layout", "Search contacts or enter number")); }