mirror of
https://github.com/qTox/qTox.git
synced 2024-03-22 14:00:36 +08:00
commit
753edf3c6f
|
@ -10,7 +10,7 @@ INSTALL_DIR=libs
|
|||
# just for convenience
|
||||
BASE_DIR=${SCRIPT_DIR}/${INSTALL_DIR}
|
||||
|
||||
SODIUM_VER=0.7.0
|
||||
SODIUM_VER=1.0.0
|
||||
|
||||
# directory names of cloned repositories
|
||||
SODIUM_DIR=libsodium-$SODIUM_VER
|
||||
|
|
4
debian/control
vendored
4
debian/control
vendored
|
@ -3,11 +3,11 @@ Maintainer: John Smith <barrdetwix@gmail.com>
|
|||
Section: misc
|
||||
Priority: optional
|
||||
Standards-Version: 3.9.5
|
||||
Build-Depends: debhelper (>= 9), cdbs, qt5-qmake, libopenal-dev (>= 1:1.15.1), libopencv-dev (>= 2.4.8), libopus-dev (>= 1.0), qtbase5-dev (>= 5.2), sudo, autoconf, libtool, pkg-config, libvpx-dev
|
||||
Build-Depends: debhelper (>= 9), cdbs, qt5-qmake, libopenal-dev (>= 1:1.14), libopencv-dev (>= 2.3), libopus-dev (>= 0.9), qtbase5-dev (>= 5.2), sudo, autoconf, libtool, pkg-config, libvpx-dev
|
||||
|
||||
Package: qtox
|
||||
Architecture: any
|
||||
Depends: libc6 (>= 2.17), libgcc1 (>= 1:4.1.1), libgl1-mesa-glx | libgl1, libopenal1 (>= 1.14), libopencv-core2.4, libopencv-highgui2.4, libopus0 (>= 1.0), libqt5core5a (>= 5.2), libqt5gui5 (>= 5.2), libqt5network5 (>= 5.0), libqt5widgets5 (>= 5.2), libqt5xml5 (>= 5.0), libstdc++6 (>= 4.9), libvpx1 (>= 1.0.0)
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}, libgcc1 (>= 1:4.1.1), libgl1-mesa-glx | libgl1, libopenal1 (>= 1.14), libopus0 (>= 0.9), libqt5core5a (>= 5.2), libqt5gui5 (>= 5.2), libqt5network5 (>= 5.0), libqt5widgets5 (>= 5.2), libqt5xml5 (>= 5.0), libstdc++6 (>= 4.9), libvpx1 (>= 1.0.0)
|
||||
Description: Tox client
|
||||
qTox is a powerful Tox client that follows the Tox design guidelines.
|
||||
Tox is a decentralized and encrypted replacement for Skype, supporting
|
||||
|
|
|
@ -9,4 +9,4 @@ Exec=qtox
|
|||
Icon=qtox
|
||||
Categories=InstantMessaging;;AudioVideo;Network;
|
||||
Terminal=false
|
||||
MimeType=x-scheme-handler/tox;
|
||||
MimeType=x-scheme-handler/tox;application/x-tox;
|
||||
|
|
4
qtox.pro
4
qtox.pro
|
@ -71,11 +71,11 @@ win32 {
|
|||
LIBS += -Wl,-Bdynamic -ltbb -lv4l1 -lv4l2 -lgnutls -lrtmp -lgnutls -lavformat -lavcodec -lavutil -lavfilter -lswscale -lusb-1.0
|
||||
|
||||
} else {
|
||||
LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxencryptsave -ltoxav -lvpx -lopenal -lopencv_core -lopencv_highgui -lopencv_imgproc
|
||||
LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -ltoxencryptsave -lvpx -lopenal -lopencv_core -lopencv_highgui -lopencv_imgproc
|
||||
}
|
||||
|
||||
contains(JENKINS, YES) {
|
||||
LIBS = ./libs/lib/libtoxav.a ./libs/lib/libtoxencryptsave.a ./libs/lib/libvpx.a ./libs/lib/libopus.a ./libs/lib/libtoxcore.a ./libs/lib/libsodium.a -lopencv_core -lopencv_highgui -lopenal
|
||||
LIBS = ./libs/lib/libsodium.a ./libs/lib/libtoxcore.a ./libs/lib/libtoxav.a ./libs/lib/libtoxencryptsave.a ./libs/lib/libvpx.a ./libs/lib/libopus.a -lopencv_core -lopencv_highgui -lopenal
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
245
src/core.cpp
245
src/core.cpp
|
@ -21,6 +21,7 @@
|
|||
#include "widget/widget.h"
|
||||
|
||||
#include <tox/tox.h>
|
||||
#include <tox/toxencryptsave.h>
|
||||
|
||||
#include <ctime>
|
||||
#include <functional>
|
||||
|
@ -39,12 +40,15 @@
|
|||
#include <QMessageBox>
|
||||
|
||||
const QString Core::CONFIG_FILE_NAME = "data";
|
||||
const QString Core::TOX_EXT = ".tox";
|
||||
QList<ToxFile> Core::fileSendQueue;
|
||||
QList<ToxFile> Core::fileRecvQueue;
|
||||
|
||||
Core::Core(Camera* cam, QThread *coreThread) :
|
||||
tox(nullptr), camera(cam)
|
||||
Core::Core(Camera* cam, QThread *coreThread, QString loadPath) :
|
||||
tox(nullptr), camera(cam), loadPath(loadPath)
|
||||
{
|
||||
qDebug() << "Core: loading Tox from" << loadPath;
|
||||
|
||||
videobuf = new uint8_t[videobufsize];
|
||||
videoBusyness=0;
|
||||
|
||||
|
@ -110,6 +114,8 @@ Core::~Core()
|
|||
alcCloseDevice(alOutDev);
|
||||
if (alInDev)
|
||||
alcCaptureCloseDevice(alInDev);
|
||||
|
||||
clearPassword();
|
||||
}
|
||||
|
||||
Core* Core::getInstance()
|
||||
|
@ -117,12 +123,11 @@ Core* Core::getInstance()
|
|||
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.
|
||||
bool enableIPv6 = Settings::getInstance().getEnableIPv6();
|
||||
bool forceTCP = Settings::getInstance().getForceTCP();
|
||||
|
||||
bool useProxy = Settings::getInstance().getUseProxy();
|
||||
|
||||
if (enableIPv6)
|
||||
|
@ -181,7 +186,7 @@ void Core::start()
|
|||
emit failedToStart();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
qWarning() << "Core failed to start with IPv6, falling back to IPv4. LAN discovery may not work properly.";
|
||||
}
|
||||
|
@ -205,15 +210,24 @@ void Core::start()
|
|||
emit failedToStart();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Core::start()
|
||||
{
|
||||
make_tox();
|
||||
|
||||
qsrand(time(nullptr));
|
||||
|
||||
if (!loadConfiguration())
|
||||
if (loadPath != "")
|
||||
{
|
||||
emit failedToStart();
|
||||
tox_kill(tox);
|
||||
tox = nullptr;
|
||||
return;
|
||||
if (!loadConfiguration(loadPath)) // loadPath is meaningless after this
|
||||
{
|
||||
emit failedToStart();
|
||||
tox_kill(tox);
|
||||
tox = nullptr;
|
||||
return;
|
||||
}
|
||||
loadPath = "";
|
||||
}
|
||||
|
||||
tox_callback_friend_request(tox, onFriendRequest, this);
|
||||
|
@ -273,9 +287,9 @@ void Core::start()
|
|||
* 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.
|
||||
* 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()
|
||||
{
|
||||
|
@ -574,7 +588,7 @@ void Core::onFileControlCallback(Tox* tox, int32_t friendnumber, uint8_t receive
|
|||
|
||||
uint64_t resumePos = *reinterpret_cast<const uint64_t*>(data);
|
||||
|
||||
if (resumePos >= file->filesize)
|
||||
if (resumePos >= (unsigned)file->filesize)
|
||||
{
|
||||
qWarning() << "Core::onFileControlCallback: invalid resume position";
|
||||
tox_file_send_control(tox, file->friendId, 0, file->fileNum, TOX_FILECONTROL_KILL, nullptr, 0); // don't sure about it
|
||||
|
@ -627,8 +641,8 @@ void Core::onAvatarInfoCallback(Tox*, int32_t friendnumber, uint8_t format,
|
|||
{
|
||||
qDebug() << "Core: Got null avatar info from" << core->getFriendUsername(friendnumber);
|
||||
emit core->friendAvatarRemoved(friendnumber);
|
||||
QFile::remove(QDir(Settings::getInstance().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)+".png"));
|
||||
QFile::remove(QDir(Settings::getSettingsDirPath()).filePath("avatars/"+core->getFriendAddress(friendnumber).left(64)+".hash"));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -918,6 +932,8 @@ void Core::acceptFileRecvRequest(int friendId, int fileNum, QString path)
|
|||
|
||||
void Core::removeFriend(int friendId)
|
||||
{
|
||||
if (!tox)
|
||||
return;
|
||||
if (tox_del_friend(tox, friendId) == -1) {
|
||||
emit failedToRemoveFriend(friendId);
|
||||
} else {
|
||||
|
@ -928,6 +944,8 @@ void Core::removeFriend(int friendId)
|
|||
|
||||
void Core::removeGroup(int groupId)
|
||||
{
|
||||
if (!tox)
|
||||
return;
|
||||
tox_del_groupchat(tox, groupId);
|
||||
}
|
||||
|
||||
|
@ -949,8 +967,8 @@ void Core::setUsername(const QString& username)
|
|||
if (tox_set_name(tox, cUsername.data(), cUsername.size()) == -1) {
|
||||
emit failedToSetUsername(username);
|
||||
} else {
|
||||
saveConfiguration();
|
||||
emit usernameSet(username);
|
||||
saveConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -981,6 +999,13 @@ ToxID Core::getSelfId()
|
|||
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()
|
||||
{
|
||||
int size = tox_get_self_status_message_size(tox);
|
||||
|
@ -1038,11 +1063,25 @@ void Core::onFileTransferFinished(ToxFile file)
|
|||
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);
|
||||
qDebug() << "Core::loadConfiguration: reading from " << path;
|
||||
|
||||
if (!configurationFile.exists()) {
|
||||
qWarning() << "The Tox configuration file was not found";
|
||||
|
@ -1064,14 +1103,27 @@ bool Core::loadConfiguration()
|
|||
}
|
||||
else if (error == 1) // Encrypted data save
|
||||
{
|
||||
qWarning() << "Core: Can not open encrypted tox save";
|
||||
if (QMessageBox::Ok != QMessageBox::warning(nullptr, tr("Encrypted profile"),
|
||||
tr("Your tox profile seems to be encrypted, qTox can't open it\nDo you want to erase this profile ?"),
|
||||
QMessageBox::Ok | QMessageBox::Cancel))
|
||||
if (!pwsaltedkey)
|
||||
{
|
||||
qWarning() << "Core: Couldn't open encrypted save, giving up";
|
||||
configurationFile.close();
|
||||
return false;
|
||||
qWarning() << "Core: Can not open encrypted tox save";
|
||||
if (QMessageBox::Ok != QMessageBox::warning(nullptr, tr("Encrypted profile"),
|
||||
tr("Your tox profile seems to be encrypted, qTox can't open it\nDo you want to erase this profile ?"),
|
||||
QMessageBox::Ok | QMessageBox::Cancel))
|
||||
{
|
||||
qWarning() << "Core: Couldn't open encrypted save, giving up";
|
||||
configurationFile.close();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /*
|
||||
while (error != 0)
|
||||
{
|
||||
error = tox_encrypted_load(tox, reinterpret_cast<uint8_t *>(data.data()), data.size(), pwsaltedkey, TOX_HASH_LENGTH);
|
||||
emit blockingGetPassword();
|
||||
if (!pwsaltedkey)
|
||||
// we need a way to start core without any profile
|
||||
} */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1093,42 +1145,108 @@ bool Core::loadConfiguration()
|
|||
|
||||
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();
|
||||
|
||||
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();
|
||||
|
||||
Settings::getInstance().setCurrentProfile(profile);
|
||||
}
|
||||
|
||||
QString path = directory.filePath(profile + TOX_EXT);
|
||||
|
||||
saveConfiguration(path);
|
||||
}
|
||||
|
||||
void Core::saveConfiguration(const QString& path)
|
||||
{
|
||||
if (!tox)
|
||||
{
|
||||
qWarning() << "Core::saveConfiguration: Tox not started, aborting!";
|
||||
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);
|
||||
if (!configurationFile.open(QIODevice::WriteOnly)) {
|
||||
qCritical() << "File " << path << " cannot be opened";
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "Core: Saving";
|
||||
qDebug() << "Core: writing tox_save to " << path;
|
||||
|
||||
uint32_t fileSize;
|
||||
if (Settings::getInstance().getEncryptTox())
|
||||
fileSize = tox_encrypted_size(tox);
|
||||
else
|
||||
fileSize = tox_size(tox);
|
||||
|
||||
uint32_t fileSize = tox_size(tox);
|
||||
if (fileSize > 0 && fileSize <= INT32_MAX) {
|
||||
uint8_t *data = new uint8_t[fileSize];
|
||||
tox_save(tox, data);
|
||||
|
||||
if (Settings::getInstance().getEncryptTox())
|
||||
{
|
||||
if (!pwsaltedkey)
|
||||
emit blockingGetPassword();
|
||||
//if (!pwsaltedkey)
|
||||
// revert to unsaved...? or maybe we shouldn't even try to get a pw from here ^
|
||||
int ret = tox_encrypted_save(tox, data, pwsaltedkey, TOX_HASH_LENGTH);
|
||||
if (ret == -1)
|
||||
{
|
||||
qCritical() << "Core::saveConfiguration: encryption of save file failed!!!";
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
tox_save(tox, data);
|
||||
|
||||
configurationFile.write(reinterpret_cast<char *>(data), fileSize);
|
||||
configurationFile.commit();
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
|
||||
void Core::switchConfiguration(const QString& profile)
|
||||
{
|
||||
if (profile.isEmpty())
|
||||
{
|
||||
qWarning() << "Core: got null profile to switch to, not switching";
|
||||
return;
|
||||
}
|
||||
else
|
||||
qDebug() << "Core: switching from" << Settings::getInstance().getCurrentProfile() << "to" << profile;
|
||||
|
||||
saveConfiguration();
|
||||
clearPassword();
|
||||
toxTimer->stop();
|
||||
|
||||
if (tox) {
|
||||
toxav_kill(toxav);
|
||||
toxav = nullptr;
|
||||
tox_kill(tox);
|
||||
tox = nullptr;
|
||||
}
|
||||
emit selfAvatarChanged(QPixmap(":/img/contact_dark.png"));
|
||||
emit blockingClearContacts(); // we need this to block, but signals are required for thread safety
|
||||
|
||||
loadPath = QDir(Settings::getSettingsDirPath()).filePath(profile + TOX_EXT);
|
||||
Settings::getInstance().setCurrentProfile(profile);
|
||||
|
||||
start();
|
||||
}
|
||||
|
||||
void Core::loadFriends()
|
||||
{
|
||||
const uint32_t friendCount = tox_count_friendlist(tox);
|
||||
|
@ -1405,3 +1523,54 @@ QList<CString> Core::splitMessage(const QString &message)
|
|||
|
||||
return splittedMsgs;
|
||||
}
|
||||
|
||||
void Core::setPassword(QString& password)
|
||||
{
|
||||
if (password.isEmpty())
|
||||
{
|
||||
clearPassword();
|
||||
return;
|
||||
}
|
||||
if (!pwsaltedkey)
|
||||
pwsaltedkey = new uint8_t[tox_pass_key_length()];
|
||||
|
||||
CString str(password);
|
||||
tox_derive_key_from_pass(str.data(), str.size(), pwsaltedkey);
|
||||
password.clear();
|
||||
}
|
||||
|
||||
void Core::clearPassword()
|
||||
{
|
||||
if (pwsaltedkey)
|
||||
{
|
||||
delete[] pwsaltedkey;
|
||||
pwsaltedkey = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray Core::encryptData(const QByteArray& data)
|
||||
{
|
||||
if (!pwsaltedkey)
|
||||
return QByteArray();
|
||||
uint8_t encrypted[data.size() + tox_pass_encryption_extra_length()];
|
||||
if (tox_pass_key_encrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(), pwsaltedkey, encrypted) == -1)
|
||||
{
|
||||
qWarning() << "Core::encryptData: encryption failed";
|
||||
return QByteArray();
|
||||
}
|
||||
return QByteArray(reinterpret_cast<char*>(encrypted), data.size() + tox_pass_encryption_extra_length());
|
||||
}
|
||||
|
||||
QByteArray Core::decryptData(const QByteArray& data)
|
||||
{
|
||||
if (!pwsaltedkey)
|
||||
return QByteArray();
|
||||
int sz = data.size() - tox_pass_encryption_extra_length();
|
||||
uint8_t decrypted[sz];
|
||||
if (tox_pass_key_decrypt(reinterpret_cast<const uint8_t*>(data.data()), data.size(), pwsaltedkey, decrypted) != sz)
|
||||
{
|
||||
qWarning() << "Core::decryptData: decryption failed";
|
||||
return QByteArray();
|
||||
}
|
||||
return QByteArray(reinterpret_cast<char*>(decrypted), sz);
|
||||
}
|
||||
|
|
27
src/core.h
27
src/core.h
|
@ -34,9 +34,13 @@ class Core : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
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
|
||||
~Core();
|
||||
|
||||
static const QString TOX_EXT;
|
||||
static const QString CONFIG_FILE_NAME;
|
||||
static QString sanitize(QString name);
|
||||
|
||||
int getGroupNumberPeers(int groupId) const;
|
||||
QString getGroupPeerName(int groupId, int peerId) const;
|
||||
|
@ -48,6 +52,9 @@ public:
|
|||
void dispatchVideoFrame(vpx_image img) const;
|
||||
|
||||
void saveConfiguration();
|
||||
void saveConfiguration(const QString& path);
|
||||
|
||||
QString getIDString();
|
||||
|
||||
QString getUsername();
|
||||
QString getStatusMessage();
|
||||
|
@ -56,10 +63,13 @@ public:
|
|||
void increaseVideoBusyness();
|
||||
void decreaseVideoBusyness();
|
||||
|
||||
bool anyActiveCalls();
|
||||
|
||||
public slots:
|
||||
void start();
|
||||
void process();
|
||||
void bootstrapDht();
|
||||
void switchConfiguration(const QString& profile);
|
||||
|
||||
void acceptFriendRequest(const QString& userId);
|
||||
void requestFriendship(const QString& friendAddress, const QString& message);
|
||||
|
@ -94,9 +104,16 @@ public slots:
|
|||
|
||||
void micMuteToggle(int callId);
|
||||
|
||||
void setPassword(QString& password);
|
||||
void clearPassword();
|
||||
QByteArray encryptData(const QByteArray& data);
|
||||
QByteArray decryptData(const QByteArray& data);
|
||||
|
||||
signals:
|
||||
void connected();
|
||||
void disconnected();
|
||||
void blockingClearContacts();
|
||||
void blockingGetPassword();
|
||||
|
||||
void friendRequestReceived(const QString& userId, const QString& message);
|
||||
void friendMessageReceived(int friendId, const QString& message, bool isAction);
|
||||
|
@ -209,7 +226,8 @@ private:
|
|||
|
||||
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();
|
||||
|
||||
static void sendAllFileData(Core* core, ToxFile* file);
|
||||
|
@ -225,14 +243,15 @@ private slots:
|
|||
private:
|
||||
Tox* tox;
|
||||
ToxAv* toxav;
|
||||
QTimer *toxTimer, *fileTimer, *bootstrapTimer; //, *saveTimer;
|
||||
QTimer *toxTimer, *fileTimer; //, *saveTimer;
|
||||
Camera* camera;
|
||||
QString loadPath; // meaningless after start() is called
|
||||
QList<DhtServer> dhtServerList;
|
||||
int dhtServerId;
|
||||
static QList<ToxFile> fileSendQueue, fileRecvQueue;
|
||||
static ToxCall calls[];
|
||||
uint8_t* pwsaltedkey = nullptr; // use the pw's hash as the "pw"
|
||||
|
||||
static const QString CONFIG_FILE_NAME;
|
||||
static const int videobufsize;
|
||||
static uint8_t* videobuf;
|
||||
static int videoBusyness; // Used to know when to drop frames
|
||||
|
|
|
@ -28,6 +28,14 @@ ALCdevice* Core::alOutDev, *Core::alInDev;
|
|||
ALCcontext* Core::alContext;
|
||||
ALuint Core::alMainSource;
|
||||
|
||||
bool Core::anyActiveCalls()
|
||||
{
|
||||
for (auto& call : calls)
|
||||
if (call.active)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void Core::prepareCall(int friendId, int callId, ToxAv* toxav, bool videoEnabled)
|
||||
{
|
||||
qDebug() << QString("Core: preparing call %1").arg(callId);
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#include <QDebug>
|
||||
#include <QPainter>
|
||||
|
||||
#define CONTENT_WIDTH 250
|
||||
#define MAX_CONTENT_WIDTH 250
|
||||
#define MAX_PREVIEW_SIZE 25*1024*1024
|
||||
|
||||
uint FileTransferInstance::Idconter = 0;
|
||||
|
@ -43,9 +43,10 @@ FileTransferInstance::FileTransferInstance(ToxFile File)
|
|||
// update this whenever you change the font in innerStyle.css
|
||||
QFontMetrics fm(Style::getFont(Style::Small));
|
||||
|
||||
filenameElided = fm.elidedText(filename, Qt::ElideRight, CONTENT_WIDTH);
|
||||
|
||||
filenameElided = fm.elidedText(filename, Qt::ElideRight, MAX_CONTENT_WIDTH);
|
||||
size = getHumanReadableSize(File.filesize);
|
||||
contentPrefWidth = std::max(fm.width(filenameElided), fm.width(size));
|
||||
|
||||
speed = "0B/s";
|
||||
eta = "00:00";
|
||||
|
||||
|
@ -57,7 +58,7 @@ FileTransferInstance::FileTransferInstance(ToxFile File)
|
|||
File.file->seek(0);
|
||||
if (preview.loadFromData(File.file->readAll()))
|
||||
{
|
||||
pic = preview.scaledToHeight(50);
|
||||
pic = preview.scaled(100, 50, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
}
|
||||
File.file->seek(0);
|
||||
|
@ -127,7 +128,7 @@ void FileTransferInstance::onFileTransferFinished(ToxFile File)
|
|||
{
|
||||
if (preview.loadFromData(previewFile.readAll()))
|
||||
{
|
||||
pic = preview.scaledToHeight(50);
|
||||
pic = preview.scaled(100, 50, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
previewFile.close();
|
||||
}
|
||||
|
@ -377,7 +378,8 @@ QString FileTransferInstance::draw2ButtonsForm(const QString &type, const QImage
|
|||
QString imgBstr = "<img src=\"data:ftrans." + widgetId + ".btnB/png;base64," + QImage2base64(imgB) + "\">";
|
||||
|
||||
QString content;
|
||||
QString progrBar = "<img src=\"data:progressbar." + widgetId + "/png;base64," + QImage2base64(drawProgressBarImg(double(lastBytesSent)/totalBytes, CONTENT_WIDTH, 9)) + "\">";
|
||||
QString progrBar = "<img src=\"data:progressbar." + widgetId + "/png;base64," +
|
||||
QImage2base64(drawProgressBarImg(double(lastBytesSent)/totalBytes, MAX_CONTENT_WIDTH, 9)) + "\">";
|
||||
|
||||
content = "<p>" + filenameElided + "</p>";
|
||||
content += "<table cellspacing=\"0\"><tr>";
|
||||
|
@ -421,11 +423,14 @@ QString FileTransferInstance::wrapIntoForm(const QString& content, const QString
|
|||
res += "<div class=button>" + imgLeftA + "<br>" + imgLeftB + "</div>\n";
|
||||
res += "</td>\n";
|
||||
res += insertMiniature(type);
|
||||
res += "<td width=" + QString::number(CONTENT_WIDTH + 30) + ">\n";
|
||||
res += "<td width=" + QString::number(contentPrefWidth) + ">\n";
|
||||
res += "<div class=" + type + ">";
|
||||
res += content;
|
||||
res += "</div>\n";
|
||||
res += "</td>\n";
|
||||
res += "<td width=3>\n";
|
||||
res += "<div class=" + type + "></div>\n";
|
||||
res += "</td>\n";
|
||||
res += "<td>\n";
|
||||
res += "<div class=button>" + imgAstr + "<br>" + imgBstr + "</div>\n";
|
||||
res += "</td>\n";
|
||||
|
|
|
@ -78,6 +78,7 @@ private:
|
|||
long long lastBytesSent, totalBytes;
|
||||
int fileNum;
|
||||
int friendId;
|
||||
int contentPrefWidth;
|
||||
QString savePath;
|
||||
ToxFile::FileDirection direction;
|
||||
QString stopFileButtonStylesheet, pauseFileButtonStylesheet, acceptFileButtonStylesheet;
|
||||
|
|
|
@ -44,9 +44,8 @@ HistoryKeeper *HistoryKeeper::getInstance()
|
|||
|
||||
if (encrypted)
|
||||
{
|
||||
QString key = "plainKey"; // FIXME: ask user about it
|
||||
path = QDir(Settings::getInstance().getSettingsDirPath()).filePath("qtox_history.encrypted");
|
||||
dbIntf = new EncryptedDb(path, key);
|
||||
dbIntf = new EncryptedDb(path);
|
||||
|
||||
historyInstance = new HistoryKeeper(dbIntf);
|
||||
return historyInstance;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "encrypteddb.h"
|
||||
#include "src/misc/settings.h"
|
||||
#include "src/core.h"
|
||||
|
||||
#include <tox/toxencryptsave.h>
|
||||
|
||||
|
@ -23,17 +24,9 @@
|
|||
#include <QDebug>
|
||||
#include <QSqlError>
|
||||
|
||||
EncryptedDb::EncryptedDb(const QString &fname, const QString &key) :
|
||||
EncryptedDb::EncryptedDb(const QString &fname) :
|
||||
PlainDb(":memory:"), encrFile(fname)
|
||||
{
|
||||
encrkey = new u_int8_t[tox_pass_key_length()];
|
||||
QByteArray key_ba;
|
||||
key_ba.append(key);
|
||||
// tox_derive_key_from_pass(reinterpret_cast<uint8_t*>(key_ba.data()), key_ba.size(), encrkey);
|
||||
passwd = "test";
|
||||
|
||||
qDebug() << QByteArray::fromRawData(reinterpret_cast<char *>(encrkey), tox_pass_key_length()).toBase64();
|
||||
|
||||
plainChunkSize = 1024;
|
||||
encryptedChunkSize = plainChunkSize + tox_pass_encryption_extra_length();
|
||||
|
||||
|
@ -60,8 +53,7 @@ EncryptedDb::EncryptedDb(const QString &fname, const QString &key) :
|
|||
|
||||
EncryptedDb::~EncryptedDb()
|
||||
{
|
||||
encrFile.close();
|
||||
delete encrkey;
|
||||
encrFile.close(); // what if program is killed without being able to clean up?
|
||||
}
|
||||
|
||||
QSqlQuery EncryptedDb::exec(const QString &query)
|
||||
|
@ -85,7 +77,7 @@ QList<QString> EncryptedDb::decryptFile()
|
|||
while (!encrFile.atEnd())
|
||||
{
|
||||
QByteArray encrChunk = encrFile.read(encryptedChunkSize);
|
||||
buffer = decrypt(encrChunk);
|
||||
buffer = Core::getInstance()->decryptData(encrChunk);
|
||||
fileContent += buffer;
|
||||
}
|
||||
|
||||
|
@ -114,44 +106,14 @@ void EncryptedDb::appendToEncrypted(const QString &sql)
|
|||
{
|
||||
QByteArray filledChunk = buffer.left(plainChunkSize);
|
||||
encrFile.seek(chunkPosition * encryptedChunkSize);
|
||||
encrFile.write(encrypt(filledChunk));
|
||||
encrFile.write(Core::getInstance()->encryptData(filledChunk));
|
||||
buffer = buffer.right(buffer.size() - plainChunkSize);
|
||||
chunkPosition++;
|
||||
}
|
||||
encrFile.seek(chunkPosition * encryptedChunkSize);
|
||||
|
||||
encrFile.write(encrypt(buffer));
|
||||
encrFile.write(Core::getInstance()->encryptData(buffer));
|
||||
encrFile.flush();
|
||||
|
||||
qDebug() << sql;
|
||||
}
|
||||
|
||||
QByteArray EncryptedDb::encrypt(QByteArray data)
|
||||
{
|
||||
int encrSize = data.size() + tox_pass_encryption_extra_length();
|
||||
int plainSize = data.size();
|
||||
|
||||
uint8_t *out = new u_int8_t[encrSize];
|
||||
// int state = tox_pass_key_encrypt(reinterpret_cast<uint8_t*>(data.data()), plainSize, encrkey, out);
|
||||
int state = tox_pass_encrypt(reinterpret_cast<uint8_t*>(data.data()), plainSize,
|
||||
reinterpret_cast<uint8_t*>(passwd.data()), passwd.size(), out);
|
||||
qDebug() << state;
|
||||
|
||||
QByteArray ret = QByteArray::fromRawData(reinterpret_cast<const char*>(out), encrSize);
|
||||
return ret;
|
||||
}
|
||||
|
||||
QByteArray EncryptedDb::decrypt(QByteArray data)
|
||||
{
|
||||
int encrSize = data.size();
|
||||
int plainSize = data.size() - tox_pass_encryption_extra_length();
|
||||
|
||||
uint8_t *out = new u_int8_t[plainSize];
|
||||
// int state = tox_pass_key_decrypt(reinterpret_cast<uint8_t*>(data.data()), encrSize, encrkey, out);
|
||||
int state = tox_pass_decrypt(reinterpret_cast<uint8_t*>(data.data()), encrSize,
|
||||
reinterpret_cast<uint8_t*>(passwd.data()), passwd.size(), out);
|
||||
qDebug() << state << encrSize << plainSize;
|
||||
|
||||
QByteArray ret = QByteArray::fromRawData(reinterpret_cast<const char*>(out), plainSize);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -25,22 +25,17 @@
|
|||
class EncryptedDb : public PlainDb
|
||||
{
|
||||
public:
|
||||
EncryptedDb(const QString& fname, const QString &key);
|
||||
EncryptedDb(const QString& fname);
|
||||
virtual ~EncryptedDb();
|
||||
|
||||
virtual QSqlQuery exec(const QString &query);
|
||||
virtual bool save();
|
||||
|
||||
private:
|
||||
QByteArray encrypt(QByteArray data);
|
||||
QByteArray decrypt(QByteArray data);
|
||||
|
||||
QList<QString> decryptFile();
|
||||
void appendToEncrypted(const QString &sql);
|
||||
|
||||
u_int8_t *encrkey;
|
||||
QFile encrFile;
|
||||
QByteArray passwd;
|
||||
|
||||
qint64 plainChunkSize;
|
||||
qint64 encryptedChunkSize;
|
||||
|
|
|
@ -115,6 +115,8 @@ void Settings::load()
|
|||
useProxy = s.value("useProxy", false).toBool();
|
||||
proxyAddr = s.value("proxyAddr", "").toString();
|
||||
proxyPort = s.value("proxyPort", 0).toInt();
|
||||
currentProfile = s.value("currentProfile", "").toString();
|
||||
autoAwayTime = s.value("autoAwayTime", 10).toInt();
|
||||
s.endGroup();
|
||||
|
||||
s.beginGroup("Widgets");
|
||||
|
@ -135,6 +137,8 @@ void Settings::load()
|
|||
timestampFormat = s.value("timestampFormat", "hh:mm").toString();
|
||||
minimizeOnClose = s.value("minimizeOnClose", false).toBool();
|
||||
useNativeStyle = s.value("nativeStyle", false).toBool();
|
||||
style = s.value("style", "None").toString();
|
||||
statusChangeNotificationEnabled = s.value("statusChangeNotificationEnabled", false).toBool();
|
||||
s.endGroup();
|
||||
|
||||
s.beginGroup("State");
|
||||
|
@ -221,6 +225,8 @@ void Settings::save(QString path)
|
|||
s.setValue("forceTCP", forceTCP);
|
||||
s.setValue("proxyAddr", proxyAddr);
|
||||
s.setValue("proxyPort", proxyPort);
|
||||
s.setValue("currentProfile", currentProfile);
|
||||
s.setValue("autoAwayTime", autoAwayTime);
|
||||
s.endGroup();
|
||||
|
||||
s.beginGroup("Widgets");
|
||||
|
@ -241,6 +247,8 @@ void Settings::save(QString path)
|
|||
s.setValue("timestampFormat", timestampFormat);
|
||||
s.setValue("minimizeOnClose", minimizeOnClose);
|
||||
s.setValue("nativeStyle", useNativeStyle);
|
||||
s.setValue("style",style);
|
||||
s.setValue("statusChangeNotificationEnabled", statusChangeNotificationEnabled);
|
||||
s.endGroup();
|
||||
|
||||
s.beginGroup("State");
|
||||
|
@ -360,11 +368,31 @@ bool Settings::getAutostartInTray() const
|
|||
return autostartInTray;
|
||||
}
|
||||
|
||||
QString Settings::getStyle() const
|
||||
{
|
||||
return style;
|
||||
}
|
||||
|
||||
void Settings::setStyle(const QString& newStyle)
|
||||
{
|
||||
style = newStyle;
|
||||
}
|
||||
|
||||
void Settings::setAutostartInTray(bool newValue)
|
||||
{
|
||||
autostartInTray = newValue;
|
||||
}
|
||||
|
||||
bool Settings::getStatusChangeNotificationEnabled() const
|
||||
{
|
||||
return statusChangeNotificationEnabled;
|
||||
}
|
||||
|
||||
void Settings::setStatusChangeNotificationEnabled(bool newValue)
|
||||
{
|
||||
statusChangeNotificationEnabled = newValue;
|
||||
}
|
||||
|
||||
bool Settings::getUseTranslations() const
|
||||
{
|
||||
return useTranslations;
|
||||
|
@ -414,6 +442,16 @@ void Settings::setProxyPort(int newValue)
|
|||
proxyPort = newValue;
|
||||
}
|
||||
|
||||
QString Settings::getCurrentProfile() const
|
||||
{
|
||||
return currentProfile;
|
||||
}
|
||||
|
||||
void Settings::setCurrentProfile(QString profile)
|
||||
{
|
||||
currentProfile = profile;
|
||||
}
|
||||
|
||||
bool Settings::getEnableLogging() const
|
||||
{
|
||||
return enableLogging;
|
||||
|
@ -434,6 +472,28 @@ void Settings::setEncryptLogs(bool newValue)
|
|||
encryptLogs = newValue;
|
||||
}
|
||||
|
||||
bool Settings::getEncryptTox() const
|
||||
{
|
||||
return encryptTox;
|
||||
}
|
||||
|
||||
void Settings::setEncryptTox(bool newValue)
|
||||
{
|
||||
encryptTox = newValue;
|
||||
}
|
||||
|
||||
int Settings::getAutoAwayTime() const
|
||||
{
|
||||
return autoAwayTime;
|
||||
}
|
||||
|
||||
void Settings::setAutoAwayTime(int newValue)
|
||||
{
|
||||
if (newValue < 0)
|
||||
newValue = 10;
|
||||
autoAwayTime = newValue;
|
||||
}
|
||||
|
||||
void Settings::setWidgetData(const QString& uniqueName, const QByteArray& data)
|
||||
{
|
||||
widgetSettings[uniqueName] = data;
|
||||
|
|
|
@ -51,6 +51,12 @@ public:
|
|||
|
||||
bool getAutostartInTray() const;
|
||||
void setAutostartInTray(bool newValue);
|
||||
|
||||
QString getStyle() const;
|
||||
void setStyle(const QString& newValue);
|
||||
|
||||
QString getCurrentProfile() const;
|
||||
void setCurrentProfile(QString profile);
|
||||
|
||||
bool getUseTranslations() const;
|
||||
void setUseTranslations(bool newValue);
|
||||
|
@ -73,6 +79,12 @@ public:
|
|||
bool getEncryptLogs() const;
|
||||
void setEncryptLogs(bool newValue);
|
||||
|
||||
bool getEncryptTox() const;
|
||||
void setEncryptTox(bool newValue);
|
||||
|
||||
int getAutoAwayTime() const;
|
||||
void setAutoAwayTime(int newValue);
|
||||
|
||||
QPixmap getSavedAvatar(const QString& ownerId);
|
||||
void saveAvatar(QPixmap& pic, const QString& ownerId);
|
||||
|
||||
|
@ -129,10 +141,14 @@ public:
|
|||
bool isMinimizeOnCloseEnabled() const;
|
||||
void setMinimizeOnClose(bool newValue);
|
||||
|
||||
bool getStatusChangeNotificationEnabled() const;
|
||||
void setStatusChangeNotificationEnabled(bool newValue);
|
||||
|
||||
// Privacy
|
||||
bool isTypingNotificationEnabled() const;
|
||||
void setTypingNotification(bool enabled);
|
||||
|
||||
// State
|
||||
bool getUseNativeStyle() const;
|
||||
void setUseNativeStyle(bool value);
|
||||
|
||||
|
@ -176,8 +192,13 @@ private:
|
|||
QString proxyAddr;
|
||||
int proxyPort;
|
||||
|
||||
QString currentProfile;
|
||||
|
||||
bool enableLogging;
|
||||
bool encryptLogs;
|
||||
bool encryptTox;
|
||||
|
||||
int autoAwayTime;
|
||||
|
||||
QHash<QString, QByteArray> widgetSettings;
|
||||
|
||||
|
@ -192,11 +213,13 @@ private:
|
|||
QByteArray windowGeometry;
|
||||
QByteArray windowState;
|
||||
QByteArray splitterState;
|
||||
|
||||
QString style;
|
||||
|
||||
// ChatView
|
||||
int firstColumnHandlePos;
|
||||
int secondColumnHandlePosFromRight;
|
||||
QString timestampFormat;
|
||||
bool statusChangeNotificationEnabled;
|
||||
|
||||
// Privacy
|
||||
bool typingNotification;
|
||||
|
|
|
@ -127,12 +127,21 @@ bool SmileyPack::load(const QString& filename)
|
|||
{
|
||||
QString emoticon = stringElement.text();
|
||||
filenameTable.insert(emoticon, file);
|
||||
emoticonSet.push_back(emoticon);
|
||||
|
||||
cacheSmiley(file); // preload all smileys
|
||||
|
||||
|
||||
QPixmap pm;
|
||||
pm.loadFromData(getCachedSmiley(emoticon), "PNG");
|
||||
|
||||
if(pm.size().width() > 0)
|
||||
emoticonSet.push_back(emoticon);
|
||||
|
||||
stringElement = stringElement.nextSibling().toElement();
|
||||
|
||||
}
|
||||
emoticons.push_back(emoticonSet);
|
||||
|
||||
if(emoticonSet.size() > 0)
|
||||
emoticons.push_back(emoticonSet);
|
||||
}
|
||||
|
||||
// success!
|
||||
|
@ -176,7 +185,6 @@ QIcon SmileyPack::getAsIcon(const QString &key)
|
|||
{
|
||||
QPixmap pm;
|
||||
pm.loadFromData(getCachedSmiley(key), "PNG");
|
||||
|
||||
return QIcon(pm);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,6 @@ Camera::Camera()
|
|||
|
||||
connect(workerThread, &QThread::started, worker, &CameraWorker::onStart);
|
||||
connect(workerThread, &QThread::finished, worker, &CameraWorker::deleteLater);
|
||||
connect(workerThread, &QThread::deleteLater, worker, &CameraWorker::deleteLater);
|
||||
connect(worker, &CameraWorker::started, this, &Camera::onWorkerStarted);
|
||||
connect(worker, &CameraWorker::newFrameAvailable, this, &Camera::onNewFrameAvailable);
|
||||
connect(worker, &CameraWorker::resProbingFinished, this, &Camera::onResProbingFinished);
|
||||
|
|
|
@ -118,6 +118,11 @@ void ChatAreaWidget::insertMessage(ChatAction *msgAction)
|
|||
messages.append(msgAction);
|
||||
}
|
||||
|
||||
int ChatAreaWidget::getNumberOfMessages()
|
||||
{
|
||||
return messages.size();
|
||||
}
|
||||
|
||||
void ChatAreaWidget::onSliderRangeChanged()
|
||||
{
|
||||
QScrollBar* scroll = verticalScrollBar();
|
||||
|
|
|
@ -34,6 +34,7 @@ public:
|
|||
|
||||
int nameColWidth() {return nameWidth;}
|
||||
void setNameColWidth(int w);
|
||||
int getNumberOfMessages();
|
||||
|
||||
public slots:
|
||||
void clearChatArea();
|
||||
|
|
|
@ -132,6 +132,11 @@ GenericChatForm::GenericChatForm(QWidget *parent) :
|
|||
connect(chatWidget, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(onChatContextMenuRequested(QPoint)));
|
||||
}
|
||||
|
||||
int GenericChatForm::getNumberOfMessages()
|
||||
{
|
||||
return chatWidget->getNumberOfMessages();
|
||||
}
|
||||
|
||||
void GenericChatForm::setName(const QString &newName)
|
||||
{
|
||||
nameLabel->setText(newName);
|
||||
|
|
|
@ -48,6 +48,7 @@ public:
|
|||
virtual void show(Ui::MainWindow &ui);
|
||||
void addMessage(const QString &author, const QString &message, bool isAction, const QDateTime &datetime);
|
||||
void addSystemInfoMessage(const QString &message, const QString &type, const QDateTime &datetime);
|
||||
int getNumberOfMessages();
|
||||
|
||||
signals:
|
||||
void sendMessage(int, QString);
|
||||
|
|
|
@ -21,24 +21,39 @@
|
|||
#include "src/misc/settings.h"
|
||||
#include "src/misc/smileypack.h"
|
||||
#include <QMessageBox>
|
||||
#include <QStyleFactory>
|
||||
|
||||
GeneralForm::GeneralForm() :
|
||||
GeneralForm::GeneralForm(SettingsWidget *myParent) :
|
||||
GenericForm(tr("General Settings"), QPixmap(":/img/settings/general.png"))
|
||||
{
|
||||
parent = myParent;
|
||||
|
||||
bodyUI = new Ui::GeneralSettings;
|
||||
bodyUI->setupUi(this);
|
||||
|
||||
|
||||
bodyUI->cbEnableIPv6->setChecked(Settings::getInstance().getEnableIPv6());
|
||||
bodyUI->cbUseTranslations->setChecked(Settings::getInstance().getUseTranslations());
|
||||
bodyUI->cbMakeToxPortable->setChecked(Settings::getInstance().getMakeToxPortable());
|
||||
bodyUI->startInTray->setChecked(Settings::getInstance().getAutostartInTray());
|
||||
bodyUI->statusChangesCheckbox->setChecked(Settings::getInstance().getStatusChangeNotificationEnabled());
|
||||
|
||||
for (auto entry : SmileyPack::listSmileyPacks())
|
||||
{
|
||||
bodyUI->smileyPackBrowser->addItem(entry.first, entry.second);
|
||||
}
|
||||
bodyUI->smileyPackBrowser->setCurrentIndex(bodyUI->smileyPackBrowser->findData(Settings::getInstance().getSmileyPack()));
|
||||
reloadSmiles();
|
||||
|
||||
bodyUI->styleBrowser->addItems(QStyleFactory::keys());
|
||||
bodyUI->styleBrowser->addItem("None");
|
||||
|
||||
if(QStyleFactory::keys().contains(Settings::getInstance().getStyle()))
|
||||
bodyUI->styleBrowser->setCurrentText(Settings::getInstance().getStyle());
|
||||
else
|
||||
bodyUI->styleBrowser->setCurrentText("None");
|
||||
|
||||
bodyUI->autoAwaySpinBox->setValue(Settings::getInstance().getAutoAwayTime());
|
||||
|
||||
bodyUI->cbUDPDisabled->setChecked(Settings::getInstance().getForceTCP());
|
||||
bodyUI->proxyAddr->setText(Settings::getInstance().getProxyAddr());
|
||||
int port = Settings::getInstance().getProxyPort();
|
||||
|
@ -52,12 +67,15 @@ GeneralForm::GeneralForm() :
|
|||
connect(bodyUI->cbUseTranslations, &QCheckBox::stateChanged, this, &GeneralForm::onUseTranslationUpdated);
|
||||
connect(bodyUI->cbMakeToxPortable, &QCheckBox::stateChanged, this, &GeneralForm::onMakeToxPortableUpdated);
|
||||
connect(bodyUI->startInTray, &QCheckBox::stateChanged, this, &GeneralForm::onSetAutostartInTray);
|
||||
connect(bodyUI->statusChangesCheckbox, &QCheckBox::stateChanged, this, &GeneralForm::onSetStatusChange);
|
||||
connect(bodyUI->smileyPackBrowser, SIGNAL(currentIndexChanged(int)), this, SLOT(onSmileyBrowserIndexChanged(int)));
|
||||
// new syntax can't handle overloaded signals... (at least not in a pretty way)
|
||||
connect(bodyUI->cbUDPDisabled, &QCheckBox::stateChanged, this, &GeneralForm::onUDPUpdated);
|
||||
connect(bodyUI->proxyAddr, &QLineEdit::editingFinished, this, &GeneralForm::onProxyAddrEdited);
|
||||
connect(bodyUI->proxyPort, SIGNAL(valueChanged(int)), this, SLOT(onProxyPortEdited(int)));
|
||||
connect(bodyUI->cbUseProxy, &QCheckBox::stateChanged, this, &GeneralForm::onUseProxyUpdated);
|
||||
connect(bodyUI->styleBrowser, SIGNAL(currentTextChanged(QString)), this, SLOT(onStyleSelected(QString)));
|
||||
connect(bodyUI->autoAwaySpinBox, SIGNAL(editingFinished()), this, SLOT(onAutoAwayChanged()));
|
||||
}
|
||||
|
||||
GeneralForm::~GeneralForm()
|
||||
|
@ -85,10 +103,30 @@ void GeneralForm::onSetAutostartInTray()
|
|||
Settings::getInstance().setAutostartInTray(bodyUI->startInTray->isChecked());
|
||||
}
|
||||
|
||||
void GeneralForm::onStyleSelected(QString style)
|
||||
{
|
||||
Settings::getInstance().setStyle(style);
|
||||
this->setStyle(QStyleFactory::create(style));
|
||||
parent->setBodyHeadStyle(style);
|
||||
}
|
||||
|
||||
void GeneralForm::onAutoAwayChanged()
|
||||
{
|
||||
int minutes = bodyUI->autoAwaySpinBox->value();
|
||||
Settings::getInstance().setAutoAwayTime(minutes);
|
||||
Widget::getInstance()->setIdleTimer(minutes);
|
||||
}
|
||||
|
||||
void GeneralForm::onSetStatusChange()
|
||||
{
|
||||
Settings::getInstance().setStatusChangeNotificationEnabled(bodyUI->statusChangesCheckbox->isChecked());
|
||||
}
|
||||
|
||||
void GeneralForm::onSmileyBrowserIndexChanged(int index)
|
||||
{
|
||||
QString filename = bodyUI->smileyPackBrowser->itemData(index).toString();
|
||||
Settings::getInstance().setSmileyPack(filename);
|
||||
reloadSmiles();
|
||||
}
|
||||
|
||||
void GeneralForm::onUDPUpdated()
|
||||
|
@ -119,3 +157,26 @@ void GeneralForm::onUseProxyUpdated()
|
|||
bodyUI->proxyPort->setEnabled(state);
|
||||
Settings::getInstance().setUseProxy(state);
|
||||
}
|
||||
|
||||
void GeneralForm::reloadSmiles()
|
||||
{
|
||||
QList<QStringList> emoticons = SmileyPack::getInstance().getEmoticons();
|
||||
QStringList smiles;
|
||||
smiles << ":)" << ";)" << ":p" << ":O" << ":["; //just in case...
|
||||
|
||||
for(int i = 0; i < emoticons.size(); i++)
|
||||
smiles.push_front(emoticons.at(i).first());
|
||||
|
||||
int pixSize = 30;
|
||||
bodyUI->smile1->setPixmap(SmileyPack::getInstance().getAsIcon(smiles[0]).pixmap(pixSize, pixSize));
|
||||
bodyUI->smile2->setPixmap(SmileyPack::getInstance().getAsIcon(smiles[1]).pixmap(pixSize, pixSize));
|
||||
bodyUI->smile3->setPixmap(SmileyPack::getInstance().getAsIcon(smiles[2]).pixmap(pixSize, pixSize));
|
||||
bodyUI->smile4->setPixmap(SmileyPack::getInstance().getAsIcon(smiles[3]).pixmap(pixSize, pixSize));
|
||||
bodyUI->smile5->setPixmap(SmileyPack::getInstance().getAsIcon(smiles[4]).pixmap(pixSize, pixSize));
|
||||
|
||||
bodyUI->smile1->setToolTip(smiles[0]);
|
||||
bodyUI->smile2->setToolTip(smiles[1]);
|
||||
bodyUI->smile3->setToolTip(smiles[2]);
|
||||
bodyUI->smile4->setToolTip(smiles[3]);
|
||||
bodyUI->smile5->setToolTip(smiles[4]);
|
||||
}
|
||||
|
|
|
@ -18,8 +18,6 @@
|
|||
#define GENERALFORM_H
|
||||
|
||||
#include "genericsettings.h"
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
|
||||
namespace Ui {
|
||||
class GeneralSettings;
|
||||
|
@ -29,7 +27,7 @@ class GeneralForm : public GenericForm
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
GeneralForm();
|
||||
GeneralForm(SettingsWidget *parent);
|
||||
~GeneralForm();
|
||||
|
||||
private slots:
|
||||
|
@ -42,9 +40,15 @@ private slots:
|
|||
void onProxyAddrEdited();
|
||||
void onProxyPortEdited(int port);
|
||||
void onUseProxyUpdated();
|
||||
void onStyleSelected(QString style);
|
||||
void onSetStatusChange();
|
||||
void onAutoAwayChanged();
|
||||
|
||||
|
||||
private:
|
||||
Ui::GeneralSettings *bodyUI;
|
||||
void reloadSmiles();
|
||||
SettingsWidget *parent;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>527</width>
|
||||
<height>369</height>
|
||||
<height>500</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
|
@ -53,6 +53,49 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="statusChangesCheckbox">
|
||||
<property name="text">
|
||||
<string>Show contacts' status changes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item alignment="Qt::AlignLeft">
|
||||
<widget class="QLabel" name="autoAwayLabel">
|
||||
<property name="toolTip">
|
||||
<string>Provided in minutes</string>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Auto away after:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="autoAwaySpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> minutes</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>600</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -72,6 +115,70 @@
|
|||
<item>
|
||||
<widget class="QComboBox" name="smileyPackBrowser"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="smile1">
|
||||
<property name="toolTip">
|
||||
<string>:)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="smile2">
|
||||
<property name="toolTip">
|
||||
<string>;)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="smile3">
|
||||
<property name="toolTip">
|
||||
<string>:p</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="smile4">
|
||||
<property name="toolTip">
|
||||
<string>:O</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="smile5">
|
||||
<property name="toolTip">
|
||||
<string>:'(</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="styleLabel">
|
||||
<property name="text">
|
||||
<string>Style</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="styleBrowser"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
|
|
@ -18,11 +18,16 @@
|
|||
#include "ui_identitysettings.h"
|
||||
#include "identityform.h"
|
||||
#include "src/widget/form/settingswidget.h"
|
||||
#include "src/misc/settings.h"
|
||||
#include "src/widget/croppinglabel.h"
|
||||
#include "src/widget/widget.h"
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
#include <QInputDialog>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
|
||||
IdentityForm::IdentityForm() :
|
||||
GenericForm(tr("Your identity"), QPixmap(":/img/settings/identity.png"))
|
||||
|
@ -38,7 +43,7 @@ IdentityForm::IdentityForm() :
|
|||
|
||||
// toxId->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||
toxId->setReadOnly(true);
|
||||
// toxId->setFrameStyle(QFrame::NoFrame);
|
||||
toxId->setFrame(false);
|
||||
// toxId->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
// toxId->setFixedHeight(toxId->document()->size().height()*2);
|
||||
toxId->setFont(small);
|
||||
|
@ -49,6 +54,11 @@ IdentityForm::IdentityForm() :
|
|||
connect(toxId, SIGNAL(clicked()), this, SLOT(copyIdClicked()));
|
||||
connect(bodyUI->userName, SIGNAL(editingFinished()), this, SLOT(onUserNameEdited()));
|
||||
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()
|
||||
|
@ -61,6 +71,7 @@ void IdentityForm::copyIdClicked()
|
|||
QString txt = toxId->text();
|
||||
txt.replace('\n',"");
|
||||
QApplication::clipboard()->setText(txt);
|
||||
toxId->setCursorPosition(0);
|
||||
}
|
||||
|
||||
void IdentityForm::onUserNameEdited()
|
||||
|
@ -76,6 +87,13 @@ void IdentityForm::onStatusMessageEdited()
|
|||
void IdentityForm::present()
|
||||
{
|
||||
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)
|
||||
|
@ -87,3 +105,80 @@ void IdentityForm::setStatusMessage(const QString &msg)
|
|||
{
|
||||
bodyUI->statusMessage->setText(msg);
|
||||
}
|
||||
|
||||
void IdentityForm::onLoadClicked()
|
||||
{
|
||||
if (bodyUI->profiles->currentText() != Settings::getInstance().getCurrentProfile())
|
||||
{
|
||||
if (Core::getInstance()->anyActiveCalls())
|
||||
QMessageBox::warning(this, tr("Call active", "popup title"),
|
||||
tr("You can't switch profiles while a call is active!", "popup text"));
|
||||
else
|
||||
emit Widget::getInstance()->changeProfile(bodyUI->profiles->currentText());
|
||||
// I think by directly calling the function, I may have been causing thread issues
|
||||
}
|
||||
}
|
||||
|
||||
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"));
|
||||
if (!path.isEmpty())
|
||||
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"));
|
||||
if (path.isEmpty())
|
||||
return;
|
||||
|
||||
QFileInfo info(path);
|
||||
|
||||
if (info.suffix() != "tox")
|
||||
{
|
||||
QMessageBox::warning(this, tr("Ignoring non-Tox file", "popup title"), tr("Warning: you've chosen a file that is not a Tox save file; ignoring.", "popup text"));
|
||||
return;
|
||||
}
|
||||
|
||||
QString profile = info.completeBaseName();
|
||||
QString profilePath = QDir(Settings::getSettingsDirPath()).filePath(profile + Core::TOX_EXT);
|
||||
QFile::copy(path, profilePath);
|
||||
bodyUI->profiles->addItem(profile);
|
||||
}
|
||||
|
|
|
@ -60,6 +60,11 @@ private slots:
|
|||
void copyIdClicked();
|
||||
void onUserNameEdited();
|
||||
void onStatusMessageEdited();
|
||||
void onLoadClicked();
|
||||
void onRenameClicked();
|
||||
void onExportClicked();
|
||||
void onDeleteClicked();
|
||||
void onImportClicked();
|
||||
|
||||
private:
|
||||
Ui::IdentitySettings* bodyUI;
|
||||
|
|
|
@ -59,6 +59,71 @@
|
|||
</layout>
|
||||
</widget>
|
||||
</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>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
|
|
|
@ -52,7 +52,7 @@ SettingsWidget::SettingsWidget(QWidget* parent)
|
|||
tabBar = new QTabBar;
|
||||
bodyLayout->addWidget(tabBar);
|
||||
|
||||
GeneralForm *gfrm = new GeneralForm;
|
||||
GeneralForm *gfrm = new GeneralForm(this);
|
||||
ifrm = new IdentityForm;
|
||||
PrivacyForm *pfrm = new PrivacyForm;
|
||||
AVForm *avfrm = new AVForm;
|
||||
|
@ -73,6 +73,12 @@ SettingsWidget::~SettingsWidget()
|
|||
{
|
||||
}
|
||||
|
||||
void SettingsWidget::setBodyHeadStyle(QString style)
|
||||
{
|
||||
head->setStyle(QStyleFactory::create(style));
|
||||
body->setStyle(QStyleFactory::create(style));
|
||||
}
|
||||
|
||||
void SettingsWidget::show(Ui::MainWindow& ui)
|
||||
{
|
||||
ui.mainContent->layout()->addWidget(body);
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
#include <QHBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QStyleFactory>
|
||||
|
||||
class Camera;
|
||||
class GenericForm;
|
||||
class GeneralForm;
|
||||
|
@ -40,6 +42,7 @@ public:
|
|||
|
||||
void show(Ui::MainWindow &ui);
|
||||
IdentityForm *getIdentityForm() {return ifrm;}
|
||||
void setBodyHeadStyle(QString style);
|
||||
|
||||
private slots:
|
||||
void onTabChanged(int);
|
||||
|
|
|
@ -41,9 +41,13 @@
|
|||
#include <QClipboard>
|
||||
#include <QThread>
|
||||
#include <QFileDialog>
|
||||
#include <QInputDialog>
|
||||
#include <QTimer>
|
||||
#include <QStyleFactory>
|
||||
#include "src/historykeeper.h"
|
||||
#include <tox/tox.h>
|
||||
|
||||
|
||||
Widget *Widget::instance{nullptr};
|
||||
|
||||
Widget::Widget(QWidget *parent)
|
||||
|
@ -74,7 +78,16 @@ Widget::Widget(QWidget *parent)
|
|||
ui->mainHead->setLayout(new QVBoxLayout());
|
||||
ui->mainHead->layout()->setMargin(0);
|
||||
ui->mainHead->layout()->setSpacing(0);
|
||||
ui->mainHead->setStyleSheet(Style::getStylesheet(":ui/settings/mainHead.css"));
|
||||
|
||||
|
||||
if(QStyleFactory::keys().contains(Settings::getInstance().getStyle())
|
||||
&& Settings::getInstance().getStyle() != "None")
|
||||
{
|
||||
ui->mainHead->setStyle(QStyleFactory::create(Settings::getInstance().getStyle()));
|
||||
ui->mainContent->setStyle(QStyleFactory::create(Settings::getInstance().getStyle()));
|
||||
}
|
||||
|
||||
ui->mainHead->setStyleSheet(Style::getStylesheet(":ui/settings/mainHead.css"));
|
||||
ui->mainContent->setStyleSheet(Style::getStylesheet(":ui/settings/mainContent.css"));
|
||||
|
||||
contactListWidget = new FriendListWidget();
|
||||
|
@ -107,6 +120,11 @@ Widget::Widget(QWidget *parent)
|
|||
// Disable some widgets until we're connected to the DHT
|
||||
ui->statusButton->setEnabled(false);
|
||||
|
||||
idleTimer = new QTimer();
|
||||
int mins = Settings::getInstance().getAutoAwayTime();
|
||||
if (mins > 0)
|
||||
idleTimer->start(mins * 1000*60);
|
||||
|
||||
qRegisterMetaType<Status>("Status");
|
||||
qRegisterMetaType<vpx_image>("vpx_image");
|
||||
qRegisterMetaType<uint8_t>("uint8_t");
|
||||
|
@ -117,8 +135,9 @@ Widget::Widget(QWidget *parent)
|
|||
qRegisterMetaType<ToxFile>("ToxFile");
|
||||
qRegisterMetaType<ToxFile::FileDirection>("ToxFile::FileDirection");
|
||||
|
||||
QString profilePath = detectProfile();
|
||||
coreThread = new QThread(this);
|
||||
core = new Core(Camera::getInstance(), coreThread);
|
||||
core = new Core(Camera::getInstance(), coreThread, profilePath);
|
||||
core->moveToThread(coreThread);
|
||||
connect(coreThread, &QThread::started, core, &Core::start);
|
||||
|
||||
|
@ -134,7 +153,6 @@ Widget::Widget(QWidget *parent)
|
|||
connect(core, SIGNAL(fileUploadFinished(const QString&)), &filesForm, SLOT(onFileUploadComplete(const QString&)));
|
||||
connect(core, &Core::friendAdded, this, &Widget::addFriend);
|
||||
connect(core, &Core::failedToAddFriend, this, &Widget::addFriendFailed);
|
||||
connect(core, &Core::friendStatusChanged, this, &Widget::onFriendStatusChanged);
|
||||
connect(core, &Core::friendUsernameChanged, this, &Widget::onFriendUsernameChanged);
|
||||
connect(core, &Core::friendStatusChanged, this, &Widget::onFriendStatusChanged);
|
||||
connect(core, &Core::friendStatusMessageChanged, this, &Widget::onFriendStatusMessageChanged);
|
||||
|
@ -145,6 +163,8 @@ Widget::Widget(QWidget *parent)
|
|||
connect(core, &Core::groupNamelistChanged, this, &Widget::onGroupNamelistChanged);
|
||||
connect(core, &Core::emptyGroupCreated, this, &Widget::onEmptyGroupCreated);
|
||||
connect(core, &Core::avInvite, this, &Widget::playRingtone);
|
||||
connect(core, &Core::blockingClearContacts, this, &Widget::clearContactsList, Qt::BlockingQueuedConnection);
|
||||
connect(core, &Core::blockingGetPassword, this, &Widget::getPassword, Qt::BlockingQueuedConnection);
|
||||
|
||||
connect(core, SIGNAL(messageSentResult(int,QString,int)), this, SLOT(onMessageSendResult(int,QString,int)));
|
||||
connect(core, SIGNAL(groupSentResult(int,QString,int)), this, SLOT(onGroupSendResult(int,QString,int)));
|
||||
|
@ -152,6 +172,7 @@ Widget::Widget(QWidget *parent)
|
|||
connect(this, &Widget::statusSet, core, &Core::setStatus);
|
||||
connect(this, &Widget::friendRequested, core, &Core::requestFriendship);
|
||||
connect(this, &Widget::friendRequestAccepted, core, &Core::acceptFriendRequest);
|
||||
connect(this, &Widget::changeProfile, core, &Core::switchConfiguration);
|
||||
|
||||
connect(ui->addButton, SIGNAL(clicked()), this, SLOT(onAddClicked()));
|
||||
connect(ui->groupButton, SIGNAL(clicked()), this, SLOT(onGroupClicked()));
|
||||
|
@ -166,6 +187,7 @@ Widget::Widget(QWidget *parent)
|
|||
connect(setStatusAway, SIGNAL(triggered()), this, SLOT(setStatusAway()));
|
||||
connect(setStatusBusy, SIGNAL(triggered()), this, SLOT(setStatusBusy()));
|
||||
connect(&friendForm, SIGNAL(friendRequested(QString,QString)), this, SIGNAL(friendRequested(QString,QString)));
|
||||
connect(idleTimer, &QTimer::timeout, this, &Widget::onUserAway);
|
||||
|
||||
coreThread->start();
|
||||
|
||||
|
@ -212,6 +234,74 @@ void Widget::closeEvent(QCloseEvent *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;
|
||||
}
|
||||
|
||||
void Widget::setIdleTimer(int minutes)
|
||||
{
|
||||
idleTimer->start(minutes * 1000*60);
|
||||
}
|
||||
|
||||
QString Widget::getUsername()
|
||||
{
|
||||
return core->getUsername();
|
||||
|
@ -220,7 +310,7 @@ QString Widget::getUsername()
|
|||
void Widget::onAvatarClicked()
|
||||
{
|
||||
QString filename = QFileDialog::getOpenFileName(this, tr("Choose a profile picture"), QDir::homePath());
|
||||
if (filename == "")
|
||||
if (filename.isEmpty())
|
||||
return;
|
||||
QFile file(filename);
|
||||
file.open(QIODevice::ReadOnly);
|
||||
|
@ -455,6 +545,25 @@ void Widget::onFriendStatusChanged(int friendId, Status status)
|
|||
|
||||
f->friendStatus = status;
|
||||
f->widget->updateStatusLight();
|
||||
|
||||
//won't print the message if there were no messages before
|
||||
if(f->chatForm->getNumberOfMessages() != 0
|
||||
&& Settings::getInstance().getStatusChangeNotificationEnabled() == true)
|
||||
{
|
||||
QString fStatus = "";
|
||||
switch(f->friendStatus){
|
||||
case Status::Away:
|
||||
fStatus = tr("away", "contact status"); break;
|
||||
case Status::Busy:
|
||||
fStatus = tr("busy", "contact status"); break;
|
||||
case Status::Offline:
|
||||
fStatus = tr("offline", "contact status"); break;
|
||||
default:
|
||||
fStatus = tr("online", "contact status"); break;
|
||||
}
|
||||
f->chatForm->addSystemInfoMessage(tr("%1 is now %2", "e.g. \"Dubslow is now online\"").arg(f->getName()).arg(fStatus),
|
||||
"white", QDateTime::currentDateTime());
|
||||
}
|
||||
}
|
||||
|
||||
void Widget::onFriendStatusMessageChanged(int friendId, const QString& message)
|
||||
|
@ -572,19 +681,31 @@ void Widget::onFriendRequestReceived(const QString& userId, const QString& messa
|
|||
emit friendRequestAccepted(userId);
|
||||
}
|
||||
|
||||
void Widget::removeFriend(int friendId)
|
||||
void Widget::removeFriend(Friend* f)
|
||||
{
|
||||
Friend* f = FriendList::findFriend(friendId);
|
||||
f->widget->setAsInactiveChatroom();
|
||||
if (static_cast<GenericChatroomWidget*>(f->widget) == activeChatroomWidget)
|
||||
activeChatroomWidget = nullptr;
|
||||
FriendList::removeFriend(friendId);
|
||||
core->removeFriend(friendId);
|
||||
FriendList::removeFriend(f->friendId);
|
||||
core->removeFriend(f->friendId);
|
||||
delete f;
|
||||
if (ui->mainHead->layout()->isEmpty())
|
||||
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)
|
||||
{
|
||||
Friend* f = FriendList::findFriend(friendId);
|
||||
|
@ -648,19 +769,23 @@ void Widget::onGroupNamelistChanged(int groupnumber, int peernumber, uint8_t Cha
|
|||
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();
|
||||
if (static_cast<GenericChatroomWidget*>(g->widget) == activeChatroomWidget)
|
||||
activeChatroomWidget = nullptr;
|
||||
GroupList::removeGroup(groupId);
|
||||
core->removeGroup(groupId);
|
||||
GroupList::removeGroup(g->groupId);
|
||||
core->removeGroup(g->groupId);
|
||||
delete g;
|
||||
if (ui->mainHead->layout()->isEmpty())
|
||||
onAddClicked();
|
||||
}
|
||||
|
||||
void Widget::removeGroup(int groupId)
|
||||
{
|
||||
removeGroup(GroupList::findGroup(groupId));
|
||||
}
|
||||
|
||||
Core *Widget::getCore()
|
||||
{
|
||||
return core;
|
||||
|
@ -706,18 +831,49 @@ bool Widget::isFriendWidgetCurActiveWidget(Friend* f)
|
|||
|
||||
bool Widget::event(QEvent * e)
|
||||
{
|
||||
if (e->type() == QEvent::WindowActivate)
|
||||
{
|
||||
if (activeChatroomWidget != nullptr)
|
||||
{
|
||||
activeChatroomWidget->resetEventFlags();
|
||||
activeChatroomWidget->updateStatusLight();
|
||||
}
|
||||
switch(e->type()) {
|
||||
case QEvent::WindowActivate:
|
||||
if (activeChatroomWidget != nullptr)
|
||||
{
|
||||
activeChatroomWidget->resetEventFlags();
|
||||
activeChatroomWidget->updateStatusLight();
|
||||
}
|
||||
// http://qt-project.org/faq/answer/how_can_i_detect_a_period_of_no_user_interaction
|
||||
// Detecting global inactivity, like Skype, is possible but not via Qt:
|
||||
// http://stackoverflow.com/a/21905027/1497645
|
||||
case QEvent::MouseButtonPress:
|
||||
case QEvent::MouseButtonRelease:
|
||||
case QEvent::Wheel:
|
||||
case QEvent::KeyPress:
|
||||
case QEvent::KeyRelease:
|
||||
if (autoAwayActive)
|
||||
{
|
||||
qDebug() << "Widget: auto away deactivated";
|
||||
autoAwayActive = false;
|
||||
emit statusSet(Status::Online);
|
||||
int mins = Settings::getInstance().getAutoAwayTime();
|
||||
if (mins > 0)
|
||||
idleTimer->start(mins * 1000*60);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return QWidget::event(e);
|
||||
}
|
||||
|
||||
void Widget::onUserAway()
|
||||
{
|
||||
if (Settings::getInstance().getAutoAwayTime() > 0
|
||||
&& ui->statusButton->property("status").toString() == "online") // leave user-set statuses in place
|
||||
{
|
||||
qDebug() << "Widget: auto away activated";
|
||||
emit statusSet(Status::Away);
|
||||
autoAwayActive = true;
|
||||
}
|
||||
idleTimer->stop();
|
||||
}
|
||||
|
||||
void Widget::setStatusOnline()
|
||||
{
|
||||
core->setStatus(Status::Online);
|
||||
|
@ -754,3 +910,12 @@ void Widget::onGroupSendResult(int groupId, const QString& message, int result)
|
|||
if (result == -1)
|
||||
g->chatForm->addSystemInfoMessage("Message failed to send", "red", QDateTime::currentDateTime());
|
||||
}
|
||||
|
||||
void Widget::getPassword()
|
||||
{
|
||||
//QString password = QInputDialog();
|
||||
//if (password.isEmpty())
|
||||
// core->clearPassword();
|
||||
//else
|
||||
// core->setPassword(password);
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ class Core;
|
|||
class Camera;
|
||||
class FriendListWidget;
|
||||
class MaskablePixmapWidget;
|
||||
class QTimer;
|
||||
|
||||
class Widget : public QMainWindow
|
||||
{
|
||||
|
@ -56,6 +57,9 @@ public:
|
|||
void newMessageAlert();
|
||||
bool isFriendWidgetCurActiveWidget(Friend* f);
|
||||
bool getIsWindowMinimized();
|
||||
static QList<QString> searchProfiles();
|
||||
void clearContactsList();
|
||||
void setIdleTimer(int minutes);
|
||||
~Widget();
|
||||
|
||||
virtual void closeEvent(QCloseEvent *event);
|
||||
|
@ -67,6 +71,7 @@ signals:
|
|||
void statusSelected(Status status);
|
||||
void usernameChanged(const QString& username);
|
||||
void statusMessageChanged(const QString& statusMessage);
|
||||
void changeProfile(const QString& profile);
|
||||
|
||||
private slots:
|
||||
void onConnected();
|
||||
|
@ -106,13 +111,18 @@ private slots:
|
|||
void onGroupSendResult(int groupId, const QString& message, int result);
|
||||
void playRingtone();
|
||||
void onIconClick();
|
||||
void onUserAway();
|
||||
void getPassword();
|
||||
|
||||
private:
|
||||
void hideMainForms();
|
||||
virtual bool event(QEvent * e);
|
||||
Group* createGroup(int groupId);
|
||||
void removeFriend(Friend* f);
|
||||
void removeGroup(Group* g);
|
||||
QString askProfiles();
|
||||
QString detectProfile();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
QSplitter *centralLayout;
|
||||
QPoint dragPosition;
|
||||
|
@ -126,6 +136,8 @@ private:
|
|||
FriendListWidget* contactListWidget;
|
||||
MaskablePixmapWidget* profilePicture;
|
||||
bool notify(QObject *receiver, QEvent *event);
|
||||
bool autoAwayActive = false;
|
||||
QTimer* idleTimer;
|
||||
};
|
||||
|
||||
#endif // WIDGET_H
|
||||
|
|
|
@ -87,7 +87,7 @@ mv qTox-master $VERNAME
|
|||
|
||||
# Build packages
|
||||
cd $VERNAME
|
||||
./bootstrap.sh --local
|
||||
./bootstrap.sh -t
|
||||
debuild -us -uc -aamd64
|
||||
debuild -us -uc -ai386
|
||||
cd ..
|
||||
|
|
Binary file not shown.
|
@ -4,116 +4,144 @@
|
|||
<context>
|
||||
<name>AVForm</name>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/avform.cpp" line="22"/>
|
||||
<location filename="../src/widget/form/settings/avform.cpp" line="22"/>
|
||||
<source>Audio/Video settings</source>
|
||||
<translation>Impostazioni Audio/Video</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/avform.cpp" line="41"/>
|
||||
<source>Hide video preview</source>
|
||||
<comment>On a button</comment>
|
||||
<translation>Ferma webcam</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/avform.cpp" line="47"/>
|
||||
<source>Show video preview</source>
|
||||
<comment>On a button</comment>
|
||||
<translation>Prova webcam</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>AVSettings</name>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/avsettings.ui" line="14"/>
|
||||
<location filename="../src/widget/form/settings/avsettings.ui" line="14"/>
|
||||
<source>Form</source>
|
||||
<translation>Form</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/avsettings.ui" line="20"/>
|
||||
<location filename="../src/widget/form/settings/avsettings.ui" line="20"/>
|
||||
<source>Volume Settings (Stubs)</source>
|
||||
<translation>Impostazioni Volume (Stub)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/avsettings.ui" line="26"/>
|
||||
<source>Playback</source>
|
||||
<translation>Altoparlanti</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/avsettings.ui" line="40"/>
|
||||
<source>Microphone</source>
|
||||
<translation>Microfono</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/avsettings.ui" line="57"/>
|
||||
<source>Video settings</source>
|
||||
<translation>Impostazioni Video</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/avsettings.ui" line="26"/>
|
||||
<source>Show video preview</source>
|
||||
<translation>Prova webcam</translation>
|
||||
<location filename="../src/widget/form/settings/avsettings.ui" line="66"/>
|
||||
<source>Modes</source>
|
||||
<translation>Modalità</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/avsettings.ui" line="83"/>
|
||||
<source>Hue</source>
|
||||
<translation>Colore</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/avsettings.ui" line="97"/>
|
||||
<source>Brightness</source>
|
||||
<translation>Luminoistà</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/avsettings.ui" line="111"/>
|
||||
<source>Saturation</source>
|
||||
<translation>Saturazione</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/avsettings.ui" line="125"/>
|
||||
<source>Contrast</source>
|
||||
<translation>Contrasto</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/avsettings.ui" line="139"/>
|
||||
<source>Preview</source>
|
||||
<translation>Anteprima</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>AddFriendForm</name>
|
||||
<message>
|
||||
<location filename="../widget/form/addfriendform.cpp" line="34"/>
|
||||
<location filename="../src/widget/form/addfriendform.cpp" line="34"/>
|
||||
<source>Add Friends</source>
|
||||
<translation>Aggiungi Contatto</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/addfriendform.cpp" line="37"/>
|
||||
<location filename="../src/widget/form/addfriendform.cpp" line="37"/>
|
||||
<source>Tox ID</source>
|
||||
<comment>Tox ID of the person you're sending a friend request to</comment>
|
||||
<translation>Tox ID</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/addfriendform.cpp" line="38"/>
|
||||
<location filename="../src/widget/form/addfriendform.cpp" line="38"/>
|
||||
<source>Message</source>
|
||||
<comment>The message you send in friend requests</comment>
|
||||
<translation>Messaggio</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/addfriendform.cpp" line="39"/>
|
||||
<location filename="../src/widget/form/addfriendform.cpp" line="39"/>
|
||||
<source>Send friend request</source>
|
||||
<translation>Invia richiesta d'amicizia</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/addfriendform.cpp" line="40"/>
|
||||
<location filename="../src/widget/form/addfriendform.cpp" line="40"/>
|
||||
<source>Tox me maybe?</source>
|
||||
<comment>Default message in friend requests if the field is left blank. Write something appropriate!</comment>
|
||||
<translation>Permettimi di aggiungerti alla mia lista contatti</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/addfriendform.cpp" line="96"/>
|
||||
<location filename="../src/widget/form/addfriendform.cpp" line="96"/>
|
||||
<source>Please fill in a valid Tox ID</source>
|
||||
<comment>Tox ID of the friend you're sending a friend request to</comment>
|
||||
<translation>Inserisci un Tox ID valido</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/addfriendform.cpp" line="99"/>
|
||||
<location filename="../src/widget/form/addfriendform.cpp" line="99"/>
|
||||
<source>You can't add yourself as a friend!</source>
|
||||
<comment>When trying to add your own Tox ID as friend</comment>
|
||||
<translation>Non puoi aggiungere te stesso come contatto!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/addfriendform.cpp" line="116"/>
|
||||
<location filename="../src/widget/form/addfriendform.cpp" line="116"/>
|
||||
<source>This address does not exist</source>
|
||||
<comment>The DNS gives the Tox ID associated to toxme.se addresses</comment>
|
||||
<translation>Questo indirizzo non esiste</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/addfriendform.cpp" line="120"/>
|
||||
<location filename="../src/widget/form/addfriendform.cpp" line="120"/>
|
||||
<source>Error while looking up DNS</source>
|
||||
<comment>The DNS gives the Tox ID associated to toxme.se addresses</comment>
|
||||
<translation>Errore nel consultare il server DNS</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/addfriendform.cpp" line="126"/>
|
||||
<location filename="../src/widget/form/addfriendform.cpp" line="126"/>
|
||||
<source>Unexpected number of text records</source>
|
||||
<comment>Error with the DNS</comment>
|
||||
<translation>Numero inaspettato di text-records</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/addfriendform.cpp" line="132"/>
|
||||
<location filename="../src/widget/form/addfriendform.cpp" line="132"/>
|
||||
<source>Unexpected number of values in text record</source>
|
||||
<comment>Error with the DNS</comment>
|
||||
<translation>Numero inaspettato di valori nel text-record</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/addfriendform.cpp" line="139"/>
|
||||
<location filename="../src/widget/form/addfriendform.cpp" line="139"/>
|
||||
<source>The DNS lookup does not contain any Tox ID</source>
|
||||
<comment>Error with the DNS</comment>
|
||||
<translation>La risposta del server DNS non contiene nessun Tox ID</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/addfriendform.cpp" line="145"/>
|
||||
<location filename="../widget/form/addfriendform.cpp" line="151"/>
|
||||
<location filename="../src/widget/form/addfriendform.cpp" line="145"/>
|
||||
<location filename="../src/widget/form/addfriendform.cpp" line="151"/>
|
||||
<source>The DNS lookup does not contain a valid Tox ID</source>
|
||||
<comment>Error with the DNS</comment>
|
||||
<translation>La risposta del server DNS non contiene un Tox ID valido</translation>
|
||||
|
@ -122,7 +150,7 @@
|
|||
<context>
|
||||
<name>ChatForm</name>
|
||||
<message>
|
||||
<location filename="../widget/form/chatform.cpp" line="105"/>
|
||||
<location filename="../src/widget/form/chatform.cpp" line="105"/>
|
||||
<source>Send a file</source>
|
||||
<translation>Invia un file</translation>
|
||||
</message>
|
||||
|
@ -130,12 +158,12 @@
|
|||
<context>
|
||||
<name>Core</name>
|
||||
<message>
|
||||
<location filename="../core.cpp" line="1068"/>
|
||||
<location filename="../src/core.cpp" line="1104"/>
|
||||
<source>Encrypted profile</source>
|
||||
<translation>Profilo criptato</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../core.cpp" line="1069"/>
|
||||
<location filename="../src/core.cpp" line="1105"/>
|
||||
<source>Your tox profile seems to be encrypted, qTox can't open it
|
||||
Do you want to erase this profile ?</source>
|
||||
<translation>Il tuo profilo Tox sembra essere criptato, qTox non può aprirlo\nVuoi eliminare questo profilo?</translation>
|
||||
|
@ -144,19 +172,19 @@ Do you want to erase this profile ?</source>
|
|||
<context>
|
||||
<name>FileTransferInstance</name>
|
||||
<message>
|
||||
<location filename="../filetransferinstance.cpp" line="208"/>
|
||||
<location filename="../src/filetransferinstance.cpp" line="209"/>
|
||||
<source>Save a file</source>
|
||||
<comment>Title of the file saving dialog</comment>
|
||||
<translation>Salva file</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../filetransferinstance.cpp" line="219"/>
|
||||
<location filename="../src/filetransferinstance.cpp" line="220"/>
|
||||
<source>Location not writable</source>
|
||||
<comment>Title of permissions popup</comment>
|
||||
<translation>Errore</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../filetransferinstance.cpp" line="219"/>
|
||||
<location filename="../src/filetransferinstance.cpp" line="220"/>
|
||||
<source>You do not have permission to write that location. Choose another, or cancel the save dialog.</source>
|
||||
<comment>text of permissions popup</comment>
|
||||
<translation>Non hai sufficienti permessi per scrivere in questa locazione. Scegli un'altra posizione, o annulla il salvataggio.</translation>
|
||||
|
@ -165,18 +193,18 @@ Do you want to erase this profile ?</source>
|
|||
<context>
|
||||
<name>FilesForm</name>
|
||||
<message>
|
||||
<location filename="../widget/form/filesform.cpp" line="30"/>
|
||||
<location filename="../src/widget/form/filesform.cpp" line="30"/>
|
||||
<source>Transfered Files</source>
|
||||
<comment>"Headline" of the window</comment>
|
||||
<translation>Files Trasferiti</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/filesform.cpp" line="38"/>
|
||||
<location filename="../src/widget/form/filesform.cpp" line="38"/>
|
||||
<source>Downloads</source>
|
||||
<translation>Ricevuti</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/filesform.cpp" line="39"/>
|
||||
<location filename="../src/widget/form/filesform.cpp" line="39"/>
|
||||
<source>Uploads</source>
|
||||
<translation>Inviati</translation>
|
||||
</message>
|
||||
|
@ -184,34 +212,34 @@ Do you want to erase this profile ?</source>
|
|||
<context>
|
||||
<name>FriendRequestDialog</name>
|
||||
<message>
|
||||
<location filename="../widget/tool/friendrequestdialog.cpp" line="30"/>
|
||||
<location filename="../src/widget/tool/friendrequestdialog.cpp" line="30"/>
|
||||
<source>Friend request</source>
|
||||
<comment>Title of the window to aceept/deny a friend request</comment>
|
||||
<translation>Richiesta d'amicizia</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/tool/friendrequestdialog.cpp" line="32"/>
|
||||
<location filename="../src/widget/tool/friendrequestdialog.cpp" line="32"/>
|
||||
<source>Someone wants to make friends with you</source>
|
||||
<translation>Qualcuno vuole chattare con te</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/tool/friendrequestdialog.cpp" line="33"/>
|
||||
<location filename="../src/widget/tool/friendrequestdialog.cpp" line="33"/>
|
||||
<source>User ID:</source>
|
||||
<translation>ID Utente:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/tool/friendrequestdialog.cpp" line="37"/>
|
||||
<location filename="../src/widget/tool/friendrequestdialog.cpp" line="37"/>
|
||||
<source>Friend request message:</source>
|
||||
<translation>Messaggio della richiesta d'amicizia:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/tool/friendrequestdialog.cpp" line="44"/>
|
||||
<location filename="../src/widget/tool/friendrequestdialog.cpp" line="44"/>
|
||||
<source>Accept</source>
|
||||
<comment>Accept a friend request</comment>
|
||||
<translation>Accetta</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/tool/friendrequestdialog.cpp" line="45"/>
|
||||
<location filename="../src/widget/tool/friendrequestdialog.cpp" line="45"/>
|
||||
<source>Reject</source>
|
||||
<comment>Reject a friend request</comment>
|
||||
<translation>Rifiuta</translation>
|
||||
|
@ -220,19 +248,19 @@ Do you want to erase this profile ?</source>
|
|||
<context>
|
||||
<name>FriendWidget</name>
|
||||
<message>
|
||||
<location filename="../widget/friendwidget.cpp" line="48"/>
|
||||
<location filename="../src/widget/friendwidget.cpp" line="48"/>
|
||||
<source>Copy friend ID</source>
|
||||
<comment>Menu to copy the Tox ID of that friend</comment>
|
||||
<translation>Copia Tox ID del contatto</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/friendwidget.cpp" line="49"/>
|
||||
<location filename="../src/widget/friendwidget.cpp" line="49"/>
|
||||
<source>Invite in group</source>
|
||||
<comment>Menu to invite a friend in a groupchat</comment>
|
||||
<translation>Invita nel gruppo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/friendwidget.cpp" line="59"/>
|
||||
<location filename="../src/widget/friendwidget.cpp" line="59"/>
|
||||
<source>Remove friend</source>
|
||||
<comment>Menu to remove the friend from our friendlist</comment>
|
||||
<translation>Rimuovi contatto</translation>
|
||||
|
@ -241,7 +269,7 @@ Do you want to erase this profile ?</source>
|
|||
<context>
|
||||
<name>GeneralForm</name>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/generalform.cpp" line="26"/>
|
||||
<location filename="../src/widget/form/settings/generalform.cpp" line="26"/>
|
||||
<source>General Settings</source>
|
||||
<translation>Impostazioni Generali</translation>
|
||||
</message>
|
||||
|
@ -249,79 +277,84 @@ Do you want to erase this profile ?</source>
|
|||
<context>
|
||||
<name>GeneralSettings</name>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/generalsettings.ui" line="14"/>
|
||||
<location filename="../src/widget/form/settings/generalsettings.ui" line="14"/>
|
||||
<source>Form</source>
|
||||
<translation>Form</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/generalsettings.ui" line="29"/>
|
||||
<location filename="../src/widget/form/settings/generalsettings.ui" line="29"/>
|
||||
<source>General Settings</source>
|
||||
<translation>Impostazioni Generali</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/generalsettings.ui" line="74"/>
|
||||
<location filename="../src/widget/form/settings/generalsettings.ui" line="81"/>
|
||||
<source>Connection Settings</source>
|
||||
<translation>Impostazioni Connessione</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/generalsettings.ui" line="80"/>
|
||||
<location filename="../src/widget/form/settings/generalsettings.ui" line="87"/>
|
||||
<source>Enable IPv6 (recommended)</source>
|
||||
<extracomment>Text on a checkbox to enable IPv6</extracomment>
|
||||
<translation>Abilita IPv6 (consigliato)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/generalsettings.ui" line="35"/>
|
||||
<location filename="../src/widget/form/settings/generalsettings.ui" line="35"/>
|
||||
<source>Use translations</source>
|
||||
<extracomment>Text on a checkbox to enable translations</extracomment>
|
||||
<translation>Abilita traduzioni</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/generalsettings.ui" line="42"/>
|
||||
<location filename="../src/widget/form/settings/generalsettings.ui" line="42"/>
|
||||
<source>Save settings to the working directory instead of the usual conf dir</source>
|
||||
<extracomment>describes makeToxPortable checkbox</extracomment>
|
||||
<translation>Slava le impostazioni nella directory di lavoro corrente, invece della directory di default</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/generalsettings.ui" line="45"/>
|
||||
<location filename="../src/widget/form/settings/generalsettings.ui" line="45"/>
|
||||
<source>Make Tox portable</source>
|
||||
<translation>Rendi qTox portabile</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/generalsettings.ui" line="55"/>
|
||||
<location filename="../src/widget/form/settings/generalsettings.ui" line="52"/>
|
||||
<source>Start in tray</source>
|
||||
<translation>Avvia minimizzato</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/generalsettings.ui" line="62"/>
|
||||
<source>Theme</source>
|
||||
<translation>Impostazioni Tema</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/generalsettings.ui" line="61"/>
|
||||
<location filename="../src/widget/form/settings/generalsettings.ui" line="68"/>
|
||||
<source>Smiley Pack</source>
|
||||
<extracomment>Text on smiley pack label</extracomment>
|
||||
<translation>Emoticons</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/generalsettings.ui" line="97"/>
|
||||
<location filename="../src/widget/form/settings/generalsettings.ui" line="104"/>
|
||||
<source>Use proxy (SOCKS5)</source>
|
||||
<translation>Usa proxy (SOCKS5)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/generalsettings.ui" line="106"/>
|
||||
<location filename="../src/widget/form/settings/generalsettings.ui" line="113"/>
|
||||
<source>Address</source>
|
||||
<extracomment>Text on proxy addr label</extracomment>
|
||||
<translation>IP</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/generalsettings.ui" line="116"/>
|
||||
<location filename="../src/widget/form/settings/generalsettings.ui" line="123"/>
|
||||
<source>Port</source>
|
||||
<extracomment>Text on proxy port label</extracomment>
|
||||
<translation>Porta</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/generalsettings.ui" line="90"/>
|
||||
<location filename="../src/widget/form/settings/generalsettings.ui" line="97"/>
|
||||
<source>Disable UDP (not recommended)</source>
|
||||
<extracomment>Text on checkbox to disable UDP</extracomment>
|
||||
<translation>Disabilita connessioni UDP (non raccomandato)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/generalsettings.ui" line="87"/>
|
||||
<location filename="../src/widget/form/settings/generalsettings.ui" line="94"/>
|
||||
<source>This allows, e.g., toxing over Tor. It adds load to the Tox network however, so use only when necessary.</source>
|
||||
<extracomment>force tcp checkbox tooltip</extracomment>
|
||||
<translation>Questo permette di usare qTox con Tor; tuttavia aggiunge carico alla rete Tox, quindi usalo solo se necessario.</translation>
|
||||
|
@ -330,8 +363,8 @@ Do you want to erase this profile ?</source>
|
|||
<context>
|
||||
<name>GenericChatForm</name>
|
||||
<message>
|
||||
<location filename="../widget/form/genericchatform.cpp" line="149"/>
|
||||
<location filename="../widget/form/genericchatform.cpp" line="155"/>
|
||||
<location filename="../src/widget/form/genericchatform.cpp" line="149"/>
|
||||
<location filename="../src/widget/form/genericchatform.cpp" line="155"/>
|
||||
<source>Save chat log</source>
|
||||
<translation>Salva il log della chat</translation>
|
||||
</message>
|
||||
|
@ -339,13 +372,13 @@ Do you want to erase this profile ?</source>
|
|||
<context>
|
||||
<name>GroupChatForm</name>
|
||||
<message>
|
||||
<location filename="../widget/form/groupchatform.cpp" line="47"/>
|
||||
<location filename="../src/widget/form/groupchatform.cpp" line="47"/>
|
||||
<source>%1 users in chat</source>
|
||||
<comment>Number of users in chat</comment>
|
||||
<translation>%1 utenti in chat</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/groupchatform.cpp" line="85"/>
|
||||
<location filename="../src/widget/form/groupchatform.cpp" line="85"/>
|
||||
<source>%1 users in chat</source>
|
||||
<translation>%1 utenti in chat</translation>
|
||||
</message>
|
||||
|
@ -353,19 +386,19 @@ Do you want to erase this profile ?</source>
|
|||
<context>
|
||||
<name>GroupWidget</name>
|
||||
<message>
|
||||
<location filename="../widget/groupwidget.cpp" line="39"/>
|
||||
<location filename="../widget/groupwidget.cpp" line="59"/>
|
||||
<location filename="../src/widget/groupwidget.cpp" line="39"/>
|
||||
<location filename="../src/widget/groupwidget.cpp" line="59"/>
|
||||
<source>%1 users in chat</source>
|
||||
<translation>%1 utenti in chat</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/groupwidget.cpp" line="41"/>
|
||||
<location filename="../widget/groupwidget.cpp" line="61"/>
|
||||
<location filename="../src/widget/groupwidget.cpp" line="41"/>
|
||||
<location filename="../src/widget/groupwidget.cpp" line="61"/>
|
||||
<source>0 users in chat</source>
|
||||
<translation>0 utenti in chat</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/groupwidget.cpp" line="48"/>
|
||||
<location filename="../src/widget/groupwidget.cpp" line="48"/>
|
||||
<source>Quit group</source>
|
||||
<comment>Menu to quit a groupchat</comment>
|
||||
<translation>Esci dal gruppo</translation>
|
||||
|
@ -374,88 +407,188 @@ Do you want to erase this profile ?</source>
|
|||
<context>
|
||||
<name>IdentityForm</name>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/identityform.cpp" line="29"/>
|
||||
<location filename="../src/widget/form/settings/identityform.cpp" line="33"/>
|
||||
<source>Your identity</source>
|
||||
<translation>Il tuo profilo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/identityform.cpp" line="117"/>
|
||||
<source>Rename "%1"</source>
|
||||
<comment>renaming a profile</comment>
|
||||
<translation>Rinomina "%1"</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/identityform.cpp" line="132"/>
|
||||
<source>Export profile</source>
|
||||
<comment>save dialog title</comment>
|
||||
<translation>Esporta profilo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/identityform.cpp" line="134"/>
|
||||
<source>Tox save file (*.tox)</source>
|
||||
<comment>save dialog filter</comment>
|
||||
<translation>Tox save file (*.tox)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/identityform.cpp" line="143"/>
|
||||
<source>Profile currently loaded</source>
|
||||
<comment>current profile deletion warning title</comment>
|
||||
<translation>Profilo attualmente in uso</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/identityform.cpp" line="143"/>
|
||||
<source>This profile is currently in use. Please load a different profile before deleting this one.</source>
|
||||
<comment>current profile deletion warning text</comment>
|
||||
<translation>Questo profilo è attualmente in uso. Per favore carica un profilo differente prima di eliminare questo.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/identityform.cpp" line="148"/>
|
||||
<source>Deletion imminent!</source>
|
||||
<comment>deletion confirmation title</comment>
|
||||
<translation>Eliminazione imminente!</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/identityform.cpp" line="148"/>
|
||||
<source>Are you sure you want to delete this profile?</source>
|
||||
<comment>deletion confirmation text</comment>
|
||||
<translation>Sei sicuro di voler eliminare questo profilo?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/identityform.cpp" line="160"/>
|
||||
<source>Import profile</source>
|
||||
<comment>import dialog title</comment>
|
||||
<translation>Importa profilo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/identityform.cpp" line="160"/>
|
||||
<source>Tox save file (*.tox)</source>
|
||||
<comment>import dialog filter</comment>
|
||||
<translation>Tox save file (*.tox)</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>IdentitySettings</name>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/identitysettings.ui" line="14"/>
|
||||
<location filename="../src/widget/form/settings/identitysettings.ui" line="14"/>
|
||||
<source>Form</source>
|
||||
<translation>Form</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/identitysettings.ui" line="20"/>
|
||||
<location filename="../src/widget/form/settings/identitysettings.ui" line="20"/>
|
||||
<source>Public Information</source>
|
||||
<translation>Informazioni Pubbliche</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/identitysettings.ui" line="26"/>
|
||||
<location filename="../src/widget/form/settings/identitysettings.ui" line="26"/>
|
||||
<source>Name</source>
|
||||
<translation>Nome</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/identitysettings.ui" line="36"/>
|
||||
<location filename="../src/widget/form/settings/identitysettings.ui" line="36"/>
|
||||
<source>Status</source>
|
||||
<translation>Stato</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/identitysettings.ui" line="49"/>
|
||||
<location filename="../src/widget/form/settings/identitysettings.ui" line="49"/>
|
||||
<source>Tox ID</source>
|
||||
<translation>Tox ID</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/identitysettings.ui" line="55"/>
|
||||
<location filename="../src/widget/form/settings/identitysettings.ui" line="55"/>
|
||||
<source>Your Tox ID (click to copy)</source>
|
||||
<translation>(clicca qui per copiare)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/identitysettings.ui" line="65"/>
|
||||
<source>Profiles</source>
|
||||
<translation>Profili</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/identitysettings.ui" line="73"/>
|
||||
<source>Available profiles:</source>
|
||||
<translation>Profili disponibili:</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/identitysettings.ui" line="87"/>
|
||||
<source>Load</source>
|
||||
<comment>load profile button</comment>
|
||||
<translation>Carica</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/identitysettings.ui" line="94"/>
|
||||
<source>Rename</source>
|
||||
<comment>rename profile button</comment>
|
||||
<translation>Rinomina</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/identitysettings.ui" line="101"/>
|
||||
<source>Export</source>
|
||||
<comment>export profile button</comment>
|
||||
<translation>Esporta</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/identitysettings.ui" line="108"/>
|
||||
<source>Delete</source>
|
||||
<comment>delete profile button</comment>
|
||||
<translation>Elimina</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/identitysettings.ui" line="111"/>
|
||||
<source>This is useful to remain safe on public computers</source>
|
||||
<comment>delete profile button tooltip</comment>
|
||||
<translation>Utile per preservare la tua sicurezza su computer pubblici</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/form/settings/identitysettings.ui" line="120"/>
|
||||
<source>Import a profile</source>
|
||||
<comment>import profile button</comment>
|
||||
<translation>Importa un profilo</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MainWindow</name>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="20"/>
|
||||
<location filename="../src/mainwindow.ui" line="20"/>
|
||||
<source>qTox</source>
|
||||
<translation>qTox</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="859"/>
|
||||
<location filename="../src/mainwindow.ui" line="859"/>
|
||||
<source>Your name</source>
|
||||
<translation>qTox User</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="941"/>
|
||||
<location filename="../src/mainwindow.ui" line="941"/>
|
||||
<source>Your status</source>
|
||||
<translation>Toxing on qTox</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="1089"/>
|
||||
<location filename="../src/mainwindow.ui" line="1089"/>
|
||||
<source>Add friends</source>
|
||||
<translation>Aggiungi contatto</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="1115"/>
|
||||
<location filename="../src/mainwindow.ui" line="1115"/>
|
||||
<source>Create a group chat</source>
|
||||
<translation>Crea un gruppo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="1147"/>
|
||||
<location filename="../src/mainwindow.ui" line="1147"/>
|
||||
<source>View completed file transfers</source>
|
||||
<translation>Visualizza i trasferimenti completati</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="1179"/>
|
||||
<location filename="../src/mainwindow.ui" line="1179"/>
|
||||
<source>Change your settings</source>
|
||||
<translation>Cambia le impostazioni</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="1761"/>
|
||||
<location filename="../src/mainwindow.ui" line="1761"/>
|
||||
<source>Close</source>
|
||||
<translation>Chiudi</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../mainwindow.ui" line="1764"/>
|
||||
<location filename="../src/mainwindow.ui" line="1764"/>
|
||||
<source>Ctrl+Q</source>
|
||||
<translation>Ctrl+Q</translation>
|
||||
</message>
|
||||
|
@ -463,80 +596,81 @@ Do you want to erase this profile ?</source>
|
|||
<context>
|
||||
<name>PrivacyForm</name>
|
||||
<message>
|
||||
<location filename="../widget/form/settings/privacyform.cpp" line="21"/>
|
||||
<location filename="../src/widget/form/settings/privacyform.cpp" line="21"/>
|
||||
<source>Privacy settings</source>
|
||||
<translation>Impostazioni privacy</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>SelfCamView</name>
|
||||
<message>
|
||||
<location filename="../widget/selfcamview.cpp" line="33"/>
|
||||
<source>Tox video test</source>
|
||||
<comment>Title of the window to test the video/webcam</comment>
|
||||
<translation>qTox video test</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Widget</name>
|
||||
<message>
|
||||
<location filename="../widget/widget.cpp" line="88"/>
|
||||
<location filename="../src/widget/widget.cpp" line="90"/>
|
||||
<source>Online</source>
|
||||
<comment>Button to set your status to 'Online'</comment>
|
||||
<translation>Online</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/widget.cpp" line="90"/>
|
||||
<location filename="../src/widget/widget.cpp" line="92"/>
|
||||
<source>Away</source>
|
||||
<comment>Button to set your status to 'Away'</comment>
|
||||
<translation>Assente</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/widget.cpp" line="92"/>
|
||||
<location filename="../src/widget/widget.cpp" line="94"/>
|
||||
<source>Busy</source>
|
||||
<comment>Button to set your status to 'Busy'</comment>
|
||||
<translation>Occupato</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/widget.cpp" line="225"/>
|
||||
<location filename="../src/widget/widget.cpp" line="264"/>
|
||||
<source>Choose a profile</source>
|
||||
<translation>Scegli un profilo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/widget.cpp" line="265"/>
|
||||
<source>Please choose which identity to use</source>
|
||||
<translation>Per favore scegli quale identità usare</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../src/widget/widget.cpp" line="286"/>
|
||||
<source>Choose a profile picture</source>
|
||||
<translation>Scegli un'immagine per il profilo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/widget.cpp" line="232"/>
|
||||
<location filename="../widget/widget.cpp" line="239"/>
|
||||
<location filename="../widget/widget.cpp" line="260"/>
|
||||
<location filename="../src/widget/widget.cpp" line="293"/>
|
||||
<location filename="../src/widget/widget.cpp" line="300"/>
|
||||
<location filename="../src/widget/widget.cpp" line="321"/>
|
||||
<source>Error</source>
|
||||
<translation>Errore</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/widget.cpp" line="232"/>
|
||||
<location filename="../src/widget/widget.cpp" line="293"/>
|
||||
<source>Unable to open this file</source>
|
||||
<translation>Impossibile aprire il file</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/widget.cpp" line="239"/>
|
||||
<location filename="../src/widget/widget.cpp" line="300"/>
|
||||
<source>Unable to read this image</source>
|
||||
<translation>Impossibile leggere l'immagine</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/widget.cpp" line="260"/>
|
||||
<location filename="../src/widget/widget.cpp" line="321"/>
|
||||
<source>This image is too big</source>
|
||||
<translation>L'immagine è troppo grande</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/widget.cpp" line="287"/>
|
||||
<location filename="../src/widget/widget.cpp" line="348"/>
|
||||
<source>Toxcore failed to start, the application will terminate after you close this message.</source>
|
||||
<translation>Impossibile avviare Toxcore.\nqTox terminerà dopo che avrai chiuso questo messaggio.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/widget.cpp" line="296"/>
|
||||
<location filename="../src/widget/widget.cpp" line="357"/>
|
||||
<source>toxcore failed to start with your proxy settings. qTox cannot run; please modify your settings and restart.</source>
|
||||
<comment>popup text</comment>
|
||||
<translation>Impossibile avviare Toxcore con le tue impostazione proxy.\nqTox non può funzionare correttamente, per favore modifica le impostazioni e riavvia il programma.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../widget/widget.cpp" line="611"/>
|
||||
<location filename="../src/widget/widget.cpp" line="712"/>
|
||||
<source><Unknown></source>
|
||||
<comment>Placeholder when we don't know someone's name in a group chat</comment>
|
||||
<translation><Sconosciuto></translation>
|
||||
|
|
|
@ -41,7 +41,7 @@ div.green {
|
|||
margin-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
margin-left: 0px;
|
||||
margin-right: 12px;
|
||||
margin-right: 0px;
|
||||
color: @white;
|
||||
background-color: @green;
|
||||
font: @small;
|
||||
|
@ -51,7 +51,7 @@ div.silver {
|
|||
margin-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
margin-left: 0px;
|
||||
margin-right: 12px;
|
||||
margin-right: 0px;
|
||||
color: @black;
|
||||
background-color: @lightGrey;
|
||||
font: @small;
|
||||
|
@ -61,7 +61,7 @@ div.red {
|
|||
margin-top: 12px;
|
||||
margin-bottom: 12px;
|
||||
margin-left: 0px;
|
||||
margin-right: 12px;
|
||||
margin-right: 0px;
|
||||
color: @white;
|
||||
background-color: @red;
|
||||
font: @small;
|
||||
|
|
|
@ -11,7 +11,11 @@ QLabel
|
|||
QGroupBox::title
|
||||
{
|
||||
color: black;
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
QGroupBox
|
||||
{
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
QWidget
|
||||
|
|
Loading…
Reference in New Issue
Block a user