diff --git a/Daemon.cpp b/Daemon.cpp index 7ca28a6f..d34712a3 100644 --- a/Daemon.cpp +++ b/Daemon.cpp @@ -265,5 +265,5 @@ namespace i2p return true; } - } + } } diff --git a/Daemon.h b/Daemon.h index 7467a518..fa4f47ec 100644 --- a/Daemon.h +++ b/Daemon.h @@ -33,8 +33,8 @@ namespace i2p #if defined(QT_GUI_LIB) // check if QT #define Daemon i2p::util::DaemonQT::Instance() - class DaemonQTImpl; - class DaemonQT: public i2p::util::Daemon_Singleton + // dummy, invoked from RunQT + class DaemonQT: public i2p::util::Daemon_Singleton { public: @@ -43,14 +43,7 @@ namespace i2p static DaemonQT instance; return instance; } - - bool init(int argc, char* argv[]); - void run (); - - private: - - std::shared_ptr m_Impl; - }; + }; #elif defined(_WIN32) #define Daemon i2p::util::DaemonWin32::Instance() diff --git a/i2pd.cpp b/i2pd.cpp index f3ac6b3f..589274f5 100644 --- a/i2pd.cpp +++ b/i2pd.cpp @@ -1,9 +1,24 @@ #include #include "Daemon.h" +#if defined(QT_GUI_LIB) + +namespace i2p +{ +namespace qt +{ + int RunQT (int argc, char* argv[]); +} +} int main( int argc, char* argv[] ) { - if (Daemon.init(argc, argv)) + return i2p::qt::RunQT (argc, argv); +} + +#else +int main( int argc, char* argv[] ) +{ + if (Daemon.init(argc, argv)) { if (Daemon.start()) Daemon.run (); @@ -11,6 +26,7 @@ int main( int argc, char* argv[] ) } return EXIT_SUCCESS; } +#endif #ifdef _WIN32 #include diff --git a/qt/.gitignore b/qt/.gitignore index e3a93c87..8fe8328a 100644 --- a/qt/.gitignore +++ b/qt/.gitignore @@ -1,2 +1,3 @@ /build-i2pd_qt-Android_armeabi_v7a_GCC_4_9_Qt_5_6_0-Debug/ /build-i2pd_qt-Desktop_Qt_5_6_0_GCC_64bit-Debug/ +/build-i2pd_qt-Android_x86_GCC_4_9_Qt_5_6_0-Debug/ diff --git a/qt/i2pd_qt/DaemonQT.cpp b/qt/i2pd_qt/DaemonQT.cpp index 41242e3b..2f8a824f 100644 --- a/qt/i2pd_qt/DaemonQT.cpp +++ b/qt/i2pd_qt/DaemonQT.cpp @@ -1,64 +1,165 @@ -#include +#include "DaemonQT.h" +#include "../../Daemon.h" #include "mainwindow.h" +#include #include -#include -#include "../../Daemon.h" +#include +#include namespace i2p { -namespace util +namespace qt { - class DaemonQTImpl: public std::enable_shared_from_this + Worker::Worker (DaemonQTImpl& daemon): + m_Daemon (daemon) + { + } + + void Worker::startDaemon() { - public: + qDebug("Performing daemon start..."); + m_Daemon.start(); + qDebug("Daemon started."); + emit resultReady(); + } + void Worker::restartDaemon() + { + qDebug("Performing daemon restart..."); + m_Daemon.restart(); + qDebug("Daemon restarted."); + emit resultReady(); + } + void Worker::stopDaemon() { + qDebug("Performing daemon stop..."); + m_Daemon.stop(); + qDebug("Daemon stopped."); + emit resultReady(); + } - DaemonQTImpl (int argc, char* argv[]): - m_App (argc, argv) - { - } + Controller::Controller(DaemonQTImpl& daemon): + m_Daemon (daemon) + { + Worker *worker = new Worker (m_Daemon); + worker->moveToThread(&workerThread); + connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater); + connect(this, &Controller::startDaemon, worker, &Worker::startDaemon); + connect(this, &Controller::stopDaemon, worker, &Worker::stopDaemon); + connect(this, &Controller::restartDaemon, worker, &Worker::restartDaemon); + connect(worker, &Worker::resultReady, this, &Controller::handleResults); + workerThread.start(); + } + Controller::~Controller() + { + qDebug("Closing and waiting for daemon worker thread..."); + workerThread.quit(); + workerThread.wait(); + qDebug("Waiting for daemon worker thread finished."); + if(m_Daemon.isRunning()) + { + qDebug("Stopping the daemon..."); + m_Daemon.stop(); + qDebug("Stopped the daemon."); + } + } + + DaemonQTImpl::DaemonQTImpl (): + mutex(nullptr), m_IsRunning(nullptr), m_RunningChangedCallback(nullptr) + { + } + + DaemonQTImpl::~DaemonQTImpl () + { + delete mutex; + } - void Run () - { - MainWindow w; - w.show (); - m_App.exec(); - } + bool DaemonQTImpl::init(int argc, char* argv[]) + { + mutex=new QMutex(QMutex::Recursive); + setRunningCallback(0); + m_IsRunning=false; + return Daemon.init(argc,argv); - private: + } + void DaemonQTImpl::deinit() + { + delete mutex; mutex = nullptr; + } - void StartDaemon () - { - Daemon.start (); - } + void DaemonQTImpl::start() + { + QMutexLocker locker(mutex); + setRunning(true); + Daemon.start(); + } - void StopDaemon () - { - Daemon.stop (); - } + void DaemonQTImpl::stop() + { + QMutexLocker locker(mutex); + Daemon.stop(); + setRunning(false); + } - bool IsRunning () const - { - return Daemon.running; - } + void DaemonQTImpl::restart() + { + QMutexLocker locker(mutex); + stop(); + start(); + } - private: + void DaemonQTImpl::setRunningCallback(runningChangedCallback cb) + { + m_RunningChangedCallback = cb; + } - QApplication m_App; - }; + bool DaemonQTImpl::isRunning() + { + return m_IsRunning; + } - bool DaemonQT::init(int argc, char* argv[]) + void DaemonQTImpl::setRunning(bool newValue) { - m_Impl = std::make_shared (argc, argv); - return Daemon_Singleton::init(argc, argv); + bool oldValue = m_IsRunning; + if(oldValue!=newValue) + { + m_IsRunning = newValue; + if(m_RunningChangedCallback) + m_RunningChangedCallback(); + } } - void DaemonQT::run () + int RunQT (int argc, char* argv[]) { - if (m_Impl) + //int result = runGUI(argc, argv); + //QMessageBox::information(0,"Debug","runGUI completed"); + QApplication app(argc, argv); + DaemonQTImpl daemon; + qDebug("Initialising the daemon..."); + bool daemonInitSuccess = daemon.init(argc, argv); + if(!daemonInitSuccess) + { + QMessageBox::critical(0, "Error", "Daemon init failed"); + return 1; + } + qDebug("Initialised, creating the main window..."); + MainWindow w; + qDebug("Before main window.show()..."); + w.show (); + int result; { - m_Impl->Run (); - m_Impl = nullptr; + /* i2p::qt::Controller daemonQtController(daemon); + qDebug("Starting the daemon..."); + emit daemonQtController.startDaemon(); + qDebug("Starting gui event loop...");*/ + daemon.start (); + result = app.exec(); + daemon.stop (); } + daemon.deinit(); + //QMessageBox::information(&w, "Debug", "demon stopped"); + //exit(result); //return from main() causes intermittent sigsegv bugs in some Androids. exit() is a workaround for this + qDebug("Exiting the application"); + return result; } } } + diff --git a/qt/i2pd_qt/DaemonQT.h b/qt/i2pd_qt/DaemonQT.h new file mode 100644 index 00000000..85a9dccd --- /dev/null +++ b/qt/i2pd_qt/DaemonQT.h @@ -0,0 +1,82 @@ +#ifndef DAEMONQT_H +#define DAEMONQT_H + +#include +#include +#include + +namespace i2p +{ +namespace qt +{ + class DaemonQTImpl + { + public: + + DaemonQTImpl (); + ~DaemonQTImpl (); + + typedef void (*runningChangedCallback)(); + + /** + * @brief init + * @param argc + * @param argv + * @return success + */ + bool init(int argc, char* argv[]); + void deinit(); + void start(); + void stop(); + void restart(); + void setRunningCallback(runningChangedCallback cb); + bool isRunning(); + private: + void setRunning(bool running); + private: + QMutex* mutex; + bool m_IsRunning; + runningChangedCallback m_RunningChangedCallback; + }; + + class Worker : public QObject + { + Q_OBJECT + public: + + Worker (DaemonQTImpl& daemon); + + private: + + DaemonQTImpl& m_Daemon; + + public slots: + void startDaemon(); + void restartDaemon(); + void stopDaemon(); + + signals: + void resultReady(); + }; + + class Controller : public QObject + { + Q_OBJECT + QThread workerThread; + public: + Controller(DaemonQTImpl& daemon); + ~Controller(); + private: + DaemonQTImpl& m_Daemon; + + public slots: + void handleResults(){} + signals: + void startDaemon(); + void stopDaemon(); + void restartDaemon(); + }; +} +} + +#endif // DAEMONQT_H diff --git a/qt/i2pd_qt/android/AndroidManifest.xml b/qt/i2pd_qt/android/AndroidManifest.xml index 603776e7..73f6eb6d 100644 --- a/qt/i2pd_qt/android/AndroidManifest.xml +++ b/qt/i2pd_qt/android/AndroidManifest.xml @@ -1,6 +1,6 @@ - + @@ -46,7 +46,7 @@ - +