From 46bba3f2f1f86fc9bb07e18168c0376988d8a807 Mon Sep 17 00:00:00 2001 From: tux3/mlkj Date: Fri, 6 Feb 2015 12:28:49 +0100 Subject: [PATCH] Initial Android support We create a GUI class to abstract common GUI needs (showing a message box, asking a question, ...) from the actual GUI backend. We also create a Nexus class to manage the startup and lifetime of our main systems (Core, GUI, ...) instead of delegating that to Widget. Eventually, Widget will only be in charge of the Desktop GUI and AndroidGUI of the mobile GUI. Nexus will overview the system and GUI will provide a clean platform-independant interface. --- qtox.pro | 15 +- src/core.cpp | 9 +- src/main.cpp | 6 +- src/misc/settings.cpp | 66 +++++++++ src/misc/settings.h | 3 + src/nexus.cpp | 121 ++++++++++++++++ src/nexus.h | 35 +++++ src/widget/androidgui.cpp | 13 ++ src/widget/androidgui.h | 19 +++ src/widget/form/settings/identityform.cpp | 2 +- src/widget/gui.cpp | 47 +++++++ src/widget/gui.h | 33 +++++ src/widget/widget.cpp | 164 +++------------------- src/widget/widget.h | 53 +++---- 14 files changed, 401 insertions(+), 185 deletions(-) create mode 100644 src/nexus.cpp create mode 100644 src/nexus.h create mode 100644 src/widget/androidgui.cpp create mode 100644 src/widget/androidgui.h create mode 100644 src/widget/gui.cpp create mode 100644 src/widget/gui.h diff --git a/qtox.pro b/qtox.pro index d42fba74b..3c95c22ba 100644 --- a/qtox.pro +++ b/qtox.pro @@ -80,7 +80,8 @@ android { ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android contains(ANDROID_TARGET_ARCH,armeabi) { ANDROID_EXTRA_LIBS = \ - $$ANDROID_TOOLCHAIN/lib/libopenal.so + $$ANDROID_TOOLCHAIN/lib/libopenal.so \ + $$ANDROID_TOOLCHAIN/lib/libsodium.so } } @@ -106,7 +107,7 @@ contains(JENKINS,YES) { # Rules for Windows, Mac OSX, and Linux win32 { RC_FILE = windows/qtox.rc - LIBS += -L$$PWD/libs/lib -ltoxav -ltoxcore -ltoxencryptsave -ltoxdns -lsodium -lvpx -lpthread + LIBS += -L$$PWD/libs/lib -ltoxav -ltoxcore -ltoxencryptsave -ltoxdns -lsodium -lvpx -lpthread LIBS += -L$$PWD/libs/lib -lopencv_core249 -lopencv_highgui249 -lopencv_imgproc249 -lOpenAL32 -lopus LIBS += -lopengl32 -lole32 -loleaut32 -luuid -lvfw32 -lws2_32 -liphlpapi -lz @@ -229,7 +230,10 @@ HEADERS += src/widget/form/addfriendform.h \ src/audio.h \ src/widget/callconfirmwidget.h \ src/widget/systemtrayicon.h \ - src/widget/systemtrayicon_private.h + src/widget/systemtrayicon_private.h \ + src/nexus.h \ + src/widget/gui.h \ + src/widget/androidgui.h SOURCES += \ src/widget/form/addfriendform.cpp \ @@ -298,7 +302,10 @@ SOURCES += \ src/widget/form/settings/advancedform.cpp \ src/audio.cpp \ src/widget/callconfirmwidget.cpp \ - src/widget/systemtrayicon.cpp + src/widget/systemtrayicon.cpp \ + src/nexus.cpp \ + src/widget/gui.cpp \ + src/widget/androidgui.cpp contains(DEFINES, QTOX_FILTER_AUDIO) { HEADERS += src/audiofilterer.h diff --git a/src/core.cpp b/src/core.cpp index 4b82a1d5a..f6fa4463c 100644 --- a/src/core.cpp +++ b/src/core.cpp @@ -15,6 +15,7 @@ */ #include "core.h" +#include "nexus.h" #include "misc/cdata.h" #include "misc/cstring.h" #include "misc/settings.h" @@ -106,6 +107,7 @@ Core::~Core() { qDebug() << "Deleting Core"; + saveConfiguration(); toxTimer->stop(); coreThread->exit(0); while (coreThread->isRunning()) @@ -128,7 +130,7 @@ Core::~Core() Core* Core::getInstance() { - return Widget::getInstance()->getCore(); + return Nexus::getCore(); } void Core::make_tox() @@ -223,6 +225,8 @@ void Core::make_tox() void Core::start() { + qDebug() << "Core: Starting up"; + make_tox(); qsrand(time(nullptr)); @@ -1202,8 +1206,7 @@ bool Core::loadConfiguration(QString path) { configurationFile.close(); - QString profile; - QMetaObject::invokeMethod(Widget::getInstance(), "askProfiles", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, profile)); + QString profile = Settings::getInstance().askProfiles(); if (!profile.isEmpty()) { diff --git a/src/main.cpp b/src/main.cpp index a1c3dbdde..8d5ba8934 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,6 +16,7 @@ #include "widget/widget.h" #include "misc/settings.h" +#include "src/nexus.h" #include "src/ipc.h" #include "src/widget/toxuri.h" #include "src/widget/toxsave.h" @@ -70,6 +71,7 @@ int main(int argc, char *argv[]) parser.process(a); Settings::getInstance(); // Build our Settings singleton as soon as QApplication is ready, not before + if (parser.isSet("p")) { QString profile = parser.value("p"); @@ -121,6 +123,8 @@ int main(int argc, char *argv[]) AutoUpdater::installLocalUpdate(); ///< NORETURN #endif +Nexus::getInstance().start(); + #ifndef Q_OS_ANDROID // Inter-process communication IPC ipc; @@ -180,10 +184,8 @@ int main(int argc, char *argv[]) // Run a.setQuitOnLastWindowClosed(false); - Widget* w = Widget::getInstance(); int errorcode = a.exec(); - delete w; #ifdef LOG_TO_FILE delete logFile; logFile = nullptr; diff --git a/src/misc/settings.cpp b/src/misc/settings.cpp index 196202865..96b2b2c6e 100644 --- a/src/misc/settings.cpp +++ b/src/misc/settings.cpp @@ -18,6 +18,8 @@ #include "smileypack.h" #include "src/corestructs.h" #include "src/misc/db/plaindb.h" +#include "src/core.h" +#include "src/widget/gui.h" #include #include @@ -65,6 +67,70 @@ void Settings::switchProfile(const QString& profile) resetInstance(); } +QString Settings::detectProfile() +{ + QDir dir(getSettingsDirPath()); + QString path, profile = getCurrentProfile(); + path = dir.filePath(profile + Core::TOX_EXT); + QFile file(path); + if (profile.isEmpty() || !file.exists()) + { + setCurrentProfile(""); +#if 1 // deprecation attempt + // if the last profile doesn't exist, fall back to old "data" + path = dir.filePath(Core::CONFIG_FILE_NAME); + QFile file(path); + if (file.exists()) + return path; + else if (QFile(path = dir.filePath("tox_save")).exists()) // also import tox_save if no data + return path; + else +#endif + { + profile = askProfiles(); + if (profile.isEmpty()) + return ""; + else + { + switchProfile(profile); + return dir.filePath(profile + Core::TOX_EXT); + } + } + } + else + return path; +} + +QList Settings::searchProfiles() +{ + QList out; + QDir dir(getSettingsDirPath()); + dir.setFilter(QDir::Files | QDir::NoDotAndDotDot); + dir.setNameFilters(QStringList("*.tox")); + for (QFileInfo file : dir.entryInfoList()) + out += file.completeBaseName(); + return out; +} + +QString Settings::askProfiles() +{ // TODO: allow user to create new Tox ID, even if a profile already exists + QList profiles = searchProfiles(); + if (profiles.empty()) return ""; + bool ok; + QString profile = GUI::itemInputDialog(nullptr, + tr("Choose a profile"), + tr("Please choose which identity to use"), + profiles, + 0, // which slot to start on + false, // if the user can enter their own input + &ok); + if (!ok) // user cancelled + return ""; + else + return profile; +} + + void Settings::load() { if (loaded) diff --git a/src/misc/settings.h b/src/misc/settings.h index 391fe1c58..550b79840 100644 --- a/src/misc/settings.h +++ b/src/misc/settings.h @@ -33,6 +33,9 @@ public: static Settings& getInstance(); static void resetInstance(); void switchProfile(const QString& profile); + QString detectProfile(); + QList searchProfiles(); + QString askProfiles(); ~Settings() = default; void executeSettingsDialog(QWidget* parent); diff --git a/src/nexus.cpp b/src/nexus.cpp new file mode 100644 index 000000000..91b65530e --- /dev/null +++ b/src/nexus.cpp @@ -0,0 +1,121 @@ +#include "nexus.h" +#include "core.h" +#include "misc/settings.h" +#include "video/camera.h" +#include +#include + +#ifdef Q_OS_ANDROID +#include +#else +#include +#endif + +Nexus::Nexus(QObject *parent) : + QObject(parent), + core{nullptr}, + coreThread{nullptr}, + widget{nullptr}, + androidgui{nullptr}, + started{false} +{ +} + +Nexus::~Nexus() +{ + delete core; + delete coreThread; +#ifdef Q_OS_ANDROID + delete androidgui; +#else + delete widget; +#endif +} + +void Nexus::start() +{ + if (started) + return; + qDebug() << "Nexus: Starting up"; + + // Setup the environment + qRegisterMetaType("Status"); + qRegisterMetaType("vpx_image"); + qRegisterMetaType("uint8_t"); + qRegisterMetaType("uint16_t"); + qRegisterMetaType("const int16_t*"); + qRegisterMetaType("int32_t"); + qRegisterMetaType("int64_t"); + qRegisterMetaType("QPixmap"); + qRegisterMetaType("ToxFile"); + qRegisterMetaType("ToxFile::FileDirection"); + qRegisterMetaType("Core::PasswordType"); + + // Create Core + QString profilePath = Settings::getInstance().detectProfile(); + coreThread = new QThread(this); + coreThread->setObjectName("qTox Core"); + core = new Core(Camera::getInstance(), coreThread, profilePath); + core->moveToThread(coreThread); + connect(coreThread, &QThread::started, core, &Core::start); + + // Start GUI +#ifdef Q_OS_ANDROID + androidgui = new AndroidGUI; + androidgui->show(); +#else + widget = Widget::getInstance(); +#endif + + // Connections +#ifndef Q_OS_ANDROID + connect(core, &Core::connected, widget, &Widget::onConnected); + connect(core, &Core::disconnected, widget, &Widget::onDisconnected); + connect(core, &Core::failedToStart, widget, &Widget::onFailedToStartCore); + connect(core, &Core::badProxy, widget, &Widget::onBadProxyCore); + connect(core, &Core::statusSet, widget, &Widget::onStatusSet); + connect(core, &Core::usernameSet, widget, &Widget::setUsername); + connect(core, &Core::statusMessageSet, widget, &Widget::setStatusMessage); + connect(core, &Core::selfAvatarChanged, widget, &Widget::onSelfAvatarLoaded); + connect(core, &Core::friendAdded, widget, &Widget::addFriend); + connect(core, &Core::failedToAddFriend, widget, &Widget::addFriendFailed); + connect(core, &Core::friendUsernameChanged, widget, &Widget::onFriendUsernameChanged); + connect(core, &Core::friendStatusChanged, widget, &Widget::onFriendStatusChanged); + connect(core, &Core::friendStatusMessageChanged, widget, &Widget::onFriendStatusMessageChanged); + connect(core, &Core::friendRequestReceived, widget, &Widget::onFriendRequestReceived); + connect(core, &Core::friendMessageReceived, widget, &Widget::onFriendMessageReceived); + connect(core, &Core::receiptRecieved, widget, &Widget::onReceiptRecieved); + connect(core, &Core::groupInviteReceived, widget, &Widget::onGroupInviteReceived); + connect(core, &Core::groupMessageReceived, widget, &Widget::onGroupMessageReceived); + connect(core, &Core::groupNamelistChanged, widget, &Widget::onGroupNamelistChanged); + connect(core, &Core::groupTitleChanged, widget, &Widget::onGroupTitleChanged); + connect(core, &Core::emptyGroupCreated, widget, &Widget::onEmptyGroupCreated); + connect(core, &Core::avInvite, widget, &Widget::playRingtone); + connect(core, &Core::blockingClearContacts, widget, &Widget::clearContactsList, Qt::BlockingQueuedConnection); + connect(core, &Core::friendTypingChanged, widget, &Widget::onFriendTypingChanged); + + connect(core, SIGNAL(messageSentResult(int,QString,int)), widget, SLOT(onMessageSendResult(int,QString,int))); + connect(core, SIGNAL(groupSentResult(int,QString,int)), widget, SLOT(onGroupSendResult(int,QString,int))); + + connect(widget, &Widget::statusSet, core, &Core::setStatus); + connect(widget, &Widget::friendRequested, core, &Core::requestFriendship); + connect(widget, &Widget::friendRequestAccepted, core, &Core::acceptFriendRequest); + connect(widget, &Widget::changeProfile, core, &Core::switchConfiguration); +#endif + + // Start Core + coreThread->start(); + + started = true; +} + +Nexus& Nexus::getInstance() +{ + static Nexus nexus; + return nexus; +} + +Core* Nexus::getCore() +{ + return getInstance().core; +} diff --git a/src/nexus.h b/src/nexus.h new file mode 100644 index 000000000..f8b5dd4b5 --- /dev/null +++ b/src/nexus.h @@ -0,0 +1,35 @@ +#ifndef NEXUS_H +#define NEXUS_H + +#include + +class QThread; +class Core; +class Widget; +class AndroidGUI; + +/// This class is in charge of connecting various systems together +/// and forwarding signals appropriately to the right objects +/// It is in charge of starting the GUI and the Core +class Nexus : public QObject +{ + Q_OBJECT +public: + void start(); ///< Will initialise the systems (GUI, Core, ...) + + static Nexus& getInstance(); + static Core* getCore(); ///< Will return 0 if not started + +private: + explicit Nexus(QObject *parent = 0); + ~Nexus(); + +private: + Core* core; + QThread* coreThread; + Widget* widget; + AndroidGUI* androidgui; + bool started; +}; + +#endif // NEXUS_H diff --git a/src/widget/androidgui.cpp b/src/widget/androidgui.cpp new file mode 100644 index 000000000..7ae41d983 --- /dev/null +++ b/src/widget/androidgui.cpp @@ -0,0 +1,13 @@ +#include "androidgui.h" +#include + +AndroidGUI::AndroidGUI(QWidget *parent) : + QWidget(parent) +{ + l = new QLabel("qTox Android", this); +} + +AndroidGUI::~AndroidGUI() +{ + delete l; +} diff --git a/src/widget/androidgui.h b/src/widget/androidgui.h new file mode 100644 index 000000000..853483ce2 --- /dev/null +++ b/src/widget/androidgui.h @@ -0,0 +1,19 @@ +#ifndef ANDROIDGUI_H +#define ANDROIDGUI_H + +#include + +class QLabel; + +class AndroidGUI : public QWidget +{ + Q_OBJECT +public: + explicit AndroidGUI(QWidget *parent = 0); + ~AndroidGUI(); + +private: + QLabel* l; +}; + +#endif // ANDROIDGUI_H diff --git a/src/widget/form/settings/identityform.cpp b/src/widget/form/settings/identityform.cpp index 8d067b606..a856af1b5 100644 --- a/src/widget/form/settings/identityform.cpp +++ b/src/widget/form/settings/identityform.cpp @@ -111,7 +111,7 @@ void IdentityForm::present() toxId->setText(Core::getInstance()->getSelfId().toString()); toxId->setCursorPosition(0); bodyUI->profiles->clear(); - for (QString profile : Widget::searchProfiles()) + for (QString profile : Settings::getInstance().searchProfiles()) bodyUI->profiles->addItem(profile); QString current = Settings::getInstance().getCurrentProfile(); if (current != "") diff --git a/src/widget/gui.cpp b/src/widget/gui.cpp new file mode 100644 index 000000000..76f77e8db --- /dev/null +++ b/src/widget/gui.cpp @@ -0,0 +1,47 @@ +#include "gui.h" +#include +#include +#include + +GUI::GUI(QObject *parent) : + QObject(parent) +{ +} + +GUI& GUI::getInstance() +{ + static GUI gui; + return gui; +} + +QString GUI::itemInputDialog(QWidget * parent, const QString & title, + const QString & label, const QStringList & items, + int current, bool editable, bool * ok, + Qt::WindowFlags flags, + Qt::InputMethodHints hints) +{ + if (QThread::currentThread() == qApp->thread()) + { + return getInstance()._itemInputDialog(parent, title, label, items, current, editable, ok, flags, hints); + } + else + { + QString r; + QMetaObject::invokeMethod(&getInstance(), "_itemInputDialog", Qt::BlockingQueuedConnection, + Q_RETURN_ARG(QString, r), + Q_ARG(QWidget*, parent), Q_ARG(const QString&, title), + Q_ARG(const QString&,label), Q_ARG(const QStringList&, items), + Q_ARG(int, current), Q_ARG(bool, editable), Q_ARG(bool*, ok), + Q_ARG(Qt::WindowFlags, flags), Q_ARG(Qt::InputMethodHints, hints)); + return r; + } +} + +QString GUI::_itemInputDialog(QWidget * parent, const QString & title, + const QString & label, const QStringList & items, + int current, bool editable, bool * ok, + Qt::WindowFlags flags, + Qt::InputMethodHints hints) +{ + return QInputDialog::getItem(parent, title, label, items, current, editable, ok, flags, hints); +} diff --git a/src/widget/gui.h b/src/widget/gui.h new file mode 100644 index 000000000..7a7f70339 --- /dev/null +++ b/src/widget/gui.h @@ -0,0 +1,33 @@ +#ifndef GUI_H +#define GUI_H + +#include + +class QWidget; + +/// Abstracts the GUI from the target backend (AndroidGUI, DesktopGUI, ...) +/// All the functions exposed here are thread-safe +/// Prefer calling this class to calling a GUI backend directly +class GUI : public QObject +{ + Q_OBJECT +public: + static GUI& getInstance(); + static QString itemInputDialog(QWidget * parent, const QString & title, + const QString & label, const QStringList & items, + int current = 0, bool editable = true, bool * ok = 0, + Qt::WindowFlags flags = 0, + Qt::InputMethodHints hints = Qt::ImhNone); + +private: + explicit GUI(QObject *parent = 0); + +private slots: + QString _itemInputDialog(QWidget * parent, const QString & title, + const QString & label, const QStringList & items, + int current = 0, bool editable = true, bool * ok = 0, + Qt::WindowFlags flags = 0, + Qt::InputMethodHints inputMethodHints = Qt::ImhNone); +}; + +#endif // GUI_H diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index cca091025..3a5d5ee5c 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -36,6 +36,7 @@ #include "src/audio.h" #include "src/platform/timer.h" #include "systemtrayicon.h" +#include "src/nexus.h" #include #include #include @@ -194,67 +195,15 @@ void Widget::init() Style::setThemeColor(Settings::getInstance().getThemeColor()); Style::applyTheme(); - - qRegisterMetaType("Status"); - qRegisterMetaType("vpx_image"); - qRegisterMetaType("uint8_t"); - qRegisterMetaType("uint16_t"); - qRegisterMetaType("const int16_t*"); - qRegisterMetaType("int32_t"); - qRegisterMetaType("int64_t"); - qRegisterMetaType("QPixmap"); - qRegisterMetaType("ToxFile"); - qRegisterMetaType("ToxFile::FileDirection"); - qRegisterMetaType("Core::PasswordType"); - - QString profilePath = detectProfile(); - coreThread = new QThread(this); - coreThread->setObjectName("qTox Core"); - core = new Core(Camera::getInstance(), coreThread, profilePath); - core->moveToThread(coreThread); - connect(coreThread, &QThread::started, core, &Core::start); filesForm = new FilesForm(); addFriendForm = new AddFriendForm; settingsWidget = new SettingsWidget(); - connect(settingsWidget, &SettingsWidget::setShowSystemTray, this, &Widget::onSetShowSystemTray); - - connect(core, &Core::connected, this, &Widget::onConnected); - connect(core, &Core::disconnected, this, &Widget::onDisconnected); - connect(core, &Core::failedToStart, this, &Widget::onFailedToStartCore); - connect(core, &Core::badProxy, this, &Widget::onBadProxyCore); - connect(core, &Core::statusSet, this, &Widget::onStatusSet); - connect(core, &Core::usernameSet, this, &Widget::setUsername); - connect(core, &Core::statusMessageSet, this, &Widget::setStatusMessage); - connect(core, &Core::selfAvatarChanged, this, &Widget::onSelfAvatarLoaded); + Core* core = Nexus::getCore(); connect(core, SIGNAL(fileDownloadFinished(const QString&)), filesForm, SLOT(onFileDownloadComplete(const QString&))); connect(core, SIGNAL(fileUploadFinished(const QString&)), filesForm, SLOT(onFileUploadComplete(const QString&))); - connect(core, &Core::friendAdded, this, &Widget::addFriend); - connect(core, &Core::failedToAddFriend, this, &Widget::addFriendFailed); - connect(core, &Core::friendUsernameChanged, this, &Widget::onFriendUsernameChanged); - connect(core, &Core::friendStatusChanged, this, &Widget::onFriendStatusChanged); - connect(core, &Core::friendStatusMessageChanged, this, &Widget::onFriendStatusMessageChanged); - connect(core, &Core::friendRequestReceived, this, &Widget::onFriendRequestReceived); - connect(core, &Core::friendMessageReceived, this, &Widget::onFriendMessageReceived); - connect(core, &Core::receiptRecieved, this, &Widget::onReceiptRecieved); - connect(core, &Core::groupInviteReceived, this, &Widget::onGroupInviteReceived); - connect(core, &Core::groupMessageReceived, this, &Widget::onGroupMessageReceived); - connect(core, &Core::groupNamelistChanged, this, &Widget::onGroupNamelistChanged); - connect(core, &Core::groupTitleChanged, this, &Widget::onGroupTitleChanged); - connect(core, &Core::emptyGroupCreated, this, &Widget::onEmptyGroupCreated); - connect(core, &Core::avInvite, this, &Widget::playRingtone); - connect(core, &Core::blockingClearContacts, this, &Widget::clearContactsList, Qt::BlockingQueuedConnection); - connect(core, &Core::friendTypingChanged, this, &Widget::onFriendTypingChanged); - - connect(core, SIGNAL(messageSentResult(int,QString,int)), this, SLOT(onMessageSendResult(int,QString,int))); - connect(core, SIGNAL(groupSentResult(int,QString,int)), this, SLOT(onGroupSendResult(int,QString,int))); - - connect(this, &Widget::statusSet, core, &Core::setStatus); - connect(this, &Widget::friendRequested, core, &Core::requestFriendship); - connect(this, &Widget::friendRequestAccepted, core, &Core::acceptFriendRequest); - connect(this, &Widget::changeProfile, core, &Core::switchConfiguration); - + connect(settingsWidget, &SettingsWidget::setShowSystemTray, this, &Widget::onSetShowSystemTray); connect(ui->addButton, SIGNAL(clicked()), this, SLOT(onAddClicked())); connect(ui->groupButton, SIGNAL(clicked()), this, SLOT(onGroupClicked())); connect(ui->transferButton, SIGNAL(clicked()), this, SLOT(onTransferClicked())); @@ -270,8 +219,6 @@ void Widget::init() connect(timer, &QTimer::timeout, this, &Widget::onUserAwayCheck); connect(timer, &QTimer::timeout, this, &Widget::onEventIconTick); - coreThread->start(); - addFriendForm->show(*ui); #if (AUTOUPDATE_ENABLED) @@ -318,9 +265,7 @@ void Widget::updateTrayIcon() Widget::~Widget() { qDebug() << "Deleting Widget"; - core->saveConfiguration(); AutoUpdater::abortUpdates(); - delete core; icon->hide(); hideMainForms(); delete settingsWidget; @@ -346,11 +291,6 @@ Widget* Widget::getInstance() return instance; } -QThread* Widget::getCoreThread() -{ - return coreThread; -} - void Widget::closeEvent(QCloseEvent *event) { if (Settings::getInstance().getShowSystemTray() && Settings::getInstance().getCloseToTray() == true) @@ -386,72 +326,9 @@ void Widget::resizeEvent(QResizeEvent *event) emit resized(); } -QString Widget::detectProfile() -{ - QDir dir(Settings::getSettingsDirPath()); - QString path, profile = Settings::getInstance().getCurrentProfile(); - path = dir.filePath(profile + Core::TOX_EXT); - QFile file(path); - if (profile.isEmpty() || !file.exists()) - { - Settings::getInstance().setCurrentProfile(""); -#if 1 // deprecation attempt - // if the last profile doesn't exist, fall back to old "data" - path = dir.filePath(Core::CONFIG_FILE_NAME); - QFile file(path); - if (file.exists()) - return path; - else if (QFile(path = dir.filePath("tox_save")).exists()) // also import tox_save if no data - return path; - else -#endif - { - profile = askProfiles(); - if (profile.isEmpty()) - return ""; - else - { - Settings::getInstance().switchProfile(profile); - return dir.filePath(profile + Core::TOX_EXT); - } - } - } - else - return path; -} - -QList Widget::searchProfiles() -{ - QList out; - QDir dir(Settings::getSettingsDirPath()); - dir.setFilter(QDir::Files | QDir::NoDotAndDotDot); - dir.setNameFilters(QStringList("*.tox")); - for (QFileInfo file : dir.entryInfoList()) - out += file.completeBaseName(); - return out; -} - -QString Widget::askProfiles() -{ // TODO: allow user to create new Tox ID, even if a profile already exists - QList profiles = searchProfiles(); - if (profiles.empty()) return ""; - bool ok; - QString profile = QInputDialog::getItem(this, - tr("Choose a profile"), - tr("Please choose which identity to use"), - profiles, - 0, // which slot to start on - false, // if the user can enter their own input - &ok); - if (!ok) // user cancelled - return ""; - else - return profile; -} - QString Widget::getUsername() { - return core->getUsername(); + return Nexus::getCore()->getUsername(); } void Widget::onAvatarClicked() @@ -495,7 +372,7 @@ void Widget::onAvatarClicked() return; } - core->setAvatar(TOX_AVATAR_FORMAT_PNG, bytes); + Nexus::getCore()->setAvatar(TOX_AVATAR_FORMAT_PNG, bytes); } void Widget::onSelfAvatarLoaded(const QPixmap& pic) @@ -591,7 +468,7 @@ void Widget::onAddClicked() void Widget::onGroupClicked() { - core->createGroup(); + Nexus::getCore()->createGroup(); } void Widget::onTransferClicked() @@ -664,7 +541,7 @@ void Widget::hideMainForms() void Widget::onUsernameChanged(const QString& newUsername, const QString& oldUsername) { setUsername(oldUsername); // restore old username until Core tells us to set it - core->setUsername(newUsername); + Nexus::getCore()->setUsername(newUsername); } void Widget::setUsername(const QString& username) @@ -681,7 +558,7 @@ void Widget::onStatusMessageChanged(const QString& newStatusMessage, const QStri { ui->statusLabel->setText(oldStatusMessage); // restore old status message until Core tells us to set it ui->statusLabel->setToolTip(oldStatusMessage); // for overlength messsages - core->setStatusMessage(newStatusMessage); + Nexus::getCore()->setStatusMessage(newStatusMessage); } void Widget::setStatusMessage(const QString &statusMessage) @@ -707,6 +584,7 @@ void Widget::addFriend(int friendId, const QString &userId) if (Settings::getInstance().getEnableLogging()) newfriend->getChatForm()->loadHistory(QDateTime::currentDateTime().addDays(-7), true); + Core* core = Nexus::getCore(); connect(settingsWidget, &SettingsWidget::compactToggled, newfriend->getFriendWidget(), &GenericChatroomWidget::onCompactChanged); connect(newfriend->getFriendWidget(), SIGNAL(chatroomWidgetClicked(GenericChatroomWidget*)), this, SLOT(onChatroomWidgetClicked(GenericChatroomWidget*))); connect(newfriend->getFriendWidget(), SIGNAL(removeFriend(int)), this, SLOT(removeFriend(int))); @@ -928,7 +806,7 @@ void Widget::removeFriend(Friend* f, bool fake) onAddClicked(); } FriendList::removeFriend(f->getFriendID(), fake); - core->removeFriend(f->getFriendID(), fake); + Nexus::getCore()->removeFriend(f->getFriendID(), fake); delete f; if (ui->mainHead->layout()->isEmpty()) onAddClicked(); @@ -959,7 +837,7 @@ void Widget::copyFriendIdToClipboard(int friendId) if (f != nullptr) { QClipboard *clipboard = QApplication::clipboard(); - clipboard->setText(core->getFriendAddress(f->getFriendID()), QClipboard::Clipboard); + clipboard->setText(Nexus::getCore()->getFriendAddress(f->getFriendID()), QClipboard::Clipboard); } } @@ -967,7 +845,7 @@ void Widget::onGroupInviteReceived(int32_t friendId, uint8_t type, QByteArray in { if (type == TOX_GROUPCHAT_TYPE_TEXT || type == TOX_GROUPCHAT_TYPE_AV) { - int groupId = core->joinGroupchat(friendId, type, (uint8_t*)invite.data(), invite.length()); + int groupId = Nexus::getCore()->joinGroupchat(friendId, type, (uint8_t*)invite.data(), invite.length()); if (groupId < 0) { qWarning() << "Widget::onGroupInviteReceived: Unable to accept group invite"; @@ -1014,7 +892,7 @@ void Widget::onGroupNamelistChanged(int groupnumber, int peernumber, uint8_t Cha g = createGroup(groupnumber); } - QString name = core->getGroupPeerName(groupnumber, peernumber); + QString name = Nexus::getCore()->getGroupPeerName(groupnumber, peernumber); TOX_CHAT_CHANGE change = static_cast(Change); if (change == TOX_CHAT_CHANGE_PEER_ADD) { @@ -1033,7 +911,7 @@ void Widget::onGroupNamelistChanged(int groupnumber, int peernumber, uint8_t Cha //g->chatForm->addSystemInfoMessage(tr("%1 has left the chat").arg(name), "silver"); } else if (change == TOX_CHAT_CHANGE_PEER_NAME) // core overwrites old name before telling us it changed... - g->updatePeer(peernumber,core->getGroupPeerName(groupnumber, peernumber)); + g->updatePeer(peernumber,Nexus::getCore()->getGroupPeerName(groupnumber, peernumber)); } void Widget::onGroupTitleChanged(int groupnumber, const QString& author, const QString& title) @@ -1056,7 +934,7 @@ void Widget::removeGroup(Group* g, bool fake) onAddClicked(); } GroupList::removeGroup(g->getGroupId(), fake); - core->removeGroup(g->getGroupId(), fake); + Nexus::getCore()->removeGroup(g->getGroupId(), fake); delete g; if (ui->mainHead->layout()->isEmpty()) onAddClicked(); @@ -1070,11 +948,6 @@ void Widget::removeGroup(int groupId) removeGroup(GroupList::findGroup(groupId)); } -Core *Widget::getCore() -{ - return core; -} - Group *Widget::createGroup(int groupId) { Group* g = GroupList::findGroup(groupId); @@ -1090,6 +963,7 @@ Group *Widget::createGroup(int groupId) layout->addWidget(newgroup->getGroupWidget()); newgroup->getGroupWidget()->updateStatusLight(); + Core* core = Nexus::getCore(); connect(newgroup->getGroupWidget(), SIGNAL(chatroomWidgetClicked(GenericChatroomWidget*)), this, SLOT(onChatroomWidgetClicked(GenericChatroomWidget*))); connect(newgroup->getGroupWidget(), SIGNAL(removeGroup(int)), this, SLOT(removeGroup(int))); connect(newgroup->getGroupWidget(), SIGNAL(chatroomWidgetClicked(GenericChatroomWidget*)), newgroup->getChatForm(), SLOT(focusInput())); @@ -1174,17 +1048,17 @@ void Widget::onEventIconTick() void Widget::setStatusOnline() { - core->setStatus(Status::Online); + Nexus::getCore()->setStatus(Status::Online); } void Widget::setStatusAway() { - core->setStatus(Status::Away); + Nexus::getCore()->setStatus(Status::Away); } void Widget::setStatusBusy() { - core->setStatus(Status::Busy); + Nexus::getCore()->setStatus(Status::Busy); } void Widget::onMessageSendResult(int friendId, const QString& message, int messageId) diff --git a/src/widget/widget.h b/src/widget/widget.h index 0a8307cbe..f43a301f7 100644 --- a/src/widget/widget.h +++ b/src/widget/widget.h @@ -54,14 +54,11 @@ public: explicit Widget(QWidget *parent = 0); void setCentralWidget(QWidget *widget, const QString &widgetName); QString getUsername(); - Core* getCore(); - QThread* getCoreThread(); Camera* getCamera(); static Widget* getInstance(); void newMessageAlert(GenericChatroomWidget* chat); bool isFriendWidgetCurActiveWidget(Friend* f); bool getIsWindowMinimized(); - static QList searchProfiles(); void clearContactsList(); void setTranslation(); void updateTrayIcon(); @@ -69,7 +66,6 @@ public: Q_INVOKABLE void setEnabledThreadsafe(bool enabled); Q_INVOKABLE bool askQuestion(const QString& title, const QString& msg, bool defaultAns = false, bool warning = true); Q_INVOKABLE QString passwordDialog(const QString& cancel, const QString& body); - Q_INVOKABLE QString askProfiles(); // hooray for threading hacks ~Widget(); @@ -86,6 +82,29 @@ public slots: void onSettingsClicked(); void setWindowTitle(const QString& title); void forceShow(); + void onConnected(); + void onDisconnected(); + void onStatusSet(Status status); + void onFailedToStartCore(); + void onBadProxyCore(); + void onSelfAvatarLoaded(const QPixmap &pic); + void setUsername(const QString& username); + void setStatusMessage(const QString &statusMessage); + void addFriend(int friendId, const QString& userId); + void addFriendFailed(const QString& userId, const QString& errorInfo = QString()); + void onFriendStatusChanged(int friendId, Status status); + void onFriendStatusMessageChanged(int friendId, const QString& message); + void onFriendUsernameChanged(int friendId, const QString& username); + void onFriendMessageReceived(int friendId, const QString& message, bool isAction); + void onFriendRequestReceived(const QString& userId, const QString& message); + void onReceiptRecieved(int friendId, int receipt); + void onEmptyGroupCreated(int groupId); + void onGroupInviteReceived(int32_t friendId, uint8_t type, QByteArray invite); + void onGroupMessageReceived(int groupnumber, int peernumber, const QString& message, bool isAction); + void onGroupNamelistChanged(int groupnumber, int peernumber, uint8_t change); + void onGroupTitleChanged(int groupnumber, const QString& author, const QString& title); + void playRingtone(); + void onFriendTypingChanged(int friendId, bool isTyping); signals: void friendRequestAccepted(const QString& userId); @@ -98,34 +117,13 @@ signals: void resized(); private slots: - void onConnected(); - void onDisconnected(); - void onStatusSet(Status status); void onAddClicked(); void onGroupClicked(); void onTransferClicked(); - void onFailedToStartCore(); - void onBadProxyCore(); void onAvatarClicked(); - void onSelfAvatarLoaded(const QPixmap &pic); void onUsernameChanged(const QString& newUsername, const QString& oldUsername); void onStatusMessageChanged(const QString& newStatusMessage, const QString& oldStatusMessage); - void setUsername(const QString& username); - void setStatusMessage(const QString &statusMessage); - void addFriend(int friendId, const QString& userId); - void addFriendFailed(const QString& userId, const QString& errorInfo = QString()); - void onFriendStatusChanged(int friendId, Status status); - void onFriendStatusMessageChanged(int friendId, const QString& message); - void onFriendUsernameChanged(int friendId, const QString& username); void onChatroomWidgetClicked(GenericChatroomWidget *); - void onFriendMessageReceived(int friendId, const QString& message, bool isAction); - void onFriendRequestReceived(const QString& userId, const QString& message); - void onReceiptRecieved(int friendId, int receipt); - void onEmptyGroupCreated(int groupId); - void onGroupInviteReceived(int32_t friendId, uint8_t type, QByteArray invite); - void onGroupMessageReceived(int groupnumber, int peernumber, const QString& message, bool isAction); - void onGroupNamelistChanged(int groupnumber, int peernumber, uint8_t change); - void onGroupTitleChanged(int groupnumber, const QString& author, const QString& title); void removeFriend(int friendId); void copyFriendIdToClipboard(int friendId); void removeGroup(int groupId); @@ -134,11 +132,9 @@ private slots: void setStatusBusy(); void onMessageSendResult(int friendId, const QString& message, int messageId); void onGroupSendResult(int groupId, const QString& message, int result); - void playRingtone(); void onIconClick(QSystemTrayIcon::ActivationReason); void onUserAwayCheck(); void onEventIconTick(); - void onFriendTypingChanged(int friendId, bool isTyping); void onSetShowSystemTray(bool newValue); void onSplitterMoved(int pos, int index); @@ -151,7 +147,6 @@ private: void removeGroup(Group* g, bool fake = false); void saveWindowGeometry(); void saveSplitterGeometry(); - QString detectProfile(); SystemTrayIcon *icon; QMenu *trayMenu; QAction *statusOnline, @@ -162,8 +157,6 @@ private: Ui::MainWindow *ui; QSplitter *centralLayout; QPoint dragPosition; - Core* core; - QThread* coreThread; AddFriendForm* addFriendForm; SettingsWidget* settingsWidget; FilesForm* filesForm;