1 // Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File: QtxWebBrowser.cxx
24 // Author: Roman NIKOLAEV
26 #include "QtxWebBrowser.h"
27 #include "QtxResourceMgr.h"
28 #include "QtxSearchTool.h"
30 #include <QApplication>
31 #include <QButtonGroup>
33 #include <QFileDialog>
35 #include <QGridLayout>
36 #include <QHBoxLayout>
40 #include <QMessageBox>
41 #include <QPushButton>
42 #include <QRadioButton>
45 #include <QVBoxLayout>
49 \class QtxWebBrowser::Searcher
50 \brief A class is used with QtxSearchTool in order to search text within the web page
54 class QtxWebBrowser::Searcher : public QtxSearchTool::Searcher
57 Searcher( QWebView* );
60 bool find( const QString&, QtxSearchTool* );
61 bool findNext( const QString&, QtxSearchTool* );
62 bool findPrevious( const QString&, QtxSearchTool* );
63 bool findFirst( const QString&, QtxSearchTool* );
64 bool findLast( const QString&, QtxSearchTool* );
75 QtxWebBrowser::Searcher::Searcher( QWebView* view ) : myView( view )
83 QtxWebBrowser::Searcher::~Searcher()
88 \brief Find specified text
89 \param text text being searched
91 \return \c true if text has been found or \c false otherwise
94 bool QtxWebBrowser::Searcher::find( const QString& text, QtxSearchTool* st )
96 QWebPage::FindFlags fl = 0;
97 if ( st->isCaseSensitive() ) fl = fl | QWebPage::FindCaseSensitively;
98 if ( st->isSearchWrapped() ) fl = fl | QWebPage::FindWrapsAroundDocument;
99 return myView->findText( text, fl );
103 \brief Find next entry of specified text starting from the current position
104 \param text text being searched
105 \param st search tool
106 \return \c true if text has been found or \c false otherwise
109 bool QtxWebBrowser::Searcher::findNext( const QString& text, QtxSearchTool* st )
111 return find( text, st );
115 \brief Find previous entry of specified text starting from the current position
116 \param text text being searched
117 \param st search tool
118 \return \c true if text has been found or \c false otherwise
121 bool QtxWebBrowser::Searcher::findPrevious( const QString& text, QtxSearchTool* st )
123 QWebPage::FindFlags fl = QWebPage::FindBackward;
124 if ( st->isCaseSensitive() ) fl = fl | QWebPage::FindCaseSensitively;
125 if ( st->isSearchWrapped() ) fl = fl | QWebPage::FindWrapsAroundDocument;
126 return myView->findText( text, fl );
130 \brief Find first entry of specified text; does nothing in this implementation
131 \param text text being searched
132 \param st search tool
133 \return \c true if text has been found or \c false otherwise
136 bool QtxWebBrowser::Searcher::findFirst( const QString& /*text*/, QtxSearchTool* /*st*/ )
142 \brief Find last entry of specified text; does nothing in this implementation
143 \param text text being searched
144 \param st search tool
145 \return \c true if text has been found or \c false otherwise
148 bool QtxWebBrowser::Searcher::findLast( const QString& /*text*/, QtxSearchTool* /*st*/)
155 \class QtxWebBrowser::Downloader
156 \brief A dialog box that is used to process file links
162 \param fileName name of the file being opened
163 \param action default action to be used for the file
164 \param program default program to be used to open the file
165 \param parent parent widget
168 QtxWebBrowser::Downloader::Downloader( const QString& fileName, int action, const QString& program, QWidget* parent )
169 : QDialog( parent ), myProgram( program )
172 setWindowTitle( tr( "Open URL" ) );
173 setSizeGripEnabled( true );
175 myFileName = new QLabel( this );
176 QRadioButton* rbOpen = new QRadioButton( tr( "Open in" ), this );
177 QRadioButton* rbSave = new QRadioButton( tr( "Save file" ), this );
178 myBrowse = new QPushButton( tr( "&Browse..." ), this );
179 myRepeat = new QCheckBox( tr( "Use this program for all files of this type" ), this );
181 myAction = new QButtonGroup( this );
182 myAction->addButton( rbOpen, mOpen );
183 myAction->addButton( rbSave, mSave );
185 QPushButton* btnOk = new QPushButton( tr( "&OK" ), this );
186 QPushButton* btnCancel = new QPushButton( tr( "&Cancel" ), this );
188 QFont f = myFileName->font(); f.setBold( true ); myFileName->setFont( f );
190 QHBoxLayout* btnLayout = new QHBoxLayout;
191 btnLayout->addWidget( btnOk );
192 btnLayout->addStretch();
193 btnLayout->addWidget( btnCancel );
195 QGridLayout* l = new QGridLayout( this );
196 l->addWidget( new QLabel( tr( "You are opening the file" ), this ),
198 l->addWidget( myFileName, 1, 1, 1, 3 );
199 l->addWidget( new QLabel( tr( "Please choose the action to be done" ), this ),
201 l->addWidget( rbOpen, 4, 1, 1, 1 );
202 l->addWidget( myBrowse, 4, 2, 1, 1 );
203 l->addWidget( rbSave, 5, 1, 1, 3 );
204 l->addWidget( myRepeat, 6, 1, 1, 3 );
205 l->addLayout( btnLayout, 7, 0, 1, 4 );
206 l->setRowMinimumHeight( 2, 10 );
208 connect( myAction, SIGNAL( buttonClicked( int ) ), this, SLOT( setAction( int ) ) );
209 connect( myBrowse, SIGNAL( clicked() ), this, SLOT( browse() ) );
210 connect( btnOk, SIGNAL( clicked() ), this, SLOT( accept() ) );
211 connect( btnCancel, SIGNAL( clicked() ), this, SLOT( reject() ) );
213 myFileName->setText( QFileInfo( fileName ).fileName() );
214 myAction->button( action )->click();
220 QtxWebBrowser::Downloader::~Downloader()
225 \brief Get action selected by the user
226 \return action being selected:
230 int QtxWebBrowser::Downloader::action() const
232 return myAction->checkedId();
236 \brief Get "repeat action for all such files" flag status
237 \return \c true if chosen action should be automatically done for all files of given type
238 or \c false otherwise
240 bool QtxWebBrowser::Downloader::isRepeatAction() const
242 return myRepeat->isChecked();
246 \brief Get program to be used to open chosen file
247 \return path to the program
249 QString QtxWebBrowser::Downloader::program() const
255 \brief Set current action
256 \param action action to be done for the file:
260 void QtxWebBrowser::Downloader::setAction( int action )
262 myBrowse->setEnabled( action == mOpen );
266 \brief Browse program to be used to open the file
268 void QtxWebBrowser::Downloader::browse()
270 QString program = QFileDialog::getOpenFileName( this, tr( "Choose program" ), myProgram );
271 if ( !program.isEmpty() ) myProgram = program;
278 \brief The QtxWebBrowser provides a window that can display html pages.
280 Only one instance of the QtxWebBrowser class can be created. To access the browser
281 window, use static method QtxWebBrowser::webBrowser(), which creates an
282 instance of the QtxWebBrowser widget (if it is not yet created) and returns a
285 You should not destroy this instance - it is done automatically after
286 closing of the browser window. To close window programmatically use
289 To set visual properties of the browser use static method setData().
291 Optionally resource manager can be specified to automatically store
292 action (open/save) and program to be used to download files to the
295 The following sample demonstrates how to use web browser.
296 In this code the browser window is created, /data/index.html file is opened
297 and scrolled to the "anchor1" anchor on this page.
300 int main(int argc, char *argv[])
302 QApplication app(argc, argv);
304 // set resource manager
305 QtxWebBrowser::setResourceManager(myResourceMgr);
306 // set icon, title and menu items
307 QtxWebBrowser::setData("browser:title", tr("Web Browser"));
308 QtxWebBrowser::setData("browser:icon", QPixmap(":/icon.png"));
309 QtxWebBrowser::setData("menu:file:title", tr("&File"));
310 QtxWebBrowser::setData("action:close:title", tr("&Close"));
313 QtxWebBrowser::loadUrl("file:///data/index.html", "anchor1");
321 //! The only one instance of web browser
322 QtxWebBrowser* QtxWebBrowser::myBrowser = 0;
324 //! Resources manager
325 QtxResourceMgr* QtxWebBrowser::myResourceMgr = 0;
327 //! Internal data map to store resources of the browser.
328 QMap<QString, QVariant> QtxWebBrowser::myData;
332 Construct the web browser.
334 QtxWebBrowser::QtxWebBrowser( ) : QMainWindow( 0 )
336 setAttribute( Qt::WA_DeleteOnClose );
339 QWidget* frame = new QWidget( this );
341 myWebView = new QWebView( frame );
343 QAction *copyAction = myWebView->pageAction(QWebPage::Copy);
344 copyAction->setShortcut(QKeySequence::Copy);
345 myWebView->addAction(copyAction);
348 myWebView->page()->setLinkDelegationPolicy( QWebPage::DelegateAllLinks );
349 myFindPanel = new QtxSearchTool( frame, myWebView,
350 QtxSearchTool::Basic | QtxSearchTool::Case | QtxSearchTool::Wrap,
352 myFindPanel->setFrameStyle( QFrame::NoFrame | QFrame::Plain );
353 myFindPanel->setActivators( QtxSearchTool::SlashKey );
354 myFindPanel->setSearcher( new Searcher( myWebView ) );
355 myFindPanel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed );
357 myToolbar = addToolBar( tr( "Navigation" ) );
358 myToolbar->addAction( myWebView->pageAction( QWebPage::Back ) );
359 myToolbar->addAction( myWebView->pageAction( QWebPage::Forward ) );
361 myMenus[ File ] = menuBar()->addMenu( tr( "&File" ) );
362 myActions[ Find ] = myMenus[ File ]->addAction( tr( "&Find in text..." ), myFindPanel, SLOT( find() ), QKeySequence( QKeySequence::Find ) );
363 myActions[ FindNext ] = myMenus[ File ]->addAction( tr( "&Find next" ), myFindPanel, SLOT( findNext() ), QKeySequence( QKeySequence::FindNext ) );
364 myActions[ FindPrev ] = myMenus[ File ]->addAction( tr( "&Find previous" ), myFindPanel, SLOT( findPrevious() ), QKeySequence( QKeySequence::FindPrevious ) );
365 myMenus[ File ]->addSeparator();
366 myActions[ Close ] = myMenus[ File ]->addAction( tr( "&Close" ), this, SLOT( close() ) );
368 QVBoxLayout* main = new QVBoxLayout( frame );
369 main->addWidget( myWebView );
370 main->addWidget( myFindPanel );
371 main->setMargin( 0 );
372 main->setSpacing( 3 );
374 connect( myWebView, SIGNAL( titleChanged( QString ) ), SLOT( adjustTitle() ) );
375 connect( myWebView, SIGNAL( loadFinished( bool ) ), SLOT( finished( bool ) ) );
376 connect( myWebView, SIGNAL( linkClicked( QUrl ) ), SLOT( linkClicked( QUrl ) ) );
377 connect( myWebView->page(), SIGNAL( linkHovered( QString, QString, QString ) ),
378 SLOT( linkHovered( QString, QString, QString ) ) );
379 connect( myWebView->pageAction( QWebPage::DownloadLinkToDisk ), SIGNAL( activated() ),
380 SLOT( linkAction() ) );
381 disconnect( myWebView->pageAction( QWebPage::OpenLink ), 0, 0, 0 );
382 connect( myWebView->pageAction( QWebPage::OpenLink ), SIGNAL( activated() ),
383 SLOT( linkAction() ) );
386 myWebView->pageAction( QWebPage::OpenLinkInNewWindow )->setVisible( false );
388 setCentralWidget( frame );
389 setFocusProxy( myWebView );
391 qAddPostRoutine( QtxWebBrowser::clearData );
397 QtxWebBrowser::~QtxWebBrowser()
403 \brief Return the only instance of the QtxWebBrowser
404 \return instance of the QtxWebBrowser
406 QtxWebBrowser* QtxWebBrowser::webBrowser()
409 myBrowser = new QtxWebBrowser();
414 \brief Load given url address and optional scroll to the specified anchor
415 \param url an url address to load
416 \param anchor an anchor to scroll page to
418 void QtxWebBrowser::loadUrl( const QString& url, const QString& anchor )
421 if( !anchor.isEmpty() ) anUrl += "#" + anchor;
422 anUrl.replace('\\', '/');
424 Qtx::alignWidget( webBrowser(), (QWidget*)QApplication::desktop(), Qtx::AlignCenter );
426 QtxWebBrowser* browser = webBrowser();
428 browser->myWebView->load( QUrl( anUrl ) );
430 browser->activateWindow();
435 \brief Set browser settings from.
437 This method can be used to setup the browser properties.
438 - \c "browser:title" : title of the browser window
439 - \c "browser:icon" : icon of the browser window
440 - \c "toolbar:title" : title of the toolbar
441 - \c "menu:file:title" : File menu of the browser
442 - \c "action:close:title" : File/Close menu item title
443 - \c "action:close:icon" : File/Close menu item icon
444 - \c "action:back:title" : Navigation/Back menu item title
445 - \c "action:back:icon" : Navigation/Back menu item icon
446 - \c "action:forward:title" : Navigation/Forward menu item title
447 - \c "action:forward:icon" : Navigation/Forward menu item icon
448 - \c "action:find:title" : File/Find menu item title
449 - \c "action:find:icon" : File/Find menu item icon
450 - \c "action:findnext:title" : File/Find Next menu item title
451 - \c "action:findnext:icon" : File/Find Next menu item icon
452 - \c "action:findprev:title" : File/Find Previous menu item title
453 - \c "action:findprev:icon" : File/Find Previous menu item icon
454 - \c "preferences:section" : Preferences file section (base, used as prefix to the file extension)
455 - \c "preferences:action" : Preferences file parameter name for action
456 - \c "preferences:program" : Preferences file parameter name for program
457 - \c "preferences:repeat" : Preferences file parameter name for repeat action flag
459 \param key name of the property
460 \param val value of the property
463 void QtxWebBrowser::setData( const QString& key, const QVariant& val )
465 myData.insert( key, val );
466 if ( myBrowser ) myBrowser->updateData();
470 \brief Shutdown help browser
472 void QtxWebBrowser::shutdown()
479 \brief Get string value by key from the internal data map
480 \param key data key identifier
481 \param def default value
482 \return string value assigned to the key (null string if data is not assigned to the key)
485 QString QtxWebBrowser::getStringValue( const QString& key, const QString& def )
488 if ( myData.contains( key ) && myData[key].canConvert( QVariant::String ) )
489 val = myData[key].toString();
494 \brief Get icon value by key from the internal data map
495 \param key data key identifier
496 \param def default value
497 \return icon assigned to the key (null icon if data is not assigned to the key)
500 QIcon QtxWebBrowser::getIconValue( const QString& key, const QIcon& def )
503 if ( myData.contains( key ) ) {
504 if ( myData[key].canConvert( QVariant::Pixmap ) )
505 val = myData[key].value<QPixmap>();
506 else if ( myData[key].canConvert( QVariant::Icon ) )
507 val = myData[key].value<QIcon>();
513 \brief Update web browser properties from internal data map
515 void QtxWebBrowser::updateData()
521 QIcon icon = getIconValue( "browser:icon" );
522 if ( !icon.isNull() )
523 setWindowIcon( icon );
526 QString tbTitle = getStringValue( "toolbar:title" );
527 if ( myToolbar && !tbTitle.isEmpty() )
528 myToolbar->setWindowTitle( tbTitle );
531 QString fmenu = getStringValue( "menu:file:title" );
532 if ( myMenus.contains( File ) && !fmenu.isEmpty() )
533 myMenus[ File ]->setTitle( fmenu );
536 QString closeTlt = getStringValue( "action:close:title" );
537 QIcon closeIco = getIconValue( "action:close:icon" );
538 if ( myActions.contains( Close ) ) {
539 if ( !closeTlt.isEmpty() )
540 myActions[ Close ]->setText( closeTlt );
541 if ( !closeIco.isNull() )
542 myActions[ Close ]->setIcon( closeIco );
545 // Navigation/Go Back menu
546 QString backTlt = getStringValue( "action:back:title" );
547 QIcon backIco = getIconValue( "action:back:icon" );
548 if ( !backTlt.isEmpty() )
549 myWebView->pageAction( QWebPage::Back )->setText( backTlt );
550 if ( !backIco.isNull() )
551 myWebView->pageAction( QWebPage::Back )->setIcon( backIco );
553 // Navigation/Go Forward menu
554 QString fwdTlt = getStringValue( "action:forward:title" );
555 QIcon fwdIco = getIconValue( "action:forward:icon" );
556 if ( !fwdTlt.isEmpty() )
557 myWebView->pageAction( QWebPage::Forward )->setText( fwdTlt );
558 if ( !fwdIco.isNull() )
559 myWebView->pageAction( QWebPage::Forward )->setIcon( fwdIco );
562 QString findTlt = getStringValue( "action:find:title" );
563 QIcon findIco = getIconValue( "action:find:icon" );
564 if ( myActions.contains( Find ) ) {
565 if ( !findTlt.isEmpty() )
566 myActions[ Find ]->setText( findTlt );
567 if ( !findIco.isNull() )
568 myActions[ Find ]->setIcon( findIco );
571 // File/Find Next menu
572 QString findNextTlt = getStringValue( "action:findnext:title" );
573 QIcon findNextIco = getIconValue( "action:findnext:icon" );
574 if ( myActions.contains( FindNext ) ) {
575 if ( !findNextTlt.isEmpty() )
576 myActions[ FindNext ]->setText( findNextTlt );
577 if ( !findNextIco.isNull() )
578 myActions[ FindNext ]->setIcon( findNextIco );
581 // File/Find Previous menu
582 QString findPrevTlt = getStringValue( "action:findprev:title" );
583 QIcon findPrevIco = getIconValue( "action:findprev:icon" );
584 if ( myActions.contains( FindPrev ) ) {
585 if ( !findPrevTlt.isEmpty() )
586 myActions[ FindPrev ]->setText( findPrevTlt );
587 if ( !findPrevIco.isNull() )
588 myActions[ FindPrev ]->setIcon( findPrevIco );
593 \brief Clear internal data map
596 void QtxWebBrowser::clearData()
602 \brief Set resource manager
604 void QtxWebBrowser::setResourceManager( QtxResourceMgr* resMgr )
606 myResourceMgr = resMgr;
610 \brief Called when users activated any link at the page
611 \param url URL being clicked
614 void QtxWebBrowser::linkClicked( const QUrl& url )
616 myWebView->page()->setLinkDelegationPolicy( QWebPage::DontDelegateLinks );
617 myWebView->load( url );
618 myWebView->page()->setLinkDelegationPolicy( QWebPage::DelegateAllLinks );
622 \brief Called when link is hovered
623 \param link link being hovered
624 \param title link title (if it is specified in the markup)
625 \param content provides text within the link element, e.g., text inside an HTML anchor tag
628 void QtxWebBrowser::linkHovered( const QString& link, const QString& /*title*/, const QString& /*context*/ )
631 if ( !link.isEmpty() && url.scheme() == "file" ) myLastUrl = url;
632 statusBar()->showMessage( link );
636 \brief Update title of the window
639 void QtxWebBrowser::adjustTitle()
641 QString title = getStringValue( "browser:title" );
642 setWindowTitle( title.isEmpty() ? myWebView->title() : title + QString( " [%1]" ).arg( myWebView->title() ) );
646 \brief Called when link is processed by browser
647 \param ok operation status: \c true is URL is correctly processed, \c false otherwise
649 void QtxWebBrowser::finished( bool ok )
651 if ( !ok && !myLastUrl.isEmpty() ) {
652 if ( myLastUrl.scheme() == "file" ) {
653 QString filename = myLastUrl.toLocalFile();
654 QString extension = QFileInfo( filename ).suffix();
655 if ( extension == "html" || extension == "htm" ) return;
656 openLink( filename );
662 \brief Called when link is processed from browser via popup menu actions
664 void QtxWebBrowser::linkAction()
666 QObject* s = sender();
667 if ( s == myWebView->pageAction( QWebPage::DownloadLinkToDisk ) ) {
668 saveLink( myLastUrl.toLocalFile() );
670 else if ( s == myWebView->pageAction( QWebPage::OpenLink ) ) {
671 QString fileName = myLastUrl.toLocalFile();
672 QString extension = QFileInfo( fileName ).suffix();
673 if ( extension != "html" && extension != "htm" ) {
674 openLink( fileName, true );
677 linkClicked( myLastUrl );
684 \param fileName link to the file being opened
685 Opens dialog box to allow the user to choose the program to be used to open the file.
687 void QtxWebBrowser::openLink( const QString& fileName, bool force )
689 QString extension = QFileInfo( fileName ).suffix();
690 int defAction = Downloader::mOpen;
691 bool defRepeat = false;
693 QString resSection = QString( "%1:%2" ).arg( getStringValue( "preferences:section", "web_browser" ) ).arg( extension );
694 QString actionParam = getStringValue( "preferences:action", "action" );
695 QString programParam = getStringValue( "preferences:program", "program" );
696 QString repeatParam = getStringValue( "preferences:repeat", "repeat" );
698 if ( !extension.isEmpty() && myResourceMgr ) {
699 defAction = myResourceMgr->integerValue( resSection, actionParam, defAction );
700 defRepeat = myResourceMgr->booleanValue( resSection, repeatParam, defRepeat );
701 defProgram = myResourceMgr->stringValue( resSection, programParam, defProgram );
704 if ( force || !defRepeat || ( defAction == Downloader::mOpen && defProgram.isEmpty() ) ) {
705 Downloader downloader( fileName, defAction, defProgram, this );
706 if ( !downloader.exec() ) return;
707 defAction = downloader.action();
708 defRepeat = downloader.isRepeatAction();
709 defProgram = downloader.program();
710 if ( myResourceMgr ) {
711 myResourceMgr->setValue( resSection, actionParam, defAction );
712 myResourceMgr->setValue( resSection, repeatParam, defRepeat );
713 if ( defAction == Downloader::mOpen )
714 myResourceMgr->setValue( resSection, programParam, defProgram );
717 switch( defAction ) {
718 case Downloader::mOpen:
719 if ( !defProgram.isEmpty() ) {
723 // If Salome Qt version is lower than the system one, on KDE an unresolved symbol is raised
724 // In this case, we can try to launch the pdf viewer after unsetting the LD_LIBRARY_PATH environnement variable
725 QString cmd = "env LD_LIBRARY_PATH=/usr/lib:/usr/lib64";
727 int r = ::system( QString( "%1 %2 %3 &" ).arg( cmd ).arg( defProgram ).arg( myLastUrl.toLocalFile() ).toLatin1().constData() );
730 case Downloader::mSave:
732 saveLink( fileName );
742 \param fileName link to the file being saved
743 Shows "Save file" standard dialog box to allow user to choose where to save the file.
745 void QtxWebBrowser::saveLink( const QString& fileName )
747 QString newFileName = QFileDialog::getSaveFileName( this, tr( "Save File" ), fileName,
748 QString( "*.%1" ).arg( QFileInfo( fileName ).suffix() ) );
749 if ( !newFileName.isEmpty() &&
750 QFileInfo( newFileName ).canonicalFilePath() != QFileInfo( fileName ).canonicalFilePath() ) {
751 QFile toFile( newFileName );
752 QFile fromFile( fileName );
753 if ( toFile.exists() && !toFile.remove() || !fromFile.copy( newFileName ) )
754 QMessageBox::warning( this, tr( "Error"), tr( "Can't save file:\n%1" ).arg( newFileName ) );