2015-02-06 19:28:49 +08:00
|
|
|
#include "gui.h"
|
2015-02-07 02:01:31 +08:00
|
|
|
#include "src/nexus.h"
|
|
|
|
#include <assert.h>
|
2015-02-06 19:28:49 +08:00
|
|
|
#include <QCoreApplication>
|
2015-02-07 02:01:31 +08:00
|
|
|
#include <QDebug>
|
|
|
|
#include <QDialogButtonBox>
|
2015-02-06 19:28:49 +08:00
|
|
|
#include <QInputDialog>
|
2015-02-07 02:01:31 +08:00
|
|
|
#include <QLabel>
|
|
|
|
#include <QMessageBox>
|
|
|
|
#include <QPushButton>
|
2015-02-06 19:28:49 +08:00
|
|
|
#include <QThread>
|
|
|
|
|
2015-02-07 02:01:31 +08:00
|
|
|
#ifdef Q_OS_ANDROID
|
|
|
|
#include "androidgui.h"
|
|
|
|
#else
|
|
|
|
#include "widget.h"
|
|
|
|
#endif
|
|
|
|
|
2015-02-06 19:28:49 +08:00
|
|
|
GUI::GUI(QObject *parent) :
|
|
|
|
QObject(parent)
|
|
|
|
{
|
2015-02-07 02:01:31 +08:00
|
|
|
assert(QThread::currentThread() == qApp->thread());
|
|
|
|
|
|
|
|
#ifndef Q_OS_ANDROID
|
|
|
|
assert(Nexus::getDesktopGUI());
|
|
|
|
connect(Nexus::getDesktopGUI(), &Widget::resized, this, &GUI::resized);
|
|
|
|
#endif
|
2015-02-06 19:28:49 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
GUI& GUI::getInstance()
|
|
|
|
{
|
|
|
|
static GUI gui;
|
|
|
|
return gui;
|
|
|
|
}
|
|
|
|
|
2015-02-07 02:01:31 +08:00
|
|
|
// Implementation of the public clean interface
|
|
|
|
|
|
|
|
void GUI::setEnabled(bool state)
|
|
|
|
{
|
|
|
|
if (QThread::currentThread() == qApp->thread())
|
|
|
|
{
|
|
|
|
getInstance()._setEnabled(state);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
QMetaObject::invokeMethod(&getInstance(), "_setEnabled", Qt::BlockingQueuedConnection,
|
|
|
|
Q_ARG(bool, state));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GUI::setWindowTitle(const QString& title)
|
|
|
|
{
|
|
|
|
if (QThread::currentThread() == qApp->thread())
|
|
|
|
{
|
|
|
|
getInstance()._setWindowTitle(title);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
QMetaObject::invokeMethod(&getInstance(), "_setWindowTitle", Qt::BlockingQueuedConnection,
|
|
|
|
Q_ARG(const QString&, title));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void GUI::reloadTheme()
|
|
|
|
{
|
|
|
|
if (QThread::currentThread() == qApp->thread())
|
|
|
|
{
|
|
|
|
getInstance()._reloadTheme();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
QMetaObject::invokeMethod(&getInstance(), "_reloadTheme", Qt::BlockingQueuedConnection);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-07 19:46:55 +08:00
|
|
|
void GUI::showInfo(const QString& title, const QString& msg)
|
|
|
|
{
|
|
|
|
if (QThread::currentThread() == qApp->thread())
|
|
|
|
{
|
|
|
|
getInstance()._showInfo(title, msg);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
QMetaObject::invokeMethod(&getInstance(), "_showInfo", Qt::BlockingQueuedConnection,
|
|
|
|
Q_ARG(const QString&, title), Q_ARG(const QString&, msg));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-07 02:01:31 +08:00
|
|
|
void GUI::showWarning(const QString& title, const QString& msg)
|
|
|
|
{
|
|
|
|
if (QThread::currentThread() == qApp->thread())
|
|
|
|
{
|
|
|
|
getInstance()._showWarning(title, msg);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
QMetaObject::invokeMethod(&getInstance(), "_showWarning", Qt::BlockingQueuedConnection,
|
|
|
|
Q_ARG(const QString&, title), Q_ARG(const QString&, msg));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-07 19:46:55 +08:00
|
|
|
void GUI::showError(const QString& title, const QString& msg)
|
2015-02-07 02:01:31 +08:00
|
|
|
{
|
|
|
|
if (QThread::currentThread() == qApp->thread())
|
|
|
|
{
|
2015-02-07 19:46:55 +08:00
|
|
|
getInstance()._showError(title, msg);
|
2015-02-07 02:01:31 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-02-07 19:46:55 +08:00
|
|
|
QMetaObject::invokeMethod(&getInstance(), "_showError", Qt::BlockingQueuedConnection,
|
2015-02-07 02:01:31 +08:00
|
|
|
Q_ARG(const QString&, title), Q_ARG(const QString&, msg));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool GUI::askQuestion(const QString& title, const QString& msg,
|
2015-02-20 23:36:35 +08:00
|
|
|
bool defaultAns, bool warning,
|
|
|
|
bool yesno)
|
2015-02-07 02:01:31 +08:00
|
|
|
{
|
|
|
|
if (QThread::currentThread() == qApp->thread())
|
|
|
|
{
|
2015-02-20 23:36:35 +08:00
|
|
|
return getInstance()._askQuestion(title, msg, defaultAns, warning, yesno);
|
2015-02-07 02:01:31 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bool ret;
|
|
|
|
QMetaObject::invokeMethod(&getInstance(), "_askQuestion", Qt::BlockingQueuedConnection,
|
|
|
|
Q_RETURN_ARG(bool, ret),
|
|
|
|
Q_ARG(const QString&, title), Q_ARG(const QString&, msg),
|
2015-02-20 23:36:35 +08:00
|
|
|
Q_ARG(bool, defaultAns), Q_ARG(bool, warning),
|
|
|
|
Q_ARG(bool, yesno));
|
2015-02-07 02:01:31 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-06 19:28:49 +08:00
|
|
|
QString GUI::itemInputDialog(QWidget * parent, const QString & title,
|
|
|
|
const QString & label, const QStringList & items,
|
|
|
|
int current, bool editable, bool * ok,
|
|
|
|
Qt::WindowFlags flags,
|
|
|
|
Qt::InputMethodHints hints)
|
|
|
|
{
|
|
|
|
if (QThread::currentThread() == qApp->thread())
|
|
|
|
{
|
|
|
|
return getInstance()._itemInputDialog(parent, title, label, items, current, editable, ok, flags, hints);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
QString r;
|
|
|
|
QMetaObject::invokeMethod(&getInstance(), "_itemInputDialog", Qt::BlockingQueuedConnection,
|
|
|
|
Q_RETURN_ARG(QString, r),
|
|
|
|
Q_ARG(QWidget*, parent), Q_ARG(const QString&, title),
|
|
|
|
Q_ARG(const QString&,label), Q_ARG(const QStringList&, items),
|
|
|
|
Q_ARG(int, current), Q_ARG(bool, editable), Q_ARG(bool*, ok),
|
|
|
|
Q_ARG(Qt::WindowFlags, flags), Q_ARG(Qt::InputMethodHints, hints));
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-07 02:01:31 +08:00
|
|
|
QString GUI::passwordDialog(const QString& cancel, const QString& body)
|
|
|
|
{
|
|
|
|
if (QThread::currentThread() == qApp->thread())
|
|
|
|
{
|
|
|
|
return getInstance()._passwordDialog(cancel, body);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
QString r;
|
|
|
|
QMetaObject::invokeMethod(&getInstance(), "_passwordDialog", Qt::BlockingQueuedConnection,
|
|
|
|
Q_RETURN_ARG(QString, r),
|
|
|
|
Q_ARG(const QString&, cancel), Q_ARG(const QString&, body));
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Private implementations
|
|
|
|
|
|
|
|
void GUI::_setEnabled(bool state)
|
|
|
|
{
|
|
|
|
#ifdef Q_OS_ANDROID
|
|
|
|
Nexus::getAndroidGUI()->setEnabled(state);
|
|
|
|
#else
|
|
|
|
Nexus::getDesktopGUI()->setEnabled(state);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
void GUI::_setWindowTitle(const QString& title)
|
|
|
|
{
|
|
|
|
if (title.isEmpty())
|
|
|
|
getMainWidget()->setWindowTitle("qTox");
|
|
|
|
else
|
|
|
|
getMainWidget()->setWindowTitle("qTox - " +title);
|
|
|
|
}
|
|
|
|
|
|
|
|
void GUI::_reloadTheme()
|
|
|
|
{
|
|
|
|
#ifndef Q_OS_ANDROID
|
|
|
|
Nexus::getDesktopGUI()->reloadTheme();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2015-02-07 19:46:55 +08:00
|
|
|
void GUI::_showInfo(const QString& title, const QString& msg)
|
|
|
|
{
|
|
|
|
QMessageBox::information(getMainWidget(), title, msg);
|
|
|
|
}
|
|
|
|
|
2015-02-07 02:01:31 +08:00
|
|
|
void GUI::_showWarning(const QString& title, const QString& msg)
|
|
|
|
{
|
|
|
|
QMessageBox::warning(getMainWidget(), title, msg);
|
|
|
|
}
|
|
|
|
|
2015-02-07 19:46:55 +08:00
|
|
|
void GUI::_showError(const QString& title, const QString& msg)
|
2015-02-07 02:01:31 +08:00
|
|
|
{
|
2015-02-07 19:46:55 +08:00
|
|
|
QMessageBox::critical(getMainWidget(), title, msg);
|
2015-02-07 02:01:31 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
bool GUI::_askQuestion(const QString& title, const QString& msg,
|
2015-02-20 23:36:35 +08:00
|
|
|
bool defaultAns, bool warning,
|
|
|
|
bool yesno)
|
2015-02-07 02:01:31 +08:00
|
|
|
{
|
2015-02-20 23:36:35 +08:00
|
|
|
QMessageBox::StandardButton positiveButton = yesno ? QMessageBox::Yes : QMessageBox::Ok;
|
|
|
|
QMessageBox::StandardButton negativeButton = yesno ? QMessageBox::No : QMessageBox::Cancel;
|
|
|
|
|
|
|
|
QMessageBox::StandardButton defButton = defaultAns ? positiveButton : negativeButton;
|
|
|
|
|
2015-02-07 02:01:31 +08:00
|
|
|
if (warning)
|
2015-02-20 23:36:35 +08:00
|
|
|
return QMessageBox::warning(getMainWidget(), title, msg, positiveButton | negativeButton, defButton) == positiveButton;
|
2015-02-07 02:01:31 +08:00
|
|
|
else
|
2015-02-20 23:36:35 +08:00
|
|
|
return QMessageBox::question(getMainWidget(), title, msg, positiveButton | negativeButton, defButton) == positiveButton;
|
2015-02-07 02:01:31 +08:00
|
|
|
}
|
|
|
|
|
2015-02-06 19:28:49 +08:00
|
|
|
QString GUI::_itemInputDialog(QWidget * parent, const QString & title,
|
|
|
|
const QString & label, const QStringList & items,
|
|
|
|
int current, bool editable, bool * ok,
|
|
|
|
Qt::WindowFlags flags,
|
|
|
|
Qt::InputMethodHints hints)
|
|
|
|
{
|
|
|
|
return QInputDialog::getItem(parent, title, label, items, current, editable, ok, flags, hints);
|
|
|
|
}
|
2015-02-07 02:01:31 +08:00
|
|
|
|
|
|
|
QString GUI::_passwordDialog(const QString& cancel, const QString& body)
|
|
|
|
{
|
|
|
|
// we use a hack. It is considered that closing the dialog without explicitly clicking
|
|
|
|
// disable history is confusing. But we can't distinguish between clicking the cancel
|
|
|
|
// button and closing the dialog. So instead, we reverse the Ok and Cancel roles,
|
|
|
|
// so that nothing but explicitly clicking disable history closes the dialog
|
|
|
|
QString ret;
|
|
|
|
QInputDialog dialog;
|
|
|
|
dialog.setWindowTitle(tr("Enter your password"));
|
|
|
|
dialog.setOkButtonText(cancel);
|
|
|
|
dialog.setCancelButtonText(tr("Decrypt"));
|
|
|
|
dialog.setInputMode(QInputDialog::TextInput);
|
|
|
|
dialog.setTextEchoMode(QLineEdit::Password);
|
|
|
|
dialog.setLabelText(body);
|
|
|
|
|
|
|
|
// problem with previous hack: the default button is disable history, not decrypt.
|
|
|
|
// use another hack to reverse the default buttons.
|
|
|
|
// http://www.qtcentre.org/threads/49924-Change-property-of-QInputDialog-button
|
|
|
|
QList<QDialogButtonBox*> l = dialog.findChildren<QDialogButtonBox*>();
|
|
|
|
if (!l.isEmpty())
|
|
|
|
{
|
|
|
|
QPushButton* ok = l.first()->button(QDialogButtonBox::Ok);
|
|
|
|
QPushButton* cancel = l.first()->button(QDialogButtonBox::Cancel);
|
|
|
|
if (ok && cancel)
|
|
|
|
{
|
|
|
|
ok->setAutoDefault(false);
|
|
|
|
ok->setDefault(false);
|
|
|
|
cancel->setAutoDefault(true);
|
|
|
|
cancel->setDefault(true);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
qWarning() << "PasswordDialog: Missing button!";
|
|
|
|
}
|
|
|
|
else
|
|
|
|
qWarning() << "PasswordDialog: No QDialogButtonBox!";
|
|
|
|
|
|
|
|
// using similar code, set QLabels to wrap
|
|
|
|
for (auto* label : dialog.findChildren<QLabel*>())
|
|
|
|
label->setWordWrap(true);
|
|
|
|
|
|
|
|
while (true)
|
|
|
|
{
|
|
|
|
int val = dialog.exec();
|
|
|
|
if (val == QDialog::Accepted)
|
|
|
|
return QString();
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ret = dialog.textValue();
|
|
|
|
if (!ret.isEmpty())
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
dialog.setTextValue("");
|
|
|
|
dialog.setLabelText(body + "\n\n" + tr("You must enter a non-empty password:"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Other
|
|
|
|
|
|
|
|
QWidget* GUI::getMainWidget()
|
|
|
|
{
|
|
|
|
QWidget* maingui{nullptr};
|
|
|
|
#ifdef Q_OS_ANDROID
|
|
|
|
maingui = Nexus::getAndroidGUI();
|
|
|
|
#else
|
|
|
|
maingui = Nexus::getDesktopGUI();
|
|
|
|
#endif
|
|
|
|
return maingui;
|
|
|
|
}
|