Salome HOME
SIMAN removal
[modules/gui.git] / src / Qtx / QtxWebBrowser.cxx
index abd715030445777e665c32ab935854c40762666c..146029464458f8dec7c2fedb373e334d365a5f1b 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2015  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
 //
 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
@@ -6,7 +6,7 @@
 // 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
 // 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.
+// version 2.1 of the License, or (at your option) any later version.
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 //
 // This library is distributed in the hope that it will be useful,
 // but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 // File:      QtxWebBrowser.cxx
 // Author:    Roman NIKOLAEV
 
 // File:      QtxWebBrowser.cxx
 // Author:    Roman NIKOLAEV
-//
+
 #include "QtxWebBrowser.h"
 #include "QtxWebBrowser.h"
+#include "QtxResourceMgr.h"
 #include "QtxSearchTool.h"
 
 #include <QApplication>
 #include "QtxSearchTool.h"
 
 #include <QApplication>
+#include <QButtonGroup>
+#include <QCheckBox>
+#include <QFileDialog>
 #include <QFileInfo>
 #include <QFileInfo>
-#include <QWebView>
-#include <QMenuBar>
-#include <QToolBar>
+#include <QGridLayout>
+#include <QHBoxLayout>
+#include <QLabel>
 #include <QMenu>
 #include <QMenu>
+#include <QMenuBar>
+#include <QMessageBox>
+#include <QPushButton>
+#include <QRadioButton>
 #include <QStatusBar>
 #include <QStatusBar>
+#include <QToolBar>
 #include <QVBoxLayout>
 #include <QVBoxLayout>
+#include <QWebView>
+#include <QProcess>
+
+namespace
+{
+  bool isLocalFile( const QUrl& url )
+  {
+    QFileInfo fi( url.path() );
+    return fi.exists();
+  }
+}
 
 /*!
 
 /*!
-  \class WebViewSearcher
+  \class QtxWebBrowser::Searcher
   \brief A class is used with QtxSearchTool in order to search text within the web page 
   \internal
 */
   \brief A class is used with QtxSearchTool in order to search text within the web page 
   \internal
 */
-class WebViewSearcher : public QtxSearchTool::Searcher
+
+class QtxWebBrowser::Searcher : public QtxSearchTool::Searcher
 {
 public:
 {
 public:
-  WebViewSearcher( QWebView* );
-  ~WebViewSearcher();
+  Searcher( QWebView* );
+  ~Searcher();
 
   bool find( const QString&, QtxSearchTool* );
   bool findNext( const QString&, QtxSearchTool* );
 
   bool find( const QString&, QtxSearchTool* );
   bool findNext( const QString&, QtxSearchTool* );
@@ -56,15 +77,31 @@ private:
   QWebView* myView;
 };
 
   QWebView* myView;
 };
 
-WebViewSearcher::WebViewSearcher( QWebView* view ) : myView( view )
+/*!
+  \brief Constructor
+  \param view web view
+  \internal
+*/
+QtxWebBrowser::Searcher::Searcher( QWebView* view ) : myView( view )
 {
 }
 
 {
 }
 
-WebViewSearcher::~WebViewSearcher()
+/*!
+  \brief Destructor
+  \internal
+*/
+QtxWebBrowser::Searcher::~Searcher()
 {
 }
 
 {
 }
 
-bool WebViewSearcher::find( const QString& text, QtxSearchTool* st )
+/*!
+  \brief Find specified text
+  \param text text being searched
+  \param st search tool
+  \return \c true if text has been found or \c false otherwise
+  \internal
+*/
+bool QtxWebBrowser::Searcher::find( const QString& text, QtxSearchTool* st )
 {
   QWebPage::FindFlags fl = 0;
   if ( st->isCaseSensitive() ) fl = fl | QWebPage::FindCaseSensitively;
 {
   QWebPage::FindFlags fl = 0;
   if ( st->isCaseSensitive() ) fl = fl | QWebPage::FindCaseSensitively;
@@ -72,12 +109,26 @@ bool WebViewSearcher::find( const QString& text, QtxSearchTool* st )
   return myView->findText( text, fl );
 }
 
   return myView->findText( text, fl );
 }
 
-bool WebViewSearcher::findNext( const QString& text, QtxSearchTool* st )
+/*!
+  \brief Find next entry of specified text starting from the current position
+  \param text text being searched
+  \param st search tool
+  \return \c true if text has been found or \c false otherwise
+  \internal
+*/
+bool QtxWebBrowser::Searcher::findNext( const QString& text, QtxSearchTool* st )
 {
   return find( text, st );
 }
 
 {
   return find( text, st );
 }
 
-bool WebViewSearcher::findPrevious( const QString& text, QtxSearchTool* st )
+/*!
+  \brief Find previous entry of specified text starting from the current position
+  \param text text being searched
+  \param st search tool
+  \return \c true if text has been found or \c false otherwise
+  \internal
+*/
+bool QtxWebBrowser::Searcher::findPrevious( const QString& text, QtxSearchTool* st )
 {
   QWebPage::FindFlags fl = QWebPage::FindBackward;
   if ( st->isCaseSensitive() ) fl = fl | QWebPage::FindCaseSensitively;
 {
   QWebPage::FindFlags fl = QWebPage::FindBackward;
   if ( st->isCaseSensitive() ) fl = fl | QWebPage::FindCaseSensitively;
@@ -85,20 +136,156 @@ bool WebViewSearcher::findPrevious( const QString& text, QtxSearchTool* st )
   return myView->findText( text, fl );
 }
 
   return myView->findText( text, fl );
 }
 
-bool WebViewSearcher::findFirst( const QString&, QtxSearchTool* )
+/*!
+  \brief Find first entry of specified text; does nothing in this implementation
+  \param text text being searched
+  \param st search tool
+  \return \c true if text has been found or \c false otherwise
+  \internal
+*/
+bool QtxWebBrowser::Searcher::findFirst( const QString& /*text*/, QtxSearchTool* /*st*/ )
 {
   return false;
 }
 
 {
   return false;
 }
 
-bool WebViewSearcher::findLast( const QString&, QtxSearchTool* )
+/*!
+  \brief Find last entry of specified text; does nothing in this implementation
+  \param text text being searched
+  \param st search tool
+  \return \c true if text has been found or \c false otherwise
+  \internal
+*/
+bool QtxWebBrowser::Searcher::findLast( const QString& /*text*/, QtxSearchTool* /*st*/)
 {
   return false;
 }
 
 {
   return false;
 }
 
+
+/*!
+  \class QtxWebBrowser::Downloader
+  \brief A dialog box that is used to process file links
+  \internal
+*/
+
+/*!
+  \brief Constructor
+  \param fileName name of the file being opened
+  \param action default action to be used for the file
+  \param program default program to be used to open the file
+  \param parent parent widget
+  \internal
+*/
+QtxWebBrowser::Downloader::Downloader( const QString& fileName, int action, const QString& program, QWidget* parent )
+  : QDialog( parent ), myProgram( program )
+{
+  setModal( true );
+  setWindowTitle( QtxWebBrowser::tr( "Open URL" ) );
+  setSizeGripEnabled( true );
+
+  myFileName = new QLabel( this );
+  QRadioButton* rbOpen = new QRadioButton( QtxWebBrowser::tr( "Open in" ), this );
+  QRadioButton* rbSave = new QRadioButton( QtxWebBrowser::tr( "Save file" ), this );
+  myBrowse = new QPushButton( QtxWebBrowser::tr( "&Browse..." ),     this );
+  myRepeat = new QCheckBox( QtxWebBrowser::tr( "Use this program for all files of this type" ), this );
+
+  myAction = new QButtonGroup( this );
+  myAction->addButton( rbOpen, mOpen );
+  myAction->addButton( rbSave, mSave );
+
+  QPushButton* btnOk     = new QPushButton( QtxWebBrowser::tr( "&OK" ),     this );
+  QPushButton* btnCancel = new QPushButton( QtxWebBrowser::tr( "&Cancel" ), this );
+
+  QFont f = myFileName->font(); f.setBold( true ); myFileName->setFont( f );
+
+  QHBoxLayout* btnLayout = new QHBoxLayout;
+  btnLayout->addWidget( btnOk );
+  btnLayout->addStretch();
+  btnLayout->addWidget( btnCancel );
+
+  QGridLayout* l = new QGridLayout( this );
+  l->addWidget( new QLabel( QtxWebBrowser::tr( "You are opening the file" ), this ), 
+                           0, 0, 1, 4 );
+  l->addWidget( myFileName, 1, 1, 1, 3 );
+  l->addWidget( new QLabel( QtxWebBrowser::tr( "Please choose the action to be done" ), this ), 
+                           3, 0, 1, 4 );
+  l->addWidget( rbOpen,     4, 1, 1, 1 );
+  l->addWidget( myBrowse,   4, 2, 1, 1 );
+  l->addWidget( rbSave,     5, 1, 1, 3 );
+  l->addWidget( myRepeat,   6, 1, 1, 3 );
+  l->addLayout( btnLayout,  7, 0, 1, 4 );
+  l->setRowMinimumHeight( 2, 10 );
+
+  connect( myAction,  SIGNAL( buttonClicked( int ) ), this, SLOT( setAction( int ) ) );
+  connect( myBrowse,  SIGNAL( clicked() ), this, SLOT( browse() ) );
+  connect( btnOk,     SIGNAL( clicked() ), this, SLOT( accept() ) );
+  connect( btnCancel, SIGNAL( clicked() ), this, SLOT( reject() ) );
+
+  myFileName->setText( QFileInfo( fileName ).fileName() );
+  myAction->button( action )->click();
+}
+
+/*!
+  \brief Destructor
+*/
+QtxWebBrowser::Downloader::~Downloader()
+{
+}
+
+/*!
+  \brief Get action selected by the user
+  \return action being selected:
+  - 0: open file
+  - 1: save file
+*/
+int QtxWebBrowser::Downloader::action() const
+{
+  return myAction->checkedId();
+}
+
+/*!
+  \brief Get "repeat action for all such files" flag status
+  \return \c true if chosen action should be automatically done for all files of given type
+  or \c false otherwise
+*/
+bool QtxWebBrowser::Downloader::isRepeatAction() const
+{
+  return myRepeat->isChecked();
+}
+
+/*!
+  \brief Get program to be used to open chosen file
+  \return path to the program
+*/
+QString QtxWebBrowser::Downloader::program() const
+{
+  return myProgram;
+}
+
+/*!
+  \brief Set current action
+  \param action action to be done for the file:
+  - 0: open file
+  - 1: save file
+*/
+void QtxWebBrowser::Downloader::setAction( int action )
+{
+  myBrowse->setEnabled( action == mOpen );
+}
+
+/*!
+  \brief Browse program to be used to open the file
+*/
+void QtxWebBrowser::Downloader::browse()
+{
+  QString program = QFileDialog::getOpenFileName( this, QtxWebBrowser::tr( "Choose program" ), myProgram );
+  if ( !program.isEmpty() ) myProgram = program;
+}
+
+
 /*!
   \class QtxWebBrowser
 
 /*!
   \class QtxWebBrowser
 
-  \brief The QtxWebBrowser provides a window that can display html pages.
+  \brief The QtxWebBrowser provides a window that can display html pages from local file system.
   
   Only one instance of the QtxWebBrowser class can be created. To access the browser 
   window, use static method QtxWebBrowser::webBrowser(), which creates an
   
   Only one instance of the QtxWebBrowser class can be created. To access the browser 
   window, use static method QtxWebBrowser::webBrowser(), which creates an
@@ -109,45 +296,38 @@ bool WebViewSearcher::findLast( const QString&, QtxSearchTool* )
   closing of the browser window. To close window programmatically use 
   method close().
 
   closing of the browser window. To close window programmatically use 
   method close().
 
-  To set visual properties of the browser use static method setData().
+  Optionally resource manager can be specified to automatically store
+  action (open/save) and program to be used to download files in the
+  application preferences.
 
   The following sample demonstrates how to use web browser.
   In this code the browser window is created, /data/index.html file is opened
   and scrolled to the "anchor1" anchor on this page.
 
   \code
 
   The following sample demonstrates how to use web browser.
   In this code the browser window is created, /data/index.html file is opened
   and scrolled to the "anchor1" anchor on this page.
 
   \code
-  int main(int argc, char *argv[])
-  {
-    QApplication app(argc, argv);    
-
-    // set icon, title and menu items.
-    QtxWebBrowser::setData("browser:title",      tr("Web Browser"));
-    QtxWebBrowser::setData("browser:icon",       QPixmap(":/icon.png"));
-    QtxWebBrowser::setData("menu:file:title",    tr("&File"));
-    QtxWebBrowser::setData("action:close:title", tr("&Close"));
-
-    // show HTML page
-    QtxWebBrowser::loadUrl("file:///data/index.html", "anchor1");
-    
-    return app.exec();
-  }
+  // initialize application
+  // - set resource manager
+  QtxWebBrowser::setResourceMgr(myResourceMgr);
+  // ...
+  // show HTML page
+  QtxWebBrowser::loadUrl("file:///data/index.html", "anchor1");
   \endcode
   \endcode
-
 */
 
 //! The only one instance of web browser
 QtxWebBrowser* QtxWebBrowser::myBrowser = 0;
 
 */
 
 //! The only one instance of web browser
 QtxWebBrowser* QtxWebBrowser::myBrowser = 0;
 
-//! Internal data map to store resources of the browser.
-QMap<QString, QVariant> QtxWebBrowser::myData;
+//! Resources manager
+QtxResourceMgr* QtxWebBrowser::myResourceMgr = 0;
 
 /*!
   \brief Constructor.
 
 /*!
   \brief Constructor.
   Construct the web browser.
 */
   Construct the web browser.
 */
-QtxWebBrowser::QtxWebBrowser() : QMainWindow( 0 )
+QtxWebBrowser::QtxWebBrowser( ) : QMainWindow( 0 )
 {
 {
+  Q_INIT_RESOURCE( Qtx );
+
   setAttribute( Qt::WA_DeleteOnClose );
   statusBar();
 
   setAttribute( Qt::WA_DeleteOnClose );
   statusBar();
 
@@ -155,31 +335,54 @@ QtxWebBrowser::QtxWebBrowser() : QMainWindow( 0 )
 
   myWebView = new QWebView( frame );
 
 
   myWebView = new QWebView( frame );
 
-  QAction *copyAction = myWebView->pageAction(QWebPage::Copy);
-  copyAction->setShortcut(QKeySequence::Copy);
-  myWebView->addAction(copyAction);
-
+  myWebView->pageAction( QWebPage::Copy )->setShortcut( QKeySequence::Copy );
+  myWebView->addAction( myWebView->pageAction( QWebPage::Copy ) );
+  myWebView->pageAction( QWebPage::OpenLinkInNewWindow )->setVisible( false );
+  myWebView->pageAction( QWebPage::Back )->setText( tr( "Go Back" ) );
+  myWebView->pageAction( QWebPage::Forward )->setText( tr( "Go Forward" ) );
+  myWebView->pageAction( QWebPage::Reload )->setText( tr( "Refresh" ) );
 
   myWebView->page()->setLinkDelegationPolicy( QWebPage::DelegateAllLinks );
 
   myWebView->page()->setLinkDelegationPolicy( QWebPage::DelegateAllLinks );
+
   myFindPanel = new QtxSearchTool( frame, myWebView,
                                   QtxSearchTool::Basic | QtxSearchTool::Case | QtxSearchTool::Wrap, 
                                   Qt::Horizontal );
   myFindPanel->setFrameStyle( QFrame::NoFrame | QFrame::Plain );
   myFindPanel->setActivators( QtxSearchTool::SlashKey );
   myFindPanel = new QtxSearchTool( frame, myWebView,
                                   QtxSearchTool::Basic | QtxSearchTool::Case | QtxSearchTool::Wrap, 
                                   Qt::Horizontal );
   myFindPanel->setFrameStyle( QFrame::NoFrame | QFrame::Plain );
   myFindPanel->setActivators( QtxSearchTool::SlashKey );
-  myFindPanel->setSearcher( new WebViewSearcher( myWebView ) );
+  myFindPanel->setSearcher( new Searcher( myWebView ) );
   myFindPanel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
 
   myFindPanel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
 
-  myToolbar = addToolBar( tr( "Navigation" ) );
-  myToolbar->addAction( myWebView->pageAction( QWebPage::Back ) );
-  myToolbar->addAction( myWebView->pageAction( QWebPage::Forward ) );
-
-  myMenus[ File ]        = menuBar()->addMenu( tr( "&File" ) );
-  myActions[ Find ]      = myMenus[ File ]->addAction( tr( "&Find in text..." ), myFindPanel, SLOT( find() ),         QKeySequence( QKeySequence::Find ) );
-  myActions[ FindNext ]  = myMenus[ File ]->addAction( tr( "&Find next" ),       myFindPanel, SLOT( findNext() ),     QKeySequence( QKeySequence::FindNext ) );
-  myActions[ FindPrev ]  = myMenus[ File ]->addAction( tr( "&Find previous" ),   myFindPanel, SLOT( findPrevious() ), QKeySequence( QKeySequence::FindPrevious ) );
-  myMenus[ File ]->addSeparator();
-  myActions[ Close ]     = myMenus[ File ]->addAction( tr( "&Close" ),           this, SLOT( close() ) );
-
+  QToolBar* toolbar = addToolBar( tr( "Navigation" ) );
+  toolbar->addAction( myWebView->pageAction( QWebPage::Back ) );
+  toolbar->addAction( myWebView->pageAction( QWebPage::Forward ) );
+  toolbar->addAction( myWebView->pageAction( QWebPage::Reload ) );
+
+  QMenu* fileMenu = menuBar()->addMenu( tr( "&File" ) );
+  fileMenu->addAction( QPixmap( ":/images/open.png" ), tr( "&Open..." ), 
+                      this, SLOT( open() ),
+                      QKeySequence( QKeySequence::Open ) );
+  fileMenu->addSeparator();
+  fileMenu->addAction( myWebView->pageAction( QWebPage::Back ) );
+  fileMenu->addAction( myWebView->pageAction( QWebPage::Forward ) );
+  fileMenu->addAction( myWebView->pageAction( QWebPage::Reload ) );
+  fileMenu->addSeparator();
+  fileMenu->addAction( tr( "&Find in text..." ),
+                      myFindPanel, SLOT( find() ),
+                      QKeySequence( QKeySequence::Find ) );
+  fileMenu->addAction( tr( "&Find next" ),
+                      myFindPanel, SLOT( findNext() ),
+                      QKeySequence( QKeySequence::FindNext ) );
+  fileMenu->addAction( tr( "&Find previous" ),
+                      myFindPanel, SLOT( findPrevious() ),
+                      QKeySequence( QKeySequence::FindPrevious ) );
+  fileMenu->addSeparator();
+  fileMenu->addAction( QPixmap( ":/images/close.png" ), tr( "&Close" ),
+                      this, SLOT( close() ) );
+
+  QMenu* helpMenu = menuBar()->addMenu( tr( "&Help" ) );
+  helpMenu->addAction( tr( "&About..." ),
+                      this, SLOT( about() ) );
+  
   QVBoxLayout* main = new QVBoxLayout( frame );
   main->addWidget( myWebView );
   main->addWidget( myFindPanel );
   QVBoxLayout* main = new QVBoxLayout( frame );
   main->addWidget( myWebView );
   main->addWidget( myFindPanel );
@@ -187,13 +390,20 @@ QtxWebBrowser::QtxWebBrowser() : QMainWindow( 0 )
   main->setSpacing( 3 );
 
   connect( myWebView, SIGNAL( titleChanged( QString ) ), SLOT( adjustTitle() ) ); 
   main->setSpacing( 3 );
 
   connect( myWebView, SIGNAL( titleChanged( QString ) ), SLOT( adjustTitle() ) ); 
+  connect( myWebView, SIGNAL( loadFinished( bool ) ),    SLOT( finished( bool ) ) ); 
   connect( myWebView, SIGNAL( linkClicked( QUrl ) ),     SLOT( linkClicked( QUrl ) ) ); 
   connect( myWebView, SIGNAL( linkClicked( QUrl ) ),     SLOT( linkClicked( QUrl ) ) ); 
-  connect( myWebView->page(), SIGNAL( linkHovered( QString, QString, QString ) ), SLOT( linkHovered( QString, QString, QString ) ) ); 
+  connect( myWebView->page(), SIGNAL( linkHovered( QString, QString, QString ) ), 
+          SLOT( linkHovered( QString, QString, QString ) ) ); 
+  connect( myWebView->pageAction( QWebPage::DownloadLinkToDisk ), SIGNAL( activated() ),
+          SLOT( linkAction() ) );
+  disconnect( myWebView->pageAction( QWebPage::OpenLink ), 0, 0, 0 );
+  connect( myWebView->pageAction( QWebPage::OpenLink ), SIGNAL( activated() ),
+          SLOT( linkAction() ) );
   
   setCentralWidget( frame );
   setFocusProxy( myWebView );
   
   setCentralWidget( frame );
   setFocusProxy( myWebView );
-  updateData();
-  qAddPostRoutine( QtxWebBrowser::clearData );
+  setWindowIcon( QPixmap( ":/images/appicon.png" ) );
+  adjustTitle();
 }
 
 /*!
 }
 
 /*!
@@ -224,167 +434,51 @@ void QtxWebBrowser::loadUrl( const QString& url, const QString& anchor )
 {
   QString anUrl = url;
   if( !anchor.isEmpty() ) anUrl += "#" + anchor;
 {
   QString anUrl = url;
   if( !anchor.isEmpty() ) anUrl += "#" + anchor;
-  anUrl.replace('\\', '/');
 
   Qtx::alignWidget( webBrowser(), (QWidget*)QApplication::desktop(), Qtx::AlignCenter );
 
 
   Qtx::alignWidget( webBrowser(), (QWidget*)QApplication::desktop(), Qtx::AlignCenter );
 
-  webBrowser()->show();
-  webBrowser()->myWebView->load( QUrl( anUrl ) );
-  webBrowser()->setFocus();
-  webBrowser()->activateWindow();
-  webBrowser()->raise();
-}
-
-/*!
-  \brief  Set browser settings from.
-
-  This method can be used to setup the browser properties.
-  - \c "browser:title"         : title of the browser window
-  - \c "browser:icon"          : icon of the browser window
-  - \c "toolbar:title"         : title of the toolbar
-  - \c "menu:file:title"       : File menu of the browser
-  - \c "action:close:title"    : File/Close menu item title
-  - \c "action:close:icon"     : File/Close menu item icon
-  - \c "action:back:title"     : Navigation/Back menu item title
-  - \c "action:back:icon"      : Navigation/Back menu item icon
-  - \c "action:forward:title"  : Navigation/Forward menu item title
-  - \c "action:forward:icon"   : Navigation/Forward menu item icon
-  - \c "action:find:title"     : File/Find menu item title
-  - \c "action:find:icon"      : File/Find menu item icon
-  - \c "action:findnext:title" : File/Find Next menu item title
-  - \c "action:findnext:icon"  : File/Find Next menu item icon
-  - \c "action:findprev:title" : File/Find Previous menu item title
-  - \c "action:findprev:icon"  : File/Find Previous menu item icon
-  
-  \param key name of the property
-  \param val value of the property
-  
-*/
-void QtxWebBrowser::setData( const QString& key, const QVariant& val )
-{
-  myData.insert( key, val );
-  if ( myBrowser ) myBrowser->updateData();
+  QtxWebBrowser* browser = webBrowser();
+  browser->show();
+  browser->load( anUrl );
+  browser->setFocus();
+  browser->activateWindow();
+  browser->raise();
 }
 
 /*!
 }
 
 /*!
-  \brief Get string value by key from the internal data map
-  \param key data key identifier
-  \return string value assigned to the key (null string if data is not assigned to the key)
-  \internal
+  \brief Shutdown help browser
 */
 */
-QString QtxWebBrowser::getStringValue( const QString& key )
+void QtxWebBrowser::shutdown()
 {
 {
-  QString val;
-  if ( myData.contains( key ) && myData[key].canConvert( QVariant::String ) )
-    val = myData[key].toString();
-  return val;
+  if ( myBrowser )
+    myBrowser->close();
 }
 
 /*!
 }
 
 /*!
-  \brief Get icon value by key from the internal data map
-  \param key data key identifier
-  \return icon assigned to the key (null icon if data is not assigned to the key)
-  \internal
+  \brief Set resource manager
+  \param resMgr resource manager
 */
 */
-QIcon QtxWebBrowser::getIconValue(const QString& key)
+void QtxWebBrowser::setResourceMgr( QtxResourceMgr* resMgr )
 {
 {
-  QIcon val;
-  if ( myData.contains( key ) ) {
-    if ( myData[key].canConvert( QVariant::Pixmap ) )
-      val = myData[key].value<QPixmap>();
-    else if ( myData[key].canConvert( QVariant::Icon ) )
-      val = myData[key].value<QIcon>();
-  }
-  return val;
+  myResourceMgr = resMgr;
 }
 
 /*!
 }
 
 /*!
-  \brief Update web browser properties from internal data map
+  \brief Get resource manager
+  \return resource manager
 */
 */
-void QtxWebBrowser::updateData()
+QtxResourceMgr* QtxWebBrowser::resourceMgr() const
 {
 {
-  // main title
-  adjustTitle();
-
-  // window icon
-  QIcon icon = getIconValue( "browser:icon" );
-  if ( !icon.isNull() )
-    setWindowIcon( icon );
-
-  // toolbar title
-  QString tbTitle = getStringValue( "toolbar:title" );
-  if ( myToolbar && !tbTitle.isEmpty() )
-    myToolbar->setWindowTitle( tbTitle );
-
-  // File menu
-  QString fmenu = getStringValue( "menu:file:title" );
-  if ( myMenus.contains( File ) && !fmenu.isEmpty() )
-    myMenus[ File ]->setTitle( fmenu );
-
-  // File/Close menu
-  QString closeTlt = getStringValue( "action:close:title" );
-  QIcon closeIco = getIconValue( "action:close:icon" );
-  if ( myActions.contains( Close ) ) {
-    if ( !closeTlt.isEmpty() )
-      myActions[ Close ]->setText( closeTlt );
-    if ( !closeIco.isNull() )
-      myActions[ Close ]->setIcon( closeIco );
-  }
-
-  // Navigation/Go Back menu
-  QString backTlt = getStringValue( "action:back:title" );
-  QIcon backIco = getIconValue( "action:back:icon" );
-  if ( !backTlt.isEmpty() )
-    myWebView->pageAction( QWebPage::Back )->setText( backTlt );
-  if ( !backIco.isNull() )
-    myWebView->pageAction( QWebPage::Back )->setIcon( backIco );
-
-  // Navigation/Go Forward menu
-  QString fwdTlt = getStringValue( "action:forward:title" );
-  QIcon fwdIco = getIconValue( "action:forward:icon" );
-  if ( !fwdTlt.isEmpty() )
-    myWebView->pageAction( QWebPage::Forward )->setText( fwdTlt );
-  if ( !fwdIco.isNull() )
-    myWebView->pageAction( QWebPage::Forward )->setIcon( fwdIco );
-
-  // File/Find menu
-  QString findTlt = getStringValue( "action:find:title" );
-  QIcon findIco = getIconValue( "action:find:icon" );
-  if ( myActions.contains( Find ) ) {
-    if ( !findTlt.isEmpty() )
-      myActions[ Find ]->setText( findTlt );
-    if ( !findIco.isNull() )
-      myActions[ Find ]->setIcon( findIco );
-  }
-
-  // File/Find Next menu
-  QString findNextTlt = getStringValue( "action:findnext:title" );
-  QIcon findNextIco = getIconValue( "action:findnext:icon" );
-  if ( myActions.contains( FindNext ) ) {
-    if ( !findNextTlt.isEmpty() )
-      myActions[ FindNext ]->setText( findNextTlt );
-    if ( !findNextIco.isNull() )
-      myActions[ FindNext ]->setIcon( findNextIco );
-  }
-
-  // File/Find Previous menu
-  QString findPrevTlt = getStringValue( "action:findprev:title" );
-  QIcon findPrevIco = getIconValue( "action:findprev:icon" );
-  if ( myActions.contains( FindPrev ) ) {
-    if ( !findPrevTlt.isEmpty() )
-      myActions[ FindPrev ]->setText( findPrevTlt );
-    if ( !findPrevIco.isNull() )
-      myActions[ FindPrev ]->setIcon( findPrevIco );
-  }
+  return myResourceMgr;
 }
 
 /*!
 }
 
 /*!
-  \brief Clear internal data map
-  \internal
+  Shows About dialog box
 */
 */
-void QtxWebBrowser::clearData()
+void QtxWebBrowser::about()
 {
 {
-  myData.clear();
+  QMessageBox::about( this, tr( "About %1" ).arg( tr( "Help Browser" ) ),
+                     QString( "SALOME %1" ).arg( tr( "Help Browser" ) ) );
 }
 
 /*!
 }
 
 /*!
@@ -396,25 +490,6 @@ void QtxWebBrowser::linkClicked( const QUrl& url )
 {
   myWebView->page()->setLinkDelegationPolicy( QWebPage::DontDelegateLinks );
   myWebView->load( url );
 {
   myWebView->page()->setLinkDelegationPolicy( QWebPage::DontDelegateLinks );
   myWebView->load( url );
-  if ( url.scheme() == "file" ) {
-    QString filename = url.toLocalFile();
-    if ( QFileInfo( filename ).suffix().toLower() == "pdf" ) {
-#ifdef WIN32
-      ::system( QString( "start %2" ).arg( filename ).toLatin1().constData() );
-#else
-      // special processing of PDF files
-      QStringList readers;
-      readers << "xdg-open" << "acroread" << "kpdf" << "kghostview" << "xpdf";
-      foreach ( QString r, readers ) {
-       QString reader = QString( "/usr/bin/%1" ).arg( r );
-       if ( QFileInfo( reader ).exists() ) {
-         ::system( QString( "unset LD_LIBRARY_PATH; %1 %2 &" ).arg( reader ).arg( url.toLocalFile() ).toLatin1().constData() );
-         break;
-       }
-      }
-#endif // WIN32
-    }
-  }
   myWebView->page()->setLinkDelegationPolicy( QWebPage::DelegateAllLinks );
 }
 
   myWebView->page()->setLinkDelegationPolicy( QWebPage::DelegateAllLinks );
 }
 
@@ -427,6 +502,8 @@ void QtxWebBrowser::linkClicked( const QUrl& url )
 */
 void QtxWebBrowser::linkHovered( const QString& link, const QString& /*title*/, const QString& /*context*/ )
 {
 */
 void QtxWebBrowser::linkHovered( const QString& link, const QString& /*title*/, const QString& /*context*/ )
 {
+  QUrl url = link;
+  if ( !link.isEmpty() && isLocalFile( url ) ) myLastUrl = url;
   statusBar()->showMessage( link );
 }
 
   statusBar()->showMessage( link );
 }
 
@@ -436,6 +513,147 @@ void QtxWebBrowser::linkHovered( const QString& link, const QString& /*title*/,
 */
 void QtxWebBrowser::adjustTitle()
 {
 */
 void QtxWebBrowser::adjustTitle()
 {
-  QString title = getStringValue( "browser:title" );
-  setWindowTitle( title.isEmpty() ? myWebView->title() : title + QString( " [%1]" ).arg( myWebView->title() ) );
+  QString title = tr( "Help Browser" );
+  if ( !myWebView->title().isEmpty() ) title += QString( " [%1]" ).arg( myWebView->title() );
+  setWindowTitle( title );
+}
+
+/*
+  \brief Called when link is processed by browser
+  \param ok operation status: \c true is URL is correctly processed, \c false otherwise
+*/
+void QtxWebBrowser::finished( bool ok )
+{
+  if ( !ok && !myLastUrl.isEmpty() ) {
+    if ( isLocalFile( myLastUrl ) ) {
+      QString filename = myLastUrl.path();
+      QString extension = QFileInfo( filename ).suffix();
+      if ( extension == "html" || extension == "htm" ) return;
+      openLink( filename );
+    }
+  }
+}
+
+/*
+  \brief Called when link is processed from browser via popup menu actions
+*/
+void QtxWebBrowser::linkAction()
+{
+  QObject* s = sender();
+  if ( s == myWebView->pageAction( QWebPage::DownloadLinkToDisk ) ) {
+    saveLink( myLastUrl.path() );
+  }
+  else if ( s == myWebView->pageAction( QWebPage::OpenLink ) ) {
+    QString fileName  = myLastUrl.path();
+    QString extension = QFileInfo( fileName ).suffix();
+    if ( extension != "html" && extension != "htm" ) {
+      openLink( fileName, true );
+    }
+    else {
+      linkClicked( myLastUrl );
+    }
+  }
+}
+
+/*!
+  \brief Open file
+  \param fileName link to the file being opened
+  Opens dialog box to allow the user to choose the program to be used to open the file.
+*/
+void QtxWebBrowser::openLink( const QString& fileName, bool force )
+{
+  QString extension = QFileInfo( fileName ).suffix();
+  int defAction = Downloader::mOpen;
+  bool defRepeat = false;
+  QString defProgram;
+  QString resSection   = QString( "%1:%2" ).arg( "web_browser" ).arg( extension );
+  QString actionParam  = "action";
+  QString programParam = "program";
+  QString repeatParam  = "repeat";
+  
+  if ( !extension.isEmpty() && myResourceMgr ) {
+    defAction  = myResourceMgr->integerValue( resSection, actionParam, defAction );
+    defRepeat  = myResourceMgr->booleanValue( resSection, repeatParam, defRepeat );
+    defProgram = myResourceMgr->stringValue( resSection, programParam, defProgram );
+  }
+  
+  if ( force || !defRepeat || ( defAction == Downloader::mOpen && defProgram.isEmpty() ) ) {
+    Downloader downloader( fileName, defAction, defProgram, this );
+    if ( !downloader.exec() ) return;
+    defAction  = downloader.action();
+    defRepeat  = downloader.isRepeatAction();
+    defProgram = downloader.program();
+    if ( myResourceMgr ) {
+      myResourceMgr->setValue( resSection, actionParam, defAction );
+      myResourceMgr->setValue( resSection, repeatParam, defRepeat );
+      if ( defAction == Downloader::mOpen )
+       myResourceMgr->setValue( resSection, programParam, defProgram );
+    }
+  }
+  switch( defAction ) {
+  case Downloader::mOpen:
+    if ( !defProgram.isEmpty() ) {
+      QStringList parameters;
+#ifdef WIN32
+      QString cmd = defProgram;
+#else
+      // If Salome Qt version is lower than the system one, on KDE an unresolved symbol is raised
+      // In this case, we can try to launch the pdf viewer after unsetting the LD_LIBRARY_PATH environnement variable
+      QString cmd = "env";
+      parameters << "LD_LIBRARY_PATH=/usr/lib:/usr/lib64";
+      parameters << defProgram;
+#endif
+      parameters << QFileInfo( myLastUrl.path() ).absoluteFilePath();
+      QProcess::startDetached( cmd, parameters );
+    }
+    break;
+  case Downloader::mSave:
+    {
+      saveLink( fileName );
+    }
+    break;
+  default:
+    break;
+  }
+}
+
+/*!
+  \brief Load URL
+  \param url path to the file to be opened in the browser
+*/
+void QtxWebBrowser::load( const QString& url )
+{
+  QString u = url;
+  if ( !u.isEmpty() )
+    myWebView->load( QUrl( u.replace('\\', '/') ) );
+}
+
+/*!
+  \brief Save file
+  \param fileName link to the file being saved
+  Shows "Save file" standard dialog box to allow user to choose where to save the file.
+*/
+void QtxWebBrowser::saveLink( const QString& fileName )
+{
+  QString newFileName = QFileDialog::getSaveFileName( this, tr( "Save file" ), fileName, 
+                                                     QString( "*.%1" ).arg( QFileInfo( fileName ).suffix() ) );
+  if ( !newFileName.isEmpty() && 
+       QFileInfo( newFileName ).canonicalFilePath() != QFileInfo( fileName ).canonicalFilePath() ) {
+    QFile toFile( newFileName );
+    QFile fromFile( fileName );
+    if ( toFile.exists() && !toFile.remove() || !fromFile.copy( newFileName ) )
+      QMessageBox::warning( this, tr( "Error"), tr( "Can't save file:\n%1" ).arg( newFileName ) );
+  }
+}
+
+/*!
+  \brief Open file
+  Shows "Open file" standard dialog box to allow user to choose file to open.
+*/
+void QtxWebBrowser::open()
+{
+  QString url;
+  if ( isLocalFile( myWebView->url() ) ) url = myWebView->url().path();
+  url = QFileDialog::getOpenFileName( this, tr( "Open file" ), url, "HTML files (*.html *.htm);; All files (*)" );
+  if ( !url.isEmpty() ) load( url );
 }
 }