Browse Source

Merge pull request #5711

jenli669 (10):
      refactor(startup): decouple loginscreen from model
      refactor(startup): check parser args with empty(), not size()
      refactor(startup): display last used profile when logging out
      refactor(startup): remove unnecessary arg. passing in loadDatabase
      refactor(startup): extract startup makeToxPortable logic
      refactor(startup): condense and rename scanProfiles
      refactor(startup): handle autoLogin checkbox with signals
      refactor(startup): use instance during profile import
      refactor(startup): clang-format changes to edited files
      refactor(startup): return early in makeToxPortable logic
reviewable/pr5721/r2
Diadlo 6 years ago
parent
commit
0a30a657fc
No known key found for this signature in database
GPG Key ID: 5AF9F2E29107C727
  1. 57
      src/main.cpp
  2. 8
      src/model/profile/profileinfo.cpp
  3. 103
      src/nexus.cpp
  4. 25
      src/nexus.h
  5. 22
      src/persistence/profile.cpp
  6. 8
      src/persistence/profile.h
  7. 52
      src/persistence/settings.cpp
  8. 5
      src/persistence/settings.h
  9. 103
      src/widget/loginscreen.cpp
  10. 19
      src/widget/loginscreen.h

57
src/main.cpp

@ -18,7 +18,6 @@
*/ */
#include "src/audio/audio.h" #include "src/audio/audio.h"
#include "src/core/coreav.h"
#include "src/ipc.h" #include "src/ipc.h"
#include "src/net/toxuri.h" #include "src/net/toxuri.h"
#include "src/nexus.h" #include "src/nexus.h"
@ -194,8 +193,8 @@ int main(int argc, char* argv[])
#endif #endif
qsrand(time(nullptr)); qsrand(time(nullptr));
Settings::getInstance(); Settings& settings = Settings::getInstance();
QString locale = Settings::getInstance().getTranslation(); QString locale = settings.getTranslation();
Translator::translate(locale); Translator::translate(locale);
// Process arguments // Process arguments
@ -215,15 +214,14 @@ int main(int argc, char* argv[])
QObject::tr("Starts new instance and opens the login screen."))); QObject::tr("Starts new instance and opens the login screen.")));
parser.process(*a); parser.process(*a);
uint32_t profileId = Settings::getInstance().getCurrentProfileId(); uint32_t profileId = settings.getCurrentProfileId();
IPC ipc(profileId); IPC ipc(profileId);
if (!ipc.isAttached()) { if (!ipc.isAttached()) {
qCritical() << "Can't init IPC"; qCritical() << "Can't init IPC";
return EXIT_FAILURE; return EXIT_FAILURE;
} }
QObject::connect(&Settings::getInstance(), &Settings::currentProfileIdChanged, &ipc, QObject::connect(&settings, &Settings::currentProfileIdChanged, &ipc, &IPC::setProfileId);
&IPC::setProfileId);
// For the auto-updater // For the auto-updater
if (sodium_init() < 0) { if (sodium_init() < 0) {
@ -232,7 +230,7 @@ int main(int argc, char* argv[])
} }
#ifdef LOG_TO_FILE #ifdef LOG_TO_FILE
QString logFileDir = Settings::getInstance().getAppCacheDirPath(); QString logFileDir = settings.getAppCacheDirPath();
QDir(logFileDir).mkpath("."); QDir(logFileDir).mkpath(".");
QString logfile = logFileDir + "qtox.log"; QString logfile = logFileDir + "qtox.log";
@ -274,7 +272,7 @@ int main(int argc, char* argv[])
qDebug() << "commit: " << GIT_VERSION; qDebug() << "commit: " << GIT_VERSION;
QString profileName; QString profileName;
bool autoLogin = Settings::getInstance().getAutoLogin(); bool autoLogin = settings.getAutoLogin();
uint32_t ipcDest = 0; uint32_t ipcDest = 0;
bool doIpc = true; bool doIpc = true;
@ -294,10 +292,10 @@ int main(int argc, char* argv[])
doIpc = false; doIpc = false;
autoLogin = false; autoLogin = false;
} else { } else {
profileName = Settings::getInstance().getCurrentProfile(); profileName = settings.getCurrentProfile();
} }
if (parser.positionalArguments().size() == 0) { if (parser.positionalArguments().empty()) {
eventType = "activate"; eventType = "activate";
} else { } else {
firstParam = parser.positionalArguments()[0]; firstParam = parser.positionalArguments()[0];
@ -330,38 +328,27 @@ int main(int argc, char* argv[])
} }
} }
Profile* profile = nullptr; // 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);
// Autologin // Autologin
// TODO (kriby): Shift responsibility of linking views to model objects from nexus
// Further: generate view instances separately (loginScreen, mainGUI, audio)
if (autoLogin && Profile::exists(profileName) && !Profile::isEncrypted(profileName)) { if (autoLogin && Profile::exists(profileName) && !Profile::isEncrypted(profileName)) {
profile = Profile::loadProfile(profileName); Profile* profile = Profile::loadProfile(profileName);
settings.updateProfileData(profile);
nexus.bootstrapWithProfile(profile);
} else { } else {
LoginScreen loginScreen{profileName}; int returnval = nexus.showLogin(profileName);
loginScreen.exec(); if (returnval != 0) {
profile = loginScreen.getProfile(); return returnval;
if (profile) {
profileName = profile->getName();
} }
} }
if (!profile) {
return EXIT_FAILURE;
}
Nexus::getInstance().setProfile(profile);
Settings& s = Settings::getInstance();
s.setCurrentProfile(profileName);
auto audio = Audio::makeAudio(s);
assert(audio != nullptr);
// TODO(sudden6): init CoreAV audio backend somewhere else so main doesn't depend on coreav.h
profile->getCore()->getAv()->setAudio(*audio);
Nexus& nexus = Nexus::getInstance();
// TODO(sudden6): remove once we get rid of Nexus
nexus.audio = audio.get();
nexus.start();
// Start to accept Inter-process communication // Start to accept Inter-process communication
ipc.registerEventHandler("uri", &toxURIEventHandler); ipc.registerEventHandler("uri", &toxURIEventHandler);
ipc.registerEventHandler("save", &toxSaveEventHandler); ipc.registerEventHandler("save", &toxSaveEventHandler);

8
src/model/profile/profileinfo.cpp

@ -226,8 +226,10 @@ QStringList ProfileInfo::removeProfile()
*/ */
void ProfileInfo::logout() void ProfileInfo::logout()
{ {
// TODO(kriby): Refactor all of these invokeMethod calls with connect() properly when possible
Settings::getInstance().saveGlobal(); Settings::getInstance().saveGlobal();
QMetaObject::invokeMethod(&Nexus::getInstance(), "showLogin"); QMetaObject::invokeMethod(&Nexus::getInstance(), "showLogin",
Q_ARG(QString, Settings::getInstance().getCurrentProfile()));
} }
/** /**
@ -340,8 +342,8 @@ IProfileInfo::SetAvatarResult ProfileInfo::byteArrayToPng(QByteArray inData, QBy
} }
if (format == "png") { if (format == "png") {
// FIXME: re-encode the png even though inData is already valid. This strips the metadata since // FIXME: re-encode the png even though inData is already valid. This strips the metadata
// we don't have a good png metadata stripping method currently. // since we don't have a good png metadata stripping method currently.
outPng = picToPng(image); outPng = picToPng(image);
} else { } else {
outPng = picToPng(image); outPng = picToPng(image);

103
src/nexus.cpp

@ -35,6 +35,7 @@
#include <QThread> #include <QThread>
#include <cassert> #include <cassert>
#include <vpx/vpx_image.h> #include <vpx/vpx_image.h>
#include <src/audio/audio.h>
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
#include <QActionGroup> #include <QActionGroup>
@ -67,7 +68,7 @@ Nexus::~Nexus()
widget = nullptr; widget = nullptr;
delete profile; delete profile;
profile = nullptr; profile = nullptr;
Settings::getInstance().saveGlobal(); emit saveGlobal();
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
delete globalMenuBar; delete globalMenuBar;
#endif #endif
@ -148,7 +149,7 @@ void Nexus::start()
/** /**
* @brief Hides the main GUI, delete the profile, and shows the login screen * @brief Hides the main GUI, delete the profile, and shows the login screen
*/ */
void Nexus::showLogin() int Nexus::showLogin(const QString& profileName)
{ {
delete widget; delete widget;
widget = nullptr; widget = nullptr;
@ -156,26 +157,72 @@ void Nexus::showLogin()
delete profile; delete profile;
profile = nullptr; profile = nullptr;
LoginScreen loginScreen; LoginScreen loginScreen{profileName};
loginScreen.exec(); connectLoginScreen(loginScreen);
profile = loginScreen.getProfile(); // TODO(kriby): Move core out of profile
// This is awkward because the core is in the profile
// The connection order ensures profile will be ready for bootstrap for now
connect(this, &Nexus::currentProfileChanged, this, &Nexus::bootstrapWithProfile);
int returnval = loginScreen.exec();
disconnect(this, &Nexus::currentProfileChanged, this, &Nexus::bootstrapWithProfile);
return returnval;
}
void Nexus::bootstrapWithProfile(Profile *p)
{
// kriby: This is a hack until a proper controller is written
profile = p;
if (profile) { if (profile) {
Nexus::getInstance().setProfile(profile); audioControl = std::unique_ptr<IAudioControl>(Audio::makeAudio(*settings));
Settings::getInstance().setCurrentProfile(profile->getName()); assert(audioControl != nullptr);
showMainGUI(); profile->getCore()->getAv()->setAudio(*audioControl);
} else { start();
qApp->quit(); }
}
void Nexus::setSettings(Settings* settings)
{
if (this->settings) {
QObject::disconnect(this, &Nexus::currentProfileChanged, this->settings,
&Settings::updateProfileData);
QObject::disconnect(this, &Nexus::saveGlobal, this->settings, &Settings::saveGlobal);
} }
this->settings = settings;
if (this->settings) {
QObject::connect(this, &Nexus::currentProfileChanged, this->settings,
&Settings::updateProfileData);
QObject::connect(this, &Nexus::saveGlobal, this->settings, &Settings::saveGlobal);
}
}
void Nexus::connectLoginScreen(const LoginScreen& loginScreen)
{
// TODO(kriby): Move connect sequences to a controller class object instead
// Nexus -> LoginScreen
QObject::connect(this, &Nexus::profileLoaded, &loginScreen, &LoginScreen::onProfileLoaded);
QObject::connect(this, &Nexus::profileLoadFailed, &loginScreen, &LoginScreen::onProfileLoadFailed);
// LoginScreen -> Nexus
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);
// Settings -> LoginScreen
QObject::connect(settings, &Settings::autoLoginChanged, &loginScreen,
&LoginScreen::onAutoLoginChanged);
} }
void Nexus::showMainGUI() void Nexus::showMainGUI()
{ {
// TODO(kriby): Rewrite as view-model connect sequence only, add to a controller class object
assert(profile); assert(profile);
// Create GUI // Create GUI
widget = Widget::getInstance(audio); widget = Widget::getInstance(audioControl.get());
// Start GUI // Start GUI
widget->init(); widget->init();
@ -270,14 +317,36 @@ Profile* Nexus::getProfile()
} }
/** /**
* @brief Unload the current profile, if any, and replaces it. * @brief Creates a new profile and replaces the current one.
* @param profile Profile to set. * @param name New username
* @param pass New password
*/
void Nexus::onCreateNewProfile(const QString& name, const QString& pass)
{
setProfile(Profile::createProfile(name, pass));
}
/**
* Loads an existing profile and replaces the current one.
*/ */
void Nexus::setProfile(Profile* profile) void Nexus::onLoadProfile(const QString& name, const QString& pass)
{ {
getInstance().profile = profile; setProfile(Profile::loadProfile(name, pass));
if (profile) }
Settings::getInstance().loadPersonal(profile->getName(), profile->getPasskey()); /**
* Changes the loaded profile and notifies listeners.
* @param p
*/
void Nexus::setProfile(Profile* p) {
if (!p) {
emit profileLoadFailed();
// Warnings are issued during respective createNew/load calls
return;
} else {
emit profileLoaded();
}
emit currentProfileChanged(p);
} }
/** /**

25
src/nexus.h

@ -27,6 +27,8 @@
class Widget; class Widget;
class Profile; class Profile;
class Settings;
class LoginScreen;
class Core; class Core;
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
@ -44,16 +46,13 @@ class Nexus : public QObject
public: public:
void start(); void start();
void showMainGUI(); void showMainGUI();
void setSettings(Settings* settings);
static Nexus& getInstance(); static Nexus& getInstance();
static void destroyInstance(); static void destroyInstance();
static Core* getCore(); static Core* getCore();
static Profile* getProfile(); static Profile* getProfile();
static void setProfile(Profile* profile);
static Widget* getDesktopGUI(); static Widget* getDesktopGUI();
public slots:
void showLogin();
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
public: public:
@ -81,17 +80,29 @@ private:
QSignalMapper* windowMapper; QSignalMapper* windowMapper;
QActionGroup* windowActions = nullptr; QActionGroup* windowActions = nullptr;
#endif #endif
public: signals:
// TODO(sudden6): hack to pass the audio instance void currentProfileChanged(Profile* Profile);
IAudioControl* audio = nullptr; void profileLoaded();
void profileLoadFailed();
void saveGlobal();
public slots:
void onCreateNewProfile(const QString& name, const QString& pass);
void onLoadProfile(const QString& name, const QString& pass);
int showLogin(const QString& profileName = QString());
void bootstrapWithProfile(Profile *p);
private: private:
explicit Nexus(QObject* parent = nullptr); explicit Nexus(QObject* parent = nullptr);
void connectLoginScreen(const LoginScreen& loginScreen);
void setProfile(Profile* p);
~Nexus(); ~Nexus();
private: private:
Profile* profile; Profile* profile;
Settings* settings;
Widget* widget; Widget* widget;
std::unique_ptr<IAudioControl> audioControl;
}; };
#endif // NEXUS_H #endif // NEXUS_H

22
src/persistence/profile.cpp

@ -105,13 +105,11 @@ Profile::Profile(QString name, const QString& password, bool isNewProfile,
, encrypted{this->passkey != nullptr} , encrypted{this->passkey != nullptr}
{ {
Settings& s = Settings::getInstance(); Settings& s = Settings::getInstance();
s.setCurrentProfile(name); // TODO(kriby): Move/refactor core initialization to remove settings dependency
s.saveGlobal(); // note to self: use slots/signals for this?
s.loadPersonal(name, this->passkey.get());
initCore(toxsave, s, isNewProfile); initCore(toxsave, s, isNewProfile);
const ToxId& selfId = core->getSelfId(); loadDatabase(password);
loadDatabase(selfId, password);
} }
/** /**
@ -271,21 +269,17 @@ QStringList Profile::getFilesByExt(QString extension)
* @brief Scan for profile, automatically importing them if needed. * @brief Scan for profile, automatically importing them if needed.
* @warning NOT thread-safe. * @warning NOT thread-safe.
*/ */
void Profile::scanProfiles() const QStringList Profile::getAllProfileNames()
{ {
profiles.clear(); profiles.clear();
QStringList toxfiles = getFilesByExt("tox"), inifiles = getFilesByExt("ini"); QStringList toxfiles = getFilesByExt("tox"), inifiles = getFilesByExt("ini");
for (QString toxfile : toxfiles) { for (const QString& toxfile : toxfiles) {
if (!inifiles.contains(toxfile)) { if (!inifiles.contains(toxfile)) {
Settings::getInstance().createPersonal(toxfile); Settings::getInstance().createPersonal(toxfile);
} }
profiles.append(toxfile); profiles.append(toxfile);
} }
}
QStringList Profile::getProfiles()
{
return profiles; return profiles;
} }
@ -473,14 +467,16 @@ QByteArray Profile::loadAvatarData(const ToxPk& owner)
return pic; return pic;
} }
void Profile::loadDatabase(const ToxId& id, QString password) void Profile::loadDatabase(QString password)
{ {
assert(core);
if (isRemoved) { if (isRemoved) {
qDebug() << "Can't load database of removed profile"; qDebug() << "Can't load database of removed profile";
return; return;
} }
QByteArray salt = id.getPublicKey().getByteArray(); QByteArray salt = core->getSelfId().getPublicKey().getByteArray();
if (salt.size() != TOX_PASS_SALT_LENGTH) { if (salt.size() != TOX_PASS_SALT_LENGTH) {
qWarning() << "Couldn't compute salt from public key" << name; qWarning() << "Couldn't compute salt from public key" << name;
GUI::showError(QObject::tr("Error"), GUI::showError(QObject::tr("Error"),

8
src/persistence/profile.h

@ -67,8 +67,7 @@ public:
bool rename(QString newName); bool rename(QString newName);
static void scanProfiles(); static const QStringList getAllProfileNames();
static QStringList getProfiles();
static bool exists(QString name); static bool exists(QString name);
static bool isEncrypted(QString name); static bool isEncrypted(QString name);
@ -90,7 +89,7 @@ public slots:
void onRequestSent(const ToxPk& friendPk, const QString& message); void onRequestSent(const ToxPk& friendPk, const QString& message);
private slots: private slots:
void loadDatabase(const ToxId& id, QString password); void loadDatabase(QString password);
void saveAvatar(const ToxPk& owner, const QByteArray& avatar); void saveAvatar(const ToxPk& owner, const QByteArray& avatar);
void removeAvatar(const ToxPk& owner); void removeAvatar(const ToxPk& owner);
void onSaveToxSave(); void onSaveToxSave();
@ -98,7 +97,8 @@ private slots:
void onAvatarOfferReceived(uint32_t friendId, uint32_t fileId, const QByteArray& avatarHash); void onAvatarOfferReceived(uint32_t friendId, uint32_t fileId, const QByteArray& avatarHash);
private: private:
Profile(QString name, const QString& password, bool newProfile, const QByteArray& toxsave, std::unique_ptr<ToxEncrypt> passKey); Profile(QString name, const QString& password, bool newProfile, const QByteArray& toxsave,
std::unique_ptr<ToxEncrypt> passKey);
static QStringList getFilesByExt(QString extension); static QStringList getFilesByExt(QString extension);
QString avatarPath(const ToxPk& owner, bool forceUnencrypted = false); QString avatarPath(const ToxPk& owner, bool forceUnencrypted = false);
bool saveToxSave(QByteArray data); bool saveToxSave(QByteArray data);

52
src/persistence/settings.cpp

@ -109,17 +109,7 @@ void Settings::loadGlobal()
createSettingsDir(); createSettingsDir();
QString localSettingsPath = qApp->applicationDirPath() + QDir::separator() + globalSettingsFile; makeToxPortable = Settings::isToxPortable();
if (QFile(localSettingsPath).exists()) {
QSettings ps(localSettingsPath, QSettings::IniFormat);
ps.setIniCodec("UTF-8");
ps.beginGroup("Advanced");
makeToxPortable = ps.value("makeToxPortable", false).toBool();
ps.endGroup();
} else {
makeToxPortable = false;
}
QDir dir(getSettingsDirPath()); QDir dir(getSettingsDirPath());
QString filePath = dir.filePath(globalSettingsFile); QString filePath = dir.filePath(globalSettingsFile);
@ -153,9 +143,11 @@ void Settings::loadGlobal()
} }
autoAwayTime = s.value("autoAwayTime", 10).toInt(); autoAwayTime = s.value("autoAwayTime", 10).toInt();
checkUpdates = s.value("checkUpdates", true).toBool(); checkUpdates = s.value("checkUpdates", true).toBool();
notifySound = s.value("notifySound", true).toBool(); // note: notifySound and busySound UI elements are now under UI settings // note: notifySound and busySound UI elements are now under UI settings
// page, but kept under General in settings file to be backwards compatible
notifySound = s.value("notifySound", true).toBool();
notifyHide = s.value("notifyHide", false).toBool(); notifyHide = s.value("notifyHide", false).toBool();
busySound = s.value("busySound", false).toBool(); // page, but kept under General in settings file to be backwards compatible busySound = s.value("busySound", false).toBool();
autoSaveEnabled = s.value("autoSaveEnabled", false).toBool(); autoSaveEnabled = s.value("autoSaveEnabled", false).toBool();
globalAutoAcceptDir = s.value("globalAutoAcceptDir", globalAutoAcceptDir = s.value("globalAutoAcceptDir",
QStandardPaths::locate(QStandardPaths::HomeLocation, QString(), QStandardPaths::locate(QStandardPaths::HomeLocation, QString(),
@ -273,6 +265,33 @@ void Settings::loadGlobal()
loaded = true; loaded = true;
} }
bool Settings::isToxPortable()
{
QString localSettingsPath = qApp->applicationDirPath() + QDir::separator() + globalSettingsFile;
if (!QFile(localSettingsPath).exists()) {
return false;
}
QSettings ps(localSettingsPath, QSettings::IniFormat);
ps.setIniCodec("UTF-8");
ps.beginGroup("Advanced");
bool result = ps.value("makeToxPortable", false).toBool();
ps.endGroup();
return result;
}
void Settings::updateProfileData(Profile *profile)
{
QMutexLocker locker{&bigLock};
if (profile == nullptr) {
qWarning() << QString("Could not load new settings (profile change to nullptr)");
return;
}
setCurrentProfile(profile->getName());
saveGlobal();
loadPersonal(profile->getName(), profile->getPasskey());
}
void Settings::loadPersonal(QString profileName, const ToxEncrypt* passKey) void Settings::loadPersonal(QString profileName, const ToxEncrypt* passKey)
{ {
QMutexLocker locker{&bigLock}; QMutexLocker locker{&bigLock};
@ -319,7 +338,7 @@ void Settings::loadPersonal(QString profileName, const ToxEncrypt* passKey)
fp.circleID = ps.value("circle", -1).toInt(); fp.circleID = ps.value("circle", -1).toInt();
if (getEnableLogging()) if (getEnableLogging())
fp.activity = ps.value("activity", QDateTime()).toDateTime(); fp.activity = ps.value("activity", QDateTime()).toDateTime();
friendLst.insert(ToxId(fp.addr).getPublicKey().getByteArray(), fp); friendLst.insert(ToxId(fp.addr).getPublicKey().getByteArray(), fp);
} }
ps.endArray(); ps.endArray();
@ -346,7 +365,8 @@ void Settings::loadPersonal(QString profileName, const ToxEncrypt* passKey)
ps.beginGroup("GUI"); ps.beginGroup("GUI");
{ {
compactLayout = ps.value("compactLayout", true).toBool(); compactLayout = ps.value("compactLayout", true).toBool();
sortingMode = static_cast<FriendListSortingMode>(ps.value("friendSortingMethod", static_cast<int>(FriendListSortingMode::Name)).toInt()); sortingMode = static_cast<FriendListSortingMode>(
ps.value("friendSortingMethod", static_cast<int>(FriendListSortingMode::Name)).toInt());
} }
ps.endGroup(); ps.endGroup();
@ -1281,7 +1301,7 @@ void Settings::setCurrentProfile(const QString& profile)
if (profile != currentProfile) { if (profile != currentProfile) {
currentProfile = profile; currentProfile = profile;
currentProfileId = makeProfileId(currentProfile); currentProfileId = makeProfileId(currentProfile);
emit currentProfileChanged(currentProfile);
emit currentProfileIdChanged(currentProfileId); emit currentProfileIdChanged(currentProfileId);
} }
} }

5
src/persistence/settings.h

@ -154,6 +154,7 @@ public:
void savePersonal(); void savePersonal();
void loadGlobal(); void loadGlobal();
bool isToxPortable();
void loadPersonal(QString profileName, const ToxEncrypt* passKey); void loadPersonal(QString profileName, const ToxEncrypt* passKey);
void resetToDefault(); void resetToDefault();
@ -168,6 +169,8 @@ public:
public slots: public slots:
void saveGlobal(); void saveGlobal();
void sync(); void sync();
void setAutoLogin(bool state);
void updateProfileData(Profile *profile);
signals: signals:
// General // General
@ -190,7 +193,6 @@ signals:
void toxmeBioChanged(const QString& bio); void toxmeBioChanged(const QString& bio);
void toxmePrivChanged(bool priv); void toxmePrivChanged(bool priv);
void toxmePassChanged(); void toxmePassChanged();
void currentProfileChanged(const QString& profile);
void currentProfileIdChanged(quint32 id); void currentProfileIdChanged(quint32 id);
void enableLoggingChanged(bool enabled); void enableLoggingChanged(bool enabled);
void autoAwayTimeChanged(int minutes); void autoAwayTimeChanged(int minutes);
@ -541,7 +543,6 @@ public:
void setShowIdenticons(bool value); void setShowIdenticons(bool value);
bool getAutoLogin() const; bool getAutoLogin() const;
void setAutoLogin(bool state);
void setEnableGroupChatsColor(bool state); void setEnableGroupChatsColor(bool state);
bool getEnableGroupChatsColor() const; bool getEnableGroupChatsColor() const;

103
src/widget/loginscreen.cpp

@ -32,7 +32,7 @@
#include <QMessageBox> #include <QMessageBox>
#include <QToolButton> #include <QToolButton>
LoginScreen::LoginScreen(QString initialProfile, QWidget* parent) LoginScreen::LoginScreen(const QString& initialProfileName, QWidget* parent)
: QDialog(parent) : QDialog(parent)
, ui(new Ui::LoginScreen) , ui(new Ui::LoginScreen)
, quitShortcut{QKeySequence(Qt::CTRL + Qt::Key_Q), this} , quitShortcut{QKeySequence(Qt::CTRL + Qt::Key_Q), this}
@ -56,10 +56,10 @@ LoginScreen::LoginScreen(QString initialProfile, QWidget* parent)
connect(ui->loginPassword, &QLineEdit::returnPressed, this, &LoginScreen::onLogin); connect(ui->loginPassword, &QLineEdit::returnPressed, this, &LoginScreen::onLogin);
connect(ui->newPass, &QLineEdit::textChanged, this, &LoginScreen::onPasswordEdited); connect(ui->newPass, &QLineEdit::textChanged, this, &LoginScreen::onPasswordEdited);
connect(ui->newPassConfirm, &QLineEdit::textChanged, this, &LoginScreen::onPasswordEdited); connect(ui->newPassConfirm, &QLineEdit::textChanged, this, &LoginScreen::onPasswordEdited);
connect(ui->autoLoginCB, &QCheckBox::stateChanged, this, &LoginScreen::onAutoLoginToggled); connect(ui->autoLoginCB, &QCheckBox::stateChanged, this, &LoginScreen::onAutoLoginCheckboxChanged);
connect(ui->importButton, &QPushButton::clicked, this, &LoginScreen::onImportProfile); connect(ui->importButton, &QPushButton::clicked, this, &LoginScreen::onImportProfile);
reset(initialProfile); reset(initialProfileName);
this->setStyleSheet(Style::getStylesheet("loginScreen/loginScreen.css")); this->setStyleSheet(Style::getStylesheet("loginScreen/loginScreen.css"));
retranslateUi(); retranslateUi();
@ -72,10 +72,19 @@ LoginScreen::~LoginScreen()
delete ui; delete ui;
} }
void LoginScreen::closeEvent(QCloseEvent* event)
{
// If we are in the bootstrap, returning -1 will give us something to exit with in main.cpp
this->setResult(-1);
// If we are in application exec, we can quit by closing it, instead.
qApp->quit();
}
/** /**
* @brief Resets the UI, clears all fields. * @brief Resets the UI, clears all fields.
*/ */
void LoginScreen::reset(QString initialProfile) void LoginScreen::reset(const QString& initialProfileName)
{ {
ui->newUsername->clear(); ui->newUsername->clear();
ui->newPass->clear(); ui->newPass->clear();
@ -83,34 +92,36 @@ void LoginScreen::reset(QString initialProfile)
ui->loginPassword->clear(); ui->loginPassword->clear();
ui->loginUsernames->clear(); ui->loginUsernames->clear();
Profile::scanProfiles(); QStringList allProfileNames = Profile::getAllProfileNames();
if (initialProfile.isEmpty()) {
initialProfile = Settings::getInstance().getCurrentProfile();
}
QStringList profiles = Profile::getProfiles();
for (QString profile : profiles) {
ui->loginUsernames->addItem(profile);
if (profile == initialProfile) {
ui->loginUsernames->setCurrentIndex(ui->loginUsernames->count() - 1);
}
}
if (profiles.isEmpty()) { if (allProfileNames.isEmpty()) {
ui->stackedWidget->setCurrentIndex(0); ui->stackedWidget->setCurrentIndex(0);
ui->newUsername->setFocus(); ui->newUsername->setFocus();
} else { } else {
for (const QString& profileName : allProfileNames) {
ui->loginUsernames->addItem(profileName);
}
ui->loginUsernames->setCurrentText(initialProfileName);
ui->stackedWidget->setCurrentIndex(1); ui->stackedWidget->setCurrentIndex(1);
ui->loginPassword->setFocus(); ui->loginPassword->setFocus();
} }
}
void LoginScreen::onProfileLoaded()
{
done(0);
}
ui->autoLoginCB->blockSignals(true); void LoginScreen::onProfileLoadFailed() {
ui->autoLoginCB->setChecked(Settings::getInstance().getAutoLogin()); QMessageBox::critical(this, tr("Couldn't load this profile"), tr("Wrong password."));
ui->autoLoginCB->blockSignals(false); ui->loginPassword->setFocus();
ui->loginPassword->selectAll();
} }
Profile *LoginScreen::getProfile() const void LoginScreen::onAutoLoginChanged(bool state)
{ {
return profile; ui->autoLoginCB->setChecked(state);
} }
bool LoginScreen::event(QEvent* event) bool LoginScreen::event(QEvent* event)
@ -129,11 +140,6 @@ bool LoginScreen::event(QEvent* event)
return QWidget::event(event); return QWidget::event(event);
} }
void LoginScreen::closeEvent(QCloseEvent*)
{
emit closed();
}
void LoginScreen::onNewProfilePageClicked() void LoginScreen::onNewProfilePageClicked()
{ {
ui->stackedWidget->setCurrentIndex(0); ui->stackedWidget->setCurrentIndex(0);
@ -174,16 +180,7 @@ void LoginScreen::onCreateNewProfile()
return; return;
} }
profile = Profile::createProfile(name, pass); emit createNewProfile(name, pass);
if (!profile) {
// Unknown error
QMessageBox::critical(this, tr("Couldn't create a new profile"),
tr("Unknown error: Couldn't create a new profile.\nIf you "
"encountered this error, please report it."));
done(-1);
return;
}
done(0);
} }
void LoginScreen::onLoginUsernameSelected(const QString& name) void LoginScreen::onLoginUsernameSelected(const QString& name)
@ -227,20 +224,7 @@ void LoginScreen::onLogin()
return; return;
} }
profile = Profile::loadProfile(name, pass); emit loadProfile(name, pass);
if (!profile) {
if (!ProfileLocker::isLockable(name)) {
QMessageBox::critical(this, tr("Couldn't load this profile"),
tr("Profile already in use. Close other clients."));
return;
} else {
QMessageBox::critical(this, tr("Couldn't load this profile"), tr("Wrong password."));
ui->loginPassword->setFocus();
ui->loginPassword->selectAll();
return;
}
}
done(0);
} }
void LoginScreen::onPasswordEdited() void LoginScreen::onPasswordEdited()
@ -248,15 +232,10 @@ void LoginScreen::onPasswordEdited()
ui->passStrengthMeter->setValue(SetPasswordDialog::getPasswordStrength(ui->newPass->text())); ui->passStrengthMeter->setValue(SetPasswordDialog::getPasswordStrength(ui->newPass->text()));
} }
void LoginScreen::onAutoLoginToggled(int state) void LoginScreen::onAutoLoginCheckboxChanged(int state)
{ {
Qt::CheckState cstate = static_cast<Qt::CheckState>(state); auto cstate = static_cast<Qt::CheckState>(state);
if (cstate == Qt::CheckState::Unchecked) emit autoLoginChanged(cstate == Qt::CheckState::Checked);
Settings::getInstance().setAutoLogin(false);
else
Settings::getInstance().setAutoLogin(true);
Settings::getInstance().saveGlobal();
} }
void LoginScreen::retranslateUi() void LoginScreen::retranslateUi()
@ -266,10 +245,8 @@ void LoginScreen::retranslateUi()
void LoginScreen::onImportProfile() void LoginScreen::onImportProfile()
{ {
ProfileImporter* pi = new ProfileImporter(this); ProfileImporter pi(this);
if (pi.importProfile()) {
if (pi->importProfile())
reset(); reset();
}
delete pi;
} }

19
src/widget/loginscreen.h

@ -36,22 +36,27 @@ class LoginScreen : public QDialog
Q_OBJECT Q_OBJECT
public: public:
LoginScreen(QString selectedProfile = QString(), QWidget* parent = nullptr); LoginScreen(const QString& initialProfileName = QString(), QWidget* parent = nullptr);
~LoginScreen(); ~LoginScreen();
void reset(QString selectedProfile = QString());
Profile* getProfile() const;
bool event(QEvent* event) final override; bool event(QEvent* event) final override;
signals: signals:
void windowStateChanged(Qt::WindowStates states); void windowStateChanged(Qt::WindowStates states);
void closed(); void autoLoginChanged(bool state);
void createNewProfile(QString name, const QString& pass);
void loadProfile(QString name, const QString& pass);
protected: protected:
virtual void closeEvent(QCloseEvent* event) final override; virtual void closeEvent(QCloseEvent* event) final override;
public slots:
void onProfileLoaded();
void onProfileLoadFailed();
void onAutoLoginChanged(bool state);
private slots: private slots:
void onAutoLoginToggled(int state); void onAutoLoginCheckboxChanged(int state);
void onLoginUsernameSelected(const QString& name); void onLoginUsernameSelected(const QString& name);
void onPasswordEdited(); void onPasswordEdited();
// Buttons to change page // Buttons to change page
@ -63,6 +68,7 @@ private slots:
void onImportProfile(); void onImportProfile();
private: private:
void reset(const QString& initialProfileName = QString());
void retranslateUi(); void retranslateUi();
void showCapsIndicator(); void showCapsIndicator();
void hideCapsIndicator(); void hideCapsIndicator();
@ -71,7 +77,6 @@ private:
private: private:
Ui::LoginScreen* ui; Ui::LoginScreen* ui;
QShortcut quitShortcut; QShortcut quitShortcut;
Profile* profile{nullptr};
}; };
#endif // LOGINSCREEN_H #endif // LOGINSCREEN_H

Loading…
Cancel
Save