Fix crash if key bindings specified in profile cannot be found. Improve
[personal-kdebase.git] / runtime / khelpcenter / mainwindow.cpp
blobc2e73f5243797bfbb3d5e9c1b99bdbd7cfc915fb
1 /*
2 * This file is part of the KDE Help Center
4 * Copyright (C) 1999 Matthias Elter (me@kde.org)
5 * 2001 Stephan Kulow (coolo@kde.org)
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #include "mainwindow.h"
24 #include "history.h"
25 #include "view.h"
26 #include "searchengine.h"
27 #include "fontdialog.h"
28 #include "prefs.h"
29 #include <QtDBus/QDBusConnection>
30 #include <kaction.h>
31 #include <kactioncollection.h>
32 #include <kapplication.h>
33 #include <kconfig.h>
34 #include <kicon.h>
35 #include <kiconloader.h>
36 #include <kmimetype.h>
37 #include <krun.h>
38 #include <kaboutdata.h>
39 #include <kdebug.h>
40 #include <khtmlview.h>
41 #include <khtml_settings.h>
42 #include <kstatusbar.h>
43 #include <kstandardshortcut.h>
44 #include <kdialog.h>
45 #include <klocale.h>
46 #include <kstandardaction.h>
47 #include <kxmlguifactory.h>
48 #include <kstartupinfo.h>
50 #include <QSplitter>
51 #include <QTextEdit>
52 #include <QLayout>
53 //Added by qt3to4:
54 #include <QVBoxLayout>
55 #include <QFrame>
56 #include <QList>
57 #include <QBoxLayout>
59 #include <stdlib.h>
60 #include <assert.h>
61 #include <kglobal.h>
62 #include <kconfiggroup.h>
64 using namespace KHC;
66 class LogDialog : public KDialog
68 public:
69 LogDialog( QWidget *parent = 0 )
70 : KDialog( parent )
72 setCaption( i18n("Search Error Log") );
73 setButtons( Ok );
75 QFrame *topFrame = new QFrame( this );
76 setMainWidget( topFrame );
78 QBoxLayout *topLayout = new QVBoxLayout( topFrame );
80 mTextView = new QTextEdit( topFrame );
81 mTextView->setTextFormat( Qt::LogText );
82 topLayout->addWidget( mTextView );
84 KConfigGroup cg = KGlobal::config()->group( "logdialog" );
85 restoreDialogSize( cg );
88 ~LogDialog()
90 KConfigGroup cg = KGlobal::config()->group( "logdialog" );
91 KDialog::saveDialogSize( cg );
94 void setLog( const QString &log )
96 mTextView->setText( log );
99 private:
100 QTextEdit *mTextView;
104 MainWindow::MainWindow()
105 : KXmlGuiWindow(0),
106 mLogDialog( 0 )
108 setObjectName( "MainWindow" );
110 QDBusConnection::sessionBus().registerObject("/KHelpCenter", this, QDBusConnection::ExportScriptableSlots);
111 mSplitter = new QSplitter( this );
113 mDoc = new View( mSplitter, this, KHTMLPart::DefaultGUI, actionCollection() );
114 connect( mDoc, SIGNAL( setWindowCaption( const QString & ) ),
115 SLOT( setCaption( const QString & ) ) );
116 connect( mDoc, SIGNAL( setStatusBarText( const QString & ) ),
117 SLOT( statusBarMessage( const QString & ) ) );
118 connect( mDoc, SIGNAL( onURL( const QString & ) ),
119 SLOT( statusBarMessage( const QString & ) ) );
120 connect( mDoc, SIGNAL( started( KIO::Job * ) ),
121 SLOT( slotStarted( KIO::Job * ) ) );
122 connect( mDoc, SIGNAL( completed() ),
123 SLOT( documentCompleted() ) );
124 connect( mDoc, SIGNAL( searchResultCacheAvailable() ),
125 SLOT( enableLastSearchAction() ) );
127 connect( mDoc, SIGNAL( selectionChanged() ),
128 SLOT( enableCopyTextAction() ) );
130 statusBar()->insertItem(i18n("Preparing Index"), 0, 1);
131 statusBar()->setItemAlignment(0, Qt::AlignLeft | Qt::AlignVCenter);
133 connect( mDoc->browserExtension(),
134 SIGNAL( openUrlRequest( const KUrl &,
135 const KParts::OpenUrlArguments &, const KParts::BrowserArguments & ) ),
136 SLOT( slotOpenURLRequest( const KUrl &,
137 const KParts::OpenUrlArguments &, const KParts::BrowserArguments & ) ) );
139 mNavigator = new Navigator( mDoc, mSplitter, "nav" );
140 connect( mNavigator, SIGNAL( itemSelected( const QString & ) ),
141 SLOT( viewUrl( const QString & ) ) );
142 connect( mNavigator, SIGNAL( glossSelected( const GlossaryEntry & ) ),
143 SLOT( slotGlossSelected( const GlossaryEntry & ) ) );
145 mSplitter->insertWidget(0, mNavigator);
146 mSplitter->setStretchFactor(mSplitter->indexOf(mNavigator), 0);
147 setCentralWidget( mSplitter );
148 QList<int> sizes;
149 sizes << 220 << 580;
150 mSplitter->setSizes(sizes);
151 setGeometry(366, 0, 800, 600);
153 KSharedConfig::Ptr cfg = KGlobal::config();
155 KConfigGroup configGroup( cfg, "General" );
156 if ( configGroup.readEntry( "UseKonqSettings", true) ) {
157 KConfig konqCfg( "konquerorrc" );
158 const_cast<KHTMLSettings *>( mDoc->settings() )->init( &konqCfg );
160 const int zoomFactor = configGroup.readEntry( "Font zoom factor", 100 );
161 mDoc->setZoomFactor( zoomFactor );
164 setupActions();
166 foreach (QAction *act, mDoc->actionCollection()->actions())
167 actionCollection()->addAction(act->objectName(), act);
169 setupGUI(ToolBar | Keys | StatusBar | Create);
170 setAutoSaveSettings();
172 History::self().installMenuBarHook( this );
174 connect( &History::self(), SIGNAL( goInternalUrl( const KUrl & ) ),
175 mNavigator, SLOT( openInternalUrl( const KUrl & ) ) );
176 connect( &History::self(), SIGNAL( goUrl( const KUrl & ) ),
177 mNavigator, SLOT( selectItem( const KUrl & ) ) );
179 statusBarMessage(i18n("Ready"));
180 enableCopyTextAction();
182 readConfig();
185 MainWindow::~MainWindow()
187 writeConfig();
190 void MainWindow::enableCopyTextAction()
192 mCopyText->setEnabled( mDoc->hasSelection() );
195 void MainWindow::saveProperties( KConfigGroup &config )
197 kDebug();
198 config.writePathEntry( "URL" , mDoc->baseURL().url() );
201 void MainWindow::readProperties( const KConfigGroup &config )
203 kDebug();
204 mDoc->slotReload( KUrl( config.readPathEntry( "URL", QString() ) ) );
207 void MainWindow::readConfig()
209 KConfigGroup config(KGlobal::config(), "MainWindowState");
210 QList<int> sizes = config.readEntry( "Splitter", QList<int>() );
211 if ( sizes.count() == 2 ) {
212 mSplitter->setSizes( sizes );
215 mNavigator->readConfig();
218 void MainWindow::writeConfig()
220 KConfigGroup config(KGlobal::config(), "MainWindowState");
221 config.writeEntry( "Splitter", mSplitter->sizes() );
223 mNavigator->writeConfig();
225 Prefs::self()->writeConfig();
228 void MainWindow::setupActions()
230 actionCollection()->addAction( KStandardAction::Quit, this, SLOT( close() ) );
231 actionCollection()->addAction( KStandardAction::Print, "printFrame", this, SLOT( print() ) );
233 KAction *prevPage = actionCollection()->addAction( "prevPage" );
234 prevPage->setText( i18n( "Previous Page" ) );
235 prevPage->setShortcut( Qt::CTRL+Qt::Key_PageUp );
236 prevPage->setWhatsThis( i18n( "Moves to the previous page of the document" ) );
237 connect( prevPage, SIGNAL( triggered() ), mDoc, SLOT( prevPage() ) );
239 KAction *nextPage = actionCollection()->addAction( "nextPage" );
240 nextPage->setText( i18n( "Next Page" ) );
241 nextPage->setShortcut( Qt::CTRL + Qt::Key_PageDown );
242 nextPage->setWhatsThis( i18n( "Moves to the next page of the document" ) );
243 connect( nextPage, SIGNAL( triggered() ), mDoc, SLOT( nextPage() ) );
245 QAction *home = KStandardAction::home( this, SLOT( slotShowHome() ), this );
246 actionCollection()->addAction( home->objectName(), home );
247 home->setText(i18n("Table of &Contents"));
248 home->setToolTip(i18n("Table of contents"));
249 home->setWhatsThis(i18n("Go back to the table of contents"));
251 mCopyText = KStandardAction::copy( this, SLOT(slotCopySelectedText()), this );
252 actionCollection()->addAction( "copy_text", mCopyText );
254 mLastSearchAction = actionCollection()->addAction( QLatin1String("lastsearch") );
255 mLastSearchAction->setText( i18n("&Last Search Result") );
256 mLastSearchAction->setEnabled( false );
257 connect( mLastSearchAction, SIGNAL( triggered() ), this, SLOT( slotLastSearch() ) );
259 QAction *action = actionCollection()->addAction( QLatin1String("build_index") );
260 action->setText( i18n("Build Search Index...") );
261 connect( action, SIGNAL( triggered() ), mNavigator, SLOT( showIndexDialog() ) );
263 actionCollection()->addAction( KStandardAction::KeyBindings, guiFactory(), SLOT( configureShortcuts() ) );
265 KConfigGroup debugGroup( KGlobal::config(), "Debug" );
266 if ( debugGroup.readEntry( "SearchErrorLog", false) ) {
267 action = actionCollection()->addAction(QLatin1String("show_search_stderr"));
268 action->setText( i18n("Show Search Error Log") );
269 connect( action, SIGNAL( triggered() ), this, SLOT( showSearchStderr() ) );
272 History::self().setupActions( actionCollection() );
274 action = actionCollection()->addAction(QLatin1String("configure_fonts" ));
275 action->setText( i18n( "Configure Fonts..." ) );
276 connect( action, SIGNAL( triggered() ), this, SLOT( slotConfigureFonts() ) );
278 action = actionCollection()->addAction(QLatin1String("incFontSizes"));
279 action->setText( i18n( "Increase Font Sizes" ) );
280 action->setIcon( KIcon( QLatin1String("zoom-in") ) );
281 connect( action, SIGNAL( triggered() ), this, SLOT( slotIncFontSizes() ) );
283 action = actionCollection()->addAction(QLatin1String("decFontSizes"));
284 action->setText( i18n( "Decrease Font Sizes" ) );
285 action->setIcon( KIcon( QLatin1String("zoom-out") ) );
286 connect( action, SIGNAL( triggered() ), this, SLOT( slotDecFontSizes() ) );
289 void MainWindow::slotCopySelectedText()
291 mDoc->copySelectedText();
294 void MainWindow::print()
296 mDoc->view()->print();
299 void MainWindow::slotStarted(KIO::Job *job)
301 if (job)
302 connect(job, SIGNAL(infoMessage( KJob *, const QString &, const QString &)),
303 SLOT(slotInfoMessage(KJob *, const QString &)));
305 History::self().updateActions();
308 void MainWindow::goInternalUrl( const KUrl &url )
310 mDoc->closeUrl();
311 slotOpenURLRequest( url );
314 void MainWindow::slotOpenURLRequest( const KUrl &url,
315 const KParts::OpenUrlArguments &args,
316 const KParts::BrowserArguments &browserArgs )
318 kDebug( 1400 ) << url.url();
320 mNavigator->selectItem( url );
321 viewUrl( url, args, browserArgs );
324 void MainWindow::viewUrl( const QString &url )
326 viewUrl( KUrl( url ) );
329 void MainWindow::viewUrl( const KUrl &url, const KParts::OpenUrlArguments &args, const KParts::BrowserArguments &browserArgs )
331 stop();
333 QString proto = url.protocol().toLower();
335 if ( proto == "khelpcenter" ) {
336 History::self().createEntry();
337 mNavigator->openInternalUrl( url );
338 return;
341 bool own = false;
343 if ( proto == QLatin1String("help")
344 || proto == QLatin1String("glossentry")
345 || proto == QLatin1String("about")
346 || proto == QLatin1String("man")
347 || proto == QLatin1String("info")
348 || proto == QLatin1String("cgi")
349 || proto == QLatin1String("ghelp"))
350 own = true;
351 else if ( url.isLocalFile() ) {
352 KMimeType::Ptr mime = KMimeType::findByPath( url.path() );
353 if ( mime->is("text/html") )
354 own = true;
357 if ( !own ) {
358 new KRun( url,this );
359 return;
362 History::self().createEntry();
364 mDoc->setArguments( args );
365 mDoc->browserExtension()->setBrowserArguments( browserArgs );
367 if ( proto == QLatin1String("glossentry") ) {
368 QString decodedEntryId = QUrl::fromPercentEncoding( url.encodedPathAndQuery().toAscii() );
369 slotGlossSelected( mNavigator->glossEntry( decodedEntryId ) );
370 mNavigator->slotSelectGlossEntry( decodedEntryId );
371 } else {
372 mDoc->openUrl( url );
376 void MainWindow::documentCompleted()
378 kDebug();
380 History::self().updateCurrentEntry( mDoc );
381 History::self().updateActions();
384 void MainWindow::slotInfoMessage(KJob *, const QString &m)
386 statusBarMessage(m);
389 void MainWindow::statusBarMessage(const QString &m)
391 statusBar()->changeItem(m, 0);
394 void MainWindow::openUrl( const QString &url )
396 openUrl( KUrl( url ) );
399 void MainWindow::openUrl( const QString &url, const QByteArray& startup_id )
401 KStartupInfo::setNewStartupId( this, startup_id );
402 openUrl( KUrl( url ) );
405 void MainWindow::openUrl( const KUrl &url )
407 if ( url.isEmpty() ) slotShowHome();
408 else {
409 mNavigator->selectItem( url );
410 viewUrl( url );
414 void MainWindow::slotGlossSelected(const GlossaryEntry &entry)
416 kDebug();
418 stop();
419 History::self().createEntry();
420 mDoc->begin( KUrl( "help:/khelpcenter/glossary" ) );
421 mDoc->write( Glossary::entryToHtml( entry ) );
422 mDoc->end();
425 void MainWindow::stop()
427 kDebug();
429 mDoc->closeUrl();
430 History::self().updateCurrentEntry( mDoc );
433 void MainWindow::showHome()
435 slotShowHome();
438 void MainWindow::slotShowHome()
440 viewUrl( mNavigator->homeURL() );
441 mNavigator->clearSelection();
444 void MainWindow::lastSearch()
446 slotLastSearch();
449 void MainWindow::slotLastSearch()
451 mDoc->lastSearch();
454 void MainWindow::enableLastSearchAction()
456 mLastSearchAction->setEnabled( true );
459 void MainWindow::showSearchStderr()
461 QString log = mNavigator->searchEngine()->errorLog();
463 if ( !mLogDialog ) {
464 mLogDialog = new LogDialog( this );
467 mLogDialog->setLog( log );
468 mLogDialog->show();
469 mLogDialog->raise();
472 void MainWindow::slotIncFontSizes()
474 mDoc->slotIncFontSizes();
475 updateZoomActions();
478 void MainWindow::slotDecFontSizes()
480 mDoc->slotDecFontSizes();
481 updateZoomActions();
484 void MainWindow::updateZoomActions()
486 actionCollection()->action( QLatin1String("incFontSizes") )->setEnabled( mDoc->zoomFactor() + mDoc->zoomStepping() <= 300 );
487 actionCollection()->action( QLatin1String("decFontSizes") )->setEnabled( mDoc->zoomFactor() - mDoc->zoomStepping() >= 20 );
489 KConfigGroup configGroup( KGlobal::config(), QLatin1String("General") );
490 configGroup.writeEntry( QLatin1String("Font zoom factor"), mDoc->zoomFactor() );
491 configGroup.sync();
494 void MainWindow::slotConfigureFonts()
496 FontDialog dlg( this );
497 if ( dlg.exec() == QDialog::Accepted )
499 if (mDoc->baseURL().isEmpty())
501 const_cast<KHTMLSettings *>( mDoc->settings() )->init( KGlobal::config().data() );
502 slotShowHome();
504 else mDoc->slotReload();
508 #include "mainwindow.moc"
510 // vim:ts=2:sw=2:et