📄 kchmmainwindow.cpp
字号:
/*************************************************************************** * 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., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/#include <stdlib.h>#include <signal.h>#include <string.h>#include <stdio.h>#include <errno.h>#include <unistd.h>#include "kde-qt.h"#include <qaccel.h>#include <qevent.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 layout - a splitter with tab window in left, and text browser in right m_windowSplitter = new QSplitter(this); m_tabWidget = new KQTabWidget( 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 ); QValueList<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) */ QAccel * accel = new QAccel( this ); accel->connectItem ( accel->insertItem ( Key_F11 ), this, SLOT ( slotToggleFullScreenMode() ) ); accel->connectItem ( accel->insertItem ( CTRL + Key_1), this, SLOT ( slotActivateContentTab() ) ); accel->connectItem ( accel->insertItem ( CTRL + Key_2), this, SLOT ( slotActivateIndexTab() ) ); accel->connectItem ( accel->insertItem ( CTRL + Key_3), this, SLOT ( slotActivateSearchTab() ) ); accel->connectItem ( accel->insertItem ( CTRL + Key_4), this, SLOT ( slotActivateBookmarkTab() ) ); accel->connectItem ( accel->insertItem ( Key_F3 ), m_searchToolbar, 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) QString fn = KFileDialog::getOpenFileName( appConfig.m_lastOpenedDir, i18n("*.chm|Compressed Help Manual (*.chm)"), this);#else QString fn = QFileDialog::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 QString &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 QDir qd; qd.setPath (fileName); m_chmFilename = qd.absPath(); // Qt's 'dirname' does not work well QFileInfo 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->invalidate(); m_navToolbar->updateIconStatus( false, false ); m_viewWindowMgr->invalidate(); 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 QValueList<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 { if ( !m_chmFile ) { QMessageBox mbox( i18n("%1 - failed to load the chm file") . arg(APP_NAME), i18n("Unable to load the chm file %1") . arg(fileName), QMessageBox::Critical, QMessageBox::Ok, QMessageBox::NoButton, QMessageBox::NoButton); mbox.exec(); exit (1); } statusBar()->message( i18n("Could not load file %1").arg(fileName), 2000 ); delete new_chmfile; return false; }}void KCHMMainWindow::slotPrintMenuItemActivated(){ currentBrowser()->printCurrentPage();}void KCHMMainWindow::slotAboutMenuItemActivated(){ QString caption = i18n( "About %1" ) . arg(APP_NAME); QString text = m_aboutDlgMenuText; // It is quite funny that the argument order differs#if defined (USE_KDE) KMessageBox::about( this, text, caption );#else QMessageBox::about( this, caption, text );#endif}void KCHMMainWindow::slotAboutQtMenuItemActivated(){ QMessageBox::aboutQt( this, APP_NAME);}void KCHMMainWindow::refreshCurrentBrowser( ){ QString 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 = (QString) APP_NAME + " - " + title;#endif setCaption ( title ); currentBrowser()->invalidate(); if ( m_contentsWindow ) m_contentsWindow->refillTableOfContents();}void KCHMMainWindow::slotOnTreeClicked( QListViewItem * item ){ bool unused; if ( !item ) return; KCHMIndTocItem * treeitem = (KCHMIndTocItem*) item; slotLinkClicked( treeitem->getUrl(), unused );}void KCHMMainWindow::slotLinkClicked ( const QString & 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 QString & srcurl, unsigned int flags ){ QString 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 ( QMessageBox::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?").arg( url ), i18n("&Yes"), i18n("&No"), QString::null, 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_QtBrowserPath, url );#endif } break; } return false; // do not change the current page. } // Filter the URLs which do not need to be opened at all by Qt version if ( LCHMUrlFactory::isJavascriptURL (url) ) { QMessageBox::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 ( QMessageBox::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?").arg( p1 ), i18n( "&Yes" ), i18n( "&No" ), QString::null, 0, 1 ) ) return false; // Because chm file always contain relative link, and current filename is not changed, // we need to form a new path QFileInfo qfi( m_chmFilename ); QString newfilename = qfi.dirPath(true) + "/" + p1; QStringList event_args; event_args.push_back( newfilename ); event_args.push_back( p2 ); // url qApp->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(); QString hist_url = currentBrowser()->getOpenedPage();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -