diff --git a/README.md b/README.md
index 8147def8d..9252e7c42 100644
--- a/README.md
+++ b/README.md
@@ -20,15 +20,15 @@ However, it is not a fork.
This client runs on Windows, Linux and Mac natively.
-You can find the latest versions of qTox here, or from the Tox Project's servers :
+You can find the latest versions of qTox here (Windows and Linux), or from the Tox Project's servers :
-Windows download
-Mac download
-Linux download (click "Last successful artifacts")
+Mac download
+Linux download (click "Last successful artifacts")
Screenshots
Note: The screenshots may not always be up to date, but they should give a good idea of the general look and features
-
+
+
##Documentation:
diff --git a/debian/control b/debian/control
index 1147f4397..6f7c59daa 100644
--- a/debian/control
+++ b/debian/control
@@ -7,7 +7,7 @@ Build-Depends: debhelper (>= 9), cdbs, qt5-qmake, libopenal-dev (>= 1:1.14), lib
Package: qtox
Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, libgcc1 (>= 1:4.1.1), libgl1-mesa-glx | libgl1, libopenal1 (>= 1.14), libopus0 (>= 0.9), libqt5core5a (>= 5.2), libqt5gui5 (>= 5.2), libqt5network5 (>= 5.0), libqt5widgets5 (>= 5.2), libqt5xml5 (>= 5.0), libstdc++6 (>= 4.9), libvpx1 (>= 1.0.0)
+Depends: ${shlibs:Depends}, ${misc:Depends}, libgcc1 (>= 1:4.1.1), libgl1-mesa-glx | libgl1, libopenal1 (>= 1.14), libopus0 (>= 0.9), libqt5core5a (>= 5.2), libqt5gui5 (>= 5.2), libqt5network5 (>= 5.0), libqt5widgets5 (>= 5.2), libqt5xml5 (>= 5.0), libstdc++6 (>= 4.8.2), libvpx1 (>= 1.0.0)
Description: Tox client
qTox is a powerful Tox client that follows the Tox design guidelines.
Tox is a decentralized and encrypted replacement for Skype, supporting
diff --git a/img/icons/qtox.icns b/img/icons/qtox.icns
new file mode 100644
index 000000000..bb96d3ae3
Binary files /dev/null and b/img/icons/qtox.icns differ
diff --git a/qtox.pro b/qtox.pro
index 10a17f2fc..0d0019c91 100644
--- a/qtox.pro
+++ b/qtox.pro
@@ -60,6 +60,7 @@ win32 {
LIBS += -lz -lopengl32 -lole32 -loleaut32 -luuid -lvfw32 -ljpeg -ltiff -lpng -ljasper -lIlmImf -lHalf -lws2_32
} else {
macx {
+ ICON = img/icons/qtox.icns
LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -lsodium -lvpx -framework OpenAL -lopencv_core -lopencv_highgui
} else {
# If we're building a package, static link libtox[core,av] and libsodium, since they are not provided by any package
@@ -68,7 +69,7 @@ win32 {
INSTALLS += target
LIBS += -L$$PWD/libs/lib/ -lopus -lvpx -lopenal -Wl,-Bstatic -ltoxcore -ltoxav -lsodium -lopencv_highgui -lopencv_imgproc -lopencv_core -lz -Wl,-Bdynamic
LIBS += -Wl,-Bstatic -ljpeg -ltiff -lpng -ljasper -lIlmImf -lIlmThread -lIex -ldc1394 -lraw1394 -lHalf -lz -llzma -ljbig
- LIBS += -Wl,-Bdynamic -ltbb -lv4l1 -lv4l2 -lgnutls -lrtmp -lgnutls -lavformat -lavcodec -lavutil -lavfilter -lswscale -lusb-1.0
+ LIBS += -Wl,-Bdynamic -lv4l1 -lv4l2 -lavformat -lavcodec -lavutil -lswscale -lusb-1.0
} else {
LIBS += -L$$PWD/libs/lib/ -ltoxcore -ltoxav -lvpx -lopenal -lopencv_core -lopencv_highgui -lopencv_imgproc
@@ -134,10 +135,12 @@ HEADERS += src/widget/form/addfriendform.h \
src/widget/tool/chatactions/filetransferaction.h \
src/widget/tool/chatactions/systemmessageaction.h \
src/widget/tool/chatactions/actionaction.h \
+ src/widget/tool/chatactions/alertaction.h \
src/widget/maskablepixmapwidget.h \
src/videosource.h \
src/cameraworker.h \
- src/widget/videosurface.h
+ src/widget/videosurface.h \
+ src/widget/form/tabcompleter.h
SOURCES += \
src/widget/form/addfriendform.cpp \
@@ -182,7 +185,9 @@ SOURCES += \
src/widget/tool/chatactions/filetransferaction.cpp \
src/widget/tool/chatactions/systemmessageaction.cpp \
src/widget/tool/chatactions/actionaction.cpp \
+ src/widget/tool/chatactions/alertaction.cpp \
src/widget/maskablepixmapwidget.cpp \
src/cameraworker.cpp \
src/widget/videosurface.cpp \
- src/netvideosource.cpp
+ src/netvideosource.cpp \
+ src/widget/form/tabcompleter.cpp
diff --git a/src/cameraworker.cpp b/src/cameraworker.cpp
index 3a6ef4f2a..b2829c579 100644
--- a/src/cameraworker.cpp
+++ b/src/cameraworker.cpp
@@ -18,6 +18,7 @@
#include
#include
+#include
CameraWorker::CameraWorker(int index)
: clock(nullptr)
@@ -178,6 +179,7 @@ void CameraWorker::setProp(int prop, double val)
double CameraWorker::getProp(int prop)
{
double ret = 0.0;
+ qApp->processEvents();
QMetaObject::invokeMethod(this, "_getProp", Qt::BlockingQueuedConnection, Q_RETURN_ARG(double, ret), Q_ARG(int, prop));
return ret;
diff --git a/src/core.cpp b/src/core.cpp
index 58fd47aff..559139dbf 100644
--- a/src/core.cpp
+++ b/src/core.cpp
@@ -226,6 +226,12 @@ void Core::start()
}
loadPath = "";
}
+ else // new ID
+ {
+ setStatusMessage(tr("Toxing on qTox")); // this also solves the not updating issue
+ setUsername(tr("qTox User"));
+ Widget::getInstance()->onSettingsClicked(); // update ui with new profile (im worried about threading, but it seems to work)
+ }
tox_callback_friend_request(tox, onFriendRequest, this);
tox_callback_friend_message(tox, onFriendMessage, this);
@@ -1187,10 +1193,7 @@ void Core::saveConfiguration(const QString& path)
void Core::switchConfiguration(const QString& profile)
{
if (profile.isEmpty())
- {
- qWarning() << "Core: got null profile to switch to, not switching";
- return;
- }
+ qDebug() << "Core: creating new Id";
else
qDebug() << "Core: switching from" << Settings::getInstance().getCurrentProfile() << "to" << profile;
saveConfiguration();
@@ -1205,8 +1208,11 @@ void Core::switchConfiguration(const QString& profile)
}
emit selfAvatarChanged(QPixmap(":/img/contact_dark.png"));
emit blockingClearContacts(); // we need this to block, but signals are required for thread safety
-
- loadPath = QDir(Settings::getSettingsDirPath()).filePath(profile + TOX_EXT);
+
+ if (profile.isEmpty())
+ loadPath = "";
+ else
+ loadPath = QDir(Settings::getSettingsDirPath()).filePath(profile + TOX_EXT);
Settings::getInstance().setCurrentProfile(profile);
start();
diff --git a/src/filetransferinstance.cpp b/src/filetransferinstance.cpp
index b6534e2ab..16717eb1f 100644
--- a/src/filetransferinstance.cpp
+++ b/src/filetransferinstance.cpp
@@ -46,7 +46,7 @@ FileTransferInstance::FileTransferInstance(ToxFile File)
filenameElided = fm.elidedText(filename, Qt::ElideRight, MAX_CONTENT_WIDTH);
size = getHumanReadableSize(File.filesize);
- contentPrefWidth = std::max(fm.width(filenameElided), fm.width(size));
+ contentPrefWidth = std::max(fm.boundingRect(filenameElided).width(), fm.width(size));
speed = "0B/s";
eta = "00:00";
@@ -209,6 +209,7 @@ bool isFileWritable(QString& path)
void FileTransferInstance::acceptRecvRequest()
{
QString path = Settings::getInstance().getAutoAcceptDir(Core::getInstance()->getFriendAddress(friendId));
+ if (path.isEmpty()) path = Settings::getInstance().getGlobalAutoAcceptDir();
if (!path.isEmpty())
{
QDir dir(path);
diff --git a/src/main.cpp b/src/main.cpp
index c683f462c..0dcc9726c 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -18,7 +18,6 @@
#include "misc/settings.h"
#include
#include
-#include
#include
int main(int argc, char *argv[])
@@ -38,24 +37,6 @@ int main(int argc, char *argv[])
QFontDatabase::addApplicationFont("://DejaVuSans.ttf");
Widget* w = Widget::getInstance();
- if (QSystemTrayIcon::isSystemTrayAvailable() == false)
- {
- qWarning() << "No system tray detected!";
- w->show();
- }
- else
- {
- QSystemTrayIcon *icon = new QSystemTrayIcon(w);
- QObject::connect(icon,
- SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
- w,
- SLOT(onIconClick()));
- icon->setIcon(w->windowIcon());
- icon->show();
- if(Settings::getInstance().getAutostartInTray() == false)
- w->show();
- }
-
int errorcode = a.exec();
diff --git a/src/misc/settings.cpp b/src/misc/settings.cpp
index de84e7a3c..98109a964 100644
--- a/src/misc/settings.cpp
+++ b/src/misc/settings.cpp
@@ -112,6 +112,7 @@ void Settings::load()
translation = s.value("translation", "").toString();
makeToxPortable = s.value("makeToxPortable", false).toBool();
autostartInTray = s.value("autostartInTray", false).toBool();
+ closeToTray = s.value("closeToTray", false).toBool();
forceTCP = s.value("forceTCP", false).toBool();
useProxy = s.value("useProxy", false).toBool();
proxyAddr = s.value("proxyAddr", "").toString();
@@ -137,6 +138,7 @@ void Settings::load()
secondColumnHandlePosFromRight = s.value("secondColumnHandlePosFromRight", 50).toInt();
timestampFormat = s.value("timestampFormat", "hh:mm").toString();
minimizeOnClose = s.value("minimizeOnClose", false).toBool();
+ minimizeToTray = s.value("minimizeToTray", false).toBool();
useNativeStyle = s.value("nativeStyle", false).toBool();
style = s.value("style", "None").toString();
statusChangeNotificationEnabled = s.value("statusChangeNotificationEnabled", false).toBool();
@@ -153,6 +155,7 @@ void Settings::load()
s.endGroup();
s.beginGroup("AutoAccept");
+ globalAutoAcceptDir = s.value("globalAutoAcceptDir", "").toString();
for (auto& key : s.childKeys())
autoAccept[key] = s.value(key).toString();
s.endGroup();
@@ -225,6 +228,7 @@ void Settings::save(QString path)
s.setValue("translation",translation);
s.setValue("makeToxPortable",makeToxPortable);
s.setValue("autostartInTray",autostartInTray);
+ s.setValue("closeToTray", closeToTray);
s.setValue("useProxy", useProxy);
s.setValue("forceTCP", forceTCP);
s.setValue("proxyAddr", proxyAddr);
@@ -250,6 +254,7 @@ void Settings::save(QString path)
s.setValue("secondColumnHandlePosFromRight", secondColumnHandlePosFromRight);
s.setValue("timestampFormat", timestampFormat);
s.setValue("minimizeOnClose", minimizeOnClose);
+ s.setValue("minimizeToTray", minimizeToTray);
s.setValue("nativeStyle", useNativeStyle);
s.setValue("style",style);
s.setValue("statusChangeNotificationEnabled", statusChangeNotificationEnabled);
@@ -266,6 +271,7 @@ void Settings::save(QString path)
s.endGroup();
s.beginGroup("AutoAccept");
+ s.setValue("globalAutoAcceptDir", globalAutoAcceptDir);
for (auto& id : autoAccept.keys())
s.setValue(id, autoAccept.value(id));
s.endGroup();
@@ -390,6 +396,27 @@ void Settings::setAutostartInTray(bool newValue)
autostartInTray = newValue;
}
+bool Settings::getCloseToTray() const
+{
+ return closeToTray;
+}
+
+void Settings::setCloseToTray(bool newValue)
+{
+ closeToTray = newValue;
+}
+
+bool Settings::getMinimizeToTray() const
+{
+ return minimizeToTray;
+}
+
+
+void Settings::setMinimizeToTray(bool newValue)
+{
+ minimizeToTray = newValue;
+}
+
bool Settings::getStatusChangeNotificationEnabled() const
{
return statusChangeNotificationEnabled;
@@ -504,6 +531,16 @@ void Settings::setAutoAcceptDir(const QString& id, const QString& dir)
autoAccept[id.left(TOX_ID_PUBLIC_KEY_LENGTH)] = dir;
}
+QString Settings::getGlobalAutoAcceptDir() const
+{
+ return globalAutoAcceptDir;
+}
+
+void Settings::setGlobalAutoAcceptDir(const QString& newValue)
+{
+ globalAutoAcceptDir = newValue;
+}
+
void Settings::setWidgetData(const QString& uniqueName, const QByteArray& data)
{
widgetSettings[uniqueName] = data;
diff --git a/src/misc/settings.h b/src/misc/settings.h
index 5d4363f31..5c3e6bc17 100644
--- a/src/misc/settings.h
+++ b/src/misc/settings.h
@@ -52,6 +52,12 @@ public:
bool getAutostartInTray() const;
void setAutostartInTray(bool newValue);
+ bool getCloseToTray() const;
+ void setCloseToTray(bool newValue);
+
+ bool getMinimizeToTray() const;
+ void setMinimizeToTray(bool newValue);
+
QString getStyle() const;
void setStyle(const QString& newValue);
@@ -128,6 +134,9 @@ public:
QString getAutoAcceptDir(const QString& id) const;
void setAutoAcceptDir(const QString&id, const QString& dir);
+ QString getGlobalAutoAcceptDir() const;
+ void setGlobalAutoAcceptDir(const QString& dir);
+
// ChatView
int getFirstColumnHandlePos() const;
void setFirstColumnHandlePos(const int pos);
@@ -185,6 +194,8 @@ private:
QString translation;
static bool makeToxPortable;
bool autostartInTray;
+ bool closeToTray;
+ bool minimizeToTray;
bool forceTCP;
@@ -201,6 +212,7 @@ private:
QHash widgetSettings;
QHash autoAccept;
+ QString globalAutoAcceptDir;
// GUI
bool enableSmoothAnimation;
diff --git a/src/misc/style.cpp b/src/misc/style.cpp
index 70100270f..e9dec32e3 100644
--- a/src/misc/style.cpp
+++ b/src/misc/style.cpp
@@ -70,6 +70,7 @@ QColor Style::getColor(Style::ColorPalette entry)
QColor("#414141").lighter(120),
QColor("#d1d1d1"),
QColor("#ffffff"),
+ QColor("#ff7700"),
};
return palette[entry];
@@ -108,6 +109,7 @@ QString Style::resolve(QString qss)
{"@mediumGreyLight", getColor(MediumGreyLight).name()},
{"@lightGrey", getColor(LightGrey).name()},
{"@white", getColor(White).name()},
+ {"@orange", getColor(Orange).name()},
// fonts
{"@extraBig", qssifyFont(getFont(ExtraBig))},
diff --git a/src/misc/style.h b/src/misc/style.h
index a07064e04..e818b2ddb 100644
--- a/src/misc/style.h
+++ b/src/misc/style.h
@@ -37,6 +37,7 @@ public:
MediumGreyLight,
LightGrey,
White,
+ Orange,
};
enum Font
diff --git a/src/widget/form/addfriendform.cpp b/src/widget/form/addfriendform.cpp
index b31a7818e..9e1243eff 100644
--- a/src/widget/form/addfriendform.cpp
+++ b/src/widget/form/addfriendform.cpp
@@ -154,4 +154,6 @@ void AddFriendForm::handleDnsLookup()
// finally we got it
emit friendRequested(friendAdress, getMessage());
+ this->toxId.setText("");
+ this->message.setText("");
}
diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp
index 0d317332f..40bf599cb 100644
--- a/src/widget/form/chatform.cpp
+++ b/src/widget/form/chatform.cpp
@@ -87,7 +87,7 @@ void ChatForm::onSendTriggered()
if (msg.isEmpty())
return;
QString name = Widget::getInstance()->getUsername();
- if (msg.startsWith("/me "))
+ if (msg.startsWith("/me"))
{
msg = msg.right(msg.length() - 4);
addMessage(name, msg, true);
@@ -180,7 +180,8 @@ void ChatForm::onFileRecvRequest(ToxFile file)
chatWidget->insertMessage(new FileTransferAction(fileTrans, getElidedName(name), QTime::currentTime().toString("hh:mm"), false));
- if (!Settings::getInstance().getAutoAcceptDir(Core::getInstance()->getFriendAddress(f->friendId)).isEmpty())
+ if (!Settings::getInstance().getAutoAcceptDir(Core::getInstance()->getFriendAddress(f->friendId)).isEmpty()
+ || !Settings::getInstance().getGlobalAutoAcceptDir().isEmpty())
fileTrans->pressFromHtml("btnB");
}
@@ -408,7 +409,8 @@ void ChatForm::onAvPeerTimeout(int FriendId, int)
void ChatForm::onAvMediaChange(int FriendId, int CallId, bool video)
{
- Q_UNUSED(FriendId)
+ if (FriendId != f->friendId || CallId != callId)
+ return;
if (video)
{
diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp
index bdb764777..d25484543 100644
--- a/src/widget/form/genericchatform.cpp
+++ b/src/widget/form/genericchatform.cpp
@@ -25,6 +25,7 @@
#include "src/widget/tool/chatactions/messageaction.h"
#include "src/widget/tool/chatactions/systemmessageaction.h"
#include "src/widget/tool/chatactions/actionaction.h"
+#include "src/widget/tool/chatactions/alertaction.h"
#include "src/widget/chatareawidget.h"
#include "src/widget/tool/chattextedit.h"
#include "src/widget/maskablepixmapwidget.h"
@@ -173,7 +174,7 @@ void GenericChatForm::addMessage(QString author, QString message, bool isAction,
QString date = datetime.toString(Settings::getInstance().getTimestampFormat());
bool isMe = (author == Widget::getInstance()->getUsername());
- if (!isAction && message.startsWith("/me "))
+ if (!isAction && message.startsWith("/me"))
{ // always render actions regardless of what core thinks
isAction = true;
message = message.right(message.length()-4);
@@ -193,6 +194,13 @@ void GenericChatForm::addMessage(QString author, QString message, bool isAction,
previousName = author;
}
+void GenericChatForm::addAlertMessage(QString author, QString message, QDateTime datetime)
+{
+ QString date = datetime.toString(Settings::getInstance().getTimestampFormat());
+ chatWidget->insertMessage(new AlertAction(author, message, date));
+ previousName = author;
+}
+
void GenericChatForm::onEmoteButtonClicked()
{
// don't show the smiley selection widget if there are no smileys available
diff --git a/src/widget/form/genericchatform.h b/src/widget/form/genericchatform.h
index 0baa4f315..5782823a6 100644
--- a/src/widget/form/genericchatform.h
+++ b/src/widget/form/genericchatform.h
@@ -22,7 +22,7 @@
#include
// Spacing in px inserted when the author of the last message changes
-#define AUTHOR_CHANGE_SPACING 5
+#define AUTHOR_CHANGE_SPACING 5 // why the hell is this a thing? surely the different font is enough?
class QLabel;
class QVBoxLayout;
@@ -45,6 +45,7 @@ public:
virtual void setName(const QString &newName);
virtual void show(Ui::MainWindow &ui);
void addMessage(QString author, QString message, bool isAction = false, QDateTime datetime=QDateTime::currentDateTime());
+ void addAlertMessage(QString author, QString message, QDateTime datetime=QDateTime::currentDateTime());
void addSystemInfoMessage(const QString &message, const QString &type, const QDateTime &datetime=QDateTime::currentDateTime());
int getNumberOfMessages();
diff --git a/src/widget/form/groupchatform.cpp b/src/widget/form/groupchatform.cpp
index 0c5b4c9e1..11a32a71a 100644
--- a/src/widget/form/groupchatform.cpp
+++ b/src/widget/form/groupchatform.cpp
@@ -15,6 +15,7 @@
*/
#include "groupchatform.h"
+#include "tabcompleter.h"
#include "src/group.h"
#include "src/widget/groupwidget.h"
#include "src/widget/tool/chattextedit.h"
@@ -33,6 +34,8 @@ GroupChatForm::GroupChatForm(Group* chatGroup)
namesList = new QLabel();
namesList->setObjectName("peersLabel");
+ tabber = new TabCompleter(msgEdit, group);
+
fileButton->setEnabled(false);
callButton->setVisible(false);
videoButton->setVisible(false);
@@ -59,6 +62,8 @@ GroupChatForm::GroupChatForm(Group* chatGroup)
connect(sendButton, SIGNAL(clicked()), this, SLOT(onSendTriggered()));
connect(msgEdit, SIGNAL(enterPressed()), this, SLOT(onSendTriggered()));
+ connect(msgEdit, &ChatTextEdit::tabPressed, tabber, &TabCompleter::complete);
+ connect(msgEdit, &ChatTextEdit::keyPressed, tabber, &TabCompleter::reset);
setAcceptDrops(true);
}
diff --git a/src/widget/form/groupchatform.h b/src/widget/form/groupchatform.h
index 6b3984b06..f715768e8 100644
--- a/src/widget/form/groupchatform.h
+++ b/src/widget/form/groupchatform.h
@@ -21,6 +21,7 @@
namespace Ui {class MainWindow;}
class Group;
+class TabCompleter;
class GroupChatForm : public GenericChatForm
{
@@ -41,6 +42,7 @@ protected:
private:
Group* group;
QLabel *nusersLabel, *namesList;
+ TabCompleter* tabber;
};
#endif // GROUPCHATFORM_H
diff --git a/src/widget/form/settings/avsettings.ui b/src/widget/form/settings/avsettings.ui
index 74de38e38..daba3b9d3 100644
--- a/src/widget/form/settings/avsettings.ui
+++ b/src/widget/form/settings/avsettings.ui
@@ -34,7 +34,44 @@
489
-
+
+
+
+
+ Volume Settings (Stubs)
+
+
+
+
+
+ Microphone
+
+
+
+
+
+
+ Playback
+
+
+
+
+
+
+ Qt::Horizontal
+
+
+
+
+
+
+ Qt::Horizontal
+
+
+
+
+
+
@@ -47,7 +84,7 @@
QFormLayout::ExpandingFieldsGrow
-
+ Resolution
@@ -64,7 +101,7 @@
-
+ Hue
@@ -78,7 +115,7 @@
-
+ Brightness
@@ -92,7 +129,7 @@
-
+ Saturation
@@ -106,7 +143,7 @@
-
+ Contrast
@@ -119,64 +156,27 @@
-
-
-
-
- 1
- 99
-
-
-
- QFrame::NoFrame
-
-
- QFrame::Raised
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Volume Settings (Stubs)
-
-
-
-
-
- Playback
+
+
+
+
+ 1
+ 99
+
-
-
-
-
-
- Qt::Horizontal
+
+ QFrame::NoFrame
-
-
-
-
-
- Microphone
-
-
-
-
-
-
- Qt::Horizontal
+
+ QFrame::Raised
+
+
+
+
+
diff --git a/src/widget/form/settings/generalform.cpp b/src/widget/form/settings/generalform.cpp
index 78867b60e..e6b21b109 100644
--- a/src/widget/form/settings/generalform.cpp
+++ b/src/widget/form/settings/generalform.cpp
@@ -40,7 +40,9 @@ GeneralForm::GeneralForm(SettingsWidget *myParent) :
bodyUI->transComboBox->setCurrentIndex(locales.indexOf(Settings::getInstance().getTranslation()));
bodyUI->cbMakeToxPortable->setChecked(Settings::getInstance().getMakeToxPortable());
bodyUI->startInTray->setChecked(Settings::getInstance().getAutostartInTray());
- bodyUI->statusChangesCheckbox->setChecked(Settings::getInstance().getStatusChangeNotificationEnabled());
+ bodyUI->closeToTray->setChecked(Settings::getInstance().getCloseToTray());
+ bodyUI->minimizeToTray->setChecked(Settings::getInstance().getMinimizeToTray());
+ bodyUI->statusChanges->setChecked(Settings::getInstance().getStatusChangeNotificationEnabled());
for (auto entry : SmileyPack::listSmileyPacks())
{
@@ -72,7 +74,9 @@ GeneralForm::GeneralForm(SettingsWidget *myParent) :
connect(bodyUI->transComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(onTranslationUpdated()));
connect(bodyUI->cbMakeToxPortable, &QCheckBox::stateChanged, this, &GeneralForm::onMakeToxPortableUpdated);
connect(bodyUI->startInTray, &QCheckBox::stateChanged, this, &GeneralForm::onSetAutostartInTray);
- connect(bodyUI->statusChangesCheckbox, &QCheckBox::stateChanged, this, &GeneralForm::onSetStatusChange);
+ connect(bodyUI->closeToTray, &QCheckBox::stateChanged, this, &GeneralForm::onSetCloseToTray);
+ connect(bodyUI->minimizeToTray, &QCheckBox::stateChanged, this, &GeneralForm::onSetMinimizeToTray);
+ connect(bodyUI->statusChanges, &QCheckBox::stateChanged, this, &GeneralForm::onSetStatusChange);
connect(bodyUI->smileyPackBrowser, SIGNAL(currentIndexChanged(int)), this, SLOT(onSmileyBrowserIndexChanged(int)));
// new syntax can't handle overloaded signals... (at least not in a pretty way)
connect(bodyUI->cbUDPDisabled, &QCheckBox::stateChanged, this, &GeneralForm::onUDPUpdated);
@@ -109,6 +113,16 @@ void GeneralForm::onSetAutostartInTray()
Settings::getInstance().setAutostartInTray(bodyUI->startInTray->isChecked());
}
+void GeneralForm::onSetCloseToTray()
+{
+ Settings::getInstance().setCloseToTray(bodyUI->closeToTray->isChecked());
+}
+
+void GeneralForm::onSetMinimizeToTray()
+{
+ Settings::getInstance().setMinimizeToTray(bodyUI->minimizeToTray->isChecked());
+}
+
void GeneralForm::onStyleSelected(QString style)
{
Settings::getInstance().setStyle(style);
@@ -125,7 +139,7 @@ void GeneralForm::onAutoAwayChanged()
void GeneralForm::onSetStatusChange()
{
- Settings::getInstance().setStatusChangeNotificationEnabled(bodyUI->statusChangesCheckbox->isChecked());
+ Settings::getInstance().setStatusChangeNotificationEnabled(bodyUI->statusChanges->isChecked());
}
void GeneralForm::onSmileyBrowserIndexChanged(int index)
diff --git a/src/widget/form/settings/generalform.h b/src/widget/form/settings/generalform.h
index bae1eb8d0..6397ccdfd 100644
--- a/src/widget/form/settings/generalform.h
+++ b/src/widget/form/settings/generalform.h
@@ -35,6 +35,7 @@ private slots:
void onTranslationUpdated();
void onMakeToxPortableUpdated();
void onSetAutostartInTray();
+ void onSetCloseToTray();
void onSmileyBrowserIndexChanged(int index);
void onUDPUpdated();
void onProxyAddrEdited();
@@ -43,6 +44,7 @@ private slots:
void onStyleSelected(QString style);
void onSetStatusChange();
void onAutoAwayChanged();
+ void onSetMinimizeToTray();
private:
diff --git a/src/widget/form/settings/generalsettings.ui b/src/widget/form/settings/generalsettings.ui
index 924bc057b..f2976eea5 100644
--- a/src/widget/form/settings/generalsettings.ui
+++ b/src/widget/form/settings/generalsettings.ui
@@ -7,7 +7,7 @@
00527
- 500
+ 525
@@ -74,7 +74,21 @@
-
+
+
+ Close to tray
+
+
+
+
+
+
+ Minimize to tray
+
+
+
+
+ Show contacts' status changes
diff --git a/src/widget/form/settings/identityform.cpp b/src/widget/form/settings/identityform.cpp
index 691aa4d86..3347ea30c 100644
--- a/src/widget/form/settings/identityform.cpp
+++ b/src/widget/form/settings/identityform.cpp
@@ -54,6 +54,7 @@ IdentityForm::IdentityForm() :
connect(bodyUI->exportButton, &QPushButton::clicked, this, &IdentityForm::onExportClicked);
connect(bodyUI->deleteButton, &QPushButton::clicked, this, &IdentityForm::onDeleteClicked);
connect(bodyUI->importButton, &QPushButton::clicked, this, &IdentityForm::onImportClicked);
+ connect(bodyUI->newButton, &QPushButton::clicked, this, &IdentityForm::onNewClicked);
connect(Core::getInstance(), &Core::usernameSet, this, [=](const QString& val) { bodyUI->userName->setText(val); });
connect(Core::getInstance(), &Core::statusMessageSet, this, [=](const QString& val) { bodyUI->statusMessage->setText(val); });
@@ -120,15 +121,22 @@ void IdentityForm::onRenameClicked()
{
QString cur = bodyUI->profiles->currentText();
QString title = tr("Rename \"%1\"", "renaming a profile").arg(cur);
- QString name = QInputDialog::getText(this, title, title+":");
- if (name != "")
+ do
{
+ QString name = QInputDialog::getText(this, title, title+":");
+ if (name.isEmpty()) break;
name = Core::sanitize(name);
QDir dir(Settings::getSettingsDirPath());
- QFile::rename(dir.filePath(cur+Core::TOX_EXT), dir.filePath(name+Core::TOX_EXT));
- bodyUI->profiles->setItemText(bodyUI->profiles->currentIndex(), name);
- Settings::getInstance().setCurrentProfile(name);
- }
+ QString file = dir.filePath(name+Core::TOX_EXT);
+ if (!QFile::exists(file) || checkContinue(tr("Profile already exists", "rename confirm title"),
+ tr("A profile named \"%1\" already exists. Do you want to erase it?", "rename confirm text").arg(cur)))
+ {
+ QFile::rename(dir.filePath(cur+Core::TOX_EXT), file);
+ bodyUI->profiles->setItemText(bodyUI->profiles->currentIndex(), name);
+ Settings::getInstance().setCurrentProfile(name);
+ break;
+ }
+ } while (true);
}
void IdentityForm::onExportClicked()
@@ -149,9 +157,8 @@ void IdentityForm::onDeleteClicked()
}
else
{
- QMessageBox::StandardButton resp = QMessageBox::question(this,
- tr("Deletion imminent!","deletion confirmation title"), tr("Are you sure you want to delete this profile?","deletion confirmation text"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
- if (resp == QMessageBox::Yes)
+ if (checkContinue(tr("Deletion imminent!","deletion confirmation title"),
+ tr("Are you sure you want to delete this profile?","deletion confirmation text")))
{
QFile::remove(QDir(Settings::getSettingsDirPath()).filePath(bodyUI->profiles->currentText()+Core::TOX_EXT));
bodyUI->profiles->removeItem(bodyUI->profiles->currentIndex());
@@ -167,6 +174,7 @@ void IdentityForm::onImportClicked()
return;
QFileInfo info(path);
+ QString profile = info.completeBaseName();
if (info.suffix() != "tox")
{
@@ -174,8 +182,22 @@ void IdentityForm::onImportClicked()
return;
}
- QString profile = info.completeBaseName();
+ if (info.exists() && !checkContinue(tr("Profile already exists", "import confirm title"),
+ tr("A profile named \"%1\" already exists. Do you want to erase it?", "import confirm text").arg(profile)))
+ return;
+
QString profilePath = QDir(Settings::getSettingsDirPath()).filePath(profile + Core::TOX_EXT);
QFile::copy(path, profilePath);
bodyUI->profiles->addItem(profile);
}
+
+void IdentityForm::onNewClicked()
+{
+ emit Widget::getInstance()->changeProfile(QString());
+}
+
+bool IdentityForm::checkContinue(const QString& title, const QString& msg)
+{
+ QMessageBox::StandardButton resp = QMessageBox::question(this, title, msg, QMessageBox::Yes | QMessageBox::No, QMessageBox::No);
+ return resp == QMessageBox::Yes;
+}
diff --git a/src/widget/form/settings/identityform.h b/src/widget/form/settings/identityform.h
index f21f653f1..93fc38947 100644
--- a/src/widget/form/settings/identityform.h
+++ b/src/widget/form/settings/identityform.h
@@ -63,6 +63,8 @@ private slots:
void onExportClicked();
void onDeleteClicked();
void onImportClicked();
+ void onNewClicked();
+ bool checkContinue(const QString& title, const QString& msg);
private:
Ui::IdentitySettings* bodyUI;
diff --git a/src/widget/form/settings/identitysettings.ui b/src/widget/form/settings/identitysettings.ui
index 49314395b..ba54f46c8 100644
--- a/src/widget/form/settings/identitysettings.ui
+++ b/src/widget/form/settings/identitysettings.ui
@@ -122,11 +122,22 @@
-
-
- Import a profile
-
-
+
+
+
+
+ Import a profile
+
+
+
+
+
+
+ New Tox ID
+
+
+
+
diff --git a/src/widget/form/tabcompleter.cpp b/src/widget/form/tabcompleter.cpp
new file mode 100644
index 000000000..fa4691e13
--- /dev/null
+++ b/src/widget/form/tabcompleter.cpp
@@ -0,0 +1,122 @@
+/*
+ Copyright (C) 2005-2014 by the Quassel Project and Project Tox
+ devel@quassel-irc.org and https://tox.im
+
+ This file is part of qTox, a Qt-based graphical interface for Tox.
+
+ This program is libre software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ See the COPYING file for more details.
+*/
+
+/* This file was taken from the Quassel IRC client source (src/uisupport), and
+ was greatly simplified for use in qTox. */
+
+#include "tabcompleter.h"
+#include "src/core.h"
+#include "src/group.h"
+#include "src/widget/tool/chattextedit.h"
+#include
+#include
+
+const QString TabCompleter::nickSuffix = QString(": ");
+
+TabCompleter::TabCompleter(ChatTextEdit* msgEdit, Group* group)
+ : QObject(msgEdit), msgEdit(msgEdit), group(group), enabled(false)
+{
+}
+
+/* from quassel/src/uisupport/multilineedit.h
+ // Compatibility methods with the rest of the classes which still expect this to be a QLineEdit
+ inline QString text() const { return toPlainText(); }
+ inline QString html() const { return toHtml(); }
+ inline int cursorPosition() const { return textCursor().position(); }
+ inline void insert(const QString &newText) { insertPlainText(newText); }
+ inline void backspace() { keyPressEvent(new QKeyEvent(QEvent::KeyPress, Qt::Key_Backspace, Qt::NoModifier)); }
+*/
+
+void TabCompleter::buildCompletionList()
+{
+ // ensure a safe state in case we return early.
+ completionMap.clear();
+ nextCompletion = completionMap.begin();
+
+ // split the string on the given RE (not chars, nums or braces/brackets) and take the last section
+ QString tabAbbrev = msgEdit->toPlainText().left(msgEdit->textCursor().position()).section(QRegExp("[^\\w\\d-_\\[\\]{}|`^.\\\\]"), -1, -1);
+ // that section is then used as the completion regex
+ QRegExp regex(QString("^[-_\\[\\]{}|`^.\\\\]*").append(QRegExp::escape(tabAbbrev)), Qt::CaseInsensitive);
+
+ for(auto name : group->peers.values())
+ if (regex.indexIn(name) > -1)
+ completionMap[name.toLower()] = name;
+
+ nextCompletion = completionMap.begin();
+ lastCompletionLength = tabAbbrev.length();
+}
+
+
+void TabCompleter::complete()
+{
+ if (!enabled) {
+ buildCompletionList();
+ enabled = true;
+ }
+
+ 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));
+ }
+
+ // insert completion
+ msgEdit->insertPlainText(*nextCompletion);
+
+ // remember charcount to delete next time and advance to next completion
+ lastCompletionLength = nextCompletion->length();
+ nextCompletion++;
+
+ // we're completing the first word of the line
+ if (msgEdit->textCursor().position() == lastCompletionLength) {
+ msgEdit->insertPlainText(nickSuffix);
+ lastCompletionLength += nickSuffix.length();
+ }
+ }
+ else { // we're at the end of the list -> start over again
+ if (!completionMap.isEmpty()) {
+ nextCompletion = completionMap.begin();
+ complete();
+ }
+ }
+}
+
+
+void TabCompleter::reset()
+{
+ enabled = false;
+}
+
+// this determines the sort order
+bool TabCompleter::SortableString::operator<(const SortableString &other) const
+{
+ QString name = Core::getInstance()->getUsername();
+ if (this->contents == name)
+ return false;
+ else if (other.contents == name)
+ return true;
+
+/* QDateTime thisTime = thisUser->lastChannelActivity(_currentBufferId);
+ QDateTime thatTime = thatUser->lastChannelActivity(_currentBufferId);
+
+
+ if (thisTime.isValid() || thatTime.isValid())
+ return thisTime > thatTime;
+*/ // this could be a useful feature at some point
+
+ return QString::localeAwareCompare(this->contents, other.contents) < 0;
+}
diff --git a/src/widget/form/tabcompleter.h b/src/widget/form/tabcompleter.h
new file mode 100644
index 000000000..f48b1a797
--- /dev/null
+++ b/src/widget/form/tabcompleter.h
@@ -0,0 +1,61 @@
+/*
+ Copyright (C) 2005-2014 by the Quassel Project and Project Tox
+ devel@quassel-irc.org and https://tox.im
+
+ This file is part of qTox, a Qt-based graphical interface for Tox.
+
+ This program is libre software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ See the COPYING file for more details.
+*/
+
+/* This file was taken from the Quassel IRC client source (src/uisupport), and
+ was greatly simplified for use in qTox. */
+
+#ifndef TABCOMPLETER_H
+#define TABCOMPLETER_H
+
+#include
+#include
+#include // I'm really confused why I need this
+
+class ChatTextEdit;
+class Group;
+
+class TabCompleter : public QObject
+{
+ Q_OBJECT
+public:
+ explicit TabCompleter(ChatTextEdit* msgEdit, Group* group);
+
+public slots:
+ void complete();
+ void reset();
+
+private:
+ struct SortableString {
+ inline SortableString(const QString &n) { contents = n; }
+ bool operator<(const SortableString &other) const;
+ QString contents;
+ };
+
+ ChatTextEdit* msgEdit;
+ Group* group;
+ bool enabled;
+ const static QString nickSuffix;
+
+ QMap completionMap;
+ QMap::Iterator nextCompletion;
+ int lastCompletionLength;
+
+ void buildCompletionList();
+};
+
+
+#endif
diff --git a/src/widget/friendwidget.cpp b/src/widget/friendwidget.cpp
index 3a584c6f3..7d790a221 100644
--- a/src/widget/friendwidget.cpp
+++ b/src/widget/friendwidget.cpp
@@ -49,9 +49,10 @@ void FriendWidget::contextMenuEvent(QContextMenuEvent * event)
QPoint pos = event->globalPos();
QString id = Core::getInstance()->getFriendAddress(friendId);
QString dir = Settings::getInstance().getAutoAcceptDir(id);
+ QString globalDir = Settings::getInstance().getGlobalAutoAcceptDir();
QMenu menu;
+ QMenu* inviteMenu = menu.addMenu(tr("Invite to group","Menu to invite a friend to a groupchat"));
QAction* copyId = menu.addAction(tr("Copy friend ID","Menu to copy the Tox ID of that friend"));
- QMenu* inviteMenu = menu.addMenu(tr("Invite in group","Menu to invite a friend in a groupchat"));
QMap groupActions;
for (Group* group : GroupList::groupList)
{
@@ -60,10 +61,15 @@ void FriendWidget::contextMenuEvent(QContextMenuEvent * event)
}
if (groupActions.isEmpty())
inviteMenu->setEnabled(false);
+ menu.addSeparator();
QAction* autoAccept = menu.addAction(tr("Auto accept files from this friend", "context menu entry"));
- QAction* disableAutoAccept = menu.addAction(tr("Diasble auto accepting files", "context menu entry"));
+ QAction* disableAutoAccept = menu.addAction(tr("Manually accept files from this friend", "context menu entry"));
+ QAction* globalAA = menu.addAction(tr("Auto accept files from all friends", "context menu entry"));
+ QAction* disableGlobalAA = menu.addAction(tr("Disable global auto accept", "context menu entry"));
if (dir.isEmpty())
disableAutoAccept->setEnabled(false);
+ if (globalDir.isEmpty())
+ disableGlobalAA->setEnabled(false);
menu.addSeparator();
QAction* removeFriendAction = menu.addAction(tr("Remove friend", "Menu to remove the friend from our friendlist"));
@@ -98,6 +104,21 @@ void FriendWidget::contextMenuEvent(QContextMenuEvent * event)
{
Settings::getInstance().setAutoAcceptDir(id, "");
}
+ else if (selectedItem == globalAA)
+ {
+ if (globalDir.isEmpty())
+ globalDir = QDir::homePath();
+ globalDir = QFileDialog::getExistingDirectory(0, tr("Choose an auto accept directory","popup title"), dir);
+ if (!globalDir.isEmpty())
+ {
+ qDebug() << "FriendWidget: setting global auto accept dir to" << globalDir;
+ Settings::getInstance().setGlobalAutoAcceptDir(globalDir);
+ }
+ }
+ else if (selectedItem == disableGlobalAA)
+ {
+ Settings::getInstance().setGlobalAutoAcceptDir("");
+ }
else if (groupActions.contains(selectedItem))
{
Group* group = groupActions[selectedItem];
diff --git a/src/widget/tool/chatactions/actionaction.cpp b/src/widget/tool/chatactions/actionaction.cpp
index 3facb978c..c68f4449f 100644
--- a/src/widget/tool/chatactions/actionaction.cpp
+++ b/src/widget/tool/chatactions/actionaction.cpp
@@ -15,11 +15,10 @@
*/
#include "actionaction.h"
-#include "src/misc/smileypack.h"
+#include
-ActionAction::ActionAction(const QString &author, const QString &message, const QString &date, const bool& me) :
- ChatAction(me, author, date),
- message(message)
+ActionAction::ActionAction(const QString &author, QString message, const QString &date, const bool& me) :
+ MessageAction(author, author+" "+message, date, me)
{
}
@@ -45,24 +44,5 @@ QString ActionAction::getName()
QString ActionAction::getMessage()
{
- QString message_ = SmileyPack::getInstance().smileyfied(toHtmlChars(message));
-
- // detect urls
- QRegExp exp("(www\\.|http[s]?:\\/\\/|ftp:\\/\\/)\\S+");
- int offset = 0;
- while ((offset = exp.indexIn(message_, offset)) != -1)
- {
- QString url = exp.cap();
-
- // add scheme if not specified
- if (exp.cap(1) == "www.")
- url.prepend("http://");
-
- QString htmledUrl = QString("%1").arg(url);
- message_.replace(offset, exp.cap().length(), htmledUrl);
-
- offset += htmledUrl.length();
- }
-
- return QString("
%1 %2
").arg(name).arg(message_);
+ return MessageAction::getMessage("action");
}
diff --git a/src/widget/tool/chatactions/actionaction.h b/src/widget/tool/chatactions/actionaction.h
index 08553a96e..d438f0ecd 100644
--- a/src/widget/tool/chatactions/actionaction.h
+++ b/src/widget/tool/chatactions/actionaction.h
@@ -17,12 +17,12 @@
#ifndef ACTIONACTION_H
#define ACTIONACTION_H
-#include "chataction.h"
+#include "messageaction.h"
-class ActionAction : public ChatAction
+class ActionAction : public MessageAction
{
public:
- ActionAction(const QString &author, const QString &message, const QString& date, const bool&);
+ ActionAction(const QString &author, QString message, const QString& date, const bool&);
virtual ~ActionAction(){;}
virtual QString getMessage();
virtual QString getName();
diff --git a/src/widget/tool/chatactions/alertaction.cpp b/src/widget/tool/chatactions/alertaction.cpp
new file mode 100644
index 000000000..b62c1896e
--- /dev/null
+++ b/src/widget/tool/chatactions/alertaction.cpp
@@ -0,0 +1,47 @@
+/*
+ Copyright (C) 2014 by Project Tox
+
+ This file is part of qTox, a Qt-based graphical interface for Tox.
+
+ This program is libre software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ See the COPYING file for more details.
+*/
+
+#include "alertaction.h"
+
+AlertAction::AlertAction(const QString &author, const QString &message, const QString &date) :
+ MessageAction(author, message, date, false)
+{
+}
+
+void AlertAction::setup(QTextCursor cursor, QTextEdit *)
+{
+ // When this function is called, we're supposed to only update ourselve when needed
+ // Nobody should ask us to do anything with our content, we're on our own
+ // Except we never udpate on our own, so we can safely free our resources
+
+ (void) cursor;
+ message.clear();
+ message.squeeze();
+ name.clear();
+ name.squeeze();
+ date.clear();
+ date.squeeze();
+}
+/*
+QString AlertAction::getName()
+{
+ return QString("
%2
").arg("alert_name").arg(toHtmlChars(name));
+}
+*/
+QString AlertAction::getMessage()
+{
+ return MessageAction::getMessage("alert");
+}
diff --git a/src/widget/tool/chatactions/alertaction.h b/src/widget/tool/chatactions/alertaction.h
new file mode 100644
index 000000000..64e00e6bf
--- /dev/null
+++ b/src/widget/tool/chatactions/alertaction.h
@@ -0,0 +1,35 @@
+/*
+ Copyright (C) 2014 by Project Tox
+
+ This file is part of qTox, a Qt-based graphical interface for Tox.
+
+ This program is libre software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ See the COPYING file for more details.
+*/
+
+#ifndef ALERTACTION_H
+#define ALERTACTION_H
+
+#include "messageaction.h"
+
+class AlertAction : public MessageAction
+{
+public:
+ AlertAction(const QString &author, const QString &message, const QString& date);
+ virtual ~AlertAction(){;}
+ virtual QString getMessage();
+ //virtual QString getName(); only do the message for now; preferably would do the whole row
+ virtual void setup(QTextCursor cursor, QTextEdit*) override;
+
+private:
+ QString message;
+};
+
+#endif // MESSAGEACTION_H
diff --git a/src/widget/tool/chatactions/messageaction.cpp b/src/widget/tool/chatactions/messageaction.cpp
index 4a8b6962b..8058aa56e 100644
--- a/src/widget/tool/chatactions/messageaction.cpp
+++ b/src/widget/tool/chatactions/messageaction.cpp
@@ -38,7 +38,7 @@ void MessageAction::setup(QTextCursor cursor, QTextEdit *)
date.squeeze();
}
-QString MessageAction::getMessage()
+QString MessageAction::getMessage(QString div)
{
QString message_ = SmileyPack::getInstance().smileyfied(toHtmlChars(message));
@@ -65,14 +65,19 @@ QString MessageAction::getMessage()
for (QString& s : messageLines)
{
if (QRegExp("^[ ]*>.*").exactMatch(s))
- message_ += ">" + s.right(s.length()-4) + " ";
+ message_ += "" + s.right(s.length()-4) + " ";
else
message_ += s + " ";
}
message_ = message_.left(message_.length()-4);
- if (isMe)
- return QString("
" + message_ + "
");
- else
- return QString("
" + message_ + "
");
+ return QString(QString("
").arg(div) + message_ + "
");
+}
+
+QString MessageAction::getMessage()
+{
+ if (isMe)
+ return getMessage("message_me");
+ else
+ return getMessage("message");
}
diff --git a/src/widget/tool/chatactions/messageaction.h b/src/widget/tool/chatactions/messageaction.h
index aa32801eb..c5ba63de3 100644
--- a/src/widget/tool/chatactions/messageaction.h
+++ b/src/widget/tool/chatactions/messageaction.h
@@ -25,9 +25,10 @@ public:
MessageAction(const QString &author, const QString &message, const QString &date, const bool &me);
virtual ~MessageAction(){;}
virtual QString getMessage();
+ virtual QString getMessage(QString div);
virtual void setup(QTextCursor cursor, QTextEdit*) override;
-private:
+protected:
QString message;
};
diff --git a/src/widget/tool/chattextedit.cpp b/src/widget/tool/chattextedit.cpp
index 9b51b8fba..d9ba2ee46 100644
--- a/src/widget/tool/chattextedit.cpp
+++ b/src/widget/tool/chattextedit.cpp
@@ -27,11 +27,15 @@ 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();
- return;
+ 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
+ {
+ emit keyPressed();
+ QTextEdit::keyPressEvent(event);
}
- QTextEdit::keyPressEvent(event);
}
diff --git a/src/widget/tool/chattextedit.h b/src/widget/tool/chattextedit.h
index f8a1cb73a..6bab07cda 100644
--- a/src/widget/tool/chattextedit.h
+++ b/src/widget/tool/chattextedit.h
@@ -28,6 +28,8 @@ public:
signals:
void enterPressed();
+ void tabPressed();
+ void keyPressed();
public slots:
diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp
index fdc3465d8..51285fc99 100644
--- a/src/widget/widget.cpp
+++ b/src/widget/widget.cpp
@@ -61,7 +61,52 @@ Widget::Widget(QWidget *parent)
void Widget::init()
{
+
ui->setupUi(this);
+
+ if (QSystemTrayIcon::isSystemTrayAvailable() == true)
+ {
+ icon = new QSystemTrayIcon(this);
+ icon->setIcon(this->windowIcon());
+ trayMenu = new QMenu;
+ trayMenu->setStyleSheet("QMenu {background: white; color: black; border: 1px solid black;}"
+ "QMenu::item:selected { background: #414141}");
+
+ statusOnline = new QAction(tr("online"), this);
+ statusOnline->setIcon(QIcon(":ui/statusButton/dot_online.png"));
+ connect(statusOnline, SIGNAL(triggered()), this, SLOT(setStatusOnline()));
+ statusAway = new QAction(tr("away"), this);
+ statusAway->setIcon(QIcon(":ui/statusButton/dot_idle.png"));
+ connect(statusAway, SIGNAL(triggered()), this, SLOT(setStatusAway()));
+ statusBusy = new QAction(tr("busy"), this);
+ connect(statusBusy, SIGNAL(triggered()), this, SLOT(setStatusBusy()));
+ statusBusy->setIcon(QIcon(":ui/statusButton/dot_busy.png"));
+ actionQuit = new QAction(tr("&Quit"), this);
+ connect(actionQuit, SIGNAL(triggered()), qApp, SLOT(quit()));
+
+ trayMenu->addAction(new QAction(tr("Change status to:"), this));
+ trayMenu->addAction(statusOnline);
+ trayMenu->addAction(statusAway);
+ trayMenu->addAction(statusBusy);
+ trayMenu->addSeparator();
+ trayMenu->addAction(actionQuit);
+ icon->setContextMenu(trayMenu);
+
+ connect(icon,
+ SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
+ this,
+ SLOT(onIconClick(QSystemTrayIcon::ActivationReason)));
+
+ icon->show();
+
+ if(Settings::getInstance().getAutostartInTray() == false)
+ this->show();
+ }
+ else
+ {
+ qWarning() << "No system tray detected!";
+ this->show();
+ }
ui->statusbar->hide();
ui->menubar->hide();
@@ -148,7 +193,6 @@ void Widget::init()
filesForm = new FilesForm();
addFriendForm = new AddFriendForm;
settingsWidget = new SettingsWidget();
-
connect(core, &Core::connected, this, &Widget::onConnected);
connect(core, &Core::disconnected, this, &Widget::onDisconnected);
@@ -233,12 +277,19 @@ Widget::~Widget()
for (Group* g : GroupList::groupList)
delete g;
GroupList::groupList.clear();
+ delete statusAway;
+ delete statusBusy;
+ delete statusOnline;
+ delete actionQuit;
+ delete trayMenu;
+ delete icon;
delete ui;
instance = nullptr;
}
Widget* Widget::getInstance()
{
+
if (!instance)
{
instance = new Widget();
@@ -254,10 +305,30 @@ QThread* Widget::getCoreThread()
void Widget::closeEvent(QCloseEvent *event)
{
- Settings::getInstance().setWindowGeometry(saveGeometry());
- Settings::getInstance().setWindowState(saveState());
- Settings::getInstance().setSplitterState(ui->mainSplitter->saveState());
- QWidget::closeEvent(event);
+ if(Settings::getInstance().getCloseToTray() == true)
+ {
+ event->ignore();
+ this->hide();
+ }
+ else
+ {
+ Settings::getInstance().setWindowGeometry(saveGeometry());
+ Settings::getInstance().setWindowState(saveState());
+ Settings::getInstance().setSplitterState(ui->mainSplitter->saveState());
+ QWidget::closeEvent(event);
+ }
+}
+
+void Widget::changeEvent(QEvent *event)
+{
+ if (event->type() == QEvent::WindowStateChange)
+ {
+ if(isMinimized() == true
+ && Settings::getInstance().getMinimizeToTray() == true)
+ {
+ this->hide();
+ }
+ }
}
QString Widget::detectProfile()
@@ -454,12 +525,21 @@ void Widget::onTransferClicked()
activeChatroomWidget = nullptr;
}
-void Widget::onIconClick()
+void Widget::onIconClick(QSystemTrayIcon::ActivationReason reason)
{
- if(this->isHidden() == true)
- this->show();
- else
- this->hide();
+ switch (reason) {
+ case QSystemTrayIcon::Trigger:
+ if(this->isHidden() == true)
+ this->show();
+ else
+ this->hide();
+ case QSystemTrayIcon::DoubleClick:
+ break;
+ case QSystemTrayIcon::MiddleClick:
+ break;
+ default:
+ ;
+ }
}
void Widget::onSettingsClicked()
@@ -750,14 +830,19 @@ void Widget::onGroupMessageReceived(int groupnumber, const QString& message, con
if (!g)
return;
- g->chatForm->addMessage(author, message);
+ QString name = core->getUsername();
+ bool targeted = (author != name) && message.contains(name, Qt::CaseInsensitive);
+ if (targeted)
+ g->chatForm->addAlertMessage(author, message);
+ else
+ g->chatForm->addMessage(author, message);
if ((static_cast(g->widget) != activeChatroomWidget) || isMinimized() || !isActiveWindow())
{
g->hasNewMessages = 1;
- newMessageAlert(); // sound alert on any message, not just naming user
- if (message.contains(core->getUsername(), Qt::CaseInsensitive))
+ if (targeted)
{
+ newMessageAlert();
g->userWasMentioned = 1; // useful for highlighting line or desktop notifications
}
g->widget->updateStatusLight();
@@ -773,17 +858,23 @@ void Widget::onGroupNamelistChanged(int groupnumber, int peernumber, uint8_t Cha
g = createGroup(groupnumber);
}
+ QString name = core->getGroupPeerName(groupnumber, peernumber);
TOX_CHAT_CHANGE change = static_cast(Change);
if (change == TOX_CHAT_CHANGE_PEER_ADD)
{
- QString name = core->getGroupPeerName(groupnumber, peernumber);
if (name.isEmpty())
name = tr("", "Placeholder when we don't know someone's name in a group chat");
g->addPeer(peernumber,name);
+ //g->chatForm->addSystemInfoMessage(tr("%1 has joined the chat").arg(name), "green");
+ // we can't display these messages until irungentoo fixes peernumbers
+ // https://github.com/irungentoo/toxcore/issues/1128
}
else if (change == TOX_CHAT_CHANGE_PEER_DEL)
+ {
g->removePeer(peernumber);
- else if (change == TOX_CHAT_CHANGE_PEER_NAME)
+ //g->chatForm->addSystemInfoMessage(tr("%1 has left the chat").arg(name), "silver");
+ }
+ else if (change == TOX_CHAT_CHANGE_PEER_NAME) // core overwrites old name before telling us it changed...
g->updatePeer(peernumber,core->getGroupPeerName(groupnumber, peernumber));
}
diff --git a/src/widget/widget.h b/src/widget/widget.h
index 37af9b499..c75851a1b 100644
--- a/src/widget/widget.h
+++ b/src/widget/widget.h
@@ -18,6 +18,7 @@
#define WIDGET_H
#include
+#include
#include "form/addfriendform.h"
#include "form/settingswidget.h"
#include "form/settings/identityform.h"
@@ -65,6 +66,11 @@ public:
~Widget();
virtual void closeEvent(QCloseEvent *event);
+ virtual void changeEvent(QEvent *event);
+
+
+public slots:
+ void onSettingsClicked();
signals:
void friendRequestAccepted(const QString& userId);
@@ -82,7 +88,6 @@ private slots:
void onAddClicked();
void onGroupClicked();
void onTransferClicked();
- void onSettingsClicked();
void onFailedToStartCore();
void onBadProxyCore();
void onAvatarClicked();
@@ -112,7 +117,7 @@ private slots:
void onMessageSendResult(int friendId, const QString& message, int messageId);
void onGroupSendResult(int groupId, const QString& message, int result);
void playRingtone();
- void onIconClick();
+ void onIconClick(QSystemTrayIcon::ActivationReason);
void onUserAway();
private:
@@ -124,6 +129,12 @@ private:
void removeGroup(Group* g);
QString askProfiles();
QString detectProfile();
+ QSystemTrayIcon *icon;
+ QMenu *trayMenu;
+ QAction *statusOnline,
+ *statusAway,
+ *statusBusy,
+ *actionQuit;
Ui::MainWindow *ui;
QSplitter *centralLayout;
diff --git a/translations/fr.qm b/translations/fr.qm
index ff6462596..cba6869e9 100644
Binary files a/translations/fr.qm and b/translations/fr.qm differ
diff --git a/translations/fr.ts b/translations/fr.ts
index a9837cde0..d18f9b982 100644
--- a/translations/fr.ts
+++ b/translations/fr.ts
@@ -3,11 +3,6 @@
AVForm
-
-
-
-
- On a button
@@ -18,6 +13,11 @@
On a buttonMontrer l'aperçu vidéo
+
+
+
+ Audio/Vidéo
+ AVPage
@@ -41,57 +41,52 @@
-
+ qTox
-
+
+
+ Options vidéo
+
+
+
+
+ Résolution
+
+
+
-
+ Options du volume (Fictif)
-
+
-
+ Haut-parleurs
-
+
-
-
-
-
-
-
+ Microphone
-
-
-
-
-
-
+ Teinte
-
+
-
+ Luminosité
-
+
-
+ Saturation
-
+
-
-
-
-
-
-
+ Contraste
@@ -192,7 +187,7 @@
ChatForm
-
+ Envoyer un fichier
@@ -211,33 +206,44 @@
Core
-
-
-
+
+
+ Toxer avec qTox
-
+
+
+ Utilisateur de qTox
+
+
+
+
+ Profil chiffré
+
+
+
-
+ Votre profil tox semble être chiffré, qTox ne peut pas l'ouvrir
+Voulez-vous effacer ce profil ?FileTransferInstance
-
+ Title of the file saving dialogSauvegarder un fichier
-
+ Title of permissions popupImpossible d'écrire ici
-
+ text of permissions popupVous n'avez pas la permission d'écrire ici. Choisissez un audre endroit, ou annulez.
@@ -309,19 +315,55 @@ Do you want to erase this profile ?
FriendWidget
-
+
+
+ Menu to invite a friend to a groupchat
+ Inviter au groupe
+
+
+ Menu to copy the Tox ID of that friendCopier l'ID ami
-
-
- Menu to invite a friend in a groupchat
- Inviter dans un groupe
+
+
+ context menu entry
+ Automatiquement accepter les fichiers de ce contact
-
+
+
+ context menu entry
+ Accepter les fichiers de ce contact manuellement
+
+
+
+
+ context menu entry
+ Accepter les fichiers de tous les contacts automatiquement
+
+
+
+
+ context menu entry
+ Désactiver l'acceptation automatique de fichier
+
+
+
+
+
+ popup title
+ Choisir un dossier de téléchargement
+
+
+
+ Menu to invite a friend in a groupchat
+ Inviter dans un groupe
+
+
+ Menu to remove the friend from our friendlistSupprimer ami
@@ -330,9 +372,13 @@ Do you want to erase this profile ?
GeneralForm
-
- Options Générales
+ Options Générales
+
+
+
+
+ Général
@@ -375,95 +421,110 @@ Do you want to erase this profile ?
-
+ qTox
- Options Générales
+ Options Générales
- Text on a checkbox to enable translations
- Utiliser les traductions
+ Utiliser les traductions
-
+
+
+
+ La translation peut ne pas se charger jusqu'à ce que qTox redémarre.
+
+
+
+
+ Traduction:
+
+
+ describes makeToxPortable checkbox
- Sauvegarde les options dans le dossier courant au lieu du dossier de configuration habituel
+ Sauvegarde les options dans le dossier courant au lieu du dossier de configuration habituel
-
+
- Rendre Tox portable
+ Rendre Tox portable
-
+
-
+ Démarrer dans la barre d'état
-
+
-
+ Montrer les changements de status des contacts
-
+
-
+ En minutes
-
+
-
+ Auto-absent après (0 pour désactiver):
-
-
-
-
-
-
-
- Thème
+
+
+ Mettre à 0 pour désactiver
+
+ minutes
+
+
+
+
+ Thème
+
+
+ Text on smiley pack label
-
+ Pack de smileys:
-
+
-
+ :)
-
+
-
+ :)
-
+
-
+ :p
-
+
-
+ :O
-
+
-
+ :'(
-
+
-
+ Style:
@@ -471,51 +532,51 @@ Do you want to erase this profile ?
Pack de smileys
-
+
-
-
-
-
-
- Text on a checkbox to enable IPv6
- Activer IPv6 (recommandé)
-
-
-
-
- force tcp checkbox tooltip
-
-
-
-
-
- Text on checkbox to disable UDP
-
-
-
-
-
-
+ Options de réseau
-
- Text on proxy addr label
-
+
+ Text on a checkbox to enable IPv6
+ Activer IPv6 (recommandé)
+
+
+
+
+ force tcp checkbox tooltip
+ Permet par exemple d'utiliser Tox à travers Tor, mais ce n'est à utiliser que si nécessaire, car cela ralenti le réseau Tox.
+
+ Text on checkbox to disable UDP
+ Désactiver UDP (non recommandé)
+
+
+
+
+ Utiliser un proxy (SOCKS5)
+
+
+
+
+ Text on proxy addr label
+ Addresse
+
+
+ Text on proxy port label
-
+ PortGenericChatForm
-
-
+
+ Sauvegarder l'historique de conversation
@@ -523,7 +584,7 @@ Do you want to erase this profile ?
GroupChatForm
-
+ Number of users in chat%1 personnes
@@ -533,7 +594,7 @@ Do you want to erase this profile ?
<Inconnu>
-
+ %1 personnes
@@ -545,19 +606,19 @@ Do you want to erase this profile ?
GroupWidget
-
-
+
+ %1 personnes
-
-
+
+ 0 personnes
-
+ Menu to quit a groupchatQuitter le groupe
@@ -566,87 +627,111 @@ Do you want to erase this profile ?
IdentityForm
-
-
-
+
+
+ Identité
-
+ popup title
-
+ Appel en cours
-
+ popup text
-
+ Vous ne pouvez pas changer de profil quand un appel est en cours!
-
+ renaming a profile
-
+ Renommer "%1"
-
+
+
+ rename confirm title
+ Ce profil existe déjà
+
+
+
+
+ rename confirm text
+ Un profil appelé "%1" existe déjà. Voulez-vous le supprimer ?
+
+
+ save dialog title
-
+ Exporter le profil
-
+ save dialog filter
-
+ Fichier sauvegarde Tox (*.tox)
-
+ current profile deletion warning title
-
+ Profil en cours d'utilisation
-
+ current profile deletion warning text
-
+ Ce profil est en cours d'utilisation. Merci de choisir un autre profil avant de supprimer celui-ci.
-
+ deletion confirmation title
-
+ Suppression imminente!
-
+ 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 non-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 ?
@@ -679,78 +764,84 @@ Do you want to erase this profile ?
-
+ qTox
- Informations Publiques
+ Informations Publiques
- Nom
+ Nom
- Status
+ Status
- ID Tox
+ ID Tox
-
+ Votre ID Tox (cliquez pour copier)
-
+ Profils
-
+ Profils disponibles:load profile button
-
+ Chargerrename profile button
-
+ Renommerexport profile button
-
+ Exporterdelete profile button
-
+ Supprimerdelete profile button tooltip
-
+ Util pour sécuriser sur un ordinateur public
-
+ import profile button
-
+ Importer un profil
+
+
+
+
+ new profile button
+ Nouvel ID Tox
@@ -805,8 +896,8 @@ Do you want to erase this profile ?
PrivacyForm
-
-
+
+ Vie privée
@@ -903,103 +994,103 @@ Do you want to erase this profile ?
Ctrl+Q
-
+ Button to set your status to 'Online'Connecté
-
+ Button to set your status to 'Away'
- Indisponnible
+ Indisponible
-
+ 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 quitter quand vous fermerez ce message.
-
+ popup text
-
+ Toxcore n'as pas pu démarrer avec ces paramètres de proxy, qTox ne peut pas continuer; merci de modifier vos paramètres et redémarrer.
-
+ contact status
-
+ indisponnible
-
+ contact status
-
+ occupé
-
+ contact status
-
+ déconnecté
-
+ 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>
diff --git a/translations/it.qm b/translations/it.qm
index 8aef73313..f4945ef5b 100644
Binary files a/translations/it.qm and b/translations/it.qm differ
diff --git a/translations/it.ts b/translations/it.ts
index 00ff091fe..80933d3e8 100644
--- a/translations/it.ts
+++ b/translations/it.ts
@@ -17,47 +17,47 @@
Form
-
+ Impostazioni Video
-
+ Risoluzione
-
+
- Impostazioni Volume (Stub)
+ Impostazioni Audio (Stub)
-
+ Altoparlanti
-
+ Microfono
-
+ Colore
-
+ Luminoistà
-
+ Saturazione
-
+ Contrasto
@@ -153,12 +153,22 @@
Core
-
+
+
+ Toxing on qTox
+
+
+
+
+ qTox User
+
+
+ Profilo criptato
-
+ Il tuo profilo Tox sembra essere criptato, qTox non può aprirlo\nVuoi eliminare questo profilo?
@@ -167,19 +177,19 @@ Do you want to erase this profile ?
FileTransferInstance
-
+ Title of the file saving dialogSalva file
-
+ Title of permissions popupErrore
-
+ text of permissions popupNon hai sufficienti permessi per scrivere in questa locazione. Scegli un'altra posizione, o annulla il salvataggio.
@@ -243,37 +253,50 @@ Do you want to erase this profile ?
FriendWidget
-
+ Menu to copy the Tox ID of that friendCopia Tox ID del contatto
-
-
- Menu to invite a friend in a groupchat
- Invita nel gruppo
-
-
-
+ context menu entryAccetta automaticamente i files inviati da questo contatto
-
-
+
+
+ Menu to invite a friend to a groupchat
+ Invita nel gruppo
+
+
+
+
context menu entry
- Non accettare automaticamente i files inviati da questo contatto
+ Accetta manualmente i files inviati da questo contatto
+
+
+
+
+ context menu entry
+ Accetta automaticamente i files inviati da tutti i contatti
+
+ context menu entry
+ Accetta manualmente i files inviati da tutti i contatti
+
+
+ Menu to remove the friend from our friendlistRimuovi contatto
-
+
+ popup titleScegli dove salvare i files accettati automaticamente
@@ -311,33 +334,33 @@ Do you want to erase this profile ?
Lingua:
-
+ Imposta assenza dopo:
-
+ Imposta 0 per disabilitare
-
+ Text on smiley pack labelEmoticons:
-
+ Stile:
-
+ Impostazioni Connessione
-
+ Text on a checkbox to enable IPv6Abilita IPv6 (consigliato)
@@ -356,78 +379,88 @@ Do you want to erase this profile ?
- Avvia minimizzato
+ Avvia minimizzato nella traybar
+
+ Chiudi nella traybar
+
+
+
+
+ Minimizza nella traybar
+
+
+ Mostra quando i contatti cambiano stato
-
+ Espresso in minuti
-
+ minuti
-
+ Impostazioni Tema
-
+ :)
-
+ ;)
-
+ :p
-
+ :O
-
+ :'(
-
+ Usa proxy (SOCKS5)
-
+ Text on proxy addr labelIP
-
+ Text on proxy port labelPorta
-
+ Text on checkbox to disable UDPDisabilita connessioni UDP (non raccomandato)
-
+ force tcp checkbox tooltipQuesto permette di usare qTox con Tor; tuttavia aggiunge carico alla rete Tox, quindi usalo solo se necessario.
@@ -436,8 +469,8 @@ Do you want to erase this profile ?
GenericChatForm
-
-
+
+ Salva il log della chat
@@ -445,13 +478,13 @@ Do you want to erase this profile ?
GroupChatForm
-
+ Number of users in chat%1 utenti in chat
-
+ %1 utenti in chat
@@ -485,83 +518,107 @@ Do you want to erase this profile ?
Identità
-
+ popup titleChiamata in corso
-
+ popup textNon puoi cambiare profilo durante una chiamata!
-
+ renaming a profileRinomina "%1"
-
+
+
+ rename confirm title
+ Profilo già esistente
+
+
+
+
+ rename confirm text
+ Un profilo chiamato "%1" esiste già. Vuoi sovrascriverlo?
+
+
+ save dialog titleEsporta profilo
-
+ save dialog filterTox save file (*.tox)
-
+ current profile deletion warning titleProfilo attualmente in uso
-
+ current profile deletion warning textQuesto profilo è attualmente in uso. Per favore carica un profilo differente prima di eliminare questo.
-
+ deletion confirmation titleEliminazione imminente!
-
+ deletion confirmation textSei sicuro di voler eliminare questo profilo?
-
+ import dialog titleImporta profilo
-
+ import dialog filterTox save file (*.tox)
-
+ popup titleFile ignorato
-
+ popup textAttenzione: 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?
+ IdentitySettings
@@ -636,10 +693,16 @@ Do you want to erase this profile ?
Utile per preservare la tua sicurezza su computer pubblici
-
+ import profile button
- Importa un profilo
+ Importa profilo
+
+
+
+
+ new profile button
+ Nuovo profilo
@@ -701,103 +764,128 @@ Do you want to erase this profile ?
Widget
-
+
+
+ online
+
+
+
+
+ assente
+
+
+
+
+ occupato
+
+
+
+
+ &Esci
+
+
+
+
+ Cambia stato in:
+
+
+ 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 textImpossibile avviare Toxcore con le tue impostazione proxy.\nqTox non può funzionare correttamente, per favore modifica le impostazioni e riavvia il programma.
-
+ contact statusassente
-
+ contact statusoccupato
-
+ contact statusoffline
-
+ contact statusonline
-
+ e.g. "Dubslow is now online"%1 è ora %2
-
+ Placeholder when we don't know someone's name in a group chat<Sconosciuto>
diff --git a/translations/pl.qm b/translations/pl.qm
index 8f6d42d71..84f49ab21 100644
Binary files a/translations/pl.qm and b/translations/pl.qm differ
diff --git a/translations/pl.ts b/translations/pl.ts
index 8ca565afa..3a0b4a6de 100644
--- a/translations/pl.ts
+++ b/translations/pl.ts
@@ -48,27 +48,27 @@
Ustawienia
-
+ Ustawienia wideo
-
+ Rozdzielczość
-
+ Ustawienia dźwięku
-
+ Odtwarzanie
-
+ Mikrofon
@@ -81,22 +81,22 @@
Tryby
-
+ Odcień
-
+ Jasność
-
+ Nasycenie
-
+ Kontrast
@@ -200,12 +200,23 @@
Core
-
+
+
+ better translation?
+ Toxuję na qTox
+
+
+
+
+ Użytkownik qToxa
+
+
+ Zaszyfrowany profil
-
+ Twój profil zdaje się być zaszyfrowany, qTox nie jest w stanie go otworzyć
@@ -215,19 +226,19 @@ Czy chcesz usunąć ten profil ?FileTransferInstance
-
+ Title of the file saving dialogZapisz plik
-
+ Title of permissions popupNie można zapisać w lokacji
-
+ text of permissions popupNie masz uprawnienia by zapisać w tej lokacji. Wybierz inną lub anuluj zapis.
@@ -291,37 +302,61 @@ Czy chcesz usunąć ten profil ?
FriendWidget
-
+ Menu to copy the Tox ID of that friendKopiuj ID kontaktu
- Menu to invite a friend in a groupchat
- Zaproś do grupy
+ Zaproś do grupy
-
+ context menu entryOdbieraj pliki automatycznie
- context menu entry
- Nie odbieraj plików automatycznie
+ Nie odbieraj plików automatycznie
+
+
+
+
+ Menu to invite a friend to a groupchat
+ Zaproś do grupy
+
+
+
+
+ context menu entry
+ Ręcznie akceptuj pliki od tego znajomego
+
+
+
+
+ context menu entry
+ Automatycznie akceptuj pliki od wszystkich znajomych
+
+ context menu entry
+ better translation?
+ Wyłącz globalnie automatyczną akceptację
+
+
+ Menu to remove the friend from our friendlistUsuń kontakt
-
+
+ popup titleWybierz domyślną ścieżkę dla plików
@@ -390,7 +425,7 @@ Czy chcesz usunąć ten profil ?
Text on a checkbox to enable translations
- Użyj tłumaczenia
+ Użyj tłumaczenia
@@ -422,33 +457,43 @@ Czy chcesz usunąć ten profil ?
+
+ Zamknij do traya
+
+
+
+
+ Minimalizuj do traya
+
+
+ Pokazuj zmiany statusów
-
+ Podane w minutach
-
+ Zmiana statusu na "Nieobecny" (0 by wyłączyć):
-
+ Ustaw na 0 by wyłączyć
-
+ Text on smiley pack labelbetter translation? anyone?Paczka uśmiechów:
-
+ Styl:
@@ -457,12 +502,12 @@ Czy chcesz usunąć ten profil ?
Automatyczna zmiana statusu na "Nieobecny" po:
-
+ min
-
+ Motyw
@@ -473,27 +518,27 @@ Czy chcesz usunąć ten profil ?
Paczka uśmiechów
-
+ :)
-
+ ;)
-
+ :p
-
+ :O
-
+ :'(
@@ -502,41 +547,41 @@ Czy chcesz usunąć ten profil ?
Styl
-
+ Ustawienia połączenia
-
+ Text on a checkbox to enable IPv6Użyj IPv6 (zalecane)
-
+ force tcp checkbox tooltipTo 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 UDPWyłącz UDP (nie zalecane)
-
+ Użyj proxy (SOCKS5)
-
+ Text on proxy addr labelAdres
-
+ Text on proxy port labelPort
@@ -545,8 +590,8 @@ Czy chcesz usunąć ten profil ?
GenericChatForm
-
-
+
+ Zapisz historię rozmowy
@@ -554,7 +599,7 @@ Czy chcesz usunąć ten profil ?
GroupChatForm
-
+ Number of users in chat%1 użytkowników w czacie
@@ -564,7 +609,7 @@ Czy chcesz usunąć ten profil ?
<Nieznany/a>
-
+ %1 użytkowników w czacie
@@ -602,83 +647,107 @@ Czy chcesz usunąć ten profil ?
Tożsamość
-
+ popup titleRozmowa w trakcie
-
+ popup textNie można zmienić profilu podczas aktywnego połączenia!
-
+ renaming a profileZmień nazwę "%1"
-
+
+
+ rename confirm title
+ Profil już istnieje
+
+
+
+
+ rename confirm text
+ Profil pod nazwą "%1" już istnieje. Czy chcesz go usunąć?
+
+
+ save dialog titleEksportuj profil
-
+ save dialog filterPlik zapisu Tox (*.tox)
-
+ current profile deletion warning titleProfil obecnie załadowany
-
+ current profile deletion warning textTen profil jest obecnie w użyciu. Proszę załaduj inny profil przed usunięciem tego.
-
+ deletion confirmation titleUsuwanie profilu!
-
+ deletion confirmation textCzy na pewno chcesz usunąć ten profil?
-
+ import dialog titleImportuj profil
-
+ import dialog filterPlik zapisu Tox (*.tox)
-
+ popup titleZignorowano niepoprawny plik profilu
-
+ popup textOstrzeż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ąć?
+ IdentityPage
@@ -778,11 +847,17 @@ Czy chcesz usunąć ten profil ?
Użyteczne by pozostać bezpiecznym na publicznych komputerach
-
+ import profile buttonImportuj profil
+
+
+
+ new profile button
+ Nowy Tox ID
+ MainWindow
@@ -891,103 +966,128 @@ Czy chcesz usunąć ten profil ?
Widget
-
+
+
+ online
+
+
+
+
+ nieobecna/y
+
+
+
+
+ zajęta/y
+
+
+
+
+ &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 textNie udało się uruchomić toxcore z twoimi ustawieniami proxy. qTox nie może działać, proszę zmodyfikuj ustawienia i zrestartuj.
-
+ contact statusnieobecna/y
-
+ contact statuszajęta/y
-
+ contact statusoffline
-
+ contact statusonline
-
+ 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>
diff --git a/translations/ru.qm b/translations/ru.qm
index f3d7a3e2a..e228ad220 100644
Binary files a/translations/ru.qm and b/translations/ru.qm differ
diff --git a/translations/ru.ts b/translations/ru.ts
index 7860d8430..5290150e2 100644
--- a/translations/ru.ts
+++ b/translations/ru.ts
@@ -5,18 +5,8 @@
AVForm
-
- Настройки аудио/видео
-
-
-
- On a button
- Спрятать видео-превью
-
-
-
- On a button
- Посмотреть видео-превью
+
+ Аудио/Видео
@@ -27,58 +17,49 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
Настройки видео
-
-
-
+
+
+ Разрешение
-
+
+
+ Настройки звука (заглушка)
+
+
+
+
+ Воспроизведение
+
+
+
+
+ Микрофон
+
+
+
-
+ Тон
-
+
-
+ Яркость
-
+
-
+ Насыщенность
-
+
-
-
-
-
-
-
-
-
-
- Посмотреть видео-превью
+ Контраст
@@ -166,7 +147,7 @@
ChatForm
-
+ Отправить файл
@@ -174,12 +155,23 @@
Core
-
+
+
+ Как-то так. Может, можно ещё что-нибудь придумать?
+ Всем привет из qTox'а
+
+
+
+
+ Пользователь qTox
+
+
+ Зашифрованный профиль
-
+ Похоже, ваш tox-профиль зашифрован, qTox не может открыть его
@@ -189,19 +181,19 @@ Do you want to erase this profile ?
FileTransferInstance
-
+ Title of the file saving dialogСохранить файл
-
+ Title of permissions popupНепригодная для записи локация
-
+ text of permissions popupУ вас нет прав записи в эту локацию. Выберете другую или закройте диалог сохранения.
@@ -267,40 +259,71 @@ Do you want to erase this profile ?
FriendWidget
-
+ Menu to copy the Tox ID of that friendКопировать ID друга
- Menu to invite a friend in a groupchat
+ Пригласить в группу
+
+
+
+
+ context menu entry
+ Автоматически принимать файлы от этого друга
+
+
+
+ context menu entry
+ Запретить принимать файлы автоматически
+
+
+
+
+ Menu to invite a friend to a groupchatПригласить в группу
-
+
+
+ context menu entry
+ Вручную принимать файлы от этого друга
+
+
+
+
+ context menu entry
+ Автоматически принимать файлы от всех друзей
+
+
+
+
+ context menu entry
+ Выключить глобальное автопринятие
+
+
+ Menu to remove the friend from our friendlistУдалить друга
+
+
+
+
+ popup title
+ Выбрать папку для автоматического приёма
+ GeneralForm
-
-
- Общие настройки
-
-
-
- title of bad port popup
- Неправильный порт
-
-
-
- text of bad port popup
- Введёный порт неверен; введите другой.
+
+
+ Общие
@@ -316,153 +339,154 @@ Do you want to erase this profile ?
Общие настройки
-
+
+
+
+ Перевод не изменится до перезапуска qTox.
+
+
+
+
+ Перевод:
+
+
+
+
+ Сворачивать в трей при закрытии
+
+
+
+
+ Сворачивать в трей
+
+
+
+
+ Укажите 0, чтобы отключить
+
+
+ Text on smiley pack label
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ Набор смайликов:
+
+ :)
+
+
+
+
+ ;)
+
+
+
+
+ :p
+
+
+
+
+ :O
+
+
+
-
+ :'(
-
+
-
+ Стиль:
-
+
-
+ Настройки соединения
-
+ Text on a checkbox to enable IPv6Включить IPv6 (рекомендуется)
-
+
-
+ Использовать прокси (SOCKS5)
-
+ Text on proxy addr label
-
+ Адрес
-
+ Text on proxy port label
-
+ Порт
-
-
- Text on a checkbox to enable translations
- Использовать перевод
-
-
-
+ describes makeToxPortable checkboxСохранять настройки в рабочую директорию вместо страндартной папки настроек
-
+ Портативный режим
-
+
-
+ Запускать в системном лотке
-
+
-
+ Показывать изменения статусов контактов
-
+
-
+ Выставлено в минутах
-
+
-
+ Автоматически отсутствовать после (0 для отключения):
-
+
-
+ минут
-
+ Тема
-
- Text on smiley pack label
- Набор смайликов
-
-
-
- Настройки прокси
-
-
-
+ Text on checkbox to disable UDPВыключить UDP (не рекомендуется)
-
+ force tcp checkbox tooltipЭто позволяет, например, использовать tox поверх Tor. Однако это добавляет нагрузку на сеть Tox, так что используйте только в случае необходимости.
-
-
- Text on proxy addr label
- Адрес прокси
-
-
-
- Text on proxy port label
- Порт прокси
- GenericChatForm
-
-
+
+ Сохранить лог чата
@@ -470,13 +494,13 @@ Do you want to erase this profile ?
GroupChatForm
-
+ Number of users in chat%1 пользователей в чате
-
+ %1 пользователей в чате
@@ -484,20 +508,20 @@ Do you want to erase this profile ?
GroupWidget
-
+ Menu to quit a groupchatПокинуть группу
-
-
+
+ %1 пользователей в чате
-
-
+
+ Ни одного пользователя в чате
@@ -505,87 +529,111 @@ Do you want to erase this profile ?
IdentityForm
-
-
- Ваша идентификация
+
+
+ Личность
-
+ popup title
-
+ Идёт звонок
-
+ popup text
-
+ Вы не можете переключить профиль, пока идёт звонок!
-
+ renaming a profile
-
+ Переименовать «%1»
-
+
+
+ rename confirm title
+ Профиль уже существует
+
+
+
+
+ rename confirm text
+ Профиль с именем «%1» уже существует. Желаете его стереть?
+
+
+ save dialog title
-
+ Экспортировать профиль
-
+ save dialog filter
-
+ Файл сохранения Tox (*.tox)
-
+ current profile deletion warning title
-
+ Профиль в настоящее время загружен
-
+ current profile deletion warning text
-
+ Этот профиль используется. Загрузите другой профиль, прежде чем удалять этот.
-
+ deletion confirmation title
-
+ Необратимое удаление!
-
+ deletion confirmation text
-
+ Вы действительно хотите удалить этот профиль?
-
+ import dialog title
-
+ Импортировать профиль
-
+ import dialog filter
-
+ Файл сохранения Tox (*.tox)
-
+ popup title
-
+ Игнорирование не-Tox файла
-
+ popup text
-
+ Внимание: вы выбрали не файл сохранения Tox; игнорирование.
+
+
+
+
+ import confirm title
+ Профиль уже существует
+
+
+
+
+ import confirm text
+ Профиль с именем «%1» уже существует. Желаете его стереть?
@@ -623,48 +671,54 @@ Do you want to erase this profile ?
-
+ Профили
-
+ Доступные профили:load profile button
-
+ Загрузитьrename profile button
-
+ Переименоватьexport profile button
-
+ Экспортироватьdelete profile button
-
+ Удалитьdelete profile button tooltip
-
+ Это полезно, чтобы оставаться в безопасности за общими компьютерами
-
+ import profile button
-
+ Импортировать профиль
+
+
+
+
+ new profile button
+ Новый Tox ID
@@ -719,122 +773,139 @@ Do you want to erase this profile ?
PrivacyForm
-
- Настройки приватности
-
-
-
- SelfCamView
-
-
- Title of the window to test the video/webcam
- Проверка видео
+
+ ЗащищённостьWidget
-
+
+
+ в сети
+
+
+
+
+ отошёл
+
+
+
+
+ занят
+
+
+
+
+ В&ыход
+
+
+
+
+ Сменить статус на:
+
+
+ Button to set your status to 'Online'В сети
-
+ Button to set your status to 'Away'Вероятно, это не столь долгое путешествиеОтошёл
-
+ Button to set your status to 'Busy'Занят
-
+
-
+ Выберите профиль
-
+
-
+ Выберите личность, которую хотите использовать
-
+ Выбрать картинку для профиля
-
-
-
+
+
+ Ошибка
-
+ Невозможно открыть файл
-
+ Невозможно прочесть это изображение
-
+ Это изображение слишком большое
-
+ Не удалось запустить toxcore, приложение будет завершено после того как вы закроете это сообщение.
-
+ popup textНе удалось запустить toxcore с вашими настройками прокси, qTox не может работать; измените ваши настройки и перезапустите его.
-
+ contact status
-
+ отсутствует
-
+ contact status
-
+ занят
-
+ contact status
-
+ офлайн
-
+ contact status
-
+ в сети
-
+ e.g. "Dubslow is now online"
-
+ %1 сейчас %2
-
+ Placeholder when we don't know someone's name in a group chat
- <Неизвестно>
+ <Неизвестный>
diff --git a/ui/chatArea/innerStyle.css b/ui/chatArea/innerStyle.css
index b5c537362..dc1f46d73 100644
--- a/ui/chatArea/innerStyle.css
+++ b/ui/chatArea/innerStyle.css
@@ -38,8 +38,8 @@ span.quote {
}
div.green {
- margin-top: 12px;
- margin-bottom: 12px;
+ margin-top: 6px;
+ margin-bottom: 6px;
margin-left: 0px;
margin-right: 0px;
color: @white;
@@ -48,8 +48,8 @@ div.green {
}
div.silver {
- margin-top: 12px;
- margin-bottom: 12px;
+ margin-top: 6px;
+ margin-bottom: 6px;
margin-left: 0px;
margin-right: 0px;
color: @black;
@@ -58,8 +58,8 @@ div.silver {
}
div.red {
- margin-top: 12px;
- margin-bottom: 12px;
+ margin-top: 6px;
+ margin-bottom: 6px;
margin-left: 0px;
margin-right: 0px;
color: @white;
@@ -67,6 +67,20 @@ div.red {
font: @small;
}
+div.alert {
+ margin-left: 0px;
+ margin-right: 0px;
+ color: @black;
+ background-color: @orange;
+ font: @big;
+}
+
+div.alert_name {
+ color: @black;
+ background-color: @orange;
+ font: @bigBold;
+}
+
div.button {
margin-top: 0px;
margin-bottom: 0px;