diff --git a/src/chatlog/chatlog.cpp b/src/chatlog/chatlog.cpp index 528e9a9ee..baceb7555 100644 --- a/src/chatlog/chatlog.cpp +++ b/src/chatlog/chatlog.cpp @@ -15,6 +15,7 @@ #include "chatlog.h" #include "chatmessage.h" #include "chatlinecontent.h" +#include "src/translator.h" #include #include @@ -61,7 +62,6 @@ ChatLog::ChatLog(QWidget* parent) // copy action (ie. Ctrl+C) copyAction = new QAction(this); copyAction->setIcon(QIcon::fromTheme("edit-copy")); - copyAction->setText(tr("Copy")); copyAction->setShortcut(QKeySequence::Copy); copyAction->setEnabled(false); connect(copyAction, &QAction::triggered, this, [this]() { copySelectedText(); }); @@ -74,9 +74,8 @@ ChatLog::ChatLog(QWidget* parent) #endif // select all action (ie. Ctrl+A) - QAction* selectAllAction = new QAction(this); + selectAllAction = new QAction(this); selectAllAction->setIcon(QIcon::fromTheme("edit-select-all")); - selectAllAction->setText(tr("Select all")); selectAllAction->setShortcut(QKeySequence::SelectAll); connect(selectAllAction, &QAction::triggered, this, [this]() { selectAll(); }); addAction(selectAllAction); @@ -103,10 +102,15 @@ ChatLog::ChatLog(QWidget* parent) copySelectedText(true); #endif }); + + retranslateUi(); + Translator::registerHandler(std::bind(&ChatLog::retranslateUi, this), this); } ChatLog::~ChatLog() { + Translator::unregister(this); + // Remove chatlines from scene for (ChatLine::Ptr l : lines) l->removeFromScene(); @@ -812,3 +816,9 @@ void ChatLog::focusOutEvent(QFocusEvent* ev) lines[i]->selectionFocusChanged(false); } } + +void ChatLog::retranslateUi() +{ + copyAction->setText(tr("Copy")); + selectAllAction->setText(tr("Select all")); +} diff --git a/src/chatlog/chatlog.h b/src/chatlog/chatlog.h index 9350fae15..f62c603ec 100644 --- a/src/chatlog/chatlog.h +++ b/src/chatlog/chatlog.h @@ -99,6 +99,9 @@ private slots: void onSelectionTimerTimeout(); void onWorkerTimeout(); +private: + void retranslateUi(); + private: enum SelectionMode { None, @@ -113,6 +116,7 @@ private: }; QAction* copyAction = nullptr; + QAction* selectAllAction = nullptr; QGraphicsScene* scene = nullptr; QGraphicsScene* busyScene = nullptr; QVector lines; @@ -141,9 +145,6 @@ private: // layout QMargins margins = QMargins(10,10,10,10); qreal lineSpacing = 5.0f; - - - }; #endif // CHATLOG_H diff --git a/src/translator.cpp b/src/translator.cpp index 252015e14..8d1e2d593 100644 --- a/src/translator.cpp +++ b/src/translator.cpp @@ -6,11 +6,16 @@ #include #include #include +#include QTranslator* Translator::translator{nullptr}; +QVector>> Translator::callbacks; +QMutex Translator::lock; void Translator::translate() { + QMutexLocker locker{&lock}; + if (!translator) translator = new QTranslator(); @@ -20,29 +25,51 @@ void Translator::translate() if ((locale = Settings::getInstance().getTranslation()).isEmpty()) locale = QLocale::system().name().section('_', 0, 0); - if (locale == "en") - return; - - if (translator->load(locale, ":translations/")) + if (locale != "en") { - qDebug() << "Loaded translation" << locale; - - // system menu translation - QTranslator *qtTranslator = new QTranslator(); - QString s_locale = "qt_"+locale; - if (qtTranslator->load(s_locale, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) + if (translator->load(locale, ":translations/")) { - QApplication::installTranslator(qtTranslator); - qDebug() << "System translation loaded" << locale; + qDebug() << "Loaded translation" << locale; + + // system menu translation + QTranslator *qtTranslator = new QTranslator(); + QString s_locale = "qt_"+locale; + if (qtTranslator->load(s_locale, QLibraryInfo::location(QLibraryInfo::TranslationsPath))) + { + QApplication::installTranslator(qtTranslator); + qDebug() << "System translation loaded" << locale; + } + else + { + qDebug() << "System translation not loaded" << locale; + } } else { - qDebug() << "System translation not loaded" << locale; + qDebug() << "Error loading translation" << locale; + } + QCoreApplication::installTranslator(translator); + } + + for (auto pair : callbacks) + pair.second(); +} + +void Translator::registerHandler(std::function f, void *owner) +{ + QMutexLocker locker{&lock}; + callbacks.push_back({owner, f}); +} + +void Translator::unregister(void *owner) +{ + QMutexLocker locker{&lock}; + for (int i=0; i +#include +#include +#include + class QTranslator; class Translator @@ -8,9 +13,15 @@ class Translator public: /// Loads the translations according to the settings or locale static void translate(); + /// Register a function to be called when the UI needs to be retranslated + static void registerHandler(std::function, void* owner); + /// Unregisters all handlers of an owner + static void unregister(void* owner); private: static QTranslator* translator; + static QVector>> callbacks; + static QMutex lock; }; #endif // TRANSLATOR_H diff --git a/src/widget/form/addfriendform.cpp b/src/widget/form/addfriendform.cpp index 5c1ba25d5..48f35aeba 100644 --- a/src/widget/form/addfriendform.cpp +++ b/src/widget/form/addfriendform.cpp @@ -26,18 +26,16 @@ #include "src/toxdns.h" #include "src/misc/settings.h" #include "src/widget/gui.h" +#include "src/translator.h" AddFriendForm::AddFriendForm() { main = new QWidget(), head = new QWidget(); QFont bold; bold.setBold(true); - headLabel.setText(tr("Add Friends")); headLabel.setFont(bold); - toxIdLabel.setText(tr("Tox ID","Tox ID of the person you're sending a friend request to")); - messageLabel.setText(tr("Message","The message you send in friend requests")); - sendButton.setText(tr("Send friend request")); + retranslateUi(); main->setLayout(&layout); layout.addWidget(&toxIdLabel); @@ -52,10 +50,13 @@ AddFriendForm::AddFriendForm() connect(&toxId,&QLineEdit::returnPressed, this, &AddFriendForm::onSendTriggered); connect(&sendButton, SIGNAL(clicked()), this, SLOT(onSendTriggered())); connect(Nexus::getCore(), &Core::usernameSet, this, &AddFriendForm::onUsernameSet); + + Translator::registerHandler(std::bind(&AddFriendForm::retranslateUi, this), this); } AddFriendForm::~AddFriendForm() { + Translator::unregister(this); head->deleteLater(); main->deleteLater(); } @@ -78,7 +79,8 @@ QString AddFriendForm::getMessage() const void AddFriendForm::onUsernameSet(const QString& username) { - message.setPlaceholderText(tr("%1 here! Tox me maybe?","Default message in friend requests if the field is left blank. Write something appropriate!").arg(username)); + lastUsername = username; + retranslateUi(); } void AddFriendForm::onSendTriggered() @@ -133,3 +135,14 @@ void AddFriendForm::setIdFromClipboard() toxId.setText(id); } } + +void AddFriendForm::retranslateUi() +{ + headLabel.setText(tr("Add Friends")); + toxIdLabel.setText(tr("Tox ID","Tox ID of the person you're sending a friend request to")); + messageLabel.setText(tr("Message","The message you send in friend requests")); + sendButton.setText(tr("Send friend request")); + message.setPlaceholderText(tr("%1 here! Tox me maybe?", + "Default message in friend requests if the field is left blank. Write something appropriate!") + .arg(lastUsername)); +} diff --git a/src/widget/form/addfriendform.h b/src/widget/form/addfriendform.h index 5136b9dd1..61c856126 100644 --- a/src/widget/form/addfriendform.h +++ b/src/widget/form/addfriendform.h @@ -42,6 +42,9 @@ public slots: private slots: void onSendTriggered(); +private: + void retranslateUi(); + private: void setIdFromClipboard(); QLabel headLabel, toxIdLabel, messageLabel; @@ -50,6 +53,7 @@ private: QTextEdit message; QVBoxLayout layout, headLayout; QWidget *head, *main; + QString lastUsername; // Cached username so we can retranslate the invite message }; #endif // ADDFRIENDFORM_H diff --git a/src/widget/form/chatform.cpp b/src/widget/form/chatform.cpp index 5f4ec0d89..194783fb1 100644 --- a/src/widget/form/chatform.cpp +++ b/src/widget/form/chatform.cpp @@ -47,6 +47,7 @@ #include "src/offlinemsgengine.h" #include "src/widget/tool/screenshotgrabber.h" #include "src/widget/tool/flyoutoverlaywidget.h" +#include "src/translator.h" ChatForm::ChatForm(Friend* chatFriend) : f(chatFriend) @@ -79,7 +80,7 @@ ChatForm::ChatForm(Friend* chatFriend) headTextLayout->addWidget(callDuration, 1, Qt::AlignCenter); callDuration->hide(); - menu.addAction(QObject::tr("Load chat history..."), this, SLOT(onLoadHistory())); + loadHistoryAction = menu.addAction(QString(), this, SLOT(onLoadHistory())); connect(Core::getInstance(), &Core::fileSendStarted, this, &ChatForm::startFileSend); connect(sendButton, &QPushButton::clicked, this, &ChatForm::onSendTriggered); @@ -100,10 +101,14 @@ ChatForm::ChatForm(Friend* chatFriend) } ); setAcceptDrops(true); + + retranslateUi(); + Translator::registerHandler(std::bind(&ChatForm::retranslateUi, this), this); } ChatForm::~ChatForm() { + Translator::unregister(this); delete netcam; delete callConfirm; delete offlineEngine; @@ -1049,3 +1054,8 @@ void ChatForm::hideNetcam() delete netcam; netcam = nullptr; } + +void ChatForm::retranslateUi() +{ + loadHistoryAction->setText(tr("Load chat history...")); +} diff --git a/src/widget/form/chatform.h b/src/widget/form/chatform.h index 03999b1e1..5b9001a72 100644 --- a/src/widget/form/chatform.h +++ b/src/widget/form/chatform.h @@ -96,6 +96,9 @@ private slots: void onScreenshotTaken(const QPixmap &pixmap); void doScreenshot(); +private: + void retranslateUi(); + protected: void showNetcam(); void hideNetcam(); @@ -116,6 +119,7 @@ private: QTimer *disableCallButtonsTimer; QElapsedTimer timeElapsed; OfflineMsgEngine *offlineEngine; + QAction* loadHistoryAction; QHash ftransWidgets; void startCounter(); diff --git a/src/widget/form/filesform.cpp b/src/widget/form/filesform.cpp index 224b4dac7..b0b8866b4 100644 --- a/src/widget/form/filesform.cpp +++ b/src/widget/form/filesform.cpp @@ -15,6 +15,7 @@ #include "filesform.h" #include "ui_mainwindow.h" #include "src/widget/widget.h" +#include "src/translator.h" #include #include #include @@ -26,7 +27,6 @@ FilesForm::FilesForm() head = new QWidget(); QFont bold; bold.setBold(true); - headLabel.setText(tr("Transfered Files","\"Headline\" of the window")); headLabel.setFont(bold); head->setLayout(&headLayout); headLayout.addWidget(&headLabel); @@ -34,16 +34,19 @@ FilesForm::FilesForm() recvd = new QListWidget; sent = new QListWidget; - main.addTab(recvd, tr("Downloads")); - main.addTab(sent, tr("Uploads")); + main.addTab(recvd, QString()); + main.addTab(sent, QString()); connect(sent, SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(onFileActivated(QListWidgetItem*))); connect(recvd, SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(onFileActivated(QListWidgetItem*))); + retranslateUi(); + Translator::registerHandler(std::bind(&FilesForm::retranslateUi, this), this); } FilesForm::~FilesForm() { + Translator::unregister(this); delete recvd; delete sent; head->deleteLater(); @@ -82,3 +85,10 @@ void FilesForm::onFileActivated(QListWidgetItem* item) Widget::confirmExecutableOpen(QFileInfo(tmp->path)); } + +void FilesForm::retranslateUi() +{ + headLabel.setText(tr("Transfered Files","\"Headline\" of the window")); + main.setTabText(0, tr("Downloads")); + main.setTabText(1, tr("Uploads")); +} diff --git a/src/widget/form/filesform.h b/src/widget/form/filesform.h index 524627dd9..c67a656c9 100644 --- a/src/widget/form/filesform.h +++ b/src/widget/form/filesform.h @@ -41,6 +41,9 @@ public slots: private slots: void onFileActivated(QListWidgetItem* item); +private: + void retranslateUi(); + private: QWidget* head; QLabel headLabel; diff --git a/src/widget/form/genericchatform.cpp b/src/widget/form/genericchatform.cpp index c02d28828..97a2040e2 100644 --- a/src/widget/form/genericchatform.cpp +++ b/src/widget/form/genericchatform.cpp @@ -35,6 +35,7 @@ #include "src/chatlog/chatlog.h" #include "src/chatlog/content/timestamp.h" #include "src/widget/tool/flyoutoverlaywidget.h" +#include "src/translator.h" GenericChatForm::GenericChatForm(QWidget *parent) : QWidget(parent) @@ -69,21 +70,15 @@ GenericChatForm::GenericChatForm(QWidget *parent) msgEdit = new ChatTextEdit(); sendButton = new QPushButton(); - sendButton->setToolTip(tr("Send message")); emoteButton = new QPushButton(); - emoteButton->setToolTip(tr("Smileys")); // Setting the sizes in the CSS doesn't work (glitch with high DPIs) fileButton = new QPushButton(); - fileButton->setToolTip(tr("Send file(s)")); screenshotButton = new QPushButton; - screenshotButton->setToolTip(tr("Send a screenshot")); callButton = new QPushButton(); callButton->setFixedSize(50,40); - callButton->setToolTip(tr("Start an audio call")); videoButton = new QPushButton(); videoButton->setFixedSize(50,40); - videoButton->setToolTip(tr("Start a video call")); volButton = new QPushButton(); //volButton->setFixedSize(25,20); volButton->setToolTip(""); @@ -172,8 +167,8 @@ GenericChatForm::GenericChatForm(QWidget *parent) menu.addActions(chatWidget->actions()); menu.addSeparator(); - menu.addAction(QIcon::fromTheme("document-save"), tr("Save chat log"), this, SLOT(onSaveLogClicked())); - menu.addAction(QIcon::fromTheme("edit-clear"), tr("Clear displayed messages"), this, SLOT(clearChatArea(bool))); + saveChatAction = menu.addAction(QIcon::fromTheme("document-save"), QString(), this, SLOT(onSaveLogClicked())); + clearAction = menu.addAction(QIcon::fromTheme("edit-clear"), QString(), this, SLOT(clearChatArea(bool))); menu.addSeparator(); connect(emoteButton, &QPushButton::clicked, this, &GenericChatForm::onEmoteButtonClicked); @@ -188,6 +183,14 @@ GenericChatForm::GenericChatForm(QWidget *parent) fileFlyout->setParent(this); fileButton->installEventFilter(this); fileFlyout->installEventFilter(this); + + retranslateUi(); + Translator::registerHandler(std::bind(&GenericChatForm::retranslateUi, this), this); +} + +GenericChatForm::~GenericChatForm() +{ + Translator::unregister(this); } void GenericChatForm::adjustFileMenuPosition() @@ -459,3 +462,15 @@ bool GenericChatForm::eventFilter(QObject* object, QEvent* event) return false; } + +void GenericChatForm::retranslateUi() +{ + sendButton->setToolTip(tr("Send message")); + emoteButton->setToolTip(tr("Smileys")); + fileButton->setToolTip(tr("Send file(s)")); + screenshotButton->setToolTip(tr("Send a screenshot")); + callButton->setToolTip(tr("Start an audio call")); + videoButton->setToolTip(tr("Start a video call")); + saveChatAction->setText(tr("Save chat log")); + clearAction->setText(tr("Clear displayed messages")); +} diff --git a/src/widget/form/genericchatform.h b/src/widget/form/genericchatform.h index d97185309..34f914c90 100644 --- a/src/widget/form/genericchatform.h +++ b/src/widget/form/genericchatform.h @@ -45,6 +45,7 @@ class GenericChatForm : public QWidget Q_OBJECT public: GenericChatForm(QWidget *parent = 0); + ~GenericChatForm(); virtual void setName(const QString &newName); virtual void show(Ui::MainWindow &ui); @@ -79,6 +80,9 @@ protected slots: void showFileMenu(); void hideFileMenu(); +private: + void retranslateUi(); + protected: QString resolveToxId(const ToxId &id); void insertChatMessage(ChatMessage::Ptr msg); @@ -86,6 +90,7 @@ protected: void resizeEvent(QResizeEvent* event); void adjustFileMenuPosition(); + QAction* saveChatAction, *clearAction; ToxId previousId; QDateTime prevMsgDateTime; Widget *parent; diff --git a/src/widget/form/groupchatform.cpp b/src/widget/form/groupchatform.cpp index ab6411a00..1786c332d 100644 --- a/src/widget/form/groupchatform.cpp +++ b/src/widget/form/groupchatform.cpp @@ -21,13 +21,14 @@ #include "src/widget/maskablepixmapwidget.h" #include "src/core/core.h" #include "src/misc/style.h" +#include "src/historykeeper.h" +#include "src/misc/flowlayout.h" +#include "src/translator.h" +#include +#include #include #include #include -#include "src/historykeeper.h" -#include "src/misc/flowlayout.h" -#include -#include GroupChatForm::GroupChatForm(Group* chatGroup) : group(chatGroup), inCall{false} @@ -53,8 +54,8 @@ GroupChatForm::GroupChatForm(Group* chatGroup) nameLabel->setText(group->getGroupWidget()->getName()); nusersLabel->setFont(Style::getFont(Style::Medium)); - nusersLabel->setText(GroupChatForm::tr("%1 users in chat","Number of users in chat").arg(group->getPeersCount())); nusersLabel->setObjectName("statusLabel"); + retranslateUi(); avatar->setPixmap(Style::scaleSvgImage(":/img/group_dark.svg", avatar->width(), avatar->height()), Qt::transparent); @@ -88,6 +89,12 @@ GroupChatForm::GroupChatForm(Group* chatGroup) {if (text != orig) emit groupTitleChanged(group->getGroupId(), text.left(128));} ); setAcceptDrops(true); + Translator::registerHandler(std::bind(&GroupChatForm::retranslateUi, this), this); +} + +GroupChatForm::~GroupChatForm() +{ + Translator::unregister(this); } void GroupChatForm::onSendTriggered() @@ -319,3 +326,8 @@ void GroupChatForm::keyReleaseEvent(QKeyEvent* ev) if (msgEdit->hasFocus()) return; } + +void GroupChatForm::retranslateUi() +{ + nusersLabel->setText(GroupChatForm::tr("%1 users in chat","Number of users in chat").arg(group->getPeersCount())); +} diff --git a/src/widget/form/groupchatform.h b/src/widget/form/groupchatform.h index ef0ce7bea..ac3d964da 100644 --- a/src/widget/form/groupchatform.h +++ b/src/widget/form/groupchatform.h @@ -29,6 +29,7 @@ class GroupChatForm : public GenericChatForm Q_OBJECT public: GroupChatForm(Group* chatGroup); + ~GroupChatForm(); void onUserListChanged(); void peerAudioPlaying(int peer); @@ -50,6 +51,9 @@ protected: void dragEnterEvent(QDragEnterEvent* ev); void dropEvent(QDropEvent* ev); +private: + void retranslateUi(); + private: Group* group; QList peerLabels; // maps peernumbers to the QLabels in namesListLayout diff --git a/src/widget/form/profileform.cpp b/src/widget/form/profileform.cpp index 58ab70e63..a146f6a56 100644 --- a/src/widget/form/profileform.cpp +++ b/src/widget/form/profileform.cpp @@ -28,6 +28,7 @@ #include "src/misc/style.h" #include "src/profilelocker.h" #include "src/profile.h" +#include "src/translator.h" #include #include #include @@ -51,14 +52,13 @@ ProfileForm::ProfileForm(QWidget *parent) : QLabel* imgLabel = new QLabel(); headLayout->addWidget(imgLabel); - QLabel* nameLabel = new QLabel(); + nameLabel = new QLabel(); QFont bold; bold.setBold(true); nameLabel->setFont(bold); headLayout->addWidget(nameLabel); headLayout->addStretch(1); - nameLabel->setText(QObject::tr("User Profile")); imgLabel->setPixmap(QPixmap(":/img/settings/identity.png").scaledToHeight(40, Qt::SmoothTransformation)); // tox @@ -106,10 +106,14 @@ ProfileForm::ProfileForm(QWidget *parent) : cb->installEventFilter(this); cb->setFocusPolicy(Qt::StrongFocus); } + + retranslateUi(); + Translator::registerHandler(std::bind(&ProfileForm::retranslateUi, this), this); } ProfileForm::~ProfileForm() { + Translator::unregister(this); delete qr; delete bodyUI; head->deleteLater(); @@ -336,3 +340,11 @@ void ProfileForm::onChangePassClicked() QString newPass = dialog->getPassword(); Nexus::getProfile()->setPassword(newPass); } + +void ProfileForm::retranslateUi() +{ + bodyUI->retranslateUi(this); + nameLabel->setText(QObject::tr("User Profile")); + // We have to add the toxId tooltip here and not in the .ui or Qt won't know how to translate it dynamically + toxId->setToolTip(tr("This bunch of characters tells other Tox clients how to contact you.\nShare it with your friends to communicate.")); +} diff --git a/src/widget/form/profileform.h b/src/widget/form/profileform.h index 60d5da37e..b778960a4 100644 --- a/src/widget/form/profileform.h +++ b/src/widget/form/profileform.h @@ -72,16 +72,19 @@ private slots: void onDeletePassClicked(); void onChangePassClicked(); +private: + void retranslateUi(); + private: void refreshProfiles(); Ui::IdentitySettings* bodyUI; MaskablePixmapWidget* profilePicture; + QLabel* nameLabel; QWidget *head; Core* core; QTimer timer; bool hasCheck = false; QRWidget *qr; - ClickableTE* toxId; }; diff --git a/src/widget/form/profileform.ui b/src/widget/form/profileform.ui index 2149f2779..239f76f3b 100644 --- a/src/widget/form/profileform.ui +++ b/src/widget/form/profileform.ui @@ -39,7 +39,7 @@ 0 0 - 630 + 579 625 @@ -104,21 +104,13 @@ Share it with your friends to communicate. - - - This bunch of characters tells other Tox clients how to contact you. -Share it with your friends to communicate. - - + - - QRCODE - Qt::AlignCenter diff --git a/src/widget/form/settings/advancedform.cpp b/src/widget/form/settings/advancedform.cpp index 2a63e8413..525b37393 100644 --- a/src/widget/form/settings/advancedform.cpp +++ b/src/widget/form/settings/advancedform.cpp @@ -18,9 +18,10 @@ #include "src/historykeeper.h" #include "src/misc/settings.h" #include "src/misc/db/plaindb.h" +#include "src/translator.h" AdvancedForm::AdvancedForm() : - GenericForm(tr("Advanced"), QPixmap(":/img/settings/general.png")) + GenericForm(QPixmap(":/img/settings/general.png")) { bodyUI = new Ui::AdvancedSettings; bodyUI->setupUi(this); @@ -46,10 +47,13 @@ AdvancedForm::AdvancedForm() : cb->installEventFilter(this); cb->setFocusPolicy(Qt::StrongFocus); } + + Translator::registerHandler(std::bind(&AdvancedForm::retranslateUi, this), this); } AdvancedForm::~AdvancedForm() { + Translator::unregister(this); delete bodyUI; } @@ -82,3 +86,8 @@ bool AdvancedForm::eventFilter(QObject *o, QEvent *e) } return QWidget::eventFilter(o, e); } + +void AdvancedForm::retranslateUi() +{ + bodyUI->retranslateUi(this); +} diff --git a/src/widget/form/settings/advancedform.h b/src/widget/form/settings/advancedform.h index fb6802d6b..b00f9abf5 100644 --- a/src/widget/form/settings/advancedform.h +++ b/src/widget/form/settings/advancedform.h @@ -29,6 +29,7 @@ class AdvancedForm : public GenericForm public: AdvancedForm(); virtual ~AdvancedForm(); + QString getFormName() final {return tr("Advanced");} protected: bool eventFilter(QObject *o, QEvent *e); @@ -38,6 +39,9 @@ private slots: void onDbSyncTypeUpdated(); void resetToDefault(); +private: + void retranslateUi(); + private: Ui::AdvancedSettings* bodyUI; }; diff --git a/src/widget/form/settings/avform.cpp b/src/widget/form/settings/avform.cpp index 4e75c58d6..74dbf9d24 100644 --- a/src/widget/form/settings/avform.cpp +++ b/src/widget/form/settings/avform.cpp @@ -19,6 +19,7 @@ #include "src/video/camerasource.h" #include "src/video/cameradevice.h" #include "src/widget/videosurface.h" +#include "src/translator.h" #if defined(__APPLE__) && defined(__MACH__) #include @@ -35,7 +36,7 @@ #endif AVForm::AVForm() : - GenericForm(tr("Audio/Video"), QPixmap(":/img/settings/av.png")), + GenericForm(QPixmap(":/img/settings/av.png")), camVideoSurface{nullptr}, camera{nullptr} { bodyUI = new Ui::AVSettings; @@ -62,10 +63,13 @@ AVForm::AVForm() : cb->installEventFilter(this); cb->setFocusPolicy(Qt::StrongFocus); } + + Translator::registerHandler(std::bind(&AVForm::retranslateUi, this), this); } AVForm::~AVForm() { + Translator::unregister(this); delete bodyUI; if (camera) { @@ -387,3 +391,8 @@ void AVForm::killVideoSurface() delete camVideoSurface; camVideoSurface = nullptr; } + +void AVForm::retranslateUi() +{ + bodyUI->retranslateUi(this); +} diff --git a/src/widget/form/settings/avform.h b/src/widget/form/settings/avform.h index a4a458a91..2fd931664 100644 --- a/src/widget/form/settings/avform.h +++ b/src/widget/form/settings/avform.h @@ -16,6 +16,7 @@ #define AVFORM_H #include +#include #include #include "genericsettings.h" #include "src/video/videomode.h" @@ -33,6 +34,7 @@ class AVForm : public GenericForm public: AVForm(); ~AVForm(); + QString getFormName() final {return tr("Audio/Video");} private: void getAudioInDevices(); @@ -42,6 +44,8 @@ private: void createVideoSurface(); void killVideoSurface(); + void retranslateUi(); + private slots: void on_videoModescomboBox_currentIndexChanged(int index); diff --git a/src/widget/form/settings/generalform.cpp b/src/widget/form/settings/generalform.cpp index e21adc717..7e9b9e8fa 100644 --- a/src/widget/form/settings/generalform.cpp +++ b/src/widget/form/settings/generalform.cpp @@ -40,7 +40,7 @@ static QStringList timeFormats = {"hh:mm AP", "hh:mm", "hh:mm:ss AP", "hh:mm:ss" static QStringList dateFormats = {"yyyy-MM-dd", "dd-MM-yyyy", "d-MM-yyyy", "dddd d-MM-yyyy", "dddd d-MM", "dddd dd MMMM"}; GeneralForm::GeneralForm(SettingsWidget *myParent) : - GenericForm(tr("General"), QPixmap(":/img/settings/general.png")) + GenericForm(QPixmap(":/img/settings/general.png")) { parent = myParent; @@ -197,10 +197,13 @@ GeneralForm::GeneralForm(SettingsWidget *myParent) : bodyUI->autoAwayLabel->setEnabled(false); // these don't seem to change the appearance of the widgets, bodyUI->autoAwaySpinBox->setEnabled(false); // though they are unusable #endif + + Translator::registerHandler(std::bind(&GeneralForm::retranslateUi, this), this); } GeneralForm::~GeneralForm() { + Translator::unregister(this); delete bodyUI; } @@ -444,3 +447,8 @@ bool GeneralForm::eventFilter(QObject *o, QEvent *e) } return QWidget::eventFilter(o, e); } + +void GeneralForm::retranslateUi() +{ + bodyUI->retranslateUi(this); +} diff --git a/src/widget/form/settings/generalform.h b/src/widget/form/settings/generalform.h index c1b9bce04..c60d057b0 100644 --- a/src/widget/form/settings/generalform.h +++ b/src/widget/form/settings/generalform.h @@ -29,6 +29,7 @@ class GeneralForm : public GenericForm public: GeneralForm(SettingsWidget *parent); ~GeneralForm(); + QString getFormName() final {return tr("General");} private slots: void onEnableIPv6Updated(); @@ -64,6 +65,9 @@ private slots: void onGroupchatPositionChanged(); void onThemeColorChanged(int); +private: + void retranslateUi(); + private: Ui::GeneralSettings *bodyUI; void reloadSmiles(); diff --git a/src/widget/form/settings/genericsettings.h b/src/widget/form/settings/genericsettings.h index 0bd284a15..84e2a5599 100644 --- a/src/widget/form/settings/genericsettings.h +++ b/src/widget/form/settings/genericsettings.h @@ -21,14 +21,13 @@ class GenericForm : public QWidget { Q_OBJECT public: - GenericForm(const QString &name, const QPixmap &icon) : formName(name), formIcon(icon) {;} + GenericForm(const QPixmap &icon) : formIcon(icon) {;} ~GenericForm() {;} - QString getFormName() {return formName;} + virtual QString getFormName() = 0; QPixmap getFormIcon() {return formIcon;} protected: - QString formName; QPixmap formIcon; }; diff --git a/src/widget/form/settings/privacyform.cpp b/src/widget/form/settings/privacyform.cpp index 0c2c4006c..ff6345eba 100644 --- a/src/widget/form/settings/privacyform.cpp +++ b/src/widget/form/settings/privacyform.cpp @@ -21,12 +21,13 @@ #include "src/widget/widget.h" #include "src/widget/gui.h" #include "src/widget/form/setpassworddialog.h" +#include "src/translator.h" #include #include #include PrivacyForm::PrivacyForm() : - GenericForm(tr("Privacy"), QPixmap(":/img/settings/privacy.png")) + GenericForm(QPixmap(":/img/settings/privacy.png")) { bodyUI = new Ui::PrivacySettings; bodyUI->setupUi(this); @@ -36,10 +37,13 @@ PrivacyForm::PrivacyForm() : connect(bodyUI->nospamLineEdit, SIGNAL(editingFinished()), this, SLOT(setNospam())); connect(bodyUI->randomNosapamButton, SIGNAL(clicked()), this, SLOT(generateRandomNospam())); connect(bodyUI->nospamLineEdit, SIGNAL(textChanged(QString)), this, SLOT(onNospamEdit())); + + Translator::registerHandler(std::bind(&PrivacyForm::retranslateUi, this), this); } PrivacyForm::~PrivacyForm() { + Translator::unregister(this); delete bodyUI; } @@ -96,3 +100,8 @@ void PrivacyForm::onNospamEdit() bodyUI->nospamLineEdit->setCursorPosition(curs); }; } + +void PrivacyForm::retranslateUi() +{ + bodyUI->retranslateUi(this); +} diff --git a/src/widget/form/settings/privacyform.h b/src/widget/form/settings/privacyform.h index 2feaf41a0..e1afa2823 100644 --- a/src/widget/form/settings/privacyform.h +++ b/src/widget/form/settings/privacyform.h @@ -27,6 +27,7 @@ class PrivacyForm : public GenericForm public: PrivacyForm(); ~PrivacyForm(); + QString getFormName() final {return tr("Privacy");} private slots: void onEnableLoggingUpdated(); @@ -36,6 +37,9 @@ private slots: void onNospamEdit(); virtual void showEvent(QShowEvent*); +private: + void retranslateUi(); + private: Ui::PrivacySettings* bodyUI; }; diff --git a/src/widget/form/settingswidget.cpp b/src/widget/form/settingswidget.cpp index d524bfa41..b6fdad079 100644 --- a/src/widget/form/settingswidget.cpp +++ b/src/widget/form/settingswidget.cpp @@ -20,6 +20,7 @@ #include "src/widget/form/settings/privacyform.h" #include "src/widget/form/settings/avform.h" #include "src/widget/form/settings/advancedform.h" +#include "src/translator.h" #include SettingsWidget::SettingsWidget(QWidget* parent) @@ -53,15 +54,18 @@ SettingsWidget::SettingsWidget(QWidget* parent) AVForm* avfrm = new AVForm; AdvancedForm *expfrm = new AdvancedForm; - GenericForm* cfgForms[] = { gfrm, pfrm, avfrm, expfrm }; + cfgForms = {{ gfrm, pfrm, avfrm, expfrm }}; for (GenericForm* cfgForm : cfgForms) settingsWidgets->addTab(cfgForm, cfgForm->getFormIcon(), cfgForm->getFormName()); connect(settingsWidgets, &QTabWidget::currentChanged, this, &SettingsWidget::onTabChanged); + + Translator::registerHandler(std::bind(&SettingsWidget::retranslateUi, this), this); } SettingsWidget::~SettingsWidget() { + Translator::unregister(this); } void SettingsWidget::setBodyHeadStyle(QString style) @@ -86,3 +90,11 @@ void SettingsWidget::onTabChanged(int index) nameLabel->setText(currentWidget->getFormName()); imgLabel->setPixmap(currentWidget->getFormIcon().scaledToHeight(40, Qt::SmoothTransformation)); } + +void SettingsWidget::retranslateUi() +{ + GenericForm* currentWidget = static_cast(settingsWidgets->currentWidget()); + nameLabel->setText(currentWidget->getFormName()); + for (size_t i=0; isetTabText(i, cfgForms[i]->getFormName()); +} diff --git a/src/widget/form/settingswidget.h b/src/widget/form/settingswidget.h index 4aa7b73bf..ca8c1383d 100644 --- a/src/widget/form/settingswidget.h +++ b/src/widget/form/settingswidget.h @@ -18,6 +18,7 @@ #include #include #include +#include class Camera; class GenericForm; @@ -47,10 +48,15 @@ signals: private slots: void onTabChanged(int); +private: + void retranslateUi(); + private: QWidget *head, *body; QTabWidget *settingsWidgets; QLabel *nameLabel, *imgLabel; + std::array cfgForms; + int currentIndex; }; #endif // SETTINGSWIDGET_H diff --git a/src/widget/loginscreen.cpp b/src/widget/loginscreen.cpp index dbaa5e870..047ad1b72 100644 --- a/src/widget/loginscreen.cpp +++ b/src/widget/loginscreen.cpp @@ -5,6 +5,7 @@ #include "src/nexus.h" #include "src/misc/settings.h" #include "src/widget/form/setpassworddialog.h" +#include "src/translator.h" #include #include @@ -30,10 +31,13 @@ LoginScreen::LoginScreen(QWidget *parent) : connect(ui->autoLoginCB, &QCheckBox::stateChanged, this, &LoginScreen::onAutoLoginToggled); reset(); + retranslateUi(); + Translator::registerHandler(std::bind(&LoginScreen::retranslateUi, this), this); } LoginScreen::~LoginScreen() { + Translator::unregister(this); delete ui; } @@ -47,7 +51,7 @@ void LoginScreen::reset() Profile::scanProfiles(); QString lastUsed = Settings::getInstance().getCurrentProfile(); - qDebug() << "Last used is "< profiles = Profile::getProfiles(); for (QString profile : profiles) { @@ -187,3 +191,8 @@ void LoginScreen::onAutoLoginToggled(int state) Settings::getInstance().save(false); } + +void LoginScreen::retranslateUi() +{ + ui->retranslateUi(this); +} diff --git a/src/widget/loginscreen.h b/src/widget/loginscreen.h index 4bb53d6cc..0e5b23833 100644 --- a/src/widget/loginscreen.h +++ b/src/widget/loginscreen.h @@ -28,6 +28,9 @@ private slots: void onCreateNewProfile(); void onLogin(); +private: + void retranslateUi(); + private: Ui::LoginScreen *ui; QShortcut quitShortcut; diff --git a/src/widget/tool/chattextedit.cpp b/src/widget/tool/chattextedit.cpp index 02042111e..a1a2a757a 100644 --- a/src/widget/tool/chattextedit.cpp +++ b/src/widget/tool/chattextedit.cpp @@ -13,13 +13,21 @@ */ #include "chattextedit.h" +#include "src/translator.h" #include ChatTextEdit::ChatTextEdit(QWidget *parent) : QTextEdit(parent) { - setPlaceholderText(tr("Type your message here...")); + retranslateUi(); setAcceptRichText(false); + + Translator::registerHandler(std::bind(&ChatTextEdit::retranslateUi, this), this); +} + +ChatTextEdit::~ChatTextEdit() +{ + Translator::unregister(this); } void ChatTextEdit::keyPressEvent(QKeyEvent * event) @@ -51,3 +59,8 @@ void ChatTextEdit::setLastMessage(QString lm) { lastMessage = lm; } + +void ChatTextEdit::retranslateUi() +{ + setPlaceholderText(tr("Type your message here...")); +} diff --git a/src/widget/tool/chattextedit.h b/src/widget/tool/chattextedit.h index c71316a26..fc7c4fa96 100644 --- a/src/widget/tool/chattextedit.h +++ b/src/widget/tool/chattextedit.h @@ -22,6 +22,7 @@ class ChatTextEdit : public QTextEdit Q_OBJECT public: explicit ChatTextEdit(QWidget *parent = 0); + ~ChatTextEdit(); virtual void keyPressEvent(QKeyEvent * event) override; void setLastMessage(QString lm); @@ -30,6 +31,9 @@ signals: void tabPressed(); void keyPressed(); +private: + void retranslateUi(); + private: QString lastMessage; }; diff --git a/src/widget/widget.cpp b/src/widget/widget.cpp index 22625b8c0..537211c54 100644 --- a/src/widget/widget.cpp +++ b/src/widget/widget.cpp @@ -101,13 +101,13 @@ void Widget::init() restoreState(Settings::getInstance().getWindowState()); ui->mainSplitter->restoreState(Settings::getInstance().getSplitterState()); - statusOnline = new QAction(tr("Online", "Button to set your status to 'Online'"), this); + statusOnline = new QAction(this); statusOnline->setIcon(getStatusIcon(Status::Online, 10, 10)); connect(statusOnline, SIGNAL(triggered()), this, SLOT(setStatusOnline())); - statusAway = new QAction(tr("Away", "Button to set your status to 'Away'"), this); + statusAway = new QAction(this); statusAway->setIcon(getStatusIcon(Status::Away, 10, 10)); connect(statusAway, SIGNAL(triggered()), this, SLOT(setStatusAway())); - statusBusy = new QAction(tr("Busy", "Button to set your status to 'Busy'"), this); + statusBusy = new QAction(this); statusBusy->setIcon(getStatusIcon(Status::Busy, 10, 10)); connect(statusBusy, SIGNAL(triggered()), this, SLOT(setStatusBusy())); @@ -128,14 +128,6 @@ void Widget::init() ui->mainHead->layout()->setMargin(0); ui->mainHead->layout()->setSpacing(0); - ui->searchContactFilterCBox->addItem(tr("All")); - ui->searchContactFilterCBox->addItem(tr("Online")); - ui->searchContactFilterCBox->addItem(tr("Offline")); - ui->searchContactFilterCBox->addItem(tr("Friends")); - ui->searchContactFilterCBox->addItem(tr("Groups")); - - ui->searchContactText->setPlaceholderText(tr("Search Contacts")); - if (QStyleFactory::keys().contains(Settings::getInstance().getStyle()) && Settings::getInstance().getStyle() != "None") { @@ -222,6 +214,10 @@ void Widget::init() if (Settings::getInstance().getCheckUpdates()) AutoUpdater::checkUpdatesAsyncInteractive(); #endif + + retranslateUi(); + Translator::registerHandler(std::bind(&Widget::retranslateUi, this), this); + if (!Settings::getInstance().getShowSystemTray()) show(); } @@ -274,6 +270,7 @@ void Widget::updateIcons() Widget::~Widget() { qDebug() << "Deleting Widget"; + Translator::unregister(this); AutoUpdater::abortUpdates(); if (icon) icon->hide(); @@ -1454,3 +1451,22 @@ void Widget::setActiveToolMenuButton(ActiveToolMenuButton newActiveButton) ui->settingsButton->setChecked(newActiveButton == Widget::SettingButton); ui->settingsButton->setDisabled(newActiveButton == Widget::SettingButton); } + +void Widget::retranslateUi() +{ + QString name = ui->nameLabel->text(), status = ui->statusLabel->text(); + ui->retranslateUi(this); + ui->nameLabel->setText(name); + ui->statusLabel->setText(status); + ui->searchContactFilterCBox->clear(); + ui->searchContactFilterCBox->addItem(tr("All")); + ui->searchContactFilterCBox->addItem(tr("Online")); + ui->searchContactFilterCBox->addItem(tr("Offline")); + ui->searchContactFilterCBox->addItem(tr("Friends")); + ui->searchContactFilterCBox->addItem(tr("Groups")); + ui->searchContactText->setPlaceholderText(tr("Search Contacts")); + statusOnline->setText(tr("Online", "Button to set your status to 'Online'")); + statusAway->setText(tr("Away", "Button to set your status to 'Away'")); + statusBusy->setText(tr("Busy", "Button to set your status to 'Busy'")); + setWindowTitle(tr("Settings")); +} diff --git a/src/widget/widget.h b/src/widget/widget.h index e0d9da25f..86a076da0 100644 --- a/src/widget/widget.h +++ b/src/widget/widget.h @@ -173,6 +173,7 @@ private: void saveWindowGeometry(); void saveSplitterGeometry(); void cycleContacts(int offset); + void retranslateUi(); SystemTrayIcon *icon; QMenu *trayMenu; QAction *statusOnline,