|
|
|
/***************************************************************************
|
|
|
|
* 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. *
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include "kde-qt.h"
|
|
|
|
|
|
|
|
#include <tqaccel.h>
|
|
|
|
#include <tqevent.h>
|
|
|
|
|
|
|
|
#include "libchmfile.h"
|
|
|
|
#include "libchmfileimpl.h"
|
|
|
|
#include "libchmurlfactory.h"
|
|
|
|
|
|
|
|
#include "kchmmainwindow.h"
|
|
|
|
#include "kchmconfig.h"
|
|
|
|
#include "kchmindexwindow.h"
|
|
|
|
#include "kchmsearchwindow.h"
|
|
|
|
#include "kchmbookmarkwindow.h"
|
|
|
|
#include "kchmtreeviewitem.h"
|
|
|
|
#include "kchmsearchtoolbar.h"
|
|
|
|
#include "kchmsettings.h"
|
|
|
|
#include "kchmsetupdialog.h"
|
|
|
|
#include "iconstorage.h"
|
|
|
|
#include "kchmnavtoolbar.h"
|
|
|
|
#include "kchmviewwindow.h"
|
|
|
|
#include "kchmviewwindowmgr.h"
|
|
|
|
#include "kchmkeyeventfilter.h"
|
|
|
|
#include "kchmcontentswindow.h"
|
|
|
|
|
|
|
|
#if !defined (USE_KDE)
|
|
|
|
#include "kqrunprocess.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "kchmmainwindow.moc"
|
|
|
|
|
|
|
|
|
|
|
|
KCHMMainWindow::KCHMMainWindow()
|
|
|
|
: KQMainWindow ( 0, "KCHMMainWindow", WDestructiveClose )
|
|
|
|
{
|
|
|
|
const unsigned int WND_X_SIZE = 700;
|
|
|
|
const unsigned int WND_Y_SIZE = 500;
|
|
|
|
const unsigned int SPLT_X_SIZE = 200;
|
|
|
|
|
|
|
|
m_FirstTimeShow = true;
|
|
|
|
m_chmFile = 0;
|
|
|
|
|
|
|
|
m_indexWindow = 0;
|
|
|
|
m_searchWindow = 0;
|
|
|
|
m_contentsWindow = 0;
|
|
|
|
m_viewWindowMgr = 0;
|
|
|
|
|
|
|
|
m_tabContextPage = -1;
|
|
|
|
m_tabIndexPage = -1;
|
|
|
|
m_tabSearchPage = -1;
|
|
|
|
m_tabBookmarkPage = -1;
|
|
|
|
|
|
|
|
setupSignals();
|
|
|
|
|
|
|
|
m_currentSettings = new KCHMSettings;
|
|
|
|
|
|
|
|
// Create the initial tqlayout - a splitter with tab window in left, and text browser in right
|
|
|
|
m_windowSplitter = new TQSplitter(this);
|
|
|
|
m_tabWidget = new KTQTabWidget( m_windowSplitter );
|
|
|
|
m_viewWindowMgr = new KCHMViewWindowMgr( m_windowSplitter );
|
|
|
|
|
|
|
|
m_bookmarkWindow = new KCHMBookmarkWindow (m_tabWidget);
|
|
|
|
|
|
|
|
// Add the tabs
|
|
|
|
m_tabWidget->addTab( m_bookmarkWindow, i18n("Bookmarks") );
|
|
|
|
|
|
|
|
setupToolbarsAndMenu();
|
|
|
|
|
|
|
|
setCentralWidget( m_windowSplitter );
|
|
|
|
|
|
|
|
TQValueList<int> sizes;
|
|
|
|
sizes.push_back (SPLT_X_SIZE);
|
|
|
|
sizes.push_back (WND_X_SIZE - SPLT_X_SIZE);
|
|
|
|
m_windowSplitter->setSizes (sizes);
|
|
|
|
|
|
|
|
resize (WND_X_SIZE, WND_Y_SIZE);
|
|
|
|
|
|
|
|
#if defined (ENABLE_AUTOTEST_SUPPORT)
|
|
|
|
m_autoteststate = STATE_OFF;
|
|
|
|
m_useShortAutotest = false;
|
|
|
|
#endif /* defined (ENABLE_AUTOTEST_SUPPORT) */
|
|
|
|
|
|
|
|
TQAccel * accel = new TQAccel( this );
|
|
|
|
accel->connectItem ( accel->insertItem ( Key_F11 ), this, TQT_SLOT ( slotToggleFullScreenMode() ) );
|
|
|
|
accel->connectItem ( accel->insertItem ( CTRL + Key_1), this, TQT_SLOT ( slotActivateContentTab() ) );
|
|
|
|
accel->connectItem ( accel->insertItem ( CTRL + Key_2), this, TQT_SLOT ( slotActivateIndexTab() ) );
|
|
|
|
accel->connectItem ( accel->insertItem ( CTRL + Key_3), this, TQT_SLOT ( slotActivateSearchTab() ) );
|
|
|
|
accel->connectItem ( accel->insertItem ( CTRL + Key_4), this, TQT_SLOT ( slotActivateBookmarkTab() ) );
|
|
|
|
accel->connectItem ( accel->insertItem ( Key_F3 ), m_searchToolbar, TQT_SLOT ( onBtnNextSearchResult() ) );
|
|
|
|
|
|
|
|
statusBar()->show();
|
|
|
|
setIcon( *gIconStorage.getApplicationIcon() );
|
|
|
|
|
|
|
|
m_aboutDlgMenuText = i18n( "%1 version %2\n\nCopyright (C) George Yunaev,"
|
|
|
|
"gyunaev@ulduzsoft.com, 2004-2007\nhttp://www.kchmviewer.net\n\n"
|
|
|
|
"Licensed under GNU GPL license.\n\n"
|
|
|
|
"Please check my another project, http://www.transientmail.com - temporary "
|
|
|
|
"e-mail address, which expires automatically." )
|
|
|
|
. arg(APP_NAME) . arg(APP_VERSION);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
KCHMMainWindow::~KCHMMainWindow()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotOpenMenuItemActivated()
|
|
|
|
{
|
|
|
|
#if defined (USE_KDE)
|
|
|
|
TQString fn = KFileDialog::getOpenFileName( appConfig.m_lastOpenedDir, i18n("*.chm|Compressed Help Manual (*.chm)"), this);
|
|
|
|
#else
|
|
|
|
TQString fn = TQFileDialog::getOpenFileName( appConfig.m_lastOpenedDir, i18n("Compressed Help Manual (*.chm)"), this);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if ( !fn.isEmpty() )
|
|
|
|
loadChmFile( fn );
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( !m_chmFile )
|
|
|
|
exit (1);
|
|
|
|
|
|
|
|
statusBar()->message( i18n("Loading aborted"), 2000 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool KCHMMainWindow::loadChmFile ( const TQString &fileName, bool call_open_page )
|
|
|
|
{
|
|
|
|
LCHMFile * new_chmfile = new LCHMFile();
|
|
|
|
|
|
|
|
if ( new_chmfile->loadFile( fileName ) )
|
|
|
|
{
|
|
|
|
// The new file is opened, so we can close the old one
|
|
|
|
if ( m_chmFile )
|
|
|
|
{
|
|
|
|
closeChmFile( );
|
|
|
|
delete m_chmFile;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_chmFile = new_chmfile;
|
|
|
|
|
|
|
|
// Show current encoding in status bar
|
|
|
|
showInStatusBar( tr("Detected chm file charset: %1") . arg(m_chmFile->currentEncoding()->language) );
|
|
|
|
|
|
|
|
// Make the file name absolute; we'll need it later
|
|
|
|
TQDir qd;
|
|
|
|
qd.setPath (fileName);
|
|
|
|
m_chmFilename = qd.absPath();
|
|
|
|
|
|
|
|
// TQt's 'dirname' does not work well
|
|
|
|
TQFileInfo qf ( m_chmFilename );
|
|
|
|
appConfig.m_lastOpenedDir = qf.dirPath(true);
|
|
|
|
|
|
|
|
// Order the tabulations
|
|
|
|
int number_of_pages = 0;
|
|
|
|
|
|
|
|
if ( m_chmFile->hasTableOfContents() )
|
|
|
|
m_tabContextPage = number_of_pages++;
|
|
|
|
else
|
|
|
|
m_tabContextPage = -1;
|
|
|
|
|
|
|
|
if ( m_chmFile->hasIndexTable() )
|
|
|
|
m_tabIndexPage = number_of_pages++;
|
|
|
|
else
|
|
|
|
m_tabIndexPage = -1;
|
|
|
|
|
|
|
|
// We always show search
|
|
|
|
m_tabSearchPage = number_of_pages++;
|
|
|
|
|
|
|
|
m_tabBookmarkPage = number_of_pages;
|
|
|
|
|
|
|
|
showOrHideContextWindow( m_tabContextPage );
|
|
|
|
showOrHideIndexWindow( m_tabIndexPage );
|
|
|
|
showOrHideSearchWindow( m_tabSearchPage );
|
|
|
|
|
|
|
|
m_bookmarkWindow->tqinvalidate();
|
|
|
|
m_navToolbar->updateIcontqStatus( false, false );
|
|
|
|
m_viewWindowMgr->tqinvalidate();
|
|
|
|
refreshCurrentBrowser();
|
|
|
|
|
|
|
|
if ( m_currentSettings->loadSettings (fileName) )
|
|
|
|
{
|
|
|
|
const LCHMTextEncoding * encoding =
|
|
|
|
m_chmFile->impl()->lookupByLCID( m_currentSettings->m_activeencodinglcid );
|
|
|
|
|
|
|
|
m_tabWidget->setCurrentPage( m_currentSettings->m_activetabsystem );
|
|
|
|
|
|
|
|
if ( encoding )
|
|
|
|
{
|
|
|
|
m_chmFile->setCurrentEncoding( encoding );
|
|
|
|
m_searchToolbar->setChosenEncodingInMenu( encoding );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( m_searchWindow )
|
|
|
|
m_searchWindow->restoreSettings (m_currentSettings->m_searchhistory);
|
|
|
|
|
|
|
|
m_bookmarkWindow->restoreSettings (m_currentSettings->m_bookmarks);
|
|
|
|
|
|
|
|
if ( call_open_page )
|
|
|
|
{
|
|
|
|
m_viewWindowMgr->restoreSettings( m_currentSettings->m_viewwindows );
|
|
|
|
m_viewWindowMgr->setCurrentPage( m_currentSettings->m_activetabwindow );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Restore the main window size
|
|
|
|
TQValueList<int> sizes;
|
|
|
|
sizes.push_back( m_currentSettings->m_window_size_splitter );
|
|
|
|
sizes.push_back( m_currentSettings->m_window_size_x - m_currentSettings->m_window_size_splitter );
|
|
|
|
|
|
|
|
m_windowSplitter->setSizes( sizes );
|
|
|
|
resize( m_currentSettings->m_window_size_x, m_currentSettings->m_window_size_y );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_tabWidget->setCurrentPage (0);
|
|
|
|
m_searchToolbar->setChosenEncodingInMenu( m_chmFile->currentEncoding() );
|
|
|
|
|
|
|
|
if ( call_open_page )
|
|
|
|
openPage( m_chmFile->homeUrl() );
|
|
|
|
}
|
|
|
|
|
|
|
|
m_searchToolbar->setEnabled (true);
|
|
|
|
appConfig.addFileToHistory( m_chmFilename );
|
|
|
|
updateHistoryMenu();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
TQMessageBox mbox(
|
|
|
|
i18n("%1 - failed to load the chm file") . arg(APP_NAME),
|
|
|
|
i18n("Unable to load the chm file %1") . arg(fileName),
|
|
|
|
TQMessageBox::Critical,
|
|
|
|
TQMessageBox::Ok,
|
|
|
|
TQMessageBox::NoButton,
|
|
|
|
TQMessageBox::NoButton);
|
|
|
|
mbox.exec();
|
|
|
|
|
|
|
|
statusBar()->message(
|
|
|
|
i18n("Could not load file %1").tqarg(fileName),
|
|
|
|
2000 );
|
|
|
|
delete new_chmfile;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotPrintMenuItemActivated()
|
|
|
|
{
|
|
|
|
currentBrowser()->printCurrentPage();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotAboutMenuItemActivated()
|
|
|
|
{
|
|
|
|
TQString caption = i18n( "About %1" ) . arg(APP_NAME);
|
|
|
|
TQString text = m_aboutDlgMenuText;
|
|
|
|
|
|
|
|
// It is quite funny that the argument order differs
|
|
|
|
#if defined (USE_KDE)
|
|
|
|
KMessageBox::about( this, text, caption );
|
|
|
|
#else
|
|
|
|
TQMessageBox::about( this, caption, text );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotAboutQtMenuItemActivated()
|
|
|
|
{
|
|
|
|
TQMessageBox::aboutTQt( this, APP_NAME);
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::refreshCurrentBrowser( )
|
|
|
|
{
|
|
|
|
TQString title = m_chmFile->title();
|
|
|
|
|
|
|
|
if ( !title )
|
|
|
|
title = APP_NAME;
|
|
|
|
// KDE adds application name automatically, so we don't need it here
|
|
|
|
#if !defined (USE_KDE)
|
|
|
|
else
|
|
|
|
title = (TQString) APP_NAME + " - " + title;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
setCaption ( title );
|
|
|
|
|
|
|
|
currentBrowser()->tqinvalidate();
|
|
|
|
|
|
|
|
if ( m_contentsWindow )
|
|
|
|
m_contentsWindow->refillTableOfContents();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotOnTreeClicked( TQListViewItem * item )
|
|
|
|
{
|
|
|
|
bool unused;
|
|
|
|
|
|
|
|
if ( !item )
|
|
|
|
return;
|
|
|
|
|
|
|
|
KCHMIndTocItem * treeitem = (KCHMIndTocItem*) item;
|
|
|
|
slotLinkClicked( treeitem->getUrl(), unused );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotLinkClicked ( const TQString & link, bool& follow_link )
|
|
|
|
{
|
|
|
|
if ( link.isEmpty() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ( gKeyEventFilter.isShiftPressed() )
|
|
|
|
{
|
|
|
|
openPage( link, OPF_NEW_TAB | OPF_CONTENT_TREE );
|
|
|
|
follow_link = false;
|
|
|
|
}
|
|
|
|
else if ( gKeyEventFilter.isCtrlPressed() )
|
|
|
|
{
|
|
|
|
openPage( link, OPF_NEW_TAB | OPF_BACKGROUND );
|
|
|
|
follow_link = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
// If the openPage failed, we do not need to follow the link.
|
|
|
|
follow_link = openPage( link, OPF_CONTENT_TREE | OPF_ADD2HISTORY );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool KCHMMainWindow::openPage( const TQString & srcurl, unsigned int flags )
|
|
|
|
{
|
|
|
|
TQString p1, p2, url = srcurl;
|
|
|
|
|
|
|
|
if ( url == "/" )
|
|
|
|
url = m_chmFile->homeUrl();
|
|
|
|
|
|
|
|
if ( LCHMUrlFactory::isRemoteURL (url, p1) )
|
|
|
|
{
|
|
|
|
switch ( appConfig.m_onExternalLinkClick )
|
|
|
|
{
|
|
|
|
case KCHMConfig::ACTION_DONT_OPEN:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case KCHMConfig::ACTION_ASK_USER:
|
|
|
|
if ( TQMessageBox::question(this,
|
|
|
|
i18n("%1 - remote link clicked - %2") . arg(APP_NAME) . arg(p1),
|
|
|
|
i18n("A remote link %1 will start the external program to open it.\n\nDo you want to continue?").tqarg( url ),
|
|
|
|
i18n("&Yes"), i18n("&No"),
|
|
|
|
TQString(), 0, 1 ) )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// no break! should continue to open.
|
|
|
|
|
|
|
|
case KCHMConfig::ACTION_ALWAYS_OPEN:
|
|
|
|
{
|
|
|
|
#if defined (USE_KDE)
|
|
|
|
new KRun ( url );
|
|
|
|
#else
|
|
|
|
run_process( appConfig.m_TQtBrowserPath, url );
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false; // do not change the current page.
|
|
|
|
}
|
|
|
|
|
|
|
|
// Filter the URLs which do not need to be opened at all by TQt version
|
|
|
|
if ( LCHMUrlFactory::isJavascriptURL (url) )
|
|
|
|
{
|
|
|
|
TQMessageBox::information( this,
|
|
|
|
i18n( "%1 - JavsScript link clicked") . arg(APP_NAME),
|
|
|
|
i18n( "You have clicked a JavaScript link.\nTo prevent security-related issues JavaScript URLs are disabled in CHM files.") );
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( LCHMUrlFactory::isNewChmURL (url, p1, p2) && p1 != m_chmFilename )
|
|
|
|
{
|
|
|
|
if ( TQMessageBox::question( this,
|
|
|
|
i18n( "%1 - link to a new CHM file clicked"). arg(APP_NAME),
|
|
|
|
i18n( "You have clicked a link, which leads to a new CHM file %1.\nThe current file will be closed.\n\nDo you want to continue?").tqarg( p1 ),
|
|
|
|
i18n( "&Yes" ), i18n( "&No" ),
|
|
|
|
TQString(), 0, 1 ) )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// Because chm file always contain relative link, and current filename is not changed,
|
|
|
|
// we need to form a new path
|
|
|
|
TQFileInfo qfi( m_chmFilename );
|
|
|
|
TQString newfilename = qfi.dirPath(true) + "/" + p1;
|
|
|
|
|
|
|
|
TQStringList event_args;
|
|
|
|
event_args.push_back( newfilename );
|
|
|
|
event_args.push_back( p2 ); // url
|
|
|
|
|
|
|
|
tqApp->postEvent( this, new KCHMUserEvent( "loadAndOpen", event_args ) );
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
KCHMViewWindow * vwnd = currentBrowser();
|
|
|
|
if ( flags & OPF_NEW_TAB )
|
|
|
|
vwnd = m_viewWindowMgr->addNewTab( !(flags & OPF_BACKGROUND) );
|
|
|
|
|
|
|
|
// Store current page and position to add it to history if we change it
|
|
|
|
int hist_scrollpos = currentBrowser()->getScrollbarPosition();
|
|
|
|
TQString hist_url = currentBrowser()->getOpenedPage();
|
|
|
|
|
|
|
|
if ( vwnd->openUrl (url) )
|
|
|
|
{
|
|
|
|
// Open all the tree items to show current item (if needed)
|
|
|
|
if ( (flags & OPF_CONTENT_TREE) != 0 )
|
|
|
|
locateInContentTree( vwnd->getOpenedPage() );
|
|
|
|
|
|
|
|
if ( flags & OPF_ADD2HISTORY )
|
|
|
|
currentBrowser()->addNavigationHistory( hist_url, hist_scrollpos );
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KCHMMainWindow::showEvent( TQShowEvent * )
|
|
|
|
{
|
|
|
|
if ( !m_FirstTimeShow )
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_FirstTimeShow = false;
|
|
|
|
|
|
|
|
if ( !parseCmdLineArgs( ) )
|
|
|
|
{
|
|
|
|
if ( appConfig.m_LoadLatestFileOnStartup && appConfig.m_History.size() > 0 )
|
|
|
|
{
|
|
|
|
if ( loadChmFile ( appConfig.m_History[0] ) )
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
emit slotOpenMenuItemActivated();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::setupToolbarsAndMenu( )
|
|
|
|
{
|
|
|
|
// Create a 'file' toolbar
|
|
|
|
TQToolBar * toolbar = new TQToolBar(this);
|
|
|
|
|
|
|
|
toolbar->setLabel( i18n( "File Operations") );
|
|
|
|
|
|
|
|
TQPixmap iconFileOpen (*gIconStorage.getToolbarPixmap(KCHMIconStorage::fileopen));
|
|
|
|
TQToolButton * fileOpen = new TQToolButton (iconFileOpen,
|
|
|
|
i18n( "Open File" ),
|
|
|
|
TQString(),
|
|
|
|
this,
|
|
|
|
TQT_SLOT( slotOpenMenuItemActivated() ),
|
|
|
|
toolbar);
|
|
|
|
|
|
|
|
TQString fileOpenText = i18n( "Click this button to open an existing chm file." );
|
|
|
|
TQWhatsThis::add( fileOpen, fileOpenText );
|
|
|
|
|
|
|
|
TQPixmap iconFilePrint (*gIconStorage.getToolbarPixmap(KCHMIconStorage::print));
|
|
|
|
TQToolButton * filePrint = new TQToolButton (iconFilePrint,
|
|
|
|
i18n( "Print File" ),
|
|
|
|
TQString(),
|
|
|
|
this,
|
|
|
|
TQT_SLOT( slotPrintMenuItemActivated() ),
|
|
|
|
toolbar);
|
|
|
|
|
|
|
|
TQString filePrintText = i18n( "Click this button to print the current page");
|
|
|
|
TQWhatsThis::add( filePrint, filePrintText );
|
|
|
|
|
|
|
|
// Setup the menu
|
|
|
|
KTQPopupMenu * file = new KTQPopupMenu( this );
|
|
|
|
menuBar()->insertItem( i18n( "&File"), file );
|
|
|
|
|
|
|
|
int id;
|
|
|
|
id = file->insertItem ( iconFileOpen, i18n( "&Open..."), this, TQT_SLOT( slotOpenMenuItemActivated() ), CTRL+Key_O );
|
|
|
|
file->TQMenuData::setWhatsThis( id, fileOpenText );
|
|
|
|
|
|
|
|
id = file->insertItem( iconFilePrint, i18n( "&Print..."), this, TQT_SLOT( slotPrintMenuItemActivated() ), CTRL+Key_P );
|
|
|
|
file->TQMenuData::setWhatsThis( id, filePrintText );
|
|
|
|
|
|
|
|
file->insertSeparator();
|
|
|
|
id = file->insertItem ( i18n( "E&xtract CHM content..."), this, TQT_SLOT( slotExtractCHM() ) );
|
|
|
|
file->TQMenuData::setWhatsThis( id, i18n( "Click this button to extract the whole CHM file content into a specific directory") );
|
|
|
|
file->insertSeparator();
|
|
|
|
|
|
|
|
m_menuHistory = new KTQPopupMenu( file );
|
|
|
|
connect ( m_menuHistory, TQT_SIGNAL( activated(int) ), this, TQT_SLOT ( slotHistoryMenuItemActivated(int) ));
|
|
|
|
|
|
|
|
file->insertItem( i18n( "&Recent files"), m_menuHistory );
|
|
|
|
|
|
|
|
file->insertSeparator();
|
|
|
|
file->insertItem( i18n( "&Quit"), tqApp, TQT_SLOT( closeAllWindows() ), CTRL+Key_Q );
|
|
|
|
|
|
|
|
KTQPopupMenu * menu_edit = new KTQPopupMenu( this );
|
|
|
|
menuBar()->insertItem( i18n( "&Edit"), menu_edit );
|
|
|
|
|
|
|
|
menu_edit->insertItem ( i18n( "&Copy"), this, TQT_SLOT( slotBrowserCopy()), CTRL+Key_C );
|
|
|
|
menu_edit->insertItem ( i18n( "&Select all"), this, TQT_SLOT( slotBrowserSelectAll()), CTRL+Key_A );
|
|
|
|
|
|
|
|
menu_edit->insertSeparator();
|
|
|
|
|
|
|
|
// KCHMNavToolbar
|
|
|
|
m_navToolbar = new KCHMNavToolbar( this );
|
|
|
|
|
|
|
|
// KCHMSearchToolbar also adds 'view' menu
|
|
|
|
m_searchToolbar = new KCHMSearchAndViewToolbar (this);
|
|
|
|
|
|
|
|
// m_bookmarkWindow adds 'Bookmarks' menu
|
|
|
|
m_bookmarkWindow->createMenu( this );
|
|
|
|
|
|
|
|
// m_viewWindowMgr creates 'Window' menu
|
|
|
|
m_viewWindowMgr->createMenu( this );
|
|
|
|
|
|
|
|
KTQPopupMenu * settings = new KTQPopupMenu( this );
|
|
|
|
menuBar()->insertItem( i18n( "&Settings"), settings );
|
|
|
|
settings->insertItem( i18n( "&Change settings..."), this, TQT_SLOT( slotChangeSettingsMenuItemActivated() ));
|
|
|
|
|
|
|
|
#if defined(USE_KDE)
|
|
|
|
TQPopupMenu *help = helpMenu( m_aboutDlgMenuText );
|
|
|
|
#else
|
|
|
|
KTQPopupMenu * help = new KTQPopupMenu( this );
|
|
|
|
help->insertItem( i18n( "&About"), this, TQT_SLOT( slotAboutMenuItemActivated() ), Key_F1 );
|
|
|
|
help->insertItem( i18n( "About &TQt"), this, TQT_SLOT( slotAboutQtMenuItemActivated() ));
|
|
|
|
help->insertSeparator();
|
|
|
|
help->insertItem( i18n( "What's &This"), this, TQT_SLOT(whatsThis()), SHIFT+Key_F1 );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
menuBar()->insertItem( i18n( "&Help"), help );
|
|
|
|
updateHistoryMenu();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotAddBookmark( )
|
|
|
|
{
|
|
|
|
emit m_bookmarkWindow->onAddBookmarkPressed ();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::setTextEncoding( const LCHMTextEncoding * encoding )
|
|
|
|
{
|
|
|
|
m_chmFile->setCurrentEncoding( encoding );
|
|
|
|
m_searchToolbar->setChosenEncodingInMenu( encoding );
|
|
|
|
|
|
|
|
// Because updateView() will call view->tqinvalidate(), which clears the view->getOpenedPage(),
|
|
|
|
// we have to make a copy of it.
|
|
|
|
TQString url = currentBrowser()->getOpenedPage();
|
|
|
|
|
|
|
|
// Regenerate the content and index trees
|
|
|
|
refreshCurrentBrowser();
|
|
|
|
|
|
|
|
currentBrowser()->openUrl( url );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::closeChmFile( )
|
|
|
|
{
|
|
|
|
// Prepare the settings
|
|
|
|
if ( appConfig.m_HistoryStoreExtra )
|
|
|
|
{
|
|
|
|
m_currentSettings->m_activeencodinglcid = m_chmFile->currentEncoding()->winlcid;
|
|
|
|
m_currentSettings->m_activetabsystem = m_tabWidget->currentPageIndex( );
|
|
|
|
m_currentSettings->m_activetabwindow = m_viewWindowMgr->currentPageIndex( );
|
|
|
|
|
|
|
|
m_currentSettings->m_window_size_x = width();
|
|
|
|
m_currentSettings->m_window_size_y = height();
|
|
|
|
m_currentSettings->m_window_size_splitter = m_windowSplitter->sizes()[0];
|
|
|
|
|
|
|
|
if ( m_searchWindow )
|
|
|
|
m_searchWindow->saveSettings (m_currentSettings->m_searchhistory);
|
|
|
|
|
|
|
|
m_bookmarkWindow->saveSettings( m_currentSettings->m_bookmarks );
|
|
|
|
|
|
|
|
m_viewWindowMgr->saveSettings( m_currentSettings->m_viewwindows );
|
|
|
|
|
|
|
|
m_currentSettings->saveSettings( );
|
|
|
|
}
|
|
|
|
|
|
|
|
appConfig.save();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KCHMMainWindow::closeEvent ( TQCloseEvent * e )
|
|
|
|
{
|
|
|
|
// Save the settings if we have something opened
|
|
|
|
if ( m_chmFile )
|
|
|
|
{
|
|
|
|
closeChmFile( );
|
|
|
|
delete m_chmFile;
|
|
|
|
m_chmFile = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQMainWindow::closeEvent ( e );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KCHMMainWindow::parseCmdLineArgs( )
|
|
|
|
{
|
|
|
|
TQString filename = TQString(), search_query = TQString();
|
|
|
|
TQString search_index = TQString(), search_bookmark = TQString();
|
|
|
|
bool do_autotest = false;
|
|
|
|
|
|
|
|
#if defined (USE_KDE)
|
|
|
|
KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
|
|
|
|
|
|
|
|
if ( args->isSet("autotestmode") )
|
|
|
|
do_autotest = true;
|
|
|
|
|
|
|
|
if ( args->isSet("shortautotestmode") )
|
|
|
|
do_autotest = m_useShortAutotest = true;
|
|
|
|
|
|
|
|
search_query = args->getOption ("search");
|
|
|
|
search_index = args->getOption ("sindex");
|
|
|
|
|
|
|
|
if ( args->count() > 0 )
|
|
|
|
filename = args->arg(0);
|
|
|
|
#else
|
|
|
|
// argv[0] in TQt is still a program name
|
|
|
|
for ( int i = 1; i < tqApp->argc(); i++ )
|
|
|
|
{
|
|
|
|
if ( !strcmp (tqApp->argv()[i], "--autotestmode") )
|
|
|
|
do_autotest = m_useShortAutotest = true;
|
|
|
|
else if ( !strcmp (tqApp->argv()[i], "--shortautotestmode") )
|
|
|
|
do_autotest = true;
|
|
|
|
else if ( !strcmp (tqApp->argv()[i], "--search") )
|
|
|
|
search_query = tqApp->argv()[++i];
|
|
|
|
else if ( !strcmp (tqApp->argv()[i], "--sindex") )
|
|
|
|
search_index = tqApp->argv()[++i];
|
|
|
|
else if ( !strcmp (tqApp->argv()[i], "-h") || !strcmp (tqApp->argv()[i], "--help") )
|
|
|
|
{
|
|
|
|
fprintf (stderr, "Usage: %s [chmfile]\n", tqApp->argv()[0]);
|
|
|
|
exit (1);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
filename = tqApp->argv()[i];
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if ( !filename.isEmpty() )
|
|
|
|
{
|
|
|
|
if ( !loadChmFile( TQString::fromLocal8Bit( filename )) )
|
|
|
|
return true; // skip the latest checks, but do not exit from the program
|
|
|
|
|
|
|
|
if ( !search_index.isEmpty() )
|
|
|
|
{
|
|
|
|
TQStringList event_args;
|
|
|
|
event_args.push_back( search_index );
|
|
|
|
tqApp->postEvent( this, new KCHMUserEvent( "findInIndex", event_args ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !search_query.isEmpty() )
|
|
|
|
{
|
|
|
|
TQStringList event_args;
|
|
|
|
event_args.push_back( search_query );
|
|
|
|
tqApp->postEvent( this, new KCHMUserEvent( "searchQuery", event_args ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( do_autotest )
|
|
|
|
{
|
|
|
|
#if defined (ENABLE_AUTOTEST_SUPPORT)
|
|
|
|
if ( filename.isEmpty() )
|
|
|
|
qFatal ("Could not use Auto Test mode without a chm file!");
|
|
|
|
|
|
|
|
m_autoteststate = STATE_INITIAL;
|
|
|
|
showMinimized ();
|
|
|
|
runAutoTest();
|
|
|
|
#else
|
|
|
|
qFatal ("Auto Test mode support is not compiled in.");
|
|
|
|
#endif /* defined (ENABLE_AUTOTEST_SUPPORT) */
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotBrowserSelectAll( )
|
|
|
|
{
|
|
|
|
currentBrowser()->clipSelectAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotBrowserCopy( )
|
|
|
|
{
|
|
|
|
currentBrowser()->clipCopy();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotChangeSettingsMenuItemActivated()
|
|
|
|
{
|
|
|
|
KCHMSetupDialog dlg ( this );
|
|
|
|
|
|
|
|
// Set up the parameters
|
|
|
|
dlg.m_radioOnBeginOpenDialog->setChecked ( !appConfig.m_LoadLatestFileOnStartup );
|
|
|
|
dlg.m_radioOnBeginOpenLast->setChecked ( appConfig.m_LoadLatestFileOnStartup );
|
|
|
|
dlg.m_historySize->setValue ( appConfig.m_HistorySize );
|
|
|
|
dlg.m_rememberHistoryInfo->setChecked ( appConfig.m_HistoryStoreExtra );
|
|
|
|
|
|
|
|
dlg.m_radioExtLinkOpenAlways->setChecked ( appConfig.m_onExternalLinkClick == KCHMConfig::ACTION_ALWAYS_OPEN );
|
|
|
|
dlg.m_radioExtLinkAsk->setChecked ( appConfig.m_onExternalLinkClick == KCHMConfig::ACTION_ASK_USER );
|
|
|
|
dlg.m_radioExtLinkOpenNever->setChecked ( appConfig.m_onExternalLinkClick == KCHMConfig::ACTION_DONT_OPEN );
|
|
|
|
|
|
|
|
dlg.m_radioNewChmOpenAlways->setChecked ( appConfig.m_onNewChmClick == KCHMConfig::ACTION_ALWAYS_OPEN );
|
|
|
|
dlg.m_radioNewChmAsk->setChecked ( appConfig.m_onNewChmClick == KCHMConfig::ACTION_ASK_USER );
|
|
|
|
dlg.m_radioNewChmOpenNever->setChecked ( appConfig.m_onNewChmClick == KCHMConfig::ACTION_DONT_OPEN );
|
|
|
|
|
|
|
|
#if defined (USE_KDE)
|
|
|
|
dlg.m_groupQtsettings->setEnabled ( false );
|
|
|
|
dlg.m_groupKDEsettings->setEnabled ( true );
|
|
|
|
#else
|
|
|
|
dlg.m_groupQtsettings->setEnabled ( true );
|
|
|
|
dlg.m_groupKDEsettings->setEnabled ( false );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
dlg.m_qtBrowserPath->setText ( appConfig.m_TQtBrowserPath );
|
|
|
|
dlg.m_radioUseQtextBrowser->setChecked ( appConfig.m_kdeUseTQTextBrowser );
|
|
|
|
dlg.m_radioUseKHTMLPart->setChecked ( !appConfig.m_kdeUseTQTextBrowser );
|
|
|
|
|
|
|
|
dlg.m_enableJS->setChecked ( appConfig.m_kdeEnableJS );
|
|
|
|
dlg.m_enablePlugins->setChecked ( appConfig.m_kdeEnablePlugins );
|
|
|
|
dlg.m_enableJava->setChecked ( appConfig.m_kdeEnableJava );
|
|
|
|
dlg.m_enableRefresh->setChecked ( appConfig.m_kdeEnableRefresh );
|
|
|
|
|
|
|
|
dlg.m_advExternalProgramName->setText( appConfig.m_advExternalEditorPath );
|
|
|
|
dlg.m_advViewSourceExternal->setChecked ( !appConfig.m_advUseInternalEditor );
|
|
|
|
dlg.m_advViewSourceInternal->setChecked ( appConfig.m_advUseInternalEditor );
|
|
|
|
|
|
|
|
// Search engine
|
|
|
|
dlg.m_useSearchEngineInternal->setChecked( appConfig.m_useSearchEngine == KCHMConfig::SEARCH_USE_CHM );
|
|
|
|
dlg.m_useSearchEngineNew->setChecked( appConfig.m_useSearchEngine == KCHMConfig::SEARCH_USE_MINE );
|
|
|
|
|
|
|
|
// Connect buddies
|
|
|
|
dlg.m_labelUseSearchEngineInternal->setBuddy( dlg.m_useSearchEngineInternal );
|
|
|
|
dlg.m_labelUseSearchEngineNew->setBuddy( dlg.m_useSearchEngineNew );
|
|
|
|
|
|
|
|
if ( dlg.exec() == TQDialog::Accepted )
|
|
|
|
{
|
|
|
|
appConfig.m_LoadLatestFileOnStartup = dlg.m_radioOnBeginOpenLast->isChecked();
|
|
|
|
appConfig.m_HistorySize = dlg.m_historySize->value();
|
|
|
|
appConfig.m_HistoryStoreExtra = dlg.m_rememberHistoryInfo->isChecked();
|
|
|
|
|
|
|
|
if ( dlg.m_radioExtLinkOpenAlways->isChecked () )
|
|
|
|
appConfig.m_onExternalLinkClick = KCHMConfig::ACTION_ALWAYS_OPEN;
|
|
|
|
else if ( dlg.m_radioExtLinkAsk->isChecked () )
|
|
|
|
appConfig.m_onExternalLinkClick = KCHMConfig::ACTION_ASK_USER;
|
|
|
|
else
|
|
|
|
appConfig.m_onExternalLinkClick = KCHMConfig::ACTION_DONT_OPEN;
|
|
|
|
|
|
|
|
if ( dlg.m_radioNewChmOpenAlways->isChecked () )
|
|
|
|
appConfig.m_onNewChmClick = KCHMConfig::ACTION_ALWAYS_OPEN;
|
|
|
|
else if ( dlg.m_radioNewChmAsk->isChecked () )
|
|
|
|
appConfig.m_onNewChmClick = KCHMConfig::ACTION_ASK_USER;
|
|
|
|
else
|
|
|
|
appConfig.m_onNewChmClick = KCHMConfig::ACTION_DONT_OPEN;
|
|
|
|
|
|
|
|
appConfig.m_TQtBrowserPath = dlg.m_qtBrowserPath->text();
|
|
|
|
|
|
|
|
// Check the changes
|
|
|
|
bool need_restart = false;
|
|
|
|
|
|
|
|
if ( appConfig.m_kdeEnableJS != dlg.m_enableJS->isChecked() )
|
|
|
|
{
|
|
|
|
need_restart = true;
|
|
|
|
appConfig.m_kdeEnableJS = dlg.m_enableJS->isChecked();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( appConfig.m_kdeEnablePlugins != dlg.m_enablePlugins->isChecked() )
|
|
|
|
{
|
|
|
|
need_restart = true;
|
|
|
|
appConfig.m_kdeEnablePlugins = dlg.m_enablePlugins->isChecked();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( appConfig.m_kdeEnableJava != dlg.m_enableJava->isChecked() )
|
|
|
|
{
|
|
|
|
need_restart = true;
|
|
|
|
appConfig.m_kdeEnableJava = dlg.m_enableJava->isChecked();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( appConfig.m_kdeEnableRefresh != dlg.m_enableRefresh->isChecked() )
|
|
|
|
{
|
|
|
|
need_restart = true;
|
|
|
|
appConfig.m_kdeEnableRefresh = dlg.m_enableRefresh->isChecked();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( appConfig.m_kdeUseTQTextBrowser != dlg.m_radioUseQtextBrowser->isChecked() )
|
|
|
|
{
|
|
|
|
need_restart = true;
|
|
|
|
appConfig.m_kdeUseTQTextBrowser = dlg.m_radioUseQtextBrowser->isChecked();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( dlg.m_useSearchEngineNew->isChecked()
|
|
|
|
&& appConfig.m_useSearchEngine == KCHMConfig::SEARCH_USE_CHM )
|
|
|
|
{
|
|
|
|
appConfig.m_useSearchEngine = KCHMConfig::SEARCH_USE_MINE;
|
|
|
|
m_searchWindow->tqinvalidate();
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( dlg.m_useSearchEngineInternal->isChecked()
|
|
|
|
&& appConfig.m_useSearchEngine == KCHMConfig::SEARCH_USE_MINE )
|
|
|
|
{
|
|
|
|
appConfig.m_useSearchEngine = KCHMConfig::SEARCH_USE_CHM;
|
|
|
|
m_searchWindow->tqinvalidate();
|
|
|
|
}
|
|
|
|
|
|
|
|
appConfig.m_advExternalEditorPath = dlg.m_advExternalProgramName->text();
|
|
|
|
appConfig.m_advUseInternalEditor = dlg.m_advViewSourceExternal->isChecked();
|
|
|
|
appConfig.m_advUseInternalEditor = dlg.m_advViewSourceInternal->isChecked();
|
|
|
|
|
|
|
|
appConfig.save();
|
|
|
|
|
|
|
|
if ( need_restart )
|
|
|
|
TQMessageBox::information(
|
|
|
|
this,
|
|
|
|
APP_NAME,
|
|
|
|
i18n( "Changing browser view options or search engine used\n"
|
|
|
|
"requires restarting the application to take effect." ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KCHMMainWindow::setupSignals( )
|
|
|
|
{
|
|
|
|
#if defined(HAVE_SIGACTION)
|
|
|
|
struct sigaction sa;
|
|
|
|
memset ((char *)&sa, 0, sizeof(sa));
|
|
|
|
sigemptyset (&sa.sa_mask);
|
|
|
|
sigaddset (&sa.sa_mask, SIGCHLD);
|
|
|
|
|
|
|
|
#ifdef SA_RESTART
|
|
|
|
sa.sa_flags = SA_RESTART;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
sa.sa_handler = SIG_IGN;
|
|
|
|
sigaction (SIGCHLD, &sa, (struct sigaction *)0);
|
|
|
|
#else /* !HAVE_SIGACTION */
|
|
|
|
signal (SIGCHLD, SIG_IGN);
|
|
|
|
#endif /* HAVE_SIGACTION */
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotHistoryMenuItemActivated( int item )
|
|
|
|
{
|
|
|
|
if ( item < 0 || item >= (signed) appConfig.m_History.size() )
|
|
|
|
qFatal ("KCHMMainWindow::slotHistoryMenuItemActivated: bad history menu id %d", item);
|
|
|
|
|
|
|
|
TQString filename = appConfig.m_History[item];
|
|
|
|
|
|
|
|
// remove it, so it will be added again at the history top, and will not shitf anything.
|
|
|
|
// appConfig.m_History.remove ( appConfig.m_History.begin() + item);
|
|
|
|
loadChmFile ( filename );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::updateHistoryMenu()
|
|
|
|
{
|
|
|
|
m_menuHistory->clear ();
|
|
|
|
|
|
|
|
for ( int i = appConfig.m_History.size() - 1; i >= 0; i-- )
|
|
|
|
m_menuHistory->insertItem( appConfig.m_History[i], i );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotActivateContentTab( )
|
|
|
|
{
|
|
|
|
if ( m_tabContextPage != -1 )
|
|
|
|
m_tabWidget->setCurrentPage( m_tabContextPage );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotActivateIndexTab( )
|
|
|
|
{
|
|
|
|
if ( m_tabIndexPage != -1 )
|
|
|
|
m_tabWidget->setCurrentPage( m_tabIndexPage );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotActivateSearchTab( )
|
|
|
|
{
|
|
|
|
if ( m_tabSearchPage != -1 )
|
|
|
|
m_tabWidget->setCurrentPage( m_tabSearchPage );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotActivateBookmarkTab( )
|
|
|
|
{
|
|
|
|
m_tabWidget->setCurrentPage( m_tabBookmarkPage );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::showOrHideContextWindow( int tabindex )
|
|
|
|
{
|
|
|
|
if ( tabindex == -1 )
|
|
|
|
{
|
|
|
|
if ( m_contentsWindow )
|
|
|
|
{
|
|
|
|
m_tabWidget->removePage (m_contentsWindow);
|
|
|
|
delete m_contentsWindow;
|
|
|
|
m_contentsWindow = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( !m_contentsWindow )
|
|
|
|
{
|
|
|
|
m_contentsWindow = new KCHMContentsWindow( m_tabWidget );
|
|
|
|
|
|
|
|
// Handle clicking on m_contentsWindow element
|
|
|
|
connect( m_contentsWindow,
|
|
|
|
TQT_SIGNAL( clicked( TQListViewItem* ) ),
|
|
|
|
this,
|
|
|
|
TQT_SLOT( slotOnTreeClicked( TQListViewItem* ) ) );
|
|
|
|
|
|
|
|
connect( m_contentsWindow,
|
|
|
|
TQT_SIGNAL( doubleClicked ( TQListViewItem *, const TQPoint &, int ) ),
|
|
|
|
this,
|
|
|
|
TQT_SLOT( slotOnTreeDoubleClicked ( TQListViewItem *, const TQPoint &, int ) ) );
|
|
|
|
|
|
|
|
m_tabWidget->insertTab (m_contentsWindow, i18n( "Contents" ), tabindex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::showOrHideIndexWindow( int tabindex )
|
|
|
|
{
|
|
|
|
// Test whether to show/tqinvalidate the index window
|
|
|
|
if ( tabindex == -1 )
|
|
|
|
{
|
|
|
|
if ( m_indexWindow )
|
|
|
|
{
|
|
|
|
m_tabWidget->removePage (m_indexWindow);
|
|
|
|
delete m_indexWindow;
|
|
|
|
m_indexWindow = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( !m_indexWindow )
|
|
|
|
{
|
|
|
|
m_indexWindow = new KCHMIndexWindow (m_tabWidget);
|
|
|
|
m_tabWidget->insertTab (m_indexWindow, i18n( "Index" ), tabindex);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
m_indexWindow->tqinvalidate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::showOrHideSearchWindow( int tabindex )
|
|
|
|
{
|
|
|
|
if ( tabindex == -1 )
|
|
|
|
{
|
|
|
|
if ( m_searchWindow )
|
|
|
|
{
|
|
|
|
m_tabWidget->removePage (m_searchWindow);
|
|
|
|
delete m_searchWindow;
|
|
|
|
m_searchWindow = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( !m_searchWindow )
|
|
|
|
{
|
|
|
|
m_searchWindow = new KCHMSearchWindow (m_tabWidget);
|
|
|
|
m_tabWidget->insertTab (m_searchWindow, i18n( "Search" ), tabindex);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
m_searchWindow->tqinvalidate();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotEnableFullScreenMode( bool enable )
|
|
|
|
{
|
|
|
|
if ( enable )
|
|
|
|
{
|
|
|
|
if ( !isFullScreen() )
|
|
|
|
{
|
|
|
|
showFullScreen ();
|
|
|
|
menuBar()->hide();
|
|
|
|
statusBar()->hide();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( isFullScreen() )
|
|
|
|
{
|
|
|
|
showNormal ();
|
|
|
|
menuBar()->show();
|
|
|
|
statusBar()->show();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotShowContentsWindow( bool show )
|
|
|
|
{
|
|
|
|
if ( show )
|
|
|
|
m_tabWidget->show();
|
|
|
|
else
|
|
|
|
m_tabWidget->hide();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotToggleFullScreenMode( )
|
|
|
|
{
|
|
|
|
slotEnableFullScreenMode( !isFullScreen() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotLocateInContentWindow( )
|
|
|
|
{
|
|
|
|
// There may be no content tab at all
|
|
|
|
if ( !m_contentsWindow || m_tabContextPage == -1 )
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Activate a content tab
|
|
|
|
m_tabWidget->setCurrentPage( m_tabContextPage );
|
|
|
|
|
|
|
|
if ( m_contentsWindow )
|
|
|
|
{
|
|
|
|
// Open all the tree items to show current item (if needed)
|
|
|
|
KCHMIndTocItem * treeitem = m_contentsWindow->getTreeItem( currentBrowser()->getOpenedPage() );
|
|
|
|
|
|
|
|
if ( treeitem )
|
|
|
|
{
|
|
|
|
KCHMIndTocItem * itemparent = treeitem;
|
|
|
|
|
|
|
|
while ( (itemparent = (KCHMIndTocItem*) itemparent->parent()) != 0 )
|
|
|
|
itemparent->setOpen(true);
|
|
|
|
|
|
|
|
m_contentsWindow->setCurrentItem (treeitem);
|
|
|
|
m_contentsWindow->ensureItemVisible (treeitem);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
statusBar()->message( i18n( "Could not locate opened topic in content window"), 2000 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotExtractCHM( )
|
|
|
|
{
|
|
|
|
TQStringList files;
|
|
|
|
|
|
|
|
#if defined (USE_KDE)
|
|
|
|
TQString outdir = KFileDialog::getExistingDirectory (
|
|
|
|
TQString(),
|
|
|
|
this,
|
|
|
|
i18n("Choose a directory to store CHM content") );
|
|
|
|
#else
|
|
|
|
TQString outdir = TQFileDialog::getExistingDirectory (
|
|
|
|
TQString(),
|
|
|
|
this,
|
|
|
|
0,
|
|
|
|
i18n("Choose a directory to store CHM content"),
|
|
|
|
TRUE );
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if ( outdir.isEmpty() )
|
|
|
|
return;
|
|
|
|
|
|
|
|
outdir += "/";
|
|
|
|
|
|
|
|
// Enumerate all the files in archive
|
|
|
|
if ( !m_chmFile || !m_chmFile->enumerateFiles( &files ) )
|
|
|
|
return;
|
|
|
|
|
|
|
|
KTQProgressModalDialog progress( i18n("Extracting CHM content"), i18n("Extracting files..."), i18n("Abort"), files.size(), this );
|
|
|
|
|
|
|
|
for ( unsigned int i = 0; i < files.size(); i++ )
|
|
|
|
{
|
|
|
|
progress.setProgress( i );
|
|
|
|
|
|
|
|
if ( (i % 3) == 0 )
|
|
|
|
{
|
|
|
|
tqApp->processEvents();
|
|
|
|
|
|
|
|
if ( progress.wasCancelled() )
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Extract the file
|
|
|
|
TQByteArray buf;
|
|
|
|
|
|
|
|
if ( m_chmFile->getFileContentAsBinary( &buf, files[i] ) )
|
|
|
|
{
|
|
|
|
// Split filename to get the list of subdirectories
|
|
|
|
TQStringList dirs = TQStringList::split( '/', files[i] );
|
|
|
|
|
|
|
|
// Walk through the list of subdirectories, and create them if needed
|
|
|
|
// dirlevel is used to detect extra .. and prevent overwriting files
|
|
|
|
// outside the directory (like creating the file images/../../../../../etc/passwd
|
|
|
|
unsigned int i, dirlevel = 0;
|
|
|
|
TQStringList dirlist;
|
|
|
|
|
|
|
|
for ( i = 0; i < dirs.size() - 1; i++ )
|
|
|
|
{
|
|
|
|
// Skip .. which lead too far above
|
|
|
|
if ( dirs[i] == ".." )
|
|
|
|
{
|
|
|
|
if ( dirlevel > 0 )
|
|
|
|
{
|
|
|
|
dirlevel--;
|
|
|
|
dirlist.pop_back();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
dirlist.push_back( dirs[i] );
|
|
|
|
|
|
|
|
TQDir dir ( outdir + dirlist.join( "/" ) );
|
|
|
|
if ( !dir.exists() )
|
|
|
|
{
|
|
|
|
if ( !dir.mkdir( dir.path() ) )
|
|
|
|
qWarning( "Could not create subdir %s\n", dir.path().ascii() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString filename = outdir + dirlist.join( "/" ) + "/" + dirs[i];
|
|
|
|
TQFile wf( filename );
|
|
|
|
if ( !wf.open( IO_WriteOnly ) )
|
|
|
|
{
|
|
|
|
qWarning( "Could not write file %s\n", filename.ascii() );
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
wf. writeBlock( buf );
|
|
|
|
wf.close();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
qWarning( "Could not get file %s\n", files[i].ascii() );
|
|
|
|
}
|
|
|
|
|
|
|
|
progress.setProgress( files.size() );
|
|
|
|
}
|
|
|
|
|
|
|
|
KCHMViewWindow * KCHMMainWindow::currentBrowser( ) const
|
|
|
|
{
|
|
|
|
return m_viewWindowMgr->current();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotOpenPageInNewTab( )
|
|
|
|
{
|
|
|
|
openPage( currentBrowser()->getNewTabLink(), OPF_NEW_TAB | OPF_CONTENT_TREE );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotOpenPageInNewBackgroundTab( )
|
|
|
|
{
|
|
|
|
openPage( currentBrowser()->getNewTabLink(), OPF_NEW_TAB | OPF_BACKGROUND );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotBrowserChanged( KCHMViewWindow * newbrowser )
|
|
|
|
{
|
|
|
|
locateInContentTree( newbrowser->getOpenedPage() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::locateInContentTree( const TQString & url )
|
|
|
|
{
|
|
|
|
if ( !m_contentsWindow )
|
|
|
|
return;
|
|
|
|
|
|
|
|
KCHMIndTocItem * treeitem = m_contentsWindow->getTreeItem( url );
|
|
|
|
|
|
|
|
if ( treeitem )
|
|
|
|
{
|
|
|
|
KCHMIndTocItem * itemparent = treeitem;
|
|
|
|
while ( (itemparent = (KCHMIndTocItem*) itemparent->parent()) != 0 )
|
|
|
|
itemparent->setOpen(true);
|
|
|
|
|
|
|
|
m_contentsWindow->setCurrentItem (treeitem);
|
|
|
|
m_contentsWindow->ensureItemVisible (treeitem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void KCHMMainWindow::slotOnTreeDoubleClicked( TQListViewItem * item, const TQPoint &, int )
|
|
|
|
{
|
|
|
|
// Open/close only existing item which have tqchildren
|
|
|
|
if ( !item || item->childCount() == 0 )
|
|
|
|
return;
|
|
|
|
|
|
|
|
item->setOpen( !item->isOpen() );
|
|
|
|
item->tqrepaint();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KCHMMainWindow::event( TQEvent * e )
|
|
|
|
{
|
|
|
|
if ( e->type() == TQEvent::User )
|
|
|
|
return handleUserEvent( (KCHMUserEvent*) e );
|
|
|
|
|
|
|
|
return TQWidget::event( e );
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KCHMMainWindow::handleUserEvent( const KCHMUserEvent * event )
|
|
|
|
{
|
|
|
|
if ( event->m_action == "loadAndOpen" )
|
|
|
|
{
|
|
|
|
if ( event->m_args.size() != 1 && event->m_args.size() != 2 )
|
|
|
|
qFatal("handleUserEvent: event loadAndOpen must receive 1 or 2 args");
|
|
|
|
|
|
|
|
TQString chmfile = event->m_args[0];
|
|
|
|
TQString openurl = event->m_args.size() > 1 ? event->m_args[1] : "/";
|
|
|
|
|
|
|
|
return loadChmFile( chmfile, false ) && openPage( openurl );
|
|
|
|
}
|
|
|
|
else if ( event->m_action == "openPage" )
|
|
|
|
{
|
|
|
|
if ( event->m_args.size() != 1 )
|
|
|
|
qFatal("handleUserEvent: event openPage must receive 1 arg");
|
|
|
|
|
|
|
|
return openPage( event->m_args[0] );
|
|
|
|
}
|
|
|
|
else if ( event->m_action == "findInIndex" )
|
|
|
|
{
|
|
|
|
if ( event->m_args.size() != 1 )
|
|
|
|
qFatal( "handleUserEvent: event searchQuery must receive 1 arg" );
|
|
|
|
|
|
|
|
if ( m_tabIndexPage == -1 )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
slotActivateIndexTab();
|
|
|
|
m_indexWindow->search( event->m_args[0] );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else if ( event->m_action == "searchQuery" )
|
|
|
|
{
|
|
|
|
if ( event->m_args.size() != 1 )
|
|
|
|
qFatal( "handleUserEvent: event searchQuery must receive 1 arg" );
|
|
|
|
|
|
|
|
if ( m_tabSearchPage == -1 )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
slotActivateSearchTab();
|
|
|
|
m_searchWindow->execSearchQueryInGui( event->m_args[0] );
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
qWarning( "Unknown user event received: %s", event->m_action.ascii() );
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#if defined (ENABLE_AUTOTEST_SUPPORT)
|
|
|
|
void KCHMMainWindow::runAutoTest()
|
|
|
|
{
|
|
|
|
KCHMIndTocItem * item;
|
|
|
|
|
|
|
|
switch (m_autoteststate)
|
|
|
|
{
|
|
|
|
case STATE_INITIAL:
|
|
|
|
if ( m_contentsWindow && !m_useShortAutotest )
|
|
|
|
{
|
|
|
|
m_autotestlistiterator = TQListViewItemIterator (m_contentsWindow);
|
|
|
|
m_autoteststate = STATE_CONTENTS_OPENNEXTPAGE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
m_autoteststate = STATE_OPEN_INDEX;
|
|
|
|
|
|
|
|
TQTimer::singleShot (500, this, TQT_SLOT(runAutoTest()) );
|
|
|
|
break; // allow to finish the initialization sequence
|
|
|
|
|
|
|
|
case STATE_CONTENTS_OPENNEXTPAGE:
|
|
|
|
if ( (item = (KCHMIndTocItem *) m_autotestlistiterator.current()) != 0 )
|
|
|
|
{
|
|
|
|
openPage( item->getUrl(), OPF_CONTENT_TREE | OPF_ADD2HISTORY );
|
|
|
|
m_autotestlistiterator++;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
m_autoteststate = STATE_OPEN_INDEX;
|
|
|
|
|
|
|
|
TQTimer::singleShot (50, this, TQT_SLOT(runAutoTest()) );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_OPEN_INDEX:
|
|
|
|
if ( m_indexWindow )
|
|
|
|
m_tabWidget->setCurrentPage (1);
|
|
|
|
|
|
|
|
m_autoteststate = STATE_SHUTDOWN;
|
|
|
|
TQTimer::singleShot (500, this, TQT_SLOT(runAutoTest()) );
|
|
|
|
break;
|
|
|
|
|
|
|
|
case STATE_SHUTDOWN:
|
|
|
|
tqApp->quit();
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* defined (ENABLE_AUTOTEST_SUPPORT) */
|
|
|
|
|
|
|
|
|
|
|
|
//TODO: KDE: xmlgui
|
|
|
|
//TODO: Search result highlighting
|