diff --git a/.ci-scripts/build-local-qt.sh b/.ci-scripts/build-local-qt.sh index 831d213295..98a4b9882b 100755 --- a/.ci-scripts/build-local-qt.sh +++ b/.ci-scripts/build-local-qt.sh @@ -14,4 +14,5 @@ install_deps \ qttools \ qtsvg \ qtimageformats \ + qtremoteobjects \ qtwayland diff --git a/CMakeLists.txt b/CMakeLists.txt index 805161b662..8daf9c2a18 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -59,7 +59,7 @@ execute_process( OUTPUT_VARIABLE QT_PREFIX_PATH OUTPUT_STRIP_TRAILING_WHITESPACE) -project(qtox) +project(qtox LANGUAGES CXX) # C++ and C standards. set(CMAKE_CXX_STANDARD 20) @@ -262,6 +262,8 @@ set(${PROJECT_NAME}_SOURCES src/chatlog/customtextdocument.h src/chatlog/documentcache.cpp src/chatlog/documentcache.h + src/chatlog/imageloader.cpp + src/chatlog/imageloader.h src/chatlog/pixmapcache.cpp src/chatlog/pixmapcache.h src/core/toxfileprogress.cpp @@ -430,6 +432,12 @@ set(${PROJECT_NAME}_SOURCES src/platform/desktop_notifications/desktopnotifybackend.h src/platform/posixsignalnotifier.cpp src/platform/posixsignalnotifier.h + src/platform/sandbox.cpp + src/platform/sandbox.h + src/platform/sandboxclient.cpp + src/platform/sandboxclient.h + src/platform/sandboxserver.cpp + src/platform/sandboxserver.h src/platform/timer.h src/platform/timer_osx.cpp src/platform/timer_win.cpp @@ -653,6 +661,8 @@ add_subdirectory(cmake/warnings) add_library(${PROJECT_NAME}_static STATIC ${${PROJECT_NAME}_FORMS} ${${PROJECT_NAME}_SOURCES}) +qt_add_repc_sources(${PROJECT_NAME}_static src/platform/sandbox.rep) +qt_add_repc_replicas(${PROJECT_NAME}_static src/platform/sandbox.rep) target_link_libraries(${PROJECT_NAME}_static ${CMAKE_REQUIRED_LIBRARIES} ${ALL_LIBRARIES} coverage_config) @@ -667,8 +677,8 @@ if(COMMAND qt_policy) qt_policy(SET QTP0002 NEW) endif() -qt_add_executable(${PROJECT_NAME} WIN32 MACOSX_BUNDLE - ${${PROJECT_NAME}_RESOURCES} ${SMILEY_RESOURCES} src/main.cpp) +qt_add_executable(${PROJECT_NAME} ${${PROJECT_NAME}_RESOURCES} ${SMILEY_RESOURCES} src/main.cpp) +set_target_properties(${PROJECT_NAME} PROPERTIES WIN32_EXECUTABLE TRUE MACOSX_BUNDLE TRUE) target_link_libraries( ${PROJECT_NAME} PRIVATE ${PROJECT_NAME}_static ${CMAKE_REQUIRED_LIBRARIES} ${ALL_LIBRARIES}) diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake index 6370cd400e..e48a6ce379 100644 --- a/cmake/Dependencies.cmake +++ b/cmake/Dependencies.cmake @@ -9,16 +9,18 @@ ################################################################################ # This should go into subdirectories later. -find_package(PkgConfig REQUIRED) -find_package(Qt6Concurrent REQUIRED) -find_package(Qt6Core REQUIRED) -find_package(Qt6Gui REQUIRED) -find_package(Qt6Linguist REQUIRED) -find_package(Qt6Network REQUIRED) -find_package(Qt6Svg REQUIRED) -find_package(Qt6Test REQUIRED) -find_package(Qt6Widgets REQUIRED) -find_package(Qt6Xml REQUIRED) +find_package(PkgConfig REQUIRED) +find_package(Qt6 REQUIRED COMPONENTS + Concurrent + Core + Gui + Linguist + Network + RemoteObjects + Svg + Test + Widgets + Xml) function(add_dependency) set(ALL_LIBRARIES ${ALL_LIBRARIES} ${ARGN} PARENT_SCOPE) @@ -29,6 +31,7 @@ add_dependency( Qt6::Core Qt6::Gui Qt6::Network + Qt6::RemoteObjects Qt6::Svg Qt6::Widgets Qt6::Xml) @@ -214,7 +217,7 @@ if(QT_FEATURE_static) find_library(KIMG_${fmt_lib}_LIBRARY kimg_${fmt} PATHS "${QT6_INSTALL_PREFIX}/plugins/imageformats") if(KIMG_${fmt_lib}_LIBRARY) - message(STATUS "Found ${fmt_lib} imageformats plugin: ${KIMG_${fmt}_LIBRARY}") + message(STATUS "Found ${fmt_lib} imageformats plugin: ${KIMG_${fmt_lib}_LIBRARY}") add_dependency(${KIMG_${fmt_lib}_LIBRARY}) set_property(SOURCE src/main.cpp APPEND PROPERTY COMPILE_DEFINITIONS QTOX_USE_KIMG_${fmt_lib}) else() diff --git a/src/BUILD.bazel b/src/BUILD.bazel index 37f3efaa86..e3f6079d20 100644 --- a/src/BUILD.bazel +++ b/src/BUILD.bazel @@ -1,5 +1,5 @@ load("@rules_cc//cc:defs.bzl", "cc_library", "objc_library") -load("//third_party/qt:build_defs.bzl", "qt_moc", "qt_uic") +load("//third_party/qt:build_defs.bzl", "qt_moc", "qt_repc", "qt_uic") load("//tools/project:build_defs.bzl", "mkstamp") DEFINES = [ @@ -10,6 +10,20 @@ DEFINES = [ "UPDATE_CHECK_ENABLED", ] +qt_repc( + name = "src_repc_source", + srcs = ["platform/sandbox.rep"], + tags = ["qt"], + type = "source", +) + +qt_repc( + name = "src_repc_replica", + srcs = ["platform/sandbox.rep"], + tags = ["qt"], + type = "replica", +) + qt_moc( name = "src_moc", srcs = [ @@ -24,6 +38,7 @@ qt_moc( "chatlog/content/text.h", "chatlog/content/timestamp.h", "chatlog/customtextdocument.h", + "chatlog/imageloader.h", "core/core.h", "core/coreav.h", "core/corefile.h", @@ -60,6 +75,9 @@ qt_moc( "platform/desktop_notifications/desktopnotify.h", "platform/desktop_notifications/desktopnotifybackend.h", "platform/posixsignalnotifier.h", + "platform/sandbox.h", + "platform/sandboxclient.h", + "platform/sandboxserver.h", "video/camerasource.h", "video/corevideosource.h", "video/netcamview.h", @@ -124,15 +142,19 @@ qt_moc( "widget/tool/screenshotgrabber.h", "widget/tool/toolboxgraphicsitem.h", "widget/widget.h", + ":src_repc_replica", + ":src_repc_source", ], hdrs = glob(["**/*.h"]), mocopts = [ "-Iqtox", + "-Iqtox/src", "-Iqtox/util/include", ] + ["-D%s=1" % d for d in DEFINES], tags = ["qt"], deps = [ "//qtox/util", + "@qt//:qt_remoteobjects", "@qt//:qt_widgets", ], ) @@ -166,6 +188,7 @@ mkstamp( COPTS = [ "-Iqtox", "-I$(GENDIR)/qtox", + "-I$(GENDIR)/qtox/src/platform", ] + select({ "//tools/config:freebsd": [], "//tools/config:linux": ["-fPIC"], @@ -187,6 +210,8 @@ cc_library( name = "src", srcs = [":version"] + [ ":src_moc", + ":src_repc_replica", + ":src_repc_source", ":src_ui", ] + glob( ["**/*.cpp"], @@ -227,6 +252,7 @@ cc_library( "@qt//:qt_dbus", "@qt//:qt_gui", "@qt//:qt_network", + "@qt//:qt_remoteobjects", "@qt//:qt_svg", "@qt//:qt_widgets", "@qt//:qt_xml", @@ -245,15 +271,7 @@ cc_library( cc_library( name = "main", srcs = ["main.cpp"], - copts = [ - "-Iqtox", - "-I$(GENDIR)/qtox", - ] + select({ - "//tools/config:freebsd": [], - "//tools/config:linux": ["-fPIC"], - "//tools/config:osx": [], - "//tools/config:windows": [], - }), + copts = COPTS, tags = ["qt"], visibility = ["//qtox:__subpackages__"], deps = [ diff --git a/src/appmanager.cpp b/src/appmanager.cpp index 5d0ea444dd..42df79bb03 100644 --- a/src/appmanager.cpp +++ b/src/appmanager.cpp @@ -13,6 +13,8 @@ #include "src/persistence/settings.h" #include "src/persistence/toxsave.h" #include "src/platform/posixsignalnotifier.h" +#include "src/platform/sandboxclient.h" +#include "src/platform/sandboxserver.h" #include "src/version.h" #include "src/video/camerasource.h" #include "src/widget/tool/messageboxmanager.h" @@ -25,6 +27,7 @@ #include #include #include +#include namespace { // logMessageHandler and associated data must be static due to qInstallMessageHandler's @@ -189,7 +192,6 @@ AppManager::AppManager(int& argc, char** argv) : qapp((preConstructionInitialization(), new QApplication(argc, argv))) , messageBoxManager(new MessageBoxManager(nullptr)) , settings(new Settings(*messageBoxManager)) - , ipc(new IPC(settings->getCurrentProfileId())) { } @@ -200,6 +202,37 @@ void AppManager::preConstructionInitialization() int AppManager::startGui(QCommandLineParser& parser) { + // Terminating signals are connected directly to quit() without any filtering. + connect(&PosixSignalNotifier::globalInstance(), &PosixSignalNotifier::terminatingSignal, + qapp.get(), &QApplication::quit); + PosixSignalNotifier::watchCommonTerminatingSignals(); + + // User signal 1 is used to screenshot the application. + connect(&PosixSignalNotifier::globalInstance(), &PosixSignalNotifier::usrSignal, qapp.get(), + [this](PosixSignalNotifier::UserSignal signal) { + if (signal == PosixSignalNotifier::UserSignal::Screenshot) { + nexus->screenshot(); + } + }); + PosixSignalNotifier::watchUsrSignals(); + + // Install Unicode 6.1 supporting font + // Keep this as close to the beginning of `main()` as possible, otherwise + // on systems that have poor support for Unicode qTox will look bad. + if (QFontDatabase::addApplicationFont(":/font/DejaVuSans.ttf") == -1) { + qWarning() << "Couldn't load font"; + } + + if (parser.isSet("portable")) { + // We don't go through settings here, because we're not making qTox + // portable (which moves files around). Instead, we start up in + // portable mode as a one-off. + settings->getPaths().setPortable(true); + settings->getPaths().setPortablePath(parser.value("portable")); + } + + ipc = std::make_unique(settings->getCurrentProfileId()); + if (ipc->isAttached()) { connect(settings.get(), &Settings::currentProfileIdChanged, ipc.get(), &IPC::setProfileId); } else { @@ -253,6 +286,14 @@ int AppManager::startGui(QCommandLineParser& parser) qDebug() << "Commit:" << VersionInfo::gitVersion(); qDebug() << "Process ID:" << QCoreApplication::applicationPid(); + if (settings->getExperimentalSandbox()) { + sandbox = std::make_unique(this); + qDebug() << "Sandbox ready:" << sandbox->isReady(); + } else { + sandbox = std::make_unique(this); + qDebug() << "Sandbox disabled"; + } + QString profileName; bool autoLogin = settings->getAutoLogin(); @@ -317,7 +358,7 @@ int AppManager::startGui(QCommandLineParser& parser) // note: Because Settings is shouldering global settings as well as model specific ones it // cannot be integrated into a central model object yet cameraSource = std::unique_ptr(new CameraSource{*settings}); - nexus = std::unique_ptr(new Nexus{*settings, *messageBoxManager, *cameraSource, *ipc}); + nexus = std::unique_ptr(new Nexus{*settings, *messageBoxManager, *cameraSource, *ipc, *sandbox}); // Autologin // TODO (kriby): Shift responsibility of linking views to model objects from nexus // Further: generate view instances separately (loginScreen, mainGUI, audio) @@ -364,20 +405,6 @@ int AppManager::startGui(QCommandLineParser& parser) int AppManager::run() { - // Terminating signals are connected directly to quit() without any filtering. - connect(&PosixSignalNotifier::globalInstance(), &PosixSignalNotifier::terminatingSignal, - qapp.get(), &QApplication::quit); - PosixSignalNotifier::watchCommonTerminatingSignals(); - - // User signal 1 is used to screenshot the application. - connect(&PosixSignalNotifier::globalInstance(), &PosixSignalNotifier::usrSignal, qapp.get(), - [this](PosixSignalNotifier::UserSignal signal) { - if (signal == PosixSignalNotifier::UserSignal::Screenshot) { - nexus->screenshot(); - } - }); - PosixSignalNotifier::watchUsrSignals(); - qapp->setApplicationName("qTox"); qapp->setDesktopFileName("io.github.qtox.qTox"); qapp->setApplicationVersion(QStringLiteral("%1, git commit %2 (%3)") @@ -387,13 +414,6 @@ int AppManager::run() ? QStringLiteral("stable") : QStringLiteral("unstable"))); - // Install Unicode 6.1 supporting font - // Keep this as close to the beginning of `main()` as possible, otherwise - // on systems that have poor support for Unicode qTox will look bad. - if (QFontDatabase::addApplicationFont("://font/DejaVuSans.ttf") == -1) { - qWarning() << "Couldn't load font"; - } - QString locale = settings->getTranslation(); // We need to init the resources in the translations_library explicitly. // See https://doc.qt.io/qt-5/resources.html#using-resources-in-a-library @@ -417,17 +437,10 @@ int AppManager::run() #ifdef UPDATE_CHECK_ENABLED {{"u", "update-check"}, tr("Checks whether this program is running the latest qTox version.")}, #endif // UPDATE_CHECK_ENABLED + {{"S", "sandbox"}, tr("Start the qTox sandbox process (internal, don't use).")}, }); parser.process(*qapp); - if (parser.isSet("portable")) { - // We don't go through settings here, because we're not making qTox - // portable (which moves files around). Instead, we start up in - // portable mode as a one-off. - settings->getPaths().setPortable(true); - settings->getPaths().setPortablePath(parser.value("portable")); - } - // If update-check is requested, do it and exit. if (parser.isSet("update-check")) { UpdateCheck* updateCheck = new UpdateCheck(*settings, qapp.get()); @@ -442,11 +455,20 @@ int AppManager::run() QTextStream(stdout) << message; qapp->quit(); }); - } else { - const int result = startGui(parser); - if (result != 0) { - return result; - } + return qapp->exec(); + } + + if (parser.isSet("sandbox")) { + // Start the sandbox process. + SandboxServer sandboxServer; + QRemoteObjectHost srcNode(QUrl(QStringLiteral("local:replica"))); + srcNode.enableRemoting(&sandboxServer); + return qapp->exec(); + } + + const int result = startGui(parser); + if (result != 0) { + return result; } return qapp->exec(); diff --git a/src/appmanager.h b/src/appmanager.h index efd000f138..dce85163da 100644 --- a/src/appmanager.h +++ b/src/appmanager.h @@ -9,14 +9,15 @@ #include -class MessageBoxManager; -class Settings; +class CameraSource; class IPC; +class MessageBoxManager; +class Nexus; class QApplication; class QCommandLineParser; +class Sandbox; +class Settings; class ToxURIDialog; -class Nexus; -class CameraSource; class AppManager : public QObject { @@ -42,4 +43,5 @@ private slots: std::unique_ptr uriDialog; std::unique_ptr cameraSource; std::unique_ptr nexus; + std::unique_ptr sandbox; }; diff --git a/src/chatlog/chatmessage.cpp b/src/chatlog/chatmessage.cpp index 218586abcb..dbbff48b18 100644 --- a/src/chatlog/chatmessage.cpp +++ b/src/chatlog/chatmessage.cpp @@ -4,7 +4,6 @@ */ #include "chatmessage.h" -#include "chatlinecontentproxy.h" #include "textformatter.h" #include "content/broken.h" #include "content/filetransferwidget.h" @@ -13,6 +12,7 @@ #include "content/spinner.h" #include "content/text.h" #include "content/timestamp.h" +#include "src/chatlog/chatlinecontentproxy.h" #include "src/widget/style.h" #include "src/widget/tool/identicon.h" @@ -165,7 +165,7 @@ ChatMessage::Ptr ChatMessage::createFileTransferMessage(const QString& sender, C ToxFile file, bool isMe, const QDateTime& date, DocumentCache& documentCache, Settings& settings, Style& style, - IMessageBoxManager& messageBoxManager) + IMessageBoxManager& messageBoxManager, ImageLoader& imageLoader) { ChatMessage::Ptr msg = ChatMessage::Ptr(new ChatMessage(documentCache, settings, style)); @@ -178,7 +178,7 @@ ChatMessage::Ptr ChatMessage::createFileTransferMessage(const QString& sender, C msg->addColumn(new Text(documentCache, settings, style, sender, authorFont, true), ColumnFormat(NAME_COL_WIDTH, ColumnFormat::FixedSize, ColumnFormat::Right)); msg->addColumn(new ChatLineContentProxy(new FileTransferWidget(nullptr, coreFile, file, settings, - style, messageBoxManager), + style, messageBoxManager, imageLoader), 320, 0.6f), ColumnFormat(1.0, ColumnFormat::VariableSize)); msg->addColumn(new Timestamp(date, settings.getTimestampFormat(), baseFont, documentCache, diff --git a/src/chatlog/chatmessage.h b/src/chatlog/chatmessage.h index c695c38476..1e9e2984aa 100644 --- a/src/chatlog/chatmessage.h +++ b/src/chatlog/chatmessage.h @@ -12,12 +12,13 @@ #include class CoreFile; -class QGraphicsScene; class DocumentCache; -class SmileyPack; +class IMessageBoxManager; +class QGraphicsScene; +class ImageLoader; class Settings; +class SmileyPack; class Style; -class IMessageBoxManager; class ChatMessage : public ChatLine { @@ -55,7 +56,7 @@ class ChatMessage : public ChatLine ToxFile file, bool isMe, const QDateTime& date, DocumentCache& documentCache, Settings& settings, Style& style, - IMessageBoxManager& messageBoxManager); + IMessageBoxManager& messageBoxManager, ImageLoader& imageLoader); static ChatMessage::Ptr createTypingNotification(DocumentCache& documentCache, Settings& settings, Style& style); static ChatMessage::Ptr createBusyNotification(DocumentCache& documentCache, Settings& settings, diff --git a/src/chatlog/chatwidget.cpp b/src/chatlog/chatwidget.cpp index ea939fc8bf..93f3a59901 100644 --- a/src/chatlog/chatwidget.cpp +++ b/src/chatlog/chatwidget.cpp @@ -14,7 +14,6 @@ #include "src/persistence/settings.h" #include "src/widget/style.h" #include "src/widget/translator.h" -#include #include #include @@ -27,8 +26,6 @@ #include #include -#include - namespace { @@ -194,7 +191,7 @@ ChatLogIdx clampedAdd(ChatLogIdx idx, int val, IChatLog& chatLog) ChatWidget::ChatWidget(IChatLog& chatLog_, const Core& core_, DocumentCache& documentCache_, SmileyPack& smileyPack_, Settings& settings_, Style& style_, - IMessageBoxManager& messageBoxManager_, QWidget* parent) + IMessageBoxManager& messageBoxManager_, ImageLoader& imageLoader_, QWidget* parent) : QGraphicsView(parent) , selectionRectColor{style_.getColor(Style::ColorPalette::SelectText)} , chatLog(chatLog_) @@ -205,6 +202,7 @@ ChatWidget::ChatWidget(IChatLog& chatLog_, const Core& core_, DocumentCache& doc , settings(settings_) , style{style_} , messageBoxManager{messageBoxManager_} + , imageLoader{imageLoader_} { // Create the scene busyScene = new QGraphicsScene(this); @@ -1439,7 +1437,7 @@ void ChatWidget::renderFile(QString displayName, ToxFile file, bool isSelf, QDat assert(coreFile); chatMessage = ChatMessage::createFileTransferMessage(displayName, *coreFile, file, isSelf, timestamp, documentCache, settings, - style, messageBoxManager); + style, messageBoxManager, imageLoader); } else { auto proxy = static_cast(chatMessage->getContent(1)); assert(proxy->getWidgetType() == ChatLineContentProxy::FileTransferWidgetType); diff --git a/src/chatlog/chatwidget.h b/src/chatlog/chatwidget.h index 2e81157e04..03347bb909 100644 --- a/src/chatlog/chatwidget.h +++ b/src/chatlog/chatwidget.h @@ -13,17 +13,18 @@ #include "chatmessage.h" #include "src/model/ichatlog.h" -class QGraphicsScene; +class ChatLineContent; +class ChatLineStorage; +class IMessageBoxManager; class QGraphicsRectItem; +class QGraphicsScene; class QMouseEvent; class QTimer; -class ChatLineContent; -struct ToxFile; -class SmileyPack; +class ImageLoader; class Settings; +class SmileyPack; class Style; -class ChatLineStorage; -class IMessageBoxManager; +struct ToxFile; static const size_t DEF_NUM_MSG_TO_LOAD = 100; class ChatWidget : public QGraphicsView @@ -32,7 +33,7 @@ class ChatWidget : public QGraphicsView public: ChatWidget(IChatLog& chatLog_, const Core& core_, DocumentCache& documentCache, SmileyPack& smileyPack, Settings& settings, Style& style, - IMessageBoxManager& messageBoxManager, QWidget* parent = nullptr); + IMessageBoxManager& messageBoxManager, ImageLoader& imageLoader, QWidget* parent = nullptr); ~ChatWidget() override; void insertChatlines(std::map chatLines); @@ -216,4 +217,5 @@ private slots: Settings& settings; Style& style; IMessageBoxManager& messageBoxManager; + ImageLoader& imageLoader; }; diff --git a/src/chatlog/content/filetransferwidget.cpp b/src/chatlog/content/filetransferwidget.cpp index 35404be174..3885f52ef1 100644 --- a/src/chatlog/content/filetransferwidget.cpp +++ b/src/chatlog/content/filetransferwidget.cpp @@ -7,7 +7,6 @@ #include "ui_filetransferwidget.h" #include "src/core/corefile.h" -#include "src/model/exiftransform.h" #include "src/persistence/settings.h" #include "src/widget/style.h" #include "src/widget/tool/imessageboxmanager.h" @@ -22,10 +21,10 @@ #include #include #include +#include #include #include -#include // The leftButton is used to accept, pause, or resume a file transfer, as well as to open a @@ -35,7 +34,8 @@ FileTransferWidget::FileTransferWidget(QWidget* parent, CoreFile& _coreFile, ToxFile file, Settings& settings_, Style& style_, - IMessageBoxManager& messageBoxManager_) + IMessageBoxManager& messageBoxManager_, + ImageLoader& imageLoader_) : QWidget(parent) , coreFile{_coreFile} , ui(new Ui::FileTransferWidget) @@ -47,6 +47,7 @@ FileTransferWidget::FileTransferWidget(QWidget* parent, CoreFile& _coreFile, Tox , settings(settings_) , style{style_} , messageBoxManager{messageBoxManager_} + , imageLoader{imageLoader_} { ui->setupUi(this); @@ -195,7 +196,7 @@ void FileTransferWidget::paintEvent(QPaintEvent* event) buttonFieldWidth, buttonFieldWidth + lineWidth, 50, 50, Qt::RelativeSize); buttonBackground.addRect(width() - 2 * buttonFieldWidth - lineWidth * 2, 0, - buttonFieldWidth * 2, buttonFieldWidth / 2); + buttonFieldWidth * 2, static_cast(buttonFieldWidth) / 2); buttonBackground.addRect(width() - 1.5 * buttonFieldWidth - lineWidth * 2, 0, buttonFieldWidth * 2, buttonFieldWidth + 1); buttonBackground.setFillRule(Qt::WindingFill); @@ -208,7 +209,7 @@ void FileTransferWidget::paintEvent(QPaintEvent* event) buttonFieldWidth, buttonFieldWidth), 50, 50, Qt::RelativeSize); leftButton.addRect(QRect(width() - 2 * buttonFieldWidth - lineWidth, 0, - buttonFieldWidth / 2, buttonFieldWidth / 2)); + buttonFieldWidth / 2, static_cast(buttonFieldWidth) / 2)); leftButton.addRect(QRect(width() - 1.5 * buttonFieldWidth - lineWidth, 0, buttonFieldWidth / 2, buttonFieldWidth)); leftButton.setFillRule(Qt::WindingFill); @@ -478,7 +479,7 @@ void FileTransferWidget::handleButton(QPushButton* btn) void FileTransferWidget::showPreview(const QString& filename) { - ui->previewButton->setIconFromFile(filename); + ui->previewButton->setIconFromFile(imageLoader, filename); ui->previewButton->show(); } diff --git a/src/chatlog/content/filetransferwidget.h b/src/chatlog/content/filetransferwidget.h index 0c5f5e3a18..30063cf264 100644 --- a/src/chatlog/content/filetransferwidget.h +++ b/src/chatlog/content/filetransferwidget.h @@ -8,7 +8,6 @@ #include #include -#include "src/chatlog/chatlinecontent.h" #include "src/core/toxfile.h" class CoreFile; @@ -17,11 +16,12 @@ namespace Ui { class FileTransferWidget; } -class QVariantAnimation; +class IMessageBoxManager; class QPushButton; +class QVariantAnimation; +class ImageLoader; class Settings; class Style; -class IMessageBoxManager; class FileTransferWidget : public QWidget { @@ -29,7 +29,7 @@ class FileTransferWidget : public QWidget public: FileTransferWidget(QWidget* parent, CoreFile& _coreFile, ToxFile file, Settings& settings, - Style& style, IMessageBoxManager& messageBoxManager); + Style& style, IMessageBoxManager& messageBoxManager, ImageLoader& imageLoader); ~FileTransferWidget() override; bool isActive() const; void onFileTransferUpdate(ToxFile file); @@ -81,4 +81,5 @@ private slots: Settings& settings; Style& style; IMessageBoxManager& messageBoxManager; + ImageLoader& imageLoader; }; diff --git a/src/chatlog/imageloader.cpp b/src/chatlog/imageloader.cpp new file mode 100644 index 0000000000..77afcc3d2e --- /dev/null +++ b/src/chatlog/imageloader.cpp @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2025 The TokTok team. + */ + +#include "imageloader.h" + +ImageLoader::~ImageLoader() = default; diff --git a/src/chatlog/imageloader.h b/src/chatlog/imageloader.h new file mode 100644 index 0000000000..86f9f4ec8f --- /dev/null +++ b/src/chatlog/imageloader.h @@ -0,0 +1,16 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2025 The TokTok team. + */ + +#pragma once + +class QPixmap; +class QByteArray; + +class ImageLoader +{ +public: + virtual ~ImageLoader(); + + virtual QPixmap loadImage(const QByteArray& data) = 0; +}; diff --git a/src/nexus.cpp b/src/nexus.cpp index 4f9ae2d07a..901ea5d89a 100644 --- a/src/nexus.cpp +++ b/src/nexus.cpp @@ -48,7 +48,7 @@ Q_DECLARE_OPAQUE_POINTER(ToxAV*) Nexus::Nexus(Settings& settings_, IMessageBoxManager& messageBoxManager_, - CameraSource& cameraSource_, IPC& ipc_, QObject* parent) + CameraSource& cameraSource_, IPC& ipc_, ImageLoader& imageLoader_, QObject* parent) : QObject(parent) , profile{nullptr} , settings{settings_} @@ -57,6 +57,7 @@ Nexus::Nexus(Settings& settings_, IMessageBoxManager& messageBoxManager_, , style{new Style()} , messageBoxManager{messageBoxManager_} , ipc{ipc_} + , imageLoader{imageLoader_} { QObject::connect(this, &Nexus::saveGlobal, &settings, &Settings::saveGlobal); } @@ -220,8 +221,8 @@ void Nexus::showMainGUI() assert(profile); // Create GUI - widget = - std::make_unique(*profile, *audioControl, cameraSource, settings, *style, ipc, *this); + widget = std::make_unique(*profile, *audioControl, cameraSource, settings, *style, ipc, + imageLoader, *this); // Start GUI widget->init(); diff --git a/src/nexus.h b/src/nexus.h index 5a1c2e3bf7..ab3ad46604 100644 --- a/src/nexus.h +++ b/src/nexus.h @@ -12,16 +12,17 @@ #include -class Widget; -class Profile; -class Settings; -class LoginScreen; -class Core; -class QCommandLineParser; class CameraSource; -class Style; +class Core; +class ImageLoader; class IMessageBoxManager; class IPC; +class LoginScreen; +class Profile; +class QCommandLineParser; +class Settings; +class Style; +class Widget; #ifdef Q_OS_MAC class QMenuBar; @@ -37,7 +38,7 @@ class Nexus : public QObject Q_OBJECT public: Nexus(Settings& settings, IMessageBoxManager& messageBoxManager, CameraSource& cameraSource, - IPC& ipc, QObject* parent = nullptr); + IPC& ipc, ImageLoader& imageLoader, QObject* parent = nullptr); ~Nexus() override; void start(); void showMainGUI(); @@ -99,4 +100,5 @@ public slots: std::unique_ptr