From bc4c826e687da26b1f96703015aa87a5d60d2e89 Mon Sep 17 00:00:00 2001 From: mgn Date: Mon, 19 Jan 2015 17:27:34 +0300 Subject: [PATCH] 0022817: EDF GUI: [Regression] Help Browser is not closed when we close SALOME --- src/HelpBrowser/CMakeLists.txt | 2 + src/HelpBrowser/HelpBrowser.cxx | 164 +++++++++++++++----- src/HelpBrowser/HelpBrowser_Application.cxx | 124 +++++++++++++++ src/HelpBrowser/HelpBrowser_Application.h | 51 ++++++ src/LightApp/LightApp_Application.cxx | 11 ++ src/LightApp/LightApp_Application.h | 1 + 6 files changed, 315 insertions(+), 38 deletions(-) create mode 100644 src/HelpBrowser/HelpBrowser_Application.cxx create mode 100644 src/HelpBrowser/HelpBrowser_Application.h diff --git a/src/HelpBrowser/CMakeLists.txt b/src/HelpBrowser/CMakeLists.txt index 6a90e2ef5..0ffbb06cf 100644 --- a/src/HelpBrowser/CMakeLists.txt +++ b/src/HelpBrowser/CMakeLists.txt @@ -41,6 +41,7 @@ SET(_link_LIBRARIES SET(_moc_HEADERS qtlocalpeer.h qtsingleapplication.h + HelpBrowser_Application.h ) # --- resources --- @@ -60,6 +61,7 @@ QT4_WRAP_CPP(_moc_SOURCES ${_moc_HEADERS}) SET(_other_SOURCES qtlocalpeer.cpp qtsingleapplication.cpp + HelpBrowser_Application.cxx HelpBrowser.cxx ) diff --git a/src/HelpBrowser/HelpBrowser.cxx b/src/HelpBrowser/HelpBrowser.cxx index 0e77f63ca..f2e26aca1 100644 --- a/src/HelpBrowser/HelpBrowser.cxx +++ b/src/HelpBrowser/HelpBrowser.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2013 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE // // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -21,11 +21,14 @@ // // File : HelpBrowser.cxx // Author : Vadim SANDLER, OpenCASCADE S.A.S. (vadim.sandler@opencascade.com) +// Maxim GLIBIN, OpenCASCADE S.A.S. (maxim.glibin@opencascade.com) + +#include "HelpBrowser_Application.h" -#include "qtsingleapplication.h" #include #include #include +#include #include #include #include @@ -40,7 +43,7 @@ namespace { void printHelp() { - QFileInfo fi( QtSingleApplication::arguments().at(0) ); + QFileInfo fi( HelpBrowser_Application::arguments().at(0) ); std::cout << std::endl; std::cout << "SALOME Help Browser" << std::endl; @@ -51,6 +54,8 @@ namespace std::cout << "Options:" << std::endl; std::cout << "-h, --help Prints this help and quits." << std::endl; std::cout << "--language=LANG Use LANG language in menus." << std::endl; + //std::cout << "--add=APP_PID Adds PID of application into the file." << std::endl; + //std::cout << "--remove=APP_PID Removes PID of application from the file." << std::endl; std::cout << std::endl; } } @@ -92,7 +97,7 @@ public: info << in.readAll().split( "\n" ); QMessageBox::about( this, tr( "About %1" ).arg( tr( "Help Browser" ) ), - info.join( "\n" ) ); + info.join( "\n" ) ); } void load( const QString& url ) { @@ -103,73 +108,154 @@ public: int main( int argc, char **argv ) { - // set application name (for preferences) - - QtSingleApplication::setApplicationName( "salome" ); + // Set application name (for preferences) + HelpBrowser_Application::setApplicationName( "salome" ); - // specify application identifier via its name + // Specify application identifier via its name QFileInfo fi( argv[0] ); - // create application instance - - QtSingleApplication instance( fi.fileName(), argc, argv ); + // Create application instance + HelpBrowser_Application instance( fi.fileName(), argc, argv ); - // parse command line arguments + // Parse command line arguments + bool showHelp = false; + bool removeId = false; - bool showHelp = false; QString language; QString helpfile; + QString anAppID = QString(); - QRegExp rl( "--language=(.+)" ); + QRegExp rl( "--(.+)=(.+)" ); rl.setMinimal( false ); - for ( int a = 1; a < argc; ++a ) { - QString param = argv[a]; - if ( param == "--help" || param == "-h" ) + for ( int i = 1; i < argc; i++ ) + { + QString param = argv[i]; + if ( param == "--help" || param == "-h" ) { showHelp = true; - else if ( rl.exactMatch( param ) ) - language = rl.cap( 1 ); - else + } + else if ( rl.exactMatch( param ) ) { + QString opt = rl.cap( 1 ); + QString val = rl.cap( 2 ); + if ( opt == "language" ) + language = val; + else if ( opt == "add" ) + anAppID = val; + else if ( opt == "remove" ) { + anAppID = val; + removeId = true; + } + } + else { helpfile = param; + } } - // show help and exit if --help or -h option has been specified via command line - - if ( showHelp ) { + // Show help and exit if '--help' or '-h' option has been specified via command line + if ( showHelp ) + { printHelp(); exit( 0 ); } + // Create a file with an application PIDs. File will be managed by only current application + QStringList dirs; + dirs << QDir::homePath(); + dirs << QString( ".config" ); + dirs << HelpBrowser_Application::applicationName(); + dirs << QString( "HelpBrowser" ); + QString aWatchedFile = dirs.join( QDir::separator() ); + + QFile aFile( aWatchedFile ); if ( instance.sendMessage( helpfile ) ) + { + // Client application. + if ( aFile.exists() && !anAppID.isEmpty() ) + { + // Update the content of monitoring file + if ( aFile.open( QIODevice::ReadWrite | QIODevice::Text ) ) + { + QTextStream anInStream( &aFile ); + QString aContent( anInStream.readAll() ); + + QRegExp rx("(\\d+)+"); + QStringList anAppIDs; + int pos = 0; + while ( pos >= 0 ) + { + pos = rx.indexIn( aContent, pos ); + if ( pos >= 0 ) + { + anAppIDs += rx.cap( 1 ); + pos += rx.matchedLength(); + } + } + + if ( removeId ) + { + if ( anAppIDs.contains( anAppID ) ) + anAppIDs.removeAt( anAppIDs.indexOf( anAppID ) ); + } + else + { + if ( !anAppIDs.contains( anAppID ) ) + anAppIDs.append( anAppID ); + } + + aFile.resize( 0 ); + + QTextStream anOutStream( &aFile ); + + foreach (QString anAppId, anAppIDs ) + anOutStream << anAppId << endl; + aFile.close(); + } + } return 0; + } + else + { + if ( !anAppID.isEmpty() ) + { + // Clear file system watcher if one has have path + instance.clearWatcher(); + + if ( aFile.open( QIODevice::WriteOnly | QIODevice::Text ) ) + { + // Write date and time when the file was created + QTextStream aOutStream( &aFile ); + aOutStream << anAppID << endl; + aFile.close(); + } + + // Add file path to file system watcher + instance.addWatchPath( aWatchedFile ); + } + } - // load translations - + // Load translations QtxTranslator tqt, tsal; if ( !language.isEmpty() ) { if ( tqt.load( QString( "qt_%1" ).arg( language ), QLibraryInfo::location( QLibraryInfo::TranslationsPath ) ) ) instance.installTranslator( &tqt ); - QDir appDir = QtSingleApplication::applicationDirPath(); - appDir.cdUp(); appDir.cdUp(); - + QDir appDir = HelpBrowser_Application::applicationDirPath(); + appDir.cdUp(); appDir.cdUp(); + if ( tsal.load( QString( "Qtx_msg_%1" ).arg( language ), appDir.filePath( "share/salome/resources/gui" ) ) ) instance.installTranslator( &tsal ); } - // initialize resource manager (for preferences) - + // Initialize resource manager (for preferences) QtxResourceMgr* resMgr = new QtxResourceMgr( "HelpBrowser", "%1Config" ); resMgr->setCurrentFormat( "xml" ); QtxWebBrowser::setResourceMgr( resMgr ); - // show main window - + // Show main window HelpBrowser browser; browser.show(); - // load file specified via command line - + // Load file specified via command line if ( helpfile.isEmpty() ) { QString docdir = qgetenv( "DOCUMENTATION_ROOT_DIR" ); if ( !docdir.isEmpty() ) @@ -180,12 +266,14 @@ int main( int argc, char **argv ) browser.load( helpfile ); } - // finalize main window activation - + // Finalize main window activation instance.setActivationWindow( &browser ); - + QObject::connect( &instance, SIGNAL( messageReceived( QString ) ), - &browser, SLOT( load ( QString ) ) ); + &browser, SLOT( load ( QString ) ) ); + + QObject::connect( instance.fileSysWatcher(), SIGNAL(fileChanged(const QString&)), + &instance, SLOT(updateWatchStatement(const QString&))); return instance.exec(); } diff --git a/src/HelpBrowser/HelpBrowser_Application.cxx b/src/HelpBrowser/HelpBrowser_Application.cxx new file mode 100644 index 000000000..23fbd6de8 --- /dev/null +++ b/src/HelpBrowser/HelpBrowser_Application.cxx @@ -0,0 +1,124 @@ +// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : HelpBrowser_Application.cpp +// Author : Maxim GLIBIN, OpenCASCADE S.A.S. (maxim.glibin@opencascade.com) + +#include "HelpBrowser_Application.h" + +#include +#include +#include +#include + +/*! + \brief Constructor + */ +HelpBrowser_Application::HelpBrowser_Application(const QString& appId, int& argc, char** argv) + : QtSingleApplication(appId, argc, argv) +{ + watcher = new QFileSystemWatcher(); +} + +/*! + \brief Returns the file system watcher for monitoring files for modifications. +*/ +QFileSystemWatcher* HelpBrowser_Application::fileSysWatcher() const +{ + return watcher; +} + +/*! + \brief Removes the specified paths from the file system watcher and corresponding + files if \a isDeleteFile flag is set. By default, this flag is \c true. +*/ +void HelpBrowser_Application::clearWatcher(bool isDeleteFile) +{ + QStringList aFiles = watcher->files(); + foreach ( QString aFilePath, aFiles ) + { + removeWatchPath( aFilePath ); + if ( isDeleteFile ) + QFile::remove( aFilePath ); + } +} + +/*! + Adds the path to the file system watcher if the file exists. +*/ +void HelpBrowser_Application::addWatchPath(const QString& thePath) +{ + if ( thePath.isEmpty() ) + { + qWarning("HelpBrowser_Application::addWatchPath: path is empty."); + return; + } + watcher->addPath( thePath ); +} + +/*! + Removes the path to the file system watcher. +*/ +void HelpBrowser_Application::removeWatchPath(const QString& thePath) +{ + if (thePath.isEmpty()) + { + qWarning("HelpBrowser_Application::removeWatchPath: path is empty."); + return; + } + watcher->removePath( thePath ); +} + +/*! + Updates the statement of watcher. If file becomes empty it is removed and + calls quit() function for application. +*/ +void HelpBrowser_Application::updateWatchStatement(const QString& thePath) +{ + if ( thePath.isEmpty() ) + { + qWarning("HelpBrowser_Application::updateWatchStatement: path is empty."); + return; + } + + if ( !QFile::exists( thePath ) ) + removeWatchPath( thePath ); + + // Get list of paths to files that are being watched + bool isClose = false; + if ( watcher->files().contains( thePath ) ) + { + QFile aFile( thePath ); + if ( aFile.open( QIODevice::ReadOnly | QIODevice::Text ) ) + { + QTextStream anInSteam( &aFile ); + if ( anInSteam.readAll().isEmpty() ) + isClose = true; + aFile.close(); + } + } + + if ( isClose ) + { + QFile::remove( thePath ); + this->quit(); + } +} diff --git a/src/HelpBrowser/HelpBrowser_Application.h b/src/HelpBrowser/HelpBrowser_Application.h new file mode 100644 index 000000000..3ee7c0a88 --- /dev/null +++ b/src/HelpBrowser/HelpBrowser_Application.h @@ -0,0 +1,51 @@ +// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; either +// version 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com +// +// File : HelpBrowser_Application.h +// Author : Maxim GLIBIN, OpenCASCADE S.A.S. (maxim.glibin@opencascade.com) + +#ifndef HELPBROWSER_APPLICATION_H +#define HELPBROWSER_APPLICATION_H + +#include "qtsingleapplication.h" + +class QFileSystemWatcher; + +class HelpBrowser_Application : public QtSingleApplication +{ + Q_OBJECT + +public: + HelpBrowser_Application(const QString& id, int& argc, char** argv); + + QFileSystemWatcher* fileSysWatcher() const; + void addWatchPath(const QString& thePath); + void removeWatchPath(const QString& thePath); + void clearWatcher(bool isDeleteFile = true); + +public Q_SLOTS: + void updateWatchStatement(const QString& thePath); + +private: + QFileSystemWatcher* watcher; +}; + +#endif // HELPBROWSER_APPLICATION_H diff --git a/src/LightApp/LightApp_Application.cxx b/src/LightApp/LightApp_Application.cxx index bb0e4a26f..49d8b625b 100644 --- a/src/LightApp/LightApp_Application.cxx +++ b/src/LightApp/LightApp_Application.cxx @@ -427,6 +427,15 @@ void LightApp_Application::start() LightApp_EventFilter::Init(); } +/*!Closeapplication.*/ +void LightApp_Application::closeApplication() +{ + QProcess::startDetached( "HelpBrowser", + QStringList() << QString( "--remove=%1" ).arg( QApplication::instance()->applicationPid() ) ); + + CAM_Application::closeApplication(); +} + /*!Gets application name.*/ QString LightApp_Application::applicationName() const { @@ -1108,6 +1117,7 @@ void LightApp_Application::onHelpContentsModule() else { QStringList parameters; parameters << QString( "--language=%1" ).arg( resMgr->stringValue( "language", "language" ) ); + parameters << QString( "--add=%1" ).arg( QApplication::instance()->applicationPid() ); parameters << helpFile; QProcess::startDetached( "HelpBrowser", parameters ); } @@ -1178,6 +1188,7 @@ void LightApp_Application::onHelpContextModule( const QString& theComponentName, else { QStringList parameters; parameters << QString( "--language=%1" ).arg( resMgr->stringValue( "language", "language" ) ); + parameters << QString( "--add=%1" ).arg( QApplication::instance()->applicationPid() ); parameters << QString( "%1#%2" ).arg( helpFile ).arg( context ); QProcess::startDetached( "HelpBrowser", parameters ); } diff --git a/src/LightApp/LightApp_Application.h b/src/LightApp/LightApp_Application.h index 54be0df78..d1be7fbb0 100644 --- a/src/LightApp/LightApp_Application.h +++ b/src/LightApp/LightApp_Application.h @@ -142,6 +142,7 @@ public: void placeDockWindow( const int, Qt::DockWidgetArea ); virtual void start(); + virtual void closeApplication(); virtual void contextMenuPopup( const QString&, QMenu*, QString& ); -- 2.39.2