You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kchmviewer/src/kchmviewwindow.cpp

315 lines
9.5 KiB

/***************************************************************************
* 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 )
{
invalidate();
m_contextMenu = 0;
m_contextMenuLink = 0;
m_historyMaxSize = 25;
m_parentTabWidget = parent;
}
KCHMViewWindow::~KCHMViewWindow()
{
}
void KCHMViewWindow::invalidate( )
{
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));
}
}
//tqDebug ("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 tdeio 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 )
tqFatal("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 TDEHTMLPart
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.endsWith( ".jpg", false )
|| link.endsWith( ".jpeg", false )
|| link.endsWith( ".gif", false )
|| link.endsWith( ".png", false )
|| link.endsWith( ".bmp", false ) )
link += LCHMUrlFactory::getInternalUriExtension();
}
KTQPopupMenu * KCHMViewWindow::createStandardContextMenu( TQWidget * parent )
{
KTQPopupMenu * contextMenu = new KTQPopupMenu( parent );
contextMenu->insertItem ( "&Copy", ::mainWindow, TQ_SLOT(slotBrowserCopy()) );
contextMenu->insertItem ( "&Select all", ::mainWindow, TQ_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, TQ_SLOT(slotOpenPageInNewTab()), TQKeySequence("Shift+Enter") );
m_contextMenuLink->insertItem ( "&Open this link in a new background tab", ::mainWindow, TQ_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
tqDebug("\nNavigation dump (%d entries, current pos %d)", m_history.size(), m_historyCurrentPos );
for ( unsigned int i = 0; i < m_history.size(); i++ )
tqDebug("[%02d]: %s [%d]", i, m_history[i].getUrl().ascii(), m_history[i].getScrollPosition());
#endif
if ( mainWindow )
{
mainWindow->navigationToolbar()->updateIconStatus(
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,
TQ_SLOT( slotOpenPageInNewTab() ),
TQKeySequence( "Shift+Enter" ) );
contextMenu->insertItem ( "&Open this link in a new background tab",
::mainWindow,
TQ_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 );
}