Salome HOME
Porting to the Qt-5.6.x.
[modules/gui.git] / src / Qtx / QtxWebBrowser.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
23 // File:      QtxWebBrowser.cxx
24 // Author:    Roman NIKOLAEV
25
26 #include "QtxWebBrowser.h"
27 #include "QtxResourceMgr.h"
28 #include "QtxSearchTool.h"
29
30 #include <QApplication>
31 #include <QButtonGroup>
32 #include <QCheckBox>
33 #include <QFileDialog>
34 #include <QFileInfo>
35 #include <QGridLayout>
36 #include <QHBoxLayout>
37 #include <QLabel>
38 #include <QMenu>
39 #include <QMenuBar>
40 #include <QMessageBox>
41 #include <QPushButton>
42 #include <QRadioButton>
43 #include <QStatusBar>
44 #include <QToolBar>
45 #include <QVBoxLayout>
46 #if QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
47   #include <QWebView>
48 #else
49   #include <QWebEngineView>
50 #endif
51 #include <QProcess>
52
53 // RNV:
54 // Since from Qt 5.6.0 version QtWebKit tool was removed,
55 // QtxWebBroswer is ported on QtWebEngine. So if it is built with Qt-5.6.0
56 // and newer, it uses QtWebEngine. But for Qt-5.5.1 and Qt4 QtWebKit tool
57 // is used, to provide backward compatibility.
58
59 namespace
60 {
61   bool isLocalFile( const QUrl& url )
62   {
63     QFileInfo fi( url.path() );
64     return fi.exists();
65   }
66 }
67
68 /*!
69   \class QtxWebBrowser::Searcher
70   \brief A class is used with QtxSearchTool in order to search text within the web page 
71   \internal
72 */
73
74 class QtxWebBrowser::Searcher : public QtxSearchTool::Searcher
75 {
76 public:
77   Searcher( WebView* );
78   ~Searcher();
79
80   bool find( const QString&, QtxSearchTool* );
81   bool findNext( const QString&, QtxSearchTool* );
82   bool findPrevious( const QString&, QtxSearchTool* );
83   bool findFirst( const QString&, QtxSearchTool* );
84   bool findLast( const QString&, QtxSearchTool* );
85
86 private:
87   WebView* myView;
88 };
89
90 /*!
91   \brief Constructor
92   \param view web view
93   \internal
94 */
95 QtxWebBrowser::Searcher::Searcher( WebView* view ) : myView( view )
96 {
97 }
98
99 /*!
100   \brief Destructor
101   \internal
102 */
103 QtxWebBrowser::Searcher::~Searcher()
104 {
105 }
106
107 /*!
108   \brief Find specified text
109   \param text text being searched
110   \param st search tool
111   \return \c true if text has been found or \c false otherwise
112   \internal
113 */
114 bool QtxWebBrowser::Searcher::find( const QString& text, QtxSearchTool* st )
115 {
116   WebPage::FindFlags fl = 0;
117   if ( st->isCaseSensitive() ) fl = fl | WebPage::FindCaseSensitively;
118 #if QT_VERSION < QT_VERSION_CHECK(5, 6, 0) 
119   if ( st->isSearchWrapped() ) fl = fl | WebPage::FindWrapsAroundDocument;
120   return myView->findText( text, fl );
121 #else
122   myView->findText( text, fl, [this](bool found) { return found; });  
123 #endif    
124 }
125
126 /*!
127   \brief Find next entry of specified text starting from the current position
128   \param text text being searched
129   \param st search tool
130   \return \c true if text has been found or \c false otherwise
131   \internal
132 */
133 bool QtxWebBrowser::Searcher::findNext( const QString& text, QtxSearchTool* st )
134 {
135   return find( text, st );
136 }
137
138 /*!
139   \brief Find previous entry of specified text starting from the current position
140   \param text text being searched
141   \param st search tool
142   \return \c true if text has been found or \c false otherwise
143   \internal
144 */
145 bool QtxWebBrowser::Searcher::findPrevious( const QString& text, QtxSearchTool* st )
146 {
147   WebPage::FindFlags fl = WebPage::FindBackward;
148   if ( st->isCaseSensitive() ) fl = fl | WebPage::FindCaseSensitively;
149 #if QT_VERSION < QT_VERSION_CHECK(5, 6, 0) 
150   if ( st->isSearchWrapped() ) fl = fl | WebPage::FindWrapsAroundDocument;
151   return myView->findText( text, fl );
152 #else
153   myView->findText( text, fl, [this](bool found) { return found; });
154 #endif 
155 }
156
157 /*!
158   \brief Find first entry of specified text; does nothing in this implementation
159   \param text text being searched
160   \param st search tool
161   \return \c true if text has been found or \c false otherwise
162   \internal
163 */
164 bool QtxWebBrowser::Searcher::findFirst( const QString& /*text*/, QtxSearchTool* /*st*/ )
165 {
166   return false;
167 }
168
169 /*!
170   \brief Find last entry of specified text; does nothing in this implementation
171   \param text text being searched
172   \param st search tool
173   \return \c true if text has been found or \c false otherwise
174   \internal
175 */
176 bool QtxWebBrowser::Searcher::findLast( const QString& /*text*/, QtxSearchTool* /*st*/)
177 {
178   return false;
179 }
180
181
182 /*!
183   \class QtxWebBrowser::Downloader
184   \brief A dialog box that is used to process file links
185   \internal
186 */
187
188 /*!
189   \brief Constructor
190   \param fileName name of the file being opened
191   \param action default action to be used for the file
192   \param program default program to be used to open the file
193   \param parent parent widget
194   \internal
195 */
196 QtxWebBrowser::Downloader::Downloader( const QString& fileName, int action, const QString& program, QWidget* parent )
197   : QDialog( parent ), myProgram( program )
198 {
199   setModal( true );
200   setWindowTitle( QtxWebBrowser::tr( "Open URL" ) );
201   setSizeGripEnabled( true );
202
203   myFileName = new QLabel( this );
204   QRadioButton* rbOpen = new QRadioButton( QtxWebBrowser::tr( "Open in" ), this );
205   QRadioButton* rbSave = new QRadioButton( QtxWebBrowser::tr( "Save file" ), this );
206   myBrowse = new QPushButton( QtxWebBrowser::tr( "&Browse..." ),     this );
207   myRepeat = new QCheckBox( QtxWebBrowser::tr( "Use this program for all files of this type" ), this );
208
209   myAction = new QButtonGroup( this );
210   myAction->addButton( rbOpen, mOpen );
211   myAction->addButton( rbSave, mSave );
212
213   QPushButton* btnOk     = new QPushButton( QtxWebBrowser::tr( "&OK" ),     this );
214   QPushButton* btnCancel = new QPushButton( QtxWebBrowser::tr( "&Cancel" ), this );
215
216   QFont f = myFileName->font(); f.setBold( true ); myFileName->setFont( f );
217
218   QHBoxLayout* btnLayout = new QHBoxLayout;
219   btnLayout->addWidget( btnOk );
220   btnLayout->addStretch();
221   btnLayout->addWidget( btnCancel );
222
223   QGridLayout* l = new QGridLayout( this );
224   l->addWidget( new QLabel( QtxWebBrowser::tr( "You are opening the file" ), this ), 
225                             0, 0, 1, 4 );
226   l->addWidget( myFileName, 1, 1, 1, 3 );
227   l->addWidget( new QLabel( QtxWebBrowser::tr( "Please choose the action to be done" ), this ), 
228                             3, 0, 1, 4 );
229   l->addWidget( rbOpen,     4, 1, 1, 1 );
230   l->addWidget( myBrowse,   4, 2, 1, 1 );
231   l->addWidget( rbSave,     5, 1, 1, 3 );
232   l->addWidget( myRepeat,   6, 1, 1, 3 );
233   l->addLayout( btnLayout,  7, 0, 1, 4 );
234   l->setRowMinimumHeight( 2, 10 );
235
236   connect( myAction,  SIGNAL( buttonClicked( int ) ), this, SLOT( setAction( int ) ) );
237   connect( myBrowse,  SIGNAL( clicked() ), this, SLOT( browse() ) );
238   connect( btnOk,     SIGNAL( clicked() ), this, SLOT( accept() ) );
239   connect( btnCancel, SIGNAL( clicked() ), this, SLOT( reject() ) );
240
241   myFileName->setText( QFileInfo( fileName ).fileName() );
242   myAction->button( action )->click();
243 }
244
245 /*!
246   \brief Destructor
247 */
248 QtxWebBrowser::Downloader::~Downloader()
249 {
250 }
251
252 /*!
253   \brief Get action selected by the user
254   \return action being selected:
255   - 0: open file
256   - 1: save file
257 */
258 int QtxWebBrowser::Downloader::action() const
259 {
260   return myAction->checkedId();
261 }
262
263 /*!
264   \brief Get "repeat action for all such files" flag status
265   \return \c true if chosen action should be automatically done for all files of given type
266   or \c false otherwise
267 */
268 bool QtxWebBrowser::Downloader::isRepeatAction() const
269 {
270   return myRepeat->isChecked();
271 }
272
273 /*!
274   \brief Get program to be used to open chosen file
275   \return path to the program
276 */
277 QString QtxWebBrowser::Downloader::program() const
278 {
279   return myProgram;
280 }
281
282 /*!
283   \brief Set current action
284   \param action action to be done for the file:
285   - 0: open file
286   - 1: save file
287 */
288 void QtxWebBrowser::Downloader::setAction( int action )
289 {
290   myBrowse->setEnabled( action == mOpen );
291 }
292
293 /*!
294   \brief Browse program to be used to open the file
295 */
296 void QtxWebBrowser::Downloader::browse()
297 {
298   QString program = QFileDialog::getOpenFileName( this, QtxWebBrowser::tr( "Choose program" ), myProgram );
299   if ( !program.isEmpty() ) myProgram = program;
300 }
301
302
303 /*!
304   \class QtxWebBrowser
305
306   \brief The QtxWebBrowser provides a window that can display html pages from local file system.
307   
308   Only one instance of the QtxWebBrowser class can be created. To access the browser 
309   window, use static method QtxWebBrowser::webBrowser(), which creates an
310   instance of the QtxWebBrowser widget (if it is not yet created) and returns a
311   pointer to it.
312
313   You should not destroy this instance - it is done automatically after
314   closing of the browser window. To close window programmatically use 
315   method close().
316
317   Optionally resource manager can be specified to automatically store
318   action (open/save) and program to be used to download files in the
319   application preferences.
320
321   The following sample demonstrates how to use web browser.
322   In this code the browser window is created, /data/index.html file is opened
323   and scrolled to the "anchor1" anchor on this page.
324
325   \code
326   // initialize application
327   // - set resource manager
328   QtxWebBrowser::setResourceMgr(myResourceMgr);
329   // ...
330   // show HTML page
331   QtxWebBrowser::loadUrl("file:///data/index.html", "anchor1");
332   \endcode
333 */
334
335 //! The only one instance of web browser
336 QtxWebBrowser* QtxWebBrowser::myBrowser = 0;
337
338 //! Resources manager
339 QtxResourceMgr* QtxWebBrowser::myResourceMgr = 0;
340
341 /*!
342   \brief Constructor.
343   Construct the web browser.
344 */
345 QtxWebBrowser::QtxWebBrowser( ) : QMainWindow( 0 )
346 {
347   Q_INIT_RESOURCE( Qtx );
348
349   setAttribute( Qt::WA_DeleteOnClose );
350   statusBar();
351
352   QWidget* frame = new QWidget( this );
353
354   myWebView = new WebView( frame );
355
356   myWebView->pageAction( WebPage::Copy )->setShortcut( QKeySequence::Copy );
357   myWebView->addAction( myWebView->pageAction( WebPage::Copy ) );
358 #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)
359   myWebView->pageAction( WebPage::OpenLinkInNewWindow )->setVisible( false );
360 #endif  
361   myWebView->pageAction( WebPage::Back )->setText( tr( "Go Back" ) );
362   myWebView->pageAction( WebPage::Forward )->setText( tr( "Go Forward" ) );
363   myWebView->pageAction( WebPage::Reload )->setText( tr( "Refresh" ) );
364 #if QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
365   myWebView->page()->setLinkDelegationPolicy( WebPage::DelegateAllLinks );
366 #endif
367   
368   myFindPanel = new QtxSearchTool( frame, myWebView,
369 #if QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
370                                    QtxSearchTool::Basic | QtxSearchTool::Case | QtxSearchTool::Wrap,
371 #else
372                                    QtxSearchTool::Basic | QtxSearchTool::Case,
373 #endif                             
374                                    Qt::Horizontal );
375   myFindPanel->setFrameStyle( QFrame::NoFrame | QFrame::Plain );
376   myFindPanel->setActivators( QtxSearchTool::SlashKey );
377   myFindPanel->setSearcher( new Searcher( myWebView ) );
378   myFindPanel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
379
380   QToolBar* toolbar = addToolBar( tr( "Navigation" ) );
381   toolbar->addAction( myWebView->pageAction( WebPage::Back ) );
382   toolbar->addAction( myWebView->pageAction( WebPage::Forward ) );
383   toolbar->addAction( myWebView->pageAction( WebPage::Reload ) );
384
385   QMenu* fileMenu = menuBar()->addMenu( tr( "&File" ) );
386   fileMenu->addAction( QPixmap( ":/images/open.png" ), tr( "&Open..." ), 
387                        this, SLOT( open() ),
388                        QKeySequence( QKeySequence::Open ) );
389   fileMenu->addSeparator();
390   fileMenu->addAction( myWebView->pageAction( WebPage::Back ) );
391   fileMenu->addAction( myWebView->pageAction( WebPage::Forward ) );
392   fileMenu->addAction( myWebView->pageAction( WebPage::Reload ) );
393   fileMenu->addSeparator();
394   fileMenu->addAction( tr( "&Find in text..." ),
395                        myFindPanel, SLOT( find() ),
396                        QKeySequence( QKeySequence::Find ) );
397   fileMenu->addAction( tr( "&Find next" ),
398                        myFindPanel, SLOT( findNext() ),
399                        QKeySequence( QKeySequence::FindNext ) );
400   fileMenu->addAction( tr( "&Find previous" ),
401                        myFindPanel, SLOT( findPrevious() ),
402                        QKeySequence( QKeySequence::FindPrevious ) );
403   fileMenu->addSeparator();
404   fileMenu->addAction( QPixmap( ":/images/close.png" ), tr( "&Close" ),
405                        this, SLOT( close() ) );
406
407   QMenu* helpMenu = menuBar()->addMenu( tr( "&Help" ) );
408   helpMenu->addAction( tr( "&About..." ),
409                        this, SLOT( about() ) );
410   
411   QVBoxLayout* main = new QVBoxLayout( frame );
412   main->addWidget( myWebView );
413   main->addWidget( myFindPanel );
414   main->setMargin( 0 );
415   main->setSpacing( 3 );
416
417   connect( myWebView, SIGNAL( titleChanged( QString ) ), SLOT( adjustTitle() ) ); 
418   connect( myWebView, SIGNAL( loadFinished( bool ) ),    SLOT( finished( bool ) ) );
419   
420   connect( myWebView->pageAction( WebPage::DownloadLinkToDisk ), SIGNAL( triggered() ),
421            SLOT( linkAction() ) );
422 #if QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
423   //QtWebKit case:
424   connect( myWebView, SIGNAL( linkClicked( QUrl ) ),     SLOT( linkClicked( QUrl ) ) );
425   connect( myWebView->page(), SIGNAL( linkHovered( QString, QString, QString ) ), 
426            SLOT( linkHovered( QString, QString, QString ) ) ); 
427   disconnect( myWebView->pageAction( WebPage::OpenLink ), 0, 0, 0 );
428   connect( myWebView->pageAction( WebPage::OpenLink ), SIGNAL( triggered() ),
429            SLOT( linkAction() ) );
430 #else
431   //QtWebEngine (Qt-5.6.0) case:
432   connect( myWebView->page(), SIGNAL( linkHovered( QString ) ), 
433            SLOT( linkHovered( QString ) ) );
434   disconnect( myWebView->pageAction( WebPage::OpenLinkInThisWindow ), 0, 0, 0 );
435   connect( myWebView->pageAction( WebPage::OpenLinkInThisWindow ), SIGNAL( triggered() ),
436            SLOT( linkAction() ) );
437 #endif  
438   setCentralWidget( frame );
439   setFocusProxy( myWebView );
440   setWindowIcon( QPixmap( ":/images/appicon.png" ) );
441   adjustTitle();
442 }
443
444 /*!
445   \brief Destructor.
446 */
447 QtxWebBrowser::~QtxWebBrowser()
448 {
449   myBrowser = 0;
450 }
451
452 /*!
453   \brief Return the only instance of the QtxWebBrowser
454   \return instance of the QtxWebBrowser
455 */
456 QtxWebBrowser* QtxWebBrowser::webBrowser()
457 {
458   if ( !myBrowser )
459     myBrowser = new QtxWebBrowser();
460   return myBrowser;
461 }
462
463 /*!
464   \brief Load given url address and optional scroll to the specified anchor
465   \param url an url address to load
466   \param anchor an anchor to scroll page to
467 */
468 void QtxWebBrowser::loadUrl( const QString& url, const QString& anchor )
469 {
470   QString anUrl = url;
471   if( !anchor.isEmpty() ) anUrl += "#" + anchor;
472
473   Qtx::alignWidget( webBrowser(), (QWidget*)QApplication::desktop(), Qtx::AlignCenter );
474
475   QtxWebBrowser* browser = webBrowser();
476   browser->show();
477   browser->load( anUrl );
478   browser->setFocus();
479   browser->activateWindow();
480   browser->raise();
481 }
482
483 /*!
484   \brief Shutdown help browser
485 */
486 void QtxWebBrowser::shutdown()
487 {
488   if ( myBrowser )
489     myBrowser->close();
490 }
491
492 /*!
493   \brief Set resource manager
494   \param resMgr resource manager
495 */
496 void QtxWebBrowser::setResourceMgr( QtxResourceMgr* resMgr )
497 {
498   myResourceMgr = resMgr;
499 }
500
501 /*!
502   \brief Get resource manager
503   \return resource manager
504 */
505 QtxResourceMgr* QtxWebBrowser::resourceMgr() const
506 {
507   return myResourceMgr;
508 }
509
510 /*!
511   Shows About dialog box
512 */
513 void QtxWebBrowser::about()
514 {
515   QMessageBox::about( this, tr( "About %1" ).arg( tr( "Help Browser" ) ),
516                       QString( "SALOME %1" ).arg( tr( "Help Browser" ) ) );
517 }
518
519 /*!
520   \brief Called when users activated any link at the page
521   \param url URL being clicked
522   \internal
523 */
524 void QtxWebBrowser::linkClicked( const QUrl& url )
525 {
526 #if QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
527   myWebView->page()->setLinkDelegationPolicy( WebPage::DontDelegateLinks );
528 #endif  
529   myWebView->load( url );
530 #if QT_VERSION < QT_VERSION_CHECK(5, 6, 0)  
531   myWebView->page()->setLinkDelegationPolicy( WebPage::DelegateAllLinks );
532 #endif  
533 }
534
535 /*!
536   \brief Called when link is hovered
537   \param link link being hovered
538   \param title link title (if it is specified in the markup)
539   \param content provides text within the link element, e.g., text inside an HTML anchor tag
540   \internal
541 */
542
543 void QtxWebBrowser::linkHovered( const QString& link, const QString& /*title*/, const QString& /*context*/ )
544 {
545   linkHovered(link);
546 }
547
548 void QtxWebBrowser::linkHovered( const QString& link)
549 {
550   QUrl url = link;
551   if ( !link.isEmpty() && isLocalFile( url ) ) myLastUrl = url;
552   statusBar()->showMessage( link );  
553 }
554
555 /*!
556   \brief Update title of the window
557   \internal
558 */
559 void QtxWebBrowser::adjustTitle()
560 {
561   QString title = tr( "Help Browser" );
562   if ( !myWebView->title().isEmpty() ) title += QString( " [%1]" ).arg( myWebView->title() );
563   setWindowTitle( title );
564 }
565
566 /*
567   \brief Called when link is processed by browser
568   \param ok operation status: \c true is URL is correctly processed, \c false otherwise
569 */
570 void QtxWebBrowser::finished( bool ok )
571 {
572   if ( !ok && !myLastUrl.isEmpty() ) {
573     if ( isLocalFile( myLastUrl ) ) {
574       QString filename = myLastUrl.path();
575       QString extension = QFileInfo( filename ).suffix();
576       if ( extension == "html" || extension == "htm" ) return;
577       openLink( filename );
578     }
579   }
580 }
581
582 /*
583   \brief Called when link is processed from browser via popup menu actions
584 */
585 void QtxWebBrowser::linkAction()
586 {
587   QObject* s = sender();
588   if ( s == myWebView->pageAction( WebPage::DownloadLinkToDisk ) ) {
589     saveLink( myLastUrl.path() );
590   }
591 #if QT_VERSION < QT_VERSION_CHECK(5, 6, 0)
592   if ( s == myWebView->pageAction( WebPage::OpenLink ) ) {
593 #else
594   if ( s == myWebView->pageAction( WebPage::OpenLinkInThisWindow ) ) {  
595 #endif    
596     QString fileName  = myLastUrl.path();
597     QString extension = QFileInfo( fileName ).suffix();
598     if ( extension != "html" && extension != "htm" ) {
599       openLink( fileName, true );
600     }
601     else {
602       linkClicked( myLastUrl );
603     }
604   }
605 }
606
607 /*!
608   \brief Open file
609   \param fileName link to the file being opened
610   Opens dialog box to allow the user to choose the program to be used to open the file.
611 */
612 void QtxWebBrowser::openLink( const QString& fileName, bool force )
613 {
614   QString extension = QFileInfo( fileName ).suffix();
615   int defAction = Downloader::mOpen;
616   bool defRepeat = false;
617   QString defProgram;
618   QString resSection   = QString( "%1:%2" ).arg( "web_browser" ).arg( extension );
619   QString actionParam  = "action";
620   QString programParam = "program";
621   QString repeatParam  = "repeat";
622   
623   if ( !extension.isEmpty() && myResourceMgr ) {
624     defAction  = myResourceMgr->integerValue( resSection, actionParam, defAction );
625     defRepeat  = myResourceMgr->booleanValue( resSection, repeatParam, defRepeat );
626     defProgram = myResourceMgr->stringValue( resSection, programParam, defProgram );
627   }
628   
629   if ( force || !defRepeat || ( defAction == Downloader::mOpen && defProgram.isEmpty() ) ) {
630     Downloader downloader( fileName, defAction, defProgram, this );
631     if ( !downloader.exec() ) return;
632     defAction  = downloader.action();
633     defRepeat  = downloader.isRepeatAction();
634     defProgram = downloader.program();
635     if ( myResourceMgr ) {
636       myResourceMgr->setValue( resSection, actionParam, defAction );
637       myResourceMgr->setValue( resSection, repeatParam, defRepeat );
638       if ( defAction == Downloader::mOpen )
639         myResourceMgr->setValue( resSection, programParam, defProgram );
640     }
641   }
642   switch( defAction ) {
643   case Downloader::mOpen:
644     if ( !defProgram.isEmpty() ) {
645       QStringList parameters;
646 #ifdef WIN32
647       QString cmd = defProgram;
648 #else
649       // If Salome Qt version is lower than the system one, on KDE an unresolved symbol is raised
650       // In this case, we can try to launch the pdf viewer after unsetting the LD_LIBRARY_PATH environnement variable
651       QString cmd = "env";
652       parameters << "LD_LIBRARY_PATH=/usr/lib:/usr/lib64";
653       parameters << defProgram;
654 #endif
655       parameters << QFileInfo( myLastUrl.path() ).absoluteFilePath();
656       QProcess::startDetached( cmd, parameters );
657     }
658     break;
659   case Downloader::mSave:
660     {
661       saveLink( fileName );
662     }
663     break;
664   default:
665     break;
666   }
667 }
668
669 /*!
670   \brief Load URL
671   \param url path to the file to be opened in the browser
672 */
673 void QtxWebBrowser::load( const QString& link )
674 {
675   QString linkPath = link;
676   linkPath.replace('\\', '/');
677   QUrl url = linkPath;
678   if ( !url.isEmpty() ) {
679     if ( url.scheme().isEmpty() ) url.setScheme( "file" );
680     myWebView->load( url );
681   }
682 }
683
684 /*!
685   \brief Save file
686   \param fileName link to the file being saved
687   Shows "Save file" standard dialog box to allow user to choose where to save the file.
688 */
689 void QtxWebBrowser::saveLink( const QString& fileName )
690 {
691   QString newFileName = QFileDialog::getSaveFileName( this, tr( "Save file" ), fileName, 
692                                                       QString( "*.%1" ).arg( QFileInfo( fileName ).suffix() ) );
693   if ( !newFileName.isEmpty() && 
694        QFileInfo( newFileName ).canonicalFilePath() != QFileInfo( fileName ).canonicalFilePath() ) {
695     QFile toFile( newFileName );
696     QFile fromFile( fileName );
697     if ( toFile.exists() && !toFile.remove() || !fromFile.copy( newFileName ) )
698       QMessageBox::warning( this, tr( "Error"), tr( "Can't save file:\n%1" ).arg( newFileName ) );
699   }
700 }
701
702 /*!
703   \brief Open file
704   Shows "Open file" standard dialog box to allow user to choose file to open.
705 */
706 void QtxWebBrowser::open()
707 {
708   QString url;
709   if ( isLocalFile( myWebView->url() ) ) url = myWebView->url().path();
710   url = QFileDialog::getOpenFileName( this, tr( "Open file" ), url, "HTML files (*.html *.htm);; All files (*)" );
711   if ( !url.isEmpty() ) load( url );
712 }