From 1ded562d9df2221da03959edb2523e255fc0244e Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 5 Jun 2015 16:24:47 +0200 Subject: [PATCH 1/3] Clean Settings interface --- src/core/core.cpp | 4 +- src/core/corefile.cpp | 4 +- src/core/corestructs.h | 8 ++++ src/historykeeper.cpp | 2 +- src/main.cpp | 2 +- src/misc/settings.cpp | 10 ++-- src/misc/settings.h | 84 +++++++++++++++------------------ src/profile.cpp | 14 +++--- src/widget/form/chatform.cpp | 4 +- src/widget/form/profileform.cpp | 2 +- src/widget/toxsave.cpp | 3 +- 11 files changed, 68 insertions(+), 69 deletions(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index 96b6877cd..6f09bdae2 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -419,7 +419,7 @@ bool Core::checkConnection() void Core::bootstrapDht() { const Settings& s = Settings::getInstance(); - QList dhtServerList = s.getDhtServerList(); + QList dhtServerList = s.getDhtServerList(); int listSize = dhtServerList.size(); if (listSize == 0) @@ -434,7 +434,7 @@ void Core::bootstrapDht() int i=0; while (i < 2) // i think the more we bootstrap, the more we jitter because the more we overwrite nodes { - const Settings::DhtServer& dhtServer = dhtServerList[j % listSize]; + const DhtServer& dhtServer = dhtServerList[j % listSize]; if (tox_bootstrap(tox, dhtServer.address.toLatin1().data(), dhtServer.port, CUserId(dhtServer.userId).data(), nullptr)) { diff --git a/src/core/corefile.cpp b/src/core/corefile.cpp index 33ec3a444..c8957b42e 100644 --- a/src/core/corefile.cpp +++ b/src/core/corefile.cpp @@ -243,8 +243,8 @@ void CoreFile::onFileReceiveCallback(Tox*, uint32_t friendId, uint32_t fileId, u { // Avatars of size 0 means explicitely no avatar emit core->friendAvatarRemoved(friendId); - QFile::remove(QDir(Settings::getSettingsDirPath()).filePath("avatars/"+friendAddr.left(64)+".png")); - QFile::remove(QDir(Settings::getSettingsDirPath()).filePath("avatars/"+friendAddr.left(64)+".hash")); + QFile::remove(Settings::getInstance().getSettingsDirPath()+"avatars/"+friendAddr.left(64)+".png"); + QFile::remove(Settings::getInstance().getSettingsDirPath()+"avatars/"+friendAddr.left(64)+".hash"); return; } else diff --git a/src/core/corestructs.h b/src/core/corestructs.h index 7b1901fc8..644a9dd16 100644 --- a/src/core/corestructs.h +++ b/src/core/corestructs.h @@ -11,6 +11,14 @@ class QTimer; enum class Status : int {Online = 0, Away, Busy, Offline}; +struct DhtServer +{ + QString name; + QString userId; + QString address; + quint16 port; +}; + struct ToxFile { enum FileStatus diff --git a/src/historykeeper.cpp b/src/historykeeper.cpp index 82e316aa4..f08067219 100644 --- a/src/historykeeper.cpp +++ b/src/historykeeper.cpp @@ -359,7 +359,7 @@ HistoryKeeper::ChatType HistoryKeeper::convertToChatType(int ct) QString HistoryKeeper::getHistoryPath(QString currentProfile, int encrypted) { - QDir baseDir(Settings::getSettingsDirPath()); + QDir baseDir(Settings::getInstance().getSettingsDirPath()); if (currentProfile.isEmpty()) currentProfile = Settings::getInstance().getCurrentProfile(); diff --git a/src/main.cpp b/src/main.cpp index 25f5605be..539273b74 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -144,7 +144,7 @@ int main(int argc, char *argv[]) #ifdef LOG_TO_FILE logFile = new QTextStream; - QFile logfile(Settings::getSettingsDirPath()+"qtox.log"); + QFile logfile(Settings::getInstance().getSettingsDirPath()+"qtox.log"); if (logfile.open(QIODevice::Append)) { logFile->setDevice(&logfile); diff --git a/src/misc/settings.cpp b/src/misc/settings.cpp index f478fa3da..97c683b56 100644 --- a/src/misc/settings.cpp +++ b/src/misc/settings.cpp @@ -42,10 +42,10 @@ const QString Settings::globalSettingsFile = "qtox.ini"; Settings* Settings::settings{nullptr}; -bool Settings::makeToxPortable{false}; Settings::Settings() : - loaded(false), useCustomDhtList{false}, currentProfileId(0) + loaded(false), useCustomDhtList{false}, + makeToxPortable{false}, currentProfileId(0) { load(); } @@ -420,10 +420,10 @@ QString Settings::getSettingsDirPath() // workaround for https://bugreports.qt-project.org/browse/QTBUG-38845 #ifdef Q_OS_WIN return QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::HomeLocation) + QDir::separator() - + "AppData" + QDir::separator() + "Roaming" + QDir::separator() + "tox" + QDir::separator()); + + "AppData" + QDir::separator() + "Roaming" + QDir::separator() + "tox")+QDir::separator(); #else return QDir::cleanPath(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation) - + QDir::separator() + "tox" + QDir::separator()); + + QDir::separator() + "tox")+QDir::separator(); #endif } @@ -484,7 +484,7 @@ QByteArray Settings::getAvatarHash(const QString& ownerId) return out; } -const QList& Settings::getDhtServerList() const +const QList& Settings::getDhtServerList() const { return dhtServerList; } diff --git a/src/misc/settings.h b/src/misc/settings.h index d03ff27ba..89a469452 100644 --- a/src/misc/settings.h +++ b/src/misc/settings.h @@ -20,6 +20,7 @@ #include #include #include +#include "src/core/corestructs.h" class ToxId; namespace Db { enum class syncType; } @@ -32,20 +33,22 @@ class Settings : public QObject public: ~Settings() = default; static Settings& getInstance(); + QString getSettingsDirPath(); ///< The returned path ends with a directory separator + void createSettingsDir(); ///< Creates a path to the settings dir, if it doesn't already exist + void createPersonal(QString basename); ///< Write a default personnal .ini settings file for a profile - void createPersonal(QString basename); ///< Write a default personnal settings file for a profile + void save(bool writePersonal = true); + void save(QString path, bool writePersonal = true); + void load(); - static QString getSettingsDirPath(); ///< The returned path ends with a directory separator - - struct DhtServer - { - QString name; - QString userId; - QString address; - quint16 port; - }; +signals: + void dhtServerListChanged(); + void smileyPackChanged(); + void emojiFontChanged(); +public: + // Getter/setters const QList& getDhtServerList() const; void setDhtServerList(const QList& newDhtServerList); @@ -146,28 +149,6 @@ public: QSize getCamVideoRes() const; void setCamVideoRes(QSize newValue); - // Assume all widgets have unique names - // Don't use it to save every single thing you want to save, use it - // for some general purpose widgets, such as MainWindows or Splitters, - // which have widget->saveX() and widget->loadX() methods. - QByteArray getWidgetData(const QString& uniqueName) const; - void setWidgetData(const QString& uniqueName, const QByteArray& data); - - // Wrappers around getWidgetData() and setWidgetData() - // Assume widget has a unique objectName set - template - void restoreGeometryState(T* widget) const - { - widget->restoreGeometry(getWidgetData(widget->objectName() + "Geometry")); - widget->restoreState(getWidgetData(widget->objectName() + "State")); - } - template - void saveGeometryState(const T* widget) - { - setWidgetData(widget->objectName() + "Geometry", widget->saveGeometry()); - setWidgetData(widget->objectName() + "State", widget->saveState()); - } - bool isAnimationEnabled() const; void setAnimationEnabled(bool newValue); @@ -248,14 +229,29 @@ public: bool getAutoLogin() const; void setAutoLogin(bool state); -public: - void save(bool writePersonal = true); - void save(QString path, bool writePersonal = true); - void load(); + // Assume all widgets have unique names + // Don't use it to save every single thing you want to save, use it + // for some general purpose widgets, such as MainWindows or Splitters, + // which have widget->saveX() and widget->loadX() methods. + QByteArray getWidgetData(const QString& uniqueName) const; + void setWidgetData(const QString& uniqueName, const QByteArray& data); + + // Wrappers around getWidgetData() and setWidgetData() + // Assume widget has a unique objectName set + template + void restoreGeometryState(T* widget) const + { + widget->restoreGeometry(getWidgetData(widget->objectName() + "Geometry")); + widget->restoreState(getWidgetData(widget->objectName() + "State")); + } + template + void saveGeometryState(const T* widget) + { + setWidgetData(widget->objectName() + "Geometry", widget->saveGeometry()); + setWidgetData(widget->objectName() + "State", widget->saveState()); + } private: - static Settings* settings; - Settings(); Settings(Settings &settings) = delete; Settings& operator=(const Settings&) = delete; @@ -263,9 +259,7 @@ private: void saveGlobal(QString path); void savePersonal(QString path); - static const QString globalSettingsFile; - static const QString OLDFILENAME; - +private: bool loaded; bool useCustomDhtList; @@ -279,7 +273,7 @@ private: bool groupchatPosition; bool enableIPv6; QString translation; - static bool makeToxPortable; + bool makeToxPortable; bool autostartInTray; bool closeToTray; bool minimizeToTray; @@ -354,10 +348,8 @@ private: int themeColor; -signals: - void dhtServerListChanged(); - void smileyPackChanged(); - void emojiFontChanged(); + static Settings* settings; + static const QString globalSettingsFile; }; #endif // SETTINGS_HPP diff --git a/src/profile.cpp b/src/profile.cpp index 04bf4ab38..1a06c4ae8 100644 --- a/src/profile.cpp +++ b/src/profile.cpp @@ -144,7 +144,7 @@ QByteArray Profile::loadToxSave() /// TODO: Cache the data, invalidate it only when we save QByteArray data; - QString path = Settings::getSettingsDirPath() + QDir::separator() + name + ".tox"; + QString path = Settings::getInstance().getSettingsDirPath() + name + ".tox"; QFile saveFile(path); qint64 fileSize; qDebug() << "Loading tox save "<showGrabber(); // Create dir for screenshots - QDir(Settings::getSettingsDirPath()).mkdir("screenshots"); + QDir(Settings::getInstance().getSettingsDirPath()).mkdir("screenshots"); } void ChatForm::onScreenshotTaken(const QPixmap &pixmap) { - QTemporaryFile file(QDir(Settings::getSettingsDirPath() + QDir::separator() + "screenshots" + QDir::separator()).filePath("qTox-Screenshot-XXXXXXXX.png")); + QTemporaryFile file(Settings::getInstance().getSettingsDirPath()+"screenshots"+QDir::separator()+"qTox-Screenshot-XXXXXXXX.png"); if (!file.open()) { QMessageBox::warning(this, tr("Failed to open temporary file", "Temporary file for screenshot"), diff --git a/src/widget/form/profileform.cpp b/src/widget/form/profileform.cpp index 9788264aa..58ab70e63 100644 --- a/src/widget/form/profileform.cpp +++ b/src/widget/form/profileform.cpp @@ -264,7 +264,7 @@ void ProfileForm::onExportClicked() GUI::showWarning(tr("Location not writable","Title of permissions popup"), tr("You do not have permission to write that location. Choose another, or cancel the save dialog.", "text of permissions popup")); return; } - if (!QFile::copy(QDir(Settings::getSettingsDirPath()).filePath(current), path)) + if (!QFile::copy(Settings::getInstance().getSettingsDirPath()+current, path)) GUI::showWarning(tr("Failed to copy file"), tr("The file you chose could not be written to.")); } } diff --git a/src/widget/toxsave.cpp b/src/widget/toxsave.cpp index 845ed32dd..977953912 100644 --- a/src/widget/toxsave.cpp +++ b/src/widget/toxsave.cpp @@ -17,7 +17,6 @@ #include "src/core/core.h" #include "src/misc/settings.h" #include -#include #include bool toxSaveEventHandler(const QByteArray& eventData) @@ -55,7 +54,7 @@ bool handleToxSave(const QString& path) return false; } - QString profilePath = QDir(Settings::getSettingsDirPath()).filePath(profile + Core::TOX_EXT); + QString profilePath = Settings::getInstance().getSettingsDirPath()+profile+Core::TOX_EXT; if (QFileInfo(profilePath).exists() && !GUI::askQuestion(QObject::tr("Profile already exists", "import confirm title"), QObject::tr("A profile named \"%1\" already exists. Do you want to erase it?", "import confirm text").arg(profile))) From 61de5d4c6760c807fc3cadb94808e22046f4e801 Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 5 Jun 2015 16:27:15 +0200 Subject: [PATCH 2/3] Add Settings biglock --- src/misc/settings.cpp | 149 ++++++++++++++++++++++++++++++++++++++---- src/misc/settings.h | 4 +- 2 files changed, 138 insertions(+), 15 deletions(-) diff --git a/src/misc/settings.cpp b/src/misc/settings.cpp index 97c683b56..e22b9d64f 100644 --- a/src/misc/settings.cpp +++ b/src/misc/settings.cpp @@ -36,12 +36,14 @@ #include #include #include +#include #define SHOW_SYSTEM_TRAY_DEFAULT (bool) true const QString Settings::globalSettingsFile = "qtox.ini"; Settings* Settings::settings{nullptr}; +QMutex Settings::bigLock{QMutex::Recursive}; Settings::Settings() : loaded(false), useCustomDhtList{false}, @@ -60,6 +62,8 @@ Settings& Settings::getInstance() void Settings::load() { + QMutexLocker locker{&bigLock}; + if (loaded) return; @@ -124,7 +128,7 @@ void Settings::load() showSystemTray = s.value("showSystemTray", SHOW_SYSTEM_TRAY_DEFAULT).toBool(); makeToxPortable = s.value("makeToxPortable", false).toBool(); autostartInTray = s.value("autostartInTray", false).toBool(); - closeToTray = s.value("closeToTray", false).toBool(); + closeToTray = s.value("closeToTray", false).toBool(); forceTCP = s.value("forceTCP", false).toBool(); setProxyType(s.value("proxyType", static_cast(ProxyType::ptNone)).toInt()); proxyAddr = s.value("proxyAddr", "").toString(); @@ -276,6 +280,7 @@ void Settings::save(QString path, bool writePersonal) void Settings::saveGlobal(QString path) { + QMutexLocker locker{&bigLock}; qDebug() << "Saving settings in " + path; QSettings s(path, QSettings::IniFormat); @@ -376,6 +381,7 @@ void Settings::saveGlobal(QString path) void Settings::savePersonal(QString path) { + QMutexLocker locker{&bigLock}; if (currentProfile.isEmpty()) { qDebug() << "could not save personal settings because currentProfile profile is empty"; @@ -414,6 +420,7 @@ uint32_t Settings::makeProfileId(const QString& profile) QString Settings::getSettingsDirPath() { + QMutexLocker locker{&bigLock}; if (makeToxPortable) return QString(".")+QDir::separator(); @@ -486,32 +493,38 @@ QByteArray Settings::getAvatarHash(const QString& ownerId) const QList& Settings::getDhtServerList() const { + QMutexLocker locker{&bigLock}; return dhtServerList; } void Settings::setDhtServerList(const QList& newDhtServerList) { + QMutexLocker locker{&bigLock}; dhtServerList = newDhtServerList; emit dhtServerListChanged(); } bool Settings::getEnableIPv6() const { + QMutexLocker locker{&bigLock}; return enableIPv6; } void Settings::setEnableIPv6(bool newValue) { + QMutexLocker locker{&bigLock}; enableIPv6 = newValue; } bool Settings::getMakeToxPortable() const { + QMutexLocker locker{&bigLock}; return makeToxPortable; } void Settings::setMakeToxPortable(bool newValue) { + QMutexLocker locker{&bigLock}; makeToxPortable = newValue; save(globalSettingsFile); // Commit to the portable file that we don't want to use it if (!newValue) // Update the new file right now if not already done @@ -521,6 +534,7 @@ void Settings::setMakeToxPortable(bool newValue) bool Settings::getAutorun() const { #ifdef QTOX_PLATFORM_EXT + QMutexLocker locker{&bigLock}; return Platform::getAutorun(); #else return false; @@ -530,6 +544,7 @@ bool Settings::getAutorun() const void Settings::setAutorun(bool newValue) { #ifdef QTOX_PLATFORM_EXT + QMutexLocker locker{&bigLock}; Platform::setAutorun(newValue); #else Q_UNUSED(newValue); @@ -538,152 +553,181 @@ void Settings::setAutorun(bool newValue) bool Settings::getAutostartInTray() const { + QMutexLocker locker{&bigLock}; return autostartInTray; } QString Settings::getStyle() const { + QMutexLocker locker{&bigLock}; return style; } void Settings::setStyle(const QString& newStyle) { + QMutexLocker locker{&bigLock}; style = newStyle; } bool Settings::getShowSystemTray() const { + QMutexLocker locker{&bigLock}; return showSystemTray; } void Settings::setShowSystemTray(const bool& newValue) { + QMutexLocker locker{&bigLock}; showSystemTray = newValue; } void Settings::setUseEmoticons(bool newValue) { + QMutexLocker locker{&bigLock}; useEmoticons = newValue; } bool Settings::getUseEmoticons() const { + QMutexLocker locker{&bigLock}; return useEmoticons; } void Settings::setAutoSaveEnabled(bool newValue) { + QMutexLocker locker{&bigLock}; autoSaveEnabled = newValue; } bool Settings::getAutoSaveEnabled() const { + QMutexLocker locker{&bigLock}; return autoSaveEnabled; } void Settings::setAutostartInTray(bool newValue) { + QMutexLocker locker{&bigLock}; autostartInTray = newValue; } bool Settings::getCloseToTray() const { + QMutexLocker locker{&bigLock}; return closeToTray; } void Settings::setCloseToTray(bool newValue) { + QMutexLocker locker{&bigLock}; closeToTray = newValue; } bool Settings::getMinimizeToTray() const { + QMutexLocker locker{&bigLock}; return minimizeToTray; } - void Settings::setMinimizeToTray(bool newValue) { + QMutexLocker locker{&bigLock}; minimizeToTray = newValue; } bool Settings::getLightTrayIcon() const { + QMutexLocker locker{&bigLock}; return lightTrayIcon; } void Settings::setLightTrayIcon(bool newValue) { + QMutexLocker locker{&bigLock}; lightTrayIcon = newValue; } bool Settings::getStatusChangeNotificationEnabled() const { + QMutexLocker locker{&bigLock}; return statusChangeNotificationEnabled; } void Settings::setStatusChangeNotificationEnabled(bool newValue) { + QMutexLocker locker{&bigLock}; statusChangeNotificationEnabled = newValue; } bool Settings::getShowInFront() const { + QMutexLocker locker{&bigLock}; return showInFront; } void Settings::setShowInFront(bool newValue) { + QMutexLocker locker{&bigLock}; showInFront = newValue; } bool Settings::getNotifySound() const { - return notifySound; + QMutexLocker locker{&bigLock}; + return notifySound; } void Settings::setNotifySound(bool newValue) { + QMutexLocker locker{&bigLock}; notifySound = newValue; } bool Settings::getGroupAlwaysNotify() const { + QMutexLocker locker{&bigLock}; return groupAlwaysNotify; } void Settings::setGroupAlwaysNotify(bool newValue) { + QMutexLocker locker{&bigLock}; groupAlwaysNotify = newValue; } QString Settings::getTranslation() const { + QMutexLocker locker{&bigLock}; return translation; } void Settings::setTranslation(QString newValue) { + QMutexLocker locker{&bigLock}; translation = newValue; } bool Settings::getForceTCP() const { + QMutexLocker locker{&bigLock}; return forceTCP; } void Settings::setForceTCP(bool newValue) { + QMutexLocker locker{&bigLock}; forceTCP = newValue; } ProxyType Settings::getProxyType() const { + QMutexLocker locker{&bigLock}; return proxyType; } void Settings::setProxyType(int newValue) { + QMutexLocker locker{&bigLock}; if (newValue >= 0 && newValue <= 2) proxyType = static_cast(newValue); else @@ -692,57 +736,68 @@ void Settings::setProxyType(int newValue) QString Settings::getProxyAddr() const { + QMutexLocker locker{&bigLock}; return proxyAddr; } void Settings::setProxyAddr(const QString& newValue) { + QMutexLocker locker{&bigLock}; proxyAddr = newValue; } int Settings::getProxyPort() const { + QMutexLocker locker{&bigLock}; return proxyPort; } void Settings::setProxyPort(int newValue) { + QMutexLocker locker{&bigLock}; proxyPort = newValue; } QString Settings::getCurrentProfile() const { + QMutexLocker locker{&bigLock}; return currentProfile; } uint32_t Settings::getCurrentProfileId() const { + QMutexLocker locker{&bigLock}; return currentProfileId; } void Settings::setCurrentProfile(QString profile) { + QMutexLocker locker{&bigLock}; currentProfile = profile; currentProfileId = makeProfileId(currentProfile); } bool Settings::getEnableLogging() const { + QMutexLocker locker{&bigLock}; return enableLogging; } void Settings::setEnableLogging(bool newValue) { + QMutexLocker locker{&bigLock}; enableLogging = newValue; } Db::syncType Settings::getDbSyncType() const { + QMutexLocker locker{&bigLock}; return dbSyncType; } void Settings::setDbSyncType(int newValue) { + QMutexLocker locker{&bigLock}; if (newValue >= 0 && newValue <= 2) dbSyncType = static_cast(newValue); else @@ -751,11 +806,13 @@ void Settings::setDbSyncType(int newValue) int Settings::getAutoAwayTime() const { + QMutexLocker locker{&bigLock}; return autoAwayTime; } void Settings::setAutoAwayTime(int newValue) { + QMutexLocker locker{&bigLock}; if (newValue < 0) newValue = 10; @@ -764,6 +821,7 @@ void Settings::setAutoAwayTime(int newValue) QString Settings::getAutoAcceptDir(const ToxId& id) const { + QMutexLocker locker{&bigLock}; QString key = id.publicKey; auto it = friendLst.find(key); @@ -775,6 +833,7 @@ QString Settings::getAutoAcceptDir(const ToxId& id) const void Settings::setAutoAcceptDir(const ToxId &id, const QString& dir) { + QMutexLocker locker{&bigLock}; QString key = id.publicKey; auto it = friendLst.find(key); @@ -791,251 +850,299 @@ void Settings::setAutoAcceptDir(const ToxId &id, const QString& dir) QString Settings::getGlobalAutoAcceptDir() const { + QMutexLocker locker{&bigLock}; return globalAutoAcceptDir; } void Settings::setGlobalAutoAcceptDir(const QString& newValue) { + QMutexLocker locker{&bigLock}; globalAutoAcceptDir = newValue; } void Settings::setWidgetData(const QString& uniqueName, const QByteArray& data) { + QMutexLocker locker{&bigLock}; widgetSettings[uniqueName] = data; } QByteArray Settings::getWidgetData(const QString& uniqueName) const { + QMutexLocker locker{&bigLock}; return widgetSettings.value(uniqueName); } bool Settings::isAnimationEnabled() const { + QMutexLocker locker{&bigLock}; return enableSmoothAnimation; } void Settings::setAnimationEnabled(bool newValue) { + QMutexLocker locker{&bigLock}; enableSmoothAnimation = newValue; } QString Settings::getSmileyPack() const { + QMutexLocker locker{&bigLock}; return smileyPack; } void Settings::setSmileyPack(const QString &value) { + QMutexLocker locker{&bigLock}; smileyPack = value; emit smileyPackChanged(); } bool Settings::isCurstomEmojiFont() const { + QMutexLocker locker{&bigLock}; return customEmojiFont; } void Settings::setCurstomEmojiFont(bool value) { + QMutexLocker locker{&bigLock}; customEmojiFont = value; emit emojiFontChanged(); } int Settings::getEmojiFontPointSize() const { + QMutexLocker locker{&bigLock}; return emojiFontPointSize; } void Settings::setEmojiFontPointSize(int value) { + QMutexLocker locker{&bigLock}; emojiFontPointSize = value; emit emojiFontChanged(); } int Settings::getFirstColumnHandlePos() const { + QMutexLocker locker{&bigLock}; return firstColumnHandlePos; } void Settings::setFirstColumnHandlePos(const int pos) { + QMutexLocker locker{&bigLock}; firstColumnHandlePos = pos; } int Settings::getSecondColumnHandlePosFromRight() const { + QMutexLocker locker{&bigLock}; return secondColumnHandlePosFromRight; } void Settings::setSecondColumnHandlePosFromRight(const int pos) { + QMutexLocker locker{&bigLock}; secondColumnHandlePosFromRight = pos; } const QString& Settings::getTimestampFormat() const { + QMutexLocker locker{&bigLock}; return timestampFormat; } void Settings::setTimestampFormat(const QString &format) { + QMutexLocker locker{&bigLock}; timestampFormat = format; } const QString& Settings::getDateFormat() const { + QMutexLocker locker{&bigLock}; return dateFormat; } void Settings::setDateFormat(const QString &format) { + QMutexLocker locker{&bigLock}; dateFormat = format; } - QString Settings::getEmojiFontFamily() const { + QMutexLocker locker{&bigLock}; return emojiFontFamily; } void Settings::setEmojiFontFamily(const QString &value) { + QMutexLocker locker{&bigLock}; emojiFontFamily = value; emit emojiFontChanged(); } bool Settings::getUseNativeStyle() const { + QMutexLocker locker{&bigLock}; return useNativeStyle; } void Settings::setUseNativeStyle(bool value) { + QMutexLocker locker{&bigLock}; useNativeStyle = value; } QByteArray Settings::getWindowGeometry() const { + QMutexLocker locker{&bigLock}; return windowGeometry; } void Settings::setWindowGeometry(const QByteArray &value) { + QMutexLocker locker{&bigLock}; windowGeometry = value; } QByteArray Settings::getWindowState() const { + QMutexLocker locker{&bigLock}; return windowState; } void Settings::setWindowState(const QByteArray &value) { + QMutexLocker locker{&bigLock}; windowState = value; } bool Settings::getCheckUpdates() const { + QMutexLocker locker{&bigLock}; return checkUpdates; } void Settings::setCheckUpdates(bool newValue) { + QMutexLocker locker{&bigLock}; checkUpdates = newValue; } bool Settings::getShowWindow() const { + QMutexLocker locker{&bigLock}; return showWindow; } void Settings::setShowWindow(bool newValue) { + QMutexLocker locker{&bigLock}; showWindow = newValue; } QByteArray Settings::getSplitterState() const { + QMutexLocker locker{&bigLock}; return splitterState; } void Settings::setSplitterState(const QByteArray &value) { + QMutexLocker locker{&bigLock}; splitterState = value; } bool Settings::isMinimizeOnCloseEnabled() const { + QMutexLocker locker{&bigLock}; return minimizeOnClose; } void Settings::setMinimizeOnClose(bool newValue) { + QMutexLocker locker{&bigLock}; minimizeOnClose = newValue; } bool Settings::isTypingNotificationEnabled() const { + QMutexLocker locker{&bigLock}; return typingNotification; } void Settings::setTypingNotification(bool enabled) { + QMutexLocker locker{&bigLock}; typingNotification = enabled; } QString Settings::getInDev() const { + QMutexLocker locker{&bigLock}; return inDev; } void Settings::setInDev(const QString& deviceSpecifier) { + QMutexLocker locker{&bigLock}; inDev = deviceSpecifier; } QString Settings::getVideoDev() const { + QMutexLocker locker{&bigLock}; return videoDev; } void Settings::setVideoDev(const QString& deviceSpecifier) { + QMutexLocker locker{&bigLock}; videoDev = deviceSpecifier; } QString Settings::getOutDev() const { + QMutexLocker locker{&bigLock}; return outDev; } void Settings::setOutDev(const QString& deviceSpecifier) { + QMutexLocker locker{&bigLock}; outDev = deviceSpecifier; } bool Settings::getFilterAudio() const { + QMutexLocker locker{&bigLock}; return filterAudio; } void Settings::setFilterAudio(bool newValue) { + QMutexLocker locker{&bigLock}; filterAudio = newValue; } QSize Settings::getCamVideoRes() const { + QMutexLocker locker{&bigLock}; return camVideoRes; } void Settings::setCamVideoRes(QSize newValue) { + QMutexLocker locker{&bigLock}; camVideoRes = newValue; } QString Settings::getFriendAdress(const QString &publicKey) const { + QMutexLocker locker{&bigLock}; QString key = ToxId(publicKey).publicKey; auto it = friendLst.find(key); if (it != friendLst.end()) @@ -1046,6 +1153,7 @@ QString Settings::getFriendAdress(const QString &publicKey) const void Settings::updateFriendAdress(const QString &newAddr) { + QMutexLocker locker{&bigLock}; QString key = ToxId(newAddr).publicKey; auto it = friendLst.find(key); if (it != friendLst.end()) @@ -1064,6 +1172,7 @@ void Settings::updateFriendAdress(const QString &newAddr) QString Settings::getFriendAlias(const ToxId &id) const { + QMutexLocker locker{&bigLock}; QString key = id.publicKey; auto it = friendLst.find(key); if (it != friendLst.end()) @@ -1074,6 +1183,7 @@ QString Settings::getFriendAlias(const ToxId &id) const void Settings::setFriendAlias(const ToxId &id, const QString &alias) { + QMutexLocker locker{&bigLock}; QString key = id.publicKey; auto it = friendLst.find(key); if (it != friendLst.end()) @@ -1092,50 +1202,71 @@ void Settings::setFriendAlias(const ToxId &id, const QString &alias) void Settings::removeFriendSettings(const ToxId &id) { + QMutexLocker locker{&bigLock}; QString key = id.publicKey; friendLst.remove(key); } bool Settings::getFauxOfflineMessaging() const { + QMutexLocker locker{&bigLock}; return fauxOfflineMessaging; } void Settings::setFauxOfflineMessaging(bool value) { + QMutexLocker locker{&bigLock}; fauxOfflineMessaging = value; } bool Settings::getCompactLayout() const { + QMutexLocker locker{&bigLock}; return compactLayout; } void Settings::setCompactLayout(bool value) { + QMutexLocker locker{&bigLock}; compactLayout = value; } bool Settings::getGroupchatPosition() const { + QMutexLocker locker{&bigLock}; return groupchatPosition; } void Settings::setGroupchatPosition(bool value) { + QMutexLocker locker{&bigLock}; groupchatPosition = value; } int Settings::getThemeColor() const { + QMutexLocker locker{&bigLock}; return themeColor; } void Settings::setThemeColor(const int &value) { + QMutexLocker locker{&bigLock}; themeColor = value; } +bool Settings::getAutoLogin() const +{ + QMutexLocker locker{&bigLock}; + return autoLogin; +} + +void Settings::setAutoLogin(bool state) +{ + QMutexLocker locker{&bigLock}; + autoLogin = state; +} + void Settings::createPersonal(QString basename) { QString path = getSettingsDirPath() + QDir::separator() + basename + ".ini"; @@ -1158,13 +1289,3 @@ void Settings::createSettingsDir() if (!directory.exists() && !directory.mkpath(directory.absolutePath())) qCritical() << "Error while creating directory " << dir; } - -bool Settings::getAutoLogin() const -{ - return autoLogin; -} - -void Settings::setAutoLogin(bool state) -{ - autoLogin = state; -} diff --git a/src/misc/settings.h b/src/misc/settings.h index 89a469452..136c73b50 100644 --- a/src/misc/settings.h +++ b/src/misc/settings.h @@ -20,6 +20,7 @@ #include #include #include +#include #include "src/core/corestructs.h" class ToxId; @@ -38,9 +39,9 @@ public: void createSettingsDir(); ///< Creates a path to the settings dir, if it doesn't already exist void createPersonal(QString basename); ///< Write a default personnal .ini settings file for a profile + void load(); void save(bool writePersonal = true); void save(QString path, bool writePersonal = true); - void load(); signals: void dhtServerListChanged(); @@ -348,6 +349,7 @@ private: int themeColor; + static QMutex bigLock; static Settings* settings; static const QString globalSettingsFile; }; From c9202f67949ec1ce4836897d407a53e502ab2c17 Mon Sep 17 00:00:00 2001 From: tux3 Date: Fri, 5 Jun 2015 18:01:50 +0200 Subject: [PATCH 3/3] Asynchronous settings saving --- src/main.cpp | 6 +++--- src/misc/settings.cpp | 43 +++++++++++++++++++++++++++++++++++++++++-- src/misc/settings.h | 10 +++++++--- 3 files changed, 51 insertions(+), 8 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 539273b74..095483c8a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -95,7 +95,7 @@ int main(int argc, char *argv[]) #endif qsrand(time(0)); - + Settings::getInstance(); Translator::translate(); // Process arguments @@ -110,7 +110,6 @@ int main(int argc, char *argv[]) #ifndef Q_OS_ANDROID IPC::getInstance(); #endif - Settings::getInstance(); // Build our Settings singleton as soon as QApplication is ready, not before if (parser.isSet("p")) { @@ -272,6 +271,7 @@ int main(int argc, char *argv[]) #endif Nexus::destroyInstance(); - + Settings::destroyInstance(); + qDebug() << "Clean exit with status"< #include #include - +#include #define SHOW_SYSTEM_TRAY_DEFAULT (bool) true const QString Settings::globalSettingsFile = "qtox.ini"; Settings* Settings::settings{nullptr}; QMutex Settings::bigLock{QMutex::Recursive}; +QThread* Settings::settingsThread{nullptr}; Settings::Settings() : loaded(false), useCustomDhtList{false}, makeToxPortable{false}, currentProfileId(0) { + settingsThread = new QThread(); + settingsThread->setObjectName("qTox Settings"); + settingsThread->start(QThread::LowPriority); + moveToThread(settingsThread); load(); } +Settings::~Settings() +{ + sync(); + settingsThread->exit(0); + settingsThread->wait(); + delete settingsThread; +} + Settings& Settings::getInstance() { if (!settings) @@ -60,6 +73,12 @@ Settings& Settings::getInstance() return *settings; } +void Settings::destroyInstance() +{ + delete settings; + settings = nullptr; +} + void Settings::load() { QMutexLocker locker{&bigLock}; @@ -263,12 +282,20 @@ void Settings::load() void Settings::save(bool writePersonal) { - QString filePath = QDir(getSettingsDirPath()).filePath(globalSettingsFile); + if (QThread::currentThread() != settingsThread) + return (void) QMetaObject::invokeMethod(&getInstance(), "save", + Q_ARG(bool, writePersonal)); + + QString filePath = getSettingsDirPath()+globalSettingsFile; save(filePath, writePersonal); } void Settings::save(QString path, bool writePersonal) { + if (QThread::currentThread() != settingsThread) + return (void) QMetaObject::invokeMethod(&getInstance(), "save", + Q_ARG(QString, path), Q_ARG(bool, writePersonal)); + #ifndef Q_OS_ANDROID if (IPC::getInstance().isCurrentOwner()) #endif @@ -1289,3 +1316,15 @@ void Settings::createSettingsDir() if (!directory.exists() && !directory.mkpath(directory.absolutePath())) qCritical() << "Error while creating directory " << dir; } + +void Settings::sync() +{ + if (QThread::currentThread() != settingsThread) + { + QMetaObject::invokeMethod(&getInstance(), "sync", Qt::BlockingQueuedConnection); + return; + } + + QMutexLocker locker{&bigLock}; + qApp->processEvents(); +} diff --git a/src/misc/settings.h b/src/misc/settings.h index 136c73b50..1fec001bd 100644 --- a/src/misc/settings.h +++ b/src/misc/settings.h @@ -32,16 +32,18 @@ class Settings : public QObject { Q_OBJECT public: - ~Settings() = default; static Settings& getInstance(); + static void destroyInstance(); QString getSettingsDirPath(); ///< The returned path ends with a directory separator void createSettingsDir(); ///< Creates a path to the settings dir, if it doesn't already exist void createPersonal(QString basename); ///< Write a default personnal .ini settings file for a profile +public slots: void load(); - void save(bool writePersonal = true); - void save(QString path, bool writePersonal = true); + void save(bool writePersonal = true); ///< Asynchronous + void save(QString path, bool writePersonal = true); ///< Asynchronous + void sync(); ///< Waits for all asynchronous operations to complete signals: void dhtServerListChanged(); @@ -254,6 +256,7 @@ public: private: Settings(); + ~Settings(); Settings(Settings &settings) = delete; Settings& operator=(const Settings&) = delete; static uint32_t makeProfileId(const QString& profile); @@ -352,6 +355,7 @@ private: static QMutex bigLock; static Settings* settings; static const QString globalSettingsFile; + static QThread* settingsThread; }; #endif // SETTINGS_HPP