Salome HOME
0022817: EDF GUI: [Regression] Help Browser is not closed when we close SALOME
authormgn <mgn@opencascade.com>
Mon, 19 Jan 2015 14:27:34 +0000 (17:27 +0300)
committervsr <vsr@opencascade.com>
Mon, 26 Jan 2015 14:51:33 +0000 (17:51 +0300)
src/HelpBrowser/CMakeLists.txt
src/HelpBrowser/HelpBrowser.cxx
src/HelpBrowser/HelpBrowser_Application.cxx [new file with mode: 0644]
src/HelpBrowser/HelpBrowser_Application.h [new file with mode: 0644]
src/LightApp/LightApp_Application.cxx
src/LightApp/LightApp_Application.h

index 6a90e2ef5b0114d993dab86aab4ba7571df1345c..0ffbb06cf08a583584bebb3886e6cf2db123e9a4 100644 (file)
@@ -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
 )
 
index 0e77f63caf253f7fa9092f2f471a21a084de71d9..f2e26aca161317d835d0a6690dac9b836c1a0034 100644 (file)
@@ -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
 //
 // 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 <QDir>
 #include <QFile>
 #include <QFileInfo>
+#include <QFileSystemWatcher>
 #include <QLibraryInfo>
 #include <QMessageBox>
 #include <QTextStream>
@@ -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 (file)
index 0000000..23fbd6d
--- /dev/null
@@ -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 <QFile>
+#include <QFileSystemWatcher>
+#include <QTextStream>
+#include <QWidget>
+
+/*!
+  \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 (file)
index 0000000..3ee7c0a
--- /dev/null
@@ -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
index bb0e4a26f9d05579d6df7202a1d2efee93eea2e2..49d8b625bcd467b10d8335be4c745fc1cf19184e 100644 (file)
@@ -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 );
   }
index 54be0df781f7e9e4622c2fd155a5b4a1300b2fa7..d1be7fbb0f5dda7508ad78fc3c57cd03b083bf5e 100644 (file)
@@ -142,6 +142,7 @@ public:
   void                                placeDockWindow( const int, Qt::DockWidgetArea );
 
   virtual void                        start();
+  virtual void                        closeApplication();
 
   virtual void                        contextMenuPopup( const QString&, QMenu*, QString& );