Salome HOME
Unicode support: correct handling of unicode on GUI level
[modules/gui.git] / src / HelpBrowser / HelpBrowser.cxx
1 // Copyright (C) 2007-2016  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License, or (at your option) any later version.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 // File   : HelpBrowser.cxx
23 // Author : Vadim SANDLER, OpenCASCADE S.A.S. (vadim.sandler@opencascade.com)
24 //          Maxim GLIBIN, OpenCASCADE S.A.S. (maxim.glibin@opencascade.com)
25
26 #include "HelpBrowser_Application.h"
27
28 #include <QDir>
29 #include <QFile>
30 #include <QFileInfo>
31 #include <QFileSystemWatcher>
32 #include <QLibraryInfo>
33 #include <QMessageBox>
34 #include <QTextStream>
35 #include <QTimer>
36 #include <QtxResourceMgr.h>
37 #include <QtxTranslator.h>
38 #include <QtxWebBrowser.h>
39
40 #include <iostream>
41
42 namespace
43 {
44   void printHelp()
45   {
46     QFileInfo fi( HelpBrowser_Application::arguments().at(0) );
47
48     std::cout << std::endl;
49     std::cout << "SALOME Help Browser" << std::endl;
50     std::cout << std::endl;
51     std::cout << "usage: " << qUtf8Printable( fi.fileName() ) << " [options] file" << std::endl;
52     std::cout << "    file is a help file to be opened" << std::endl;
53     std::cout << std::endl;
54     std::cout << "Options:" << std::endl;
55     std::cout << "-h, --help         Prints this help and quits." << std::endl;
56     std::cout << "--language=LANG    Use LANG language in menus." << std::endl;
57     //std::cout << "--add=APP_PID      Adds PID of application into the file." << std::endl;
58     //std::cout << "--remove=APP_PID   Removes PID of application from the file." << std::endl;
59     std::cout << std::endl;
60   }
61 }
62
63 class RaiseWindowHelper: public QDialog
64 {
65 public:
66   RaiseWindowHelper( QWidget* parent ) : QDialog( parent, Qt::FramelessWindowHint )
67   {
68     setAttribute( Qt::WA_DeleteOnClose, true );
69     resize( 1, 1 );
70     show();
71     QTimer::singleShot( 100, this, SLOT( close() ) );
72     QTimer::singleShot( 500, parent, SLOT( setFocus() ) );
73   }
74 };
75
76 class HelpBrowser: public QtxWebBrowser
77 {
78 public:
79   HelpBrowser() : QtxWebBrowser()
80   {
81     setAttribute( Qt::WA_DeleteOnClose, false );
82   }
83   ~HelpBrowser()
84   {
85     if ( resourceMgr() )
86       resourceMgr()->save();
87   }
88   void about()
89   {
90     QStringList info;
91     QFile f( ":/COPYING" );
92     f.open( QIODevice::ReadOnly );
93     QTextStream in( &f );
94
95     info << QtxWebBrowser::tr( "%1 has been developed using %2" ).arg( QString( "SALOME %1").arg( tr( "Help Browser" ) ) ).arg( "Qt Solutions Component: Single Application." );
96     info << "";
97     info << in.readAll().split( "\n" );
98
99     QMessageBox::about( this, tr( "About %1" ).arg( tr( "Help Browser" ) ),
100       info.join( "\n" ) );
101   }
102   void load( const QString& url )
103   {
104     QtxWebBrowser::load( url );
105     RaiseWindowHelper* helper = new RaiseWindowHelper( this );
106   }
107 };
108
109 int main( int argc, char **argv )
110 {
111   // Set application name (for preferences)
112   HelpBrowser_Application::setApplicationName( "salome" );
113
114   // Specify application identifier via its name
115   QFileInfo fi( argv[0] );
116
117   // Create application instance
118   HelpBrowser_Application instance( fi.fileName(), argc, argv );
119
120   // Parse command line arguments
121   bool showHelp  = false;
122   bool removeId  = false;
123
124   QString language;
125   QString helpfile;
126   QString anAppID = QString();
127
128   QRegExp rl( "--(.+)=(.+)" );
129   rl.setMinimal( false );
130
131   for ( int i = 1; i < argc; i++ )
132   {
133     QString param = argv[i];
134     if ( param == "--help" || param == "-h" ) {
135       showHelp = true;
136     }
137     else if ( rl.exactMatch( param ) ) {
138       QString opt = rl.cap( 1 );
139       QString val = rl.cap( 2 );
140       if ( opt == "language" )
141         language = val;
142       else if ( opt == "add" )
143         anAppID = val;
144       else if ( opt == "remove" ) {
145         anAppID = val;
146         removeId = true;
147       }
148     }
149     else {
150       helpfile = param;
151     }
152   }
153
154   // Show help and exit if '--help' or '-h' option has been specified via command line
155   if ( showHelp )
156   {
157     printHelp();
158     exit( 0 );
159   }
160
161   // Create a file with an application PIDs. File will be managed by only current application
162   QStringList dirs;
163   dirs << QDir::homePath();
164   dirs << QString( ".config" );
165   dirs << HelpBrowser_Application::applicationName();
166   dirs << QString( "HelpBrowser" );
167   QString aWatchedFile = dirs.join( QDir::separator() );
168
169   QFile aFile( aWatchedFile );
170   if ( instance.sendMessage( helpfile ) )
171   {
172     // Client application.
173     if ( aFile.exists() && !anAppID.isEmpty() )
174     {
175       // Update the content of monitoring file
176       if ( aFile.open( QIODevice::ReadWrite | QIODevice::Text ) )
177       {
178         QTextStream anInStream( &aFile );
179         QString aContent( anInStream.readAll() );
180
181         QRegExp rx("(\\d+)+");
182         QStringList anAppIDs;
183         int pos = 0;
184         while ( pos >= 0 )
185         {
186           pos = rx.indexIn( aContent, pos );
187           if ( pos >= 0 )
188           {
189             anAppIDs += rx.cap( 1 );
190             pos += rx.matchedLength();
191           }
192         }
193
194         if ( removeId )
195         {
196           if ( anAppIDs.contains( anAppID ) )
197             anAppIDs.removeAt( anAppIDs.indexOf( anAppID ) );
198         }
199         else
200         {
201           if ( !anAppIDs.contains( anAppID ) )
202             anAppIDs.append( anAppID );
203         }
204
205         aFile.resize( 0 );
206
207         QTextStream anOutStream( &aFile );
208         
209         foreach (QString anAppId, anAppIDs )
210           anOutStream << anAppId << endl;
211         aFile.close();
212       }
213     }
214     return 0;
215   }
216   else
217   {
218     if ( !anAppID.isEmpty() )
219     {
220       // Clear file system watcher if one has have path
221       instance.clearWatcher();
222
223       QFileInfo wfi( aFile.fileName() );
224       if ( QDir().mkpath( wfi.absolutePath() ) && aFile.open( QIODevice::WriteOnly | QIODevice::Text ) )
225       {
226         // Write date and time when the file was created
227         QTextStream aOutStream( &aFile );
228         aOutStream << anAppID << endl;
229         aFile.close();
230       }
231
232       // Add file path to file system watcher
233       instance.addWatchPath( aWatchedFile );
234     }
235   }
236
237   if ( removeId )
238     return 0;
239
240   // Load translations
241   QtxTranslator tqt, tsal;
242   if ( !language.isEmpty() ) {
243     if ( tqt.load( QString( "qt_%1" ).arg( language ), QLibraryInfo::location( QLibraryInfo::TranslationsPath ) ) )
244       instance.installTranslator( &tqt );
245
246     QDir appDir = HelpBrowser_Application::applicationDirPath();
247     appDir.cdUp(); appDir.cdUp();
248
249     if ( tsal.load( QString( "Qtx_msg_%1" ).arg( language ), appDir.filePath( "share/salome/resources/gui" ) ) )
250       instance.installTranslator( &tsal );
251   }
252
253   // Initialize resource manager (for preferences)
254   QtxResourceMgr* resMgr = new QtxResourceMgr( "HelpBrowser", "%1Config" );
255   resMgr->setCurrentFormat( "xml" );
256   QtxWebBrowser::setResourceMgr( resMgr );
257
258   // Show main window
259   HelpBrowser browser;
260   browser.show();
261
262   // Load file specified via command line
263   if ( helpfile.isEmpty() ) {
264     QString docdir = qgetenv( "DOCUMENTATION_ROOT_DIR" );
265     if ( !docdir.isEmpty() )
266       helpfile = QDir::toNativeSeparators( QString( "%1/index.html" ).arg( docdir ) );
267   }
268
269   if ( !helpfile.isEmpty() ) {
270     browser.load( helpfile );
271   }
272
273   // Finalize main window activation
274   instance.setActivationWindow( &browser );
275
276   QObject::connect( &instance, SIGNAL( messageReceived( QString ) ),
277                     &browser,  SLOT( load ( QString ) ) );
278
279   QObject::connect( instance.fileSysWatcher(), SIGNAL(fileChanged(const QString&)),
280                     &instance, SLOT(updateWatchStatement(const QString&)));
281
282   return instance.exec();
283 }