diff --git a/INSTALL.md b/INSTALL.md
index b03f17c7e..40d3fa0d2 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -230,45 +230,18 @@ The following steps assume that MinGW is installed at "C:\MinGW". If you decided
###Setting up Path
-Add MinGW/MSYS binaries to the system path to make them globally accessible.
+Add MinGW/MSYS/CMake binaries to the system path to make them globally accessible.
Open Control Panel -> System and Security -> System -> Advanced system settings -> Environment Variables...
In the second box search for the PATH variable and press Edit...
The input box "Variable value:" should already contain some directories. Each directory is separated with a semicolon.
-Extend the input box by adding ";C:\MinGW\bin;C:\MinGW\msys\1.0\bin". The very first semicolon must only be added if it is missing.
+Extend the input box by adding ";C:\MinGW\bin;C:\MinGW\msys\1.0\bin;C:\Program Files (x86)\CMake 2.8\bin".
+The very first semicolon must only be added if it is missing. CMake may be added by installer automatically.
###Cloning the Repository
Clone the repository (https://github.com/tux3/qTox.git) with your preferred Git client. [SmartGit](http://www.syntevo.com/smartgit/) is very nice for this task.
The following steps assume that you cloned the repository at "C:\qTox". If you decided to choose another location, replace corresponding parts.
-###Tox Core
-
-[jenkins.libtoxcore.so](http://jenkins.libtoxcore.so/job/libtoxcore-win32-i686/lastSuccessfulBuild/artifact/libtoxcore-win32-i686.zip)
-provides a prebuild package of Tox Core. Download this package and extract its content to "C:\qTox\libs". You may have to create the directory "libs".
-If you prefer to compile Tox Core on your own follow the instructions at https://github.com/irungentoo/toxcore/blob/master/INSTALL.md#windows
-
-###OpenCV
-
-Unfortunately there are no prebuild packages for OpenCV compiled with MinGW. Thus, you have to create your own.
-First of all download and install the most recent version of CMake from
-[cmake.org](http://www.cmake.org/cmake/resources/software.html).
-Afterwards download OpenCV in version 2.4.9 from [sourceforge.net](http://sourceforge.net/projects/opencvlibrary/files/opencv-unix/2.4.9/opencv-2.4.9.zip/download) and extract the content of the source archive to "C:\qTox\libs". Furthermore, create a new directory named "opencv-build" in "C:\qTox\libs".
-Now you should have the two directories "opencv-2.4.9" and "opencv-build" inside your "C:\qTox\libs" directory.
-
-Run CMake (cmake-gui) and set up the input boxes "Where is the source code:" and "Where to build the binaries" with "C:\qTox\libs\opencv-2.4.9" and "C:\qTox\libs\opencv-build". Press configure and choose "MSYS Makefiles" in the drop down menu with "Use default native compilers". To start initial configuration press Finish. Given that qTox only needs some components of OpenCV it's recommended to disable not required modules. Furthermore, this will decrease compilation time of OpenCV dramatically. Each module begins with "BUILD_opencv_" and can be disabled by deselecting its entry. Use the "Search" input box for convenience. Disable all modules except of "core", "highgui" and "imgproc" (highgui depends on imgproc and will automatically be disabled if imgproc is disabled). For maximum performance search for "CMAKE_BUILD_TYPE" and set this value to "Release". Finally, make sure "CMAKE_INSTALL_PREFIX" points to "C:\qTox\libs\opencv-build\install" (should be by default). To update the configuration press Configure again. To generate the Makefiles press Generate.
-
-Open a new command prompt within "C:\qTox\libs\opencv-build" (HINT: Use shift + right click -> "Open command window here" on the directory within Windows Explorer). Compile and install OpenCV with the following command. It's not recommended to use -j for multicore compilation, because it freezes the terminal from time to time.
-```bash
-make
-make install
-```
-
-After OpenCV was successfully installed to "C:\qTox\libs\opencv-build\install" copy the dlls "libopencv_core249.dll", "libopencv_highgui249.dll" and "libopencv_imgproc249.dll" located at "C:\qTox\libs\opencv-build\install\x86\mingw\bin" to "C:\qTox\libs\lib". Afterwards copy the content of the directory "C:\qTox\libs\opencv-build\install\include" to "C:\qTox\libs\include". Finally, you have to patch the file "C:\qTox\libs\include\opencv2\opencv.hpp" because it includes all modules of OpenCV regardless of your configuration. Open this file with your preferred text editor and remove all includes except of "opencv2/core/core_c.h", "opencv2/core/core.hpp", "opencv2/imgproc/imgproc_c.h", "opencv2/imgproc/imgproc.hpp", "opencv2/highgui/highgui_c.h" and "opencv2/highgui/highgui.hpp". OpenCV is now ready to use. Feel free to delete the directories "opencv-2.4.9" and "opencv-build", but you don't need to.
-
-###OpenAL Soft
-As for OpenCV there are no prebuild packages of OpenAL Softe compiled with MinGW, but the installation process is very similar to OpenCV. Download the most recent source archive of OpenAL Soft from [http://kcat.strangesoft.net](http://kcat.strangesoft.net/openal.html#download). Extract its content to "C:\qTox\libs". Besides the source folder itself you'll find the file "pax_global_header". It is not required and can be deleted. Create the directory "openal-build" next to source folder. Now you should have the two directories "openal-soft-x.y.z" where x.y.z is the version of OpenAL and "openal-build" inside your "C:\qTox\libs" directory. Run CMake (cmake-gui) and setup the source and build location. Run the initial configuration and use "MSYS Makefiles" with "Use default native compilers". The only thing you need to configure is "CMAKE_INSTALL_PREFIX" which does not point to "C:\qTox\libs\openal-build\install" by default. Configure the project and generate the Makefiles. Compile and install OpenAL Soft with:
-```bash
-make
-make install
-```
-Copy the dll "OpenAL32.dll" located at "C:\qTox\libs\openal-build\install\bin" to "C:\qTox\libs\lib". Finally, copy the directory "AL" located at "C:\qTox\libs\openal-build\install\include" to "C:\qTox\libs\include". Unlike OpenCV you don't need to patch any files. Feel free to delete the directories "openal-soft-x.y.z" and "openal-build", but you don't need to.
\ No newline at end of file
+### Getting dependencies
+Run bootstrap.bat in cloned C:\qTox directory
+Script will download rest of dependencies compile them and put to appropriate directories.
diff --git a/README.md b/README.md
index 2c55936ed..a99c8f526 100644
--- a/README.md
+++ b/README.md
@@ -20,9 +20,10 @@ qTox is a powerful Tox client that tries to follow the Tox design guidelines whi
This client runs on Windows, Linux and Mac natively.
-Windows 64 bit download
-Windows 32 bit download (for older hardware)
-Mac OS X download
+
+Windows 64 bit download
+Windows 32 bit download (for older hardware)
+Mac OS X download
Linux binary download
Linux packages
@@ -37,6 +38,6 @@ This client runs on Windows, Linux and Mac natively.
##Developer overview:
-[GitStats](http://104.219.184.93/index.html)
+[GitStats](https://tux3-dev.tox.im/)
[Mac & Linux jenkins](https://jenkins.libtoxcore.so/user/tux3/my-views/view/qTox/)
-[Windows jenkins](http://104.219.184.93:8080)
+[Windows jenkins](https://tux3-dev.tox.im/jenkins)
diff --git a/bootstrap.bat b/bootstrap.bat
index 09178b958..9ed12d602 100644
--- a/bootstrap.bat
+++ b/bootstrap.bat
@@ -1,4 +1,4 @@
-@mkdir %~dp0libs
-%~dp0tools\wget --no-check-certificate http://jenkins.libtoxcore.so/job/libtoxcore-win32-i686/lastSuccessfulBuild/artifact/libtoxcore-win32-i686.zip -O %~dp0libs\libtoxcore-latest.zip
-%~dp0tools\unzip -o %~dp0libs\libtoxcore-latest.zip -d %~dp0libs\
-@del %~dp0libs\libtoxcore-latest.zip
\ No newline at end of file
+@echo off
+
+sh bootstrap.sh
+@pause
diff --git a/bootstrap.sh b/bootstrap.sh
index d705a02c0..c5e7d2f61 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -1,5 +1,12 @@
#!/bin/bash
+WINDOWS_VERSION=$(cmd.exe /c ver 2>/dev/null | grep "Microsoft Windows")
+if [ ! -z "$WINDOWS_VERSION" ]; then
+ cd windows
+ ./bootstrap.sh
+ exit $?
+fi
+
################ parameters ################
# directory where the script is located
SCRIPT_DIR=$( cd $(dirname $0); pwd -P)
@@ -67,7 +74,7 @@ while [ $# -ge 1 ] ; do
echo ""
fi
- # print help
+ # print help
echo "Use this script to install/update libsodium and libtoxcore in ${INSTALL_DIR}"
echo ""
echo "usage:"
diff --git a/install_libfilteraudio.sh b/install_libfilteraudio.sh
index 010bcbbac..fb36f7330 100755
--- a/install_libfilteraudio.sh
+++ b/install_libfilteraudio.sh
@@ -14,6 +14,17 @@ else
INCLUDE_DIR="$2/include/"
fi
+WINDOWS_VERSION=$(cmd.exe /c ver 2>/dev/null | grep "Microsoft Windows")
+if [ ! -z "$WINDOWS_VERSION" ]; then
+ EXT="dll"
+ BIN_DIR="$2/bin/"
+ STATIC_EXT="$EXT.a"
+else
+ BIN_DIR=$LIB_DIR
+ EXT="so"
+ STATIC_EXT="a"
+fi
+
echo "Cloning filter_audio from GitHub.com"
git clone https://github.com/irungentoo/filter_audio.git $SOURCE_DIR
@@ -22,16 +33,21 @@ cd $SOURCE_DIR
gcc -c -fPIC filter_audio.c aec/*.c agc/*.c ns/*.c other/*.c -lm -lpthread
echo "Creating shared object file"
-gcc *.o -shared -o libfilteraudio.so
+gcc *.o -shared -o libfilteraudio.$EXT -Wl,--out-implib,libfilteraudio.$STATIC_EXT
echo "Cleaning up"
rm *.o
-muhcmd="cp libfilteraudio.so $LIB_DIR"
+muhcmd="cp libfilteraudio.$EXT $BIN_DIR"
[ -z "$2" ] && muhcmd="sudo $muhcmd"
echo "Installing libfilteraudio.so with $muhcmd"
$muhcmd
+muhcmd="cp libfilteraudio.$STATIC_EXT $LIB_DIR"
+[ -z "$2" ] && muhcmd="sudo $muhcmd"
+echo "Installing libfilteraudio.$STATIC_EXT with $muhcmd"
+$muhcmd
+
muhcmd="cp *.h $INCLUDE_DIR"
[ -z "$2" ] && muhcmd="sudo $muhcmd"
echo "Installing include files with $muhcmd"
diff --git a/qtox.pro b/qtox.pro
index f1cdfb7ae..026c8a247 100644
--- a/qtox.pro
+++ b/qtox.pro
@@ -54,6 +54,23 @@ TIMESTAMP = $$system($1 2>null||echo 0||a;rm null;date +%s||echo 0) # I'm so sor
DEFINES += TIMESTAMP=$$TIMESTAMP
DEFINES += LOG_TO_FILE
+contains(ENABLE_SYSTRAY_UNITY_BACKEND, YES) {
+ DEFINES += ENABLE_SYSTRAY_UNITY_BACKEND
+
+ INCLUDEPATH += "/usr/include/libappindicator-0.1"
+ INCLUDEPATH += "/usr/include/gtk-2.0"
+ INCLUDEPATH += "/usr/include/glib-2.0"
+ INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/glib-2.0/include"
+ INCLUDEPATH += "/usr/include/cairo"
+ INCLUDEPATH += "/usr/include/pango-1.0"
+ INCLUDEPATH += "/usr/lib/x86_64-linux-gnu/gtk-2.0/include"
+ INCLUDEPATH += "/usr/include/gdk-pixbuf-2.0"
+ INCLUDEPATH += "/usr/include/atk-1.0"
+ INCLUDEPATH += "/usr/include/libdbusmenu-glib-0.4"
+
+ LIBS += -lgobject-2.0 -lappindicator -lgtk-x11-2.0
+}
+
contains(DISABLE_PLATFORM_EXT, YES) {
} else {
@@ -75,9 +92,9 @@ contains(JENKINS,YES) {
# Rules for Windows, Mac OSX, and Linux
win32 {
RC_FILE = windows/qtox.rc
- LIBS += -liphlpapi -L$$PWD/libs/lib -lsodium -ltoxav -ltoxcore -ltoxencryptsave -ltoxdns -lvpx -lpthread
- LIBS += -L$$PWD/libs/lib -lopencv_core248 -lopencv_highgui248 -lopencv_imgproc248 -lOpenAL32 -lopus
- LIBS += -lopengl32 -lole32 -loleaut32 -luuid -lvfw32 -ljpeg -ltiff -lpng -ljasper -lIlmImf -lHalf -lws2_32 -lz
+ LIBS += -L$$PWD/libs/lib -ltoxav -ltoxcore -ltoxencryptsave -ltoxdns -lsodium -lvpx -lpthread
+ LIBS += -L$$PWD/libs/lib -lopencv_core249 -lopencv_highgui249 -lopencv_imgproc249 -lOpenAL32 -lopus
+ LIBS += -lopengl32 -lole32 -loleaut32 -luuid -lvfw32 -lws2_32 -liphlpapi -lz
contains(DEFINES, QTOX_FILTER_AUDIO) {
contains(STATICPKG, YES) {
@@ -195,7 +212,9 @@ HEADERS += src/widget/form/addfriendform.h \
src/chatlog/content/notificationicon.h \
src/chatlog/content/timestamp.h \
src/chatlog/documentcache.h \
- src/chatlog/pixmapcache.h
+ src/chatlog/pixmapcache.h \
+ src/widget/callconfirmwidget.h \
+ src/widget/systemtrayicon.h \
SOURCES += \
src/widget/form/addfriendform.cpp \
@@ -268,7 +287,9 @@ SOURCES += \
src/chatlog/content/notificationicon.cpp \
src/chatlog/content/timestamp.cpp \
src/chatlog/documentcache.cpp \
- src/chatlog/pixmapcache.cpp
+ src/chatlog/pixmapcache.cpp \
+ src/widget/callconfirmwidget.cpp \
+ src/widget/systemtrayicon.cpp
contains(DEFINES, QTOX_FILTER_AUDIO) {
HEADERS += src/audiofilterer.h
diff --git a/res.qrc b/res.qrc
index de2986aa8..1fe9d0f92 100644
--- a/res.qrc
+++ b/res.qrc
@@ -124,6 +124,7 @@
translations/fi.qm
translations/fr.qm
translations/it.qm
+ translations/lt.qm
translations/mannol.qm
translations/pirate.qm
translations/pl.qm
@@ -226,5 +227,8 @@
ui/fileTransferInstance/arrow_white.svg
ui/fileTransferInstance/browse.svg
ui/fileTransferInstance/filetransferWidget.css
+ ui/acceptCall/acceptCall.png
+ ui/rejectCall/rejectCall.png
+ ui/volButton/volButtonDisabled.png
diff --git a/simple_make.sh b/simple_make.sh
index 23a8682ac..9f954d7f6 100755
--- a/simple_make.sh
+++ b/simple_make.sh
@@ -6,8 +6,8 @@ if which apt-get; then
elif which pacman; then
sudo pacman -S --needed base-devel qt5 opencv openal opus libvpx libxss
elif which yum; then
- yum groupinstall "Development Tools"
- yum install qt-devel qt-doc qt-creator opencv-devel openal-soft-devel libtool autoconf automake check check-devel libXScrnSaver-devel
+ sudo yum groupinstall "Development Tools"
+ sudo yum install qt-devel qt-doc qt-creator opencv-devel openal-soft-devel libtool autoconf automake check check-devel libXScrnSaver-devel
else
echo "Unknown package manager, attempting to compile anyways"
fi
diff --git a/src/audio.cpp b/src/audio.cpp
index 64e0b0961..ecc3c95ce 100644
--- a/src/audio.cpp
+++ b/src/audio.cpp
@@ -41,6 +41,7 @@ ALCdevice* Audio::alInDev{nullptr};
ALCdevice* Audio::alOutDev{nullptr};
ALCcontext* Audio::alContext{nullptr};
ALuint Audio::alMainSource{0};
+float Audio::outputVolume{1.0};
void audioDebugLog(QString msg)
{
@@ -64,6 +65,18 @@ Audio& Audio::getInstance()
return *instance;
}
+Audio::~Audio()
+{
+ qDebug() << "Deleting Audio";
+ audioThread->exit(0);
+ audioThread->wait();
+ if (audioThread->isRunning())
+ audioThread->terminate();
+ delete audioThread;
+ delete audioInLock;
+ delete audioOutLock;
+}
+
void Audio::suscribeInput()
{
if (!alInDev)
@@ -249,7 +262,10 @@ void Audio::playGroupAudio(int group, int peer, const int16_t* data,
return;
if (!call.alSources.contains(peer))
+ {
alGenSources(1, &call.alSources[peer]);
+ alSourcef(call.alSources[peer], AL_GAIN, outputVolume);
+ }
playAudioBuffer(call.alSources[peer], data, samples, channels, sample_rate);
}
@@ -289,6 +305,7 @@ void Audio::playAudioBuffer(ALuint alSource, const int16_t *data, int samples, u
ALint state;
alGetSourcei(alSource, AL_SOURCE_STATE, &state);
+ alSourcef(alSource, AL_GAIN, outputVolume);
if (state != AL_PLAYING)
alSourcePlay(alSource);
}
diff --git a/src/audio.h b/src/audio.h
index 6fb8e7107..d43e60071 100644
--- a/src/audio.h
+++ b/src/audio.h
@@ -73,9 +73,11 @@ public:
static QThread* audioThread;
static ALCcontext* alContext;
static ALuint alMainSource;
+ static float outputVolume;
private:
explicit Audio()=default;
+ ~Audio();
static void playAudioBuffer(ALuint alSource, const int16_t *data, int samples, unsigned channels, int sampleRate);
private:
diff --git a/src/autoupdate.cpp b/src/autoupdate.cpp
index 4d6dbb87e..604442749 100644
--- a/src/autoupdate.cpp
+++ b/src/autoupdate.cpp
@@ -65,9 +65,13 @@ const QString AutoUpdater::checkURI = AutoUpdater::updateServer+"/qtox/"+AutoUpd
const QString AutoUpdater::flistURI = AutoUpdater::updateServer+"/qtox/"+AutoUpdater::platform+"/flist";
const QString AutoUpdater::filesURI = AutoUpdater::updateServer+"/qtox/"+AutoUpdater::platform+"/files/";
bool AutoUpdater::abortFlag{false};
+std::atomic_bool AutoUpdater::isDownloadingUpdate{false};
bool AutoUpdater::isUpdateAvailable()
{
+ if (isDownloadingUpdate)
+ return false;
+
VersionInfo newVersion = getUpdateVersion();
if (newVersion.timestamp <= TIMESTAMP
|| newVersion.versionString.isEmpty() || newVersion.versionString == GIT_VERSION)
@@ -280,26 +284,33 @@ bool AutoUpdater::downloadUpdate()
if (platform.isEmpty())
return false;
+ bool expectFalse = false;
+ if (!isDownloadingUpdate.compare_exchange_strong(expectFalse,true))
+ return false;
+
// Get a list of files to update
QByteArray newFlistData = getUpdateFlist();
QList newFlist = parseFlist(newFlistData);
QList diff = genUpdateDiff(newFlist);
if (abortFlag)
+ {
+ isDownloadingUpdate = false;
return false;
+ }
qDebug() << "AutoUpdater: Need to update "< updateFlist = parseFlist(updateFlistData);
QList diff = genUpdateDiff(updateFlist);
- // If the update wasn't downloaded correctly, redownload it
- // We don't check signatures to not block qTox too long, the updater will do it anyway
+ // Check that we have every file
for (UpdateFileMeta fileMeta : diff)
{
if (!QFile::exists(updateDirStr+fileMeta.installpath))
- {
- QtConcurrent::run(&AutoUpdater::downloadUpdate);
return false;
- }
QFile f(updateDirStr+fileMeta.installpath);
if (f.size() != (int64_t)fileMeta.size)
- {
- QtConcurrent::run(&AutoUpdater::downloadUpdate);
return false;
- }
}
return true;
@@ -446,6 +474,9 @@ fail:
void AutoUpdater::checkUpdatesAsyncInteractive()
{
+ if (isDownloadingUpdate)
+ return;
+
QtConcurrent::run(&AutoUpdater::checkUpdatesAsyncInteractiveWorker);
}
@@ -454,7 +485,12 @@ void AutoUpdater::checkUpdatesAsyncInteractiveWorker()
if (!isUpdateAvailable())
return;
- if (Widget::getInstance()->askMsgboxQuestion(QObject::tr("Update", "The title of a message box"),
+ // If there's already an update dir, resume updating, otherwise ask the user
+ QString updateDirStr = Settings::getInstance().getSettingsDirPath() + "/update/";
+ QDir updateDir(updateDirStr);
+
+ if ((updateDir.exists() && QFile(updateDirStr+"flist").exists())
+ || Widget::getInstance()->askMsgboxQuestion(QObject::tr("Update", "The title of a message box"),
QObject::tr("An update is available, do you want to download it now?\nIt will be installed when qTox restarts.")))
{
downloadUpdate();
@@ -464,4 +500,5 @@ void AutoUpdater::checkUpdatesAsyncInteractiveWorker()
void AutoUpdater::abortUpdates()
{
abortFlag = true;
+ isDownloadingUpdate = false;
}
diff --git a/src/autoupdate.h b/src/autoupdate.h
index 3937e3b20..fc9420ed1 100644
--- a/src/autoupdate.h
+++ b/src/autoupdate.h
@@ -21,9 +21,10 @@
#include
#include
#include
+#include
-/// For now we only support auto updates on Windows, although extending it is not a technical issue.
-/// Linux and Mac users are expected to use their package managers or update manually through official channels.
+/// For now we only support auto updates on Windows and OS X, although extending it is not a technical issue.
+/// Linux users are expected to use their package managers or update manually through official channels.
#ifdef Q_OS_WIN
#define AUTOUPDATE_ENABLED 1
#elif defined(Q_OS_OSX)
@@ -122,6 +123,7 @@ private:
static const QString updaterBin; ///< Path to the qtox-updater binary
static unsigned char key[];
static bool abortFlag; ///< If true, try to abort everything.
+ static std::atomic_bool isDownloadingUpdate; ///< We'll pretend there's no new update available if we're already updating
};
#endif // AUTOUPDATE_H
diff --git a/src/core.cpp b/src/core.cpp
index 95acc75bc..5cfafd48c 100644
--- a/src/core.cpp
+++ b/src/core.cpp
@@ -84,7 +84,7 @@ Core::Core(Camera* cam, QThread *CoreThread, QString loadPath) :
}
// OpenAL init
- QString outDevDescr = Settings::getInstance().getOutDev(); ;
+ QString outDevDescr = Settings::getInstance().getOutDev();
Audio::openOutput(outDevDescr);
QString inDevDescr = Settings::getInstance().getInDev();
Audio::openInput(inDevDescr);
@@ -92,9 +92,19 @@ Core::Core(Camera* cam, QThread *CoreThread, QString loadPath) :
Core::~Core()
{
+ qDebug() << "Deleting Core";
+
clearPassword(Core::ptMain);
clearPassword(Core::ptHistory);
+ toxTimer->stop();
+ coreThread->exit(0);
+ while (coreThread->isRunning())
+ {
+ qApp->processEvents();
+ coreThread->wait(500);
+ }
+
if (tox)
{
toxav_kill(toxav);
@@ -355,7 +365,7 @@ void Core::bootstrapDht()
}
static int j = qrand() % listSize;
- qDebug() << "Core: Bootstraping to the DHT ...";
+ qDebug() << "Core: Bootstrapping to the DHT ...";
int i=0;
while (i < 2) // i think the more we bootstrap, the more we jitter because the more we overwrite nodes
@@ -363,10 +373,10 @@ void Core::bootstrapDht()
const Settings::DhtServer& dhtServer = dhtServerList[j % listSize];
if (tox_bootstrap_from_address(tox, dhtServer.address.toLatin1().data(),
dhtServer.port, CUserId(dhtServer.userId).data()) == 1)
- qDebug() << QString("Core: Bootstraping from ")+dhtServer.name+QString(", addr ")+dhtServer.address.toLatin1().data()
+ qDebug() << QString("Core: Bootstrapping from ")+dhtServer.name+QString(", addr ")+dhtServer.address.toLatin1().data()
+QString(", port ")+QString().setNum(dhtServer.port);
else
- qDebug() << "Core: Error bootstraping from "+dhtServer.name;
+ qDebug() << "Core: Error bootstrapping from "+dhtServer.name;
j++;
i++;
@@ -731,7 +741,7 @@ void Core::acceptFriendRequest(const QString& userId)
void Core::requestFriendship(const QString& friendAddress, const QString& message)
{
- const QString userId = friendAddress.mid(0, TOX_CLIENT_ID_SIZE * 2);
+ const QString userId = friendAddress.mid(0, TOX_PUBLIC_KEY_SIZE * 2);
if (hasFriendWithAddress(friendAddress))
{
@@ -1240,8 +1250,6 @@ bool Core::loadConfiguration(QString path)
// tox core is already decrypted
if (Settings::getInstance().getEnableLogging() && Settings::getInstance().getEncryptLogs())
{
- bool error = true;
-
// get salt
QFile file(HistoryKeeper::getHistoryPath());
file.open(QIODevice::ReadOnly);
@@ -1255,6 +1263,7 @@ bool Core::loadConfiguration(QString path)
}
else
{
+ bool error = true;
do
{
while (!pwsaltedkeys[ptHistory])
@@ -1294,6 +1303,9 @@ bool Core::loadConfiguration(QString path)
void Core::saveConfiguration()
{
+ if (QThread::currentThread() != coreThread)
+ return (void) QMetaObject::invokeMethod(this, "saveConfiguration");
+
QString dir = Settings::getSettingsDirPath();
QDir directory(dir);
if (!directory.exists() && !directory.mkpath(directory.absolutePath())) {
@@ -1320,6 +1332,9 @@ void Core::saveConfiguration()
void Core::saveConfiguration(const QString& path)
{
+ if (QThread::currentThread() != coreThread)
+ return (void) QMetaObject::invokeMethod(this, "saveConfiguration", Q_ARG(const QString&, path));
+
if (!tox)
{
qWarning() << "Core::saveConfiguration: Tox not started, aborting!";
@@ -1329,27 +1344,28 @@ void Core::saveConfiguration(const QString& path)
Settings::getInstance().save();
QSaveFile configurationFile(path);
- if (!configurationFile.open(QIODevice::WriteOnly)) {
+ if (!configurationFile.open(QIODevice::WriteOnly))
+ {
qCritical() << "File " << path << " cannot be opened";
return;
}
qDebug() << "Core: writing tox_save to " << path;
- uint32_t fileSize; bool encrypt = Settings::getInstance().getEncryptTox();
+ uint32_t fileSize;
+ bool encrypt = Settings::getInstance().getEncryptTox();
if (encrypt)
fileSize = tox_encrypted_size(tox);
else
fileSize = tox_size(tox);
- if (fileSize > 0 && fileSize <= INT32_MAX) {
+ if (fileSize > 0 && fileSize <= INT32_MAX)
+ {
uint8_t *data = new uint8_t[fileSize];
-
if (encrypt)
{
if (!pwsaltedkeys[ptMain])
{
- // probably zero chance event
Widget::getInstance()->showWarningMsgBox(tr("NO Password"), tr("Will be saved without encryption!"));
tox_save(tox, data);
}
@@ -1364,7 +1380,9 @@ void Core::saveConfiguration(const QString& path)
}
}
else
+ {
tox_save(tox, data);
+ }
configurationFile.write(reinterpret_cast(data), fileSize);
configurationFile.commit();
@@ -1420,7 +1438,7 @@ void Core::loadFriends()
// assuming there are not that many friends to fill up the whole stack
int32_t *ids = new int32_t[friendCount];
tox_get_friendlist(tox, ids, friendCount);
- uint8_t clientId[TOX_CLIENT_ID_SIZE];
+ uint8_t clientId[TOX_PUBLIC_KEY_SIZE];
for (int32_t i = 0; i < static_cast(friendCount); ++i) {
if (tox_get_client_id(tox, ids[i], clientId) == 0) {
emit friendAdded(ids[i], CUserId::toString(clientId));
@@ -1481,7 +1499,7 @@ ToxID Core::getGroupPeerToxID(int groupId, int peerId) const
{
ToxID peerToxID;
- uint8_t rawID[TOX_CLIENT_ID_SIZE];
+ uint8_t rawID[TOX_PUBLIC_KEY_SIZE];
int res = tox_group_peer_pubkey(tox, groupId, peerId, rawID);
if (res == -1)
{
@@ -1687,14 +1705,14 @@ bool Core::hasFriendWithAddress(const QString &addr) const
return false;
}
- QString pubkey = addr.left(TOX_CLIENT_ID_SIZE * 2);
+ QString pubkey = addr.left(TOX_PUBLIC_KEY_SIZE * 2);
return hasFriendWithPublicKey(pubkey);
}
bool Core::hasFriendWithPublicKey(const QString &pubkey) const
{
// Valid length check
- if (pubkey.length() != (TOX_CLIENT_ID_SIZE * 2))
+ if (pubkey.length() != (TOX_PUBLIC_KEY_SIZE * 2))
{
return false;
}
@@ -1727,9 +1745,9 @@ bool Core::hasFriendWithPublicKey(const QString &pubkey) const
QString Core::getFriendAddress(int friendNumber) const
{
// If we don't know the full address of the client, return just the id, otherwise get the full address
- uint8_t rawid[TOX_CLIENT_ID_SIZE];
+ uint8_t rawid[TOX_PUBLIC_KEY_SIZE];
tox_get_client_id(tox, friendNumber, rawid);
- QByteArray data((char*)rawid,TOX_CLIENT_ID_SIZE);
+ QByteArray data((char*)rawid,TOX_PUBLIC_KEY_SIZE);
QString id = data.toHex().toUpper();
QString addr = Settings::getInstance().getFriendAdress(id);
diff --git a/src/core.h b/src/core.h
index aa66eb96c..82181865e 100644
--- a/src/core.h
+++ b/src/core.h
@@ -64,9 +64,6 @@ public:
bool hasFriendWithPublicKey(const QString &pubkey) const; ///< Check if we have a friend by public key
int joinGroupchat(int32_t friendNumber, uint8_t type, const uint8_t* pubkey,uint16_t length) const; ///< Accept a groupchat invite
void quitGroupChat(int groupId) const; ///< Quit a groupchat
-
- void saveConfiguration();
- void saveConfiguration(const QString& path);
QString getIDString() const; ///< Get the 12 first characters of our Tox ID
@@ -88,6 +85,9 @@ public slots:
void bootstrapDht(); ///< Connects us to the Tox network
void switchConfiguration(const QString& profile); ///< Load a different profile and restart the core
+ void saveConfiguration();
+ void saveConfiguration(const QString& path);
+
void acceptFriendRequest(const QString& userId);
void requestFriendship(const QString& friendAddress, const QString& message);
void groupInviteFriend(int friendId, int groupId);
@@ -117,6 +117,7 @@ public slots:
void pauseResumeFileRecv(int friendId, int fileNum);
void answerCall(int callId);
+ void rejectCall(int callId);
void hangupCall(int callId);
void startCall(int friendId, bool video=false);
void cancelCall(int callId, int friendId);
diff --git a/src/coreav.cpp b/src/coreav.cpp
index b26be579c..49abdf278 100644
--- a/src/coreav.cpp
+++ b/src/coreav.cpp
@@ -26,7 +26,7 @@
ToxCall Core::calls[TOXAV_MAX_CALLS];
#ifdef QTOX_FILTER_AUDIO
-AudioFilterer * Core::filterer[TOXAV_MAX_CALLS] { nullptr};
+AudioFilterer * Core::filterer[TOXAV_MAX_CALLS] {nullptr};
#endif
const int Core::videobufsize{TOXAV_MAX_VIDEO_WIDTH * TOXAV_MAX_VIDEO_HEIGHT * 4};
uint8_t* Core::videobuf;
@@ -159,6 +159,13 @@ void Core::hangupCall(int callId)
toxav_hangup(toxav, callId);
}
+void Core::rejectCall(int callId)
+{
+ qDebug() << QString("Core: rejecting call %1").arg(callId);
+ calls[callId].active = false;
+ toxav_reject(toxav, callId, nullptr);
+}
+
void Core::startCall(int friendId, bool video)
{
int callId;
@@ -201,7 +208,7 @@ void Core::cancelCall(int callId, int friendId)
{
qDebug() << QString("Core: Cancelling call with %1").arg(friendId);
calls[callId].active = false;
- toxav_cancel(toxav, callId, friendId, 0);
+ toxav_cancel(toxav, callId, friendId, nullptr);
}
void Core::cleanupCall(int callId)
@@ -245,10 +252,11 @@ void Core::sendCallAudio(int callId, ToxAv* toxav)
const int framesize = (calls[callId].codecSettings.audio_frame_duration * calls[callId].codecSettings.audio_sample_rate) / 1000 * av_DefaultSettings.audio_channels;
const int bufsize = framesize * 2 * av_DefaultSettings.audio_channels;
- uint8_t buf[bufsize], dest[bufsize];
+ uint8_t buf[bufsize];
if (Audio::tryCaptureSamples(buf, framesize))
{
+ uint8_t dest[bufsize];
int r;
if ((r = toxav_prepare_audio_frame(toxav, callId, dest, framesize*2, (int16_t*)buf, framesize)) < 0)
{
@@ -551,6 +559,7 @@ void Core::playAudioBuffer(ALuint alSource, const int16_t *data, int samples, un
ALint state;
alGetSourcei(alSource, AL_SOURCE_STATE, &state);
+ alSourcef(alSource, AL_GAIN, Audio::outputVolume);
if (state != AL_PLAYING)
{
alSourcePlay(alSource);
@@ -618,9 +627,8 @@ void Core::sendGroupCallAudio(int groupId, ToxAv* toxav)
if (Audio::tryCaptureSamples(buf, framesize))
{
- int r;
- if ((r = toxav_group_send_audio(toxav_get_tox(toxav), groupId, (int16_t*)buf,
- framesize, av_DefaultSettings.audio_channels, av_DefaultSettings.audio_sample_rate)) < 0)
+ if (toxav_group_send_audio(toxav_get_tox(toxav), groupId, (int16_t*)buf,
+ framesize, av_DefaultSettings.audio_channels, av_DefaultSettings.audio_sample_rate) < 0)
{
qDebug() << "Core: toxav_group_send_audio error";
groupCalls[groupId].sendAudioTimer->start();
diff --git a/src/corestructs.cpp b/src/corestructs.cpp
index 5ed31df65..980fd1301 100644
--- a/src/corestructs.cpp
+++ b/src/corestructs.cpp
@@ -33,6 +33,13 @@ bool ToxFile::open(bool write)
return write ? file->open(QIODevice::ReadWrite) : file->open(QIODevice::ReadOnly);
}
+ToxID::ToxID(const ToxID& other)
+{
+ publicKey = other.publicKey;
+ noSpam = other.noSpam;
+ checkSum = other.checkSum;
+}
+
QString ToxID::toString() const
{
return publicKey + noSpam + checkSum;
diff --git a/src/corestructs.h b/src/corestructs.h
index 9826b4c0a..657d58f7b 100644
--- a/src/corestructs.h
+++ b/src/corestructs.h
@@ -16,6 +16,9 @@ enum class Status : int {Online = 0, Away, Busy, Offline};
struct ToxID
{
+ ToxID()=default;
+ ToxID(const ToxID& other);
+
QString publicKey;
QString noSpam;
QString checkSum;
diff --git a/src/friend.cpp b/src/friend.cpp
index e30b9845f..856e2a58c 100644
--- a/src/friend.cpp
+++ b/src/friend.cpp
@@ -23,12 +23,11 @@
#include "src/misc/settings.h"
Friend::Friend(int FriendId, const ToxID &UserId)
- : friendId(FriendId)
+ : userName{Core::getInstance()->getPeerName(UserId)},
+ userID{UserId}, friendId{FriendId}
{
hasNewEvents = 0;
friendStatus = Status::Offline;
- userID = UserId;
- userName = Core::getInstance()->getPeerName(UserId);
if (userName.size() == 0)
userName = UserId.publicKey;
diff --git a/src/friend.h b/src/friend.h
index 7117acc1c..b259b6975 100644
--- a/src/friend.h
+++ b/src/friend.h
@@ -27,7 +27,9 @@ struct Friend
{
public:
Friend(int FriendId, const ToxID &UserId);
+ Friend(const Friend& other)=delete;
~Friend();
+ Friend& operator=(const Friend& other)=delete;
void setName(QString name);
void setAlias(QString name);
diff --git a/src/historykeeper.h b/src/historykeeper.h
index 300232e33..4adbdc79f 100644
--- a/src/historykeeper.h
+++ b/src/historykeeper.h
@@ -63,10 +63,10 @@ private:
void updateAliases();
QPair getChatID(const QString &id_str, ChatType ct);
int getAliasID(const QString &id_str);
- QString wrapMessage(const QString &str);
- QString unWrapMessage(const QString &str);
- ChatType convertToChatType(int);
+ static QString wrapMessage(const QString &str);
+ static QString unWrapMessage(const QString &str);
+ static ChatType convertToChatType(int);
GenericDdInterface *db;
QMap aliases;
diff --git a/src/main.cpp b/src/main.cpp
index ef378bfbc..863ff230e 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -66,12 +66,24 @@ int main(int argc, char *argv[])
parser.addHelpOption();
parser.addVersionOption();
parser.addPositionalArgument("uri", QObject::tr("Tox URI to parse"));
- parser.addOption(QCommandLineOption("P", QObject::tr("Starts new instance and loads specified profile."), QObject::tr("profile")));
+ parser.addOption(QCommandLineOption("p", QObject::tr("Starts new instance and loads specified profile."), QObject::tr("profile")));
parser.process(a);
Settings::getInstance(); // Build our Settings singleton as soon as QApplication is ready, not before
- if (parser.isSet("P"))
- Settings::getInstance().setCurrentProfile(parser.value("P"));
+ if (parser.isSet("p"))
+ {
+ QString profile = parser.value("p");
+ if (QDir(Settings::getSettingsDirPath()).exists(profile + ".tox"))
+ {
+ qDebug() << "Setting profile to" << profile;
+ Settings::getInstance().setCurrentProfile(profile);
+ }
+ else
+ {
+ qWarning() << "Error: -p profile" << profile + ".tox" << "doesn't exist";
+ return EXIT_FAILURE;
+ }
+ }
sodium_init(); // For the auto-updater
@@ -82,7 +94,7 @@ int main(int argc, char *argv[])
if (logfile.open(QIODevice::Append))
{
logFile->setDevice(&logfile);
- *logFile << QDateTime::currentDateTime().toString("\nyyyy-dd-MM HH:mm:ss' file logger starting\n'");
+ *logFile << QDateTime::currentDateTime().toString("\nyyyy-MM-dd HH:mm:ss' file logger starting\n'");
qInstallMessageHandler(myMessageHandler);
}
else
@@ -156,7 +168,7 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
}
- else if (!ipc.isCurrentOwner() && !parser.isSet("P"))
+ else if (!ipc.isCurrentOwner() && !parser.isSet("p"))
{
time_t event = ipc.postEvent("$activate");
ipc.waitUntilProcessed(event);
@@ -165,6 +177,7 @@ int main(int argc, char *argv[])
}
// Run
+ a.setQuitOnLastWindowClosed(false);
Widget* w = Widget::getInstance();
int errorcode = a.exec();
diff --git a/src/misc/cdata.cpp b/src/misc/cdata.cpp
index 18f13ca93..28025de94 100644
--- a/src/misc/cdata.cpp
+++ b/src/misc/cdata.cpp
@@ -36,7 +36,7 @@ uint8_t* CData::data()
return cData;
}
-uint16_t CData::size()
+uint16_t CData::size() const
{
return cDataSize;
}
@@ -56,7 +56,7 @@ uint16_t CData::fromString(const QString& data, uint8_t* cData)
// CUserId
-const uint16_t CUserId::SIZE{TOX_CLIENT_ID_SIZE};
+const uint16_t CUserId::SIZE{TOX_PUBLIC_KEY_SIZE};
CUserId::CUserId(const QString &userId) :
CData(userId, SIZE < userId.size() ? userId.size() : SIZE)
diff --git a/src/misc/cdata.h b/src/misc/cdata.h
index 6433e9bac..3b37b0627 100644
--- a/src/misc/cdata.h
+++ b/src/misc/cdata.h
@@ -24,11 +24,13 @@ class CData
{
public:
uint8_t* data();
- uint16_t size();
+ uint16_t size() const;
protected:
explicit CData(const QString& data, uint16_t byteSize);
+ CData(const CData& other)=delete;
virtual ~CData();
+ CData& operator=(const CData& other)=delete;
static QString toString(const uint8_t* cData, const uint16_t cDataSize);
diff --git a/src/misc/cstring.cpp b/src/misc/cstring.cpp
index b9217fbc8..8624ae8eb 100644
--- a/src/misc/cstring.cpp
+++ b/src/misc/cstring.cpp
@@ -46,7 +46,7 @@ uint8_t* CString::data()
return cString;
}
-uint16_t CString::size()
+uint16_t CString::size() const
{
return cStringSize;
}
diff --git a/src/misc/cstring.h b/src/misc/cstring.h
index 869fa29f2..ee21a99a9 100644
--- a/src/misc/cstring.h
+++ b/src/misc/cstring.h
@@ -31,7 +31,7 @@ public:
~CString();
uint8_t* data();
- uint16_t size();
+ uint16_t size() const;
static QString toString(const uint8_t* cMessage, const uint16_t cMessageSize);
static uint16_t fromString(const QString& message, uint8_t* cMessage);
diff --git a/src/misc/settings.cpp b/src/misc/settings.cpp
index 4efacb541..85d3d3289 100644
--- a/src/misc/settings.cpp
+++ b/src/misc/settings.cpp
@@ -29,12 +29,7 @@
#include
#include
-
-#ifdef Q_OS_LINUX
-#define SHOW_SYSTEM_TRAY_DEFAULT (bool) false
-#else // OS is not linux
#define SHOW_SYSTEM_TRAY_DEFAULT (bool) true
-#endif
const QString Settings::OLDFILENAME = "settings.ini";
const QString Settings::FILENAME = "qtox.ini";
@@ -136,12 +131,15 @@ void Settings::load()
currentProfile = s.value("currentProfile", "").toString();
autoAwayTime = s.value("autoAwayTime", 10).toInt();
checkUpdates = s.value("checkUpdates", false).toBool();
+ showWindow = s.value("showWindow", true).toBool();
showInFront = s.value("showInFront", false).toBool();
+ groupAlwaysNotify = s.value("groupAlwaysNotify", false).toBool();
fauxOfflineMessaging = s.value("fauxOfflineMessaging", true).toBool();
autoSaveEnabled = s.value("autoSaveEnabled", false).toBool();
globalAutoAcceptDir = s.value("globalAutoAcceptDir",
QStandardPaths::locate(QStandardPaths::HomeLocation, QString(), QStandardPaths::LocateDirectory)
).toString();
+ compactLayout = s.value("compactLayout", false).toBool();
s.endGroup();
s.beginGroup("Advanced");
@@ -201,6 +199,10 @@ void Settings::load()
filterAudio = s.value("filterAudio", false).toBool();
s.endGroup();
+ s.beginGroup("Video");
+ camVideoRes = s.value("camVideoRes",QSize()).toSize();
+ s.endGroup();
+
// Read the embedded DHT bootsrap nodes list if needed
if (dhtServerList.isEmpty())
{
@@ -289,8 +291,11 @@ void Settings::save(QString path, bool writeFriends)
s.setValue("currentProfile", currentProfile);
s.setValue("autoAwayTime", autoAwayTime);
s.setValue("checkUpdates", checkUpdates);
+ s.setValue("showWindow", showWindow);
s.setValue("showInFront", showInFront);
+ s.setValue("groupAlwaysNotify", groupAlwaysNotify);
s.setValue("fauxOfflineMessaging", fauxOfflineMessaging);
+ s.setValue("compactLayout", compactLayout);
s.setValue("autoSaveEnabled", autoSaveEnabled);
s.setValue("globalAutoAcceptDir", globalAutoAcceptDir);
s.endGroup();
@@ -344,6 +349,10 @@ void Settings::save(QString path, bool writeFriends)
s.setValue("filterAudio", filterAudio);
s.endGroup();
+ s.beginGroup("Video");
+ s.setValue("camVideoRes",camVideoRes);
+ s.endGroup();
+
if (!writeFriends || currentProfile.isEmpty()) // Core::switchConfiguration
return;
@@ -561,7 +570,17 @@ bool Settings::getShowInFront() const
void Settings::setShowInFront(bool newValue)
{
- showInFront = newValue;
+ showInFront = newValue;
+}
+
+bool Settings::getGroupAlwaysNotify() const
+{
+ return groupAlwaysNotify;
+}
+
+void Settings::setGroupAlwaysNotify(bool newValue)
+{
+ groupAlwaysNotify = newValue;
}
QString Settings::getTranslation() const
@@ -854,6 +873,16 @@ void Settings::setCheckUpdates(bool newValue)
checkUpdates = newValue;
}
+bool Settings::getShowWindow() const
+{
+ return showWindow;
+}
+
+void Settings::setShowWindow(bool newValue)
+{
+ showWindow = newValue;
+}
+
QByteArray Settings::getSplitterState() const
{
return splitterState;
@@ -914,6 +943,16 @@ void Settings::setFilterAudio(bool newValue)
filterAudio = newValue;
}
+QSize Settings::getCamVideoRes() const
+{
+ return camVideoRes;
+}
+
+void Settings::setCamVideoRes(QSize newValue)
+{
+ camVideoRes = newValue;
+}
+
QString Settings::getFriendAdress(const QString &publicKey) const
{
QString key = ToxID::fromString(publicKey).publicKey;
@@ -986,6 +1025,17 @@ void Settings::setFauxOfflineMessaging(bool value)
fauxOfflineMessaging = value;
}
+bool Settings::getCompactLayout() const
+{
+ return compactLayout;
+}
+
+void Settings::setCompactLayout(bool value)
+{
+ compactLayout = value;
+ emit compactLayoutChanged();
+}
+
int Settings::getThemeColor() const
{
return themeColor;
diff --git a/src/misc/settings.h b/src/misc/settings.h
index d05be0a03..86a9bdf31 100644
--- a/src/misc/settings.h
+++ b/src/misc/settings.h
@@ -115,9 +115,15 @@ public:
bool getCheckUpdates() const;
void setCheckUpdates(bool newValue);
+ bool getShowWindow() const;
+ void setShowWindow(bool newValue);
+
bool getShowInFront() const;
void setShowInFront(bool newValue);
+ bool getGroupAlwaysNotify() const;
+ void setGroupAlwaysNotify(bool newValue);
+
QPixmap getSavedAvatar(const QString& ownerId);
void saveAvatar(QPixmap& pic, const QString& ownerId);
@@ -133,6 +139,9 @@ public:
bool getFilterAudio() const;
void setFilterAudio(bool newValue);
+ QSize getCamVideoRes() const;
+ void setCamVideoRes(QSize newValue);
+
// Assume all widgets have unique names
// Don't use it to save every single thing you want to save, use it
// for some general purpose widgets, such as MainWindows or Splitters,
@@ -223,6 +232,9 @@ public:
bool getFauxOfflineMessaging() const;
void setFauxOfflineMessaging(bool value);
+ bool getCompactLayout() const;
+ void setCompactLayout(bool compact);
+
public:
void save(bool writeFriends = true);
void save(QString path, bool writeFriends = true);
@@ -246,6 +258,7 @@ private:
bool dontShowDhtDialog;
bool fauxOfflineMessaging;
+ bool compactLayout;
bool enableIPv6;
QString translation;
static bool makeToxPortable;
@@ -255,7 +268,9 @@ private:
bool lightTrayIcon;
bool useEmoticons;
bool checkUpdates;
+ bool showWindow;
bool showInFront;
+ bool groupAlwaysNotify;
bool forceTCP;
@@ -305,6 +320,9 @@ private:
QString outDev;
bool filterAudio;
+ // Video
+ QSize camVideoRes;
+
struct friendProp
{
QString alias;
@@ -323,6 +341,7 @@ signals:
void smileyPackChanged();
void emojiFontChanged();
void timestampFormatChanged();
+ void compactLayoutChanged();
};
#endif // SETTINGS_HPP
diff --git a/src/misc/smileypack.cpp b/src/misc/smileypack.cpp
index 258b3ae9c..73c07d979 100644
--- a/src/misc/smileypack.cpp
+++ b/src/misc/smileypack.cpp
@@ -130,7 +130,8 @@ bool SmileyPack::load(const QString& filename)
while (!stringElement.isNull())
{
- QString emoticon = stringElement.text();
+ QString emoticon = stringElement.text()
+ .replace("<","<").replace(">",">");
filenameTable.insert(emoticon, file);
cacheSmiley(file); // preload all smileys
diff --git a/src/platform/timer_win.cpp b/src/platform/timer_win.cpp
index 31542f76f..f48c5cad4 100644
--- a/src/platform/timer_win.cpp
+++ b/src/platform/timer_win.cpp
@@ -22,7 +22,7 @@
uint32_t Platform::getIdleTime()
{
- LASTINPUTINFO info = { 0 };
+ LASTINPUTINFO info = { 0, 0 };
info.cbSize = sizeof(info);
if (GetLastInputInfo(&info))
return GetTickCount() - info.dwTime;
diff --git a/src/toxdns.cpp b/src/toxdns.cpp
index 5afdc73a0..7364f180a 100644
--- a/src/toxdns.cpp
+++ b/src/toxdns.cpp
@@ -221,8 +221,8 @@ fallbackOnTox1:
toxIdStr = queryTox1(record, silent);
#elif TOX1_ASK_FALLBACK
QMessageBox::StandardButton btn = QMessageBox::warning(nullptr, "qTox", tr("It appears that qTox has to use the old tox1 protocol.\n\
-Unfortunately tox1 is not secure. Should it be used anyway?"), QMessageBox::Ok|QMessageBox::No, QMessageBox::No);
- if (btn == QMessageBox::Ok)
+Unfortunately tox1 is not secure. Should it be used anyway?"), QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
+ if (btn == QMessageBox::Yes)
queryTox1(record, silent);
#endif
return toxIdStr;
diff --git a/src/video/camera.cpp b/src/video/camera.cpp
index 9d30944ae..74f5677e8 100644
--- a/src/video/camera.cpp
+++ b/src/video/camera.cpp
@@ -99,7 +99,7 @@ double Camera::getProp(Camera::Prop prop)
return worker->getProp(int(prop));
}
-void Camera::onNewFrameAvailable(const VideoFrame frame)
+void Camera::onNewFrameAvailable(const VideoFrame &frame)
{
emit frameAvailable(frame);
diff --git a/src/video/camera.h b/src/video/camera.h
index 061e9b27a..364ae577c 100644
--- a/src/video/camera.h
+++ b/src/video/camera.h
@@ -21,7 +21,7 @@
#include
#include
#include "vpx/vpx_image.h"
-#include "opencv2/opencv.hpp"
+#include "opencv2/highgui/highgui.hpp"
#include "src/video/videosource.h"
class CameraWorker;
@@ -79,7 +79,7 @@ private:
CameraWorker* worker;
private slots:
- void onNewFrameAvailable(const VideoFrame frame);
+ void onNewFrameAvailable(const VideoFrame& frame);
};
diff --git a/src/video/cameraworker.cpp b/src/video/cameraworker.cpp
index da98e58f4..d4c40731d 100644
--- a/src/video/cameraworker.cpp
+++ b/src/video/cameraworker.cpp
@@ -29,6 +29,12 @@ CameraWorker::CameraWorker(int index)
qRegisterMetaType>();
}
+CameraWorker::~CameraWorker()
+{
+ if (clock)
+ delete clock;
+}
+
void CameraWorker::onStart()
{
clock = new QTimer(this);
@@ -112,7 +118,7 @@ void CameraWorker::_probeResolutions()
//qDebug() << "PROBING:" << res << " got " << w << h;
- if (!resolutions.contains(QSize(w,h)))
+ if (w>0 && h>0 && !resolutions.contains(QSize(w,h)))
resolutions.append(QSize(w,h));
}
diff --git a/src/video/cameraworker.h b/src/video/cameraworker.h
index 742449b5f..5bda28240 100644
--- a/src/video/cameraworker.h
+++ b/src/video/cameraworker.h
@@ -24,7 +24,7 @@
#include
#include
-#include "opencv2/opencv.hpp"
+#include "opencv2/highgui/highgui.hpp"
#include "videosource.h"
class QTimer;
@@ -34,6 +34,7 @@ class CameraWorker : public QObject
Q_OBJECT
public:
CameraWorker(int index);
+ ~CameraWorker();
void doWork();
void suspend();
@@ -48,7 +49,7 @@ public slots:
signals:
void started();
- void newFrameAvailable(const VideoFrame frame);
+ void newFrameAvailable(const VideoFrame& frame);
void resProbingFinished(QList res);
void propProbingFinished(int prop, double val);
diff --git a/src/video/netvideosource.h b/src/video/netvideosource.h
index 4ad6dfd51..c3171727e 100644
--- a/src/video/netvideosource.h
+++ b/src/video/netvideosource.h
@@ -19,7 +19,7 @@
#include "videosource.h"
-class vpx_image;
+struct vpx_image;
class NetVideoSource : public VideoSource
{
diff --git a/src/video/videosource.h b/src/video/videosource.h
index 4dd14151a..1c9646812 100644
--- a/src/video/videosource.h
+++ b/src/video/videosource.h
@@ -32,7 +32,7 @@ public:
virtual void unsubscribe() = 0;
signals:
- void frameAvailable(const VideoFrame frame);
+ void frameAvailable(const VideoFrame& frame);
};
diff --git a/src/widget/callconfirmwidget.cpp b/src/widget/callconfirmwidget.cpp
new file mode 100644
index 000000000..03cc7912f
--- /dev/null
+++ b/src/widget/callconfirmwidget.cpp
@@ -0,0 +1,93 @@
+#include "callconfirmwidget.h"
+#include "widget.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+CallConfirmWidget::CallConfirmWidget(const QWidget *Anchor) :
+ QWidget(Widget::getInstance()), anchor(Anchor),
+ rectW{120}, rectH{85},
+ spikeW{30}, spikeH{15},
+ roundedFactor{20},
+ rectRatio{static_cast(rectH)/static_cast(rectW)}
+{
+ setWindowFlags(Qt::SubWindow);
+
+ QPalette palette;
+ palette.setColor(QPalette::WindowText, Qt::white);
+ setPalette(palette);
+
+ QVBoxLayout *layout = new QVBoxLayout(this);
+ QLabel *callLabel = new QLabel(QObject::tr("Incoming call..."), this);
+ callLabel->setAlignment(Qt::AlignHCenter);
+ QDialogButtonBox *buttonBox = new QDialogButtonBox(Qt::Horizontal, this);
+ QPushButton *accept = new QPushButton(this), *reject = new QPushButton(this);
+ accept->setFlat(true);
+ reject->setFlat(true);
+ accept->setStyleSheet("QPushButton{border:none;}");
+ reject->setStyleSheet("QPushButton{border:none;}");
+ accept->setIcon(QIcon(":/ui/acceptCall/acceptCall.png"));
+ reject->setIcon(QIcon(":/ui/rejectCall/rejectCall.png"));
+ accept->setIconSize(accept->size());
+ reject->setIconSize(reject->size());
+
+ buttonBox->addButton(accept, QDialogButtonBox::AcceptRole);
+ buttonBox->addButton(reject, QDialogButtonBox::RejectRole);
+
+ connect(buttonBox, &QDialogButtonBox::accepted, this, &CallConfirmWidget::accepted);
+ connect(buttonBox, &QDialogButtonBox::rejected, this, &CallConfirmWidget::rejected);
+
+ connect(Widget::getInstance(), &Widget::resized, this, &CallConfirmWidget::reposition);
+
+ layout->setMargin(12);
+ layout->addSpacing(spikeH);
+ layout->addWidget(callLabel);
+ layout->addWidget(buttonBox);
+
+ setFixedSize(rectW,rectH+spikeH);
+ reposition();
+}
+
+void CallConfirmWidget::reposition()
+{
+ Widget* w = Widget::getInstance();
+ QPoint pos = anchor->mapToGlobal({(anchor->width()-rectW)/2,anchor->height()})-w->mapToGlobal({0,0});
+
+ // We don't want the widget to overflow past the right of the screen
+ int xOverflow=0;
+ if (pos.x() + rectW > w->width())
+ xOverflow = pos.x() + rectW - w->width();
+ pos.rx() -= xOverflow;
+
+ mainRect = {0,spikeH,rectW,rectH};
+ brush = QBrush(QColor(65,65,65));
+ spikePoly = QPolygon({{(rectW-spikeW)/2+xOverflow,spikeH},
+ {rectW/2+xOverflow,0},
+ {(rectW+spikeW)/2+xOverflow,spikeH}});
+
+ move(pos);
+ update();
+}
+
+void CallConfirmWidget::paintEvent(QPaintEvent*)
+{
+ QPainter painter(this);
+ painter.setRenderHint(QPainter::Antialiasing);
+ painter.setBrush(brush);
+ painter.setPen(Qt::NoPen);
+
+ painter.drawRoundRect(mainRect, roundedFactor*rectRatio, roundedFactor);
+ painter.drawPolygon(spikePoly);
+}
+
+void CallConfirmWidget::showEvent(QShowEvent*)
+{
+ reposition();
+ update();
+}
diff --git a/src/widget/callconfirmwidget.h b/src/widget/callconfirmwidget.h
new file mode 100644
index 000000000..e14484c97
--- /dev/null
+++ b/src/widget/callconfirmwidget.h
@@ -0,0 +1,45 @@
+#ifndef CALLCONFIRMWIDGET_H
+#define CALLCONFIRMWIDGET_H
+
+#include
+#include
+#include
+#include
+
+class QPaintEvent;
+class QShowEvent;
+
+/// This is a widget with dialog buttons to accept/reject a call
+/// It tracks the position of another widget called the anchor
+/// and looks like a bubble at the bottom of that widget.
+class CallConfirmWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ explicit CallConfirmWidget(const QWidget *Anchor);
+
+signals:
+ void accepted();
+ void rejected();
+
+protected:
+ virtual void paintEvent(QPaintEvent* event) override;
+ virtual void showEvent(QShowEvent * event) override;
+
+protected slots:
+ void reposition(); ///< Recalculate our positions to track the anchor
+
+private:
+ const QWidget* anchor; ///< The widget we're going to be tracking
+
+ QRect mainRect;
+ QPolygon spikePoly;
+ QBrush brush;
+
+ const int rectW, rectH;
+ const int spikeW, spikeH;
+ const int roundedFactor; ///< By how much are the corners of the main rect rounded
+ const qreal rectRatio; ///< Used to correct the rounding factors on non-square rects
+};
+
+#endif // CALLCONFIRMWIDGET_H
diff --git a/src/widget/form/addfriendform.cpp b/src/widget/form/addfriendform.cpp
index efacf17e8..9c1d106e1 100644
--- a/src/widget/form/addfriendform.cpp
+++ b/src/widget/form/addfriendform.cpp
@@ -98,8 +98,8 @@ void AddFriendForm::onSendTriggered()
if (Settings::getInstance().getProxyType() != ProxyType::ptNone)
{
QMessageBox::StandardButton btn = QMessageBox::warning(main, "qTox", tr("qTox needs to use the Tox DNS, but can't do it through a proxy.\n\
-Ignore the proxy and connect to the Internet directly?"), QMessageBox::Ok|QMessageBox::No, QMessageBox::No);
- if (btn != QMessageBox::Ok)
+Ignore the proxy and connect to the Internet directly?"), QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
+ if (btn != QMessageBox::Yes)
return;
}
diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp
index cd13bc427..a3e0b598e 100644
--- a/src/widget/form/chatform.cpp
+++ b/src/widget/form/chatform.cpp
@@ -24,13 +24,20 @@
#include
#include
#include "chatform.h"
-#include "src/historykeeper.h"
-#include "src/widget/form/loadhistorydialog.h"
+#include "src/core.h"
#include "src/friend.h"
+#include "src/filetransferinstance.h"
+#include "src/historykeeper.h"
+#include "src/misc/style.h"
+#include "src/misc/settings.h"
+#include "src/misc/cstring.h"
+#include "src/widget/callconfirmwidget.h"
#include "src/widget/friendwidget.h"
#include "src/widget/netcamview.h"
+#include "src/widget/chatareawidget.h"
+#include "src/widget/form/loadhistorydialog.h"
#include "src/widget/tool/chattextedit.h"
-#include "src/core.h"
+#include "src/widget/tool/chatactions/filetransferaction.h"
#include "src/widget/widget.h"
#include "src/widget/maskablepixmapwidget.h"
#include "src/widget/croppinglabel.h"
@@ -56,8 +63,13 @@ ChatForm::ChatForm(Friend* chatFriend)
statusMessageLabel->setFont(Style::getFont(Style::Medium));
statusMessageLabel->setMinimumHeight(Style::getFont(Style::Medium).pixelSize());
+ callConfirm = nullptr;
+
+ typingTimer.setSingleShot(true);
+
netcam = new NetCamView();
- timer = nullptr;
+ callDurationTimer = nullptr;
+ disableCallButtonsTimer = nullptr;
chatWidget->setTypingNotification(ChatMessage::createTypingNotification());
@@ -80,6 +92,7 @@ ChatForm::ChatForm(Friend* chatFriend)
connect(volButton, SIGNAL(clicked()), this, SLOT(onVolMuteToggle()));
connect(Core::getInstance(), &Core::fileSendFailed, this, &ChatForm::onFileSendFailed);
connect(this, SIGNAL(chatAreaCleared()), this, SLOT(clearReciepts()));
+ connect(&typingTimer, &QTimer::timeout, this, [=]{Core::getInstance()->sendTyping(f->getFriendID(), false);});
connect(nameLabel, &CroppingLabel::textChanged, this, [=](QString text, QString orig) {
if (text != orig) emit aliasChanged(text);
} );
@@ -90,6 +103,7 @@ ChatForm::ChatForm(Friend* chatFriend)
ChatForm::~ChatForm()
{
delete netcam;
+ delete callConfirm;
}
void ChatForm::setStatusMessage(QString newMessage)
@@ -132,6 +146,8 @@ void ChatForm::onSendTriggered()
rec = Core::getInstance()->sendMessage(f->getFriendID(), qt_msg);
registerReceipt(rec, id, ma);
+
+ msgEdit->setLastMessage(msg); //set last message only when sending it
}
msgEdit->clear();
@@ -145,11 +161,10 @@ void ChatForm::onTextEditChanged()
else
isNowTyping = msgEdit->toPlainText().length() > 0;
- if (isTyping != isNowTyping)
- {
- isTyping = isNowTyping;
- Core::getInstance()->sendTyping(f->getFriendID(), isTyping);
- }
+ if (isNowTyping)
+ typingTimer.start(3000);
+
+ Core::getInstance()->sendTyping(f->getFriendID(), isNowTyping);
}
void ChatForm::onAttachClicked()
@@ -245,20 +260,30 @@ void ChatForm::onAvInvite(int FriendId, int CallId, bool video)
videoButton->disconnect();
if (video)
{
+ callConfirm = new CallConfirmWidget(videoButton);
+ if (isVisible())
+ callConfirm->show();
+ connect(callConfirm, &CallConfirmWidget::accepted, this, &ChatForm::onAnswerCallTriggered);
+ connect(callConfirm, &CallConfirmWidget::rejected, this, &ChatForm::onRejectCallTriggered);
+
callButton->setObjectName("grey");
- callButton->style()->polish(callButton);
videoButton->setObjectName("yellow");
- videoButton->style()->polish(videoButton);
- connect(videoButton, SIGNAL(clicked()), this, SLOT(onAnswerCallTriggered()));
+ connect(videoButton, &QPushButton::clicked, this, &ChatForm::onAnswerCallTriggered);
}
else
{
+ callConfirm = new CallConfirmWidget(callButton);
+ if (isVisible())
+ callConfirm->show();
+ connect(callConfirm, &CallConfirmWidget::accepted, this, &ChatForm::onAnswerCallTriggered);
+ connect(callConfirm, &CallConfirmWidget::rejected, this, &ChatForm::onRejectCallTriggered);
+
callButton->setObjectName("yellow");
- callButton->style()->polish(callButton);
videoButton->setObjectName("grey");
- videoButton->style()->polish(videoButton);
- connect(callButton, SIGNAL(clicked()), this, SLOT(onAnswerCallTriggered()));
+ connect(callButton, &QPushButton::clicked, this, &ChatForm::onAnswerCallTriggered);
}
+ callButton->style()->polish(callButton);
+ videoButton->style()->polish(videoButton);
insertChatMessage(ChatMessage::createChatInfoMessage(tr("%1 calling").arg(f->getDisplayedName()), ChatMessage::INFO, QDateTime::currentDateTime()));
@@ -287,49 +312,38 @@ void ChatForm::onAvStart(int FriendId, int CallId, bool video)
if (video)
{
callButton->setObjectName("grey");
- callButton->style()->polish(callButton);
videoButton->setObjectName("red");
- videoButton->style()->polish(videoButton);
- connect(videoButton, SIGNAL(clicked()), this, SLOT(onHangupCallTriggered()));
+ connect(videoButton, SIGNAL(clicked()),
+ this, SLOT(onHangupCallTriggered()));
netcam->show(Core::getInstance()->getVideoSourceFromCall(CallId), f->getDisplayedName());
}
else
{
callButton->setObjectName("red");
- callButton->style()->polish(callButton);
videoButton->setObjectName("grey");
- videoButton->style()->polish(videoButton);
- connect(callButton, SIGNAL(clicked()), this, SLOT(onHangupCallTriggered()));
+ connect(callButton, SIGNAL(clicked()),
+ this, SLOT(onHangupCallTriggered()));
}
+ callButton->style()->polish(callButton);
+ videoButton->style()->polish(videoButton);
startCounter();
}
void ChatForm::onAvCancel(int FriendId, int)
{
-
if (FriendId != f->getFriendID())
return;
qDebug() << "onAvCancel";
+ delete callConfirm;
+ callConfirm = nullptr;
+
stopCounter();
- audioInputFlag = false;
- audioOutputFlag = false;
- micButton->setObjectName("green");
- micButton->style()->polish(micButton);
- volButton->setObjectName("green");
- volButton->style()->polish(volButton);
- callButton->disconnect();
- videoButton->disconnect();
- callButton->setObjectName("green");
- callButton->style()->polish(callButton);
- videoButton->setObjectName("green");
- videoButton->style()->polish(videoButton);
- connect(callButton, SIGNAL(clicked()), this, SLOT(onCallTriggered()));
- connect(videoButton, SIGNAL(clicked()), this, SLOT(onVideoCallTriggered()));
+ enableCallButtons();
netcam->hide();
@@ -343,21 +357,11 @@ void ChatForm::onAvEnd(int FriendId, int)
qDebug() << "onAvEnd";
- audioInputFlag = false;
- audioOutputFlag = false;
- micButton->setObjectName("green");
- micButton->style()->polish(micButton);
- volButton->setObjectName("green");
- volButton->style()->polish(volButton);
- callButton->disconnect();
- videoButton->disconnect();
- callButton->setObjectName("green");
- callButton->style()->polish(callButton);
- videoButton->setObjectName("green");
- videoButton->style()->polish(videoButton);
- connect(callButton, SIGNAL(clicked()), this, SLOT(onCallTriggered()));
- connect(videoButton, SIGNAL(clicked()), this, SLOT(onVideoCallTriggered()));
+ delete callConfirm;
+ callConfirm = nullptr;
+ enableCallButtons();
+
netcam->hide();
stopCounter();
@@ -379,7 +383,8 @@ void ChatForm::onAvRinging(int FriendId, int CallId, bool video)
callButton->style()->polish(callButton);
videoButton->setObjectName("yellow");
videoButton->style()->polish(videoButton);
- connect(videoButton, SIGNAL(clicked()), this, SLOT(onCancelCallTriggered()));
+ connect(videoButton, SIGNAL(clicked()),
+ this, SLOT(onCancelCallTriggered()));
}
else
{
@@ -387,7 +392,8 @@ void ChatForm::onAvRinging(int FriendId, int CallId, bool video)
callButton->style()->polish(callButton);
videoButton->setObjectName("grey");
videoButton->style()->polish(videoButton);
- connect(callButton, SIGNAL(clicked()), this, SLOT(onCancelCallTriggered()));
+ connect(callButton, SIGNAL(clicked()),
+ this, SLOT(onCancelCallTriggered()));
}
addSystemInfoMessage(tr("Calling to %1").arg(f->getDisplayedName()), ChatMessage::INFO, QDateTime::currentDateTime());
@@ -431,22 +437,10 @@ void ChatForm::onAvEnding(int FriendId, int)
qDebug() << "onAvEnding";
- audioInputFlag = false;
- audioOutputFlag = false;
- micButton->setObjectName("green");
- micButton->style()->polish(micButton);
- volButton->setObjectName("green");
- volButton->style()->polish(volButton);
- callButton->disconnect();
- videoButton->disconnect();
- callButton->setObjectName("green");
- callButton->style()->polish(callButton);
- callButton->disconnect();
- videoButton->setObjectName("green");
- videoButton->style()->polish(videoButton);
- videoButton->disconnect();
- connect(callButton, SIGNAL(clicked()), this, SLOT(onCallTriggered()));
- connect(videoButton, SIGNAL(clicked()), this, SLOT(onVideoCallTriggered()));
+ delete callConfirm;
+ callConfirm = nullptr;
+
+ enableCallButtons();
netcam->hide();
@@ -460,23 +454,11 @@ void ChatForm::onAvRequestTimeout(int FriendId, int)
qDebug() << "onAvRequestTimeout";
- audioInputFlag = false;
- audioOutputFlag = false;
- micButton->setObjectName("green");
- micButton->style()->polish(micButton);
- volButton->setObjectName("green");
- volButton->style()->polish(volButton);
- callButton->disconnect();
- videoButton->disconnect();
- callButton->setObjectName("green");
- callButton->style()->polish(callButton);
- callButton->disconnect();
- videoButton->setObjectName("green");
- videoButton->style()->polish(videoButton);
- videoButton->disconnect();
- connect(callButton, SIGNAL(clicked()), this, SLOT(onCallTriggered()));
- connect(videoButton, SIGNAL(clicked()), this, SLOT(onVideoCallTriggered()));
+ delete callConfirm;
+ callConfirm = nullptr;
+ enableCallButtons();
+
netcam->hide();
}
@@ -487,22 +469,10 @@ void ChatForm::onAvPeerTimeout(int FriendId, int)
qDebug() << "onAvPeerTimeout";
- audioInputFlag = false;
- audioOutputFlag = false;
- micButton->setObjectName("green");
- micButton->style()->polish(micButton);
- volButton->setObjectName("green");
- volButton->style()->polish(volButton);
- callButton->disconnect();
- videoButton->disconnect();
- callButton->setObjectName("green");
- callButton->style()->polish(callButton);
- callButton->disconnect();
- videoButton->setObjectName("green");
- videoButton->style()->polish(videoButton);
- videoButton->disconnect();
- connect(callButton, SIGNAL(clicked()), this, SLOT(onCallTriggered()));
- connect(videoButton, SIGNAL(clicked()), this, SLOT(onVideoCallTriggered()));
+ delete callConfirm;
+ callConfirm = nullptr;
+
+ enableCallButtons();
netcam->hide();
}
@@ -514,22 +484,10 @@ void ChatForm::onAvRejected(int FriendId, int)
qDebug() << "onAvRejected";
- audioInputFlag = false;
- audioOutputFlag = false;
- micButton->setObjectName("green");
- micButton->style()->polish(micButton);
- volButton->setObjectName("green");
- volButton->style()->polish(volButton);
- callButton->disconnect();
- videoButton->disconnect();
- callButton->setObjectName("green");
- callButton->style()->polish(callButton);
- callButton->disconnect();
- videoButton->setObjectName("green");
- videoButton->style()->polish(videoButton);
- videoButton->disconnect();
- connect(callButton, SIGNAL(clicked()), this, SLOT(onCallTriggered()));
- connect(videoButton, SIGNAL(clicked()), this, SLOT(onVideoCallTriggered()));
+ delete callConfirm;
+ callConfirm = nullptr;
+
+ enableCallButtons();
insertChatMessage(ChatMessage::createChatInfoMessage(tr("Call rejected"), ChatMessage::INFO, QDateTime::currentDateTime()));
@@ -557,6 +515,12 @@ void ChatForm::onAnswerCallTriggered()
{
qDebug() << "onAnswerCallTriggered";
+ if (callConfirm)
+ {
+ delete callConfirm;
+ callConfirm = nullptr;
+ }
+
audioInputFlag = true;
audioOutputFlag = true;
emit answerCall(callId);
@@ -569,16 +533,32 @@ void ChatForm::onHangupCallTriggered()
audioInputFlag = false;
audioOutputFlag = false;
emit hangupCall(callId);
- micButton->setObjectName("green");
- micButton->style()->polish(micButton);
- volButton->setObjectName("green");
- volButton->style()->polish(volButton);
+
+ enableCallButtons();
+}
+
+void ChatForm::onRejectCallTriggered()
+{
+ qDebug() << "onRejectCallTriggered";
+
+ if (callConfirm)
+ {
+ delete callConfirm;
+ callConfirm = nullptr;
+ }
+
+ audioInputFlag = false;
+ audioOutputFlag = false;
+ emit rejectCall(callId);
+
+ enableCallButtons();
+
}
void ChatForm::onCallTriggered()
{
qDebug() << "onCallTriggered";
-
+
audioInputFlag = true;
audioOutputFlag = true;
callButton->disconnect();
@@ -589,7 +569,7 @@ void ChatForm::onCallTriggered()
void ChatForm::onVideoCallTriggered()
{
qDebug() << "onVideoCallTriggered";
-
+
audioInputFlag = true;
audioOutputFlag = true;
callButton->disconnect();
@@ -604,37 +584,80 @@ void ChatForm::onAvCallFailed(int FriendId)
qDebug() << "onAvCallFailed";
- audioInputFlag = false;
- audioOutputFlag = false;
- callButton->disconnect();
- videoButton->disconnect();
- connect(callButton, SIGNAL(clicked()), this, SLOT(onCallTriggered()));
- connect(videoButton, SIGNAL(clicked()), this, SLOT(onVideoCallTriggered()));
+ delete callConfirm;
+ callConfirm = nullptr;
+
+ enableCallButtons();
}
void ChatForm::onCancelCallTriggered()
{
qDebug() << "onCancelCallTriggered";
+ enableCallButtons();
+
+ netcam->hide();
+ emit cancelCall(callId, f->getFriendID());
+}
+
+void ChatForm::enableCallButtons()
+{
+ qDebug() << "enableCallButtons";
+
+ audioInputFlag = false;
+ audioOutputFlag = false;
+
+ micButton->setObjectName("grey");
+ micButton->style()->polish(micButton);
+ micButton->disconnect();
+ volButton->setObjectName("grey");
+ volButton->style()->polish(volButton);
+ volButton->disconnect();
+
+ callButton->setObjectName("grey");
+ callButton->style()->polish(callButton);
+ callButton->disconnect();
+ videoButton->setObjectName("grey");
+ videoButton->style()->polish(videoButton);
+ videoButton->disconnect();
+
+ if(disableCallButtonsTimer == nullptr)
+ {
+ disableCallButtonsTimer = new QTimer();
+ connect(disableCallButtonsTimer, SIGNAL(timeout()),
+ this, SLOT(onEnableCallButtons()));
+ disableCallButtonsTimer->start(1500); // 1.5sec
+ qDebug() << "timer started!!";
+ }
+
+}
+
+void ChatForm::onEnableCallButtons()
+{
+ qDebug() << "onEnableCallButtons";
audioInputFlag = false;
audioOutputFlag = false;
micButton->setObjectName("green");
micButton->style()->polish(micButton);
volButton->setObjectName("green");
volButton->style()->polish(volButton);
- callButton->disconnect();
- videoButton->disconnect();
callButton->setObjectName("green");
callButton->style()->polish(callButton);
- callButton->disconnect();
videoButton->setObjectName("green");
videoButton->style()->polish(videoButton);
- videoButton->disconnect();
- connect(callButton, SIGNAL(clicked()), this, SLOT(onCallTriggered()));
- connect(videoButton, SIGNAL(clicked()), this, SLOT(onVideoCallTriggered()));
-
- netcam->hide();
- emit cancelCall(callId, f->getFriendID());
+
+ connect(callButton, SIGNAL(clicked()),
+ this, SLOT(onCallTriggered()));
+ connect(videoButton, SIGNAL(clicked()),
+ this, SLOT(onVideoCallTriggered()));
+ connect(micButton, SIGNAL(clicked()),
+ this, SLOT(onMicMuteToggle()));
+ connect(volButton, SIGNAL(clicked()),
+ this, SLOT(onVolMuteToggle()));
+
+ disableCallButtonsTimer->stop();
+ delete disableCallButtonsTimer;
+ disableCallButtonsTimer = nullptr;
}
void ChatForm::onMicMuteToggle()
@@ -695,6 +718,20 @@ void ChatForm::dropEvent(QDropEvent *ev)
{
QFileInfo info(url.path());
+ QFile file(info.absoluteFilePath());
+ if (!file.exists() || !file.open(QIODevice::ReadOnly))
+ {
+ QMessageBox::warning(this, tr("File not read"), tr("qTox wasn't able to open %1").arg(info.fileName()));
+ continue;
+ }
+ if (file.isSequential())
+ {
+ QMessageBox::critical(0, tr("Bad Idea"), tr("You're trying to send a special (sequential) file, that's not going to work!"));
+ file.close();
+ continue;
+ }
+ file.close();
+
if (info.exists())
Core::getInstance()->sendFile(f->getFriendID(), info.fileName(), info.absoluteFilePath(), info.size());
}
@@ -805,11 +842,11 @@ void ChatForm::onLoadHistory()
void ChatForm::startCounter()
{
- if (!timer)
+ if (!callDurationTimer)
{
- timer = new QTimer();
- connect(timer, SIGNAL(timeout()), this, SLOT(updateTime()));
- timer->start(1000);
+ callDurationTimer = new QTimer();
+ connect(callDurationTimer, SIGNAL(timeout()), this, SLOT(onUpdateTime()));
+ callDurationTimer->start(1000);
timeElapsed.start();
callDuration->show();
}
@@ -817,19 +854,20 @@ void ChatForm::startCounter()
void ChatForm::stopCounter()
{
- if (timer)
+ if (callDurationTimer)
{
addSystemInfoMessage(tr("Call with %1 ended. %2").arg(f->getDisplayedName(),secondsToDHMS(timeElapsed.elapsed()/1000)),
ChatMessage::INFO, QDateTime::currentDateTime());
- timer->stop();
+ callDurationTimer->stop();
callDuration->setText("");
callDuration->hide();
- timer = nullptr;
- delete timer;
+
+ delete callDurationTimer;
+ callDurationTimer = nullptr;
}
}
-void ChatForm::updateTime()
+void ChatForm::onUpdateTime()
{
callDuration->setText(secondsToDHMS(timeElapsed.elapsed()/1000));
}
@@ -915,3 +953,17 @@ void ChatForm::deliverOfflineMsgs()
registerReceipt(rec, iter.key(), iter.value());
}
}
+
+void ChatForm::show(Ui::MainWindow &ui)
+{
+ GenericChatForm::show(ui);
+
+ if (callConfirm)
+ callConfirm->show();
+}
+
+void ChatForm::hideEvent(QHideEvent*)
+{
+ if (callConfirm)
+ callConfirm->hide();
+}
diff --git a/src/widget/form/chatform.h b/src/widget/form/chatform.h
index 18616b803..047db5137 100644
--- a/src/widget/form/chatform.h
+++ b/src/widget/form/chatform.h
@@ -19,15 +19,19 @@
#include "genericchatform.h"
#include "src/corestructs.h"
+#include
#include
#include
#include
-#include
+
struct Friend;
class FileTransferInstance;
class NetCamView;
class QPixmap;
+class CallConfirmWidget;
+class QHideEvent;
+class QMoveEvent;
class ChatForm : public GenericChatForm
{
@@ -41,6 +45,8 @@ public:
void dischargeReceipt(int receipt);
void setFriendTyping(bool isTyping);
+ virtual void show(Ui::MainWindow &ui);
+
signals:
void sendFile(int32_t friendId, QString, QString, long long);
void startCall(int friendId);
@@ -48,6 +54,7 @@ signals:
void answerCall(int callId);
void hangupCall(int callId);
void cancelCall(int callId, int friendId);
+ void rejectCall(int callId);
void micMuteToggle(int callId);
void volMuteToggle(int callId);
void aliasChanged(const QString& alias);
@@ -83,15 +90,18 @@ private slots:
void onAnswerCallTriggered();
void onHangupCallTriggered();
void onCancelCallTriggered();
+ void onRejectCallTriggered();
void onFileSendFailed(int FriendId, const QString &fname);
void onLoadHistory();
- void updateTime();
+ void onUpdateTime();
+ void onEnableCallButtons();
protected:
// drag & drop
void dragEnterEvent(QDragEnterEvent* ev);
void dropEvent(QDropEvent* ev);
void registerReceipt(int receipt, int messageID, ChatMessage::Ptr msg);
+ virtual void hideEvent(QHideEvent* event);
private:
Friend* f;
@@ -99,7 +109,9 @@ private:
NetCamView* netcam;
int callId;
QLabel *callDuration;
- QTimer *timer;
+ QTimer *callDurationTimer;
+ QTimer typingTimer;
+ QTimer *disableCallButtonsTimer;
QElapsedTimer timeElapsed;
QHash ftransWidgets;
@@ -109,6 +121,8 @@ private:
QHash receipts;
QMap undeliveredMsgs;
bool isTyping;
+ CallConfirmWidget *callConfirm;
+ void enableCallButtons();
};
#endif // CHATFORM_H
diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp
index 5511df2e9..77aba3d7e 100644
--- a/src/widget/form/genericchatform.cpp
+++ b/src/widget/form/genericchatform.cpp
@@ -55,9 +55,12 @@ GenericChatForm::GenericChatForm(QWidget *parent)
*mainFootLayout = new QHBoxLayout();
QVBoxLayout *mainLayout = new QVBoxLayout(),
- *footButtonsSmall = new QVBoxLayout(),
- *volMicLayout = new QVBoxLayout();
- headTextLayout = new QVBoxLayout();
+ *footButtonsSmall = new QVBoxLayout(),
+ *micButtonsLayout = new QVBoxLayout();
+
+ QGridLayout *buttonsLayout = new QGridLayout();
+
+ headTextLayout = new QVBoxLayout();
chatWidget = new ChatLog(this);
chatWidget->setBusyNotification(ChatMessage::createBusyNotification());
@@ -123,28 +126,37 @@ GenericChatForm::GenericChatForm(QWidget *parent)
mainFootLayout->addWidget(sendButton);
mainFootLayout->setSpacing(0);
- headTextLayout->addStretch();
+ headTextLayout->addStretch();
headTextLayout->addWidget(nameLabel);
-
- volMicLayout->addWidget(micButton, Qt::AlignTop);
- volMicLayout->addSpacing(2);
- volMicLayout->addWidget(volButton, Qt::AlignBottom);
+ headTextLayout->addStretch();
+
+ micButtonsLayout->setSpacing(0);
+ micButtonsLayout->addWidget(micButton, Qt::AlignTop | Qt::AlignRight);
+ micButtonsLayout->addSpacing(4);
+ micButtonsLayout->addWidget(volButton, Qt::AlignTop | Qt::AlignRight);
+
+ buttonsLayout->addLayout(micButtonsLayout, 0, 0, 2, 1, Qt::AlignTop | Qt::AlignRight);
+ buttonsLayout->addWidget(callButton, 0, 1, 2, 1, Qt::AlignTop);
+ buttonsLayout->addWidget(videoButton, 0, 2, 2, 1, Qt::AlignTop);
+ buttonsLayout->setVerticalSpacing(0);
+ buttonsLayout->setHorizontalSpacing(4);
+
+ headLayout->addWidget(avatar, Qt::AlignTop | Qt::AlignLeft);
+ headLayout->addSpacing(5);
+ headLayout->addLayout(headTextLayout, Qt::AlignTop | Qt::AlignAbsolute);
+ headLayout->addLayout(buttonsLayout, Qt::AlignTop | Qt::AlignRight);
headWidget->setLayout(headLayout);
- headLayout->addWidget(avatar);
- headLayout->addSpacing(5);
- headLayout->addLayout(headTextLayout);
- headLayout->addLayout(volMicLayout);
- headLayout->addWidget(callButton);
- headLayout->addSpacing(3);
- headLayout->addWidget(videoButton);
- headLayout->setSpacing(0);
-
+
//Fix for incorrect layouts on OS X as per
//https://bugreports.qt-project.org/browse/QTBUG-14591
sendButton->setAttribute(Qt::WA_LayoutUsesWidgetRect);
fileButton->setAttribute(Qt::WA_LayoutUsesWidgetRect);
emoteButton->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ micButton->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ volButton->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ callButton->setAttribute(Qt::WA_LayoutUsesWidgetRect);
+ videoButton->setAttribute(Qt::WA_LayoutUsesWidgetRect);
menu.addActions(chatWidget->actions());
menu.addSeparator();
diff --git a/src/widget/form/settings/advancedform.cpp b/src/widget/form/settings/advancedform.cpp
index 44d4ecd13..6a4887217 100644
--- a/src/widget/form/settings/advancedform.cpp
+++ b/src/widget/form/settings/advancedform.cpp
@@ -30,6 +30,7 @@ AdvancedForm::AdvancedForm() :
bodyUI->dbLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
bodyUI->dbLabel->setOpenExternalLinks(true);
+ bodyUI->cbMakeToxPortable->setChecked(Settings::getInstance().getMakeToxPortable());
bodyUI->syncTypeComboBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength);
bodyUI->syncTypeComboBox->addItems({tr("FULL - very safe, slowest (recommended)"),
tr("NORMAL - almost as safe as FULL, about 20% faster than FULL"),
@@ -38,6 +39,7 @@ AdvancedForm::AdvancedForm() :
int index = 2 - static_cast(Settings::getInstance().getDbSyncType());
bodyUI->syncTypeComboBox->setCurrentIndex(index);
+ connect(bodyUI->cbMakeToxPortable, &QCheckBox::stateChanged, this, &AdvancedForm::onMakeToxPortableUpdated);
connect(bodyUI->syncTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onDbSyncTypeUpdated()));
connect(bodyUI->resetButton, SIGNAL(clicked()), this, SLOT(resetToDefault()));
}
@@ -47,6 +49,11 @@ AdvancedForm::~AdvancedForm()
delete bodyUI;
}
+void AdvancedForm::onMakeToxPortableUpdated()
+{
+ Settings::getInstance().setMakeToxPortable(bodyUI->cbMakeToxPortable->isChecked());
+}
+
void AdvancedForm::onDbSyncTypeUpdated()
{
int index = 2 - bodyUI->syncTypeComboBox->currentIndex();
diff --git a/src/widget/form/settings/advancedform.h b/src/widget/form/settings/advancedform.h
index 2b0d3cbcb..4a1fecf22 100644
--- a/src/widget/form/settings/advancedform.h
+++ b/src/widget/form/settings/advancedform.h
@@ -33,6 +33,7 @@ public:
virtual ~AdvancedForm();
private slots:
+ void onMakeToxPortableUpdated();
void onDbSyncTypeUpdated();
void resetToDefault();
diff --git a/src/widget/form/settings/advancedsettings.ui b/src/widget/form/settings/advancedsettings.ui
index 33df4b8ee..d4213713c 100644
--- a/src/widget/form/settings/advancedsettings.ui
+++ b/src/widget/form/settings/advancedsettings.ui
@@ -29,6 +29,16 @@
+ -
+
+
+ Save settings to the working directory instead of the usual conf dir
+
+
+ Make Tox portable
+
+
+
-
diff --git a/src/widget/form/settings/avform.cpp b/src/widget/form/settings/avform.cpp
index 31f9b6dd9..3c170821e 100644
--- a/src/widget/form/settings/avform.cpp
+++ b/src/widget/form/settings/avform.cpp
@@ -47,6 +47,7 @@ AVForm::AVForm() :
connect(bodyUI->outDevCombobox, qcomboboxIndexChanged, this, &AVForm::onOutDevChanged);
connect(bodyUI->filterAudio, SIGNAL(toggled(bool)), this, SLOT(onFilterAudioToggled(bool)));
connect(bodyUI->rescanButton, &QPushButton::clicked, this, [=](){getAudioInDevices(); getAudioOutDevices();});
+ bodyUI->playbackSlider->setValue(100);
}
AVForm::~AVForm()
@@ -67,6 +68,10 @@ void AVForm::present()
Camera::getInstance()->probeProp(Camera::HUE);
Camera::getInstance()->probeResolutions();
+
+ bodyUI->videoModescomboBox->blockSignals(true);
+ bodyUI->videoModescomboBox->addItem(tr("Initializing Camera..."));
+ bodyUI->videoModescomboBox->blockSignals(false);
}
void AVForm::on_ContrastSlider_sliderMoved(int position)
@@ -89,9 +94,11 @@ void AVForm::on_HueSlider_sliderMoved(int position)
Camera::getInstance()->setProp(Camera::HUE, position / 100.0);
}
-void AVForm::on_videoModescomboBox_activated(int index)
+void AVForm::on_videoModescomboBox_currentIndexChanged(int index)
{
- Camera::getInstance()->setResolution(bodyUI->videoModescomboBox->itemData(index).toSize());
+ QSize res = bodyUI->videoModescomboBox->itemData(index).toSize();
+ Settings::getInstance().setCamVideoRes(res);
+ Camera::getInstance()->setResolution(res);
}
void AVForm::onPropProbingFinished(Camera::Prop prop, double val)
@@ -117,11 +124,25 @@ void AVForm::onPropProbingFinished(Camera::Prop prop, double val)
void AVForm::onResProbingFinished(QList res)
{
+ QSize savedRes = Settings::getInstance().getCamVideoRes();
+ int savedResIndex = -1;
bodyUI->videoModescomboBox->clear();
- for (QSize r : res)
+ bodyUI->videoModescomboBox->blockSignals(true);
+ for (int i=0; ivideoModescomboBox->addItem(QString("%1x%2").arg(QString::number(r.width()),QString::number(r.height())), r);
+ if (r == savedRes)
+ savedResIndex = i;
+ }
+ //reset index, otherwise cameras with only one resolution won't get initialized
+ bodyUI->videoModescomboBox->setCurrentIndex(-1);
+ bodyUI->videoModescomboBox->blockSignals(false);
- bodyUI->videoModescomboBox->setCurrentIndex(bodyUI->videoModescomboBox->count()-1);
+ if (savedResIndex != -1)
+ bodyUI->videoModescomboBox->setCurrentIndex(savedResIndex);
+ else
+ bodyUI->videoModescomboBox->setCurrentIndex(bodyUI->videoModescomboBox->count()-1);
}
void AVForm::hideEvent(QHideEvent *)
@@ -129,36 +150,47 @@ void AVForm::hideEvent(QHideEvent *)
bodyUI->CamVideoSurface->setSource(nullptr);
}
+void AVForm::showEvent(QShowEvent *)
+{
+ bodyUI->CamVideoSurface->setSource(Camera::getInstance());
+}
+
void AVForm::getAudioInDevices()
{
QString settingsInDev = Settings::getInstance().getInDev();
- bool inDevFound = false;
+ int inDevIndex = 0;
bodyUI->inDevCombobox->clear();
const ALchar *pDeviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
if (pDeviceList)
{
+ //prevent currentIndexChanged to be fired while adding items
+ bodyUI->inDevCombobox->blockSignals(true);
while (*pDeviceList)
{
int len = strlen(pDeviceList);
- QString inDev = QString::fromLocal8Bit(pDeviceList,len);
+#ifdef Q_OS_WIN32
+ QString inDev = QString::fromUtf8(pDeviceList,len);
+#else
+ QString inDev = QString::fromLocal8Bit(pDeviceList,len);
+#endif
bodyUI->inDevCombobox->addItem(inDev);
if (settingsInDev == inDev)
{
- bodyUI->inDevCombobox->setCurrentIndex(bodyUI->inDevCombobox->count()-1);
- inDevFound = true;
+ inDevIndex = bodyUI->inDevCombobox->count()-1;
}
pDeviceList += len+1;
}
+ //addItem changes currentIndex -> reset
+ bodyUI->inDevCombobox->setCurrentIndex(-1);
+ bodyUI->inDevCombobox->blockSignals(false);
}
-
- if (!inDevFound)
- Settings::getInstance().setInDev(bodyUI->inDevCombobox->itemText(0));
+ bodyUI->inDevCombobox->setCurrentIndex(inDevIndex);
}
void AVForm::getAudioOutDevices()
{
QString settingsOutDev = Settings::getInstance().getOutDev();
- bool outDevFound = false;
+ int outDevIndex = 0;
bodyUI->outDevCombobox->clear();
const ALchar *pDeviceList;
if (alcIsExtensionPresent(NULL, "ALC_ENUMERATE_ALL_EXT") != AL_FALSE)
@@ -167,22 +199,28 @@ void AVForm::getAudioOutDevices()
pDeviceList = alcGetString(NULL, ALC_DEVICE_SPECIFIER);
if (pDeviceList)
{
+ //prevent currentIndexChanged to be fired while adding items
+ bodyUI->outDevCombobox->blockSignals(true);
while (*pDeviceList)
{
int len = strlen(pDeviceList);
- QString outDev = QString::fromLocal8Bit(pDeviceList,len);
+#ifdef Q_OS_WIN32
+ QString outDev = QString::fromUtf8(pDeviceList,len);
+#else
+ QString outDev = QString::fromLocal8Bit(pDeviceList,len);
+#endif
bodyUI->outDevCombobox->addItem(outDev);
if (settingsOutDev == outDev)
{
- bodyUI->outDevCombobox->setCurrentIndex(bodyUI->outDevCombobox->count()-1);
- outDevFound = true;
+ outDevIndex = bodyUI->outDevCombobox->count()-1;
}
pDeviceList += len+1;
}
+ //addItem changes currentIndex -> reset
+ bodyUI->outDevCombobox->setCurrentIndex(-1);
+ bodyUI->outDevCombobox->blockSignals(false);
}
-
- if (!outDevFound)
- Settings::getInstance().setOutDev(bodyUI->outDevCombobox->itemText(0));
+ bodyUI->outDevCombobox->setCurrentIndex(outDevIndex);
}
void AVForm::onInDevChanged(const QString &deviceDescriptor)
@@ -201,3 +239,28 @@ void AVForm::onFilterAudioToggled(bool filterAudio)
{
Settings::getInstance().setFilterAudio(filterAudio);
}
+
+void AVForm::on_HueSlider_valueChanged(int value)
+{
+ Camera::getInstance()->setProp(Camera::HUE, value / 100.0);
+}
+
+void AVForm::on_BrightnessSlider_valueChanged(int value)
+{
+ Camera::getInstance()->setProp(Camera::BRIGHTNESS, value / 100.0);
+}
+
+void AVForm::on_SaturationSlider_valueChanged(int value)
+{
+ Camera::getInstance()->setProp(Camera::SATURATION, value / 100.0);
+}
+
+void AVForm::on_ContrastSlider_valueChanged(int value)
+{
+ Camera::getInstance()->setProp(Camera::CONTRAST, value / 100.0);
+}
+
+void AVForm::on_playbackSlider_valueChanged(int value)
+{
+ Audio::getInstance().outputVolume = value / 100.0;
+}
diff --git a/src/widget/form/settings/avform.h b/src/widget/form/settings/avform.h
index 64b34d410..9b3980189 100644
--- a/src/widget/form/settings/avform.h
+++ b/src/widget/form/settings/avform.h
@@ -47,18 +47,28 @@ private slots:
void on_SaturationSlider_sliderMoved(int position);
void on_BrightnessSlider_sliderMoved(int position);
void on_HueSlider_sliderMoved(int position);
- void on_videoModescomboBox_activated(int index);
+ void on_videoModescomboBox_currentIndexChanged(int index);
// audio
void onInDevChanged(const QString& deviceDescriptor);
void onOutDevChanged(const QString& deviceDescriptor);
void onFilterAudioToggled(bool filterAudio);
+ void on_playbackSlider_valueChanged(int value);
// camera
void onPropProbingFinished(Camera::Prop prop, double val);
void onResProbingFinished(QList res);
virtual void hideEvent(QHideEvent*);
+ virtual void showEvent(QShowEvent*);
+
+ void on_HueSlider_valueChanged(int value);
+
+ void on_BrightnessSlider_valueChanged(int value);
+
+ void on_SaturationSlider_valueChanged(int value);
+
+ void on_ContrastSlider_valueChanged(int value);
private:
Ui::AVSettings *bodyUI;
diff --git a/src/widget/form/settings/avsettings.ui b/src/widget/form/settings/avsettings.ui
index e46c7d43f..81cb23026 100644
--- a/src/widget/form/settings/avsettings.ui
+++ b/src/widget/form/settings/avsettings.ui
@@ -60,6 +60,9 @@
Qt::Horizontal
+
+ Use slider to set volume of your speakers.
+
-
@@ -67,6 +70,10 @@
Qt::Horizontal
+
+ Use slider to set volume of your microphone.
+WARNING: slider is not supposed to work yet.
+
-
@@ -101,6 +108,9 @@
Filter audio
+
+ Filter sound from your microphone, so that people hearing you would get better sound.
+
@@ -122,6 +132,13 @@
Resolution
+
+ Set resolution of your camera.
+The higher values, the better video quality your friends may get.
+Note though that with better video quality there is needed better internet connection.
+Sometimes your connection may not be good enough to handle higher video quality,
+which may lead to problems with video calls.
+
-
@@ -132,6 +149,13 @@
0
+
+ Set resolution of your camera.
+The higher values, the better video quality your friends may get.
+Note though that with better video quality there is needed better internet connection.
+Sometimes your connection may not be good enough to handle higher video quality,
+which may lead to problems with video calls.
+
-
diff --git a/src/widget/form/settings/generalform.cpp b/src/widget/form/settings/generalform.cpp
index 726406fb9..8b74a1941 100644
--- a/src/widget/form/settings/generalform.cpp
+++ b/src/widget/form/settings/generalform.cpp
@@ -30,8 +30,8 @@
#include "src/autoupdate.h"
-static QStringList locales = {"bg", "de", "en", "es", "fr", "it", "mannol", "pirate", "pl", "pt", "ru", "fi", "sv", "uk"};
-static QStringList langs = {"Български", "Deutsch", "English", "Español", "Français", "Italiano", "mannol", "Pirate", "Polski", "Português", "Русский", "Suomi", "Svenska", "Українська"};
+static QStringList locales = {"bg", "de", "en", "es", "fr", "it", "lt", "mannol", "pirate", "pl", "pt", "ru", "fi", "sv", "uk"};
+static QStringList langs = {"Български", "Deutsch", "English", "Español", "Français", "Italiano", "Lietuvių", "mannol", "Pirate", "Polski", "Português", "Русский", "Suomi", "Svenska", "Українська"};
static QStringList timeFormats = {"hh:mm AP", "hh:mm", "hh:mm:ss AP", "hh:mm:ss"};
@@ -45,16 +45,14 @@ GeneralForm::GeneralForm(SettingsWidget *myParent) :
bodyUI->checkUpdates->setVisible(AUTOUPDATE_ENABLED);
bodyUI->checkUpdates->setChecked(Settings::getInstance().getCheckUpdates());
- bodyUI->trayBehavior->addStretch();
bodyUI->cbEnableIPv6->setChecked(Settings::getInstance().getEnableIPv6());
for (int i = 0; i < langs.size(); i++)
bodyUI->transComboBox->insertItem(i, langs[i]);
bodyUI->transComboBox->setCurrentIndex(locales.indexOf(Settings::getInstance().getTranslation()));
- bodyUI->cbMakeToxPortable->setChecked(Settings::getInstance().getMakeToxPortable());
bool showSystemTray = Settings::getInstance().getShowSystemTray();
-
+
bodyUI->showSystemTray->setChecked(showSystemTray);
bodyUI->startInTray->setChecked(Settings::getInstance().getAutostartInTray());
bodyUI->startInTray->setEnabled(showSystemTray);
@@ -68,8 +66,11 @@ GeneralForm::GeneralForm(SettingsWidget *myParent) :
bodyUI->useEmoticons->setChecked(Settings::getInstance().getUseEmoticons());
bodyUI->autoacceptFiles->setChecked(Settings::getInstance().getAutoSaveEnabled());
bodyUI->autoSaveFilesDir->setText(Settings::getInstance().getGlobalAutoAcceptDir());
+ bodyUI->showWindow->setChecked(Settings::getInstance().getShowWindow());
bodyUI->showInFront->setChecked(Settings::getInstance().getShowInFront());
+ bodyUI->groupAlwaysNotify->setChecked(Settings::getInstance().getGroupAlwaysNotify());
bodyUI->cbFauxOfflineMessaging->setChecked(Settings::getInstance().getFauxOfflineMessaging());
+ bodyUI->cbCompactLayout->setChecked(Settings::getInstance().getCompactLayout());
for (auto entry : SmileyPack::listSmileyPacks())
{
@@ -117,7 +118,6 @@ GeneralForm::GeneralForm(SettingsWidget *myParent) :
//general
connect(bodyUI->checkUpdates, &QCheckBox::stateChanged, this, &GeneralForm::onCheckUpdateChanged);
connect(bodyUI->transComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onTranslationUpdated()));
- connect(bodyUI->cbMakeToxPortable, &QCheckBox::stateChanged, this, &GeneralForm::onMakeToxPortableUpdated);
connect(bodyUI->showSystemTray, &QCheckBox::stateChanged, this, &GeneralForm::onSetShowSystemTray);
connect(bodyUI->startInTray, &QCheckBox::stateChanged, this, &GeneralForm::onSetAutostartInTray);
connect(bodyUI->closeToTray, &QCheckBox::stateChanged, this, &GeneralForm::onSetCloseToTray);
@@ -125,7 +125,9 @@ GeneralForm::GeneralForm(SettingsWidget *myParent) :
connect(bodyUI->lightTrayIcon, &QCheckBox::stateChanged, this, &GeneralForm::onSetLightTrayIcon);
connect(bodyUI->statusChanges, &QCheckBox::stateChanged, this, &GeneralForm::onSetStatusChange);
connect(bodyUI->autoAwaySpinBox, SIGNAL(editingFinished()), this, SLOT(onAutoAwayChanged()));
+ connect(bodyUI->showWindow, &QCheckBox::stateChanged, this, &GeneralForm::onShowWindowChanged);
connect(bodyUI->showInFront, &QCheckBox::stateChanged, this, &GeneralForm::onSetShowInFront);
+ connect(bodyUI->groupAlwaysNotify, &QCheckBox::stateChanged, this, &GeneralForm::onSetGroupAlwaysNotify);
connect(bodyUI->autoacceptFiles, &QCheckBox::stateChanged, this, &GeneralForm::onAutoAcceptFileChange);
if (bodyUI->autoacceptFiles->isChecked())
connect(bodyUI->autoSaveFilesDir, SIGNAL(clicked()), this, SLOT(onAutoSaveDirChange()));
@@ -144,6 +146,7 @@ GeneralForm::GeneralForm(SettingsWidget *myParent) :
connect(bodyUI->proxyPort, SIGNAL(valueChanged(int)), this, SLOT(onProxyPortEdited(int)));
connect(bodyUI->reconnectButton, &QPushButton::clicked, this, &GeneralForm::onReconnectClicked);
connect(bodyUI->cbFauxOfflineMessaging, &QCheckBox::stateChanged, this, &GeneralForm::onFauxOfflineMessaging);
+ connect(bodyUI->cbCompactLayout, &QCheckBox::stateChanged, this, &GeneralForm::onCompactLayout);
#ifndef QTOX_PLATFORM_EXT
bodyUI->autoAwayLabel->setEnabled(false); // these don't seem to change the appearance of the widgets,
@@ -167,11 +170,6 @@ void GeneralForm::onTranslationUpdated()
Widget::getInstance()->setTranslation();
}
-void GeneralForm::onMakeToxPortableUpdated()
-{
- Settings::getInstance().setMakeToxPortable(bodyUI->cbMakeToxPortable->isChecked());
-}
-
void GeneralForm::onSetShowSystemTray()
{
Settings::getInstance().setShowSystemTray(bodyUI->showSystemTray->isChecked());
@@ -330,9 +328,19 @@ void GeneralForm::onCheckUpdateChanged()
Settings::getInstance().setCheckUpdates(bodyUI->checkUpdates->isChecked());
}
+void GeneralForm::onShowWindowChanged()
+{
+ Settings::getInstance().setShowWindow(bodyUI->showWindow->isChecked());
+}
+
void GeneralForm::onSetShowInFront()
{
- Settings::getInstance().setShowInFront(bodyUI->showInFront->isChecked());
+ Settings::getInstance().setShowInFront(bodyUI->showInFront->isChecked());
+}
+
+void GeneralForm::onSetGroupAlwaysNotify()
+{
+ Settings::getInstance().setGroupAlwaysNotify(bodyUI->groupAlwaysNotify->isChecked());
}
void GeneralForm::onFauxOfflineMessaging()
@@ -340,6 +348,12 @@ void GeneralForm::onFauxOfflineMessaging()
Settings::getInstance().setFauxOfflineMessaging(bodyUI->cbFauxOfflineMessaging->isChecked());
}
+void GeneralForm::onCompactLayout()
+{
+ Settings::getInstance().setCompactLayout(bodyUI->cbCompactLayout->isChecked());
+ emit parent->compactToggled(bodyUI->cbCompactLayout->isChecked());
+}
+
void GeneralForm::onThemeColorChanged(int)
{
int index = bodyUI->themeColorCBox->currentIndex();
diff --git a/src/widget/form/settings/generalform.h b/src/widget/form/settings/generalform.h
index a560cf7ae..d21f5fd52 100644
--- a/src/widget/form/settings/generalform.h
+++ b/src/widget/form/settings/generalform.h
@@ -33,7 +33,6 @@ public:
private slots:
void onEnableIPv6Updated();
void onTranslationUpdated();
- void onMakeToxPortableUpdated();
void onSetShowSystemTray();
void onSetAutostartInTray();
void onSetCloseToTray();
@@ -54,8 +53,11 @@ private slots:
void onAutoAcceptFileChange();
void onAutoSaveDirChange();
void onCheckUpdateChanged();
+ void onShowWindowChanged();
void onSetShowInFront();
+ void onSetGroupAlwaysNotify();
void onFauxOfflineMessaging();
+ void onCompactLayout();
void onThemeColorChanged(int);
private:
diff --git a/src/widget/form/settings/generalsettings.ui b/src/widget/form/settings/generalsettings.ui
index 762b39447..c67f7b0be 100644
--- a/src/widget/form/settings/generalsettings.ui
+++ b/src/widget/form/settings/generalsettings.ui
@@ -6,7 +6,7 @@
0
0
- 545
+ 573
644
@@ -34,16 +34,16 @@
Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop
-
+
0
- -173
- 511
- 797
+ 0
+ 544
+ 785
-
+
9
@@ -57,14 +57,14 @@
-
-
+
-
The translation may not load until qTox restarts.
- Translation
+ Language:
@@ -81,27 +81,30 @@
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
- -
-
-
- Save settings to the working directory instead of the usual conf dir
-
-
- Make Tox portable
-
-
-
-
- System tray integration
+ System tray
-
-
- QFormLayout::AllNonFixedFieldsGrow
-
+
+ Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter
+
+
-
@@ -109,103 +112,131 @@
- -
-
-
-
-
-
-
- 0
- 0
-
-
-
- Start in tray
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Close to tray
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Minimize to tray
-
-
-
-
-
-
Light icon
+
+ Enable light tray icon.
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Start in tray
+
+
+ qTox will start minimized in tray.
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Close to tray
+
+
+ After pressing close (X) qTox will minimize to tray,
+instead of closing itself.
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Minimize to tray
+
+
+ After pressing minimize (_) qTox will minimize itself to tray,
+instead of system taskbar.
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
- -
-
-
- Show contacts' status changes
-
-
-
-
- Check for updates on startup (unstable)
+ Check for updates on startup
-
-
-
- Focus qTox when a message is received
+
+
+ 0
-
-
- -
-
-
- Faux offline messaging
-
-
-
- -
-
-
-
-
-
- Provided in minutes
-
-
- Qt::LeftToRight
-
+
-
+
- Auto away after (0 to disable)
+ Save to:
+
+
+ Set where files will be saved.
- -
+
-
+
+
+ You can set this on a per-friend basis by right clicking them.
+
+
+ Autoaccept files
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+ PushButton
+
+
+ Set where files will be saved.
+
+
+
+ -
@@ -230,46 +261,116 @@
-
-
- -
-
-
-
-
+
-
+
- You can set this on a per-friend basis by right clicking them.
+ Your status is changed to Away after set period of inactivity.
+
+
+ Qt::LeftToRight
- Autoaccept files
+ Auto away after (0 to disable):
+
+
+
+
+
+
+
+
+ -
+
+
+ Chat
+
+
+
-
+
+
+ Always notify about new messages in groupchats.
+
+
+ Group chats always notify
+
+
+
+ -
+
+
+ Show contacts' status changes
+
+
+
+ -
+
+
+ On new message:
+
+
+
+ -
+
+
+ 0
+
+
-
+
+
+ Show qTox's window when you receive new message.
+
+
+ Show window
-
-
-
-
-
-
- Save files in
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
- PushButton
-
-
-
-
+
+
+ Focus qTox when you receive message.
+
+
+ Focus window
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Messages you are trying to send to your friends when they are not online
+will be sent to them when they will appear online to you.
+
+
+ Faux offline messaging
+
+
+
+ -
+
+
+ Your contact list will be shown in compact mode.
+qTox's restart needed.
+
+
+ Compact contact list
+
+
+
@@ -306,7 +407,7 @@
-
- Smiley Pack
+ Smiley Pack:
@@ -378,47 +479,13 @@
-
-
+
- Style
+ Emoticon size:
-
-
-
-
- 0
- 0
-
-
-
-
- -
-
-
- Theme color
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- -
-
-
- Emoticon size
-
-
-
- -
@@ -443,10 +510,44 @@
+ -
+
+
+ Style:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+ Theme color:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
-
- Timestamp format
+ Timestamp format:
@@ -478,32 +579,76 @@
9
-
-
-
- Enable IPv6 (recommended)
-
-
-
- -
-
-
- Disabling this allows, e.g., toxing over Tor. It adds load to the Tox network however, so uncheck only when necessary.
-
-
- Enable UDP (recommended)
-
-
-
- -
-
+
-
-
+
+
+ Disabling this allows, e.g., toxing over Tor. It adds load to the Tox network however, so uncheck only when necessary.
+
- Proxy type
+ Enable UDP (recommended)
-
+
+
+ Enable IPv6 (recommended)
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
-
+
+
+ 0
+
+
+ 65535
+
+
+
+ -
+
+
+ Proxy type:
+
+
+
+ -
+
+
+ Address:
+
+
+
+ -
+
+
+ -
+
+
+ Port
+
+
+
+ -
@@ -530,40 +675,6 @@
- -
-
-
- 6
-
-
-
-
-
- Address
-
-
-
- -
-
-
- -
-
-
- Port
-
-
-
- -
-
-
- 0
-
-
- 65535
-
-
-
-
-
-
@@ -630,5 +741,21 @@
+
+ showWindow
+ toggled(bool)
+ showInFront
+ setEnabled(bool)
+
+
+ 329
+ 349
+
+
+ 451
+ 349
+
+
+
diff --git a/src/widget/form/settings/identityform.cpp b/src/widget/form/settings/identityform.cpp
index e1f46d7e4..a5cfc2aa6 100644
--- a/src/widget/form/settings/identityform.cpp
+++ b/src/widget/form/settings/identityform.cpp
@@ -46,9 +46,9 @@ IdentityForm::IdentityForm() :
bodyUI->toxGroup->layout()->addWidget(toxId);
- timer.setInterval(1000);
+ timer.setInterval(750);
timer.setSingleShot(true);
- connect(&timer, &QTimer::timeout, this, [=]() {bodyUI->toxIdLabel->setText(bodyUI->toxIdLabel->text().replace(" ✔", ""));});
+ connect(&timer, &QTimer::timeout, this, [=]() {bodyUI->toxIdLabel->setText(bodyUI->toxIdLabel->text().replace(" ✔", "")); hasCheck = false;});
connect(bodyUI->toxIdLabel, SIGNAL(clicked()), this, SLOT(copyIdClicked()));
connect(toxId, SIGNAL(clicked()), this, SLOT(copyIdClicked()));
@@ -89,7 +89,11 @@ void IdentityForm::copyIdClicked()
QApplication::clipboard()->setText(txt);
toxId->setCursorPosition(0);
- bodyUI->toxIdLabel->setText(bodyUI->toxIdLabel->text() + " ✔");
+ if (!hasCheck)
+ {
+ bodyUI->toxIdLabel->setText(bodyUI->toxIdLabel->text() + " ✔");
+ hasCheck = true;
+ }
timer.start();
}
diff --git a/src/widget/form/settings/identityform.h b/src/widget/form/settings/identityform.h
index b30ec8070..843d7e7b1 100644
--- a/src/widget/form/settings/identityform.h
+++ b/src/widget/form/settings/identityform.h
@@ -74,6 +74,7 @@ private:
Ui::IdentitySettings* bodyUI;
Core* core;
QTimer timer;
+ bool hasCheck = false;
ClickableTE* toxId;
};
diff --git a/src/widget/form/settings/identitysettings.ui b/src/widget/form/settings/identitysettings.ui
index e5c25f94a..c2d85d082 100644
--- a/src/widget/form/settings/identitysettings.ui
+++ b/src/widget/form/settings/identitysettings.ui
@@ -81,6 +81,10 @@
Tox ID
+
+ This bunch of characters tells other Tox clients how to contact you.
+Share it with your friends to communicate.
+
-
@@ -109,6 +113,9 @@
-
+
+ Currently selected profile.
+
0
@@ -124,7 +131,7 @@
-
- Switching profiles is disabled during calls
+ Load selected profile and switch to it.
Load
@@ -136,6 +143,9 @@
Rename
+
+ Rename selected profile.
+
-
@@ -143,12 +153,16 @@
Export
+
+ Allows you to export your Tox profile to a file.
+Profile does not contain your history.
+
-
- This is useful to remain safe on public computers
+ Delete selected profile.
Delete
@@ -164,12 +178,15 @@
Import a profile
+
+ Import Tox profile from a .tox file.
+
-
- Switching profiles is disabled during calls
+ Create new Tox ID and switch to it.
New Tox ID
diff --git a/src/widget/form/settings/privacysettings.ui b/src/widget/form/settings/privacysettings.ui
index 72262c327..0e5ba073e 100644
--- a/src/widget/form/settings/privacysettings.ui
+++ b/src/widget/form/settings/privacysettings.ui
@@ -44,7 +44,7 @@
-
-
+ Your friends will be able to see when you are typing.
Send Typing Notifications
@@ -54,7 +54,8 @@
-
-
+ History keeping is still in development.
+Save format changes are possible, which may result in data loss.
Keep History (unstable)
@@ -101,6 +102,12 @@
Nospam
+
+ Nospam is part of your Tox ID.
+It is there to help you change your Tox ID when you feel like you are getting too much spam friend requests.
+When you change nospam, your current contacts still can communicate with you,
+but new contacts need to know your new Tox ID to be able to add you.
+
-
diff --git a/src/widget/form/settingswidget.h b/src/widget/form/settingswidget.h
index 2c415f696..0449e16cf 100644
--- a/src/widget/form/settingswidget.h
+++ b/src/widget/form/settingswidget.h
@@ -42,15 +42,15 @@ public:
void show(Ui::MainWindow &ui);
void setBodyHeadStyle(QString style);
+signals:
+ void setShowSystemTray(bool newValue);
+ void compactToggled(bool compact);
+
private slots:
void onTabChanged(int);
-signals:
- void setShowSystemTray(bool newValue);
-
private:
- QWidget *head, *body; // keep the others private
- IdentityForm *ifrm;
+ QWidget *head, *body;
QTabWidget *settingsWidgets;
QLabel *nameLabel, *imgLabel;
};
diff --git a/src/widget/form/tabcompleter.cpp b/src/widget/form/tabcompleter.cpp
index 2fbaa48c7..382fb6c8f 100644
--- a/src/widget/form/tabcompleter.cpp
+++ b/src/widget/form/tabcompleter.cpp
@@ -28,7 +28,8 @@
const QString TabCompleter::nickSuffix = QString(": ");
TabCompleter::TabCompleter(ChatTextEdit* msgEdit, Group* group)
- : QObject(msgEdit), msgEdit(msgEdit), group(group), enabled(false)
+ : QObject{msgEdit}, msgEdit{msgEdit}, group{group},
+ enabled{false}, lastCompletionLength{0}
{
}
@@ -70,9 +71,11 @@ void TabCompleter::complete()
if (nextCompletion != completionMap.end()) {
// clear previous completion
- for (int i = 0; i < lastCompletionLength; i++) {
- msgEdit->keyPressEvent(new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier));
- }
+ auto cur = msgEdit->textCursor();
+ cur.setPosition(cur.selectionEnd());
+ msgEdit->setTextCursor(cur);
+ for (int i = 0; i < lastCompletionLength; i++)
+ msgEdit->textCursor().deletePreviousChar();
// insert completion
msgEdit->insertPlainText(*nextCompletion);
@@ -95,7 +98,6 @@ void TabCompleter::complete()
}
}
-
void TabCompleter::reset()
{
enabled = false;
diff --git a/src/widget/form/tabcompleter.h b/src/widget/form/tabcompleter.h
index f48b1a797..23a3fe000 100644
--- a/src/widget/form/tabcompleter.h
+++ b/src/widget/form/tabcompleter.h
@@ -40,7 +40,7 @@ public slots:
private:
struct SortableString {
- inline SortableString(const QString &n) { contents = n; }
+ inline SortableString(const QString &n) : contents{n} {}
bool operator<(const SortableString &other) const;
QString contents;
};
diff --git a/src/widget/genericchatroomwidget.cpp b/src/widget/genericchatroomwidget.cpp
index 724e2e419..8a46eab04 100644
--- a/src/widget/genericchatroomwidget.cpp
+++ b/src/widget/genericchatroomwidget.cpp
@@ -16,6 +16,7 @@
#include "genericchatroomwidget.h"
#include "src/misc/style.h"
+#include "src/misc/settings.h"
#include "maskablepixmapwidget.h"
#include "croppinglabel.h"
#include
@@ -24,17 +25,17 @@
GenericChatroomWidget::GenericChatroomWidget(QWidget *parent)
: QFrame(parent)
{
- setFixedHeight(55);
-
- setLayout(&layout);
- layout.setSpacing(0);
- layout.setMargin(0);
- textLayout.setSpacing(0);
- textLayout.setMargin(0);
- setLayoutDirection(Qt::LeftToRight); // parent might have set Qt::RightToLeft
+ setProperty("compact", Settings::getInstance().getCompactLayout());
// avatar
- avatar = new MaskablePixmapWidget(this, QSize(40,40), ":/img/avatar_mask.png");
+ if (property("compact").toBool())
+ {
+ avatar = new MaskablePixmapWidget(this, QSize(20,20), ":/img/avatar_mask.png");
+ }
+ else
+ {
+ avatar = new MaskablePixmapWidget(this, QSize(40,40), ":/img/avatar_mask.png");
+ }
// status text
statusMessageLabel = new CroppingLabel(this);
@@ -44,24 +45,65 @@ GenericChatroomWidget::GenericChatroomWidget(QWidget *parent)
nameLabel = new CroppingLabel(this);
nameLabel->setObjectName("name");
- textLayout.addStretch();
- textLayout.addWidget(nameLabel);
- textLayout.addWidget(statusMessageLabel);
- textLayout.addStretch();
-
- layout.addSpacing(20);
- layout.addWidget(avatar);
- layout.addSpacing(10);
- layout.addLayout(&textLayout);
- layout.addSpacing(10);
- layout.addWidget(&statusPic);
- layout.addSpacing(10);
- layout.activate();
+ onCompactChanged(property("compact").toBool());
setProperty("active", false);
setStyleSheet(Style::getStylesheet(":/ui/chatroomWidgets/genericChatroomWidget.css"));
}
+void GenericChatroomWidget::onCompactChanged(bool _compact)
+{
+ delete textLayout; // has to be first, deleted by layout
+ delete layout;
+
+ setProperty("compact", _compact);
+
+ layout = new QHBoxLayout;
+ textLayout = new QVBoxLayout;
+
+ setLayout(layout);
+ layout->setSpacing(0);
+ layout->setMargin(0);
+ textLayout->setSpacing(0);
+ textLayout->setMargin(0);
+ setLayoutDirection(Qt::LeftToRight); // parent might have set Qt::RightToLeft
+
+ // avatar
+ if (property("compact").toBool())
+ {
+ setFixedHeight(25);
+ avatar->setSize(QSize(20,20));
+ layout->addSpacing(18);
+ layout->addWidget(avatar);
+ layout->addSpacing(5);
+ layout->addWidget(nameLabel);
+ layout->addWidget(statusMessageLabel);
+ layout->addSpacing(5);
+ layout->addWidget(&statusPic);
+ layout->addSpacing(5);
+ layout->activate();
+ }
+ else
+ {
+ setFixedHeight(55);
+ avatar->setSize(QSize(40,40));
+ textLayout->addStretch();
+ textLayout->addWidget(nameLabel);
+ textLayout->addWidget(statusMessageLabel);
+ textLayout->addStretch();
+ layout->addSpacing(20);
+ layout->addWidget(avatar);
+ layout->addSpacing(10);
+ layout->addLayout(textLayout);
+ layout->addSpacing(10);
+ layout->addWidget(&statusPic);
+ layout->addSpacing(10);
+ layout->activate();
+ }
+
+ Style::repolish(this);
+}
+
bool GenericChatroomWidget::isActive()
{
return property("active").toBool();
@@ -102,3 +144,14 @@ void GenericChatroomWidget::reloadTheme()
{
setStyleSheet(Style::getStylesheet(":/ui/chatroomWidgets/genericChatroomWidget.css"));
}
+
+bool GenericChatroomWidget::isCompact() const
+{
+ return compact;
+}
+
+void GenericChatroomWidget::setCompact(bool compact)
+{
+ this->compact = compact;
+ Style::repolish(this);
+}
diff --git a/src/widget/genericchatroomwidget.h b/src/widget/genericchatroomwidget.h
index 333ef109c..ce8d84fa1 100644
--- a/src/widget/genericchatroomwidget.h
+++ b/src/widget/genericchatroomwidget.h
@@ -53,18 +53,25 @@ public:
void reloadTheme();
+ bool isCompact() const;
+ void setCompact(bool compact);
+
+ Q_PROPERTY(bool compact READ isCompact WRITE setCompact)
+
signals:
void chatroomWidgetClicked(GenericChatroomWidget* widget);
public slots:
+ void onCompactChanged(bool compact);
protected:
QColor lastColor;
- QHBoxLayout layout;
- QVBoxLayout textLayout;
+ QHBoxLayout* layout = nullptr;
+ QVBoxLayout* textLayout = nullptr;
MaskablePixmapWidget* avatar;
QLabel statusPic;
- CroppingLabel *nameLabel, *statusMessageLabel;
+ CroppingLabel* nameLabel, * statusMessageLabel;
+ bool compact;
friend class Style; ///< To update our stylesheets
};
diff --git a/src/widget/groupwidget.cpp b/src/widget/groupwidget.cpp
index 7d8892cda..60c5d2297 100644
--- a/src/widget/groupwidget.cpp
+++ b/src/widget/groupwidget.cpp
@@ -99,16 +99,9 @@ void GroupWidget::updateStatusLight()
Group *g = GroupList::findGroup(groupId);
if (!g->getEventFlag())
- {
statusPic.setPixmap(QPixmap(":img/status/dot_online.png"));
- }
else
- {
- if (!g->getMentionedFlag())
- statusPic.setPixmap(QPixmap(":img/status/dot_online_notification.png"));
- else
- statusPic.setPixmap(QPixmap(":img/status/dot_online_notification.png"));
- }
+ statusPic.setPixmap(QPixmap(":img/status/dot_online_notification.png"));
}
void GroupWidget::setChatForm(Ui::MainWindow &ui)
diff --git a/src/widget/maskablepixmapwidget.cpp b/src/widget/maskablepixmapwidget.cpp
index 5f8d2ea99..282ff9e27 100644
--- a/src/widget/maskablepixmapwidget.cpp
+++ b/src/widget/maskablepixmapwidget.cpp
@@ -19,16 +19,11 @@
MaskablePixmapWidget::MaskablePixmapWidget(QWidget *parent, QSize size, QString maskName)
: QWidget(parent)
- , renderTarget(size)
+ , maskName(maskName)
, backgroundColor(Qt::white)
, clickable(false)
{
- setFixedSize(size);
-
- QPixmap pmapMask = QPixmap(maskName);
-
- if (!pmapMask.isNull())
- mask = QPixmap(maskName).scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+ setSize(size);
}
void MaskablePixmapWidget::autopickBackground()
@@ -63,16 +58,11 @@ void MaskablePixmapWidget::autopickBackground()
QColor color = QColor::fromRgb(r,g,b);
backgroundColor = QColor::fromRgb(0xFFFFFF ^ color.rgb());
+ manualColor = false;
update();
}
-void MaskablePixmapWidget::setBackground(QColor color)
-{
- backgroundColor = color;
- update();
-}
-
void MaskablePixmapWidget::setClickable(bool clickable)
{
this->clickable = clickable;
@@ -87,9 +77,10 @@ void MaskablePixmapWidget::setPixmap(const QPixmap &pmap, QColor background)
{
if (!pmap.isNull())
{
+ unscaled = pmap;
pixmap = pmap.scaled(width(), height(), Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
backgroundColor = background;
-
+ manualColor = true;
update();
}
}
@@ -98,25 +89,44 @@ void MaskablePixmapWidget::setPixmap(const QPixmap &pmap)
{
if (!pmap.isNull())
{
+ unscaled = pmap;
pixmap = pmap.scaled(width(), height(), Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
autopickBackground();
-
update();
}
}
QPixmap MaskablePixmapWidget::getPixmap() const
{
- return renderTarget;
+ return *renderTarget;
+}
+
+void MaskablePixmapWidget::setSize(QSize size)
+{
+ setFixedSize(size);
+ delete renderTarget;
+ renderTarget = new QPixmap(size);
+
+ QPixmap pmapMask = QPixmap(maskName);
+ if (!pmapMask.isNull())
+ mask = pmapMask.scaled(size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
+
+ if (!unscaled.isNull())
+ {
+ pixmap = unscaled.scaled(width(), height(), Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation);
+ if (!manualColor)
+ autopickBackground();
+ update();
+ }
}
void MaskablePixmapWidget::paintEvent(QPaintEvent *)
{
- renderTarget.fill(Qt::transparent);
+ renderTarget->fill(Qt::transparent);
QPoint offset((width() - pixmap.size().width())/2,(height() - pixmap.size().height())/2); // centering the pixmap
- QPainter painter(&renderTarget);
+ QPainter painter(renderTarget);
painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
painter.fillRect(0,0,width(),height(),backgroundColor);
painter.drawPixmap(offset,pixmap);
@@ -125,7 +135,7 @@ void MaskablePixmapWidget::paintEvent(QPaintEvent *)
painter.end();
painter.begin(this);
- painter.drawPixmap(0,0,renderTarget);
+ painter.drawPixmap(0,0,*renderTarget);
}
void MaskablePixmapWidget::mousePressEvent(QMouseEvent*)
diff --git a/src/widget/maskablepixmapwidget.h b/src/widget/maskablepixmapwidget.h
index 86e690aae..15104f9bb 100644
--- a/src/widget/maskablepixmapwidget.h
+++ b/src/widget/maskablepixmapwidget.h
@@ -26,11 +26,11 @@ public:
MaskablePixmapWidget(QWidget *parent, QSize size, QString maskName = QString());
void autopickBackground();
- void setBackground(QColor color);
void setClickable(bool clickable);
void setPixmap(const QPixmap &pmap, QColor background);
void setPixmap(const QPixmap &pmap);
QPixmap getPixmap() const;
+ void setSize(QSize size);
signals:
void clicked();
@@ -40,13 +40,12 @@ protected:
virtual void mousePressEvent(QMouseEvent *);
private:
- QPixmap pixmap;
- QPixmap mask;
- QPixmap renderTarget;
+ QPixmap pixmap, mask, unscaled; // a lot of memory...
+ QPixmap* renderTarget = nullptr; // pointer to dynamically call the constructor
QSize size;
QString maskName;
QColor backgroundColor;
- bool clickable;
+ bool clickable, manualColor = false;
};
#endif // MASKABLEPIXMAPWIDGET_H
diff --git a/src/widget/systemtrayicon.cpp b/src/widget/systemtrayicon.cpp
new file mode 100644
index 000000000..a31929d3e
--- /dev/null
+++ b/src/widget/systemtrayicon.cpp
@@ -0,0 +1,162 @@
+#include "systemtrayicon.h"
+#include
+#include
+#include
+#include
+#include
+#include "src/misc/settings.h"
+
+SystemTrayIcon::SystemTrayIcon()
+{
+ QString desktop = getenv("XDG_CURRENT_DESKTOP");
+ if (false);
+ #ifdef ENABLE_SYSTRAY_UNITY_BACKEND
+ else if (desktop.toLower() == "unity")
+ {
+ QString settingsDir = Settings::getSettingsDirPath();
+ QFile iconFile(settingsDir+"/icon.png");
+ if (iconFile.open(QIODevice::Truncate | QIODevice::WriteOnly))
+ {
+ QFile resIconFile(":/img/icon.png");
+ if (resIconFile.open(QIODevice::ReadOnly))
+ iconFile.write(resIconFile.readAll());
+ resIconFile.close();
+ iconFile.close();
+ }
+ backendType = SystrayBackendType::Unity;
+ unityMenu = gtk_menu_new();
+ unityIndicator = app_indicator_new_with_path(
+ "qTox",
+ "icon",
+ APP_INDICATOR_CATEGORY_APPLICATION_STATUS,
+ settingsDir.toStdString().c_str()
+ );
+ app_indicator_set_menu(unityIndicator, GTK_MENU(unityMenu));
+ }
+ #endif
+ else
+ {
+ qtIcon = new QSystemTrayIcon;
+ backendType = SystrayBackendType::Qt;
+ connect(qtIcon, &QSystemTrayIcon::activated, this, &SystemTrayIcon::activated);
+ }
+}
+
+QString SystemTrayIcon::extractIconToFile(QIcon icon, QString name)
+{
+ QString iconPath;
+ (void) icon;
+ (void) name;
+#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
+ iconPath = Settings::getSettingsDirPath()+"/"+name+".png";
+ QSize iconSize = icon.actualSize(QSize{64,64});
+ icon.pixmap(iconSize).save(iconPath);
+#endif
+ return iconPath;
+}
+
+void SystemTrayIcon::setContextMenu(QMenu* menu)
+{
+ if (false);
+ #ifdef ENABLE_SYSTRAY_UNITY_BACKEND
+ else if (backendType == SystrayBackendType::Unity)
+ {
+ for (QAction* a : menu->actions())
+ {
+ gtk_image_menu_item_new();
+ QString aText = a->text().replace('&',"");
+ GtkWidget* item;
+ if (a->isSeparator())
+ item = gtk_menu_item_new();
+ else if (a->icon().isNull())
+ item = gtk_menu_item_new_with_label(aText.toStdString().c_str());
+ else
+ {
+ QString iconPath = extractIconToFile(a->icon(),"iconmenu"+a->icon().name());
+ GtkWidget* image = gtk_image_new_from_file(iconPath.toStdString().c_str());
+ item = gtk_image_menu_item_new_with_label(aText.toStdString().c_str());
+ gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), image);
+ gtk_image_menu_item_set_always_show_image(GTK_IMAGE_MENU_ITEM(item),TRUE);
+ }
+ gtk_menu_shell_append(GTK_MENU_SHELL(unityMenu), item);
+ void (*callback)(GtkMenu*, gpointer data) = [](GtkMenu*, gpointer a)
+ {
+ ((QAction*)a)->activate(QAction::Trigger);
+ };
+ g_signal_connect(item, "activate", G_CALLBACK(callback), a);
+ gtk_widget_show(item);
+ }
+ app_indicator_set_menu(unityIndicator, GTK_MENU(unityMenu));
+ DbusmenuServer *menuServer;
+ DbusmenuMenuitem *rootMenuItem;
+ g_object_get(unityIndicator, "dbus-menu-server", &menuServer, NULL);
+ g_object_get(menuServer, "root-node", &rootMenuItem, NULL);
+ void (*callback)(DbusmenuMenuitem *, gpointer) =
+ [](DbusmenuMenuitem *, gpointer data)
+ {
+ ((SystemTrayIcon*)data)->activated(QSystemTrayIcon::Unknown);
+ };
+ g_signal_connect(rootMenuItem, "about-to-show", G_CALLBACK(callback), this);
+ }
+ #endif
+ else
+ {
+ qtIcon->setContextMenu(menu);
+ }
+}
+
+void SystemTrayIcon::show()
+{
+ setVisible(true);
+}
+
+void SystemTrayIcon::hide()
+{
+ setVisible(false);
+}
+
+void SystemTrayIcon::setVisible(bool newState)
+{
+ if (false);
+ #ifdef ENABLE_SYSTRAY_UNITY_BACKEND
+ else if (backendType == SystrayBackendType::Unity)
+ {
+ if (newState)
+ app_indicator_set_status(unityIndicator, APP_INDICATOR_STATUS_ACTIVE);
+ else
+ app_indicator_set_status(unityIndicator, APP_INDICATOR_STATUS_PASSIVE);
+ }
+ #endif
+ else
+ {
+ if (newState)
+ qtIcon->show();
+ else
+ qtIcon->hide();
+ }
+}
+
+void SystemTrayIcon::setIcon(QIcon &&icon)
+{
+ if (false);
+ #ifdef ENABLE_SYSTRAY_UNITY_BACKEND
+ else if (backendType == SystrayBackendType::Unity)
+ {
+ // Alternate file names or appindicator will not reload the icon
+ if (app_indicator_get_icon(unityIndicator) == QString("icon2"))
+ {
+ extractIconToFile(icon,"icon");
+ app_indicator_set_icon_full(unityIndicator, "icon","qtox");
+ }
+ else
+ {
+ extractIconToFile(icon,"icon2");
+ app_indicator_set_icon_full(unityIndicator, "icon2","qtox");
+ }
+ }
+ #endif
+ else
+ {
+ qtIcon->setIcon(icon);
+ }
+}
diff --git a/src/widget/systemtrayicon.h b/src/widget/systemtrayicon.h
new file mode 100644
index 000000000..aa5120cd0
--- /dev/null
+++ b/src/widget/systemtrayicon.h
@@ -0,0 +1,36 @@
+#ifndef SYSTEMTRAYICON_H
+#define SYSTEMTRAYICON_H
+
+#include "systemtrayicon_private.h"
+#include
+
+class QSystemTrayIcon;
+class QMenu;
+
+class SystemTrayIcon : public QObject
+{
+ Q_OBJECT
+public:
+ SystemTrayIcon();
+ void setContextMenu(QMenu* menu);
+ void show();
+ void hide();
+ void setVisible(bool);
+ void setIcon(QIcon&& icon);
+
+signals:
+ void activated(QSystemTrayIcon::ActivationReason);
+
+private:
+ QString extractIconToFile(QIcon icon, QString name="icon");
+
+private:
+ SystrayBackendType backendType;
+ QSystemTrayIcon* qtIcon;
+#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
+ AppIndicator *unityIndicator;
+ GtkWidget *unityMenu;
+#endif
+};
+
+#endif // SYSTEMTRAYICON_H
diff --git a/src/widget/systemtrayicon_private.h b/src/widget/systemtrayicon_private.h
new file mode 100644
index 000000000..3aa4b53a2
--- /dev/null
+++ b/src/widget/systemtrayicon_private.h
@@ -0,0 +1,35 @@
+#ifndef SYSTEMTRAYICON_PRIVATE_H
+#define SYSTEMTRAYICON_PRIVATE_H
+
+#include
+
+#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
+#ifdef signals
+#undef signals
+#endif
+extern "C" {
+ #include
+ #include
+ #include
+}
+#define signals public
+#endif
+
+enum class SystrayBackendType
+{
+ Qt,
+#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
+ Unity
+#endif
+};
+
+union SystrayBackend
+{
+ QSystemTrayIcon *qt;
+#ifdef ENABLE_SYSTRAY_UNITY_BACKEND
+ AppIndicator *unity;
+#endif
+};
+
+
+#endif // SYSTEMTRAYICON_PRIVATE_H
diff --git a/src/widget/tool/chattextedit.cpp b/src/widget/tool/chattextedit.cpp
index c1b31d162..08526fc5b 100644
--- a/src/widget/tool/chattextedit.cpp
+++ b/src/widget/tool/chattextedit.cpp
@@ -25,17 +25,26 @@ ChatTextEdit::ChatTextEdit(QWidget *parent) :
}
void ChatTextEdit::keyPressEvent(QKeyEvent * event)
-{
+{
int key = event->key();
- if ((key == Qt::Key_Enter || key == Qt::Key_Return) && !(event->modifiers() && Qt::ShiftModifier))
+ if ((key == Qt::Key_Enter || key == Qt::Key_Return) && !(event->modifiers() & Qt::ShiftModifier))
emit enterPressed();
else if (key == Qt::Key_Tab)
emit tabPressed();
- else if (key == Qt::Key_Backspace) // because of the backspace() hack in tabber, we can't emit on these
- QTextEdit::keyPressEvent(event);
+ else if (key == Qt::Key_Up && this->toPlainText().isEmpty())
+ {
+ this->setText(lastMessage);
+ this->setFocus();
+ this->moveCursor(QTextCursor::MoveOperation::End,QTextCursor::MoveMode::MoveAnchor);
+ }
else
{
emit keyPressed();
QTextEdit::keyPressEvent(event);
}
}
+
+void ChatTextEdit::setLastMessage(QString lm)
+{
+ lastMessage = lm;
+}
diff --git a/src/widget/tool/chattextedit.h b/src/widget/tool/chattextedit.h
index 6bab07cda..0d36cd477 100644
--- a/src/widget/tool/chattextedit.h
+++ b/src/widget/tool/chattextedit.h
@@ -25,14 +25,15 @@ class ChatTextEdit : public QTextEdit
public:
explicit ChatTextEdit(QWidget *parent = 0);
virtual void keyPressEvent(QKeyEvent * event) override;
-
+ void setLastMessage(QString lm);
+
signals:
void enterPressed();
void tabPressed();
void keyPressed();
-public slots:
-
+private:
+ QString lastMessage;
};
#endif // CHATTEXTEDIT_H
diff --git a/src/widget/tool/friendrequestdialog.cpp b/src/widget/tool/friendrequestdialog.cpp
index cb7868e4b..ef0fa805b 100644
--- a/src/widget/tool/friendrequestdialog.cpp
+++ b/src/widget/tool/friendrequestdialog.cpp
@@ -26,6 +26,7 @@
FriendRequestDialog::FriendRequestDialog(QWidget *parent, const QString &userId, const QString &message) :
QDialog(parent)
{
+ setAttribute(Qt::WA_QuitOnClose, false);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setWindowTitle(tr("Friend request","Title of the window to aceept/deny a friend request"));
diff --git a/src/widget/videosurface.cpp b/src/widget/videosurface.cpp
index 48ae9d015..379b11afd 100644
--- a/src/widget/videosurface.cpp
+++ b/src/widget/videosurface.cpp
@@ -22,15 +22,17 @@
#include
VideoSurface::VideoSurface(QWidget* parent)
- : QGLWidget(QGLFormat(QGL::SampleBuffers | QGL::SingleBuffer), parent)
- , source(nullptr)
+ : QGLWidget(QGLFormat(QGL::SingleBuffer), parent)
+ , source{nullptr}
, pbo{nullptr, nullptr}
- , textureId(0)
- , pboAllocSize(0)
- , hasSubscribed(false)
- , pboIndex(0)
+ , bgrProgramm{nullptr}
+ , yuvProgramm{nullptr}
+ , textureId{0}
+ , pboAllocSize{0}
+ , hasSubscribed{false}
+ , pboIndex{0}
{
- setAutoBufferSwap(false);
+
}
VideoSurface::VideoSurface(VideoSource *source, QWidget* parent)
@@ -65,8 +67,8 @@ void VideoSurface::setSource(VideoSource *src)
void VideoSurface::initializeGL()
{
+ QGLWidget::initializeGL();
qDebug() << "VideoSurface: Init";
-
// pbo
pbo[0] = new QOpenGLBuffer(QOpenGLBuffer::PixelUnpackBuffer);
pbo[0]->setUsagePattern(QOpenGLBuffer::StreamDraw);
@@ -180,14 +182,6 @@ void VideoSurface::paintGL()
pbo[nextPboIndex]->release();
}
- // render pbo
- static float values[] = {
- -1, -1,
- 1, -1,
- -1, 1,
- 1, 1
- };
-
// background
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
@@ -220,6 +214,14 @@ void VideoSurface::paintGL()
if (programm)
{
+ // render pbo
+ static float values[] = {
+ -1, -1,
+ 1, -1,
+ -1, 1,
+ 1, 1
+ };
+
programm->bind();
programm->setAttributeArray(0, GL_FLOAT, values, 2);
programm->enableAttributeArray(0);
@@ -259,7 +261,7 @@ void VideoSurface::unsubscribe()
}
}
-void VideoSurface::onNewFrameAvailable(const VideoFrame newFrame)
+void VideoSurface::onNewFrameAvailable(const VideoFrame& newFrame)
{
mutex.lock();
frame = newFrame;
diff --git a/src/widget/videosurface.h b/src/widget/videosurface.h
index 18bfd11c4..c0e313e68 100644
--- a/src/widget/videosurface.h
+++ b/src/widget/videosurface.h
@@ -44,7 +44,7 @@ protected:
void unsubscribe();
private slots:
- void onNewFrameAvailable(const VideoFrame newFrame);
+ void onNewFrameAvailable(const VideoFrame &newFrame);
private:
VideoSource* source;
diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp
index 7673bea4b..382b4af11 100644
--- a/src/widget/widget.cpp
+++ b/src/widget/widget.cpp
@@ -36,6 +36,7 @@
#include "src/autoupdate.h"
#include "src/audio.h"
#include "src/platform/timer.h"
+#include "systemtrayicon.h"
#include
#include
#include
@@ -56,8 +57,7 @@ void toxActivateEventHandler(const QByteArray& data)
{
if (data != "$activate")
return;
- Widget::getInstance()->show();
- Widget::getInstance()->activateWindow();
+ Widget::getInstance()->forceShow();
}
Widget *Widget::instance{nullptr};
@@ -85,7 +85,7 @@ void Widget::init()
if (QSystemTrayIcon::isSystemTrayAvailable())
{
- icon = new QSystemTrayIcon(this);
+ icon = new SystemTrayIcon;
updateTrayIcon();
trayMenu = new QMenu;
@@ -113,7 +113,8 @@ void Widget::init()
this,
SLOT(onIconClick(QSystemTrayIcon::ActivationReason)));
- if (Settings::getInstance().getShowSystemTray()){
+ if (Settings::getInstance().getShowSystemTray())
+ {
icon->show();
if (Settings::getInstance().getAutostartInTray() == false)
this->show();
@@ -214,7 +215,7 @@ void Widget::init()
addFriendForm = new AddFriendForm;
settingsWidget = new SettingsWidget();
- connect(settingsWidget, SIGNAL(setShowSystemTray(bool)), this, SLOT(onSetShowSystemTray(bool)));
+ connect(settingsWidget, &SettingsWidget::setShowSystemTray, this, &Widget::onSetShowSystemTray);
connect(core, &Core::connected, this, &Widget::onConnected);
connect(core, &Core::disconnected, this, &Widget::onDisconnected);
@@ -314,16 +315,16 @@ void Widget::updateTrayIcon()
Widget::~Widget()
{
+ qDebug() << "Deleting Widget";
core->saveConfiguration();
- coreThread->exit();
- coreThread->wait(500); // In case of deadlock (can happen with QtAudio/PA bugs)
- if (!coreThread->isFinished())
- coreThread->terminate();
AutoUpdater::abortUpdates();
delete core;
+ icon->hide();
+ hideMainForms();
delete settingsWidget;
delete addFriendForm;
delete filesForm;
+ delete idleTimer;
FriendList::clear();
GroupList::clear();
@@ -359,6 +360,7 @@ void Widget::closeEvent(QCloseEvent *event)
{
saveWindowGeometry();
saveSplitterGeometry();
+ qApp->exit(0);
QWidget::closeEvent(event);
}
}
@@ -378,6 +380,8 @@ void Widget::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
saveWindowGeometry();
+
+ emit resized();
}
QString Widget::detectProfile()
@@ -569,6 +573,13 @@ void Widget::setWindowTitle(const QString& title)
QMainWindow::setWindowTitle("qTox - " + title);
}
+void Widget::forceShow()
+{
+ hide(); // Workaround to force minimized window to be restored
+ show();
+ activateWindow();
+}
+
void Widget::onAddClicked()
{
hideMainForms();
@@ -591,21 +602,38 @@ void Widget::onTransferClicked()
void Widget::onIconClick(QSystemTrayIcon::ActivationReason reason)
{
- switch (reason) {
+ switch (reason)
+ {
case QSystemTrayIcon::Trigger:
- if (this->isHidden() == true)
{
- this->show();
- this->activateWindow();
+ if (isHidden())
+ {
+ show();
+ activateWindow();
+ }
+ else if (isMinimized())
+ {
+ forceShow();
+ }
+ else
+ {
+ hide();
+ }
+
+ break;
}
- else
- this->hide();
- case QSystemTrayIcon::DoubleClick:
+ case QSystemTrayIcon::DoubleClick:
+ forceShow();
break;
case QSystemTrayIcon::MiddleClick:
+ hide();
+ break;
+ case QSystemTrayIcon::Unknown:
+ if (isHidden())
+ forceShow();
break;
default:
- ;
+ break;
}
}
@@ -633,15 +661,18 @@ void Widget::hideMainForms()
void Widget::onUsernameChanged(const QString& newUsername, const QString& oldUsername)
{
- ui->nameLabel->setText(oldUsername); // restore old username until Core tells us to set it
- ui->nameLabel->setToolTip(oldUsername); // for overlength names
+ setUsername(oldUsername); // restore old username until Core tells us to set it
core->setUsername(newUsername);
}
void Widget::setUsername(const QString& username)
{
ui->nameLabel->setText(username);
- ui->nameLabel->setToolTip(username); // for overlength names
+ ui->nameLabel->setToolTip(username); // for overlength names
+ QString sanename = username;
+ sanename.remove(QRegExp("[\\t\\n\\v\\f\\r\\x0000]"));
+ nameMention = QRegExp("\\b" + QRegExp::escape(username) + "\\b", Qt::CaseInsensitive);
+ sanitizedNameMention = QRegExp("\\b" + QRegExp::escape(sanename) + "\\b", Qt::CaseInsensitive);
}
void Widget::onStatusMessageChanged(const QString& newStatusMessage, const QString& oldStatusMessage)
@@ -665,6 +696,10 @@ void Widget::addFriend(int friendId, const QString &userId)
QLayout* layout = contactListWidget->getFriendLayout(Status::Offline);
layout->addWidget(newfriend->getFriendWidget());
+ if (Settings::getInstance().getEnableLogging())
+ newfriend->getChatForm()->loadHistory(QDateTime::currentDateTime().addDays(-7), true);
+
+ connect(settingsWidget, &SettingsWidget::compactToggled, newfriend->getFriendWidget(), &GenericChatroomWidget::onCompactChanged);
connect(newfriend->getFriendWidget(), SIGNAL(chatroomWidgetClicked(GenericChatroomWidget*)), this, SLOT(onChatroomWidgetClicked(GenericChatroomWidget*)));
connect(newfriend->getFriendWidget(), SIGNAL(removeFriend(int)), this, SLOT(removeFriend(int)));
connect(newfriend->getFriendWidget(), SIGNAL(copyFriendIdToClipboard(int)), this, SLOT(copyFriendIdToClipboard(int)));
@@ -674,6 +709,7 @@ void Widget::addFriend(int friendId, const QString &userId)
connect(newfriend->getChatForm(), SIGNAL(sendFile(int32_t, QString, QString, long long)), core, SLOT(sendFile(int32_t, QString, QString, long long)));
connect(newfriend->getChatForm(), SIGNAL(answerCall(int)), core, SLOT(answerCall(int)));
connect(newfriend->getChatForm(), SIGNAL(hangupCall(int)), core, SLOT(hangupCall(int)));
+ connect(newfriend->getChatForm(), SIGNAL(rejectCall(int)), core, SLOT(rejectCall(int)));
connect(newfriend->getChatForm(), SIGNAL(startCall(int)), core, SLOT(startCall(int)));
connect(newfriend->getChatForm(), SIGNAL(startVideoCall(int,bool)), core, SLOT(startCall(int,bool)));
connect(newfriend->getChatForm(), SIGNAL(cancelCall(int,int)), core, SLOT(cancelCall(int,int)));
@@ -803,25 +839,11 @@ void Widget::onFriendMessageReceived(int friendId, const QString& message, bool
QDateTime timestamp = QDateTime::currentDateTime();
f->getChatForm()->addMessage(f->getToxID(), message, isAction, timestamp, true);
- if (isAction)
- HistoryKeeper::getInstance()->addChatEntry(f->getToxID().publicKey, "/me " + message, f->getToxID().publicKey, timestamp, true);
- else
- HistoryKeeper::getInstance()->addChatEntry(f->getToxID().publicKey, message, f->getToxID().publicKey, timestamp, true);
-
- if (activeChatroomWidget != nullptr)
- {
- if ((static_cast(f->getFriendWidget()) != activeChatroomWidget) || isMinimized() || !isActiveWindow())
- {
- f->setEventFlag(true);
- newMessageAlert(f->getFriendWidget());
- }
- }
- else
- {
- f->setEventFlag(true);
- newMessageAlert(f->getFriendWidget());
- }
+ HistoryKeeper::getInstance()->addChatEntry(f->getToxID().publicKey, isAction ? "/me " + message : message,
+ f->getToxID().publicKey, timestamp, true);
+ f->setEventFlag(static_cast(f->getFriendWidget()) != activeChatroomWidget);
+ newMessageAlert(f->getFriendWidget());
f->getFriendWidget()->updateStatusLight();
}
@@ -836,17 +858,22 @@ void Widget::onReceiptRecieved(int friendId, int receipt)
void Widget::newMessageAlert(GenericChatroomWidget* chat)
{
+ bool inactiveWindow = isMinimized() || !isActiveWindow();
+ if (!inactiveWindow && activeChatroomWidget != nullptr && chat == activeChatroomWidget)
+ return;
+
QApplication::alert(this);
- static QFile sndFile(":audio/notification.pcm");
- if ((isMinimized() || !isActiveWindow()) && Settings::getInstance().getShowInFront())
+ if (Settings::getInstance().getShowWindow())
{
- this->show();
- showNormal();
- activateWindow();
- emit chat->chatroomWidgetClicked(chat);
+ show();
+ if (inactiveWindow && Settings::getInstance().getShowInFront())
+ setWindowState(Qt::WindowActive);
}
+
+ static QFile sndFile(":audio/notification.pcm");
static QByteArray sndData;
+
if (sndData.isEmpty())
{
sndFile.open(QIODevice::ReadOnly);
@@ -950,24 +977,21 @@ void Widget::onGroupMessageReceived(int groupnumber, int peernumber, const QStri
return;
ToxID author = Core::getInstance()->getGroupPeerToxID(groupnumber, peernumber);
- QString name = core->getUsername();
-
- bool targeted = (!author.isMine()) && message.contains(name, Qt::CaseInsensitive);
+ bool targeted = !author.isMine() && (message.contains(nameMention) || message.contains(sanitizedNameMention));
if (targeted && !isAction)
g->getChatForm()->addAlertMessage(author, message, QDateTime::currentDateTime());
else
g->getChatForm()->addMessage(author, message, isAction, QDateTime::currentDateTime(), true);
- if ((static_cast(g->getGroupWidget()) != activeChatroomWidget) || isMinimized() || !isActiveWindow())
- {
- g->setEventFlag(true);
- if (targeted)
- {
- newMessageAlert(g->getGroupWidget());
- g->setMentionedFlag(true); // useful for highlighting line or desktop notifications
- }
- g->getGroupWidget()->updateStatusLight();
- }
+ g->setEventFlag(static_cast(g->getGroupWidget()) != activeChatroomWidget);
+
+ if (targeted || Settings::getInstance().getGroupAlwaysNotify())
+ newMessageAlert(g->getGroupWidget());
+
+ if (targeted)
+ g->setMentionedFlag(true); // useful for highlighting line or desktop notifications
+
+ g->getGroupWidget()->updateStatusLight();
}
void Widget::onGroupNamelistChanged(int groupnumber, int peernumber, uint8_t Change)
diff --git a/src/widget/widget.h b/src/widget/widget.h
index ad6ad8b04..9f86c52d6 100644
--- a/src/widget/widget.h
+++ b/src/widget/widget.h
@@ -44,6 +44,7 @@ class FriendListWidget;
class MaskablePixmapWidget;
class QTimer;
class QTranslator;
+class SystemTrayIcon;
class Widget : public QMainWindow
{
@@ -81,6 +82,7 @@ public:
public slots:
void onSettingsClicked();
void setWindowTitle(const QString& title);
+ void forceShow();
signals:
void friendRequestAccepted(const QString& userId);
@@ -90,6 +92,7 @@ signals:
void usernameChanged(const QString& username);
void statusMessageChanged(const QString& statusMessage);
void changeProfile(const QString& profile);
+ void resized();
private slots:
void onConnected();
@@ -147,7 +150,7 @@ private:
void saveSplitterGeometry();
QString askProfiles();
QString detectProfile();
- QSystemTrayIcon *icon;
+ SystemTrayIcon *icon;
QMenu *trayMenu;
QAction *statusOnline,
*statusAway,
@@ -171,6 +174,7 @@ private:
Status beforeDisconnect = Status::Offline;
QTimer* idleTimer;
QTranslator* translator;
+ QRegExp nameMention, sanitizedNameMention;
};
void toxActivateEventHandler(const QByteArray& data);
diff --git a/translations/de.ts b/translations/de.ts
index e54e3a6b2..5abcccc6c 100644
--- a/translations/de.ts
+++ b/translations/de.ts
@@ -8,6 +8,11 @@
Audio/Video
+
+
+
+ Initialisiert Kamera...
+
AVSettings
@@ -141,17 +146,17 @@ Soll der Proxy ignoriert und eine direkte Internetverbindung genutzt werden?Fortgeschritten
-
+
VOLL - sehr sicher, langsam (empfohlen)
-
+
NORMAL - fast so sicher wie VOLL, ca. 20% schneller
-
+
AUS - keinerlei Sicherheit, geht etwas schief, kann die Historie verloren gehen, ist am schnellsten (nicht empfohlen)
@@ -165,21 +170,32 @@ Soll der Proxy ignoriert und eine direkte Internetverbindung genutzt werden?
+
+ describes makeToxPortable checkbox
+ Speichert die Einstellungen im Arbeits- statt im normalen Konfigurationsverzeichnis
+
+
+
+
+ Macht Tox portabel
+
+
+
<html><head/><body><p><span style=" font-weight:600; color:#ff0000;">WICHTIGE NOTIZ</span></p><p><span style=" color:#ff0000;">Wenn Sie nicht </span><span style=" font-weight:600; color:#ff0000;">wirklich</span><span style=" color:#ff0000;"> wissen, was Sie tun, ändern Sie hier bitte </span><span style=" font-weight:600; color:#ff0000;">nichts</span><span style=" color:#ff0000;">. Hier getätigte Änderungen können zu Problemen mit qTox führen, evtl. sogar zum Datenverlust, z.B. der Historie.</span></p></body></html>
-
+
Grundeinstellungen wiederherstellen
-
+
Historie
-
+
<html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Synchrones Schreiben in die DB</span></a></p></body></html>
@@ -187,70 +203,79 @@ Soll der Proxy ignoriert und eine direkte Internetverbindung genutzt werden?
ChatForm
-
+
Historie laden...
-
+
Datei versenden
-
+
+
Datei nicht gelesen
-
+
+
qTox konnte %1 nicht öffnen
-
+
+
Schlechte Idee
-
+
+
Sie versuchen eine spezielle (sequentielle) Datei zu senden, das funktioniert nicht!
-
+
%1 ruft an
-
+
%1 hat den Anruf beendet
-
+
Rufe %1 an
-
+
Anruf abgewiesen
-
+
Senden der Datei "%1" fehlgeschlagen
-
+
Anruf zu %1 beendet. %2
-
+
Anrufdauer:
+
+
+
+ tippt gerade...
+
ChatTextEdit
@@ -263,104 +288,104 @@ Soll der Proxy ignoriert und eine direkte Internetverbindung genutzt werden?
Core
-
+
Toxen mit qTox
-
+
qTox Benutzer
-
+
Freund wurde schon hinzugefügt
-
+
Verschlüsselungsfehler
-
+
Die .tox Datei ist verschlüsselt, aber die Verschlüsselung wurde nicht geprüft, Vorgang wird trotzdem fortgesetzt.
-
+
Entschlüsselungspasswort für Tox Datendatei
-
-
-
+
+
+
Passwortfehler
-
-
+
+
Setzen des Passwortes fehlgeschlagen.
Leeres Passwort.
-
+
Nochmal versuchen
-
+
Profil ändern
-
+
Aktuelles Profil erneut starten
-
+
Es wurde ein falsches Passwort eingegeben
-
+
Passwort zur Entschlüsselung der Historie
-
+
Verschlüsselte Logdatei
-
+
Ihre Historie wurde mit einem anderen Passwort verschlüsselt.
Wollen Sie ein weiteres probieren?
-
+
Falsches Passwort, Historie wird deaktiviert.
-
+
Historie
-
+
KEIN Passwort
-
+
Wird ohne Verschlüsselung gespeichert!
@@ -413,34 +438,34 @@ Wollen Sie ein weiteres probieren?
FriendRequestDialog
-
+
Title of the window to aceept/deny a friend request
Freundschaftsanfrage
-
+
Jemand möchte Ihr Freund werden
-
+
Benutzer ID:
-
+
Freundschaftsanfrage:
-
+
Accept a friend request
Annehmen
-
+
Reject a friend request
Ablehnen
@@ -504,25 +529,25 @@ Alias:
Allgemein
-
-
+
+
Kein
-
+
popup title
Wählen Sie ein Verzeichnis
-
+
popup title
Anwahl aktiviert
-
+
popup text
Abbruch während der Anwahl nicht möglich!
@@ -542,99 +567,105 @@ Alias:
Änderung wird erst nach Neustart von qTox aktiv.
-
-
- Sprache
-
-
-
-
- describes makeToxPortable checkbox
- Speichert die Einstellungen im Arbeits- statt im normalen Konfigurationsverzeichnis
-
-
-
-
- Macht Tox portabel
-
-
-
-
- Systemtray Integration
-
-
-
+
- Im Systemtray zeigen
+ In der Systemleiste anzeigen
-
+
- Ins Tray starten
+ In die Systemleiste starten
-
+
- Ins Tray schließen
+ In die Systemleiste schließen
-
+
- Ins Tray minimieren
+ In die Systemleiste minimieren
-
+
Helles Icon
-
+
+
+ Sprache:
+
+
+
+
+ Systemleiste
+
+
+
+
+ Beim Starten auf Updates überprüfen
+
+
+
+
+ Speichern in:
+
+
+
+
+ Automatisch abwesend nach (0 zum Deaktivieren):
+
+
+
+
+ Chat
+
+
+
+
+ Über Gruppenchats immer informieren
+
+
+
Zeigt Statusänderungen der Kontakte
-
-
- Prüft beim Start auf Updates (nicht stabil)
-
-
-
-
- Bringt qTox in den Vordergrund, wenn eine Nachricht eintrifft
-
-
-
+
Imitiert Offline Benachrichtigung
-
+
+ Kompakte Darstellung der Kontaktliste (Neustart benötigt)
+
+
+
Angabe in Minuten
-
Automatisch abwesend nach (0 deaktiviert)
-
+
Zum Deaktivieren auf 0 setzen
-
+
autoaccept cb tooltip
Sie können dies durch Rechtsklick auf den jeweiligen Freund festlegen.
-
+
Emoticons benutzen
-
Text on smiley pack label
Emoticon Paket
@@ -655,82 +686,150 @@ Alias:
Emoticon Größe
-
+
Pixel
-
Zeitformat
-
+
force tcp checkbox tooltip
Wenn deaktiviert kann z.B. über Tor getoxt werden. Dies belastet das Tox Netzwerk zusätzlich und sollte nur deaktiviert werden wenn notwendig.
-
+
Text on checkbox to disable UDP
UDP aktivieren (empfohlen)
-
+
+
+ Proxy Typ:
+
+
+
+
+ Text on proxy addr label
+ Adresse:
+
+
+
+
+ SOCKS5
+
+
+
+
+ HTTP
+
+
+
reconnect button
Erneut verbinden
-
+
Minuten
-
+
Dateien automatisch annehmen
-
- Speichern unter
+ Speichern unter
-
+
Schaltfläche
+
+ Bei neuer Nachricht:
+
+
+
+
+ Zeige Fenster
+
+
+
+
+ Bringe Fenster in den Vordergrund
+
+
+
+
+ Kompakte Kontaktliste
+
+
+
Benutzeroberfläche
-
+
+
+ Text on smiley pack label
+ Smiley Paket:
+
+
+
+
+ Emoticon Größe:
+
+
+
+
+ Stil:
+
+
+
+
+ Fensterfarbe:
+
+
+
+
+ Zeitformat:
+
+
+
Verbindungseinstellungen
-
+
Text on a checkbox to enable IPv6
IPv6 aktivieren (empfohlen)
-
-
- Proxy benutzen (SOCKS5)
+
+ Proxy Typ
+
+
+
+
+ Keinen
-
Text on proxy addr label
Adresse
-
+
Text on proxy port label
Port
@@ -739,53 +838,53 @@ Alias:
GenericChatForm
-
+
Nachricht senden
-
+
Smileys
-
+
Datei(en) senden
-
+
Sprachanruf: ROT bedeutet verbunden
-
+
Videoanruf: ROT bedeutet verbunden
-
+
Schaltet den Lautsprecher ein/aus: ROT ist AUS
-
+
Schaltet das Mikrofon ein/aus: ROT ist AUS
-
-
+
+
Chatverlauf speichern
-
+
Angezeigte Nachrichten ausblenden
-
+
Ausgeblendet
@@ -850,87 +949,87 @@ Titel:
Identität
-
+
popup title
Anruf aktiv
-
+
popup text
Das Profil kann während eines Anrufes nicht gewechselt werden!
-
+
renaming a profile
"%1" umbenennen
-
+
rename confirm title
Profil existiert bereits
-
+
rename confirm text
Ein Profil mit dem Namen "%1" existiert bereits. Wollen Sie es löschen?
-
+
save dialog title
Profil exportieren
-
+
save dialog filter
Toxdatei speichern (*.tox)
-
+
Entfernen der Datei fehlgeschlagen
-
+
Die gewählte Datei kann nicht überschrieben werden.
-
+
Kopieren der Datei fehlgeschlagen
-
+
Die gewählte Datei kann nicht überschrieben werden.
-
+
current profile deletion warning title
Profil ist zurzeit geladen
-
+
current profile deletion warning text
Dieses Profil ist aktuell in Gebrauch. Bitte laden Sie vor dem Löschen ein anderes Profil.
-
+
deletion confirmation title
Löschen steht bevor!
-
+
deletion confirmation text
@@ -938,37 +1037,37 @@ Associated friend information and chat logs will be deleted as well.
Dazugehörige Informationen und Chatprotokolle werden ebenfalls gelöscht.
-
+
import dialog title
Profil importieren
-
+
import dialog filter
Toxdatei speichern (*.tox)
-
+
popup title
Keine Toxdatei, wird ignoriert
-
+
popup text
Warnung: Sie haben eine Datei gewählt, die keine Toxdatei ist, wird ignoriert.
-
+
import confirm title
Profil existiert bereits
-
+
import confirm text
Ein Profil mit dem Namen "%1" existiert bereits. Wollen Sie es löschen?
@@ -1157,7 +1256,7 @@ Soll die alte Historiedatei gelöscht werden?
PrivacySettings
-
+
Tippen anzeigen
@@ -1199,13 +1298,13 @@ Soll die alte Historiedatei gelöscht werden?
QObject
-
+
The title of a message box
Update
-
+
Ein Update steht zur Verfügung, soll es heruntergeladen werden?
@@ -1219,7 +1318,7 @@ Es wird beim Neustart von qTox installiert.
- Startet eine neue Instanz und lädt das festgelegte Profil.
+ Startet eine neue Instanz und lädt das festgelegte Profil.
@@ -1229,7 +1328,7 @@ Es wird beim Neustart von qTox installiert.
- Default
+ Standard
@@ -1291,6 +1390,11 @@ Es wird beim Neustart von qTox installiert.
Default message in Tox URI friend requests. Write something appropriate!
Lass uns toxen!
+
+
+
+ Eingehender Anruf...
+
SetPasswordDialog
@@ -1356,6 +1460,15 @@ Es wird beim Neustart von qTox installiert.
Error with the DNS
Der DNS Eintrag enthält keine gültige TOX ID
+
+
+
+
+ Es scheint, dass qTox das veraltete tox1-Protokoll nutzen muss.
+Dieses Protokoll ist nicht sicher.
+Soll es dennoch genutzt werden?
+
ToxURIDialog
@@ -1439,116 +1552,116 @@ Es wird beim Neustart von qTox installiert.
Beschäftigt
-
+
Wählen Sie ein Profil
-
+
Wählen Sie die Identität, die benutzt werden soll
-
+
Wählen Sie ein Profilbild
-
-
-
+
+
+
Fehler
-
+
Kann diese Datei nicht öffnen
-
+
Kann dieses Bild nicht einlesen
-
+
Dieses Bild ist zu groß
-
+
Tox startet nicht, die Anwendung wird nach Schließen dieses Fensters beendet.
-
+
popup text
Tox startet nicht mit ihren Proxy-Einstellungen. qTox funktioniert nicht, ändern Sie bitte Ihre Einstellungen und starten qTox neu.
-
+
Freund hinzufügen
-
+
Dateiübertragungen
-
+
Einstellungen
-
+
Freundschaftsanfrage fehlgeschlagen
-
+
contact status
Abwesend
-
+
contact status
Beschäftigt
-
+
contact status
Offline
-
+
contact status
Online
-
+
e.g. "Dubslow is now online"
%1 ist nun %2
-
+
Placeholder when we don't know someone's name in a group chat
<Unbekannt>
-
+
%1 hat den Titel auf %2 gesetzt
-
+
Senden der Nachricht fehlgeschlagen
diff --git a/translations/fr.ts b/translations/fr.ts
index 48cc108ea..6e6bba4f2 100644
--- a/translations/fr.ts
+++ b/translations/fr.ts
@@ -4,10 +4,15 @@
AVForm
-
+
Audio/Vidéo
+
+
+
+ Initialisation de la caméra...
+
AVSettings
@@ -16,12 +21,12 @@
qTox
-
+
Options vidéo
-
+
Résolution
@@ -51,22 +56,32 @@
Microphone
-
+
+
+ Redetecter le matériel audio
+
+
+
+
+ Filtrer le son
+
+
+
Teinte
-
+
Luminosité
-
+
Saturation
-
+
Contraste
@@ -116,8 +131,14 @@
+Ignore the proxy and connect to the Internet directly?
qTox as besoin d'utiliser le DNS Tox, mais ne peut pas le faire avec un proxy.
+Ignorer le proxy et se connecter directement à Internet ?
+
+
+
+ qTox as besoin d'utiliser le DNS Tox, mais ne peut pas le faire avec un proxy.
Ignorer le proxy et se connecter directement à Internet ?
@@ -163,55 +184,134 @@ Ignorer le proxy et se connecter directement à Internet ?
La réponse DNS ne contient pas d'ID Tox valide
+
+ AdvancedForm
+
+
+
+ Avancé
+
+
+
+
+ COMPLET - très sûr, le plus lent (recommendé)
+
+
+
+
+ NORMAL - presque aussi sûr que COMPLET, à peu près 20% plus rapide que COMPLET
+
+
+
+
+ DESACTIVE - désactive toutes les sécurités, en cas de problème l'historique peut être perdu, le plus rapide (non recommandé)
+
+
+
+ AdvancedSettings
+
+
+
+ qTox
+
+
+
+
+ <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">NOTE IMPORTANTE</span></p><p><span style=" color:#ff0000;">A moins de </span><span style=" font-weight:600; color:#ff0000;">vraiment</span><span style=" color:#ff0000;"> savoir ce que vous êtes en train de faire, merci de ne </span><span style=" font-weight:600; color:#ff0000;">pas</span><span style=" color:#ff0000;"> changer quoi que ce soit ici. Tout changement ici peut conduire à des problèmes avec qTox et même la perte de vos données, comme l'historique.</span></p></body></html>
+
+
+
+
+ Retour aux options par default
+
+
+
+
+ Historique
+
+
+
+
+ Ecriture synchronisée à la BDD
+
+
ChatForm
-
+
Charger l'historique...
-
+
Envoyer un fichier
-
+
+
+
+ Fichier non lu
+
+
+
+
+
+ qTox n'as pas pu ouvrir %1
+
+
+
+
Mauvaise idée
-
+
+
Vous êtes en train d'essayer d'envoyer un fichier spécial (sequentiel), ça ne fonctionnera pas !
-
-
- %1 appel
+
+
+ %1 appelle
-
+
+
+ est en train d'écrire...
+
+
+
+ %1 appel
+
+
+
%1 a arreté l'appel
-
+
Appel de %1 en cours
-
+
Appel rejeté
-
+
+
+ Impossible d'envoyer "%1"
+
+
+
Appel avec %1 terminé. %2
-
+
Durée de l'appel:
@@ -227,104 +327,118 @@ Ignorer le proxy et se connecter directement à Internet ?
Core
-
+
Je Tox sur qTox
-
+
Utilisateur de qTox
-
+
Ce contact est déjà dans vos contacts
-
+
Erreur de chiffrement
-
+
Le fichier .tox est chiffré, mais le chiffrement n'a pas été activé. Le problème sera ignoré.
-
+
Mot de passe des données Tox
-
-
-
+
+
+
Mot de passe invalide
-
-
+
+
Impossible de mettre en place le mot de passe.
Le mot de passe est vide.
-
+
Réessayer
-
+
Changer de profil
-
+
Réinitialiser le profil courant
-
+
Un mauvais mot de passe a été entré
-
+
Mot de passe de l'historique
-
+
+
+ Votre historique est chiffré avec un mot de passe différent.
+Voulez-vous essayer un autre mot de passe?
+
+
+
+
+ Historique
+
+
+
+
+ L'historique va être désactivé à cause d''un mauvais mot de passe.
+
+
- Votre historique de conversation est chiffré avec un autre mot de passe
+ Votre historique de conversation est chiffré avec un autre mot de passe
Voulez-vous essayer un mot de passe différent?
-
+
Historique chiffré
-
- Historique
+ Historique
-
- Due à l'utilisation d'un mauvais mot de passe, l'historique sera désactivé
+ Due à l'utilisation d'un mauvais mot de passe, l'historique sera désactivé
-
+
PAS de mot de passe
-
+
L'historique sera sauvegardé sans être chiffré !
@@ -332,25 +446,25 @@ Voulez-vous essayer un mot de passe différent?
FileTransferInstance
-
+
Title of the file saving dialog
Sauvegarder un fichier
-
+
Title of permissions popup
Impossible d'écrire ici
-
+
text of permissions popup
Vous n'avez pas la permission d'écrire ici. Choisissez un audre endroit, ou annulez.
-
+
ETA
@@ -436,14 +550,20 @@ Voulez-vous essayer un mot de passe différent?
Automatiquement accepter les fichiers de ce contact
-
+
Alias utilisateur
-
+
+
+ Vous pouvez aussi modifier ceci en cliquant sur le nom dans le chat.
+Alias:
+
+
- Alias:
+ Alias:
@@ -476,30 +596,30 @@ Voulez-vous essayer un mot de passe différent?
GeneralForm
-
+
Général
-
-
+
+
Aucun
-
+
popup title
Choisir un dossier de téléchargement
-
+
popup title
Appel en cours
-
+
popup text
Vous ne pouvez pas vous déconnecter avec un appel en cours !
@@ -538,27 +658,27 @@ Voulez-vous essayer un mot de passe différent?
Rendre Tox portable
-
+
Démarrer dans la barre d'état
-
+
Fermer dans la barre d'état
-
+
Minimiser dans la barre d'état
-
+
Montrer les changements de status des contacts
-
+
En minutes
@@ -567,17 +687,17 @@ Voulez-vous essayer un mot de passe différent?
Se rendre absent après (0 pour désactiver):
-
+
Mettre à 0 pour désactiver
-
+
minutes
-
+
Thème
@@ -611,19 +731,39 @@ Voulez-vous essayer un mot de passe différent?
Style:
-
+
Text on checkbox to disable UDP
Activer UDP (recommandé)
-
+
+
+ Type de proxy
+
+
+
+
+ Aucun
+
+
+
+
+ SOCKS5
+
+
+
+
+ HTTP
+
+
+
reconnect button
Se reconnecter
-
+
Options de réseau
@@ -633,79 +773,110 @@ Voulez-vous essayer un mot de passe différent?
Traduction
-
+
+
+ Intégration avec la barre d'état
+
+
+
+
+ Montrer l'icône de barre d'état
+
+
+
+
+ Icône claire
+
+
+
Chercher des mises à jour au démarrage (instable)
-
+
Montrer la fênetre qTox quand un message est reçu
-
+
Retransmettre les messages en cas d'échec
-
+
+
+ Agencement compact
+
+
+
Indisponible après (0 désactive)
-
+
+
+ autoaccept cb tooltip
+ Vous pouvez regler ceci pour chaque contact avec un clique-droit sur leur nom.
+
+
+
Auto-accepter les fichiers
-
+
Sauvegarder les fichiers vers
-
+
PushButton
-
+
Utiliser les émoticones
-
+
Text on smiley pack label
Pack de smileys
-
+
Style
-
+
+
+ Couleur du thème
+
+
+
Taille d'émoticone
-
+
px
-
+
Format de timestamp
-
+
Text on a checkbox to enable IPv6
Activer IPv6 (recommandé)
-
+
force tcp checkbox tooltip
Désactiver ceci permet par exemple d'utiliser Tox à travers Tor, mais ce n'est à utiliser que si nécessaire, car cela ralenti le réseau Tox.
@@ -721,18 +892,17 @@ Voulez-vous essayer un mot de passe différent?
Désactiver UDP (non recommandé)
-
- Utiliser un proxy (SOCKS5)
+ Utiliser un proxy (SOCKS5)
-
+
Text on proxy addr label
Addresse
-
+
Text on proxy port label
Port
@@ -741,53 +911,69 @@ Voulez-vous essayer un mot de passe différent?
GenericChatForm
-
+
Envoyer un message
-
+
Émoticônes
-
+
Envoyer des fichiers
-
-
-
- Appel audio
-
-
-
-
- Appel vidéo
-
-
-
-
- Couper les haut-parleurs
-
-
- Couper le microphone
+
+ Appel audio: ROUGE veut dire en cours d'appel
-
-
+
+
+ Appel vidéo: ROUGE veut dire en cours d'appel
+
+
+
+
+ Changer volume des haut-parleurs: ROUGE veut dire ETEINT
+
+
+
+
+ Changer état du micrphone: ROUGE veut dire ETEINT
+
+
+
+ Appel audio
+
+
+
+ Appel vidéo
+
+
+
+ Couper les haut-parleurs
+
+
+
+ Couper le microphone
+
+
+
+
Sauvegarder l'historique de conversation
-
+
Effacer les messages affichés
-
+
Effacé
@@ -801,7 +987,7 @@ Voulez-vous essayer un mot de passe différent?
%1 personnes
-
+
%1 personnes
@@ -809,23 +995,40 @@ Voulez-vous essayer un mot de passe différent?
GroupWidget
-
-
+
+
%1 personnes
-
-
+
+
Le groupe est vide
-
+
+
+ Changer le titre...
+
+
+
Menu to quit a groupchat
Quitter le groupe
+
+
+
+ Titre du groupe
+
+
+
+
+ Vous pouvez aussi changer ceci en cliquant sur le nom du chat.
+Titre:
+
IdentityForm
@@ -916,42 +1119,49 @@ Voulez-vous essayer un mot de passe différent?
-
+
deletion confirmation text
- Êtes-vous sur de vouloir supprimer ce profil ?
+ Êtes-vous sur de vouloir supprimer ce profil ?
+Les informations des contacts et historique associés vont être perdu.
-
+
+ deletion confirmation text
+ Êtes-vous sur de vouloir supprimer ce profil ?
+
+
+
import dialog title
Importer un profil
-
+
import dialog filter
Fichier sauvegarde Tox (*.tox)
-
+
popup title
Fichier incompatible avec Tox ignoré
-
+
popup text
Attention: Vous avez sélectionné un fichier qui n'est pas une sauvegarde Tox, il sera ignoré.
-
+
import confirm title
Ce profil existe déjà
-
+
import confirm text
Un profil appelé "%1" existe déjà. Voulez-vous le supprimer ?
@@ -1091,27 +1301,27 @@ Voulez-vous essayer un mot de passe différent?
Votre status
-
+
Ajouter des contacts
-
+
Créer un groupe
-
+
Voir les transfers de fichiers terminés
-
+
Changer les options
-
+
Fermer
@@ -1136,12 +1346,12 @@ Voulez-vous essayer un mot de passe différent?
Vie privée
-
+
Historique chiffré
-
+
Vous avez déjà un historique chiffré avec un autre mot de passe
@@ -1155,9 +1365,13 @@ Voulez vous supprimer l'ancien historique ?
qTox
-
- Notifications d'écriture
+ Notifications d'écriture
+
+
+
+
+ Envoyer des notifications d'écriture
@@ -1179,6 +1393,21 @@ Voulez vous supprimer l'ancien historique ?
Chiffrer l'historique
+
+
+
+ Antispam
+
+
+
+
+ HHHHHHHH
+
+
+
+
+ Generer un antispam aléatoire
+
QObject
@@ -1223,16 +1452,22 @@ Voulez vous supprimer l'ancien historique ?
Je souhaiterais vous ajouter à mes contacts
-
+
The title of a message box
Mise à jour
-
+
+
+ Une mise à jour est disponible, voulez vous la télécharger maintenant?
+Elle sera installée au prochain démarrage de qTox.
+
+
- Une mise à jour est disponible, voulez vous la télécharger maintenant ?
+ Une mise à jour est disponible, voulez vous la télécharger maintenant ?
Elle sera installée au prochain démarrage de qTox.
@@ -1240,6 +1475,41 @@ Elle sera installée au prochain démarrage de qTox.
URL Tox à utiliser
+
+
+
+ Démarrer une nouvelle instance et charger le profil spécifié.
+
+
+
+
+ profil
+
+
+
+
+ Defaut
+
+
+
+
+ Bleu
+
+
+
+
+ Olive
+
+
+
+
+ Rouge
+
+
+
+
+ Violet
+
SetPasswordDialog
@@ -1309,6 +1579,14 @@ Elle sera installée au prochain démarrage de qTox.
Error with the DNS
La réponse DNS ne contient pas d'ID Tox valide
+
+
+
+
+ Il semble que qTox a besoin d'utiliser l'ancien protocole tox1.
+Cepandant tox1 n'est pas sécurisé. Voulez-vous l'utiliser tout de même?
+
ToxURIDialog
@@ -1319,9 +1597,13 @@ Elle sera installée au prochain démarrage de qTox.
Ajouter un contact
-
- Voulez-vous ajouter %1 à vos contacts ?
+ Voulez-vous ajouter %1 à vos contacts ?
+
+
+
+
+ Voulez-vous ajouter %1 à vos contacts?
@@ -1361,154 +1643,158 @@ Elle sera installée au prochain démarrage de qTox.
occupé
-
+
Connecté
-
+
Absent
-
+
Occupé
-
+
&Quitter
-
- Changer le status par:
+ Changer le status par:
-
+
Button to set your status to 'Online'
Connecté
-
+
Button to set your status to 'Away'
Absent
-
+
Button to set your status to 'Busy'
Occupé
-
+
Choisir un profil
-
+
Merci de choisir l'identité à utiliser
-
+
Choisissez une image de profil
-
-
-
+
+
+
Erreur
-
+
Impossible d'ouvrir ce fichier
-
+
Impossible de lire cette image
-
+
Cette image est trop volumineuse
-
+
ToxCore n'as pas pu démarrer correctement, l'application va s'arrêter quand vous fermerez cette alerte.
-
+
popup text
ToxCore n'as pas pu démarrer avec ces paramètres proxy. Merci de modifier ou désactiver vos paramètres et redémarrer l'application.
-
+
Ajouter un contact
-
+
Transfers
-
+
Options
-
+
Impossible d'envoyer la demande de contact
-
+
contact status
absent
-
+
contact status
occupé
-
+
contact status
hors ligne
-
+
contact status
connecté
-
+
e.g. "Dubslow is now online"
%1 est maintenant %2
-
+
Placeholder when we don't know someone's name in a group chat
<Inconnu>
-
+
+
+ %1 a changé le titre en %2
+
+
+
Le message n'as pu être envoyé
diff --git a/translations/i18n.pri b/translations/i18n.pri
index d76b12b0c..d13f328e2 100644
--- a/translations/i18n.pri
+++ b/translations/i18n.pri
@@ -6,6 +6,7 @@ TRANSLATIONS = translations/es.ts \
translations/fi.ts \
translations/fr.ts \
translations/it.ts \
+ translations/lt.ts \
translations/mannol.ts \
translations/pirate.ts \
translations/pl.ts \
diff --git a/translations/it.ts b/translations/it.ts
index 116745236..d8c436cda 100644
--- a/translations/it.ts
+++ b/translations/it.ts
@@ -8,16 +8,21 @@
Audio/Video
+
+
+
+ Inizializzazione Webcam...
+
AVSettings
-
+
Impostazioni Video
-
+
Risoluzione
@@ -36,43 +41,76 @@
Impostazioni Audio
+
+
+
+ Usa lo slider per impostare il volume degli altoparlanti.
+ATTENZIONE: lo slider è ancora non funzionante.
+
+
+ Usa lo slider per impostare il volume del microfono.
+ATTENZIONE: lo slider è ancora non funzionante.
+
+
+
Dispositivo di output
-
+
Dispositivo di input
-
+
Cerca dispositivi audio
-
+
Filtra audio
-
+
+
+ Filtra l'audio del microfono, così le persone che chiami ti sentiranno meglio.
+
+
+
+
+
+ Imposta la risoluzione della webcam.
+Più alto il valore, migliore sarà la qualità del video che i tuoi contatti riceveranno.
+NOTA: più alta è la qualità video, più veloce deve essere la connessione ad internet.
+Può capitare che la tua connessione ad internet non sia abbastanza veloce per gestire
+qualità video elevate, questo può causare problemi con le chiamate video.
+
+
+
Colore
-
+
Luminoistà
-
+
Saturazione
-
+
Contrasto
@@ -141,17 +179,17 @@ Ignorare le impostazioni del proxy e connettersi direttamente alla rete Tox?Avanzate
-
+
COMPLETO - molto sicuro; lento (consigliato)
-
+
NORMALE - quasi sicuro come COMPLETO, ma circa 20% più veloce
-
+
DISABILITATO - disabilita tutta la sicurezza, quando qualcosa va male i log possono essere persi; veloce (non consigliato)
@@ -165,21 +203,32 @@ Ignorare le impostazioni del proxy e connettersi direttamente alla rete Tox?
+
+ describes makeToxPortable checkbox
+ Slava le impostazioni nella directory di lavoro corrente, invece della directory di default
+
+
+
+
+ Rendi qTox portabile
+
+
+
<html><head/><body><p><span style=" font-weight:600; color:#ff0000;">IMPORTATNTE</span></p><p><span style=" color:#ff0000;">Se non sai </span><span style=" font-weight:600; color:#ff0000;">esattamente</span><span style=" color:#ff0000;"> cosa stai facendo, </span><span style=" font-weight:600; color:#ff0000;">non</span><span style=" color:#ff0000;"> cambiare niente. Le modifiche possono portare a problemi nel funzionamento di qTox e/o alla perdita di dati (per esempio i log delle chat).</span></p></body></html>
-
+
Reimposta impostazioni di default
-
+
Chat Log
-
+
<html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Scritture sincrone sul DB
@@ -187,72 +236,76 @@ Ignorare le impostazioni del proxy e connettersi direttamente alla rete Tox?
ChatForm
-
+
Carica log...
-
+
Invia un file
-
+
+
Impossibile leggere il file
-
+
+
qTox non è riuscito ad aprire %1
-
+
+
Pessima idea
-
+
+
Stai cercando di inviare un file speciale (sequenziale), questo non funzionerà!
-
+
%1 ti sta chiamando
-
+
%1 ha fermato la chiamata
-
+
Stai chiamando %1
-
+
Invio del file "%1" fallito
-
+
Chiamata con %1 terminata. %2
-
+
Durata chiamata:
-
+
sta scrivendo...
-
+
Chiamata rifiutata
@@ -268,105 +321,105 @@ Ignorare le impostazioni del proxy e connettersi direttamente alla rete Tox?
Core
-
+
Toxing on qTox
-
+
qTox User
-
+
Questo contatto è già presente nella tua lista
-
+
Errore crittografia
-
+
Il Tox datafile è criptato, ma la crittografia non è abilitata nelle impostazioni.
Continuo ignorando le impostazioni.
-
+
Password per decriptare il Tox datafile
-
-
-
+
+
+
Errore password
-
-
+
+
Impossibile impostare la password.
Password vuota.
-
+
Riprova
-
+
Cambia profilo
-
+
Reinizializza il profilo corrente
-
+
È stata inserita una password sbagliata
-
+
Password per decriptare i log
-
+
Log criptato
-
+
I log delle chat sono criptati con una password diversa.
Vuoi provare ad inserire un'altra password?
-
+
Chat Log
-
+
Password errata, i log delle chat non saranno caricati.
-
+
Nessuna password
-
+
Il Tox datafile sarà salvato senza password!
@@ -419,34 +472,34 @@ Vuoi provare ad inserire un'altra password?
FriendRequestDialog
-
+
Title of the window to aceept/deny a friend request
Richiesta d'amicizia
-
+
Qualcuno vuole chattare con te
-
+
ID Utente:
-
+
Messaggio della richiesta d'amicizia:
-
+
Accept a friend request
Accetta
-
+
Reject a friend request
Rifiuta
@@ -510,25 +563,25 @@ Soprannome:
Generale
-
-
+
+
Nessuno
-
+
popup title
Scegli dove salvare i files accettati automaticamente
-
+
popup title
Chiamata in corso
-
+
popup text
Non puoi disconnetterti mentre c'è una chiamata in corso!
@@ -548,210 +601,291 @@ Soprannome:
La traduzione potrebbe non essere caricata fino al prossimo riavvio di qTox.
-
+
+
+ Lingua:
+
+
+
+
+ Barra di sistema
+
+
+
Mostra icona nella traybar
-
+
- Icona brillante
+ Usa icona brillante
-
+
+
+ toolTip for light icon setting
+ Abilita icona brillante nella trybar.
+
+
+
+
+ toolTip for Start in tray setting
+ qTox sarà avviato minimizzato nella traybar.
+
+
+
+
+ toolTip for close to tray setting
+ Premendo l'icona "chiudi" (X) qTox sarà minimizzato
+nella traybar invece che essere chiuso.
+
+
+
+
+ toolTip for minimize to tray setting
+ Premendo l'icona "minimizza" (_) qTox sarà minimizzato
+nella traybar invece che nella taskbar.
+
+
+
+
+ Controlla aggiornamenti all'avvio
+
+
+
+
+ Salva in:
+
+
+
+
+
+ Scegli dove salvare i files ricevuti.
+
+
+
Imposta 0 per disabilitare
-
+
+
+ Il tuo stato sarà cambaito in "Assente" dopo l'ammontare di tempo impostato.
+
+
+
+
+ Mostra come assente dopo (0 per disabilitare):
+
+
+
+
+ Chat
+
+
+
+
+ toolTip for Group chat always notify
+ Mostra sempre le notifiche per i nuovi messaggi nelle chat di gruppo.
+
+
+
+
+ Usa notifiche per chat di gruppo
+
+
+
+
+ Quando arriva un nuovo messaggio:
+
+
+
+
+ tooltip for Show window setting
+ Porta la finestra di qTox in primo piano quando arriva un nuovo messaggio.
+
+
+
+
+ Mostra finestra
+
+
+
+
+ toolTip for Show window setting
+ Dai il focus alla finestra di qTox quando arriva un nuovo messaggio.
+
+
+
+
+ Dai il focus alla finestra
+
+
+
+
+ toolTip for Faux offline messaging setting
+ I messaggi che invii ai contatti offline saranno inviati quando appaiono online.
+
+
+
+
+ toolTip for compact layout setting
+ La lista contatti sarà visualizzata in modalità compatta.
+Richiede riavvio.
+
+
+
+
+ Usa lista contatti compatta
+
+
+
+
+ Text on smiley pack label
+ Emoticons:
+
+
+
+
+ Dimensione:
+
+
+
+
+ Stile:
+
+
+
+
+ Colore tema:
+
+
+
+
+ Formato data/ora:
+
+
+
Impostazioni Connessione
-
+
Text on a checkbox to enable IPv6
Abilita IPv6 (consigliato)
-
-
- describes makeToxPortable checkbox
- Slava le impostazioni nella directory di lavoro corrente, invece della directory di default
+
+
+ Proxy:
-
-
- Lingua
+
+
+ Text on proxy addr label
+ Indirizzo:
-
-
- Rendi qTox portabile
-
-
-
-
- Integrazione Traybar
-
-
-
+
Avvia nella traybar
-
+
Chiudi nella traybar
-
+
Minimizza nella traybar
-
+
Mostra quando i contatti cambiano stato
-
-
- Controlla aggiornamenti all'avvio (unstable)
-
-
-
-
- Dai il focus a qTox quando arriva un messaggio
-
-
-
+
- Falsi messaggi offline
+ Usa falsi messaggi offline
-
-
- Espresso in minuti
-
-
-
-
- Imposta assenza dopo
-
-
-
+
minuti
-
+
autoaccept cb tooltip
Puoi impostare questa preferenza per ogni singolo contatto usando il click destro sul suo nome.
-
+
Accetta automaticamente i trasferimenti di files
-
-
- Salva i files in
-
-
-
+
Sfoglia
-
+
Impostazioni Tema
-
+
Usa emoticons
-
-
- Text on smiley pack label
- Emoticons
-
-
-
-
- Stile
-
-
-
-
- Colore
-
-
-
-
- Dimensione emoticons
-
-
-
+
px
-
-
- Formato data/ora
-
-
-
+
force tcp checkbox tooltip
Disabilitando questo sarà possibile usare qTox con Tor. Tuttavia verrà aggiunto carico alla rete Tox, quindi disabilitare solo se necessario.
-
+
Text on checkbox to disable UDP
Abilita UDP (consigliato)
-
-
- Proxy
-
-
-
+
Nessuno
-
+
SOCKS 5
-
+
HTTP
-
-
- Text on proxy addr label
- IP
-
-
-
+
Text on proxy port label
Porta
-
+
reconnect button
Riconnetti
@@ -760,53 +894,53 @@ Soprannome:
GenericChatForm
-
+
Invia messaggio
-
+
Emoticons
-
+
Invia file(s)
-
+
Chiamata audio: ROSSO significa che la chiamata è in corso
-
+
Videochiamata: ROSSO significa che la chiamata è in corso
-
+
Imposta volume altoparlanti: ROSSO è SPENTO
-
+
Imposta microfono: ROSSO è SPENTO
-
-
+
+
Salva il log della chat
-
+
Rimuovi messaggi visualizzati
-
+
Pulito
@@ -871,87 +1005,87 @@ Nome gruppo:
Identità
-
+
popup title
Chiamata in corso
-
+
popup text
Non puoi cambiare profilo durante una chiamata!
-
+
renaming a profile
Rinomina "%1"
-
+
rename confirm title
Profilo già esistente
-
+
rename confirm text
Un profilo chiamato "%1" esiste già. Vuoi sovrascriverlo?
-
+
save dialog title
Esporta profilo
-
+
save dialog filter
Tox save file (*.tox)
-
+
Impossibile rimuovere il file
-
+
Il file che hai scelto di sovrascrivere non può essere prima rimosso.
-
+
Impossibile copiare il file
-
+
Il file che hai scelto non può essere copiato.
-
+
current profile deletion warning title
Profilo attualmente in uso
-
+
current profile deletion warning text
Questo profilo è attualmente in uso. Per favore carica un profilo differente prima di eliminare questo.
-
+
deletion confirmation title
Eliminazione imminente!
-
+
deletion confirmation text
@@ -959,37 +1093,37 @@ Associated friend information and chat logs will be deleted as well.
I contatti e i log delle chat associati ad esso, saranno eliminati.
-
+
import dialog title
Importa profilo
-
+
import dialog filter
Tox save file (*.tox)
-
+
popup title
File ignorato
-
+
popup text
Attenzione: hai scelto un file che non contiente un profilo Tox.\nQuesto file verrà ignorato.
-
+
import confirm title
Profilo già esistente
-
+
import confirm text
Un profilo chiamato "%1" esiste già. Vuoi sovrascriverlo?
@@ -1018,65 +1152,104 @@ I contatti e i log delle chat associati ad esso, saranno eliminati.Tox ID
-
+
+
+ Tox ID tooltip
+ Qesto mucchio di caratteri serve agli altri client Tox per contattarti.
+Condivilo con chi vuoi comunicare.
+
+
+
(clicca qui per copiare)
-
+
Gestione Profili
-
+
Profili disponibili:
-
+
+
+ toolTip for currently set profile
+ Profilo corrente.
+
+
+
+
+ tooltip for loading profile button
+ Carica il profilo selezionato.
+
+
+
load profile button
Carica
-
-
-
- tooltip
- Non puoi cambiare profilo durante una chiamata
-
-
-
+
rename profile button
Rinomina
-
+
+
+ tooltip for renaming profile button
+ Rinomina il profilo selezionato.
+
+
+
export profile button
Esporta
-
+
+
+ tooltip for profile exporting button
+ Esporta il profilo corrente in un file.
+I profili non contengono la cronologia messaggi.
+
+
+
+
+ delete profile button tooltip
+ Elimina il profilo selezionato.
+
+
+
delete profile button
Elimina
-
-
- delete profile button tooltip
- Utile per preservare la tua sicurezza su computer pubblici
-
-
-
+
import profile button
Importa profilo
-
+
+
+ tooltip for importing profile button
+ Importa un profilo da un file ".tox".
+
+
+
+
+ tooltip for creating new Tox ID button
+ Crea un nuovo profilo (Tox ID) e iniza subito ad usarlo.
+
+
+
new profile button
Nuovo profilo
@@ -1176,6 +1349,12 @@ Vuoi eliminare il vecchio file?
PrivacySettings
+
+
+
+ tooltip for typing notifications setting
+ I tuoi contatti potranno vedere se stai digitando un messaggio.
+
@@ -1187,32 +1366,52 @@ Vuoi eliminare il vecchio file?
Salva log delle chat (unstable)
-
+
+
+ toolTip for history setting
+ La cronologia messaggi è disponibile in qTox, ma non possiamo promettere che un giorno non sparisca senza lasciare tracce :-/
+Faremo del nostro meglio per assicurarci che questo non accada!
+
+
+
Crittografiia
-
+
Cripta Tox datafile
-
+
Cripta log delle chat
-
+
Nospam
-
+
+
+ toolTip for nospam
+ Il valore "nospam" fa parte del tuo Tox ID.
+Lo si deve modificare quando si ritiene che si stanno ricevendo troppe richiste d'amicizia da persone sconosciute.
+Quando modifichi il valore "nospam", i contatti che hai già aggiunto potranno continuare a comunicare con te,
+ma i nuovi contatti dovranno conoscere il tuo nuovo Tox ID per aggiungerti.
+
+
+
HHHHHHHH
-
+
Genera valore nospam casuale
@@ -1260,13 +1459,13 @@ Vuoi eliminare il vecchio file?
%1.tox è stato importato con successo
-
+
The title of a message box
Nuova versione
-
+
È disponibile una nuova versione di qTox, vuoi scaricarla adesso?
@@ -1312,6 +1511,11 @@ Verrà installata al riavvio del programma.
Viola
+
+
+
+ Chiamata in arrivo...
+
SetPasswordDialog
@@ -1446,134 +1650,134 @@ Usare comunque il protocollo tox1?
&Esci
-
+
Button to set your status to 'Online'
Online
-
+
Button to set your status to 'Away'
Assente
-
+
Button to set your status to 'Busy'
Occupato
-
+
Scegli un profilo
-
+
Per favore scegli quale identità usare
-
+
Scegli un'immagine per il profilo
-
-
-
+
+
+
Errore
-
+
Impossibile aprire il file
-
+
Impossibile leggere l'immagine
-
+
L'immagine è troppo grande
-
+
Impossibile avviare Toxcore.\nqTox terminerà dopo che avrai chiuso questo messaggio.
-
+
popup text
Impossibile avviare Toxcore con le tue impostazione proxy.\nqTox non può funzionare correttamente, per favore modifica le impostazioni e riavvia il programma.
-
+
Aggiungi contatto
-
+
Files trasferiti
-
+
Impostazioni
-
+
Impossibile inviare la richiesta d'amicizia
-
+
contact status
assente
-
+
contact status
occupato
-
+
contact status
offline
-
+
contact status
online
-
+
e.g. "Dubslow is now online"
%1 è ora %2
-
+
Placeholder when we don't know someone's name in a group chat
<Sconosciuto>
-
+
%1 ha impostato il titolo in %2
-
+
Impossibile inviare il messaggio
diff --git a/translations/lt.ts b/translations/lt.ts
new file mode 100644
index 000000000..c907a1ae7
--- /dev/null
+++ b/translations/lt.ts
@@ -0,0 +1,1579 @@
+
+
+
+
+ AVForm
+
+
+
+ Garsas ir vaizdas
+
+
+
+ AVSettings
+
+
+
+ Garso įrenginiai
+
+
+
+
+ Įrašymas
+
+
+
+
+ Išvestis
+
+
+
+
+ Išvesties įrenginys
+
+
+
+
+ Įrašymo įrenginys
+
+
+
+
+ Aptikti garso įrenginius iš naujo
+
+
+
+
+ Filtruoti garso signalą
+
+
+
+
+ Vaizdo nustatymai
+
+
+
+
+ Raiška
+
+
+
+
+ Atspalviai
+
+
+
+
+ Ryškumas
+
+
+
+
+ Sodrumas
+
+
+
+
+ Kontrastas
+
+
+
+ AddFriendForm
+
+
+
+ Pridėti kontaktą
+
+
+
+
+ Tox ID of the person you're sending a friend request to
+ Tox ID
+
+
+
+
+ The message you send in friend requests
+ Prisistatymo žinutė
+
+
+
+
+ Siųsti užklausą
+
+
+
+
+ Default message in friend requests if the field is left blank. Write something appropriate!
+ Gal susirašinėjam per Tox?
+
+
+
+
+ Tox ID of the friend you're sending a friend request to
+ Įveskite tinkamą kontakto Tox ID
+
+
+
+
+ When trying to add your own Tox ID as friend
+ Negalite naudoti savo Tox ID!
+
+
+
+
+ qTox naudoja Tox DNS, bet tai neįmanoma per įgaliotąjį (proxy) serverį.
+Ignoruoti įgaliotąjį serverį ir jungtis prie interneto tiesiogiai?
+
+
+
+
+ DNS error
+ Tokio Tox ID nėra
+
+
+
+ AdvancedForm
+
+
+
+ Kita
+
+
+
+
+ VISADA – saugiai, bet lėtai (rekomenduojama)
+
+
+
+
+ ĮPRASTAI – beveik taip pat saugiai, bet 20 % greičiau
+
+
+
+
+ NELAUKTI – apsauga išjungta: kilus problemoms gali dingti pokalbių žurnalas – greičiausia (nerekomenduojama)
+
+
+
+ AdvancedSettings
+
+
+
+ Forma
+
+
+
+
+ <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">SVARBUS PRANEŠIMAS</span></p><p><span style=" color:#ff0000;">Nebent </span><span style=" font-weight:600; color:#ff0000;">tikrai</span><span style=" color:#ff0000;"> išmanote kaip elgtis, </span><span style=" font-weight:600; color:#ff0000;">nieko</span><span style=" color:#ff0000;"> čia nekeiskite. Pakeitimai gali sukelti problemų naudotis qTox bei net duomenų (pvz., pokalbių žurnalo) praradimą.</span></p></body></html>
+
+
+
+
+ Atstatyti pradinius nustatymus
+
+
+
+
+ Pokalbių žurnalas
+
+
+
+
+ <html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Laukti, kol pildoma duomenų bazė</span></a></p></body></html>
+
+
+
+ ChatForm
+
+
+
+ Įkelti pokalbių žurnalą...
+
+
+
+
+ Siųsti failą
+
+
+
+
+ Failas neperskaitomas
+
+
+
+
+ qTox nepavyko atidaryti %1
+
+
+
+
+ Bloga mintis
+
+
+
+
+ Bandote siųsti ypatingą (nuoseklųjį) failą, tai nepavyks!
+
+
+
+
+ %1 skambina
+
+
+
+
+ %1 nutraukė skambutį
+
+
+
+
+ Skambiname: %1
+
+
+
+
+ Skambutis atmestas
+
+
+
+
+ Nepavyko nusiųsti failo „%1“
+
+
+
+
+ Pokalbis su %1 baigėsi. %2
+
+
+
+
+ Pokalbio trukmė:
+
+
+
+
+ rašo žinutę...
+
+
+
+ ChatTextEdit
+
+
+
+ Įveskite čia savo žinutę...
+
+
+
+ Core
+
+
+
+ Naudoju qTox
+
+
+
+
+ qTox naudotojas
+
+
+
+
+ Toks kontaktas jau pridėtas
+
+
+
+
+ Šifro klaida
+
+
+
+
+ .tox failas užšifruotas: nors šifras nepatikrintas, tęsiame darbą.
+
+
+
+
+ Slaptažodis Tox duomenų failui iššifruoti
+
+
+
+
+
+
+ Slaptažodis netinka
+
+
+
+
+
+ Nepavyko nustatyti slaptažodžio.
+Slaptažodis tuščias.
+
+
+
+
+ Bandykite dar kartą
+
+
+
+
+ Pakeisti profilį
+
+
+
+
+ Išvalyti dabartinį profilį
+
+
+
+
+ Įvestas slaptažodis netinka
+
+
+
+
+ Pokalbių žurnalo šifro slaptažodis
+
+
+
+
+ Žurnalas užšifruotas
+
+
+
+
+ Jūsų pokalbių žurnalas užšifruotas kitu slaptažodžiu.
+Norite išmėginti kitą slaptažodį?
+
+
+
+
+ Žurnalas
+
+
+
+
+ Dėl netinkamo slaptažodžio pokalbių žurnalas išjungtas.
+
+
+
+
+ NĖRA slaptažodžio
+
+
+
+
+ Bus saugojama be šifro!
+
+
+
+ FileTransferInstance
+
+
+
+ Title of the file saving dialog
+ Išsaugoti failą
+
+
+
+
+ Title of permissions popup
+ Įrašyti failo čia neleidžiama
+
+
+
+
+ text of permissions popup
+ Nėra teisių įrašyti failą šioje vietoje. Bandykite įrašyti kitur arba atšaukite dialogo langą.
+
+
+
+
+ Liko
+
+
+
+ FilesForm
+
+
+
+ "Headline" of the window
+ Baigti siųsti failai
+
+
+
+
+ Parsiųsti
+
+
+
+
+ Nusiųsti
+
+
+
+ FriendRequestDialog
+
+
+
+ Title of the window to aceept/deny a friend request
+ Kontakto užklausa
+
+
+
+
+ Kažkas nori su Jumis bendrauti
+
+
+
+
+ Naudojo ID:
+
+
+
+
+ Prisistatymo žinutė:
+
+
+
+
+ Accept a friend request
+ Priimti kontaktą
+
+
+
+
+ Reject a friend request
+ Atmesti kontaktą
+
+
+
+ FriendWidget
+
+
+
+ Menu to invite a friend to a groupchat
+ Pakviesti į grupės pokalbį
+
+
+
+
+ Menu to copy the Tox ID of that friend
+ Nukopijuoti kontakto ID
+
+
+
+
+ Nustatyti slapyvardį...
+
+
+
+
+ context menu entry
+ Automatiškai priimti failus iš šio kontakto
+
+
+
+
+ Menu to remove the friend from our friendlist
+ Pašalinti kontaktą
+
+
+
+
+ popup title
+ Pasirinkite priimamų failų katalogą
+
+
+
+
+ Naudotojo slapyvardis
+
+
+
+
+ Slapyvardį pakeisti galima ir spustelėjus pokalbių lange.
+Slapyvardis:
+
+
+
+ GeneralForm
+
+
+
+ Bendrosios
+
+
+
+
+
+ Nėra
+
+
+
+
+ popup title
+ Pasirinkite priimamų failų katalogą
+
+
+
+
+ popup title
+ Vyksta pokalbis
+
+
+
+
+ popup text
+ Vykstant pokalbiui atsijungti negalite!
+
+
+
+ GeneralSettings
+
+
+
+ Bendrosios nuostatos
+
+
+
+
+
+ Vertimas gali nepasirodyti, kol nepaleisite qTox iš naujo.
+
+
+
+
+ Vertimas
+
+
+
+
+ describes makeToxPortable checkbox
+ Nuostatas saugoti veikiamajame kataloge, o ne įprastame nuostatų kataloge
+
+
+
+
+ Leisti persinešti Tox programą
+
+
+
+
+ Sistemos juostelės integracija
+
+
+
+
+ Rodyti sistemos juostelėje
+
+
+
+
+ Paleidžiant paslėpti juostelėje
+
+
+
+
+ Uždarant paslėpti juostelėje
+
+
+
+
+ Sumažinant paslėpti juostelėje
+
+
+
+
+ Šviesi piktograma
+
+
+
+
+ Rodyti kontaktų būsenos pokyčius
+
+
+
+
+ Ieškoti atnaujinimų paleidžiant (nestabili funkcija)
+
+
+
+
+ Sufokusuoti qTox gavus žinutę
+
+
+
+
+ Kaupti žinutes atsijungus adresatui
+
+
+
+
+ Laikas minutėmis
+
+
+
+
+ Automatiškai „pasitraukęs“ po („0“ išjungia)
+
+
+
+
+ Išjungsite nustatydami „0“
+
+
+
+
+ minučių
+
+
+
+
+ autoaccept cb tooltip
+ Galite nustatyti individualiai ant bet kurio kontakto spustelėję dešiniuoju pelės klavišu.
+
+
+
+
+ Automatiškai priimti failus
+
+
+
+
+ Išsaugoti failus
+
+
+
+
+ PushButton
+
+
+
+
+ Apipavidalinimas
+
+
+
+
+ Naudoti jaustukus
+
+
+
+
+ Text on smiley pack label
+ Jaustukų rinkinys
+
+
+
+
+ Stilius
+
+
+
+
+ Apipavidalinimo spalva
+
+
+
+
+ Jaustukų dydis
+
+
+
+
+ px
+
+
+
+
+ Laiko formatas
+
+
+
+
+ Ryšio nuostatos
+
+
+
+
+ Text on a checkbox to enable IPv6
+ Įjungti IPv6 (rekomenduojama)
+
+
+
+
+ force tcp checkbox tooltip
+ Išjungus galima naudotis Tox protokolu per Tor. Tox tinklas dėl to yra papildomai apkraunamas, todėl atžymėkite tik tada, kai reikia.
+
+
+
+
+ Text on checkbox to disable UDP
+ Įjungti UDP (rekomenduojama)
+
+
+
+
+ Įgaliotojo serverio tipas
+
+
+
+
+ Nėra
+
+
+
+
+ SOCKS5
+
+
+
+
+ HTTP
+
+
+
+
+ Text on proxy addr label
+ Adresas
+
+
+
+
+ Text on proxy port label
+ Prievadas
+
+
+
+
+ reconnect button
+ Prisijungti iš naujo
+
+
+
+ GenericChatForm
+
+
+
+ Siųsti žinutę
+
+
+
+
+ Jaustukai
+
+
+
+
+ Siųsti failą (-us)
+
+
+
+
+ Pokalbis su garsu: RAUDONA reiškia, kad vyksta pokalbis
+
+
+
+
+ Pokalbis su vaizdu: RAUDONA reiškia, kad vyksta pokalbis
+
+
+
+
+ Garsiakalbiai: RAUDONA reiškia IŠJUNGTA
+
+
+
+
+ Mikrofonas: RAUDONA reiškia IŠJUNGTA
+
+
+
+
+
+ Išsaugoti pokalbio žurnalą
+
+
+
+
+ Išvalyti rodomas žinutes
+
+
+
+
+ Išvalyta
+
+
+
+ GroupChatForm
+
+
+
+ Number of users in chat
+ Pokalbyje %1 žmonių
+
+
+
+
+ Pokalbyje %1 žmonių
+
+
+
+ GroupWidget
+
+
+
+
+ Pokalbyje %1 žmonių
+
+
+
+
+
+ Pokalbyje žmonių nėra
+
+
+
+
+ Nustatyti pavadinimą...
+
+
+
+
+ Menu to quit a groupchat
+ Palikti grupės pokalbį
+
+
+
+
+ Grupės pavadinimas
+
+
+
+
+ Pavadinimą pakeisti galima ir spustelėjus pokalbių lange.
+Pavadinimas:
+
+
+
+ IdentityForm
+
+
+
+ Tapatybė
+
+
+
+
+ popup title
+ Vyksta pokalbis
+
+
+
+
+ popup text
+ Vykstant pokalbiui profilių keisti negalima!
+
+
+
+
+ renaming a profile
+ Pervadinti „%1“
+
+
+
+
+ rename confirm title
+ Toks profilis jau yra
+
+
+
+
+ rename confirm text
+ Profilis „%1“ jau yra. Ar norite jį ištrinti?
+
+
+
+
+ save dialog title
+ Eksportuoti profilį
+
+
+
+
+ save dialog filter
+ Tox failas (*.tox)
+
+
+
+
+ Failo ištrinti nepavyko
+
+
+
+
+ Perrašomo failo pirma ištrinti nepavyko.
+
+
+
+
+ Failo nukopijuoti nepavyko
+
+
+
+
+ Nepavyko įrašyti į pasirinktą failą.
+
+
+
+
+ current profile deletion warning title
+ Profilis aktyvus
+
+
+
+
+ current profile deletion warning text
+ Šis profilis yra aktyvus. Prieš jį ištrindami turite įjungti kitą profilį.
+
+
+
+
+ deletion confirmation title
+ Gresia ištrynimas!
+
+
+
+
+ deletion confirmation text
+ Ar tikrai norite ištrinti šį profilį?
+Susijusi kontaktų informacija bei pokalbių žurnalas bus taip pat ištrinti.
+
+
+
+
+ import dialog title
+ Importuoti profilį
+
+
+
+
+ import dialog filter
+ Tox failas (*.tox)
+
+
+
+
+ popup title
+ Rodomi tik Tox failai
+
+
+
+
+ popup text
+ Įspėjimas: pasirinktas failas nėra Tox failas – praleista.
+
+
+
+
+ import confirm title
+ Toks profilis jau yra
+
+
+
+
+ import confirm text
+ Profilis „%1“ jau yra. Ar norite jį ištrinti?
+
+
+
+ IdentitySettings
+
+
+
+ Vieša informacija
+
+
+
+
+ Vardas
+
+
+
+
+ Būsena
+
+
+
+
+ Tox ID
+
+
+
+
+ Jūsų Tox ID (spustelėję nukopijuosite)
+
+
+
+
+ Profiliai
+
+
+
+
+ Išsaugoti profiliai:
+
+
+
+
+
+ tooltip
+ Pokalbio metu keisti profilio negalima
+
+
+
+
+ load profile button
+ Aktyvuoti
+
+
+
+
+ rename profile button
+ Pervadinti
+
+
+
+
+ export profile button
+ Eksportuoti
+
+
+
+
+ delete profile button tooltip
+ Tai naudinga, jei norite likti saugūs prie viešai prieinamų kompiuterių
+
+
+
+
+ delete profile button
+ Ištrinti
+
+
+
+
+ import profile button
+ Importuoti profilį
+
+
+
+
+ new profile button
+ Naujas Tox ID
+
+
+
+ InputPasswordDialog
+
+
+
+ Slaptažodis
+
+
+
+
+ Įveskite slaptažodį:
+
+
+
+ LoadHistoryDialog
+
+
+
+ Įkelti žurnalą
+
+
+
+
+ Įkelti pokalbių žurnalą nuo:
+
+
+
+ MainWindow
+
+
+
+ Jūsų vardas
+
+
+
+
+ Jūsų būsena
+
+
+
+
+ Pridėti kontaktą
+
+
+
+
+ Sukurti grupės pokalbį
+
+
+
+
+ Rodyti baigtus siųsti failus
+
+
+
+
+ Keisti nuostatas
+
+
+
+
+ Uždaryti
+
+
+
+ NetCamView
+
+
+
+ Tox vaizdas
+
+
+
+ PrivacyForm
+
+
+
+ Privatumas
+
+
+
+
+ Užšifruotas žurnalas
+
+
+
+
+ Jau turite kitu slaptažodžiu šifruotą žurnalą
+Ar norite senąjį pokalbių žurnalą ištrinti?
+
+
+
+ PrivacySettings
+
+
+
+ Rodyti, kad rašote žinutę
+
+
+
+
+ Išsaugoti žurnalą (nestabili funkcija)
+
+
+
+
+ Šifravimas
+
+
+
+
+ Šifruoti Tox duomenų failą
+
+
+
+
+ Šifruoti pokalbių žurnalą
+
+
+
+
+ Tox ID apsauga nuo nepageidaujamų kontaktų (nospam)
+
+
+
+
+ HHHHHHHH
+
+
+
+
+ Sugeneruoti atsitiktinį
+
+
+
+ QObject
+
+
+
+ The title of a message box
+ Atnaujinimas
+
+
+
+
+ Rasta nauja programos versija, ar norite ją parsisiųsti?
+Ji bus įdiegta paleidus qTox iš naujo.
+
+
+
+
+ analizuoti Tox URI
+
+
+
+
+ Atidaro naują langą ir aktyvuoja nurodytą profilį.
+
+
+
+
+ profilis
+
+
+
+
+ Numatyta
+
+
+
+
+ Mėlyna
+
+
+
+
+ Alyvinė
+
+
+
+
+ Raudona
+
+
+
+
+ Violetinė
+
+
+
+
+ popup title
+ Praleidžiamas failas
+
+
+
+
+ popup text
+ Įspėjimas: pasirinktas failas nėra Tox failas – praleista.
+
+
+
+
+ import confirm title
+ Toks profilis jau yra
+
+
+
+
+ import confirm text
+ Profilis „%1“ jau yra. Ar norite jį ištrinti?
+
+
+
+
+ Profilis importuotas
+
+
+
+
+ %1.tox sėkmingai importuotas
+
+
+
+
+ Default message in Tox URI friend requests. Write something appropriate!
+ Gal susirašinėjam per Tox?
+
+
+
+ SetPasswordDialog
+
+
+
+ Įveskite slaptažodį
+
+
+
+
+ Pakartokite slaptažodį
+
+
+
+ ToxDNS
+
+
+
+ The DNS gives the Tox ID associated to toxme.se addresses
+ Ryšio sudaryti nepavyko
+
+
+
+
+ The DNS gives the Tox ID associated to toxme.se addresses
+ Tokio adreso nėra
+
+
+
+
+ The DNS gives the Tox ID associated to toxme.se addresses
+ Klaida gaunant DNS duomenis
+
+
+
+
+ Error with the DNS
+ DNS įrašas nerastas
+
+
+
+
+ Error with the DNS
+ Netinkamas DNS įrašas
+
+
+
+
+ Error with the DNS
+ Šio serverio Tox DNS versija nepalaikoma
+
+
+
+
+ Error with the DNS
+ DNS atsake nėra Tox ID
+
+
+
+
+
+ Error with the DNS
+ DNS atsake nėra tinkamo Tox ID
+
+
+
+
+
+ Panašu, kad qTox turi naudoti senąjį tox1 protokolą.
+Deja tox1 protokolas turi saugumo spragų. Tęsti?
+
+
+
+ ToxURIDialog
+
+
+
+ Title of the window to add a friend through Tox URI
+ Pridėti kontaktą
+
+
+
+
+ Ar norite pridėti %1 į kontaktus?
+
+
+
+
+ Naudotojo ID:
+
+
+
+
+ Prisistatymo žinutė:
+
+
+
+
+ Send a friend request
+ Siųsti
+
+
+
+
+ Don't send a friend request
+ Atšaukti
+
+
+
+ Widget
+
+
+
+ Prisijungęs
+
+
+
+
+ Pasitraukęs
+
+
+
+
+ Užsiėmęs
+
+
+
+
+ &Baigti
+
+
+
+
+ Button to set your status to 'Online'
+ Prisijungęs
+
+
+
+
+ Button to set your status to 'Away'
+ Pasitraukęs
+
+
+
+
+ Button to set your status to 'Busy'
+ Užsiėmęs
+
+
+
+
+ Pasirinkti profilį
+
+
+
+
+ Pasirinkite, kurią tapatybę naudoti
+
+
+
+
+ Pasirinkite profilio paveikslėlį
+
+
+
+
+
+
+ Klaida
+
+
+
+
+ Nepavyko atidaryti failo
+
+
+
+
+ Nepavyko perskaityti paveikslėlio
+
+
+
+
+ Paveikslėlis per didelis
+
+
+
+
+ Toxcore paleisti nepavyko: programa išsijungs uždarius šį pranešimą.
+
+
+
+
+ popup text
+ Toxcore neprisijungia su Jūsų įgaliotojo serverio nustatymais. qTox negali dirbti – pakeiskite nustatymus ir prisijunkite iš naujo.
+
+
+
+
+ Pridėti kontaktą
+
+
+
+
+ Failų siuntimai
+
+
+
+
+ Nuostatos
+
+
+
+
+ Nepavyko nusiųsti užklausos
+
+
+
+
+ contact status
+ pasitraukęs (-usi)
+
+
+
+
+ contact status
+ užsiėmęs (-usi)
+
+
+
+
+ contact status
+ neprisijungęs (-usi)
+
+
+
+
+ contact status
+ prisijungęs (-usi)
+
+
+
+
+ e.g. "Dubslow is now online"
+ %1 dabar %2
+
+
+
+
+ Placeholder when we don't know someone's name in a group chat
+ <Nepažįstamas>
+
+
+
+
+ %1 nustatė pavadinimą „%2“
+
+
+
+
+ Nepavyko nusiųsti žinutės
+
+
+
diff --git a/translations/pl.ts b/translations/pl.ts
index 4c7666729..c7daad941 100644
--- a/translations/pl.ts
+++ b/translations/pl.ts
@@ -8,6 +8,11 @@
Audio/Wideo
+
+
+
+ Inicjowanie kamery...
+
AVSettings
@@ -17,24 +22,24 @@
Ustawienia audio
-
+
better translation?
Urządzenie wyjściowe
-
+
better translation?
Urządzenie wejściowe
-
+
Ustawienia wideo
-
+
Rozdzielczość
@@ -49,27 +54,64 @@
Mikrofon
-
+
+
+
+
+
+
+
+
+
+
+
Ponownie skanuj urządzenia audio
-
+
+
+ better translation?
+ Filtruj audio
+
+
+
+
+ Filtruj dźwięk z twojego mikrofonu, by twoi znajomi mogli odebrać lepszą jakość dźwięku.
+
+
+
+
+
+ Ustaw rodzielczość swojej kamery.
+Im większa wartość, tym lepsza jakość obrazu twoi znajomi otrzymają.
+Do lepszej jakości obrazu potrzebne jest jednak lepsze połączenie z internetem.
+Może się zdarzyć, iż twoje połączenie nie jest wystarczająco dobre do wyższej jakości,
+co może spowodować problemy z połączeniami wideo.
+
+
+
Odcień
-
+
Jasność
-
+
Nasycenie
-
+
Kontrast
@@ -138,17 +180,17 @@ Zignorować proxy i połączyć się z Internetem bezpośrednio?
Zaawansowane
-
+
Pełne - bardzo bezpieczne, najwolniejsze (rekomendowane)
-
+
Normalne - prawie tak bezpieczne jak Pełne, około 20% od niego szybsze
-
+
Wyłączone - wyłącza bezpieczeństwo, gdy coś pójdzie źle twoja historia może zostać utracona. Najszybsze (nie rekomendowane)
@@ -162,21 +204,33 @@ Zignorować proxy i połączyć się z Internetem bezpośrednio?
-
-
+
+ describes makeToxPortable checkbox
+ Zamiast domyślnego katalogu użyj obecnego do zapisania ustawień
-
+
+
+ Zrób Tox przenośnym
+
+
+
+
+ better translation?
+ <html><head/><body><p><span style=" font-weight:600; color:#ff0000;">UWAGA</span></p><p><span style=" color:#ff0000;">O ile nie wiesz </span><span style=" font-weight:600; color:#ff0000;">naprawdę</span><span style=" color:#ff0000;"> co robisz, proszę, </span><span style=" font-weight:600; color:#ff0000;">nie</span><span style=" color:#ff0000;"> zmieniaj tutaj niczego. Zmiany tutaj mogą prowadzić do problemów z qToxem, a nawet do utraty twoich danych, eg. historii.</span></p></body></html>
+
+
+
Reset do domyślnych ustawień
-
+
Historia
-
+
better translation?
<html><head/><body><p><a href="http://www.sqlite.org/pragma.html#pragma_synchronous"><span style=" text-decoration: underline; color:#0000ff;">Zsynchronizowany zapis do DB</span></a></p></body></html>
@@ -185,68 +239,82 @@ Zignorować proxy i połączyć się z Internetem bezpośrednio?
ChatForm
-
+
Wczytaj historię...
-
+
Wyślij plik
-
+
+
better translation?
Nie otwarto pliku
-
+
+
qTox nie był w stanie otworzyć %1
-
+
+
Zły pomysł
-
+
+
Nie można przesłać tego pliku!
-
+
%1 dzwoni
-
+
?
Nieodebrana rozmowa od %1
-
+
at least gender neutral...
Dzwonisz do %1
-
+
Połączenie zostało odrzucone
-
+
+
+ Nie udało się wysłać pliku "%1"
+
+
+
Rozmowa z %1 została zakończona. %2
-
+
Czas trwania rozmowy:
+
+
+
+ pisze...
+
ChatTextEdit
@@ -259,108 +327,108 @@ Zignorować proxy i połączyć się z Internetem bezpośrednio?
Core
-
+
better translation?
Toxuję na qTox
-
+
Użytkownik qToxa
-
+
Znajomy jest już dodany
-
+
Błąd szyfrowania
-
+
better translation?
Plik .tox jest zaszyfrowany, lecz szyfrowanie nie zostało sprawdzone. Kontynuowanie.
-
+
Hasło odszyfrowujące plik danych Tox
-
-
-
+
+
+
better translation?
Błąd hasła
-
-
+
+
Nie udało się ustawić hasła.
Puste hasło.
-
+
Spróbuj ponownie
-
+
Zmień profil
-
+
Zainicjuj ponownie obecny profil
-
+
Podano złe hasło
-
+
Hasło odszyfrowujące historię
-
+
Zaszyfrowany log
-
+
Twoja historia jest zaszyfrowana innym hasłem
Czy chcesz spróbować z innym hasłem?
-
+
Historia
-
+
Historia będzie wyłączona z powodu złego hasła.
-
+
better translation?
BRAK hasła
-
+
Zostanie zapisane bez szyfrowania!
@@ -413,34 +481,34 @@ Czy chcesz spróbować z innym hasłem?
FriendRequestDialog
-
+
Title of the window to aceept/deny a friend request
Prośba o dodanie do kontaktów
-
+
Ktoś chce zostać Twoim znajomym
-
+
ID użytkownika:
-
+
Treść zapytania:
-
+
Accept a friend request
Zaakceptuj
-
+
Reject a friend request
Odrzuć
@@ -505,26 +573,26 @@ Alias:
Główne
-
-
+
+
Brak
-
+
popup title
better translation?
Wybierz domyślną ścieżkę dla plików
-
+
popup title
Aktywna rozmowa
-
+
popup text
Nie możesz się rozłączyć w trakcie rozmowy!
@@ -544,191 +612,301 @@ Alias:
Zmiana języka może wymagać restart aplikacji.
-
-
- describes makeToxPortable checkbox
- Zamiast domyślnego katalogu użyj obecnego do zapisania ustawień
+
+
+ Język:
-
-
- Zrób Tox przenośnym
+
+
+ better translation? it /could/ be translated as "Zasobnik systemowy", but I personally dislike that translation, so…
+ Tray systemowy
-
+
+
+ toolTip for light icon setting
+ better translation?
+ Użyj jasnej ikony w trayu.
+
+
+
Uruchamiaj w trayu
-
+
+
+ toolTip for Start in tray setting
+ qTox będzię się uruchamiał zminimalizowany w trayu.
+
+
+
Zamykaj do traya
-
+
+
+ toolTip for close to tray setting
+ Po naciśnięciu zakończ (X) qTox zminimalizuje się do traya,
+zamias zakończyć swe działanie.
+
+
+
Minimalizuj do traya
-
+
+
+ toolTip for minimize to tray setting
+ better translation?
+ Po naciścięciu minimalizuj (_) qTox zminimalizuje się to traya,
+zamiast do paska zadań.
+
+
+
+
+ Sprawdzaj aktualizacje przy starcie
+
+
+
+
+ Zapisz do:
+
+
+
+
+
+ Ustaw gdzie pliki będą zapisywane.
+
+
+
+
+ Automatycznie nieobecny/a po (0 by wyłączyć):
+
+
+
+
+ Czat
+
+
+
+
+ toolTip for Group chat always notify
+ Zawsze powiadamiaj o nowych wiadomościach w czacie grupowym.
+
+
+
+
+ Zawsze powiadamiaj o czacie grupowym
+
+
+
Pokazuj zmiany statusów
-
-
- Podane w minutach
+
+
+ toolTip for Focus window setting
+ better translation?
+ Przywołaj qTox gdy otrzyma się nową wiadomość.
-
+
+
+ Typ proxy:
+
+
+
+
+ Text on proxy addr label
+ Adres:
+
+
+
Ustaw na 0 by wyłączyć
-
+
+
+ Twój status zmieni się na nieobecny/a po ustawionym okresie braku aktywności.
+
+
+
+
+ Przy nowej wiadomości:
+
+
+
+
+ tooltip for Show window setting
+ Pokaż okno qToxa gdy otrzymasz nową wiadomość.
+
+
+
+
+ Pokaż okno
+
+
+
+
+ better translation?
+ Przywołaj qTox
+
+
+
+
+ toolTip for Faux offline messaging setting
+ Wiadomości które chcesz wysłać do znajomych, którzy nie są online,
+zostaną wysłane gdy znajomi pokażą się online dla ciebie.
+
+
+
+
+ toolTip for compact layout setting
+ Twoja lista znajomych zostanie pokazana w trybie kompaktowym.
+Potrzebny restart qToxa.
+
+
+
+
+ Kompaktowa lista kontaktów
+
+
+
+
+ Text on smiley pack label
+ Paczka Uśmiechów:
+
+
+
+
+ Rozmiar emotikonów:
+
+
+
+
+ Styl:
+
+
+
+
+ Kolor motywu:
+
+
+
+
+ Format czasu:
+
+
+
force tcp checkbox tooltip
Wyłączenie pozwala np. na toxowanie przez Tora. Niestety obciąża to sieć Tox, więc używaj tylko w razie potrzeby.
-
+
Text on checkbox to disable UDP
Używaj UDP (zalecane)
-
+
+
+ Brak
+
+
+
+
+ SOCKS5
+
+
+
+
+ HTTP
+
+
+
reconnect button
Połącz ponownie
-
+
min
-
-
- Tłumaczenie
-
-
-
+
better translation?
Pokaż ikonę w trayu
-
-
- Sprawdzaj czy są dostępne aktualizacje przy uruchomieniu (niestabilne)
+
+
+ Jasna ikona
-
-
- better translation?
- Przywołaj qTox gdy otrzyma się nową wiadomość
-
-
-
+
better translation?
Faux wiadomości offline
-
-
- Automatycznie nieobecny/a po (0 by wyłączyć)
-
-
-
+
autoaccept cb tooltip
better translation?
Możesz to ustawić dla każdego znajomego klikając nań prawym.
-
+
Automatycznie akceptuj pliki
-
-
- Zapisz pliki w
-
-
-
+
-
+
Motyw
-
+
better translation?
Używaj emotikony
-
-
- Text on smiley pack label
- Paczka Uśmiechów
-
-
-
-
- Styl
-
-
-
-
- Kolor motywu
-
-
-
-
- better translation?
- Rozmiar emotikonów
-
-
-
+
px
-
-
- Format czasu
-
-
-
+
Ustawienia połączenia
-
+
Text on a checkbox to enable IPv6
Używaj IPv6 (zalecane)
-
-
- Używaj proxy (SOCKS5)
-
-
-
-
- Text on proxy addr label
- Adres
-
-
-
+
Text on proxy port label
Port
@@ -737,55 +915,55 @@ Alias:
GenericChatForm
-
+
Wyślij wiadomość
-
+
Uśmiechy
-
+
Wyślij plik(i)
-
+
better translation?
Rozmowa audio: Czerwone oznacza aktywną rozmowę
-
+
better translation?
Rozmowa wideo: Czerwone oznacza aktywną rozmowę
-
+
Włącz/Wyłącz dźwięk: Czerwony - wyłączony
-
+
Włącz/Wyłącz mikrofon: Czerwony - wyłączony
-
-
+
+
Zapisz historię rozmowy
-
+
Wyczyść wyświetlane wiadomości
-
+
Wyczyszczono
@@ -851,124 +1029,126 @@ Nazwa:
Tożsamość
-
+
popup title
Rozmowa w trakcie
-
+
popup text
Nie można zmienić profilu podczas aktywnego połączenia!
-
+
renaming a profile
Zmień nazwę "%1"
-
+
rename confirm title
Profil już istnieje
-
+
rename confirm text
Profil pod nazwą "%1" już istnieje. Czy chcesz go usunąć?
-
+
save dialog title
Eksportuj profil
-
+
save dialog filter
Plik zapisu Tox (*.tox)
-
+
Nie udało się usunąć pliku
-
+
better translation?
Nie udało się usunąć wybranego pliku do nadpisania.
-
+
Nie udało się skopiować pliku
-
+
Nie udało się zapisać do wybranego pliku.
-
+
current profile deletion warning title
Profil obecnie załadowany
-
+
current profile deletion warning text
Ten profil jest obecnie w użyciu. Proszę załaduj inny profil przed usunięciem tego.
-
+
deletion confirmation title
Usuwanie profilu!
-
-
+
+
deletion confirmation text
- Czy na pewno chcesz usunąć ten profil?
+ Czy na pewno chcesz usunąć ten profil?
+Wszystkie powiązane dane i historia także zostaną usunięte.
-
+
import dialog title
Importuj profil
-
+
import dialog filter
Plik zapisu Tox (*.tox)
-
+
popup title
Zignorowano niepoprawny plik profilu
-
+
popup text
Ostrzeżenie: Wybrano plik który nie jest plikiem zapisu Tox; zignorowano.
-
+
import confirm title
Profil już istnieje
-
+
import confirm text
Profil pod nazwą "%1" już istnieje. Czy chcesz go usunąć?
@@ -997,65 +1177,105 @@ Nazwa:
Tox ID
-
+
+
+ Tox ID tooltip
+ Ta gromada znaków mówi innym klientom Tox jak się z tobą skontaktować.
+Podziel się tym ze znajomymi by się komunikować.
+
+
+
Twój Tox ID (kliknij by skopiować)
-
+
Profile
-
+
Dostępne profile:
-
-
-
- tooltip
- Zmiana profilu w czasie rozmowy jest wyłączona
+
+
+ toolTip for currently set profile
+ Obecnie wybrany profil.
-
+
+
+ tooltip for loading profile button
+ better translation?
+ Załaduj wybrany profil i przełącz się nań.
+
+
+
load profile button
Wczytaj
-
+
rename profile button
Zmień nazwę
-
+
+
+ tooltip for renaming profile button
+ Zmień nazwę wybranego profilu.
+
+
+
export profile button
Eksportuj
-
+
+
+ tooltip for profile exporting button
+ Pozwala na wyeksportowanie twojego profilu Tox do pliku.
+Profil nie zawiera twojej historii.
+
+
+
+
+ delete profile button tooltip
+ Usuń wybrany profil.
+
+
+
delete profile button
Usuń
-
-
- delete profile button tooltip
- Użyteczne by pozostać bezpiecznym na publicznych komputerach
-
-
-
+
import profile button
Importuj profil
-
+
+
+ tooltip for importing profile button
+ Importuj profil Tox z pliku .tox .
+
+
+
+
+ tooltip for creating new Tox ID button
+ Utwórz nowy Tox ID i przełącz się nań.
+
+
+
new profile button
Nowy Tox ID
@@ -1156,44 +1376,72 @@ Czy chcesz usunąć stary plik historii?
PrivacySettings
+
+
+
+ tooltip for typing notifications setting
+ Twoi znajomi będą w stanie zobaczyć kiedy do nich piszesz.
+
-
+
better translation?
Pokazuj gdy tekst jest pisany
-
+
+
+ toolTip for Keep History setting
+ better translation?
+ Zachowanie historii jest wciąż w trakcie rozwoju.
+Możlie, iż format zapisu zostanie zmieniony, co może skutkować utratą danych.
+
+
+
Zachowaj historię (niestabilne)
-
+
Szyfrowanie
-
+
Zaszyfruj plik danych Tox
-
+
Zaszyfruj historię
-
+
Nospam
-
+
+
+ toolTip for nospam
+ Nospam jest częścią twojego Tox ID.
+Z jego pomocą możesz zmienić swój Tox ID gdy poczujesz,
+iż otrzymujesz za dużo spamujących zapytań o dodanie do znajomych.
+Po zmianie nospamu twoi obecni znajomi wciąż będą się w stanie z tobą rozmawiać,
+ale nowi będą musieli znać twój nowy Tox ID by móc cię dodać.
+
+
+
-
+
Wygeneruj losowy nospam
@@ -1242,13 +1490,13 @@ Czy chcesz usunąć stary plik historii?
Może Tox ze mną?
-
+
The title of a message box
Aktualizacja
-
+
Aktualizacja jest dostępna, czy chcesz ją teraz pobrać?
@@ -1295,6 +1543,12 @@ Zostanie zainstalowana po restarcie qToxa.
Fioletowy
+
+
+
+ better translation?
+ Rozmowa przychodząca...
+
SetPasswordDialog
@@ -1364,6 +1618,14 @@ Zostanie zainstalowana po restarcie qToxa.
Error with the DNS
DNS nie zawiera poprawnego Tox ID
+
+
+
+
+ Wygląda na to, że qTox musi użyć stary protokół tox1.
+Niestety tox1 nie jest bezpieczny. Czy ma być użyty pomimo tego?
+
ToxURIDialog
@@ -1404,160 +1666,155 @@ Zostanie zainstalowana po restarcie qToxa.
Widget
-
+
Online
-
+
Nieobecny/a
-
+
Zajęty/a
-
+
&Wyjdź
-
-
- Zmień status na:
-
-
-
+
Button to set your status to 'Online'
Online
-
+
Button to set your status to 'Away'
Nieobecny/a
-
+
Button to set your status to 'Busy'
Zajęty/a
-
+
Wybierz profil
-
+
Proszę wybierz która tożsamość ma być użyta
-
+
Wybierz obrazek profilu
-
-
-
+
+
+
Błąd
-
+
Nie można otworzyć tego pliku
-
+
Nie można odczytać tego obrazka
-
+
Ten obrazek jest zbyt wielki
-
+
Nie udało się uruchomić Toxcore, aplikacja zamknie się po zamknięciu tej wiadomości.
-
+
popup text
Nie udało się uruchomić toxcore z twoimi ustawieniami proxy. qTox nie może działać, proszę zmodyfikuj ustawienia i zrestartuj.
-
+
Dodaj znajomych
-
+
Transfery plików
-
+
Ustawienia
-
+
better translation?
- Nie udało się dodać do znajomych
+ Nie udało się dodać do znajomych
-
+
contact status
nieobecna/y
-
+
contact status
zajęta/y
-
+
contact status
offline
-
+
contact status
online
-
+
e.g. "Dubslow is now online"
%1 jest teraz %2
-
+
Placeholder when we don't know someone's name in a group chat
<Nieznany/a>
-
+
%1 ustawił(a) nazwę na %2
-
+
Nie udało się wysłać wiadmości
diff --git a/ui/acceptCall/acceptCall.png b/ui/acceptCall/acceptCall.png
new file mode 100644
index 000000000..c892aba9b
Binary files /dev/null and b/ui/acceptCall/acceptCall.png differ
diff --git a/ui/chatArea/innerStyle.css b/ui/chatArea/innerStyle.css
index 4c7b95b2c..5639d1af4 100644
--- a/ui/chatArea/innerStyle.css
+++ b/ui/chatArea/innerStyle.css
@@ -30,3 +30,8 @@ div.alert_name {
background-color: @orange;
font: @bigBold;
}
+
+a {
+ color: blue;
+}
+
diff --git a/ui/chatroomWidgets/genericChatroomWidget.css b/ui/chatroomWidgets/genericChatroomWidget.css
index c83bb9958..09feb23c1 100644
--- a/ui/chatroomWidgets/genericChatroomWidget.css
+++ b/ui/chatroomWidgets/genericChatroomWidget.css
@@ -1,5 +1,5 @@
-GenericChatroomWidget
-{
+GenericChatroomWidget
+{
background-color: @themeMedium;
}
@@ -8,31 +8,55 @@ GenericChatroomWidget[active="true"]
background-color: @white;
}
-GenericChatroomWidget[active="false"]:hover
-{
- background-color: @themeLight;
-}
+GenericChatroomWidget[active="false"]:hover
+{
+ background-color: @themeLight;
+}
-GenericChatroomWidget[active="true"] > QLabel#status
+GenericChatroomWidget[active="true"][compact="true"] > QLabel#status
+{
+ font: @small;
+ color: @mediumGrey;
+}
+
+GenericChatroomWidget[active="false"][compact="true"] > QLabel#status
+{
+ font: @small;
+ color: @lightGrey;
+}
+
+GenericChatroomWidget[active="true"][compact="true"] > QLabel#name
+{
+ font: @medium;
+ color: @darkGrey;
+}
+
+GenericChatroomWidget[active="false"][compact="true"] > QLabel#name
+{
+ font: @medium;
+ color: @white;
+}
+
+GenericChatroomWidget[active="true"][compact="false"] > QLabel#status
{
font: @medium;
color: @mediumGrey;
}
-GenericChatroomWidget[active="false"] > QLabel#status
+GenericChatroomWidget[active="false"][compact="false"] > QLabel#status
{
font: @medium;
color: @lightGrey;
}
-GenericChatroomWidget[active="true"] > QLabel#name
+GenericChatroomWidget[active="true"][compact="false"] > QLabel#name
{
font: @big;
color: @darkGrey;
}
-GenericChatroomWidget[active="false"] > QLabel#name
+GenericChatroomWidget[active="false"][compact="false"] > QLabel#name
{
font: @big;
color: @white;
-}
\ No newline at end of file
+}
diff --git a/ui/micButton/micButton.css b/ui/micButton/micButton.css
index ec784ae7a..df03739ee 100644
--- a/ui/micButton/micButton.css
+++ b/ui/micButton/micButton.css
@@ -4,8 +4,8 @@ QPushButton#green
background-image: url(":/ui/micButton/micButton.png");
background-repeat: none;
border: none;
- width: 25px;
- height: 20px;
+ width: 22px;
+ height: 18px;
}
QPushButton#green:hover
@@ -19,8 +19,8 @@ QPushButton#red
background-image: url(":/ui/micButton/micButtonPressed.png");
background-repeat: none;
border: none;
- width: 25px;
- height: 20px;
+ width: 22px;
+ height: 18px;
}
QPushButton#grey
@@ -29,8 +29,8 @@ QPushButton#grey
background-image: url(":/ui/micButton/micButtonDisabled.png");
background-repeat: none;
border: none;
- width: 25px;
- height: 20px;
+ width: 22px;
+ height: 18px;
}
QPushButton:focus {
diff --git a/ui/rejectCall/rejectCall.png b/ui/rejectCall/rejectCall.png
new file mode 100644
index 000000000..a0480be5c
Binary files /dev/null and b/ui/rejectCall/rejectCall.png differ
diff --git a/ui/settings/mainHead.css b/ui/settings/mainHead.css
index a393850f4..1f883175e 100644
--- a/ui/settings/mainHead.css
+++ b/ui/settings/mainHead.css
@@ -1,4 +1,4 @@
-QWidget
+QWidget .QLabel, QWidget .QLineEdit
{
color: black;
background: white;
diff --git a/ui/volButton/volButton.css b/ui/volButton/volButton.css
index 8210f4819..2d3b33546 100644
--- a/ui/volButton/volButton.css
+++ b/ui/volButton/volButton.css
@@ -4,7 +4,7 @@ QPushButton#green
background-image: url(":/ui/volButton/volButton.png");
background-repeat: none;
border: none;
- width: 25px;
+ width: 22px;
height: 18px;
}
@@ -19,7 +19,17 @@ QPushButton#red
background-image: url(":/ui/volButton/volButtonPressed.png");
background-repeat: none;
border: none;
- width: 25px;
+ width: 22px;
+ height: 18px;
+}
+
+QPushButton#grey
+{
+ background-color: transparent;
+ background-image: url(":/ui/volButton/volButtonDisabled.png");
+ background-repeat: none;
+ border: none;
+ width: 22px;
height: 18px;
}
diff --git a/ui/volButton/volButtonDisabled.png b/ui/volButton/volButtonDisabled.png
new file mode 100644
index 000000000..78862daab
Binary files /dev/null and b/ui/volButton/volButtonDisabled.png differ
diff --git a/updater/widget.cpp b/updater/widget.cpp
index 940af6c33..678c6a770 100644
--- a/updater/widget.cpp
+++ b/updater/widget.cpp
@@ -58,6 +58,7 @@ Widget::~Widget()
void Widget::setProgress(int value)
{
ui->progress->setValue(value);
+ ui->progress->repaint();
qApp->processEvents();
}
@@ -126,7 +127,7 @@ void Widget::update()
setProgress(5);
/// 2. Check the update (5-50%)
- float checkProgressStep = 45/diff.size();
+ float checkProgressStep = 45.0/(float)diff.size();
float checkProgress = 5;
for (UpdateFileMeta fileMeta : diff)
{
@@ -152,21 +153,23 @@ void Widget::update()
setProgress(50);
/// 3. Install the update (50-95%)
- float installProgressStep = 45/diff.size();
+ float installProgressStep = 45.0/(float)diff.size();
float installProgress = 50;
for (UpdateFileMeta fileMeta : diff)
{
// Backup old files
if (QFile(fileMeta.installpath).exists())
{
+ QFile(fileMeta.installpath+".bak").remove();
QFile(fileMeta.installpath).rename(fileMeta.installpath+".bak");
backups.append(fileMeta.installpath);
}
// Install new ones
+ QDir().mkpath(QFileInfo(fileMeta.installpath).absolutePath());
QFile fileFile(updateDirStr+fileMeta.installpath);
if (!fileFile.copy(fileMeta.installpath))
- fatalError(tr("Unable to copy the update's files."));
+ fatalError(tr("Unable to copy the update's files from ")+(updateDirStr+fileMeta.installpath)+" to "+fileMeta.installpath);
installProgress += installProgressStep;
setProgress(installProgress);
}
diff --git a/windows/bootstrap.sh b/windows/bootstrap.sh
new file mode 100644
index 000000000..f67effa12
--- /dev/null
+++ b/windows/bootstrap.sh
@@ -0,0 +1,109 @@
+#!/bin/sh
+QTOX_DIR=`pwd`/..
+
+if [ -d $QTOX_DIR/libs ]; then
+ echo "Remove ./libs and redownload/recompile dependencies?"
+ read -p "m/a/N (missing/all/no): " yn
+ yn=$(echo $yn | tr "[:upper:]" "[:lower:]")
+ if [ "$yn" == "a" ]; then
+ rm -rf $QTOX_DIR/libs
+ elif [ "$yn" == "n" ]; then
+ exit -1
+ elif [ "$yn" != "m" ]; then
+ exit -1
+ fi
+fi
+
+mkdir -p $QTOX_DIR/libs
+cd $QTOX_DIR/libs
+
+
+## toxcore
+if [ ! -f "libtoxcore-win32-i686.zip" ]; then
+ wget --no-check-certificate http://jenkins.libtoxcore.so/job/libtoxcore-win32-i686/lastSuccessfulBuild/artifact/libtoxcore-win32-i686.zip
+ rm -rf include/tox
+fi
+
+if [ ! -d "include/tox" ]; then
+ $QTOX_DIR/tools/unzip -o libtoxcore-win32-i686.zip -d ./
+fi
+
+## filter_audio
+if [ ! -f "bin/libfilteraudio.dll" ]; then
+ $QTOX_DIR/install_libfilteraudio.sh $QTOX_DIR/libs/filter_audio $QTOX_DIR/libs
+fi
+
+
+## OpenAL
+if [ ! -f "openal-soft-1.16.0.tar.bz2" ]; then
+ wget http://kcat.strangesoft.net/openal-releases/openal-soft-1.16.0.tar.bz2
+ rm -rf openal-soft-1.16.0
+fi
+
+if [ ! -d "openal-soft-1.16.0" ]; then
+ tar -xvf openal-soft-1.16.0.tar.bz2
+ rm bin/OpenAL32.dll
+fi
+
+if [ ! -f "bin/OpenAL32.dll" ]; then
+ pushd openal-soft-1.16.0/build
+ cmake -G "MSYS Makefiles" -DQT_QMAKE_EXECUTABLE=NOTFOUND -DCMAKE_BUILD_TYPE=Release -DALSOFT_REQUIRE_DSOUND=NO -DCMAKE_INSTALL_PREFIX=$QTOX_DIR/libs ..
+ make
+ make install
+ popd
+fi
+
+## opencv
+if [ ! -f "opencv-2.4.9.tar.gz" ]; then
+ wget --no-check-certificate https://github.com/Itseez/opencv/archive/2.4.9.tar.gz -O opencv-2.4.9.tar.gz
+ rm -rf opencv-2.4.9
+fi
+
+if [ ! -d "opencv-2.4.9" ]; then
+ tar -xvf opencv-2.4.9.tar.gz
+ rm bin/libopencv_core249.dll
+fi
+
+if [ ! -f "bin/libopencv_core249.dll" ]; then
+ mkdir opencv-2.4.9/build
+ pushd opencv-2.4.9/build
+ cmake -G "MSYS Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=$QTOX_DIR/libs \
+ -DBUILD_opencv_apps=NO \
+ -DBUILD_opencv_calib3d=NO \
+ -DBUILD_opencv_contrib=NO \
+ -DBUILD_opencv_core=YES \
+ -DBUILD_opencv_features2d=NO \
+ -DBUILD_opencv_flann=NO \
+ -DBUILD_opencv_gpu=NO \
+ -DBUILD_opencv_highgui=YES \
+ -DBUILD_opencv_imgproc=YES \
+ -DBUILD_opencv_legacy=NO \
+ -DBUILD_opencv_ml=NO \
+ -DBUILD_opencv_nonfree=NO \
+ -DBUILD_opencv_objdetect=NO \
+ -DBUILD_opencv_ocl=NO \
+ -DBUILD_opencv_photo=NO \
+ -DBUILD_opencv_stiching=NO \
+ -DBUILD_opencv_superres=NO \
+ -DBUILD_opencv_ts=NO \
+ -DBUILD_opencv_video=NO \
+ -DBUILD_opencv_videostab=NO \
+ -DBUILD_opencv_world=NO \
+ -DWITH_QT=NO \
+ -DBUILD_EXAMPLES=NO \
+ ..
+
+ make
+ make install
+ for arch in x86 x64
+ do
+ if [ -d $QTOX_DIR/libs/$arch/mingw ]; then
+ mv $QTOX_DIR/libs/$arch/mingw/bin/* $QTOX_DIR/libs/bin/
+ mv $QTOX_DIR/libs/$arch/mingw/lib/* $QTOX_DIR/libs/lib/
+ rm -rf $QTOX_DIR/libs/$arch
+ fi
+ done
+ popd
+fi
+
+echo **Done**
diff --git a/windows/qtox64.nsi b/windows/qtox64.nsi
new file mode 100644
index 000000000..273e833f2
--- /dev/null
+++ b/windows/qtox64.nsi
@@ -0,0 +1,357 @@
+###################
+#META
+###################
+!define APP_NAME "qTox"
+!define COMP_NAME "Tox"
+!define WEB_SITE "https://github.com/tux3/qTox"
+!define VERSION "1.0.0.0"
+!define DESCRIPTION "qTox Installer"
+!define COPYRIGHT "The Tox Project"
+!define INSTALLER_NAME "setup-qtox.exe"
+!define MAIN_APP_EXE "bin\qtox.exe"
+!define INSTALL_TYPE "SetShellVarContext current"
+!define REG_ROOT "HKCU"
+!define REG_APP_PATH "Software\Microsoft\Windows\CurrentVersion\App Paths\qtox.exe"
+!define UNINSTALL_PATH "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}"
+!define REG_START_MENU "Start Menu Folder"
+var SM_Folder
+
+Name "${APP_NAME}"
+Caption "${APP_NAME}"
+OutFile "${INSTALLER_NAME}"
+BrandingText "${APP_NAME}"
+InstallDir "$PROGRAMFILES64\${APP_NAME}"
+SetCompressor /SOLID lzma
+
+VIProductVersion "${VERSION}"
+VIAddVersionKey "ProductName" "${APP_NAME}"
+VIAddVersionKey "CompanyName" "${COMP_NAME}"
+VIAddVersionKey "LegalCopyright" "${COPYRIGHT}"
+VIAddVersionKey "FileDescription" "${DESCRIPTION}"
+VIAddVersionKey "FileVersion" "${VERSION}"
+
+##############
+#UNINSTALL LOG
+##############
+;AddItem macro
+ !macro AddItem Path
+ FileWrite $UninstLog "${Path}$\r$\n"
+ !macroend
+
+;File macro
+ !macro File FileName
+ IfFileExists "$OUTDIR\${FileName}" +2
+ FileWrite $UninstLog "$OUTDIR\${FileName}$\r$\n"
+ File "${FileName}"
+ !macroend
+
+;CreateShortcut macro
+ !macro CreateShortcut FilePath FilePointer Pamameters Icon IconIndex
+ FileWrite $UninstLog "${FilePath}$\r$\n"
+ CreateShortcut "${FilePath}" "${FilePointer}" "${Pamameters}" "${Icon}" "${IconIndex}"
+ !macroend
+
+;Copy files macro
+ !macro CopyFiles SourcePath DestPath
+ IfFileExists "${DestPath}" +2
+ FileWrite $UninstLog "${DestPath}$\r$\n"
+ CopyFiles "${SourcePath}" "${DestPath}"
+ !macroend
+
+;Rename macro
+ !macro Rename SourcePath DestPath
+ IfFileExists "${DestPath}" +2
+ FileWrite $UninstLog "${DestPath}$\r$\n"
+ Rename "${SourcePath}" "${DestPath}"
+ !macroend
+
+;CreateDirectory macro
+ !macro CreateDirectory Path
+ CreateDirectory "${Path}"
+ FileWrite $UninstLog "${Path}$\r$\n"
+ !macroend
+
+;SetOutPath macro
+ !macro SetOutPath Path
+ SetOutPath "${Path}"
+ FileWrite $UninstLog "${Path}$\r$\n"
+ !macroend
+
+;WriteUninstaller macro
+ !macro WriteUninstaller Path
+ WriteUninstaller "${Path}"
+ FileWrite $UninstLog "${Path}$\r$\n"
+ !macroend
+
+;WriteIniStr macro
+ !macro WriteIniStr IniFile SectionName EntryName NewValue
+ IfFileExists "${IniFile}" +2
+ FileWrite $UninstLog "${IniFile}$\r$\n"
+ WriteIniStr "${IniFile}" "${SectionName}" "${EntryName}" "${NewValue}"
+ !macroend
+
+;WriteRegStr macro
+ !macro WriteRegStr RegRoot UnInstallPath Key Value
+ FileWrite $UninstLog "${RegRoot} ${UnInstallPath}$\r$\n"
+ WriteRegStr "${RegRoot}" "${UnInstallPath}" "${Key}" "${Value}"
+ !macroend
+
+
+;WriteRegDWORD macro
+ !macro WriteRegDWORD RegRoot UnInstallPath Key Value
+ FileWrite $UninstLog "${RegRoot} ${UnInstallPath}$\r$\n"
+ WriteRegDWORD "${RegRoot}" "${UnInstallPath}" "${Key}" "${Value}"
+ !macroend
+
+;BackupFile macro
+ !macro BackupFile FILE_DIR FILE BACKUP_TO
+ IfFileExists "${BACKUP_TO}\*.*" +2
+ CreateDirectory "${BACKUP_TO}"
+ IfFileExists "${FILE_DIR}\${FILE}" 0 +2
+ Rename "${FILE_DIR}\${FILE}" "${BACKUP_TO}\${FILE}"
+ !macroend
+
+;RestoreFile macro
+ !macro RestoreFile BUP_DIR FILE RESTORE_TO
+ IfFileExists "${BUP_DIR}\${FILE}" 0 +2
+ Rename "${BUP_DIR}\${FILE}" "${RESTORE_TO}\${FILE}"
+ !macroend
+
+;BackupFiles macro
+ !macro BackupFiles FILE_DIR FILE BACKUP_TO
+ IfFileExists "${BACKUP_TO}\*.*" +2
+ CreateDirectory "22222"
+ IfFileExists "${FILE_DIR}\${FILE}" 0 +7
+ FileWrite $UninstLog "${FILE_DIR}\${FILE}$\r$\n"
+ FileWrite $UninstLog "${BACKUP_TO}\${FILE}$\r$\n"
+ FileWrite $UninstLog "FileBackup$\r$\n"
+ Rename "${FILE_DIR}\${FILE}" "${BACKUP_TO}\${FILE}"
+ SetOutPath "${FILE_DIR}"
+ File "${FILE}" #After the Original file is backed up write the new file.
+ !macroend
+
+;RestoreFiles macro
+ !macro RestoreFiles BUP_FILE RESTORE_FILE
+ IfFileExists "${BUP_FILE}" 0 +2
+ CopyFiles "${BUP_FILE}" "${RESTORE_FILE}"
+ !macroend
+
+###################
+#PREPARE UNINST LOG
+###################
+ ;Set the name of the uninstall log
+ !define UninstLog "uninstall.log"
+ Var UninstLog
+
+ ;Uninstall log file missing.
+ LangString UninstLogMissing ${LANG_ENGLISH} "${UninstLog} not found!$\r$\nUninstallation cannot proceed!"
+
+ ;AddItem macro
+ !define AddItem "!insertmacro AddItem"
+
+ ;BackupFile macro
+ !define BackupFile "!insertmacro BackupFile"
+
+ ;BackupFiles macro
+ !define BackupFiles "!insertmacro BackupFiles"
+
+ ;Copy files macro
+ !define CopyFiles "!insertmacro CopyFiles"
+
+ ;CreateDirectory macro
+ !define CreateDirectory "!insertmacro CreateDirectory"
+
+ ;CreateShortcut macro
+ !define CreateShortcut "!insertmacro CreateShortcut"
+
+ ;File macro
+ !define File "!insertmacro File"
+
+ ;Rename macro
+ !define Rename "!insertmacro Rename"
+
+ ;RestoreFile macro
+ !define RestoreFile "!insertmacro RestoreFile"
+
+ ;RestoreFiles macro
+ !define RestoreFiles "!insertmacro RestoreFiles"
+
+ ;SetOutPath macro
+ !define SetOutPath "!insertmacro SetOutPath"
+
+ ;WriteRegDWORD macro
+ !define WriteRegDWORD "!insertmacro WriteRegDWORD"
+
+ ;WriteRegStr macro
+ !define WriteRegStr "!insertmacro WriteRegStr"
+
+ ;WriteUninstaller macro
+ !define WriteUninstaller "!insertmacro WriteUninstaller"
+
+ Section -openlogfile
+ CreateDirectory "$INSTDIR"
+ IfFileExists "$INSTDIR\${UninstLog}" +3
+ FileOpen $UninstLog "$INSTDIR\${UninstLog}" w
+ Goto +4
+ SetFileAttributes "$INSTDIR\${UninstLog}" NORMAL
+ FileOpen $UninstLog "$INSTDIR\${UninstLog}" a
+ FileSeek $UninstLog 0 END
+ SectionEnd
+
+##############
+#MODERN UI
+##############
+!include "MUI.nsh"
+
+!define MUI_ABORTWARNING
+!define MUI_FINISHPAGE_NOAUTOCLOSE
+!insertmacro MUI_PAGE_WELCOME
+!insertmacro MUI_PAGE_DIRECTORY
+!ifdef REG_START_MENU
+ !define MUI_STARTMENUPAGE_NODISABLE
+ !define MUI_STARTMENUPAGE_DEFAULTFOLDER "qTox"
+ !define MUI_STARTMENUPAGE_REGISTRY_ROOT "${REG_ROOT}"
+ !define MUI_STARTMENUPAGE_REGISTRY_KEY "${UNINSTALL_PATH}"
+ !define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "${REG_START_MENU}"
+ !insertmacro MUI_PAGE_STARTMENU Application $SM_Folder
+!endif
+!insertmacro MUI_PAGE_INSTFILES
+
+Function finishpageaction
+${CreateShortcut} "$DESKTOP\qTox.lnk" "$INSTDIR\${MAIN_APP_EXE}" "" "" ""
+FunctionEnd
+
+!define MUI_FINISHPAGE_SHOWREADME ""
+!define MUI_FINISHPAGE_SHOWREADME_TEXT "Create Desktop Shortcut"
+!define MUI_FINISHPAGE_SHOWREADME_FUNCTION finishpageaction
+
+!define MUI_FINISHPAGE_RUN "$INSTDIR\${MAIN_APP_EXE}"
+!define MUI_FINISHPAGE_LINK "Find qTox on GitHub"
+!define MUI_FINISHPAGE_LINK_LOCATION "https://github.com/tux3/qTox"
+!insertmacro MUI_PAGE_FINISH
+
+!define MUI_UNABORTWARNING
+!define MUI_UNFINISHPAGE_NOAUTOCLOSE
+!insertmacro MUI_UNPAGE_WELCOME
+!insertmacro MUI_UNPAGE_CONFIRM
+!insertmacro MUI_UNPAGE_INSTFILES
+!insertmacro MUI_UNPAGE_FINISH
+
+!insertmacro MUI_LANGUAGE "English"
+
+#################
+#INSTALL
+#################
+Section "Install"
+ # Install files
+ ${SetOutPath} "$INSTDIR"
+ ${WriteUninstaller} "uninstall.exe"
+
+ ${CreateDirectory} "bin"
+ ${SetOutPath} "$INSTDIR\bin"
+ ${File} "qtox\*.*"
+
+ ${CreateDirectory} "imageformats"
+ ${SetOutPath} "$INSTDIR\bin\imageformats"
+ ${File} "qtox\imageformats\*.*"
+ ${SetOutPath} "$INSTDIR\bin"
+
+ ${CreateDirectory} "platforms"
+ ${SetOutPath} "$INSTDIR\bin\platforms"
+ ${File} "qtox\platforms\*.*"
+ ${SetOutPath} "$INSTDIR\bin"
+
+ ${CreateDirectory} "sqldrivers"
+ ${SetOutPath} "$INSTDIR\bin\sqldrivers"
+ ${File} "qtox\sqldrivers\*.*"
+ ${SetOutPath} "$INSTDIR\bin"
+
+ # Create shortcuts
+ ${CreateDirectory} "$SMPROGRAMS\qTox"
+ ${CreateShortCut} "$SMPROGRAMS\qTox\qTox.lnk" "$INSTDIR\${MAIN_APP_EXE}" "" "" ""
+ ${CreateShortCut} "$SMPROGRAMS\qTox\Uninstall qTox.lnk" "$INSTDIR\uninstall.exe" "" "" ""
+
+ # Write setup/app info into the registry
+ ${WriteRegStr} "${REG_ROOT}" "${REG_APP_PATH}" "" "$INSTDIR\${MAIN_APP_EXE}"
+ ${WriteRegStr} "${REG_ROOT}" "${REG_APP_PATH}" "Path" "$INSTDIR\bin\"
+ ${WriteRegStr} ${REG_ROOT} "${UNINSTALL_PATH}" "UninstallString" "$INSTDIR\uninstall.exe"
+
+ # Register the tox: protocol
+ ${WriteRegStr} HKCR "tox" "" "URL:tox Protocol"
+ ${WriteRegStr} HKCR "tox" "URL Protocol" ""
+ ${WriteRegStr} HKCR "tox\shell\open\command" "" "$INSTDIR\${MAIN_APP_EXE} %1"
+
+ # Register the .tox file associations
+ ${WriteRegStr} "HKCR" "Applications\qtox.exe\SupportedTypes" ".tox" ""
+ ${WriteRegStr} HKCR ".tox" "" "toxsave"
+ ${WriteRegStr} HKCR "toxsave" "" "Tox save file"
+ ${WriteRegStr} HKCR "toxsave\DefaultIcon" "" "$INSTDIR\${MAIN_APP_EXE}"
+ ${WriteRegStr} HKCR "toxsave\shell\open\command" "" "$INSTDIR\${MAIN_APP_EXE} %1"
+SectionEnd
+
+
+################
+#UNINSTALL
+################
+Section Uninstall
+ ;If there's no uninstall log, we'll try anyway to clean what we can
+ IfFileExists "$INSTDIR\${UninstLog}" +3
+ Goto noLog
+
+ Push $R0
+ Push $R1
+ Push $R2
+ SetFileAttributes "$INSTDIR\${UninstLog}" NORMAL
+ FileOpen $UninstLog "$INSTDIR\${UninstLog}" r
+ StrCpy $R1 -1
+
+ GetLineCount:
+ ClearErrors
+ FileRead $UninstLog $R0
+ IntOp $R1 $R1 + 1
+ StrCpy $R0 $R0 -2
+ Push $R0
+ IfErrors 0 GetLineCount
+
+ Pop $R0
+
+ LoopRead:
+ StrCmp $R1 0 LoopDone
+ Pop $R0
+
+ IfFileExists "$R0\*.*" 0 +3
+ RMDir $R0 #is dir
+ Goto +9
+ IfFileExists $R0 0 +3
+ Delete $R0 #is file
+ Goto +6
+ StrCmp $R0 "${REG_ROOT} ${REG_APP_PATH}" 0 +3
+ DeleteRegKey ${REG_ROOT} "${REG_APP_PATH}" #is Reg Element
+ Goto +3
+ StrCmp $R0 "${REG_ROOT} ${UNINSTALL_PATH}" 0 +2
+ DeleteRegKey ${REG_ROOT} "${UNINSTALL_PATH}" #is Reg Element
+
+ IntOp $R1 $R1 - 1
+ Goto LoopRead
+ LoopDone:
+ FileClose $UninstLog
+ Delete "$INSTDIR\${UninstLog}"
+ noLog:
+ Delete /REBOOTOK "$INSTDIR\uninstall.exe"
+ RMDir /r /REBOOTOK "$INSTDIR\bin"
+ RMDir /REBOOTOK "$INSTDIR"
+ Pop $R2
+ Pop $R1
+ Pop $R0
+
+ ;Remove start menu entries
+ RMDir /r /REBOOTOK "$SMPROGRAMS\qTox"
+
+ ;Remove registry keys
+ DeleteRegKey ${REG_ROOT} "${REG_APP_PATH}"
+ DeleteRegKey ${REG_ROOT} "${UNINSTALL_PATH}"
+ DeleteRegKey HKCR "Applications\qtox.exe"
+ DeleteRegKey HKCR ".tox"
+ DeleteRegKey HKCR "tox"
+ DeleteRegKey HKCR "toxsave"
+SectionEnd