1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

Merge pull request #4183

tux3 (4):
      fix: Accept IDs as tox URIs, not just ToxDNS addresses
      fix: Various IPC event handling and related bugs on startup
      fix: Don't even try to add ourselves as a friend in the Tox URI handler
      fix: msleep in toxuri processEvents loops, to avoid 100% CPU
This commit is contained in:
tux3 2017-02-19 00:46:11 +01:00
commit ea44095c94
No known key found for this signature in database
GPG Key ID: 7E086DD661263264
11 changed files with 144 additions and 27 deletions

View File

@ -94,10 +94,13 @@ Core::~Core()
Q_ARG(bool, false)); Q_ARG(bool, false));
} }
coreThread->exit(0); coreThread->exit(0);
while (coreThread->isRunning()) if (QThread::currentThread() != coreThread)
{ {
qApp->processEvents(); while (coreThread->isRunning())
coreThread->wait(500); {
qApp->processEvents();
coreThread->wait(500);
}
} }
deadifyTox(); deadifyTox();

View File

@ -175,6 +175,10 @@ bool IPC::isCurrentOwner()
} }
} }
/**
* @brief Register a handler for an IPC event
* @param handler The handler callback. Should not block for more than a second, at worst
*/
void IPC::registerEventHandler(const QString &name, IPCEventHandler handler) void IPC::registerEventHandler(const QString &name, IPCEventHandler handler)
{ {
eventHandlers[name] = handler; eventHandlers[name] = handler;

View File

@ -295,7 +295,8 @@ int main(int argc, char *argv[])
} }
} }
Nexus::getInstance().start(); Nexus& nexus = Nexus::getInstance();
nexus.start();
// Event was not handled by already running instance therefore we handle it ourselves // Event was not handled by already running instance therefore we handle it ourselves
if (eventType == "uri") if (eventType == "uri")
@ -303,8 +304,10 @@ int main(int argc, char *argv[])
else if (eventType == "save") else if (eventType == "save")
handleToxSave(firstParam.toUtf8()); handleToxSave(firstParam.toUtf8());
// Run // Run (unless we already quit before starting!)
int errorcode = a.exec(); int errorcode = 0;
if (nexus.isRunning())
errorcode = a.exec();
Nexus::destroyInstance(); Nexus::destroyInstance();
CameraSource::destroyInstance(); CameraSource::destroyInstance();

View File

@ -33,6 +33,7 @@
#include <QPlainTextEdit> #include <QPlainTextEdit>
#include <QPushButton> #include <QPushButton>
#include <QCoreApplication> #include <QCoreApplication>
#include <QThread>
bool toxURIEventHandler(const QByteArray& eventData) bool toxURIEventHandler(const QByteArray& eventData)
{ {
@ -51,33 +52,70 @@ bool toxURIEventHandler(const QByteArray& eventData)
*/ */
bool handleToxURI(const QString &toxURI) bool handleToxURI(const QString &toxURI)
{ {
Core* core = Core::getInstance(); Nexus& nexus = Nexus::getInstance();
Core* core = nexus.getCore();
while (!core) while (!core)
{ {
core = Core::getInstance(); if (!nexus.isRunning())
return false;
core = nexus.getCore();
qApp->processEvents(); qApp->processEvents();
QThread::msleep(10);
} }
while (!core->isReady()) while (!core->isReady())
{
if (!nexus.isRunning())
return false;
qApp->processEvents(); qApp->processEvents();
QThread::msleep(10);
}
QString toxaddr = toxURI.mid(4); QString toxaddr = toxURI.mid(4);
ToxId toxId = Toxme::lookup(toxaddr); ToxId toxId(toxaddr);
if (!toxId.isValid()) if (!toxId.isValid())
{ {
QMessageBox::warning(0, "qTox", toxId = Toxme::lookup(toxaddr);
ToxURIDialog::tr("%1 is not a valid Toxme address.") if (!toxId.isValid())
.arg(toxaddr)); {
QMessageBox *messageBox = new QMessageBox(QMessageBox::Warning,
QMessageBox::tr("Couldn't add friend"),
QMessageBox::tr("%1 is not a valid Toxme address.")
.arg(toxaddr), QMessageBox::Ok, nullptr);
messageBox->setButtonText(QMessageBox::Ok, QMessageBox::tr("Ok"));
QObject::connect(messageBox, &QMessageBox::finished, messageBox, &QMessageBox::deleteLater);
messageBox->show();
return false;
}
}
if (toxId == core->getSelfId())
{
QMessageBox *messageBox = new QMessageBox(QMessageBox::Warning,
QMessageBox::tr("Couldn't add friend"),
QMessageBox::tr("You can't add yourself as a friend!",
"When trying to add your own Tox ID as friend"),
QMessageBox::Ok, nullptr);
messageBox->setButtonText(QMessageBox::Ok, QMessageBox::tr("Ok"));
QObject::connect(messageBox, &QMessageBox::finished, messageBox, &QMessageBox::deleteLater);
messageBox->show();
return false; return false;
} }
ToxURIDialog dialog(0, toxaddr, QObject::tr("%1 here! Tox me maybe?", ToxURIDialog *dialog = new ToxURIDialog(0, toxaddr, QObject::tr("%1 here! Tox me maybe?",
"Default message in Tox URI friend requests. Write something appropriate!") "Default message in Tox URI friend requests. Write something appropriate!")
.arg(Nexus::getCore()->getUsername())); .arg(Nexus::getCore()->getUsername()));
if (dialog.exec() == QDialog::Accepted) QObject::connect(dialog, &ToxURIDialog::finished, [=](int result) {
Core::getInstance()->requestFriendship(toxId, dialog.getRequestMessage()); if (result == QDialog::Accepted)
Core::getInstance()->requestFriendship(toxId, dialog->getRequestMessage());
dialog->deleteLater();
});
dialog->open();
return true; return true;
} }

View File

@ -59,15 +59,20 @@ Nexus::Nexus(QObject *parent) :
QObject(parent), QObject(parent),
profile{nullptr}, profile{nullptr},
widget{nullptr}, widget{nullptr},
loginScreen{nullptr} loginScreen{nullptr},
running{true},
quitOnLastWindowClosed{true}
{ {
} }
Nexus::~Nexus() Nexus::~Nexus()
{ {
delete widget; delete widget;
widget = nullptr;
delete loginScreen; delete loginScreen;
loginScreen = nullptr;
delete profile; delete profile;
profile = nullptr;
Settings::getInstance().saveGlobal(); Settings::getInstance().saveGlobal();
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
delete globalMenuBar; delete globalMenuBar;
@ -104,6 +109,14 @@ void Nexus::start()
loginScreen = new LoginScreen(); loginScreen = new LoginScreen();
// We need this LastWindowClosed dance because the LoginScreen may be shown
// and closed in a processEvents() loop before the start of the real
// exec() event loop, meaning we wouldn't receive the onLastWindowClosed,
// and so we wouldn't have a chance to tell the processEvents() loop to quit.
qApp->setQuitOnLastWindowClosed(false);
connect(qApp, &QApplication::lastWindowClosed, this, &Nexus::onLastWindowClosed);
connect(loginScreen, &LoginScreen::closed, this, &Nexus::onLastWindowClosed);
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
globalMenuBar = new QMenuBar(0); globalMenuBar = new QMenuBar(0);
dockMenu = new QMenu(globalMenuBar); dockMenu = new QMenu(globalMenuBar);
@ -161,14 +174,14 @@ void Nexus::showLogin()
loginScreen->reset(); loginScreen->reset();
loginScreen->move(QApplication::desktop()->screen()->rect().center() - loginScreen->rect().center()); loginScreen->move(QApplication::desktop()->screen()->rect().center() - loginScreen->rect().center());
loginScreen->show(); loginScreen->show();
((QApplication*)qApp)->setQuitOnLastWindowClosed(true); quitOnLastWindowClosed = true;
} }
void Nexus::showMainGUI() void Nexus::showMainGUI()
{ {
assert(profile); assert(profile);
((QApplication*)qApp)->setQuitOnLastWindowClosed(false); quitOnLastWindowClosed = false;
loginScreen->close(); loginScreen->close();
// Create GUI // Create GUI
@ -220,6 +233,26 @@ void Nexus::showMainGUI()
profile->startCore(); profile->startCore();
} }
/**
* @brief Calls QApplication::quit(), and causes Nexus::isRunning() to return false
*/
void Nexus::quit()
{
running = false;
qApp->quit();
}
/**
* @brief Returns true until Nexus::quit is called.
*
* Any blocking processEvents() loop should check this as a return condition,
* since the application can not quit until control is returned to the event loop.
*/
bool Nexus::isRunning()
{
return running;
}
/** /**
* @brief Returns the singleton instance. * @brief Returns the singleton instance.
*/ */
@ -310,6 +343,12 @@ void Nexus::showLoginLater()
QMetaObject::invokeMethod(&getInstance(), "showLogin", Qt::QueuedConnection); QMetaObject::invokeMethod(&getInstance(), "showLogin", Qt::QueuedConnection);
} }
void Nexus::onLastWindowClosed()
{
if (quitOnLastWindowClosed)
quit();
}
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
void Nexus::retranslateUi() void Nexus::retranslateUi()
{ {

View File

@ -43,6 +43,8 @@ class Nexus : public QObject
public: public:
void start(); void start();
void showMainGUI(); void showMainGUI();
void quit();
bool isRunning();
static Nexus& getInstance(); static Nexus& getInstance();
static void destroyInstance(); static void destroyInstance();
@ -84,6 +86,9 @@ private:
QActionGroup* windowActions = nullptr; QActionGroup* windowActions = nullptr;
#endif #endif
private slots:
void onLastWindowClosed();
private: private:
explicit Nexus(QObject *parent = 0); explicit Nexus(QObject *parent = 0);
~Nexus(); ~Nexus();
@ -92,6 +97,8 @@ private:
Profile* profile; Profile* profile;
Widget* widget; Widget* widget;
LoginScreen* loginScreen; LoginScreen* loginScreen;
bool running;
bool quitOnLastWindowClosed;
}; };
#endif // NEXUS_H #endif // NEXUS_H

View File

@ -211,7 +211,10 @@ Profile::~Profile()
saveToxSave(); saveToxSave();
} }
delete core; core->deleteLater();
while (coreThread->isRunning())
qApp->processEvents();
delete coreThread; delete coreThread;
if (!isRemoved) if (!isRemoved)
{ {

View File

@ -322,25 +322,34 @@ QString GUI::passwordDialog(const QString& cancel, const QString& body)
void GUI::_clearContacts() void GUI::_clearContacts()
{ {
Nexus::getDesktopGUI()->clearContactsList(); Widget* w = Nexus::getDesktopGUI();
if (w)
w->clearContactsList();
} }
void GUI::_setEnabled(bool state) void GUI::_setEnabled(bool state)
{ {
Nexus::getDesktopGUI()->setEnabled(state); Widget* w = Nexus::getDesktopGUI();
if (w)
w->setEnabled(state);
} }
void GUI::_setWindowTitle(const QString& title) void GUI::_setWindowTitle(const QString& title)
{ {
QWidget* w = getMainWidget();
if (!w)
return;
if (title.isEmpty()) if (title.isEmpty())
getMainWidget()->setWindowTitle("qTox"); w->setWindowTitle("qTox");
else else
getMainWidget()->setWindowTitle("qTox - " + title); w->setWindowTitle("qTox - " + title);
} }
void GUI::_reloadTheme() void GUI::_reloadTheme()
{ {
Nexus::getDesktopGUI()->reloadTheme(); Widget* w = Nexus::getDesktopGUI();
if (w)
w->reloadTheme();
} }
void GUI::_showInfo(const QString& title, const QString& msg) void GUI::_showInfo(const QString& title, const QString& msg)
@ -366,7 +375,9 @@ void GUI::_showError(const QString& title, const QString& msg)
void GUI::_showUpdateDownloadProgress() void GUI::_showUpdateDownloadProgress()
{ {
Nexus::getDesktopGUI()->showUpdateDownloadProgress(); Widget* w = Nexus::getDesktopGUI();
if (w)
w->showUpdateDownloadProgress();
} }
bool GUI::_askQuestion(const QString& title, const QString& msg, bool GUI::_askQuestion(const QString& title, const QString& msg,

View File

@ -126,6 +126,11 @@ bool LoginScreen::event(QEvent* event)
return QWidget::event(event); return QWidget::event(event);
} }
void LoginScreen::closeEvent(QCloseEvent*)
{
emit closed();
}
void LoginScreen::onNewProfilePageClicked() void LoginScreen::onNewProfilePageClicked()
{ {
ui->stackedWidget->setCurrentIndex(0); ui->stackedWidget->setCurrentIndex(0);

View File

@ -42,6 +42,10 @@ public:
signals: signals:
void windowStateChanged(Qt::WindowStates states); void windowStateChanged(Qt::WindowStates states);
void closed();
protected:
virtual void closeEvent(QCloseEvent *event) final override;
private slots: private slots:
void onAutoLoginToggled(int state); void onAutoLoginToggled(int state);

View File

@ -594,7 +594,7 @@ void Widget::closeEvent(QCloseEvent *event)
saveWindowGeometry(); saveWindowGeometry();
saveSplitterGeometry(); saveSplitterGeometry();
QWidget::closeEvent(event); QWidget::closeEvent(event);
qApp->quit(); Nexus::getInstance().quit();
} }
} }
@ -647,7 +647,7 @@ void Widget::onFailedToStartCore()
critical.setText(tr("toxcore failed to start, the application will terminate after you close this message.")); critical.setText(tr("toxcore failed to start, the application will terminate after you close this message."));
critical.setIcon(QMessageBox::Critical); critical.setIcon(QMessageBox::Critical);
critical.exec(); critical.exec();
qApp->quit(); Nexus::getInstance().quit();
} }
void Widget::onBadProxyCore() void Widget::onBadProxyCore()