From ea4f4dbf9ebc9f30793d22e7b85bb1f9ff6ce05e Mon Sep 17 00:00:00 2001 From: Amin Bandali <amin.bandali@savoirfairelinux.com> Date: Thu, 12 Aug 2021 20:03:26 -0400 Subject: [PATCH] pixbufmanipulator: refactor to simplify and ditch the class Change-Id: If94f7f163b9b2f11f8a7f5992f1121898409e0e0 --- src/accountmigrationview.cpp | 19 +-- src/avatarmanipulation.cpp | 20 +-- src/chatview.cpp | 18 +-- src/client.cpp | 1 - src/conversationsview.cpp | 8 +- src/currentcallview.cpp | 63 +++++---- src/incomingcallview.cpp | 7 +- src/mainwindow.cpp | 18 +-- src/native/pixbufmanipulator.cpp | 217 +++++++++++++------------------ src/native/pixbufmanipulator.h | 81 ++++++------ src/notifier.cpp | 21 +-- src/profileview.cpp | 8 +- src/webkitchatcontainer.cpp | 1 - 13 files changed, 224 insertions(+), 258 deletions(-) diff --git a/src/accountmigrationview.cpp b/src/accountmigrationview.cpp index a6d9a052..382186fd 100644 --- a/src/accountmigrationview.cpp +++ b/src/accountmigrationview.cpp @@ -240,19 +240,22 @@ build_migration_view(AccountMigrationView *view) } /* get the current or default profile avatar */ - auto default_avatar = Interfaces::PixbufManipulator().generateAvatar("", ""); - auto default_scaled = Interfaces::PixbufManipulator().scaleAndFrame(default_avatar.get(), QSize(AVATAR_WIDTH, AVATAR_HEIGHT)); - auto photo = default_scaled; + GdkPixbuf *p = pxbm_generate_avatar("", ""); + GdkPixbuf *photo = pxbm_scale_and_frame( + p, QSize(AVATAR_WIDTH, AVATAR_HEIGHT)); + g_object_unref(p); auto photostr = (*priv->accountInfo_)->profileInfo.avatar; if (!photostr.isEmpty()) { QByteArray byteArray = photostr.toUtf8(); - QVariant avatar = Interfaces::PixbufManipulator().personPhoto(byteArray); - auto pixbuf_photo = Interfaces::PixbufManipulator().scaleAndFrame(avatar.value<std::shared_ptr<GdkPixbuf>>().get(), QSize(AVATAR_WIDTH, AVATAR_HEIGHT)); - if (avatar.isValid()) { - photo = pixbuf_photo; + GdkPixbuf *p = pxbm_person_photo(byteArray); + if (p) { + g_object_unref(photo); + photo = pxbm_scale_and_frame(p, QSize(AVATAR_WIDTH, AVATAR_HEIGHT)); + g_object_unref(p); } } - gtk_image_set_from_pixbuf(GTK_IMAGE(priv->image_avatar), photo.get()); + gtk_image_set_from_pixbuf(GTK_IMAGE(priv->image_avatar), photo); + g_object_unref(photo); // CSS styles auto provider = gtk_css_provider_new(); diff --git a/src/avatarmanipulation.cpp b/src/avatarmanipulation.cpp index 1319c922..049bc257 100644 --- a/src/avatarmanipulation.cpp +++ b/src/avatarmanipulation.cpp @@ -23,7 +23,6 @@ /* LRC */ #include <api/newaccountmodel.h> #include <api/avmodel.h> -#include <globalinstances.h> #include <QSize> /* client */ @@ -235,19 +234,22 @@ set_state(AvatarManipulation *self, AvatarManipulationState state) case AVATAR_MANIPULATION_STATE_CURRENT: { /* get the current or default profile avatar */ - auto default_avatar = Interfaces::PixbufManipulator().generateAvatar("", ""); - auto default_scaled = Interfaces::PixbufManipulator().scaleAndFrame(default_avatar.get(), QSize(AVATAR_WIDTH, AVATAR_HEIGHT)); - auto photo = default_scaled; + GdkPixbuf *default_avatar = pxbm_generate_avatar("", ""); + GdkPixbuf *photo = pxbm_scale_and_frame( + default_avatar, QSize(AVATAR_WIDTH, AVATAR_HEIGHT)); + g_object_unref(default_avatar); if ((priv->accountInfo_ && (*priv->accountInfo_)) || priv->temporaryAvatar) { auto photostr = priv->temporaryAvatar? priv->temporaryAvatar : (*priv->accountInfo_)->profileInfo.avatar; QByteArray byteArray = photostr.toUtf8(); - QVariant avatar = Interfaces::PixbufManipulator().personPhoto(byteArray); - if (avatar.isValid()) { - auto size = QSize(AVATAR_WIDTH, AVATAR_HEIGHT); - photo = Interfaces::PixbufManipulator().scaleAndFrame(avatar.value<std::shared_ptr<GdkPixbuf>>().get(), size); + GdkPixbuf *avatar = pxbm_person_photo(byteArray); + if (avatar) { + g_object_unref(photo); + photo = pxbm_scale_and_frame(avatar, QSize(AVATAR_WIDTH, AVATAR_HEIGHT)); + g_object_unref(avatar); } } - gtk_image_set_from_pixbuf(GTK_IMAGE(priv->image_avatar), photo.get()); + gtk_image_set_from_pixbuf(GTK_IMAGE(priv->image_avatar), photo); + g_object_unref(photo); gtk_stack_set_visible_child_name(GTK_STACK(priv->stack_views), "page_avatar"); diff --git a/src/chatview.cpp b/src/chatview.cpp index d07dd30c..34682a86 100644 --- a/src/chatview.cpp +++ b/src/chatview.cpp @@ -1036,15 +1036,14 @@ load_participants_images(ChatView *self) auto& contact = (*priv->accountInfo_)->contactModel->getContact(contactUri); std::string avatar_str = contact.profileInfo.avatar.toStdString(); if (avatar_str.empty()) { - auto var_photo = Interfaces::PixbufManipulator().conversationPhoto( + GdkPixbuf *p = pxbm_conversation_photo( *priv->conversation_, **(priv->accountInfo_), QSize(AVATAR_WIDTH, AVATAR_HEIGHT), contact.isPresent ); - auto image = var_photo.value<std::shared_ptr<GdkPixbuf>>(); - auto ba = Interfaces::PixbufManipulator().toByteArray(var_photo); - avatar_str = ba.toBase64().toStdString(); + avatar_str = pxbm_to_QByteArray(p).toBase64().toStdString(); + g_object_unref(p); } webkit_chat_container_set_sender_image( WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), @@ -1058,11 +1057,12 @@ load_participants_images(ChatView *self) // For this account std::string avatar_str = (*priv->accountInfo_)->profileInfo.avatar.toStdString(); if (avatar_str.empty()) { - auto default_photo = QVariant::fromValue(Interfaces::PixbufManipulator().scaleAndFrame( - Interfaces::PixbufManipulator().generateAvatar("", "").get(), - QSize(AVATAR_WIDTH, AVATAR_HEIGHT), false)); - auto ba = Interfaces::PixbufManipulator().toByteArray(default_photo); - avatar_str = ba.toBase64().toStdString(); + GdkPixbuf *p = pxbm_generate_avatar("", ""); + GdkPixbuf *default_photo = pxbm_scale_and_frame( + p, QSize(AVATAR_WIDTH, AVATAR_HEIGHT), false); + g_object_unref(p); + avatar_str = pxbm_to_QByteArray(default_photo).toBase64().toStdString(); + g_object_unref(default_photo); } webkit_chat_container_set_sender_image( WEBKIT_CHAT_CONTAINER(priv->webkit_chat_container), diff --git a/src/client.cpp b/src/client.cpp index a27e7159..68f6035b 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -540,7 +540,6 @@ client_startup(GApplication *app) } /* init delegates */ - GlobalInstances::setPixmapManipulator(std::unique_ptr<Interfaces::PixbufManipulator>(new Interfaces::PixbufManipulator())); GlobalInstances::setDBusErrorHandler(std::unique_ptr<Interfaces::DBusErrorHandler>(new Interfaces::DBusErrorHandler())); /* Override theme since we don't have appropriate icons for a dark them (yet) */ diff --git a/src/conversationsview.cpp b/src/conversationsview.cpp index f4960f26..c5792937 100644 --- a/src/conversationsview.cpp +++ b/src/conversationsview.cpp @@ -31,7 +31,6 @@ #include <QSize> // LRC -#include <globalinstances.h> #include <api/conversationmodel.h> #include <api/contactmodel.h> #include <api/call.h> @@ -132,21 +131,20 @@ render_contact_photo(G_GNUC_UNUSED GtkTreeViewColumn *tree_column, isBanned = contactInfo.isBanned; } catch (...) { } } - std::shared_ptr<GdkPixbuf> image; static lrc::api::conversation::Info invalidConversation; auto convOpt = (*priv->accountInfo_)->conversationModel->getConversationForUid(uid); - auto var_photo = GlobalInstances::pixmapManipulator().conversationPhoto( + GdkPixbuf *p = pxbm_conversation_photo( convOpt ? convOpt->get() : invalidConversation, **(priv->accountInfo_), QSize(50, 50), isPresent ); - image = var_photo.value<std::shared_ptr<GdkPixbuf>>(); // set the width of the cell rendered to the width of the photo // so that the other renderers are shifted to the right g_object_set(G_OBJECT(cell), "width", 50, NULL); - g_object_set(G_OBJECT(cell), "pixbuf", image.get(), NULL); + g_object_set(G_OBJECT(cell), "pixbuf", p, NULL); + g_object_unref(p); // Banned contacts should be displayed with grey bg g_object_set(G_OBJECT(cell), "cell-background", isBanned ? "#BDBDBD" : NULL, NULL); diff --git a/src/currentcallview.cpp b/src/currentcallview.cpp index d3805513..ae724e07 100644 --- a/src/currentcallview.cpp +++ b/src/currentcallview.cpp @@ -36,7 +36,6 @@ #include <api/contactmodel.h> #include <api/newcallmodel.h> #include <api/newcodecmodel.h> -#include <globalinstances.h> #include <smartinfohub.h> // Gtk @@ -1262,9 +1261,11 @@ void CppImpl::add_present_contact(const QString& uri, const QString& custom_data, RowType custom_type, const QString& accountId) { QString bestName = uri, bestUri = uri; - auto default_avatar = Interfaces::PixbufManipulator().generateAvatar("", ""); - auto default_scaled = Interfaces::PixbufManipulator().scaleAndFrame(default_avatar.get(), QSize(48, 48), true, IconStatus::PRESENT); - auto photo = default_scaled; + GdkPixbuf *default_avatar = pxbm_generate_avatar("", ""); + GdkPixbuf *photo = pxbm_scale_and_frame( + default_avatar, + QSize(48, 48), true, IconStatus::PRESENT); + g_object_unref(default_avatar); try { auto &accInfo = lrc_.getAccountModel().getAccountInfo(accountId); @@ -1282,10 +1283,12 @@ CppImpl::add_present_contact(const QString& uri, const QString& custom_data, Row if (!photostr.isEmpty()) { QByteArray byteArray = photostr.toUtf8(); - QVariant avatar = Interfaces::PixbufManipulator().personPhoto(byteArray); - auto pixbuf_photo = Interfaces::PixbufManipulator().scaleAndFrame(avatar.value<std::shared_ptr<GdkPixbuf>>().get(), QSize(48, 48), true, IconStatus::PRESENT); - if (avatar.isValid()) { - photo = pixbuf_photo; + GdkPixbuf *p = pxbm_person_photo(byteArray); + if (p) { + g_object_unref(photo); + photo = pxbm_scale_and_frame( + p, QSize(48, 48), true, IconStatus::PRESENT); + g_object_unref(p); } } else { auto name = alias.isEmpty()? contactInfo.registeredName : alias; @@ -1296,8 +1299,11 @@ CppImpl::add_present_contact(const QString& uri, const QString& custom_data, Row fullUri = "ring:" + fullUri; else fullUri = "sip:" + fullUri; - photo = Interfaces::PixbufManipulator().generateAvatar(firstLetter.toStdString(), fullUri.toStdString()); - photo = Interfaces::PixbufManipulator().scaleAndFrame(photo.get(), QSize(48, 48), true, IconStatus::PRESENT); + GdkPixbuf *photo_tmp = pxbm_generate_avatar( + firstLetter.toStdString(), fullUri.toStdString()); + photo = pxbm_scale_and_frame( + photo_tmp, QSize(48, 48), true, IconStatus::PRESENT); + g_object_unref(photo_tmp); } } catch (const std::out_of_range&) { // ContactModel::getContact() exception @@ -1320,7 +1326,8 @@ CppImpl::add_present_contact(const QString& uri, const QString& custom_data, Row } auto* box_item = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - auto* avatar = gtk_image_new_from_pixbuf(photo.get()); + auto* avatar = gtk_image_new_from_pixbuf(photo); + g_object_unref(photo); auto* info = gtk_label_new(nullptr); gtk_label_set_markup(GTK_LABEL(info), text); gtk_container_add(GTK_CONTAINER(box_item), GTK_WIDGET(avatar)); @@ -1337,17 +1344,15 @@ void CppImpl::add_conference(const VectorString& uris, const QString& custom_data, const QString& accountId) { GError *error = nullptr; - auto default_avatar = std::shared_ptr<GdkPixbuf>( - gdk_pixbuf_new_from_resource_at_scale("/net/jami/JamiGnome/contacts_list", 50, 50, true, &error), - g_object_unref - ); - if (default_avatar == nullptr) { + GdkPixbuf *default_avatar = gdk_pixbuf_new_from_resource_at_scale( + "/net/jami/JamiGnome/contacts_list", 50, 50, true, &error); + if (!default_avatar) { g_debug("Could not load icon: %s", error->message); g_clear_error(&error); return; } - auto default_scaled = Interfaces::PixbufManipulator().scaleAndFrame(default_avatar.get(), QSize(50, 50)); - auto photo = default_scaled; + GdkPixbuf *photo = pxbm_scale_and_frame(default_avatar, QSize(50, 50)); + g_object_unref(default_avatar); std::string label; auto idx = 0; @@ -1382,7 +1387,8 @@ CppImpl::add_conference(const VectorString& uris, const QString& custom_data, co ); auto* box_item = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - auto* avatar = gtk_image_new_from_pixbuf(photo.get()); + auto* avatar = gtk_image_new_from_pixbuf(photo); + g_object_unref(photo); auto* info = gtk_label_new(nullptr); gtk_label_set_markup(GTK_LABEL(info), text); gtk_container_add(GTK_CONTAINER(box_item), GTK_WIDGET(avatar)); @@ -1398,12 +1404,13 @@ CppImpl::add_conference(const VectorString& uris, const QString& custom_data, co void CppImpl::add_transfer_contact(const std::string& uri) { - auto* box_item = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); - auto pixbufmanipulator = Interfaces::PixbufManipulator(); - auto image_buf = pixbufmanipulator.generateAvatar("", uri.empty() ? uri : "sip" + uri); - auto scaled = pixbufmanipulator.scaleAndFrame(image_buf.get(), QSize(48, 48)); - auto* avatar = gtk_image_new_from_pixbuf(scaled.get()); - auto* address = gtk_label_new(uri.c_str()); + auto *box_item = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); + GdkPixbuf *p = pxbm_generate_avatar("", uri.empty() ? uri : "sip" + uri); + GdkPixbuf *scaled = pxbm_scale_and_frame(p, QSize(48, 48)); + g_object_unref(p); + auto *avatar = gtk_image_new_from_pixbuf(scaled); + g_object_unref(scaled); + auto *address = gtk_label_new(uri.c_str()); gtk_container_add(GTK_CONTAINER(box_item), GTK_WIDGET(avatar)); gtk_container_add(GTK_CONTAINER(box_item), GTK_WIDGET(address)); gtk_list_box_insert(GTK_LIST_BOX(widgets->list_conversations), GTK_WIDGET(box_item), -1); @@ -1852,14 +1859,14 @@ CppImpl::updateNameAndPhoto() } catch (std::out_of_range& e) { } - QVariant var_i = GlobalInstances::pixmapManipulator().conversationPhoto( + GdkPixbuf *p = pxbm_conversation_photo( *conversation, **(accountInfo), photoSize, false ); - std::shared_ptr<GdkPixbuf> image = var_i.value<std::shared_ptr<GdkPixbuf>>(); - gtk_image_set_from_pixbuf(GTK_IMAGE(widgets->image_peer), image.get()); + gtk_image_set_from_pixbuf(GTK_IMAGE(widgets->image_peer), p); + g_object_unref(p); auto contacts = (*accountInfo)->conversationModel->peersForConversation(conversation->uid); if (contacts.empty()) return; diff --git a/src/incomingcallview.cpp b/src/incomingcallview.cpp index 45cb117e..16280f9c 100644 --- a/src/incomingcallview.cpp +++ b/src/incomingcallview.cpp @@ -39,7 +39,6 @@ #include <api/contactmodel.h> #include <api/conversationmodel.h> #include <api/contact.h> -#include <globalinstances.h> // Client #include "chatview.h" @@ -268,14 +267,14 @@ update_name_and_photo(IncomingCallView *view) g_return_if_fail(IS_INCOMING_CALL_VIEW(view)); auto priv = INCOMING_CALL_VIEW_GET_PRIVATE(view); - QVariant var_i = GlobalInstances::pixmapManipulator().conversationPhoto( + GdkPixbuf *p = pxbm_conversation_photo( *priv->conversation_, **(priv->accountInfo_), QSize(110, 110), false ); - std::shared_ptr<GdkPixbuf> image = var_i.value<std::shared_ptr<GdkPixbuf>>(); - gtk_image_set_from_pixbuf(GTK_IMAGE(priv->image_incoming), image.get()); + gtk_image_set_from_pixbuf(GTK_IMAGE(priv->image_incoming), p); + g_object_unref(p); try { auto contacts = (*priv->accountInfo_)->conversationModel->peersForConversation(priv->conversation_->uid); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index fde3a836..71519993 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -274,24 +274,26 @@ render_account_avatar(GtkCellLayout*, } else if (statusStr == "CONNECTED") { iconStatus = IconStatus::CONNECTED; } - auto default_avatar = Interfaces::PixbufManipulator().generateAvatar("", ""); - auto default_scaled = Interfaces::PixbufManipulator().scaleAndFrame(default_avatar.get(), QSize(32, 32), true, iconStatus); - auto photo = default_scaled; + GdkPixbuf *default_avatar = pxbm_generate_avatar("", ""); + GdkPixbuf *photo = pxbm_scale_and_frame(default_avatar, QSize(32, 32), true, iconStatus); + g_object_unref(default_avatar); std::string photostr = avatar; if (!photostr.empty()) { QByteArray byteArray(photostr.c_str(), photostr.length()); - QVariant avatar = Interfaces::PixbufManipulator().personPhoto(byteArray); - auto pixbuf_photo = Interfaces::PixbufManipulator().scaleAndFrame(avatar.value<std::shared_ptr<GdkPixbuf>>().get(), QSize(32, 32), true, iconStatus); - if (avatar.isValid()) { - photo = pixbuf_photo; + GdkPixbuf *p = pxbm_person_photo(byteArray); + if (p) { + g_object_unref(photo); + photo = pxbm_scale_and_frame(p, QSize(32, 32), true, iconStatus); + g_object_unref(p); } } g_object_set(G_OBJECT(cell), "width", 32, nullptr); g_object_set(G_OBJECT(cell), "height", 32, nullptr); - g_object_set(G_OBJECT(cell), "pixbuf", photo.get(), nullptr); + g_object_set(G_OBJECT(cell), "pixbuf", photo, nullptr); + g_object_unref(photo); g_free(status); g_free(avatar); g_free(id); diff --git a/src/native/pixbufmanipulator.cpp b/src/native/pixbufmanipulator.cpp index 8c6ebf26..8201b7f5 100644 --- a/src/native/pixbufmanipulator.cpp +++ b/src/native/pixbufmanipulator.cpp @@ -2,6 +2,7 @@ * Copyright (C) 2015-2021 Savoir-faire Linux Inc. * Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com> * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> + * Author: Amin Bandali <amin.bandali@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 @@ -20,10 +21,6 @@ #include "pixbufmanipulator.h" -#include <QtCore/QSize> -#include <QtCore/QMetaType> -#include <memory> - #include <string> #include <algorithm> @@ -34,32 +31,10 @@ #include <api/account.h> #include <api/contact.h> -namespace Interfaces { - -PixbufManipulator::PixbufManipulator() - : conferenceAvatar_{draw_conference_avatar(FALLBACK_AVATAR_SIZE), g_object_unref} -{ -} +#define FALLBACK_AVATAR_SIZE 100 -std::shared_ptr<GdkPixbuf> -PixbufManipulator::temporaryItemAvatar() const -{ - GError *error = nullptr; - std::shared_ptr<GdkPixbuf> result( - gdk_pixbuf_new_from_resource("/net/jami/JamiGnome/temporary-item", &error), - g_object_unref - ); - - if (result == nullptr) { - g_debug("Could not load icon: %s", error->message); - g_clear_error(&error); - return generateAvatar("", ""); - } - return result; -} - -std::shared_ptr<GdkPixbuf> -PixbufManipulator::generateAvatar(const std::string& alias, const std::string& uri) const +GdkPixbuf *pxbm_generate_avatar(const std::string& alias, + const std::string& uri) { std::string letter = {}; if (!alias.empty()) { @@ -72,22 +47,14 @@ PixbufManipulator::generateAvatar(const std::string& alias, const std::string& u color = std::string("0123456789abcdef").find(md5[0]); } - return std::shared_ptr<GdkPixbuf> { - draw_fallback_avatar( - FALLBACK_AVATAR_SIZE, - letter, - color - ), - g_object_unref - }; + return draw_fallback_avatar(FALLBACK_AVATAR_SIZE, letter, color); } -std::shared_ptr<GdkPixbuf> -PixbufManipulator::scaleAndFrame(const GdkPixbuf *photo, - const QSize& size, - bool displayInformation, - IconStatus status, - uint unreadMessages) +GdkPixbuf *pxbm_scale_and_frame(const GdkPixbuf *photo, + const QSize& size, + bool displayInformation, + IconStatus status, + uint unreadMessages) { /** * for now, respect the height requested @@ -109,32 +76,32 @@ PixbufManipulator::scaleAndFrame(const GdkPixbuf *photo, if (w > h) photo_h = h * ((double)photo_w / w); - std::unique_ptr<GdkPixbuf, decltype(g_object_unref)&> scaled_photo{ - gdk_pixbuf_scale_simple(photo, photo_w, photo_h, GDK_INTERP_BILINEAR), - g_object_unref}; + GdkPixbuf *scaled_photo = gdk_pixbuf_scale_simple( + photo, photo_w, photo_h, GDK_INTERP_BILINEAR); /* frame photo */ - std::shared_ptr<GdkPixbuf> result { - frame_avatar(scaled_photo.get()), - g_object_unref - }; + GdkPixbuf *result = frame_avatar(scaled_photo); /* draw information */ if (displayInformation) { /* draw status */ - result.reset(draw_status(result.get(), status), g_object_unref); + GdkPixbuf *result2 = draw_status(result, status); + g_object_unref(result); /* draw visual notification for unread messages */ - if (unreadMessages) - result.reset(draw_unread_messages(result.get(), unreadMessages), g_object_unref); + if (unreadMessages) { + result = draw_unread_messages(result2, unreadMessages); + g_object_unref(result2); + } else { + result = result2; + } } return result; } -QVariant PixbufManipulator::personPhoto(const QByteArray& data, const QString& type) +GdkPixbuf *pxbm_person_photo(const QByteArray& data) { - Q_UNUSED(type); /* Try to load the image from the data provided by lrc vcard utils; * lrc is getting the image data assuming that it is inlined in the vcard, * for now URIs are not supported. @@ -176,20 +143,27 @@ QVariant PixbufManipulator::personPhoto(const QByteArray& data, const QString& t } } - if (pixbuf) { - std::shared_ptr<GdkPixbuf> avatar(pixbuf, g_object_unref); - return QVariant::fromValue(avatar); - } + return pixbuf; +} - /* could not load image, return emtpy QVariant */ - return QVariant(); +static GdkPixbuf *temporary_item_avatar() +{ + GError *error = nullptr; + GdkPixbuf *result = gdk_pixbuf_new_from_resource( + "/net/jami/JamiGnome/temporary-item", &error); + + if (result == nullptr) { + g_debug("Could not load icon: %s", error->message); + g_clear_error(&error); + return pxbm_generate_avatar("", ""); + } + return result; } -QVariant -PixbufManipulator::conversationPhoto(const lrc::api::conversation::Info& conversationInfo, - const lrc::api::account::Info& accountInfo, - const QSize& size, - bool displayInformation) +GdkPixbuf *pxbm_conversation_photo(const lrc::api::conversation::Info& conversationInfo, + const lrc::api::account::Info& accountInfo, + const QSize& size, + bool displayInformation) { auto contacts = accountInfo.conversationModel->peersForConversation(conversationInfo.uid); if (!contacts.empty()) { @@ -201,95 +175,80 @@ PixbufManipulator::conversationPhoto(const lrc::api::conversation::Info& convers auto alias = contactInfo.profileInfo.alias; alias.remove('\r'); alias.remove('\n'); - auto bestName = alias.isEmpty() ? contactInfo.registeredName : alias; + auto bestName = alias.isEmpty() + ? contactInfo.registeredName + : alias; auto unreadMessages = conversationInfo.unreadMessages; - auto status = contactInfo.isPresent? IconStatus::PRESENT : IconStatus::ABSENT; - if (accountInfo.profileInfo.type == lrc::api::profile::Type::SIP && contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY) + auto status = contactInfo.isPresent + ? IconStatus::PRESENT + : IconStatus::ABSENT; + + GdkPixbuf *tmp, *ret; + if (accountInfo.profileInfo.type == lrc::api::profile::Type::SIP + && contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY) { - return QVariant::fromValue(scaleAndFrame(generateAvatar("", "").get(), size, displayInformation, status)); + tmp = pxbm_generate_avatar("", ""); + ret = pxbm_scale_and_frame(tmp, size, displayInformation, status); } else if (accountInfo.profileInfo.type == lrc::api::profile::Type::SIP) { - return QVariant::fromValue(scaleAndFrame(generateAvatar("", "sip:" + contactInfo.profileInfo.uri.toStdString()).get(), size, displayInformation, status)); - } else if (contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY && contactInfo.profileInfo.uri.isEmpty()) { - return QVariant::fromValue(scaleAndFrame(temporaryItemAvatar().get(), size, false, status, unreadMessages)); + tmp = pxbm_generate_avatar( + "", "sip:" + contactInfo.profileInfo.uri.toStdString()); + ret = pxbm_scale_and_frame(tmp, size, displayInformation, status); + } else if (contactInfo.profileInfo.type == lrc::api::profile::Type::TEMPORARY + && contactInfo.profileInfo.uri.isEmpty()) { + tmp = temporary_item_avatar(); + ret = pxbm_scale_and_frame(tmp, size, false, status, unreadMessages); } else if (!contactPhoto.isEmpty()) { - QByteArray byteArray = contactPhoto.toUtf8(); - QVariant photo = personPhoto(byteArray); - if (GDK_IS_PIXBUF(photo.value<std::shared_ptr<GdkPixbuf>>().get())) { - return QVariant::fromValue(scaleAndFrame( - photo.value<std::shared_ptr<GdkPixbuf>>().get(), size, - displayInformation, status, unreadMessages)); + tmp = pxbm_person_photo(contactPhoto.toUtf8()); + if (GDK_IS_PIXBUF(tmp)) { + ret = pxbm_scale_and_frame( + tmp, size, displayInformation, status, unreadMessages); } else { - return QVariant::fromValue(scaleAndFrame( - generateAvatar(bestName.toStdString(), - "ring:" + contactInfo.profileInfo.uri.toStdString()).get(), - size, displayInformation, status, unreadMessages)); + g_object_unref(tmp); + tmp = pxbm_generate_avatar( + bestName.toStdString(), + "ring:" + contactInfo.profileInfo.uri.toStdString()); + ret = pxbm_scale_and_frame( + tmp, size, displayInformation, status, unreadMessages); } } else { - return QVariant::fromValue(scaleAndFrame(generateAvatar(bestName.toStdString(), - "ring:" + contactInfo.profileInfo.uri.toStdString()).get(), size, displayInformation, status, unreadMessages)); + tmp = pxbm_generate_avatar( + bestName.toStdString(), + "ring:" + contactInfo.profileInfo.uri.toStdString()); + ret = pxbm_scale_and_frame( + tmp, size, displayInformation, status, unreadMessages); } + g_object_unref(tmp); + return ret; } catch (...) {} } - return QVariant::fromValue(scaleAndFrame(temporaryItemAvatar().get(), size, displayInformation)); + GdkPixbuf *tmp = temporary_item_avatar(); + GdkPixbuf *ret = pxbm_scale_and_frame(tmp, size, displayInformation); + g_object_unref(tmp); + return ret; } -QVariant -PixbufManipulator::numberCategoryIcon(const QVariant& p, const QSize& size, bool displayInformation, bool isPresent) +QByteArray pxbm_to_QByteArray(GdkPixbuf *pxm) { - Q_UNUSED(p) - Q_UNUSED(size) - Q_UNUSED(displayInformation) - Q_UNUSED(isPresent) - return QVariant(); -} - -QByteArray -PixbufManipulator::toByteArray(const QVariant& pxm) -{ - std::shared_ptr<GdkPixbuf> pixbuf_photo = pxm.value<std::shared_ptr<GdkPixbuf>>(); - - if(pixbuf_photo.get()) { - gchar* png_buffer = nullptr; + if(pxm) { + gchar *png_buffer = nullptr; gsize png_buffer_size; GError *error = nullptr; - gdk_pixbuf_save_to_buffer(pixbuf_photo.get(), &png_buffer, &png_buffer_size, "png", &error, NULL); + gdk_pixbuf_save_to_buffer(pxm, &png_buffer, &png_buffer_size, + "png", &error, NULL); QByteArray array = QByteArray(png_buffer, png_buffer_size); - g_free(png_buffer); if (error != NULL) { - g_warning("in toByteArray, gdk_pixbuf_save_to_buffer failed : %s\n", error->message); + g_warning("in toByteArray, gdk_pixbuf_save_to_buffer failed: %s\n", + error->message); g_clear_error(&error); } return array; } else { - g_debug("in toByteArray, failed to retrieve data from parameter pxm"); + g_debug("in toByteArray, the pxm parameter was null"); return QByteArray(); } } - -QVariant -PixbufManipulator::userActionIcon(const UserActionElement& state) const -{ - Q_UNUSED(state) - return QVariant(); -} - -QVariant PixbufManipulator::decorationRole(const QModelIndex& index) -{ - Q_UNUSED(index) - return QVariant(); -} - -QVariant PixbufManipulator::decorationRole(const lrc::api::conversation::Info& conversation, - const lrc::api::account::Info& accountInfo) -{ - Q_UNUSED(conversation) - Q_UNUSED(accountInfo) - return QVariant(); -} - -} // namespace Interfaces diff --git a/src/native/pixbufmanipulator.h b/src/native/pixbufmanipulator.h index deaf8726..6cc5a2d9 100644 --- a/src/native/pixbufmanipulator.h +++ b/src/native/pixbufmanipulator.h @@ -2,6 +2,7 @@ * Copyright (C) 2015-2021 Savoir-faire Linux Inc. * Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com> * Author: Sebastien Blin <sebastien.blin@savoirfairelinux.com> + * Author: Amin Bandali <amin.bandali@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 @@ -18,49 +19,45 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#pragma once +#ifndef _PIXBUFMANIPULATOR_H +#define _PIXBUFMANIPULATOR_H #include <gtk/gtk.h> -#include <memory> -#include <interfaces/pixmapmanipulatori.h> +#include <QSize> #include "../utils/drawing.h" -Q_DECLARE_METATYPE(std::shared_ptr<GdkPixbuf>); - -class Person; - -namespace Interfaces { - -/** - * TODO remove old methods (methods which use Call, ContactMethod, Person, etc) - * But before, they should be removed from PixmapManipulatorI - */ -class PixbufManipulator : public PixmapManipulatorI { - constexpr static int FALLBACK_AVATAR_SIZE {100}; -public: - PixbufManipulator(); - - QVariant conversationPhoto(const lrc::api::conversation::Info& conversation, - const lrc::api::account::Info& accountInfo, - const QSize& size, - bool displayInformation = true) override; - QVariant personPhoto(const QByteArray& data, const QString& type = "PNG") override; - - QVariant numberCategoryIcon(const QVariant& p, const QSize& size, bool displayInformation = false, bool isPresent = false) override; - QByteArray toByteArray(const QVariant& pxm) override; - QVariant userActionIcon(const UserActionElement& state) const override; - QVariant decorationRole(const QModelIndex& index) override; - QVariant decorationRole(const lrc::api::conversation::Info& conversation, - const lrc::api::account::Info& accountInfo) override; - - // Helpers - std::shared_ptr<GdkPixbuf> temporaryItemAvatar() const; - std::shared_ptr<GdkPixbuf> generateAvatar(const std::string& alias, const std::string& uri) const; - - std::shared_ptr<GdkPixbuf> scaleAndFrame(const GdkPixbuf *photo, const QSize &size, bool displayInformation = false, IconStatus status = IconStatus::INVALID, uint unreadMessages = 0); - - private: - std::shared_ptr<GdkPixbuf> conferenceAvatar_; -}; - -} // namespace Interfaces +namespace lrc +{ +namespace api +{ +namespace account +{ + struct Info; +} +namespace conversation +{ + struct Info; +} +} +} + +G_BEGIN_DECLS + +GdkPixbuf *pxbm_conversation_photo(const lrc::api::conversation::Info& conversation, + const lrc::api::account::Info& accountInfo, + const QSize& size, + bool displayInformation = true); +GdkPixbuf *pxbm_person_photo(const QByteArray& data); +GdkPixbuf *pxbm_generate_avatar(const std::string& alias, + const std::string& uri); +GdkPixbuf *pxbm_scale_and_frame(const GdkPixbuf *photo, + const QSize &size, + bool displayInformation = false, + IconStatus status = IconStatus::INVALID, + uint unreadMessages = 0); +QByteArray pxbm_to_QByteArray(GdkPixbuf *pxm); + + +G_END_DECLS + +#endif /* _PIXBUFMANIPULATOR_H */ diff --git a/src/notifier.cpp b/src/notifier.cpp index 47b31a35..59b7d2c2 100644 --- a/src/notifier.cpp +++ b/src/notifier.cpp @@ -30,9 +30,9 @@ #include <glib/gi18n.h> #include <libnotify/notify.h> #include <memory> -#include <globalinstances.h> #include "native/pixbufmanipulator.h" -#include <QtCore/QSize> +#include <QSize> +#include <QString> #include <map> #endif @@ -310,17 +310,20 @@ show_notification(Notifier* view, const std::string& icon, // Draw icon auto firstLetter = (name == uri || name.empty()) ? "" : QString(QString(name.c_str()).at(0)).toStdString(); // NOTE best way to be compatible with UTF-8 - auto default_avatar = Interfaces::PixbufManipulator().generateAvatar(firstLetter, "ring:" + uri); - auto photo = Interfaces::PixbufManipulator().scaleAndFrame(default_avatar.get(), QSize(50, 50)); + GdkPixbuf *default_avatar = pxbm_generate_avatar(firstLetter, "ring:" + uri); + GdkPixbuf *photo = pxbm_scale_and_frame(default_avatar, QSize(50, 50)); + g_object_unref(default_avatar); if (!icon.empty()) { QByteArray byteArray(icon.c_str(), icon.length()); - QVariant avatar = Interfaces::PixbufManipulator().personPhoto(byteArray); - auto pixbuf_photo = Interfaces::PixbufManipulator().scaleAndFrame(avatar.value<std::shared_ptr<GdkPixbuf>>().get(), QSize(50, 50)); - if (avatar.isValid()) { - photo = pixbuf_photo; + GdkPixbuf *avatar = pxbm_person_photo(byteArray); + if (avatar) { + g_object_unref(photo); + photo = pxbm_scale_and_frame(avatar, QSize(50, 50)); + g_object_unref(avatar); } } - notify_notification_set_image_from_pixbuf(notification.get(), photo.get()); + notify_notification_set_image_from_pixbuf(notification.get(), photo); + g_object_unref(photo); if (type != NotificationType::CHAT) { notify_notification_set_urgency(notification.get(), NOTIFY_URGENCY_CRITICAL); diff --git a/src/profileview.cpp b/src/profileview.cpp index 2addac71..77e2c00b 100644 --- a/src/profileview.cpp +++ b/src/profileview.cpp @@ -31,7 +31,6 @@ #include <api/contact.h> #include <api/contactmodel.h> #include <api/conversationmodel.h> -#include <globalinstances.h> namespace { namespace details { class CppImpl; @@ -140,15 +139,14 @@ build_view(ProfileView* view) gtk_label_set_text(GTK_LABEL(priv->id_label), qUtf8Printable(contact.profileInfo.uri)); uint32_t img_size = 128; - std::shared_ptr<GdkPixbuf> image; - auto var_photo = GlobalInstances::pixmapManipulator().conversationPhoto( + GdkPixbuf *p = pxbm_conversation_photo( *convOpt, **(priv->accountInfo_), QSize(img_size, img_size), false ); - image = var_photo.value<std::shared_ptr<GdkPixbuf>>(); - gtk_image_set_from_pixbuf(GTK_IMAGE(priv->avatar), image.get()); + gtk_image_set_from_pixbuf(GTK_IMAGE(priv->avatar), p); + g_object_unref(p); auto* surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, img_size, img_size); auto* cr = cairo_create(surface); diff --git a/src/webkitchatcontainer.cpp b/src/webkitchatcontainer.cpp index 0c13bb24..83b30bb5 100644 --- a/src/webkitchatcontainer.cpp +++ b/src/webkitchatcontainer.cpp @@ -31,7 +31,6 @@ #include <QtCore/QJsonDocument> // LRC -#include <globalinstances.h> #include <api/conversationmodel.h> #include <api/account.h> #include <api/chatview.h> -- GitLab