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));
}
coreThread->exit(0);
while (coreThread->isRunning())
if (QThread::currentThread() != coreThread)
{
qApp->processEvents();
coreThread->wait(500);
while (coreThread->isRunning())
{
qApp->processEvents();
coreThread->wait(500);
}
}
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)
{
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
if (eventType == "uri")
@ -303,8 +304,10 @@ int main(int argc, char *argv[])
else if (eventType == "save")
handleToxSave(firstParam.toUtf8());
// Run
int errorcode = a.exec();
// Run (unless we already quit before starting!)
int errorcode = 0;
if (nexus.isRunning())
errorcode = a.exec();
Nexus::destroyInstance();
CameraSource::destroyInstance();

View File

@ -33,6 +33,7 @@
#include <QPlainTextEdit>
#include <QPushButton>
#include <QCoreApplication>
#include <QThread>
bool toxURIEventHandler(const QByteArray& eventData)
{
@ -51,33 +52,70 @@ bool toxURIEventHandler(const QByteArray& eventData)
*/
bool handleToxURI(const QString &toxURI)
{
Core* core = Core::getInstance();
Nexus& nexus = Nexus::getInstance();
Core* core = nexus.getCore();
while (!core)
{
core = Core::getInstance();
if (!nexus.isRunning())
return false;
core = nexus.getCore();
qApp->processEvents();
QThread::msleep(10);
}
while (!core->isReady())
{
if (!nexus.isRunning())
return false;
qApp->processEvents();
QThread::msleep(10);
}
QString toxaddr = toxURI.mid(4);
ToxId toxId = Toxme::lookup(toxaddr);
ToxId toxId(toxaddr);
if (!toxId.isValid())
{
QMessageBox::warning(0, "qTox",
ToxURIDialog::tr("%1 is not a valid Toxme address.")
.arg(toxaddr));
toxId = Toxme::lookup(toxaddr);
if (!toxId.isValid())
{
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;
}
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!")
.arg(Nexus::getCore()->getUsername()));
if (dialog.exec() == QDialog::Accepted)
Core::getInstance()->requestFriendship(toxId, dialog.getRequestMessage());
QObject::connect(dialog, &ToxURIDialog::finished, [=](int result) {
if (result == QDialog::Accepted)
Core::getInstance()->requestFriendship(toxId, dialog->getRequestMessage());
dialog->deleteLater();
});
dialog->open();
return true;
}

View File

@ -59,15 +59,20 @@ Nexus::Nexus(QObject *parent) :
QObject(parent),
profile{nullptr},
widget{nullptr},
loginScreen{nullptr}
loginScreen{nullptr},
running{true},
quitOnLastWindowClosed{true}
{
}
Nexus::~Nexus()
{
delete widget;
widget = nullptr;
delete loginScreen;
loginScreen = nullptr;
delete profile;
profile = nullptr;
Settings::getInstance().saveGlobal();
#ifdef Q_OS_MAC
delete globalMenuBar;
@ -104,6 +109,14 @@ void Nexus::start()
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
globalMenuBar = new QMenuBar(0);
dockMenu = new QMenu(globalMenuBar);
@ -161,14 +174,14 @@ void Nexus::showLogin()
loginScreen->reset();
loginScreen->move(QApplication::desktop()->screen()->rect().center() - loginScreen->rect().center());
loginScreen->show();
((QApplication*)qApp)->setQuitOnLastWindowClosed(true);
quitOnLastWindowClosed = true;
}
void Nexus::showMainGUI()
{
assert(profile);
((QApplication*)qApp)->setQuitOnLastWindowClosed(false);
quitOnLastWindowClosed = false;
loginScreen->close();
// Create GUI
@ -220,6 +233,26 @@ void Nexus::showMainGUI()
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.
*/
@ -310,6 +343,12 @@ void Nexus::showLoginLater()
QMetaObject::invokeMethod(&getInstance(), "showLogin", Qt::QueuedConnection);
}
void Nexus::onLastWindowClosed()
{
if (quitOnLastWindowClosed)
quit();
}
#ifdef Q_OS_MAC
void Nexus::retranslateUi()
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -594,7 +594,7 @@ void Widget::closeEvent(QCloseEvent *event)
saveWindowGeometry();
saveSplitterGeometry();
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.setIcon(QMessageBox::Critical);
critical.exec();
qApp->quit();
Nexus::getInstance().quit();
}
void Widget::onBadProxyCore()