/***************************************************************************
* Copyright ( C ) 2004 - 2007 by Georgy Yunaev , gyunaev @ ulduzsoft . com *
* Please do not use email address above for bug reports ; see *
* the README file *
* *
* This program is free software ; you can redistribute it and / or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation ; either version 2 of the License , or *
* ( at your option ) any later version . *
* *
* This program 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 General Public License for more details . *
* *
* You should have received a copy of the GNU General Public License *
* along with this program ; if not , write to the *
* Free Software Foundation , Inc . , *
* 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA . *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// Do not use tr() or i18n() in this file - this class is not derived from TQObject.
# include <tqregexp.h>
# include <tqstring.h>
# include <tqdir.h>
# include "libchmfile.h"
# include "libchmurlfactory.h"
# include "kchmconfig.h"
# include "kchmviewwindow.h"
# include "kchmmainwindow.h"
# include "kchmviewwindowmgr.h"
# include "kchmnavtoolbar.h"
KCHMViewWindow : : KCHMViewWindow ( TQTabWidget * parent )
{
tqinvalidate ( ) ;
m_contextMenu = 0 ;
m_contextMenuLink = 0 ;
m_historyMaxSize = 25 ;
m_parentTabWidget = parent ;
}
KCHMViewWindow : : ~ KCHMViewWindow ( )
{
}
void KCHMViewWindow : : tqinvalidate ( )
{
m_base_url = " / " ;
m_openedPage = TQString ( ) ;
m_newTabLinkKeeper = TQString ( ) ;
m_historyCurrentPos = 0 ;
m_history . clear ( ) ;
updateNavigationToolbar ( ) ;
}
TQString KCHMViewWindow : : makeURLabsolute ( const TQString & url , bool set_as_base )
{
TQString p1 , p2 , newurl = url ;
if ( ! LCHMUrlFactory : : isRemoteURL ( url , p1 )
& & ! LCHMUrlFactory : : isJavascriptURL ( url )
& & ! LCHMUrlFactory : : isNewChmURL ( url , p1 , p2 ) )
{
newurl = TQDir : : cleanDirPath ( url ) ;
// Normalize url, so it becomes absolute
if ( newurl [ 0 ] ! = ' / ' )
newurl = m_base_url + " / " + newurl ;
newurl = TQDir : : cleanDirPath ( newurl ) ;
if ( set_as_base )
{
m_base_url = newurl ;
// and set up new baseurl
int i = newurl . findRev ( ' / ' ) ;
if ( i ! = - 1 )
m_base_url = TQDir : : cleanDirPath ( newurl . left ( i + 1 ) ) ;
}
}
//qDebug ("KCHMViewWindow::makeURLabsolute (%s) -> (%s)", url.ascii(), newurl.ascii());
return newurl ;
}
bool KCHMViewWindow : : openUrl ( const TQString & origurl )
{
TQString chmfile , page , newurl = origurl ;
if ( ! origurl )
return true ;
// URL could be a complete ms-its link. The file should be already loaded (for TQTextBrowser),
// or will be loaded (for kio slave). We care only about the path component.
if ( LCHMUrlFactory : : isNewChmURL ( newurl , chmfile , page ) )
{
// If a new chm file is opened here, and we do not use KCHMLPart, we better abort
if ( chmfile ! = : : mainWindow - > getOpenedFileName ( ) & & appConfig . m_kdeUseTQTextBrowser )
qFatal ( " KCHMViewWindow::openUrl(): opened new chm file %s while current is %s " ,
chmfile . ascii ( ) , : : mainWindow - > getOpenedFileName ( ) . ascii ( ) ) ;
// It is OK to have a new file in chm for KHTMLPart
newurl = page ;
}
makeURLabsolute ( newurl ) ;
handleStartPageAsImage ( newurl ) ;
if ( openPage ( newurl ) )
{
m_newTabLinkKeeper = TQString ( ) ;
m_openedPage = newurl ;
mainWindow - > viewWindowMgr ( ) - > setTabName ( this ) ;
return true ;
}
return false ;
}
void KCHMViewWindow : : handleStartPageAsImage ( TQString & link )
{
// Handle pics
if ( link . tqendsWith ( " .jpg " , false )
| | link . tqendsWith ( " .jpeg " , false )
| | link . tqendsWith ( " .gif " , false )
| | link . tqendsWith ( " .png " , false )
| | link . tqendsWith ( " .bmp " , false ) )
link + = LCHMUrlFactory : : getInternalUriExtension ( ) ;
}
KTQPopupMenu * KCHMViewWindow : : createStandardContextMenu ( TQWidget * parent )
{
KTQPopupMenu * contextMenu = new KTQPopupMenu ( parent ) ;
contextMenu - > insertItem ( " &Copy " , : : mainWindow , TQT_SLOT ( slotBrowserCopy ( ) ) ) ;
contextMenu - > insertItem ( " &Select all " , : : mainWindow , TQT_SLOT ( slotBrowserSelectAll ( ) ) ) ;
return contextMenu ;
}
KTQPopupMenu * KCHMViewWindow : : getContextMenu ( const TQString & link , TQWidget * parent )
{
if ( link . isNull ( ) )
{
// standard context menu
if ( ! m_contextMenu )
m_contextMenu = createStandardContextMenu ( parent ) ;
return m_contextMenu ;
}
else
{
// Open in New Tab context menu
// standard context menu
if ( ! m_contextMenuLink )
{
m_contextMenuLink = createStandardContextMenu ( parent ) ;
m_contextMenuLink - > insertSeparator ( ) ;
m_contextMenuLink - > insertItem ( " &Open this link in a new tab " , : : mainWindow , TQT_SLOT ( slotOpenPageInNewTab ( ) ) , TQKeySequence ( " Shift+Enter " ) ) ;
m_contextMenuLink - > insertItem ( " &Open this link in a new background tab " , : : mainWindow , TQT_SLOT ( slotOpenPageInNewBackgroundTab ( ) ) , TQKeySequence ( " Ctrl+Enter " ) ) ;
}
setTabKeeper ( link ) ;
return m_contextMenuLink ;
}
}
TQString KCHMViewWindow : : getTitle ( ) const
{
TQString title = : : mainWindow - > chmFile ( ) - > getTopicByUrl ( m_openedPage ) ;
if ( title . isEmpty ( ) )
title = m_openedPage ;
return title ;
}
void KCHMViewWindow : : navigateForward ( )
{
if ( m_historyCurrentPos < m_history . size ( ) )
{
m_historyCurrentPos + + ;
: : mainWindow - > openPage ( m_history [ m_historyCurrentPos ] . getUrl ( ) ) ;
setScrollbarPosition ( m_history [ m_historyCurrentPos ] . getScrollPosition ( ) ) ;
// By default navigation starts with empty array, and a new entry is added when
// you change the current page (or it may not be added). So to have the whole system
// worked, the m_historyCurrentPos should never be m_history.size() - 1, it should be
// either greater or lesser.
//
// This is a dirty hack - but the whole navigation system now looks to me like
// it was written by some drunk monkey - which is probably not far from The Real Truth.
// Shame on me - Tim.
if ( m_historyCurrentPos = = ( m_history . size ( ) - 1 ) )
m_historyCurrentPos + + ;
}
updateNavigationToolbar ( ) ;
}
void KCHMViewWindow : : navigateBack ( )
{
if ( m_historyCurrentPos > 0 )
{
// If we're on top of list, and pressing Back, the last page is still
// not in list - so add it, if it is not still here
if ( m_historyCurrentPos = = m_history . size ( ) )
{
if ( m_history [ m_historyCurrentPos - 1 ] . getUrl ( ) ! = m_openedPage )
m_history . push_back ( KCHMUrlHistory ( m_openedPage , getScrollbarPosition ( ) ) ) ;
else
{
// part 2 of the navigation hack - see navigateForward() comment
m_history [ m_historyCurrentPos - 1 ] . setScrollPosition ( getScrollbarPosition ( ) ) ;
m_historyCurrentPos - - ;
}
}
m_historyCurrentPos - - ;
: : mainWindow - > openPage ( m_history [ m_historyCurrentPos ] . getUrl ( ) ) ;
setScrollbarPosition ( m_history [ m_historyCurrentPos ] . getScrollPosition ( ) ) ;
}
updateNavigationToolbar ( ) ;
}
void KCHMViewWindow : : navigateHome ( )
{
: : mainWindow - > openPage ( : : mainWindow - > chmFile ( ) - > homeUrl ( ) ) ;
}
void KCHMViewWindow : : addNavigationHistory ( const TQString & url , int scrollpos )
{
// shred the 'forward' history
if ( m_historyCurrentPos < m_history . size ( ) )
m_history . erase ( m_history . at ( m_historyCurrentPos ) , m_history . end ( ) ) ;
// do not grow the history if already max size
if ( m_history . size ( ) > = m_historyMaxSize )
m_history . pop_front ( ) ;
m_history . push_back ( KCHMUrlHistory ( url , scrollpos ) ) ;
m_historyCurrentPos = m_history . size ( ) ;
updateNavigationToolbar ( ) ;
}
void KCHMViewWindow : : updateNavigationToolbar ( )
{
// Dump navigation for debugging
#if 0
qDebug ( " \n Navigation dump (%d entries, current pos %d) " , m_history . size ( ) , m_historyCurrentPos ) ;
for ( unsigned int i = 0 ; i < m_history . size ( ) ; i + + )
qDebug ( " [%02d]: %s [%d] " , i , m_history [ i ] . getUrl ( ) . ascii ( ) , m_history [ i ] . getScrollPosition ( ) ) ;
# endif
if ( mainWindow )
{
mainWindow - > navigationToolbar ( ) - > updateIcontqStatus (
m_historyCurrentPos > 0 ,
m_historyCurrentPos < ( m_history . size ( ) - 1 ) ) ;
}
}
KTQPopupMenu * KCHMViewWindow : : createListItemContextMenu ( TQWidget * w )
{
KTQPopupMenu * contextMenu = new KTQPopupMenu ( w ) ;
contextMenu - > insertItem ( " &Open this link in a new tab " ,
: : mainWindow ,
TQT_SLOT ( slotOpenPageInNewTab ( ) ) ,
TQKeySequence ( " Shift+Enter " ) ) ;
contextMenu - > insertItem ( " &Open this link in a new background tab " ,
: : mainWindow ,
TQT_SLOT ( slotOpenPageInNewBackgroundTab ( ) ) ,
TQKeySequence ( " Ctrl+Enter " ) ) ;
return contextMenu ;
}
void KCHMViewWindow : : setTabKeeper ( const TQString & link )
{
// If we clicked on relative link, make sure we convert it to absolute right now,
// because later we will not have access to this view window variables
m_newTabLinkKeeper = link ;
if ( m_newTabLinkKeeper [ 0 ] = = ' # ' & & ! m_openedPage . isEmpty ( ) )
{
// Clean up opened page URL
int pos = m_openedPage . find ( ' # ' ) ;
TQString fixedpath = pos = = - 1 ? m_openedPage : m_openedPage . left ( pos ) ;
m_newTabLinkKeeper = fixedpath + m_newTabLinkKeeper ;
}
m_newTabLinkKeeper = makeURLabsolute ( m_newTabLinkKeeper , false ) ;
}