1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

refactor(Nexus): Remove singleton, construct with needed arguments

This commit is contained in:
Anthony Bilinski 2022-03-28 06:42:19 -07:00
parent 0e7da7378f
commit b394f22599
No known key found for this signature in database
GPG Key ID: 2AA8E0DA1B31FB3C
8 changed files with 75 additions and 114 deletions

View File

@ -28,6 +28,7 @@
#include "src/nexus.h"
#include "src/net/toxuri.h"
#include "src/widget/widget.h"
#include "src/video/camerasource.h"
#if defined(Q_OS_UNIX)
#include "src/platform/posixsignalnotifier.h"
@ -355,35 +356,31 @@ int AppManager::run()
return -1;
}
// TODO(sudden6): remove once we get rid of Nexus
Nexus& nexus = Nexus::getInstance();
// TODO(kriby): Consider moving application initializing variables into a globalSettings object
// note: Because Settings is shouldering global settings as well as model specific ones it
// cannot be integrated into a central model object yet
nexus.setSettings(settings.get());
nexus.setMessageBoxManager(messageBoxManager.get());
nexus.setIpc(ipc.get());
auto& cameraSource = nexus.getCameraSource();
cameraSource = std::unique_ptr<CameraSource>(new CameraSource{*settings});
nexus = std::unique_ptr<Nexus>(new Nexus{*settings, *messageBoxManager, *cameraSource, *ipc});
// Autologin
// TODO (kriby): Shift responsibility of linking views to model objects from nexus
// Further: generate view instances separately (loginScreen, mainGUI, audio)
Profile* profile = nullptr;
if (autoLogin && Profile::exists(profileName, settings->getPaths()) && !Profile::isEncrypted(profileName, settings->getPaths())) {
profile = Profile::loadProfile(profileName, QString(), *settings, &parser, cameraSource, *messageBoxManager);
profile = Profile::loadProfile(profileName, QString(), *settings, &parser, *cameraSource, *messageBoxManager);
if (!profile) {
QMessageBox::information(nullptr, tr("Error"),
tr("Failed to load profile automatically."));
}
}
if (profile) {
nexus.bootstrapWithProfile(profile);
nexus->bootstrapWithProfile(profile);
} else {
nexus.setParser(&parser);
int returnval = nexus.showLogin(profileName);
nexus->setParser(&parser);
int returnval = nexus->showLogin(profileName);
if (returnval == QDialog::Rejected) {
return -1;
}
profile = nexus.getProfile();
profile = nexus->getProfile();
}
uriDialog = std::unique_ptr<ToxURIDialog>(new ToxURIDialog(nullptr, profile->getCore(), *messageBoxManager));
@ -391,14 +388,14 @@ int AppManager::run()
if (ipc->isAttached()) {
// Start to accept Inter-process communication
ipc->registerEventHandler("uri", &toxURIEventHandler, uriDialog.get());
nexus.registerIpcHandlers();
nexus->registerIpcHandlers();
}
// Event was not handled by already running instance therefore we handle it ourselves
if (eventType == "uri") {
uriDialog->handleToxURI(firstParam);
} else if (eventType == ToxSave::eventHandlerKey) {
nexus.handleToxSave(firstParam);
nexus->handleToxSave(firstParam);
}
connect(qapp.get(), &QApplication::aboutToQuit, this, &AppManager::cleanup);
@ -413,14 +410,14 @@ void AppManager::cleanup()
// force save early even though destruction saves, because Windows OS will
// close qTox before cleanup() is finished if logging out or shutting down,
// once the top level window has exited, which occurs in ~Widget within
// ~Nexus. Re-ordering Nexus destruction is not trivial.
// ~nexus-> Re-ordering Nexus destruction is not trivial.
if (settings) {
settings->saveGlobal();
settings->savePersonal();
settings->sync();
}
Nexus::destroyInstance();
nexus.reset();
settings.reset();
qDebug() << "Cleanup success";

View File

@ -28,6 +28,8 @@ class Settings;
class IPC;
class QApplication;
class ToxURIDialog;
class Nexus;
class CameraSource;
class AppManager : public QObject
{
@ -47,4 +49,6 @@ private:
std::unique_ptr<Settings> settings;
std::unique_ptr<IPC> ipc;
std::unique_ptr<ToxURIDialog> uriDialog;
std::unique_ptr<CameraSource> cameraSource;
std::unique_ptr<Nexus> nexus;
};

View File

@ -99,10 +99,11 @@ bool tryRemoveFile(const QString& filepath)
* @param profile Pointer to Profile.
* @note All pointers parameters shouldn't be null.
*/
ProfileInfo::ProfileInfo(Core* core_, Profile* profile_, Settings& settings_)
ProfileInfo::ProfileInfo(Core* core_, Profile* profile_, Settings& settings_, Nexus& nexus_)
: profile{profile_}
, core{core_}
, settings{settings_}
, nexus{nexus_}
{
connect(core_, &Core::idSet, this, &ProfileInfo::idChanged);
connect(core_, &Core::usernameSet, this, &ProfileInfo::usernameChanged);
@ -235,7 +236,7 @@ IProfileInfo::SaveResult ProfileInfo::exportProfile(const QString& path) const
QStringList ProfileInfo::removeProfile()
{
QStringList manualDeleteFiles = profile->remove();
QMetaObject::invokeMethod(&Nexus::getInstance(), "showLogin");
QMetaObject::invokeMethod(&nexus, "showLogin");
return manualDeleteFiles;
}
@ -246,7 +247,7 @@ void ProfileInfo::logout()
{
// TODO(kriby): Refactor all of these invokeMethod calls with connect() properly when possible
settings.saveGlobal();
QMetaObject::invokeMethod(&Nexus::getInstance(), "showLogin",
QMetaObject::invokeMethod(&nexus, "showLogin",
Q_ARG(QString, settings.getCurrentProfile()));
}

View File

@ -29,12 +29,13 @@ class QFile;
class QPoint;
class Profile;
class Settings;
class Nexus;
class ProfileInfo : public QObject, public IProfileInfo
{
Q_OBJECT
public:
ProfileInfo(Core* core_, Profile* profile_, Settings& settings);
ProfileInfo(Core* core_, Profile* profile_, Settings& settings, Nexus& nexus);
bool setPassword(const QString& password) override;
bool deletePassword() override;
@ -68,4 +69,5 @@ private:
Profile* const profile;
Core* const core;
Settings& settings;
Nexus& nexus;
};

View File

@ -31,6 +31,7 @@
#include "widget/loginscreen.h"
#include "src/widget/tool/messageboxmanager.h"
#include "audio/audio.h"
#include "src/ipc.h"
#include <QApplication>
#include <QCommandLineParser>
@ -59,16 +60,18 @@
Q_DECLARE_OPAQUE_POINTER(ToxAV*)
namespace {
Nexus* nexus{nullptr};
} // namespace
Nexus::Nexus(QObject* parent)
Nexus::Nexus(Settings& settings_, IMessageBoxManager& messageBoxManager_,
CameraSource& cameraSource_, IPC& ipc_, QObject* parent)
: QObject(parent)
, profile{nullptr}
, settings{settings_}
, widget{nullptr}
, cameraSource{cameraSource_}
, style{new Style()}
, messageBoxManager{messageBoxManager_}
, ipc{ipc_}
{
QObject::connect(this, &Nexus::saveGlobal, &settings, &Settings::saveGlobal);
}
Nexus::~Nexus()
@ -166,7 +169,7 @@ int Nexus::showLogin(const QString& profileName)
delete profile;
profile = nullptr;
LoginScreen loginScreen{*settings, *style, profileName};
LoginScreen loginScreen{settings, *style, profileName};
connectLoginScreen(loginScreen);
QCoreApplication::sendPostedEvents(nullptr, QEvent::DeferredDelete);
@ -192,25 +195,13 @@ void Nexus::bootstrapWithProfile(Profile* p)
profile = p;
if (profile) {
audioControl = std::unique_ptr<IAudioControl>(Audio::makeAudio(*settings));
audioControl = std::unique_ptr<IAudioControl>(Audio::makeAudio(settings));
assert(audioControl != nullptr);
profile->getCore().getAv()->setAudio(*audioControl);
start();
}
}
void Nexus::setSettings(Settings* settings_)
{
cameraSource = std::unique_ptr<CameraSource>(new CameraSource{*settings_});
if (settings) {
QObject::disconnect(this, &Nexus::saveGlobal, settings, &Settings::saveGlobal);
}
settings = settings_;
if (settings) {
QObject::connect(this, &Nexus::saveGlobal, settings, &Settings::saveGlobal);
}
}
void Nexus::connectLoginScreen(const LoginScreen& loginScreen)
{
// TODO(kriby): Move connect sequences to a controller class object instead
@ -222,10 +213,10 @@ void Nexus::connectLoginScreen(const LoginScreen& loginScreen)
QObject::connect(&loginScreen, &LoginScreen::createNewProfile, this, &Nexus::onCreateNewProfile);
QObject::connect(&loginScreen, &LoginScreen::loadProfile, this, &Nexus::onLoadProfile);
// LoginScreen -> Settings
QObject::connect(&loginScreen, &LoginScreen::autoLoginChanged, settings, &Settings::setAutoLogin);
QObject::connect(&loginScreen, &LoginScreen::autoLoginChanged, settings, &Settings::saveGlobal);
QObject::connect(&loginScreen, &LoginScreen::autoLoginChanged, &settings, &Settings::setAutoLogin);
QObject::connect(&loginScreen, &LoginScreen::autoLoginChanged, &settings, &Settings::saveGlobal);
// Settings -> LoginScreen
QObject::connect(settings, &Settings::autoLoginChanged, &loginScreen,
QObject::connect(&settings, &Settings::autoLoginChanged, &loginScreen,
&LoginScreen::onAutoLoginChanged);
}
@ -235,8 +226,8 @@ void Nexus::showMainGUI()
assert(profile);
// Create GUI
widget = new Widget(*profile, *audioControl, *cameraSource, *settings, *style,
*ipc);
widget = new Widget(*profile, *audioControl, cameraSource, settings, *style,
ipc, *this);
// Start GUI
widget->init();
@ -262,23 +253,6 @@ void Nexus::showMainGUI()
widget->setEnabled(true);
}
/**
* @brief Returns the singleton instance.
*/
Nexus& Nexus::getInstance()
{
if (!nexus)
nexus = new Nexus;
return *nexus;
}
void Nexus::destroyInstance()
{
delete nexus;
nexus = nullptr;
}
/**
* @brief Get current user profile.
* @return nullptr if not started, profile otherwise.
@ -295,8 +269,8 @@ Profile* Nexus::getProfile()
*/
void Nexus::onCreateNewProfile(const QString& name, const QString& pass)
{
setProfile(Profile::createProfile(name, pass, *settings, parser, *cameraSource,
*messageBoxManager));
setProfile(Profile::createProfile(name, pass, settings, parser, cameraSource,
messageBoxManager));
parser = nullptr; // only apply cmdline proxy settings once
}
@ -305,8 +279,8 @@ void Nexus::onCreateNewProfile(const QString& name, const QString& pass)
*/
void Nexus::onLoadProfile(const QString& name, const QString& pass)
{
setProfile(Profile::loadProfile(name, pass, *settings, parser, *cameraSource,
*messageBoxManager));
setProfile(Profile::loadProfile(name, pass, settings, parser, cameraSource,
messageBoxManager));
parser = nullptr; // only apply cmdline proxy settings once
}
/**
@ -331,21 +305,6 @@ void Nexus::setParser(QCommandLineParser* parser_)
parser = parser_;
}
CameraSource& Nexus::getCameraSource()
{
return *cameraSource;
}
void Nexus::setMessageBoxManager(IMessageBoxManager* messageBoxManager_)
{
messageBoxManager = messageBoxManager_;
}
void Nexus::setIpc(IPC* ipc_)
{
ipc = ipc_;
}
void Nexus::registerIpcHandlers()
{
widget->registerIpcHandlers();

View File

@ -50,16 +50,13 @@ class Nexus : public QObject
{
Q_OBJECT
public:
Nexus(Settings& settings, IMessageBoxManager& messageBoxManager,
CameraSource& cameraSource, IPC& ipc, QObject* parent = nullptr);
~Nexus();
void start();
void showMainGUI();
void setSettings(Settings* settings_);
void setMessageBoxManager(IMessageBoxManager* messageBoxManager);
void setIpc(IPC* ipc);
void setParser(QCommandLineParser* parser_);
static Nexus& getInstance();
static void destroyInstance();
Profile* getProfile();
CameraSource& getCameraSource();
void registerIpcHandlers();
bool handleToxSave(const QString& path);
@ -101,19 +98,17 @@ public slots:
void bootstrapWithProfile(Profile* p);
private:
explicit Nexus(QObject* parent = nullptr);
void connectLoginScreen(const LoginScreen& loginScreen);
void setProfile(Profile* p);
~Nexus();
private:
Profile* profile;
Settings* settings;
Settings& settings;
Widget* widget;
std::unique_ptr<IAudioControl> audioControl;
QCommandLineParser* parser = nullptr;
std::unique_ptr<CameraSource> cameraSource;
CameraSource& cameraSource;
std::unique_ptr<Style> style;
IMessageBoxManager* messageBoxManager = nullptr;
IPC* ipc = nullptr;
IMessageBoxManager& messageBoxManager;
IPC& ipc;
};

View File

@ -142,7 +142,7 @@ void Widget::acceptFileTransfer(const ToxFile& file, const QString& path)
Widget* Widget::instance{nullptr};
Widget::Widget(Profile &profile_, IAudioControl& audio_, CameraSource& cameraSource_,
Settings& settings_, Style& style_, IPC& ipc_, QWidget* parent)
Settings& settings_, Style& style_, IPC& ipc_, Nexus& nexus_, QWidget* parent)
: QMainWindow(parent)
, profile{profile_}
, trayMenu{nullptr}
@ -165,6 +165,7 @@ Widget::Widget(Profile &profile_, IAudioControl& audio_, CameraSource& cameraSou
, contentDialogManager(new ContentDialogManager(*friendList))
, ipc{ipc_}
, toxSave(new ToxSave{settings, ipc, this})
, nexus{nexus_}
{
installEventFilter(this);
QString locale = settings.getTranslation();
@ -314,7 +315,7 @@ void Widget::init()
updateCheck->checkForUpdate();
#endif
profileInfo = new ProfileInfo(core, &profile, settings);
profileInfo = new ProfileInfo(core, &profile, settings, nexus);
profileForm = new ProfileForm(profileInfo, settings, style, *messageBoxManager);
#if DESKTOP_NOTIFICATIONS
@ -392,10 +393,10 @@ void Widget::init()
new QShortcut(Qt::Key_F11, this, SLOT(toggleFullscreen()));
#ifdef Q_OS_MAC
QMenuBar* globalMenu = Nexus::getInstance().globalMenuBar;
QAction* windowMenu = Nexus::getInstance().windowMenu->menuAction();
QAction* viewMenu = Nexus::getInstance().viewMenu->menuAction();
QAction* frontAction = Nexus::getInstance().frontAction;
QMenuBar* globalMenu = nexus.globalMenuBar;
QAction* windowMenu = nexus.windowMenu->menuAction();
QAction* viewMenu = nexus.viewMenu->menuAction();
QAction* frontAction = nexus.frontAction;
fileMenu = globalMenu->insertMenu(viewMenu, new QMenu(this));
@ -411,14 +412,14 @@ void Widget::init()
fileMenu->menu()->addSeparator();
logoutAction = fileMenu->menu()->addAction(QString());
connect(logoutAction, &QAction::triggered, []() { Nexus::getInstance().showLogin(); });
connect(logoutAction, &QAction::triggered, [this]() { nexus.showLogin(); });
editMenu = globalMenu->insertMenu(viewMenu, new QMenu(this));
editMenu->menu()->addSeparator();
viewMenu->menu()->insertMenu(Nexus::getInstance().fullscreenAction, filterMenu);
viewMenu->menu()->insertMenu(nexus.fullscreenAction, filterMenu);
viewMenu->menu()->insertSeparator(Nexus::getInstance().fullscreenAction);
viewMenu->menu()->insertSeparator(nexus.fullscreenAction);
contactMenu = globalMenu->insertMenu(windowMenu, new QMenu(this));
@ -426,7 +427,7 @@ void Widget::init()
connect(addContactAction, &QAction::triggered, this, &Widget::onAddClicked);
nextConversationAction = new QAction(this);
Nexus::getInstance().windowMenu->insertAction(frontAction, nextConversationAction);
nexus.windowMenu->insertAction(frontAction, nextConversationAction);
nextConversationAction->setShortcut(QKeySequence::SelectNextPage);
connect(nextConversationAction, &QAction::triggered, [this]() {
if (contentDialogManager->current() == QApplication::activeWindow())
@ -436,7 +437,7 @@ void Widget::init()
});
previousConversationAction = new QAction(this);
Nexus::getInstance().windowMenu->insertAction(frontAction, previousConversationAction);
nexus.windowMenu->insertAction(frontAction, previousConversationAction);
previousConversationAction->setShortcut(QKeySequence::SelectPreviousPage);
connect(previousConversationAction, &QAction::triggered, [this] {
if (contentDialogManager->current() == QApplication::activeWindow())
@ -464,9 +465,9 @@ void Widget::init()
dockChangeStatusMenu->addSeparator();
dockChangeStatusMenu->addAction(statusAway);
dockChangeStatusMenu->addAction(statusBusy);
Nexus::getInstance().dockMenu->addAction(dockChangeStatusMenu->menuAction());
nexus.dockMenu->addAction(dockChangeStatusMenu->menuAction());
connect(this, &Widget::windowStateChanged, &Nexus::getInstance(), &Nexus::onWindowStateChanged);
connect(this, &Widget::windowStateChanged, &nexus, &Nexus::onWindowStateChanged);
#endif
contentLayout = nullptr;
@ -518,7 +519,7 @@ void Widget::init()
}
#ifdef Q_OS_MAC
Nexus::getInstance().updateWindows();
nexus.updateWindows();
#endif
}
@ -1865,7 +1866,7 @@ void Widget::registerContentDialog(ContentDialog& contentDialog) const
connect(&contentDialog, &ContentDialog::connectFriendWidget, this, &Widget::connectFriendWidget);
#ifdef Q_OS_MAC
Nexus& n = Nexus::getInstance();
Nexus& n = nexus;
connect(&contentDialog, &ContentDialog::destroyed, &n, &Nexus::updateWindowsClosed);
connect(&contentDialog, &ContentDialog::windowStateChanged, &n, &Nexus::onWindowStateChanged);
connect(contentDialog.windowHandle(), &QWindow::windowTitleChanged, &n, &Nexus::updateWindows);
@ -1944,12 +1945,12 @@ ContentLayout* Widget::createContentDialog(DialogType type) const
dialog->show();
#ifdef Q_OS_MAC
connect(dialog, &Dialog::destroyed, &Nexus::getInstance(), &Nexus::updateWindowsClosed);
connect(dialog, &ActivateDialog::windowStateChanged, &Nexus::getInstance(),
connect(dialog, &Dialog::destroyed, &nexus, &Nexus::updateWindowsClosed);
connect(dialog, &ActivateDialog::windowStateChanged, &nexus,
&Nexus::updateWindowsStates);
connect(dialog->windowHandle(), &QWindow::windowTitleChanged, &Nexus::getInstance(),
connect(dialog->windowHandle(), &QWindow::windowTitleChanged, &nexus,
&Nexus::updateWindows);
Nexus::getInstance().updateWindows();
nexus.updateWindows();
#endif
return contentLayoutDialog;
@ -2268,7 +2269,7 @@ bool Widget::event(QEvent* e)
emit windowStateChanged(windowState());
case QEvent::WindowStateChange:
Nexus::getInstance().updateWindowsStates();
nexus.updateWindowsStates();
#endif
break;
default:
@ -2336,7 +2337,7 @@ void Widget::onTryCreateTrayIcon()
}
#ifdef Q_OS_MAC
Nexus::getInstance().dockMenu->setAsDockMenu();
nexus.dockMenu->setAsDockMenu();
#endif
} else if (!isVisible()) {
show();
@ -2701,7 +2702,7 @@ void Widget::retranslateUi()
#ifdef Q_OS_MAC
Nexus::getInstance().retranslateUi();
nexus.retranslateUi();
filterMenu->menuAction()->setText(tr("Filter..."));

View File

@ -92,6 +92,7 @@ class FriendList;
class GroupList;
class IPC;
class ToxSave;
class Nexus;
class Widget final : public QMainWindow
{
@ -127,7 +128,7 @@ private:
public:
Widget(Profile& profile_, IAudioControl& audio_, CameraSource& cameraSource,
Settings& settings, Style& style, IPC& ipc, QWidget* parent = nullptr);
Settings& settings, Style& style, IPC& ipc, Nexus& nexus, QWidget* parent = nullptr);
~Widget() override;
void init();
void setCentralWidget(QWidget* widget, const QString& widgetName);
@ -403,4 +404,5 @@ private:
std::unique_ptr<ContentDialogManager> contentDialogManager;
IPC& ipc;
std::unique_ptr<ToxSave> toxSave;
Nexus& nexus;
};