how to restart my own qt application? - c++

i just asking myself how to restart my own qt application?
Can somebody please show me an example?

To restart application, try:
#include <QApplication>
#include <QProcess>
...
// restart:
qApp->quit();
QProcess::startDetached(qApp->arguments()[0], qApp->arguments());

I'm taking the other answers solutions, but better. No need for pointers, but there is a need for a ; after the while statement of a do { ... } while( ... ); construct.
int main(int argc, char *argv[])
{
const int RESTART_CODE = 1000;
do
{
QApplication app(argc, argv);
MainWindow main_window(app);
} while( app.exec() == RESTART_CODE);
return return_from_event_loop_code;
}

Assuming that 1337 is your restart code:
main.cxx
int main(int argc, char * argv[])
{
int result = 0;
do
{
QCoreApplication coreapp(argc, argv);
MyClass myObj;
result = coreapp.exec();
} while( result == 1337 );
return result;
}
myClass.cxx
qApp->exit(1337);

To restart a running Qt application (at least in Qt 5.15.2) you can do the following:
#include <QApplication>
#include <QProcess>
//...
QString program = qApp->arguments()[0];
QStringList arguments = qApp->arguments().mid(1); // remove the 1st argument - the program name
qApp->quit();
QProcess::startDetached(program, arguments);

Doing a real process restart without subclassing:
QCoreApplication a(argc, argv);
int returncode = a.exec();
if (returncode == -1)
{
QProcess* proc = new QProcess();
proc->start(QCoreApplication::applicationFilePath());
}
return returncode;
Edit for Mac OS like earlier example.
To restart call
QCoreApplication::exit(-1);
somewhere in your code.

Take a look at How to restart an application thread on qtcentre.org, where muisei gives this code
#define RESTART_CODE 1000
int main(int argc, char *argv[])
{
int return_from_event_loop_code;
QPointer<QApplication> app;
QPointer<MainWindow> main_window;
do
{
if(app) delete app;
if(main_window) delete main_window;
app = new QApplication(argc, argv);
main_window = new MainWindow(app);
return_from_event_loop_code = app->exec();
}
while(return_from_event_loop_code==RESTART_CODE)
return return_from_event_loop_code;
}

I just used the method described above and I noticed that my application crashes on restart.
...then I switched the following lines of code:
if(app) delete app;
if(main_window) delete main_window;
to:
if(main_window) delete main_window;
if(app) delete app;
and it behaves OK. For some reason the window must be deleted first.
Just a note for future readers.
EDIT: ...and a different approach for those who want a real process-restart: You can declare a myApp::Restart() method in your subclass of QApplication. The following version works OK on both MS-Windows & MacOS:
// Restart Application
void myApp::Restart(bool Abort)
{
// Spawn a new instance of myApplication:
QProcess proc;
#ifdef Q_OS_WIN
proc.start(this->applicationFilePath());
#endif
#ifdef Q_OS_MAC
// In Mac OS the full path of aplication binary is:
// <base-path>/myApp.app/Contents/MacOS/myApp
QStringList args;
args << (this->applicationDirPath() + "/../../../myApp.app");
proc.start("open", args);
#endif
// Terminate current instance:
if (Abort) // Abort Application process (exit immediattely)
::exit(0);
else
this->exit(0); // Exit gracefully by terminating the myApp instance
}

This slight variation on Rubenvb's idea works with PyQt. clearSettings is the method that triggers the restart.
class GuiMain
#Most of implementation missing
def clearSettings(self):
#Clearing the settings missing
QApplication.exit(GuiMain.restart_code)
restart_code = 1000
#staticmethod
def application_main():
"""
The application's main function.
Create application and main window and run them.
"""
while True:
app = QApplication(sys.argv)
window = GuiMain()
window.show()
ret = app.exec_()
if ret != GuiMain.restart_code:
break
del window
del app

Here is the code:
main.cpp:
int main(int argc, char *argv[])
{
int currentExitCode = 0;
do {
QApplication a(argc, argv);
MainWindow w;
w.show();
currentExitCode = a.exec();
} while( currentExitCode == MainWindow::EXIT_CODE_REBOOT );
return currentExitCode;
}
mainwindow.h
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
static int const EXIT_CODE_REBOOT;//THIS IS THE IMPORTANT THING TO ADD TO YOUR CODE
~MainWindow();
private slots:
void slotReboot();//AND THIS ALSO
//ALL THE OTHER VARIABLES
}
The slotReboot() is the slot that will receive the signal of the QAction I'm going to show in the mainwindow.cpp
mainwindow.cpp
First initialize EXIT_CODE_REBOOT :
int const MainWindow::EXIT_CODE_REBOOT = -123456789;
and declare a QAction pointer:
QAction* actionReboot;
then in the MainWindow constructor:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
actionReboot = new QAction( this );
actionReboot->setText( tr("Restart") );
actionReboot->setStatusTip( tr("Restarts the application") );
connect( actionReboot, SIGNAL (triggered()),this, SLOT (slotReboot()));
}
And finally you need to send the signal (in the part of your code you need), in this way:
actionReboot->trigger();
I did the code I showed following these instructions: How to make an application restartable - Qt Wiki

You can use my open source library:
https://marketplace.qt.io/products/main-loop-wdt-for-qt-qml
It's a watchdog timer for the main qt loop, but I have a function for forced reboot, with different strategies: startdetached + exit, exec system call on Linux / macOS, and delayed restart (for example, exit and restart after 3 seconds)

Related

Why QProgressDialog is shown without an explicit call to `exec()` or `show()`?

I have the following code
#include "dialog.h"
#include <QApplication>
#include <QProgressDialog>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QProgressDialog w;
//w.show();
return a.exec();
}
The execution of this code shows a QProgressDialog UI.
I would like to have the explanation why my QProgressDialog shows up without having an exec()or show() instructions.
I have read the documentation but did not find the explanation on it.
Both constructors of QProgressDialog call QProgressDialogPrivate::init, where forceTimer : QTimer is started:
...
forceTimer = new QTimer(q);
QObject::connect(forceTimer, SIGNAL(timeout()), q, SLOT(forceShow()));
...
forceTimer->start(showTime);
The forceShow() slot in turn looks like this:
void QProgressDialog::forceShow() {
Q_D(QProgressDialog);
d->forceTimer->stop();
if (d->shown_once || d->cancellation_flag)
return;
show();
d->shown_once = true;
}
The show(); statement there is the very reason the QProgressDialog is shown on object creation.
Since it will automatically open after being constructed, follow it with a cancellation.
auto * progressDialog = new QProgressDialog{};
progressDialog.cancel();

Running Urho3D and Qt from main

I am using the Urho3D engine with Qt for an application. The problem is that both Urho3D and QApplication require to be ran from main(). For now I am using it in separate processes but IPC makes it complicated.
Is there any way to solve this issue? Thanks
My platform is Urho3D 1.5, Qt 4.71 and Windows 7 x64 and VS2015 (C++)
I'm new to both c++ and Urho3D, but I've successfully achieved it.
Simple code, haven't had further test:
awidget.h:
#ifndef AWIDGET_H
#define AWIDGET_H
#include <QWidget>
#include <QPushButton>
#include <Urho3D/Engine/Application.h>
class aWidget : public QWidget
{
Q_OBJECT
public:
explicit aWidget(QWidget *parent = 0)
{
QPushButton *button = new QPushButton(this);
connect(button, SIGNAL(clicked()), this, SLOT(pressed()));
}
public slots:
void pressed()
{
Urho3D::Context* context = new Urho3D::Context();
Urho3D::Application *application = new Urho3D::Application(context);
application->Run();
}
};
#endif // AWIDGET_H
main.cpp:
#include <QApplication>
#include <awidget.h>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
aWidget *widget = new aWidget();
widget->show();
return app.exec();
}
By the way, I'm using Qt 5.9.0
So the answer is quite simple. Instead of running QApplication by calling
app->exec();
it is needed to manually and regularily call this from your main loop:
app->processEvents();
This will take care that all events used by Qt are processed and QApplication will respond accordingly.
Example:
#include <QApplication>
#include <awidget.h>
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
bool shallrun = true;
aWidget *widget = new aWidget();
widget->show();
while (shallrun)
{
app->processEvents();
...
}
...
}

How I show application when open application again Qt

Now, I have 1 application, but I don't want to open application twice, so I using QShareMemory to detect application when open twice.
And my question is: how I show current application in screen when user open application the second ?
int main(int argc, char *argv[]) {
Application a(argc, argv);
/*Make sure only one instance of application can run on host system at a time*/
QSharedMemory sharedMemory;
sharedMemory.setKey ("Application");
if (!sharedMemory.create(1))
{
qDebug() << "123123Exit already a process running";
return 0;
}
/**/
return a.exec();
}
Thanks.
Here's another approach in pure Qt way:
Use QLocalServer and QLocalSocket to check the existence of application and then use signal-slot mechanism to notify the existing one.
#include "widget.h"
#include <QApplication>
#include <QObject>
#include <QLocalSocket>
#include <QLocalServer>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
const QString appKey = "applicationKey";
QLocalSocket *socket = new QLocalSocket();
socket->connectToServer(appKey);
if (socket->isOpen()) {
socket->close();
socket->deleteLater();
return 0;
}
socket->deleteLater();
Widget w;
QLocalServer server;
QObject::connect(&server,
&QLocalServer::newConnection,
[&w] () {
/*Set the window on the top level.*/
w.setWindowFlags(w.windowFlags() |
Qt::WindowStaysOnTopHint);
w.showNormal();
w.setWindowFlags(w.windowFlags() &
~Qt::WindowStaysOnTopHint
);
w.showNormal();
w.activateWindow();
});
server.listen(appKey);
w.show();
return a.exec();
}
But if you're using Qt 5.3 on Windows, there's a bug for QWidget::setWindowFlags and Qt::WindowStaysOnTopHint, see https://bugreports.qt.io/browse/QTBUG-30359.
Just use QSingleApplication class instead of QApplication:
https://github.com/qtproject/qt-solutions/tree/master/qtsingleapplication
int main(int argc, char **argv)
{
QtSingleApplication app(argc, argv);
if (app.isRunning())
return 0;
MyMainWidget mmw;
app.setActivationWindow(&mmw);
mmw.show();
return app.exec();
}
It is part of Qt Solutions: https://github.com/qtproject/qt-solutions

Unable to open file with qt app on mac

I am trying to associate custom files with an osx app. I have a plist that associates files with the app, but double clicking a file opens the app with no data inside.
Calling
someapp.app/Contents/MacOs/someapp somefile.abc
from the terminal opens the file correctly inside the app.
MyApp::MyApp(int& argc, char**argv): QApplication(argc, argv)
{
...
m_MainWindow = new MainWindows();
m_MainWindow->show();
if(argc > 1 && argv[1])
m_MainWindow->openFile(QString(argv[1]);
else
m_MainWindow->showStartupDialog(); // to create a new document
}
Searching around I found that I should somehow implement QFileOpenEvent... how ?
This example looks good... but I don't understand how to combine the constructor and the event...
How do I make this work ?
(OS X 10.6-10.9, app created using Qt 4.8)
The following is the adapted code, that will respond to the OpenFileEvent either on start or during the normal functioning - and also allow opening o file from command line or creating a new file
MyApp::MyApp(int& argc, char**argv): QApplication(argc, argv)
{
...
m_MainWindow = new MainWindows();
m_MainWindow->show();
if(argc > 1 && argv[1])
m_MainWindow->openFile(QString(argv[1]);
else if (m_macFileOpenOnStart != "")
m_MainWindow->openFile(m_macFileOpenOnStart); // open file on start if it exists
else
m_MainWindow->showStartupDialog(); // to create a new document
}
// responds to FileOpenEvent specific for mac
bool MyApp::event(QEvent *event)
{
switch(event->type())
{
case QEvent::FileOpen:
{
QFileOpenEvent * fileOpenEvent = static_cast<QFileOpenEvent *>(event);
if(fileOpenEvent)
{
m_macFileOpenOnStart = fileOpenEvent->file();
if(!m_macFileOpenOnStart.isEmpty())
{
if (m_MainWindow)
{
m_MainWindow->openFile(m_macFileOpenOnStart); // open file in existing window
}
return true;
}
}
}
default:
return QApplication::event(event);
}
return QApplication::event(event);
}
i'm using a QApplication derived class that emits a signal when file is ready:
#ifndef OPENWITHAPPLICATION_H
#define OPENWITHAPPLICATION_H
#include <QApplication>
#include <QFileOpenEvent>
#include <QMessageBox>
class OpenWithApplication : public QApplication
{
Q_OBJECT
public:
QString fileName;
OpenWithApplication(int &argc, char **argv)
: QApplication(argc, argv)
{
}
signals:
void fileReady(QString fn);
protected:
bool event(QEvent *event)
{
if (event->type() == QEvent::FileOpen) {
QFileOpenEvent *openEvent = static_cast<QFileOpenEvent *>(event);
fileName = openEvent->file();
emit fileReady(fileName); // the file is ready
}
return QApplication::event(event);
}
};
#endif // OPENWITHAPPLICATION_H
main.cpp connects created OpenWindowApplication with the MainWindow object so once the file is ready, the signal is emitted and received by it for processing
#include "mainwindow.h"
#include <openwithapplication.h>
int main(int argc, char *argv[])
{
OpenWithApplication a(argc, argv);
MainWindow w;
w.connectOpenWithApp(&a);
w.show();
return a.exec();
}
and MainWindow connects fileReady signal with a lambda func that opens the file and updates widget
void MainWindow::connectOpenWithApp(OpenWithApplication*app) {
connect(app, &OpenWithApplication::fileReady, [this](QString fileName){
bw->open(fileName);
bw->update();
});
}
here's the result:

In Qt, find out that all windows are closed, when QApplication::processEvents() is used?

There is a QApplication::lastWindowClosed() signal. The Qt docs say:
This signal is emitted from QApplication::exec()
when the last visible primary window [...] is closed.
However, I used QApplication::processEvents() instead of QApplication::exec() in a loop. See this minimal example. (save as qapp.h, it must end on .h, and run qmake -project && qmake && make)
#include <QApplication>
#include <QDebug>
#include <QObject>
#include <QMainWindow>
int exitprogram = 0;
class MyMainWindow : public QMainWindow
{
Q_OBJECT
public slots:
void request_exit() {
qDebug() << "exit requested";
exitprogram = 1;
}
};
int main(int argc, char** argv)
{
QApplication app(argc, argv);
MyMainWindow w;
QObject::connect(&app, SIGNAL(lastWindowClosed()),
&w, SLOT(request_exit()));
w.show();
while(!exitprogram)
{
app.processEvents(QEventLoop::AllEvents, 20);
}
}
Is there still a good way to find out, or to even get a signal, if the last such window is being closed?
Whatever reason you have for using processEvents in place of exec is wrong. The two are not equivalent. exec() will, for example, process the deferred deletion events, while processEvents will not. As you've just found out, the lastWindowClosed signal is not emitted either. This should be telling you right there that you're doing it wrong.
The idiomatic Qt way of doing something each time the event loop goes for another iteration, is to use a zero-timeout timer. Those are virtual timers that do not use operating system resources, they are an internal Qt construct.
The example below illustrates the following:
Use of a zero-timeout timer within a QObject.
Use of the State Machine Framework to manage the state of the application. We have three states:
sWindows is the state when the application windows are still shown. The application is set not to quit on the last window being closed.
sSetup is the state reached when the last of the windows was closed. In this state we ask our Object to send its notification signal with the number of times it executed the zero-timeout timer. This will set the proper count in the message label (C++11 code) or in the count label (legacy code). The state machine automatically transitions to the following state.
sMessage is the state when the message labels are shown, and the application is set to quit upon the last window being closed.
The use of a state machine leads to declarative code: you tell the state machine how to behave, without implementing all of the behavior. You only have to implement the behaviors that are specific to your application and not already provided by Qt. The objects that the state machine manages can be very much decoupled, and the code that declares the behavior of the machine is cohesive - it can be all in one function, instead of being spread around. This is considered to be good software design.
Do note that the zero-timeout timer is very diligent: it will force your handler code to execute constantly whenever the event loop is empty. This will force 100% CPU consumption on the core where the GUI thread happens to be executing. If you have nothing to do, you should stop() the timer.
Qt 5 C++11 Code
// https://github.com/KubaO/stackoverflown/tree/master/questions/close-process-19343325
#include <QtWidgets>
int main(int argc, char** argv)
{
QApplication app{argc, argv};
QLabel widget{"Close me :)"};
QLabel message{"Last window was closed"};
int counter = 0;
auto worker = [&]{
counter++;
};
QTimer workerTimer;
QObject::connect(&workerTimer, &QTimer::timeout, worker);
workerTimer.start(0);
QStateMachine machine;
QState sWindows{&machine};
QState sSetup {&machine};
QState sMessage{&machine};
sWindows.assignProperty(qApp, "quitOnLastWindowClosed", false);
sWindows.addTransition(qApp, &QGuiApplication::lastWindowClosed, &sSetup);
QObject::connect(&sSetup, &QState::entered, [&]{
workerTimer.stop();
message.setText(QString("Last window was closed. Count was %1.").arg(counter));
});
sSetup.addTransition(&sMessage);
sMessage.assignProperty(&message, "visible", true);
sMessage.assignProperty(qApp, "quitOnLastWindowClosed", true);
machine.setInitialState(&sWindows);
machine.start();
widget.show();
return app.exec();
}
Qt 4/5 C++11 Code
#include <QApplication>
#include <QLabel>
#include <QStateMachine>
#include <QBasicTimer>
class Object : public QObject {
Q_OBJECT
QBasicTimer m_timer;
int m_counter = 0;
protected:
void timerEvent(QTimerEvent * ev) {
if (ev->timerId() == m_timer.timerId())
m_counter ++;
}
public:
Object(QObject * parent = 0) : QObject{parent} {
m_timer.start(0, this);
}
Q_SLOT void stop() const {
m_timer.stop();
emit countedTo(m_counter);
}
Q_SIGNAL void countedTo(int) const;
};
int main(int argc, char** argv)
{
QApplication app{argc, argv};
Object object;
QLabel widget{"Close me :)"};
QLabel message{"Last window was closed"};
QLabel count;
QStateMachine machine;
QState sWindows{&machine};
QState sSetup{&machine};
QState sMessage{&machine};
sWindows.assignProperty(qApp, "quitOnLastWindowClosed", false);
sWindows.addTransition(qApp, "lastWindowClosed()", &sSetup);
object.connect(&sSetup, SIGNAL(entered()), SLOT(stop()));
count.connect(&object, SIGNAL(countedTo(int)), SLOT(setNum(int)));
sSetup.addTransition(&sMessage);
sMessage.assignProperty(&message, "visible", true);
sMessage.assignProperty(&count, "visible", true);
sMessage.assignProperty(qApp, "quitOnLastWindowClosed", true);
machine.setInitialState(&sWindows);
machine.start();
widget.show();
return app.exec();
}
#include "main.moc"
I modified your code and now it works. I override closeEvent
==> test.cpp <==
#include "windows.hpp"
int exitprogram = 0;
int main(int argc, char** argv)
{
QApplication app(argc, argv);
MyMainWindow w;
w.show();
while(!exitprogram)
{
app.processEvents(QEventLoop::AllEvents, 20);
}
}
==> test.pro <==
TEMPLATE = app
TARGET = test
QT += widgets
INCLUDEPATH += .
HEADERS += windows.hpp
# Input
SOURCES += test.cpp
==> windows.hpp <==
#include <QApplication>
#include <QDebug>
#include <QObject>
#include <QMainWindow>
#include <QCloseEvent>
extern int exitprogram;
class MyMainWindow : public QMainWindow
{
Q_OBJECT
public slots:
void closeEvent(QCloseEvent *event) override {
exitprogram = 1;
event->accept();
}
};