mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
Merge pull request #414 from dubslow/profiles
Profiles -- they actually work!!!!!!!
This commit is contained in:
commit
259a1d042b
132
src/core.cpp
132
src/core.cpp
|
@ -39,11 +39,12 @@
|
||||||
#include <QMessageBox>
|
#include <QMessageBox>
|
||||||
|
|
||||||
const QString Core::CONFIG_FILE_NAME = "data";
|
const QString Core::CONFIG_FILE_NAME = "data";
|
||||||
|
const QString Core::TOX_EXT = ".tox";
|
||||||
QList<ToxFile> Core::fileSendQueue;
|
QList<ToxFile> Core::fileSendQueue;
|
||||||
QList<ToxFile> Core::fileRecvQueue;
|
QList<ToxFile> Core::fileRecvQueue;
|
||||||
|
|
||||||
Core::Core(Camera* cam, QThread *coreThread) :
|
Core::Core(Camera* cam, QThread *coreThread, QString loadPath) :
|
||||||
tox(nullptr), camera(cam)
|
tox(nullptr), camera(cam), loadPath(loadPath)
|
||||||
{
|
{
|
||||||
videobuf = new uint8_t[videobufsize];
|
videobuf = new uint8_t[videobufsize];
|
||||||
videoBusyness=0;
|
videoBusyness=0;
|
||||||
|
@ -117,12 +118,11 @@ Core* Core::getInstance()
|
||||||
return Widget::getInstance()->getCore();
|
return Widget::getInstance()->getCore();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::start()
|
void Core::make_tox()
|
||||||
{
|
{
|
||||||
// IPv6 needed for LAN discovery, but can crash some weird routers. On by default, can be disabled in options.
|
// IPv6 needed for LAN discovery, but can crash some weird routers. On by default, can be disabled in options.
|
||||||
bool enableIPv6 = Settings::getInstance().getEnableIPv6();
|
bool enableIPv6 = Settings::getInstance().getEnableIPv6();
|
||||||
bool forceTCP = Settings::getInstance().getForceTCP();
|
bool forceTCP = Settings::getInstance().getForceTCP();
|
||||||
|
|
||||||
bool useProxy = Settings::getInstance().getUseProxy();
|
bool useProxy = Settings::getInstance().getUseProxy();
|
||||||
|
|
||||||
if (enableIPv6)
|
if (enableIPv6)
|
||||||
|
@ -181,7 +181,7 @@ void Core::start()
|
||||||
emit failedToStart();
|
emit failedToStart();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
qWarning() << "Core failed to start with IPv6, falling back to IPv4. LAN discovery may not work properly.";
|
qWarning() << "Core failed to start with IPv6, falling back to IPv4. LAN discovery may not work properly.";
|
||||||
}
|
}
|
||||||
|
@ -205,15 +205,24 @@ void Core::start()
|
||||||
emit failedToStart();
|
emit failedToStart();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::start()
|
||||||
|
{
|
||||||
|
make_tox();
|
||||||
|
|
||||||
qsrand(time(nullptr));
|
qsrand(time(nullptr));
|
||||||
|
|
||||||
if (!loadConfiguration())
|
if (loadPath != "")
|
||||||
{
|
{
|
||||||
emit failedToStart();
|
if (!loadConfiguration(loadPath)) // loadPath is meaningless after this
|
||||||
tox_kill(tox);
|
{
|
||||||
tox = nullptr;
|
emit failedToStart();
|
||||||
return;
|
tox_kill(tox);
|
||||||
|
tox = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
loadPath = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
tox_callback_friend_request(tox, onFriendRequest, this);
|
tox_callback_friend_request(tox, onFriendRequest, this);
|
||||||
|
@ -273,9 +282,9 @@ void Core::start()
|
||||||
* 5 disconnected; 4 were DCd for less than 20 ticks, while the 5th was ~50 ticks.
|
* 5 disconnected; 4 were DCd for less than 20 ticks, while the 5th was ~50 ticks.
|
||||||
* So I set the tolerance here at 25, and initial DCs should be very rare now.
|
* So I set the tolerance here at 25, and initial DCs should be very rare now.
|
||||||
* This should be able to go to 50 or 100 without affecting legitimate disconnects'
|
* This should be able to go to 50 or 100 without affecting legitimate disconnects'
|
||||||
* downtime, but lets be conservative for now. Edit: now 40.
|
* downtime, but lets be conservative for now. Edit: now ~~40~~ 30.
|
||||||
*/
|
*/
|
||||||
#define CORE_DISCONNECT_TOLERANCE 40
|
#define CORE_DISCONNECT_TOLERANCE 30
|
||||||
|
|
||||||
void Core::process()
|
void Core::process()
|
||||||
{
|
{
|
||||||
|
@ -627,8 +636,8 @@ void Core::onAvatarInfoCallback(Tox*, int32_t friendnumber, uint8_t format,
|
||||||
{
|
{
|
||||||
qDebug() << "Core: Got null avatar info from" << core->getFriendUsername(friendnumber);
|
qDebug() << "Core: Got null avatar info from" << core->getFriendUsername(friendnumber);
|
||||||
emit core->friendAvatarRemoved(friendnumber);
|
emit core->friendAvatarRemoved(friendnumber);
|
||||||
QFile::remove(QDir(Settings::getInstance().getSettingsDirPath()).filePath("avatars/"+core->getFriendAddress(friendnumber).left(64)+".png"));
|
QFile::remove(QDir(Settings::getSettingsDirPath()).filePath("avatars/"+core->getFriendAddress(friendnumber).left(64)+".png"));
|
||||||
QFile::remove(QDir(Settings::getInstance().getSettingsDirPath()).filePath("avatars/"+core->getFriendAddress(friendnumber).left(64)+".hash"));
|
QFile::remove(QDir(Settings::getSettingsDirPath()).filePath("avatars/"+core->getFriendAddress(friendnumber).left(64)+".hash"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -918,6 +927,8 @@ void Core::acceptFileRecvRequest(int friendId, int fileNum, QString path)
|
||||||
|
|
||||||
void Core::removeFriend(int friendId)
|
void Core::removeFriend(int friendId)
|
||||||
{
|
{
|
||||||
|
if (!tox)
|
||||||
|
return;
|
||||||
if (tox_del_friend(tox, friendId) == -1) {
|
if (tox_del_friend(tox, friendId) == -1) {
|
||||||
emit failedToRemoveFriend(friendId);
|
emit failedToRemoveFriend(friendId);
|
||||||
} else {
|
} else {
|
||||||
|
@ -928,6 +939,8 @@ void Core::removeFriend(int friendId)
|
||||||
|
|
||||||
void Core::removeGroup(int groupId)
|
void Core::removeGroup(int groupId)
|
||||||
{
|
{
|
||||||
|
if (!tox)
|
||||||
|
return;
|
||||||
tox_del_groupchat(tox, groupId);
|
tox_del_groupchat(tox, groupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -949,8 +962,8 @@ void Core::setUsername(const QString& username)
|
||||||
if (tox_set_name(tox, cUsername.data(), cUsername.size()) == -1) {
|
if (tox_set_name(tox, cUsername.data(), cUsername.size()) == -1) {
|
||||||
emit failedToSetUsername(username);
|
emit failedToSetUsername(username);
|
||||||
} else {
|
} else {
|
||||||
saveConfiguration();
|
|
||||||
emit usernameSet(username);
|
emit usernameSet(username);
|
||||||
|
saveConfiguration();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -981,6 +994,13 @@ ToxID Core::getSelfId()
|
||||||
return ToxID::fromString(CFriendAddress::toString(friendAddress));
|
return ToxID::fromString(CFriendAddress::toString(friendAddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Core::getIDString()
|
||||||
|
{
|
||||||
|
return getSelfId().toString().left(12);
|
||||||
|
// 12 is the smallest multiple of four such that
|
||||||
|
// 16^n > 10^10 (which is roughly the planet's population)
|
||||||
|
}
|
||||||
|
|
||||||
QString Core::getStatusMessage()
|
QString Core::getStatusMessage()
|
||||||
{
|
{
|
||||||
int size = tox_get_self_status_message_size(tox);
|
int size = tox_get_self_status_message_size(tox);
|
||||||
|
@ -1038,11 +1058,25 @@ void Core::onFileTransferFinished(ToxFile file)
|
||||||
emit fileDownloadFinished(file.filePath);
|
emit fileDownloadFinished(file.filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Core::loadConfiguration()
|
QString Core::sanitize(QString name)
|
||||||
{
|
{
|
||||||
QString path = QDir(Settings::getSettingsDirPath()).filePath(CONFIG_FILE_NAME);
|
// these are pretty much Windows banned filename characters
|
||||||
|
QList<QChar> banned = {'/', '\\', ':', '<', '>', '"', '|', '?', '*'};
|
||||||
|
for (QChar c : banned)
|
||||||
|
name.replace(c, '_');
|
||||||
|
// also remove leading and trailing periods
|
||||||
|
if (name[0] == '.')
|
||||||
|
name[0] = '_';
|
||||||
|
if (name.endsWith('.'))
|
||||||
|
name[name.length()-1] = '_';
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Core::loadConfiguration(QString path)
|
||||||
|
{
|
||||||
|
// setting the profile is now the responsibility of the caller
|
||||||
QFile configurationFile(path);
|
QFile configurationFile(path);
|
||||||
|
qDebug() << "Core::loadConfiguration: reading from " << path;
|
||||||
|
|
||||||
if (!configurationFile.exists()) {
|
if (!configurationFile.exists()) {
|
||||||
qWarning() << "The Tox configuration file was not found";
|
qWarning() << "The Tox configuration file was not found";
|
||||||
|
@ -1093,32 +1127,51 @@ bool Core::loadConfiguration()
|
||||||
|
|
||||||
void Core::saveConfiguration()
|
void Core::saveConfiguration()
|
||||||
{
|
{
|
||||||
Settings::getInstance().save();
|
QString dir = Settings::getSettingsDirPath();
|
||||||
|
QDir directory(dir);
|
||||||
|
if (!directory.exists() && !directory.mkpath(directory.absolutePath())) {
|
||||||
|
qCritical() << "Error while creating directory " << dir;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString profile = Settings::getInstance().getCurrentProfile();
|
||||||
|
//qDebug() << "saveConf read profile: " << profile;
|
||||||
|
if (profile == "")
|
||||||
|
{ // no profile active; this should only happen on startup, if at all
|
||||||
|
profile = sanitize(getUsername());
|
||||||
|
if (profile == "") // happens on creation of a new Tox ID
|
||||||
|
profile = getIDString();
|
||||||
|
//qDebug() << "saveConf: read sanitized user as " << profile;
|
||||||
|
Settings::getInstance().setCurrentProfile(profile);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString path = dir + QDir::separator() + profile + TOX_EXT;
|
||||||
|
QFileInfo info(path);
|
||||||
|
// if (!info.exists()) // fall back to old school 'data'
|
||||||
|
// { //path = dir + QDir::separator() + CONFIG_FILE_NAME;
|
||||||
|
// qDebug() << "Core:" << path << " does not exist";
|
||||||
|
// }
|
||||||
|
|
||||||
|
saveConfiguration(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::saveConfiguration(const QString& path)
|
||||||
|
{
|
||||||
if (!tox)
|
if (!tox)
|
||||||
{
|
{
|
||||||
qWarning() << "Core::saveConfiguration: Tox not started, aborting!";
|
qWarning() << "Core::saveConfiguration: Tox not started, aborting!";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString path = Settings::getSettingsDirPath();
|
Settings::getInstance().save();
|
||||||
|
|
||||||
QDir directory(path);
|
|
||||||
|
|
||||||
if (!directory.exists() && !directory.mkpath(directory.absolutePath())) {
|
|
||||||
qCritical() << "Error while creating directory " << path;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
path = directory.filePath(CONFIG_FILE_NAME);
|
|
||||||
QSaveFile configurationFile(path);
|
QSaveFile configurationFile(path);
|
||||||
if (!configurationFile.open(QIODevice::WriteOnly)) {
|
if (!configurationFile.open(QIODevice::WriteOnly)) {
|
||||||
qCritical() << "File " << path << " cannot be opened";
|
qCritical() << "File " << path << " cannot be opened";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Core: Saving";
|
qDebug() << "Core: writing tox_save to " << path;
|
||||||
|
|
||||||
uint32_t fileSize = tox_size(tox);
|
uint32_t fileSize = tox_size(tox);
|
||||||
if (fileSize > 0 && fileSize <= INT32_MAX) {
|
if (fileSize > 0 && fileSize <= INT32_MAX) {
|
||||||
uint8_t *data = new uint8_t[fileSize];
|
uint8_t *data = new uint8_t[fileSize];
|
||||||
|
@ -1129,6 +1182,27 @@ void Core::saveConfiguration()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Core::switchConfiguration(QString profile)
|
||||||
|
{
|
||||||
|
saveConfiguration();
|
||||||
|
|
||||||
|
toxTimer->stop();
|
||||||
|
|
||||||
|
if (tox) {
|
||||||
|
toxav_kill(toxav);
|
||||||
|
toxav = nullptr;
|
||||||
|
tox_kill(tox);
|
||||||
|
tox = nullptr;
|
||||||
|
}
|
||||||
|
emit selfAvatarChanged(QPixmap(":/img/contact_dark.png"));
|
||||||
|
Widget::getInstance()->clearContactsList(); // we need this to block, so no signals for us
|
||||||
|
|
||||||
|
loadPath = QDir(Settings::getSettingsDirPath()).filePath(profile + TOX_EXT);
|
||||||
|
Settings::getInstance().setCurrentProfile(profile);
|
||||||
|
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
void Core::loadFriends()
|
void Core::loadFriends()
|
||||||
{
|
{
|
||||||
const uint32_t friendCount = tox_count_friendlist(tox);
|
const uint32_t friendCount = tox_count_friendlist(tox);
|
||||||
|
|
17
src/core.h
17
src/core.h
|
@ -34,9 +34,13 @@ class Core : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit Core(Camera* cam, QThread* coreThread);
|
explicit Core(Camera* cam, QThread* coreThread, QString initialLoadPath);
|
||||||
static Core* getInstance(); ///< Returns the global widget's Core instance
|
static Core* getInstance(); ///< Returns the global widget's Core instance
|
||||||
~Core();
|
~Core();
|
||||||
|
|
||||||
|
static const QString TOX_EXT;
|
||||||
|
static const QString CONFIG_FILE_NAME;
|
||||||
|
static QString sanitize(QString name);
|
||||||
|
|
||||||
int getGroupNumberPeers(int groupId) const;
|
int getGroupNumberPeers(int groupId) const;
|
||||||
QString getGroupPeerName(int groupId, int peerId) const;
|
QString getGroupPeerName(int groupId, int peerId) const;
|
||||||
|
@ -48,6 +52,10 @@ public:
|
||||||
void dispatchVideoFrame(vpx_image img) const;
|
void dispatchVideoFrame(vpx_image img) const;
|
||||||
|
|
||||||
void saveConfiguration();
|
void saveConfiguration();
|
||||||
|
void saveConfiguration(const QString& path);
|
||||||
|
void switchConfiguration(QString profile);
|
||||||
|
|
||||||
|
QString getIDString();
|
||||||
|
|
||||||
QString getUsername();
|
QString getUsername();
|
||||||
QString getStatusMessage();
|
QString getStatusMessage();
|
||||||
|
@ -209,7 +217,8 @@ private:
|
||||||
|
|
||||||
bool checkConnection();
|
bool checkConnection();
|
||||||
|
|
||||||
bool loadConfiguration(); // Returns false for a critical error, true otherwise
|
bool loadConfiguration(QString path); // Returns false for a critical error, true otherwise
|
||||||
|
void make_tox();
|
||||||
void loadFriends();
|
void loadFriends();
|
||||||
|
|
||||||
static void sendAllFileData(Core* core, ToxFile* file);
|
static void sendAllFileData(Core* core, ToxFile* file);
|
||||||
|
@ -225,14 +234,14 @@ private slots:
|
||||||
private:
|
private:
|
||||||
Tox* tox;
|
Tox* tox;
|
||||||
ToxAv* toxav;
|
ToxAv* toxav;
|
||||||
QTimer *toxTimer, *fileTimer, *bootstrapTimer; //, *saveTimer;
|
QTimer *toxTimer, *fileTimer; //, *saveTimer;
|
||||||
Camera* camera;
|
Camera* camera;
|
||||||
|
QString loadPath; // meaningless after start() is called
|
||||||
QList<DhtServer> dhtServerList;
|
QList<DhtServer> dhtServerList;
|
||||||
int dhtServerId;
|
int dhtServerId;
|
||||||
static QList<ToxFile> fileSendQueue, fileRecvQueue;
|
static QList<ToxFile> fileSendQueue, fileRecvQueue;
|
||||||
static ToxCall calls[];
|
static ToxCall calls[];
|
||||||
|
|
||||||
static const QString CONFIG_FILE_NAME;
|
|
||||||
static const int videobufsize;
|
static const int videobufsize;
|
||||||
static uint8_t* videobuf;
|
static uint8_t* videobuf;
|
||||||
static int videoBusyness; // Used to know when to drop frames
|
static int videoBusyness; // Used to know when to drop frames
|
||||||
|
|
|
@ -115,6 +115,7 @@ void Settings::load()
|
||||||
useProxy = s.value("useProxy", false).toBool();
|
useProxy = s.value("useProxy", false).toBool();
|
||||||
proxyAddr = s.value("proxyAddr", "").toString();
|
proxyAddr = s.value("proxyAddr", "").toString();
|
||||||
proxyPort = s.value("proxyPort", 0).toInt();
|
proxyPort = s.value("proxyPort", 0).toInt();
|
||||||
|
currentProfile = s.value("currentProfile", "").toString();
|
||||||
s.endGroup();
|
s.endGroup();
|
||||||
|
|
||||||
s.beginGroup("Widgets");
|
s.beginGroup("Widgets");
|
||||||
|
@ -219,6 +220,7 @@ void Settings::save(QString path)
|
||||||
s.setValue("forceTCP", forceTCP);
|
s.setValue("forceTCP", forceTCP);
|
||||||
s.setValue("proxyAddr", proxyAddr);
|
s.setValue("proxyAddr", proxyAddr);
|
||||||
s.setValue("proxyPort", proxyPort);
|
s.setValue("proxyPort", proxyPort);
|
||||||
|
s.setValue("currentProfile", currentProfile);
|
||||||
s.endGroup();
|
s.endGroup();
|
||||||
|
|
||||||
s.beginGroup("Widgets");
|
s.beginGroup("Widgets");
|
||||||
|
@ -410,6 +412,16 @@ void Settings::setProxyPort(int newValue)
|
||||||
proxyPort = newValue;
|
proxyPort = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString Settings::getCurrentProfile() const
|
||||||
|
{
|
||||||
|
return currentProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Settings::setCurrentProfile(QString profile)
|
||||||
|
{
|
||||||
|
currentProfile = profile;
|
||||||
|
}
|
||||||
|
|
||||||
bool Settings::getEnableLogging() const
|
bool Settings::getEnableLogging() const
|
||||||
{
|
{
|
||||||
return enableLogging;
|
return enableLogging;
|
||||||
|
|
|
@ -52,6 +52,9 @@ public:
|
||||||
bool getAutostartInTray() const;
|
bool getAutostartInTray() const;
|
||||||
void setAutostartInTray(bool newValue);
|
void setAutostartInTray(bool newValue);
|
||||||
|
|
||||||
|
QString getCurrentProfile() const;
|
||||||
|
void setCurrentProfile(QString profile);
|
||||||
|
|
||||||
bool getUseTranslations() const;
|
bool getUseTranslations() const;
|
||||||
void setUseTranslations(bool newValue);
|
void setUseTranslations(bool newValue);
|
||||||
|
|
||||||
|
@ -176,6 +179,8 @@ private:
|
||||||
QString proxyAddr;
|
QString proxyAddr;
|
||||||
int proxyPort;
|
int proxyPort;
|
||||||
|
|
||||||
|
QString currentProfile;
|
||||||
|
|
||||||
bool enableLogging;
|
bool enableLogging;
|
||||||
bool encryptLogs;
|
bool encryptLogs;
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,16 @@
|
||||||
#include "ui_identitysettings.h"
|
#include "ui_identitysettings.h"
|
||||||
#include "identityform.h"
|
#include "identityform.h"
|
||||||
#include "src/widget/form/settingswidget.h"
|
#include "src/widget/form/settingswidget.h"
|
||||||
|
#include "src/misc/settings.h"
|
||||||
#include "src/widget/croppinglabel.h"
|
#include "src/widget/croppinglabel.h"
|
||||||
|
#include "src/widget/widget.h"
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
|
#include <QInputDialog>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
IdentityForm::IdentityForm() :
|
IdentityForm::IdentityForm() :
|
||||||
GenericForm(tr("Your identity"), QPixmap(":/img/settings/identity.png"))
|
GenericForm(tr("Your identity"), QPixmap(":/img/settings/identity.png"))
|
||||||
|
@ -38,7 +43,7 @@ IdentityForm::IdentityForm() :
|
||||||
|
|
||||||
// toxId->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
// toxId->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||||
toxId->setReadOnly(true);
|
toxId->setReadOnly(true);
|
||||||
// toxId->setFrameStyle(QFrame::NoFrame);
|
toxId->setFrame(false);
|
||||||
// toxId->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
// toxId->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||||
// toxId->setFixedHeight(toxId->document()->size().height()*2);
|
// toxId->setFixedHeight(toxId->document()->size().height()*2);
|
||||||
toxId->setFont(small);
|
toxId->setFont(small);
|
||||||
|
@ -49,6 +54,11 @@ IdentityForm::IdentityForm() :
|
||||||
connect(toxId, SIGNAL(clicked()), this, SLOT(copyIdClicked()));
|
connect(toxId, SIGNAL(clicked()), this, SLOT(copyIdClicked()));
|
||||||
connect(bodyUI->userName, SIGNAL(editingFinished()), this, SLOT(onUserNameEdited()));
|
connect(bodyUI->userName, SIGNAL(editingFinished()), this, SLOT(onUserNameEdited()));
|
||||||
connect(bodyUI->statusMessage, SIGNAL(editingFinished()), this, SLOT(onStatusMessageEdited()));
|
connect(bodyUI->statusMessage, SIGNAL(editingFinished()), this, SLOT(onStatusMessageEdited()));
|
||||||
|
connect(bodyUI->loadButton, &QPushButton::clicked, this, &IdentityForm::onLoadClicked);
|
||||||
|
connect(bodyUI->renameButton, &QPushButton::clicked, this, &IdentityForm::onRenameClicked);
|
||||||
|
connect(bodyUI->exportButton, &QPushButton::clicked, this, &IdentityForm::onExportClicked);
|
||||||
|
connect(bodyUI->deleteButton, &QPushButton::clicked, this, &IdentityForm::onDeleteClicked);
|
||||||
|
connect(bodyUI->importButton, &QPushButton::clicked, this, &IdentityForm::onImportClicked);
|
||||||
}
|
}
|
||||||
|
|
||||||
IdentityForm::~IdentityForm()
|
IdentityForm::~IdentityForm()
|
||||||
|
@ -61,6 +71,7 @@ void IdentityForm::copyIdClicked()
|
||||||
QString txt = toxId->text();
|
QString txt = toxId->text();
|
||||||
txt.replace('\n',"");
|
txt.replace('\n',"");
|
||||||
QApplication::clipboard()->setText(txt);
|
QApplication::clipboard()->setText(txt);
|
||||||
|
toxId->setCursorPosition(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IdentityForm::onUserNameEdited()
|
void IdentityForm::onUserNameEdited()
|
||||||
|
@ -76,6 +87,13 @@ void IdentityForm::onStatusMessageEdited()
|
||||||
void IdentityForm::present()
|
void IdentityForm::present()
|
||||||
{
|
{
|
||||||
toxId->setText(Core::getInstance()->getSelfId().toString());
|
toxId->setText(Core::getInstance()->getSelfId().toString());
|
||||||
|
toxId->setCursorPosition(0);
|
||||||
|
bodyUI->profiles->clear();
|
||||||
|
for (QString profile : Widget::searchProfiles())
|
||||||
|
bodyUI->profiles->addItem(profile);
|
||||||
|
QString current = Settings::getInstance().getCurrentProfile();
|
||||||
|
if (current != "")
|
||||||
|
bodyUI->profiles->setCurrentText(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IdentityForm::setUserName(const QString &name)
|
void IdentityForm::setUserName(const QString &name)
|
||||||
|
@ -87,3 +105,62 @@ void IdentityForm::setStatusMessage(const QString &msg)
|
||||||
{
|
{
|
||||||
bodyUI->statusMessage->setText(msg);
|
bodyUI->statusMessage->setText(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IdentityForm::onLoadClicked()
|
||||||
|
{
|
||||||
|
Core::getInstance()->switchConfiguration(bodyUI->profiles->currentText());
|
||||||
|
}
|
||||||
|
|
||||||
|
void IdentityForm::onRenameClicked()
|
||||||
|
{
|
||||||
|
QString cur = bodyUI->profiles->currentText();
|
||||||
|
QString title = tr("Rename \"%1\"", "renaming a profile").arg(cur);
|
||||||
|
QString name = QInputDialog::getText(this, title, title+":");
|
||||||
|
if (name != "")
|
||||||
|
{
|
||||||
|
name = Core::sanitize(name);
|
||||||
|
QDir dir(Settings::getSettingsDirPath());
|
||||||
|
QFile::rename(dir.filePath(cur+Core::TOX_EXT), dir.filePath(name+Core::TOX_EXT));
|
||||||
|
bodyUI->profiles->setItemText(bodyUI->profiles->currentIndex(), name);
|
||||||
|
Settings::getInstance().setCurrentProfile(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IdentityForm::onExportClicked()
|
||||||
|
{
|
||||||
|
QString current = bodyUI->profiles->currentText() + Core::TOX_EXT;
|
||||||
|
QString path = QFileDialog::getSaveFileName(this, tr("Export profile", "save dialog title"),
|
||||||
|
QDir::home().filePath(current),
|
||||||
|
tr("Tox save file (*.tox)", "save dialog filter"));
|
||||||
|
QFile::copy(QDir(Settings::getSettingsDirPath()).filePath(current), path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IdentityForm::onDeleteClicked()
|
||||||
|
{
|
||||||
|
if (Settings::getInstance().getCurrentProfile() == bodyUI->profiles->currentText())
|
||||||
|
{
|
||||||
|
QMessageBox::warning(this, tr("Profile currently loaded","current profile deletion warning title"), tr("This profile is currently in use. Please load a different profile before deleting this one.","current profile deletion warning text"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QMessageBox::StandardButton resp = QMessageBox::question(this,
|
||||||
|
tr("Deletion imminent!","deletion confirmation title"), tr("Are you sure you want to delete this profile?","deletion confirmation text"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
|
||||||
|
if (resp == QMessageBox::Yes)
|
||||||
|
{
|
||||||
|
QFile::remove(QDir(Settings::getSettingsDirPath()).filePath(bodyUI->profiles->currentText()+Core::TOX_EXT));
|
||||||
|
bodyUI->profiles->removeItem(bodyUI->profiles->currentIndex());
|
||||||
|
bodyUI->profiles->setCurrentText(Settings::getInstance().getCurrentProfile());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IdentityForm::onImportClicked()
|
||||||
|
{
|
||||||
|
QString path = QFileDialog::getOpenFileName(this, tr("Import profile", "import dialog title"), QDir::homePath(), tr("Tox save file (*.tox)", "import dialog filter"));
|
||||||
|
QFileInfo info(path);
|
||||||
|
QString profile = info.completeBaseName();
|
||||||
|
QString profilePath = QDir(Settings::getSettingsDirPath()).filePath(profile + Core::TOX_EXT);
|
||||||
|
QFile::copy(path, profilePath);
|
||||||
|
bodyUI->profiles->addItem(profile);
|
||||||
|
Core::getInstance()->switchConfiguration(profile);
|
||||||
|
}
|
||||||
|
|
|
@ -60,6 +60,11 @@ private slots:
|
||||||
void copyIdClicked();
|
void copyIdClicked();
|
||||||
void onUserNameEdited();
|
void onUserNameEdited();
|
||||||
void onStatusMessageEdited();
|
void onStatusMessageEdited();
|
||||||
|
void onLoadClicked();
|
||||||
|
void onRenameClicked();
|
||||||
|
void onExportClicked();
|
||||||
|
void onDeleteClicked();
|
||||||
|
void onImportClicked();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::IdentitySettings* bodyUI;
|
Ui::IdentitySettings* bodyUI;
|
||||||
|
|
|
@ -59,6 +59,71 @@
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="profilesGroup">
|
||||||
|
<property name="title">
|
||||||
|
<string>Profiles</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="profilesVLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="profilesComboLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="profilesLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Available profiles:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="profiles" />
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="profilesButtonsLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="loadButton">
|
||||||
|
<property name="text">
|
||||||
|
<string comment="load profile button">Load</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="renameButton">
|
||||||
|
<property name="text">
|
||||||
|
<string comment="rename profile button">Rename</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="exportButton">
|
||||||
|
<property name="text">
|
||||||
|
<string comment="export profile button">Export</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="deleteButton">
|
||||||
|
<property name="text">
|
||||||
|
<string comment="delete profile button">Delete</string>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string comment="delete profile button tooltip">This is useful to remain safe on public computers</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="importButton">
|
||||||
|
<property name="text">
|
||||||
|
<string comment="import profile button">Import a profile</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="verticalSpacer">
|
<spacer name="verticalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
#include <QClipboard>
|
#include <QClipboard>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
#include <QInputDialog>
|
||||||
#include <tox/tox.h>
|
#include <tox/tox.h>
|
||||||
|
|
||||||
Widget *Widget::instance{nullptr};
|
Widget *Widget::instance{nullptr};
|
||||||
|
@ -116,8 +117,9 @@ Widget::Widget(QWidget *parent)
|
||||||
qRegisterMetaType<ToxFile>("ToxFile");
|
qRegisterMetaType<ToxFile>("ToxFile");
|
||||||
qRegisterMetaType<ToxFile::FileDirection>("ToxFile::FileDirection");
|
qRegisterMetaType<ToxFile::FileDirection>("ToxFile::FileDirection");
|
||||||
|
|
||||||
|
QString profilePath = detectProfile();
|
||||||
coreThread = new QThread(this);
|
coreThread = new QThread(this);
|
||||||
core = new Core(Camera::getInstance(), coreThread);
|
core = new Core(Camera::getInstance(), coreThread, profilePath);
|
||||||
core->moveToThread(coreThread);
|
core->moveToThread(coreThread);
|
||||||
connect(coreThread, &QThread::started, core, &Core::start);
|
connect(coreThread, &QThread::started, core, &Core::start);
|
||||||
|
|
||||||
|
@ -211,6 +213,69 @@ void Widget::closeEvent(QCloseEvent *event)
|
||||||
QWidget::closeEvent(event);
|
QWidget::closeEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 == "" || !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 != "")
|
||||||
|
return dir.filePath(profile + Core::TOX_EXT);
|
||||||
|
else
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QString> Widget::searchProfiles()
|
||||||
|
{
|
||||||
|
QList<QString> 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<QString> 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
|
||||||
|
{
|
||||||
|
qApp->quit();
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return profile;
|
||||||
|
}
|
||||||
|
|
||||||
QString Widget::getUsername()
|
QString Widget::getUsername()
|
||||||
{
|
{
|
||||||
return core->getUsername();
|
return core->getUsername();
|
||||||
|
@ -565,19 +630,31 @@ void Widget::onFriendRequestReceived(const QString& userId, const QString& messa
|
||||||
emit friendRequestAccepted(userId);
|
emit friendRequestAccepted(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::removeFriend(int friendId)
|
void Widget::removeFriend(Friend* f)
|
||||||
{
|
{
|
||||||
Friend* f = FriendList::findFriend(friendId);
|
|
||||||
f->widget->setAsInactiveChatroom();
|
f->widget->setAsInactiveChatroom();
|
||||||
if (static_cast<GenericChatroomWidget*>(f->widget) == activeChatroomWidget)
|
if (static_cast<GenericChatroomWidget*>(f->widget) == activeChatroomWidget)
|
||||||
activeChatroomWidget = nullptr;
|
activeChatroomWidget = nullptr;
|
||||||
FriendList::removeFriend(friendId);
|
FriendList::removeFriend(f->friendId);
|
||||||
core->removeFriend(friendId);
|
core->removeFriend(f->friendId);
|
||||||
delete f;
|
delete f;
|
||||||
if (ui->mainHead->layout()->isEmpty())
|
if (ui->mainHead->layout()->isEmpty())
|
||||||
onAddClicked();
|
onAddClicked();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Widget::removeFriend(int friendId)
|
||||||
|
{
|
||||||
|
removeFriend(FriendList::findFriend(friendId));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Widget::clearContactsList()
|
||||||
|
{
|
||||||
|
for (Friend* f : FriendList::friendList)
|
||||||
|
removeFriend(f);
|
||||||
|
for (Group* g : GroupList::groupList)
|
||||||
|
removeGroup(g);
|
||||||
|
}
|
||||||
|
|
||||||
void Widget::copyFriendIdToClipboard(int friendId)
|
void Widget::copyFriendIdToClipboard(int friendId)
|
||||||
{
|
{
|
||||||
Friend* f = FriendList::findFriend(friendId);
|
Friend* f = FriendList::findFriend(friendId);
|
||||||
|
@ -641,19 +718,23 @@ void Widget::onGroupNamelistChanged(int groupnumber, int peernumber, uint8_t Cha
|
||||||
g->updatePeer(peernumber,core->getGroupPeerName(groupnumber, peernumber));
|
g->updatePeer(peernumber,core->getGroupPeerName(groupnumber, peernumber));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::removeGroup(int groupId)
|
void Widget::removeGroup(Group* g)
|
||||||
{
|
{
|
||||||
Group* g = GroupList::findGroup(groupId);
|
|
||||||
g->widget->setAsInactiveChatroom();
|
g->widget->setAsInactiveChatroom();
|
||||||
if (static_cast<GenericChatroomWidget*>(g->widget) == activeChatroomWidget)
|
if (static_cast<GenericChatroomWidget*>(g->widget) == activeChatroomWidget)
|
||||||
activeChatroomWidget = nullptr;
|
activeChatroomWidget = nullptr;
|
||||||
GroupList::removeGroup(groupId);
|
GroupList::removeGroup(g->groupId);
|
||||||
core->removeGroup(groupId);
|
core->removeGroup(g->groupId);
|
||||||
delete g;
|
delete g;
|
||||||
if (ui->mainHead->layout()->isEmpty())
|
if (ui->mainHead->layout()->isEmpty())
|
||||||
onAddClicked();
|
onAddClicked();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Widget::removeGroup(int groupId)
|
||||||
|
{
|
||||||
|
removeGroup(GroupList::findGroup(groupId));
|
||||||
|
}
|
||||||
|
|
||||||
Core *Widget::getCore()
|
Core *Widget::getCore()
|
||||||
{
|
{
|
||||||
return core;
|
return core;
|
||||||
|
|
|
@ -56,6 +56,8 @@ public:
|
||||||
void newMessageAlert();
|
void newMessageAlert();
|
||||||
bool isFriendWidgetCurActiveWidget(Friend* f);
|
bool isFriendWidgetCurActiveWidget(Friend* f);
|
||||||
bool getIsWindowMinimized();
|
bool getIsWindowMinimized();
|
||||||
|
static QList<QString> searchProfiles();
|
||||||
|
void clearContactsList();
|
||||||
~Widget();
|
~Widget();
|
||||||
|
|
||||||
virtual void closeEvent(QCloseEvent *event);
|
virtual void closeEvent(QCloseEvent *event);
|
||||||
|
@ -111,8 +113,11 @@ private:
|
||||||
void hideMainForms();
|
void hideMainForms();
|
||||||
virtual bool event(QEvent * e);
|
virtual bool event(QEvent * e);
|
||||||
Group* createGroup(int groupId);
|
Group* createGroup(int groupId);
|
||||||
|
void removeFriend(Friend* f);
|
||||||
|
void removeGroup(Group* g);
|
||||||
|
QString askProfiles();
|
||||||
|
QString detectProfile();
|
||||||
|
|
||||||
private:
|
|
||||||
Ui::MainWindow *ui;
|
Ui::MainWindow *ui;
|
||||||
QSplitter *centralLayout;
|
QSplitter *centralLayout;
|
||||||
QPoint dragPosition;
|
QPoint dragPosition;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user