From 6f2ceb1273ea7b9ccd20da9ea81c2ec7f0c1e2f6 Mon Sep 17 00:00:00 2001 From: Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com> Date: Wed, 18 Apr 2018 15:08:01 -0400 Subject: [PATCH] Refactoring of the accountContainer logic Before: - RingMainWindow has an unique_ptr to an AccountContainer accountContainer_. - each view / secondary class has its own *copy* of the account container pointer (given by ringmainwindow using accountContainer_.get()). - each time the reference to the struct Info is updated, accountContainer_ has to be reset()-ed and and the account container re-created by the RingMainWindow. This makes *all* copies of the account container pointer invalid (hence all view / secondary classes trying to access the account container before getting updated perform use-after-free / NULL pointer dereference). - These copies have to be manually updated ! (well, currently they are not updated at all) After: - RingMainWindow has a pointer to a struct Info from LRC. - Each view / secondary class has a pointer pointing to the struct Info pointer of RingMainWindow - Each time the reference to the struct Info is updated, the RingMainWindow updates its pointer. Since secondary classes and views hold a pointer to this pointer, they are automatically updated and there is no dangling pointer anymore. This requires no lrc side changes. Change-Id: I1329721920a3d42ad623f9fd7202b43700713eed Reviewed-by: Sebastien Blin <sebastien.blin@savoirfairelinux.com> Reviewed-by: Guillaume Roguez <guillaume.roguez@savoirfairelinux.com> --- CMakeLists.txt | 2 +- src/accountcontainer.h | 37 ------------- src/accountinfopointer.h | 20 +++++++ src/chatview.cpp | 62 +++++++++++----------- src/chatview.h | 5 +- src/conversationpopupmenu.cpp | 40 +++++++------- src/conversationpopupmenu.h | 6 ++- src/conversationsview.cpp | 51 +++++++++--------- src/conversationsview.h | 6 ++- src/currentcallview.cpp | 48 ++++++++--------- src/currentcallview.h | 5 +- src/incomingcallview.cpp | 26 +++++----- src/incomingcallview.h | 5 +- src/ringmainwindow.cpp | 98 +++++++++++++++++------------------ src/ringwelcomeview.cpp | 25 ++++----- src/ringwelcomeview.h | 8 +-- 16 files changed, 219 insertions(+), 225 deletions(-) delete mode 100644 src/accountcontainer.h create mode 100644 src/accountinfopointer.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 76974f58..6d309c0e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -339,7 +339,7 @@ SET( SRC_FILES src/conversationsview.cpp src/conversationpopupmenu.h src/conversationpopupmenu.cpp - src/accountcontainer.h + src/accountinfopointer.h ) # compile glib resource files to c code diff --git a/src/accountcontainer.h b/src/accountcontainer.h deleted file mode 100644 index 7daecaae..00000000 --- a/src/accountcontainer.h +++ /dev/null @@ -1,37 +0,0 @@ -/**************************************************************************** - * Copyright (C) 2017-2018 Savoir-faire Linux * - * Author: Nicolas Jäger <nicolas.jager@savoirfairelinux.com> * - * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Lesser General Public * - * License as published by the Free Software Foundation; either * - * version 2.1 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * - * Lesser General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program. If not, see <http://www.gnu.org/licenses/>. * - ***************************************************************************/ -#pragma once - -// Lrc -#include <api/account.h> - -/** - * This class contains a const reference linked to an account. - * NOTE: it avoids weird initialization with Gtk - * @param accInfo the account linked - */ -class AccountContainer { - -public: - explicit AccountContainer (const lrc::api::account::Info& accInfo) - : info(accInfo) - {} - - const lrc::api::account::Info& info; -}; diff --git a/src/accountinfopointer.h b/src/accountinfopointer.h new file mode 100644 index 00000000..1375fff6 --- /dev/null +++ b/src/accountinfopointer.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2018 Savoir-faire Linux Inc. + * Author: Hugo Lefeuvre <hugo.lefeuvre@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +typedef const lrc::api::account::Info* AccountInfoPointer; diff --git a/src/chatview.cpp b/src/chatview.cpp index f30a64cb..d36e759e 100644 --- a/src/chatview.cpp +++ b/src/chatview.cpp @@ -63,7 +63,7 @@ struct _ChatViewPrivate GSettings *settings; lrc::api::conversation::Info* conversation_; - AccountContainer* accountContainer_; + AccountInfoPointer const * accountInfo_; bool isTemporary_; QMetaObject::Connection new_interaction_connection; @@ -141,7 +141,7 @@ placecall_clicked(ChatView *self) { auto priv = CHAT_VIEW_GET_PRIVATE(self); if (!priv->conversation_) return; - priv->accountContainer_->info.conversationModel->placeCall(priv->conversation_->uid); + (*priv->accountInfo_)->conversationModel->placeCall(priv->conversation_->uid); } static void @@ -152,7 +152,7 @@ place_audio_call_clicked(ChatView *self) if (!priv->conversation_) return; - priv->accountContainer_->info.conversationModel->placeAudioOnlyCall(priv->conversation_->uid); + (*priv->accountInfo_)->conversationModel->placeAudioOnlyCall(priv->conversation_->uid); } static void @@ -160,7 +160,7 @@ button_add_to_conversations_clicked(ChatView *self) { auto priv = CHAT_VIEW_GET_PRIVATE(self); if (!priv->conversation_) return; - priv->accountContainer_->info.conversationModel->makePermanent(priv->conversation_->uid); + (*priv->accountInfo_)->conversationModel->makePermanent(priv->conversation_->uid); } static gchar* @@ -198,27 +198,27 @@ webkit_chat_container_script_dialog(G_GNUC_UNUSED GtkWidget* webview, gchar *int auto order = std::string(interaction); if (!priv->conversation_) return; if (order == "ACCEPT") { - priv->accountContainer_->info.conversationModel->makePermanent(priv->conversation_->uid); + (*priv->accountInfo_)->conversationModel->makePermanent(priv->conversation_->uid); } else if (order == "REFUSE") { - priv->accountContainer_->info.conversationModel->removeConversation(priv->conversation_->uid); + (*priv->accountInfo_)->conversationModel->removeConversation(priv->conversation_->uid); } else if (order == "BLOCK") { - priv->accountContainer_->info.conversationModel->removeConversation(priv->conversation_->uid, true); + (*priv->accountInfo_)->conversationModel->removeConversation(priv->conversation_->uid, true); } else if (order.find("SEND:") == 0) { // Get text body auto toSend = order.substr(std::string("SEND:").size()); - priv->accountContainer_->info.conversationModel->sendMessage(priv->conversation_->uid, toSend); + (*priv->accountInfo_)->conversationModel->sendMessage(priv->conversation_->uid, toSend); } else if (order.find("SEND_FILE") == 0) { - if (auto model = priv->accountContainer_->info.conversationModel.get()) { + if (auto model = (*priv->accountInfo_)->conversationModel.get()) { if (auto filename = file_to_manipulate(GTK_WINDOW(gtk_widget_get_toplevel(GTK_WIDGET(self))), true)) model->sendFile(priv->conversation_->uid, filename, g_path_get_basename(filename)); } } else if (order.find("ACCEPT_FILE:") == 0) { - if (auto model = priv->accountContainer_->info.conversationModel.get()) { + if (auto model = (*priv->accountInfo_)->conversationModel.get()) { try { auto interactionId = std::stoull(order.substr(std::string("ACCEPT_FILE:").size())); lrc::api::datatransfer::Info info = {}; - priv->accountContainer_->info.conversationModel->getTransferInfo(interactionId, info); + (*priv->accountInfo_)->conversationModel->getTransferInfo(interactionId, info); // get prefered directory destination. auto* download_directory_variant = g_settings_get_value(priv->settings, "download-folder"); @@ -240,7 +240,7 @@ webkit_chat_container_script_dialog(G_GNUC_UNUSED GtkWidget* webview, gchar *int } } } else if (order.find("REFUSE_FILE:") == 0) { - if (auto model = priv->accountContainer_->info.conversationModel.get()) { + if (auto model = (*priv->accountInfo_)->conversationModel.get()) { try { auto interactionId = std::stoull(order.substr(std::string("REFUSE_FILE:").size())); model->cancelTransfer(priv->conversation_->uid, interactionId); @@ -320,11 +320,11 @@ print_interaction_to_buffer(ChatView* self, uint64_t interactionId, const lrc::a if (!priv->conversation_) return; if (interaction.status == lrc::api::interaction::Status::UNREAD) - priv->accountContainer_->info.conversationModel->setInteractionRead(priv->conversation_->uid, interactionId); + (*priv->accountInfo_)->conversationModel->setInteractionRead(priv->conversation_->uid, interactionId); webkit_chat_container_print_new_interaction( WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), - *priv->accountContainer_->info.conversationModel, + *(*priv->accountInfo_)->conversationModel, interactionId, interaction ); @@ -336,7 +336,7 @@ update_interaction(ChatView* self, uint64_t interactionId, const lrc::api::inter ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self); webkit_chat_container_update_interaction( WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), - *priv->accountContainer_->info.conversationModel, + *(*priv->accountInfo_)->conversationModel, interactionId, interaction ); @@ -352,11 +352,11 @@ load_participants_images(ChatView *self) if (!priv->conversation_) return; auto contactUri = priv->conversation_->participants.front(); try{ - auto& contact = priv->accountContainer_->info.contactModel->getContact(contactUri); + auto& contact = (*priv->accountInfo_)->contactModel->getContact(contactUri); if (!contact.profileInfo.avatar.empty()) { webkit_chat_container_set_sender_image( WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), - priv->accountContainer_->info.contactModel->getContactProfileId(contactUri), + (*priv->accountInfo_)->contactModel->getContactProfileId(contactUri), contact.profileInfo.avatar ); } @@ -365,11 +365,11 @@ load_participants_images(ChatView *self) } // For this account - if (!priv->accountContainer_->info.profileInfo.avatar.empty()) { + if (!(*priv->accountInfo_)->profileInfo.avatar.empty()) { webkit_chat_container_set_sender_image( WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), - priv->accountContainer_->info.contactModel->getContactProfileId(priv->accountContainer_->info.profileInfo.uri), - priv->accountContainer_->info.profileInfo.avatar + (*priv->accountInfo_)->contactModel->getContactProfileId((*priv->accountInfo_)->profileInfo.uri), + (*priv->accountInfo_)->profileInfo.avatar ); } } @@ -384,12 +384,12 @@ print_text_recording(ChatView *self) if (!priv->conversation_) return; for (const auto& it: priv->conversation_->interactions) { if (it.second.status == lrc::api::interaction::Status::UNREAD) - priv->accountContainer_->info.conversationModel->setInteractionRead(priv->conversation_->uid, it.first); + (*priv->accountInfo_)->conversationModel->setInteractionRead(priv->conversation_->uid, it.first); } webkit_chat_container_print_history( WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), - *priv->accountContainer_->info.conversationModel, + *(*priv->accountInfo_)->conversationModel, priv->conversation_->interactions ); @@ -404,7 +404,7 @@ update_add_to_conversations(ChatView *self) if (!priv->conversation_) return; auto participant = priv->conversation_->participants[0]; try { - auto contactInfo = priv->accountContainer_->info.contactModel->getContact(participant); + auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(participant); if(contactInfo.profileInfo.type != lrc::api::profile::Type::TEMPORARY && contactInfo.profileInfo.type != lrc::api::profile::Type::PENDING) gtk_widget_hide(priv->button_add_to_conversations); @@ -421,7 +421,7 @@ update_contact_methods(ChatView *self) if (!priv->conversation_) return; auto contactUri = priv->conversation_->participants.front(); try { - auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri); + auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(contactUri); auto bestId = std::string(contactInfo.registeredName).empty() ? contactInfo.profileInfo.uri : contactInfo.registeredName; if (contactInfo.profileInfo.alias == bestId) { gtk_widget_hide(priv->label_cm); @@ -442,7 +442,7 @@ update_name(ChatView *self) if (!priv->conversation_) return; auto contactUri = priv->conversation_->participants.front(); try { - auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri); + auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(contactUri); auto alias = contactInfo.profileInfo.alias; alias.erase(std::remove(alias.begin(), alias.end(), '\r'), alias.end()); gtk_label_set_text(GTK_LABEL(priv->label_peer), alias.c_str()); @@ -468,7 +468,7 @@ webkit_chat_container_ready(ChatView* self) load_participants_images(self); priv->new_interaction_connection = QObject::connect( - &*priv->accountContainer_->info.conversationModel, &lrc::api::ConversationModel::newInteraction, + &*(*priv->accountInfo_)->conversationModel, &lrc::api::ConversationModel::newInteraction, [self, priv](const std::string& uid, uint64_t interactionId, lrc::api::interaction::Info interaction) { if (!priv->conversation_) return; if(uid == priv->conversation_->uid) { @@ -477,7 +477,7 @@ webkit_chat_container_ready(ChatView* self) }); priv->update_interaction_connection = QObject::connect( - &*priv->accountContainer_->info.conversationModel, &lrc::api::ConversationModel::interactionStatusUpdated, + &*(*priv->accountInfo_)->conversationModel, &lrc::api::ConversationModel::interactionStatusUpdated, [self, priv](const std::string& uid, uint64_t msgId, lrc::api::interaction::Info msg) { if (!priv->conversation_) return; if(uid == priv->conversation_->uid) { @@ -488,7 +488,7 @@ webkit_chat_container_ready(ChatView* self) if (!priv->conversation_) return; auto contactUri = priv->conversation_->participants.front(); try { - auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri); + auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(contactUri); priv->isTemporary_ = contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY || contactInfo.profileInfo.type == lrc::api::profile::Type::PENDING; webkit_chat_container_set_temporary(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), priv->isTemporary_); @@ -542,7 +542,7 @@ build_chat_view(ChatView* self) GtkWidget * chat_view_new (WebKitChatContainer* webkit_chat_container, - AccountContainer* accountContainer, + AccountInfoPointer const & accountInfo, lrc::api::conversation::Info* conversation) { ChatView *self = CHAT_VIEW(g_object_new(CHAT_VIEW_TYPE, NULL)); @@ -550,7 +550,7 @@ chat_view_new (WebKitChatContainer* webkit_chat_container, ChatViewPrivate *priv = CHAT_VIEW_GET_PRIVATE(self); priv->webkit_chat_container = GTK_WIDGET(webkit_chat_container); priv->conversation_ = conversation; - priv->accountContainer_ = accountContainer; + priv->accountInfo_ = &accountInfo; build_chat_view(self); return (GtkWidget *)self; @@ -570,7 +570,7 @@ chat_view_update_temporary(ChatView* self, bool showAddButton, bool showInvitati if (!priv->conversation_) return; auto contactUri = priv->conversation_->participants.front(); try { - auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri); + auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(contactUri); auto bestName = contactInfo.profileInfo.alias; if (bestName.empty()) bestName = contactInfo.registeredName; diff --git a/src/chatview.h b/src/chatview.h index 8ab8ccfe..85fb16cc 100644 --- a/src/chatview.h +++ b/src/chatview.h @@ -25,8 +25,9 @@ #include <gtk/gtk.h> // Client related -#include "accountcontainer.h" +#include "api/account.h" #include "webkitchatcontainer.h" +#include "accountinfopointer.h" namespace lrc { @@ -52,7 +53,7 @@ typedef struct _ChatViewClass ChatViewClass; GType chat_view_get_type (void) G_GNUC_CONST; GtkWidget *chat_view_new (WebKitChatContainer* view, - AccountContainer* accountContainer, + AccountInfoPointer const & accountInfo, lrc::api::conversation::Info* conversation); lrc::api::conversation::Info chat_view_get_conversation(ChatView*); bool chat_view_get_temporary(ChatView*); diff --git a/src/conversationpopupmenu.cpp b/src/conversationpopupmenu.cpp index ea404ac3..5434748b 100644 --- a/src/conversationpopupmenu.cpp +++ b/src/conversationpopupmenu.cpp @@ -27,6 +27,8 @@ #include <api/contactmodel.h> #include <api/contact.h> +#include "accountinfopointer.h" + struct _ConversationPopupMenu { GtkMenu parent; @@ -43,7 +45,7 @@ struct _ConversationPopupMenuPrivate { GtkTreeView *treeview; - AccountContainer* accountContainer_; + AccountInfoPointer const *accountInfo_; int row_; }; @@ -56,9 +58,9 @@ copy_contact_info(G_GNUC_UNUSED GtkWidget *menu, ConversationPopupMenuPrivate* p { try { - auto conversation = priv->accountContainer_->info.conversationModel->filteredConversation(priv->row_); + auto conversation = (*priv->accountInfo_)->conversationModel->filteredConversation(priv->row_); if (conversation.participants.empty()) return; - auto& contact = priv->accountContainer_->info.contactModel->getContact(conversation.participants.front()); + auto& contact = (*priv->accountInfo_)->contactModel->getContact(conversation.participants.front()); auto bestName = contact.registeredName.empty() ? contact.profileInfo.uri : contact.registeredName; auto text = (gchar *)bestName.c_str(); GtkClipboard* clip = gtk_clipboard_get(GDK_SELECTION_CLIPBOARD); @@ -77,8 +79,8 @@ remove_history_conversation(G_GNUC_UNUSED GtkWidget *menu, ConversationPopupMenu { try { - auto conversation = priv->accountContainer_->info.conversationModel->filteredConversation(priv->row_); - priv->accountContainer_->info.conversationModel->clearHistory(conversation.uid); + auto conversation = (*priv->accountInfo_)->conversationModel->filteredConversation(priv->row_); + (*priv->accountInfo_)->conversationModel->clearHistory(conversation.uid); } catch (...) { @@ -91,8 +93,8 @@ remove_conversation(G_GNUC_UNUSED GtkWidget *menu, ConversationPopupMenuPrivate* { try { - auto conversationUid = priv->accountContainer_->info.conversationModel->filteredConversation(priv->row_).uid; - priv->accountContainer_->info.conversationModel->removeConversation(conversationUid); + auto conversationUid = (*priv->accountInfo_)->conversationModel->filteredConversation(priv->row_).uid; + (*priv->accountInfo_)->conversationModel->removeConversation(conversationUid); } catch (...) { @@ -105,8 +107,8 @@ block_conversation(G_GNUC_UNUSED GtkWidget *menu, ConversationPopupMenuPrivate* { try { - auto conversationUid = priv->accountContainer_->info.conversationModel->filteredConversation(priv->row_).uid; - priv->accountContainer_->info.conversationModel->removeConversation(conversationUid, true); + auto conversationUid = (*priv->accountInfo_)->conversationModel->filteredConversation(priv->row_).uid; + (*priv->accountInfo_)->conversationModel->removeConversation(conversationUid, true); } catch (...) { @@ -119,8 +121,8 @@ add_conversation(G_GNUC_UNUSED GtkWidget *menu, ConversationPopupMenuPrivate* pr { try { - auto conversation = priv->accountContainer_->info.conversationModel->filteredConversation(priv->row_); - priv->accountContainer_->info.conversationModel->makePermanent(conversation.uid); + auto conversation = (*priv->accountInfo_)->conversationModel->filteredConversation(priv->row_); + (*priv->accountInfo_)->conversationModel->makePermanent(conversation.uid); } catch (...) { @@ -133,8 +135,8 @@ place_video_call(G_GNUC_UNUSED GtkWidget *menu, ConversationPopupMenuPrivate* pr { try { - auto conversation = priv->accountContainer_->info.conversationModel->filteredConversation(priv->row_); - priv->accountContainer_->info.conversationModel->placeCall(conversation.uid); + auto conversation = (*priv->accountInfo_)->conversationModel->filteredConversation(priv->row_); + (*priv->accountInfo_)->conversationModel->placeCall(conversation.uid); } catch (...) { g_warning("Can't get conversation at row %i", priv->row_); } @@ -145,8 +147,8 @@ place_audio_call(G_GNUC_UNUSED GtkWidget *menu, ConversationPopupMenuPrivate* pr { try { - auto conversation = priv->accountContainer_->info.conversationModel->filteredConversation(priv->row_); - priv->accountContainer_->info.conversationModel->placeAudioOnlyCall(conversation.uid); + auto conversation = (*priv->accountInfo_)->conversationModel->filteredConversation(priv->row_); + (*priv->accountInfo_)->conversationModel->placeAudioOnlyCall(conversation.uid); } catch (...) { g_warning("Can't get conversation at row %i", priv->row_); } @@ -168,10 +170,10 @@ update(GtkTreeSelection *selection, ConversationPopupMenu *self) if (!gtk_tree_selection_get_selected(selection, &model, &iter)) return; auto path = gtk_tree_model_get_path(model, &iter); auto idx = gtk_tree_path_get_indices(path); - auto conversation = priv->accountContainer_->info.conversationModel->filteredConversation(idx[0]); + auto conversation = (*priv->accountInfo_)->conversationModel->filteredConversation(idx[0]); priv->row_ = idx[0]; try { - auto contactInfo = priv->accountContainer_->info.contactModel->getContact(conversation.participants.front()); + auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(conversation.participants.front()); if (contactInfo.profileInfo.uri.empty()) return; // we always build a menu, however in some cases some or all of the conversations will be deactivated @@ -248,11 +250,11 @@ conversation_popup_menu_init(G_GNUC_UNUSED ConversationPopupMenu *self) } GtkWidget * -conversation_popup_menu_new (GtkTreeView *treeview, AccountContainer* accountContainer) +conversation_popup_menu_new (GtkTreeView *treeview, AccountInfoPointer const & accountInfo) { gpointer self = g_object_new(CONVERSATION_POPUP_MENU_TYPE, NULL); ConversationPopupMenuPrivate *priv = CONVERSATION_POPUP_MENU_GET_PRIVATE(self); - priv->accountContainer_ = accountContainer; + priv->accountInfo_ = &accountInfo; priv->treeview = treeview; GtkTreeSelection *selection = gtk_tree_view_get_selection(priv->treeview); diff --git a/src/conversationpopupmenu.h b/src/conversationpopupmenu.h index 7f23631a..398451db 100644 --- a/src/conversationpopupmenu.h +++ b/src/conversationpopupmenu.h @@ -22,7 +22,9 @@ #include <gtk/gtk.h> // LRC -#include "accountcontainer.h" +#include "api/account.h" + +#include "accountinfopointer.h" G_BEGIN_DECLS @@ -36,7 +38,7 @@ typedef struct _ConversationPopupMenu ConversationPopupMenu; typedef struct _ConversationPopupMenuClass ConversationPopupMenuClass; GType conversation_popup_menu_get_type (void) G_GNUC_CONST; -GtkWidget *conversation_popup_menu_new (GtkTreeView *treeview, AccountContainer* accountContainer); +GtkWidget *conversation_popup_menu_new (GtkTreeView *treeview, AccountInfoPointer const & accountInfo); gboolean conversation_popup_menu_show (ConversationPopupMenu *self, GdkEventButton *event); G_END_DECLS diff --git a/src/conversationsview.cpp b/src/conversationsview.cpp index 879a8664..2089da88 100644 --- a/src/conversationsview.cpp +++ b/src/conversationsview.cpp @@ -37,7 +37,6 @@ #include "native/pixbufmanipulator.h" #include "conversationpopupmenu.h" - static constexpr const char* CALL_TARGET = "CALL_TARGET"; static constexpr int CALL_TARGET_ID = 0; @@ -55,7 +54,7 @@ typedef struct _ConversationsViewPrivate ConversationsViewPrivate; struct _ConversationsViewPrivate { - AccountContainer* accountContainer_; + AccountInfoPointer const *accountInfo_; GtkWidget* popupMenu_; @@ -88,12 +87,12 @@ render_contact_photo(G_GNUC_UNUSED GtkTreeViewColumn *tree_column, { // Draw first contact. // NOTE: We just draw the first contact, must change this for conferences when they will have their own object - auto conversationInfo = priv->accountContainer_->info.conversationModel->filteredConversation(row); - auto contactInfo = priv->accountContainer_->info.contactModel->getContact(conversationInfo.participants.front()); + auto conversationInfo = (*priv->accountInfo_)->conversationModel->filteredConversation(row); + auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(conversationInfo.participants.front()); std::shared_ptr<GdkPixbuf> image; auto var_photo = GlobalInstances::pixmapManipulator().conversationPhoto( conversationInfo, - priv->accountContainer_->info, + **(priv->accountInfo_), QSize(50, 50), contactInfo.isPresent ); @@ -185,10 +184,10 @@ render_time(G_GNUC_UNUSED GtkTreeViewColumn *tree_column, try { - auto conversation = priv->accountContainer_->info.conversationModel->filteredConversation(row); + auto conversation = (*priv->accountInfo_)->conversationModel->filteredConversation(row); auto callId = conversation.confId.empty() ? conversation.callId : conversation.confId; if (!callId.empty()) { - auto call = priv->accountContainer_->info.callModel->getCall(callId); + auto call = (*priv->accountInfo_)->callModel->getCall(callId); text = g_markup_printf_escaped("%s", lrc::api::call::to_string(call.status).c_str() ); @@ -242,9 +241,9 @@ update_conversation(ConversationsView *self, const std::string& uid) { -1); if(std::string(ringId) == uid) { // Get informations - auto conversation = priv->accountContainer_->info.conversationModel->filteredConversation(idx); + auto conversation = (*priv->accountInfo_)->conversationModel->filteredConversation(idx); auto contactUri = conversation.participants.front(); - auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri); + auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(contactUri); auto lastMessage = conversation.interactions.empty() ? "" : conversation.interactions.at(conversation.lastMessageUid).body; std::replace(lastMessage.begin(), lastMessage.end(), '\n', ' '); @@ -282,11 +281,15 @@ create_and_fill_model(ConversationsView *self) if(!priv) GTK_TREE_MODEL (store); GtkTreeIter iter; - for (auto conversation : priv->accountContainer_->info.conversationModel->allFilteredConversations()) { - if (conversation.participants.empty()) break; // Should not + for (auto conversation : (*priv->accountInfo_)->conversationModel->allFilteredConversations()) { + if (conversation.participants.empty()) { + g_debug("Found conversation with empty list of participants - most likely the result of earlier bug."); + break; + } + auto contactUri = conversation.participants.front(); try { - auto contactInfo = priv->accountContainer_->info.contactModel->getContact(contactUri); + auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(contactUri); auto lastMessage = conversation.interactions.empty() ? "" : conversation.interactions.at(conversation.lastMessageUid).body; std::replace(lastMessage.begin(), lastMessage.end(), '\n', ' '); @@ -319,8 +322,8 @@ call_conversation(GtkTreeView *self, if (row == -1) return; auto priv = CONVERSATIONS_VIEW_GET_PRIVATE(self); if (!priv) return; - auto conversation = priv->accountContainer_->info.conversationModel->filteredConversation(row); - priv->accountContainer_->info.conversationModel->placeCall(conversation.uid); + auto conversation = (*priv->accountInfo_)->conversationModel->filteredConversation(row); + (*priv->accountInfo_)->conversationModel->placeCall(conversation.uid); } static void @@ -334,7 +337,7 @@ select_conversation(GtkTreeSelection *selection, ConversationsView *self) // Destroy the not up to date menu. gtk_widget_hide(priv->popupMenu_); gtk_widget_destroy(priv->popupMenu_); - priv->popupMenu_ = conversation_popup_menu_new(GTK_TREE_VIEW(self), priv->accountContainer_); + priv->popupMenu_ = conversation_popup_menu_new(GTK_TREE_VIEW(self), *priv->accountInfo_); auto children = gtk_container_get_children (GTK_CONTAINER(priv->popupMenu_)); auto nbItems = g_list_length(children); // Show the new popupMenu_ should be visible @@ -350,7 +353,7 @@ select_conversation(GtkTreeSelection *selection, ConversationsView *self) gtk_tree_model_get(model, &iter, 0, &conversationUid, -1); - priv->accountContainer_->info.conversationModel->selectConversation(std::string(conversationUid)); + (*priv->accountInfo_)->conversationModel->selectConversation(std::string(conversationUid)); } static void @@ -500,7 +503,7 @@ on_drag_data_received(GtkWidget *treeview, 0, &conversationUidDest, -1); - priv->accountContainer_->info.conversationModel->joinConversations( + (*priv->accountInfo_)->conversationModel->joinConversations( conversationUidSrc, conversationUidDest ); @@ -566,7 +569,7 @@ build_conversations_view(ConversationsView *self) // This view should be synchronized and redraw at each update. priv->modelSortedConnection_ = QObject::connect( - &*priv->accountContainer_->info.conversationModel, + &*(*priv->accountInfo_)->conversationModel, &lrc::api::ConversationModel::modelSorted, [self] () { auto model = create_and_fill_model(self); @@ -575,14 +578,14 @@ build_conversations_view(ConversationsView *self) GTK_TREE_MODEL(model)); }); priv->conversationUpdatedConnection_ = QObject::connect( - &*priv->accountContainer_->info.conversationModel, + &*(*priv->accountInfo_)->conversationModel, &lrc::api::ConversationModel::conversationUpdated, [self] (const std::string& uid) { update_conversation(self, uid); }); priv->filterChangedConnection_ = QObject::connect( - &*priv->accountContainer_->info.conversationModel, + &*(*priv->accountInfo_)->conversationModel, &lrc::api::ConversationModel::filterChanged, [self] () { auto model = create_and_fill_model(self); @@ -599,7 +602,7 @@ build_conversations_view(ConversationsView *self) // Two clicks to placeCall g_signal_connect(self, "row-activated", G_CALLBACK(call_conversation), NULL); - priv->popupMenu_ = conversation_popup_menu_new(GTK_TREE_VIEW(self), priv->accountContainer_); + priv->popupMenu_ = conversation_popup_menu_new(GTK_TREE_VIEW(self), *priv->accountInfo_); // Right click to show actions g_signal_connect_swapped(self, "button-press-event", G_CALLBACK(show_popup_menu), self); @@ -651,14 +654,14 @@ conversations_view_class_init(ConversationsViewClass *klass) } GtkWidget * -conversations_view_new(AccountContainer* accountContainer) +conversations_view_new(AccountInfoPointer const & accountInfo) { auto self = CONVERSATIONS_VIEW(g_object_new(CONVERSATIONS_VIEW_TYPE, NULL)); auto priv = CONVERSATIONS_VIEW_GET_PRIVATE(self); - priv->accountContainer_ = accountContainer; + priv->accountInfo_ = &accountInfo; - if (priv->accountContainer_) + if (*priv->accountInfo_) build_conversations_view(self); return (GtkWidget *)self; diff --git a/src/conversationsview.h b/src/conversationsview.h index 9a39addd..2dc85a0d 100644 --- a/src/conversationsview.h +++ b/src/conversationsview.h @@ -20,7 +20,9 @@ #include <gtk/gtk.h> -#include "accountcontainer.h" +#include "api/account.h" + +#include "accountinfopointer.h" G_BEGIN_DECLS @@ -34,7 +36,7 @@ typedef struct _ConversationsView ConversationsView; typedef struct _ConversationsViewClass ConversationsViewClass; GType conversations_view_get_type (void) G_GNUC_CONST; -GtkWidget *conversations_view_new (AccountContainer* accountContainer); +GtkWidget *conversations_view_new (AccountInfoPointer const & accountInfo); void conversations_view_select_conversation (ConversationsView *self, const std::string& uid); G_END_DECLS diff --git a/src/currentcallview.cpp b/src/currentcallview.cpp index 73163025..dbf41108 100644 --- a/src/currentcallview.cpp +++ b/src/currentcallview.cpp @@ -232,7 +232,7 @@ public: void init(); void setup(WebKitChatContainer* chat_widget, - AccountContainer* accountContainer, + AccountInfoPointer const & account_info, lrc::api::conversation::Info* conversation); void insertControls(); @@ -242,7 +242,7 @@ public: CurrentCallViewPrivate* widgets = nullptr; lrc::api::conversation::Info* conversation = nullptr; - AccountContainer* accountContainer = nullptr; + AccountInfoPointer const *accountInfo = nullptr; QMetaObject::Connection state_change_connection; QMetaObject::Connection local_renderer_connection; @@ -328,7 +328,7 @@ on_button_hangup_clicked(CurrentCallView* view) auto callToHangUp = priv->cpp->conversation->callId; if (!priv->cpp->conversation->confId.empty()) callToHangUp = priv->cpp->conversation->confId; - priv->cpp->accountContainer->info.callModel->hangUp(callToHangUp); + (*priv->cpp->accountInfo)->callModel->hangUp(callToHangUp); } static void @@ -340,7 +340,7 @@ on_togglebutton_hold_clicked(CurrentCallView* view) auto callToHold = priv->cpp->conversation->callId; if (!priv->cpp->conversation->confId.empty()) callToHold = priv->cpp->conversation->confId; - priv->cpp->accountContainer->info.callModel->togglePause(callToHold); + (*priv->cpp->accountInfo)->callModel->togglePause(callToHold); } static void @@ -352,7 +352,7 @@ on_togglebutton_record_clicked(CurrentCallView* view) auto callToRecord = priv->cpp->conversation->callId; if (!priv->cpp->conversation->confId.empty()) callToRecord = priv->cpp->conversation->confId; - priv->cpp->accountContainer->info.callModel->toggleAudioRecord(callToRecord); + (*priv->cpp->accountInfo)->callModel->toggleAudioRecord(callToRecord); } static void @@ -365,7 +365,7 @@ on_togglebutton_muteaudio_clicked(CurrentCallView* view) if (!priv->cpp->conversation->confId.empty()) callToMute = priv->cpp->conversation->confId; //auto muteAudioBtn = GTK_TOGGLE_BUTTON(priv->togglebutton_muteaudio); - priv->cpp->accountContainer->info.callModel->toggleMedia(callToMute, + (*priv->cpp->accountInfo)->callModel->toggleMedia(callToMute, lrc::api::NewCallModel::Media::AUDIO); auto togglebutton = GTK_TOGGLE_BUTTON(priv->togglebutton_muteaudio); @@ -385,7 +385,7 @@ on_togglebutton_mutevideo_clicked(CurrentCallView* view) if (!priv->cpp->conversation->confId.empty()) callToMute = priv->cpp->conversation->confId; //auto muteVideoBtn = GTK_TOGGLE_BUTTON(priv->togglebutton_mutevideo); - priv->cpp->accountContainer->info.callModel->toggleMedia(callToMute, + (*priv->cpp->accountInfo)->callModel->toggleMedia(callToMute, lrc::api::NewCallModel::Media::VIDEO); auto togglebutton = GTK_TOGGLE_BUTTON(priv->togglebutton_mutevideo); @@ -439,7 +439,7 @@ on_autoquality_toggled(GtkToggleButton* button, CurrentCallView* view) auto callToRender = priv->cpp->conversation->callId; if (!priv->cpp->conversation->confId.empty()) callToRender = priv->cpp->conversation->confId; - auto renderer = priv->cpp->accountContainer->info.callModel->getRenderer(callToRender); + auto renderer = (*priv->cpp->accountInfo)->callModel->getRenderer(callToRender); for (auto* activeCall: CallModel::instance().getActiveCalls()) { if (activeCall and activeCall->videoRenderer() == renderer) set_call_quality(*activeCall, auto_quality_on, desired_quality); @@ -462,7 +462,7 @@ on_quality_changed(G_GNUC_UNUSED GtkScaleButton *button, G_GNUC_UNUSED gdouble v auto callToRender = priv->cpp->conversation->callId; if (!priv->cpp->conversation->confId.empty()) callToRender = priv->cpp->conversation->confId; - auto renderer = priv->cpp->accountContainer->info.callModel->getRenderer(callToRender); + auto renderer = (*priv->cpp->accountInfo)->callModel->getRenderer(callToRender); for (auto* activeCall: CallModel::instance().getActiveCalls()) if (activeCall and activeCall->videoRenderer() == renderer) set_call_quality(*activeCall, false, gtk_scale_button_get_value(button)); @@ -598,12 +598,12 @@ CppImpl::init() void CppImpl::setup(WebKitChatContainer* chat_widget, - AccountContainer* account_container, + AccountInfoPointer const & account_info, lrc::api::conversation::Info* conv_info) { widgets->webkit_chat_container = GTK_WIDGET(chat_widget); conversation = conv_info; - accountContainer = account_container; + accountInfo = &account_info; setCallInfo(); } @@ -623,7 +623,7 @@ CppImpl::setCallInfo() if (!conversation->confId.empty()) callToRender = conversation->confId; video_widget_push_new_renderer(VIDEO_WIDGET(widgets->video_widget), - accountContainer->info.callModel->getRenderer(callToRender), + (*accountInfo)->callModel->getRenderer(callToRender), VIDEO_RENDERER_REMOTE); // local renderer @@ -650,7 +650,7 @@ CppImpl::setCallInfo() ); remote_renderer_connection = QObject::connect( - &*accountContainer->info.callModel, + &*(*accountInfo)->callModel, &lrc::api::NewCallModel::remotePreviewStarted, [this] (const std::string& callId, Video::Renderer* renderer) { if (conversation->callId == callId) { @@ -661,7 +661,7 @@ CppImpl::setCallInfo() }); state_change_connection = QObject::connect( - &*accountContainer->info.callModel, + &*(*accountInfo)->callModel, &lrc::api::NewCallModel::callStatusChanged, [this] (const std::string& callId) { if (callId == conversation->callId) { @@ -671,7 +671,7 @@ CppImpl::setCallInfo() }); new_message_connection = QObject::connect( - &*accountContainer->info.conversationModel, + &*(*accountInfo)->conversationModel, &lrc::api::ConversationModel::newInteraction, [this] (const std::string& uid, uint64_t msgId, lrc::api::interaction::Info msg) { Q_UNUSED(uid) @@ -694,7 +694,7 @@ CppImpl::setCallInfo() // init chat view widgets->chat_view = chat_view_new(WEBKIT_CHAT_CONTAINER(widgets->webkit_chat_container), - accountContainer, conversation); + *accountInfo, conversation); gtk_container_add(GTK_CONTAINER(widgets->frame_chat), widgets->chat_view); g_signal_connect_swapped(widgets->chat_view, "new-interactions-displayed", @@ -792,7 +792,7 @@ CppImpl::insertControls() auto callToRender = conversation->callId; if (!conversation->confId.empty()) callToRender = conversation->confId; - auto renderer = accountContainer->info.callModel->getRenderer(callToRender); + auto renderer = (*accountInfo)->callModel->getRenderer(callToRender); for (auto* activeCall: CallModel::instance().getActiveCalls()) if (activeCall and activeCall->videoRenderer() == renderer) { g_signal_connect(widgets->video_widget, "drag-data-received", @@ -837,9 +837,9 @@ CppImpl::updateDetails() callRendered = conversation->confId; gtk_label_set_text(GTK_LABEL(widgets->label_duration), - accountContainer->info.callModel->getFormattedCallDuration(callRendered).c_str()); + (*accountInfo)->callModel->getFormattedCallDuration(callRendered).c_str()); - auto call = accountContainer->info.callModel->getCall(callRendered); + auto call = (*accountInfo)->callModel->getCall(callRendered); gtk_widget_set_sensitive(GTK_WIDGET(widgets->togglebutton_muteaudio), (call.type != lrc::api::call::Type::CONFERENCE)); gtk_widget_set_sensitive(GTK_WIDGET(widgets->togglebutton_mutevideo), @@ -854,7 +854,7 @@ CppImpl::updateState() auto callId = conversation->callId; try { - auto call = accountContainer->info.callModel->getCall(callId); + auto call = (*accountInfo)->callModel->getCall(callId); auto pauseBtn = GTK_TOGGLE_BUTTON(widgets->togglebutton_hold); auto image = gtk_image_new_from_resource ("/cx/ring/RingGnome/pause"); @@ -889,7 +889,7 @@ CppImpl::updateNameAndPhoto() { QVariant var_i = GlobalInstances::pixmapManipulator().conversationPhoto( *conversation, - accountContainer->info, + **(accountInfo), QSize(60, 60), false ); @@ -897,7 +897,7 @@ CppImpl::updateNameAndPhoto() gtk_image_set_from_pixbuf(GTK_IMAGE(widgets->image_peer), image.get()); try { - auto contactInfo = accountContainer->info.contactModel->getContact(conversation->participants.front()); + auto contactInfo = (*accountInfo)->contactModel->getContact(conversation->participants.front()); auto name = contactInfo.profileInfo.alias; gtk_label_set_text(GTK_LABEL(widgets->label_name), name.c_str()); @@ -1080,13 +1080,13 @@ current_call_view_class_init(CurrentCallViewClass *klass) GtkWidget * current_call_view_new(WebKitChatContainer* chat_widget, - AccountContainer* accountContainer, + AccountInfoPointer const & accountInfo, lrc::api::conversation::Info* conversation) { auto* self = g_object_new(CURRENT_CALL_VIEW_TYPE, NULL); auto* priv = CURRENT_CALL_VIEW_GET_PRIVATE(self); - priv->cpp->setup(chat_widget, accountContainer, conversation); + priv->cpp->setup(chat_widget, accountInfo, conversation); return GTK_WIDGET(self); } diff --git a/src/currentcallview.h b/src/currentcallview.h index 765ef7c0..85637de0 100644 --- a/src/currentcallview.h +++ b/src/currentcallview.h @@ -22,8 +22,9 @@ #pragma once #include <gtk/gtk.h> -#include "accountcontainer.h" +#include "api/account.h" #include "webkitchatcontainer.h" +#include "accountinfopointer.h" namespace lrc { @@ -50,7 +51,7 @@ typedef struct _CurrentCallViewClass CurrentCallViewClass; GType current_call_view_get_type (void) G_GNUC_CONST; GtkWidget *current_call_view_new (WebKitChatContainer* view, - AccountContainer* accountContainer, + AccountInfoPointer const & accountInfo, lrc::api::conversation::Info* conversation); lrc::api::conversation::Info current_call_view_get_conversation(CurrentCallView*); GtkWidget *current_call_view_get_chat_view(CurrentCallView*); diff --git a/src/incomingcallview.cpp b/src/incomingcallview.cpp index 0cfc5c32..cf8dcfbf 100644 --- a/src/incomingcallview.cpp +++ b/src/incomingcallview.cpp @@ -66,7 +66,7 @@ struct _IncomingCallViewPrivate GtkWidget *webkit_chat_container; lrc::api::conversation::Info* conversation_; - AccountContainer* accountContainer_; + AccountInfoPointer const * accountInfo_; QMetaObject::Connection state_change_connection; @@ -113,7 +113,7 @@ static void reject_incoming_call(G_GNUC_UNUSED GtkWidget *widget, ChatView *self) { auto priv = INCOMING_CALL_VIEW_GET_PRIVATE(self); - priv->accountContainer_->info.callModel->hangUp(priv->conversation_->callId); + (*priv->accountInfo_)->callModel->hangUp(priv->conversation_->callId); } static void @@ -122,12 +122,12 @@ accept_incoming_call(G_GNUC_UNUSED GtkWidget *widget, ChatView *self) auto priv = INCOMING_CALL_VIEW_GET_PRIVATE(self); auto contactUri = priv->conversation_->participants[0]; try { - auto contact = priv->accountContainer_->info.contactModel->getContact(contactUri); + auto contact = (*priv->accountInfo_)->contactModel->getContact(contactUri); // If the contact is pending, we should accept its request if (contact.profileInfo.type == lrc::api::profile::Type::PENDING) - priv->accountContainer_->info.conversationModel->makePermanent(priv->conversation_->uid); + (*priv->accountInfo_)->conversationModel->makePermanent(priv->conversation_->uid); // Accept call - priv->accountContainer_->info.callModel->accept(priv->conversation_->callId); + (*priv->accountInfo_)->callModel->accept(priv->conversation_->callId); } catch (const std::out_of_range&) { // ContactModel::getContact() exception } @@ -191,8 +191,8 @@ update_state(IncomingCallView *view) // change state label auto callId = priv->conversation_->callId; - if (!priv->accountContainer_->info.callModel->hasCall(callId)) return; - auto call = priv->accountContainer_->info.callModel->getCall(callId); + if (!(*priv->accountInfo_)->callModel->hasCall(callId)) return; + auto call = (*priv->accountInfo_)->callModel->getCall(callId); gchar *status = g_strdup_printf("%s", lrc::api::call::to_string(call.status).c_str()); gtk_label_set_text(GTK_LABEL(priv->label_status), status); @@ -214,7 +214,7 @@ update_name_and_photo(IncomingCallView *view) QVariant var_i = GlobalInstances::pixmapManipulator().conversationPhoto( *priv->conversation_, - priv->accountContainer_->info, + **(priv->accountInfo_), QSize(110, 110), false ); @@ -222,7 +222,7 @@ update_name_and_photo(IncomingCallView *view) gtk_image_set_from_pixbuf(GTK_IMAGE(priv->image_incoming), image.get()); try { - auto contactInfo = priv->accountContainer_->info.contactModel->getContact(priv->conversation_->participants.front()); + auto contactInfo = (*priv->accountInfo_)->contactModel->getContact(priv->conversation_->participants.front()); auto name = contactInfo.profileInfo.alias; gtk_label_set_text(GTK_LABEL(priv->label_name), name.c_str()); @@ -246,7 +246,7 @@ set_call_info(IncomingCallView *view) { // Update view if call state changes priv->state_change_connection = QObject::connect( - &*priv->accountContainer_->info.callModel, + &*(*priv->accountInfo_)->callModel, &lrc::api::NewCallModel::callStatusChanged, [view, priv] (const std::string& callId) { if (callId == priv->conversation_->callId) { @@ -256,7 +256,7 @@ set_call_info(IncomingCallView *view) { }); auto chat_view = chat_view_new(WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), - priv->accountContainer_, + *priv->accountInfo_, priv->conversation_); gtk_widget_show(chat_view); chat_view_set_header_visible(CHAT_VIEW(chat_view), FALSE); @@ -265,7 +265,7 @@ set_call_info(IncomingCallView *view) { GtkWidget * incoming_call_view_new(WebKitChatContainer* view, - AccountContainer* accountContainer, + AccountInfoPointer const & accountInfo, lrc::api::conversation::Info* conversation) { auto self = g_object_new(INCOMING_CALL_VIEW_TYPE, NULL); @@ -273,7 +273,7 @@ incoming_call_view_new(WebKitChatContainer* view, IncomingCallViewPrivate *priv = INCOMING_CALL_VIEW_GET_PRIVATE(self); priv->webkit_chat_container = GTK_WIDGET(view); priv->conversation_ = conversation; - priv->accountContainer_ = accountContainer; + priv->accountInfo_ = &accountInfo; set_call_info(INCOMING_CALL_VIEW(self)); diff --git a/src/incomingcallview.h b/src/incomingcallview.h index d33612f4..9214deed 100644 --- a/src/incomingcallview.h +++ b/src/incomingcallview.h @@ -25,8 +25,9 @@ #include <gtk/gtk.h> // client -#include "accountcontainer.h" +#include "api/account.h" #include "webkitchatcontainer.h" +#include "accountinfopointer.h" namespace lrc { @@ -53,7 +54,7 @@ typedef struct _IncomingCallViewClass IncomingCallViewClass; GType incoming_call_view_get_type (void) G_GNUC_CONST; GtkWidget *incoming_call_view_new (WebKitChatContainer* view, - AccountContainer* accountContainer, + AccountInfoPointer const & accountInfo, lrc::api::conversation::Info* conversation); lrc::api::conversation::Info incoming_call_view_get_conversation (IncomingCallView*); diff --git a/src/ringmainwindow.cpp b/src/ringmainwindow.cpp index b3f142ff..d78f77d3 100644 --- a/src/ringmainwindow.cpp +++ b/src/ringmainwindow.cpp @@ -36,7 +36,7 @@ #include <api/newaccountmodel.h> #include <api/newcallmodel.h> #include <api/behaviorcontroller.h> -#include "accountcontainer.h" +#include "api/account.h" #include <media/textrecording.h> #include <media/recordingmodel.h> #include <media/text.h> @@ -57,6 +57,7 @@ #include "utils/accounts.h" #include "utils/files.h" #include "ringnotify.h" +#include "accountinfopointer.h" //============================================================================== @@ -205,7 +206,7 @@ public: RingMainWindowPrivate* widgets = nullptr; std::unique_ptr<lrc::api::Lrc> lrc_; - std::unique_ptr<AccountContainer> accountContainer_; + AccountInfoPointer accountInfo_ = nullptr; std::unique_ptr<lrc::api::conversation::Info> chatViewConversation_; lrc::api::profile::Type currentTypeFilter_; bool show_settings = false; @@ -308,7 +309,7 @@ on_account_changed(RingMainWindow* self) gtk_tree_model_get(model, &iter, 0 /* col# */, &accountId /* data */, -1); priv->cpp->onAccountSelectionChange(accountId); gtk_notebook_set_show_tabs(GTK_NOTEBOOK(priv->notebook_contacts), - priv->cpp->accountContainer_->info.contactModel->hasPendingRequests()); + priv->cpp->accountInfo_->contactModel->hasPendingRequests()); g_free(accountId); } } @@ -375,7 +376,7 @@ on_search_entry_text_changed(GtkSearchEntry* search_entry, RingMainWindow* self) // Filter model const gchar *text = gtk_entry_get_text(GTK_ENTRY(search_entry)); - priv->cpp->accountContainer_->info.conversationModel->setFilter(text); + priv->cpp->accountInfo_->conversationModel->setFilter(text); } static void @@ -385,7 +386,7 @@ on_search_entry_activated(RingMainWindow* self) auto* priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(self)); // Select the first conversation of the list - auto& conversationModel = priv->cpp->accountContainer_->info.conversationModel; + auto& conversationModel = priv->cpp->accountInfo_->conversationModel; auto conversations = conversationModel->allFilteredConversations(); const gchar *text = gtk_entry_get_text(GTK_ENTRY(priv->search_entry)); @@ -402,7 +403,7 @@ on_search_entry_key_released(G_GNUC_UNUSED GtkEntry* search_entry, GdkEventKey* // if esc key pressed, clear the regex (keep the text, the user might not want to actually delete it) if (key->keyval == GDK_KEY_Escape) { - priv->cpp->accountContainer_->info.conversationModel->setFilter(""); + priv->cpp->accountInfo_->conversationModel->setFilter(""); return GDK_EVENT_STOP; } @@ -427,8 +428,8 @@ on_dtmf_pressed(RingMainWindow* self, GdkEventKey* event, gpointer user_data) if (GTK_IS_ENTRY(focus)) return GDK_EVENT_PROPAGATE; - if (priv->cpp->accountContainer_ && - priv->cpp->accountContainer_->info.profileInfo.type != lrc::api::profile::Type::SIP) + if (priv->cpp->accountInfo_ && + priv->cpp->accountInfo_->profileInfo.type != lrc::api::profile::Type::SIP) return GDK_EVENT_PROPAGATE; /* filter out cretain MOD masked key presses so that, for example, 'Ctrl+c' @@ -454,7 +455,7 @@ on_dtmf_pressed(RingMainWindow* self, GdkEventKey* event, gpointer user_data) guint32 unicode_val = gdk_keyval_to_unicode(event->keyval); QString val = QString::fromUcs4(&unicode_val, 1); g_debug("attemptingto play DTMF tone during ongoing call: %s", val.toUtf8().constData()); - priv->cpp->accountContainer_->info.callModel->playDTMF(current_item.callId, val.toStdString()); + priv->cpp->accountInfo_->callModel->playDTMF(current_item.callId, val.toStdString()); // always propogate the key, so we don't steal accelerators/shortcuts return GDK_EVENT_PROPAGATE; } @@ -468,10 +469,10 @@ on_tab_changed(GtkNotebook* notebook, GtkWidget* page, guint page_num, RingMainW g_return_if_fail(IS_RING_MAIN_WINDOW(self)); auto* priv = RING_MAIN_WINDOW_GET_PRIVATE(RING_MAIN_WINDOW(self)); - auto newType = page_num == 0 ? priv->cpp->accountContainer_->info.profileInfo.type : lrc::api::profile::Type::PENDING; + auto newType = page_num == 0 ? priv->cpp->accountInfo_->profileInfo.type : lrc::api::profile::Type::PENDING; if (priv->cpp->currentTypeFilter_ != newType) { priv->cpp->currentTypeFilter_ = newType; - priv->cpp->accountContainer_->info.conversationModel->setFilter(priv->cpp->currentTypeFilter_); + priv->cpp->accountInfo_->conversationModel->setFilter(priv->cpp->currentTypeFilter_); } } @@ -650,9 +651,9 @@ CppImpl::init() updateLrc(activeAccountId); } else { // No enabled account: create empty widgets - widgets->treeview_conversations = conversations_view_new(nullptr); + widgets->treeview_conversations = conversations_view_new(accountInfo_); gtk_container_add(GTK_CONTAINER(widgets->scrolled_window_smartview), widgets->treeview_conversations); - widgets->treeview_contact_requests = conversations_view_new(nullptr); + widgets->treeview_contact_requests = conversations_view_new(accountInfo_); gtk_container_add(GTK_CONTAINER(widgets->scrolled_window_contact_requests), widgets->treeview_contact_requests); } @@ -749,7 +750,7 @@ CppImpl::init() g_signal_connect(widgets->notebook_contacts, "switch-page", G_CALLBACK(on_tab_changed), self); /* welcome/default view */ - widgets->welcome_view = ring_welcome_view_new(accountContainer_.get()); + widgets->welcome_view = ring_welcome_view_new(accountInfo_); g_object_ref(widgets->welcome_view); // increase ref because don't want it to be destroyed when not displayed gtk_container_add(GTK_CONTAINER(widgets->frame_call), widgets->welcome_view); gtk_widget_show(widgets->welcome_view); @@ -811,12 +812,12 @@ CppImpl::init() // initialize the pending contact request icon. refreshPendingContactRequestTab(); - if (accountContainer_) { - auto& conversationModel = accountContainer_->info.conversationModel; + if (accountInfo_) { + auto& conversationModel = accountInfo_->conversationModel; auto conversations = conversationModel->allFilteredConversations(); for (const auto& conversation: conversations) { if (!conversation.callId.empty()) { - accountContainer_->info.conversationModel->selectConversation(conversation.uid); + accountInfo_->conversationModel->selectConversation(conversation.uid); } } } @@ -894,7 +895,7 @@ GtkWidget* CppImpl::displayIncomingView(lrc::api::conversation::Info conversation) { chatViewConversation_.reset(new lrc::api::conversation::Info(conversation)); - return incoming_call_view_new(webkitChatContainer(), accountContainer_.get(), chatViewConversation_.get()); + return incoming_call_view_new(webkitChatContainer(), accountInfo_, chatViewConversation_.get()); } GtkWidget* @@ -902,11 +903,11 @@ CppImpl::displayCurrentCallView(lrc::api::conversation::Info conversation) { chatViewConversation_.reset(new lrc::api::conversation::Info(conversation)); auto* new_view = current_call_view_new(webkitChatContainer(), - accountContainer_.get(), chatViewConversation_.get()); + accountInfo_, chatViewConversation_.get()); try { auto contactUri = chatViewConversation_->participants.front(); - auto contactInfo = accountContainer_->info.contactModel->getContact(contactUri); + auto contactInfo = accountInfo_->contactModel->getContact(contactUri); if (auto chat_view = current_call_view_get_chat_view(CURRENT_CALL_VIEW(new_view))) { auto isPending = contactInfo.profileInfo.type == lrc::api::profile::Type::PENDING; chat_view_update_temporary(CHAT_VIEW(chat_view), @@ -924,7 +925,7 @@ GtkWidget* CppImpl::displayChatView(lrc::api::conversation::Info conversation) { chatViewConversation_.reset(new lrc::api::conversation::Info(conversation)); - auto* new_view = chat_view_new(webkitChatContainer(), accountContainer_.get(), chatViewConversation_.get()); + auto* new_view = chat_view_new(webkitChatContainer(), accountInfo_, chatViewConversation_.get()); g_signal_connect_swapped(new_view, "hide-view-clicked", G_CALLBACK(on_hide_view_clicked), self); return new_view; } @@ -988,10 +989,10 @@ CppImpl::resetToWelcome() void CppImpl::refreshPendingContactRequestTab() { - if (not accountContainer_) + if (!accountInfo_) return; - auto hasPendingRequests = accountContainer_->info.contactModel->hasPendingRequests(); + auto hasPendingRequests = accountInfo_->contactModel->hasPendingRequests(); gtk_widget_set_visible(widgets->scrolled_window_contact_requests, hasPendingRequests); gtk_notebook_set_show_tabs(GTK_NOTEBOOK(widgets->notebook_contacts), hasPendingRequests); @@ -1093,7 +1094,7 @@ void CppImpl::changeAccountSelection(const std::string& id) { // already selected? - if (id == accountContainer_->info.id) + if (id == accountInfo_->id) return; if (auto* model = gtk_combo_box_get_model(GTK_COMBO_BOX(widgets->combobox_account_selector))) { @@ -1123,7 +1124,7 @@ CppImpl::onAccountSelectionChange(const std::string& id) // Show conversation panel gtk_notebook_set_current_page(GTK_NOTEBOOK(widgets->notebook_contacts), 0); // Update the welcome view - ring_welcome_update_view(RING_WELCOME_VIEW(widgets->welcome_view), accountContainer_.get()); + ring_welcome_update_view(RING_WELCOME_VIEW(widgets->welcome_view)); } void @@ -1185,7 +1186,7 @@ CppImpl::leaveSettingsView() * obsolete messages. It will also ensure to refresh last interaction printed in the conversations list. */ if (has_cleared_all_history) { - onAccountSelectionChange(accountContainer_->info.id); + onAccountSelectionChange(accountInfo_->id); resetToWelcome(); has_cleared_all_history = false; } @@ -1219,9 +1220,9 @@ CppImpl::updateLrc(const std::string& id, const std::string& accountIdToFlagFree // Get the account selected if (!id.empty()) - accountContainer_.reset(new AccountContainer(lrc_->getAccountModel().getAccountInfo(id))); + accountInfo_ = &lrc_->getAccountModel().getAccountInfo(id); else - accountContainer_.reset(); + accountInfo_ = nullptr; // Reinit tree views if (widgets->treeview_conversations) { @@ -1229,7 +1230,7 @@ CppImpl::updateLrc(const std::string& id, const std::string& accountIdToFlagFree gtk_tree_selection_unselect_all(GTK_TREE_SELECTION(selection_conversations)); gtk_widget_destroy(widgets->treeview_conversations); } - widgets->treeview_conversations = conversations_view_new(accountContainer_.get()); + widgets->treeview_conversations = conversations_view_new(accountInfo_); gtk_container_add(GTK_CONTAINER(widgets->scrolled_window_smartview), widgets->treeview_conversations); if (widgets->treeview_contact_requests) { @@ -1237,29 +1238,29 @@ CppImpl::updateLrc(const std::string& id, const std::string& accountIdToFlagFree gtk_tree_selection_unselect_all(GTK_TREE_SELECTION(selection_conversations)); gtk_widget_destroy(widgets->treeview_contact_requests); } - widgets->treeview_contact_requests = conversations_view_new(accountContainer_.get()); + widgets->treeview_contact_requests = conversations_view_new(accountInfo_); gtk_container_add(GTK_CONTAINER(widgets->scrolled_window_contact_requests), widgets->treeview_contact_requests); - if (!accountContainer_) return; + if (!accountInfo_) return; // Connect to signals from LRC - historyClearedConnection_ = QObject::connect(&*accountContainer_->info.conversationModel, + historyClearedConnection_ = QObject::connect(&*accountInfo_->conversationModel, &lrc::api::ConversationModel::conversationCleared, [this] (const std::string& id) { slotConversationCleared(id); }); - modelSortedConnection_ = QObject::connect(&*accountContainer_->info.conversationModel, + modelSortedConnection_ = QObject::connect(&*accountInfo_->conversationModel, &lrc::api::ConversationModel::modelSorted, [this] { slotModelSorted(); }); - filterChangedConnection_ = QObject::connect(&*accountContainer_->info.conversationModel, + filterChangedConnection_ = QObject::connect(&*accountInfo_->conversationModel, &lrc::api::ConversationModel::filterChanged, [this] { slotFilterChanged(); }); - newConversationConnection_ = QObject::connect(&*accountContainer_->info.conversationModel, + newConversationConnection_ = QObject::connect(&*accountInfo_->conversationModel, &lrc::api::ConversationModel::newConversation, [this] (const std::string& id) { slotNewConversation(id); }); - conversationRemovedConnection_ = QObject::connect(&*accountContainer_->info.conversationModel, + conversationRemovedConnection_ = QObject::connect(&*accountInfo_->conversationModel, &lrc::api::ConversationModel::conversationRemoved, [this] (const std::string& id) { slotConversationRemoved(id); }); @@ -1276,9 +1277,9 @@ CppImpl::updateLrc(const std::string& id, const std::string& accountIdToFlagFree [this] (const std::string& id, lrc::api::conversation::Info origin) { slotShowIncomingCallView(id, origin); }); const gchar *text = gtk_entry_get_text(GTK_ENTRY(widgets->search_entry)); - currentTypeFilter_ = accountContainer_->info.profileInfo.type; - accountContainer_->info.conversationModel->setFilter(text); - accountContainer_->info.conversationModel->setFilter(currentTypeFilter_); + currentTypeFilter_ = accountInfo_->profileInfo.type; + accountInfo_->conversationModel->setFilter(text); + accountInfo_->conversationModel->setFilter(currentTypeFilter_); } void @@ -1316,10 +1317,9 @@ CppImpl::slotAccountRemovedFromLrc(const std::string& id) void CppImpl::slotAccountStatusChanged(const std::string& id) { - if (not accountContainer_ ) { + if (!accountInfo_) { updateLrc(id); - ring_welcome_update_view(RING_WELCOME_VIEW(widgets->welcome_view), - accountContainer_.get()); + ring_welcome_update_view(RING_WELCOME_VIEW(widgets->welcome_view)); return; } @@ -1337,7 +1337,7 @@ CppImpl::slotAccountStatusChanged(const std::string& id) if (enabledAccounts == 0) { updateLrc(""); changeView(RING_WELCOME_VIEW_TYPE); - ring_welcome_update_view(RING_WELCOME_VIEW(widgets->welcome_view), nullptr); + ring_welcome_update_view(RING_WELCOME_VIEW(widgets->welcome_view)); } } @@ -1393,7 +1393,7 @@ CppImpl::slotFilterChanged() current_item = incoming_call_view_get_conversation(INCOMING_CALL_VIEW(old_view)); conversations_view_select_conversation(CONVERSATIONS_VIEW(widgets->treeview_conversations), current_item.uid); // Get if conversation still exists. - auto& conversationModel = accountContainer_->info.conversationModel; + auto& conversationModel = accountInfo_->conversationModel; auto conversations = conversationModel->allFilteredConversations(); auto isInConv = std::find_if( conversations.begin(), conversations.end(), @@ -1409,16 +1409,16 @@ void CppImpl::slotNewConversation(const std::string& uid) { gtk_notebook_set_current_page(GTK_NOTEBOOK(widgets->notebook_contacts), 0); - accountContainer_->info.conversationModel->setFilter(lrc::api::profile::Type::RING); + accountInfo_->conversationModel->setFilter(lrc::api::profile::Type::RING); gtk_entry_set_text(GTK_ENTRY(widgets->search_entry), ""); - accountContainer_->info.conversationModel->setFilter(""); + accountInfo_->conversationModel->setFilter(""); // Select new conversation if contact added auto* old_view = gtk_bin_get_child(GTK_BIN(widgets->frame_call)); if (IS_RING_WELCOME_VIEW(old_view) || (IS_CHAT_VIEW(old_view) && chat_view_get_temporary(CHAT_VIEW(old_view)))) { - accountContainer_->info.conversationModel->selectConversation(uid); + accountInfo_->conversationModel->selectConversation(uid); try { auto contactUri = chatViewConversation_->participants.front(); - auto contactInfo = accountContainer_->info.contactModel->getContact(contactUri); + auto contactInfo = accountInfo_->contactModel->getContact(contactUri); auto isPending = contactInfo.profileInfo.type == lrc::api::profile::Type::PENDING; chat_view_update_temporary(CHAT_VIEW(gtk_bin_get_child(GTK_BIN(widgets->frame_call))), isPending || contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY, @@ -1456,7 +1456,7 @@ CppImpl::slotShowChatView(const std::string& id, lrc::api::conversation::Info or // Do not show a conversation without any participants if (origin.participants.empty()) return; auto firstContactUri = origin.participants.front(); - auto contactInfo = accountContainer_->info.contactModel->getContact(firstContactUri); + auto contactInfo = accountInfo_->contactModel->getContact(firstContactUri); // change view if necessary or just update temporary if (current_item.uid != origin.uid) { changeView(CHAT_VIEW_TYPE, origin); diff --git a/src/ringwelcomeview.cpp b/src/ringwelcomeview.cpp index 6de165ba..4391f119 100644 --- a/src/ringwelcomeview.cpp +++ b/src/ringwelcomeview.cpp @@ -52,7 +52,7 @@ struct _RingWelcomeViewPrivate GtkWidget *button_qrcode; GtkWidget *revealer_qrcode; - AccountContainer* accountContainer_; + AccountInfoPointer const *accountInfo_; }; G_DEFINE_TYPE_WITH_PRIVATE(RingWelcomeView, ring_welcome_view, GTK_TYPE_SCROLLED_WINDOW); @@ -63,14 +63,11 @@ static gboolean draw_qrcode(GtkWidget*,cairo_t*,RingWelcomeView*); static void switch_qrcode(RingWelcomeView* self); void -ring_welcome_update_view(RingWelcomeView* self, AccountContainer* accountContainer) { +ring_welcome_update_view(RingWelcomeView* self) { auto priv = RING_WELCOME_VIEW_GET_PRIVATE(self); - if (accountContainer) - priv->accountContainer_ = accountContainer; - // Only draw a basic view for SIP accounts - if (not accountContainer || priv->accountContainer_->info.profileInfo.type == lrc::api::profile::Type::SIP) { + if (not *priv->accountInfo_ || (*priv->accountInfo_)->profileInfo.type == lrc::api::profile::Type::SIP) { gtk_widget_hide(priv->button_qrcode); gtk_widget_hide(priv->label_ringid); gtk_widget_hide(priv->label_explanation); @@ -82,21 +79,21 @@ ring_welcome_update_view(RingWelcomeView* self, AccountContainer* accountContain // Get registeredName, else the Ring Id gchar *ring_id = nullptr; - if(! priv->accountContainer_->info.registeredName.empty()){ + if(! (*priv->accountInfo_)->registeredName.empty()){ gtk_label_set_text( GTK_LABEL(priv->label_explanation), _("This is your Ring username.\nCopy and share it with your friends!") ); ring_id = g_markup_printf_escaped("<span fgcolor=\"black\">ring:%s</span>", - priv->accountContainer_->info.registeredName.c_str()); + (*priv->accountInfo_)->registeredName.c_str()); } - else if (!priv->accountContainer_->info.profileInfo.uri.empty()) { + else if (!(*priv->accountInfo_)->profileInfo.uri.empty()) { gtk_label_set_text( GTK_LABEL(priv->label_explanation), C_("Do not translate \"RingID\"", "This is your RingID.\nCopy and share it with your friends!") ); ring_id = g_markup_printf_escaped("<span fgcolor=\"black\">%s</span>", - priv->accountContainer_->info.profileInfo.uri.c_str()); + (*priv->accountInfo_)->profileInfo.uri.c_str()); } else { gtk_label_set_text(GTK_LABEL(priv->label_explanation), NULL); ring_id = {}; @@ -232,12 +229,12 @@ ring_welcome_view_class_init(RingWelcomeViewClass *klass) } GtkWidget * -ring_welcome_view_new(AccountContainer* accountContainer) +ring_welcome_view_new(AccountInfoPointer const & accountInfo) { gpointer self = g_object_new(RING_WELCOME_VIEW_TYPE, NULL); auto priv = RING_WELCOME_VIEW_GET_PRIVATE(self); - priv->accountContainer_ = accountContainer; - ring_welcome_update_view(RING_WELCOME_VIEW(self), accountContainer); + priv->accountInfo_ = &accountInfo; + ring_welcome_update_view(RING_WELCOME_VIEW(self)); return (GtkWidget *)self; } @@ -250,7 +247,7 @@ draw_qrcode(G_GNUC_UNUSED GtkWidget* diese, { auto priv = RING_WELCOME_VIEW_GET_PRIVATE(self); - auto rcode = QRcode_encodeString(priv->accountContainer_->info.profileInfo.uri.c_str(), + auto rcode = QRcode_encodeString((*priv->accountInfo_)->profileInfo.uri.c_str(), 0, //Let the version be decided by libqrencode QR_ECLEVEL_L, // Lowest level of error correction QR_MODE_8, // 8-bit data mode diff --git a/src/ringwelcomeview.h b/src/ringwelcomeview.h index cf3b05bb..b5b09a05 100644 --- a/src/ringwelcomeview.h +++ b/src/ringwelcomeview.h @@ -23,7 +23,9 @@ #include <gtk/gtk.h> -#include "accountcontainer.h" +#include "api/account.h" + +#include "accountinfopointer.h" G_BEGIN_DECLS @@ -37,7 +39,7 @@ typedef struct _RingWelcomeView RingWelcomeView; typedef struct _RingWelcomeViewClass RingWelcomeViewClass; GType ring_welcome_view_get_type (void) G_GNUC_CONST; -GtkWidget* ring_welcome_view_new (AccountContainer* accountContainer); -void ring_welcome_update_view (RingWelcomeView* self, AccountContainer* accountContainer = nullptr); +GtkWidget* ring_welcome_view_new (AccountInfoPointer const & accountInfo); +void ring_welcome_update_view (RingWelcomeView* self); G_END_DECLS -- GitLab