when a new activity is added, don't move more than necessary to show it
[kdebase.git] / runtime / khelpcenter / view.cpp
blob9289d967c924b7115d31a71e1690a71dc9d04db6
1 #include "view.h"
3 #include "formatter.h"
4 #include "history.h"
6 #include <dom/html_document.h>
7 #include <dom/html_misc.h>
8 #include <kaction.h>
9 #include <kactioncollection.h>
10 #include <kapplication.h>
11 #include <kdebug.h>
12 #include <khtml_settings.h>
13 #include <khtmlview.h>
14 #include <klocale.h>
15 #include <kmenu.h>
16 #include <kstandarddirs.h>
17 #include <ktoolbarpopupaction.h>
19 #include <QFileInfo>
20 #include <QClipboard>
21 //Added by qt3to4:
22 #include <QTextStream>
23 #include <QKeyEvent>
24 #include <QEvent>
25 #include <kglobal.h>
27 using namespace KHC;
29 View::View( QWidget *parentWidget, QObject *parent, KHTMLPart::GUIProfile prof, KActionCollection *col )
30 : KHTMLPart( parentWidget, parent, prof ), mState( Docu ), mActionCollection(col)
32 setJScriptEnabled(false);
33 setJavaEnabled(false);
34 setPluginsEnabled(false);
36 mFormatter = new Formatter;
37 if ( !mFormatter->readTemplates() ) {
38 kDebug() << "Unable to read Formatter templates.";
41 m_zoomStepping = 10;
43 connect( this, SIGNAL( setWindowCaption( const QString & ) ),
44 this, SLOT( setTitle( const QString & ) ) );
45 connect( this, SIGNAL( popupMenu( const QString &, const QPoint& ) ),
46 this, SLOT( showMenu( const QString &, const QPoint& ) ) );
48 QString css = langLookup("common/kde-default.css");
49 if (!css.isEmpty())
51 QFile css_file(css);
52 if (css_file.open(QIODevice::ReadOnly))
54 QTextStream s(&css_file);
55 QString stylesheet = s.readAll();
56 preloadStyleSheet("help:/common/kde-default.css", stylesheet);
60 view()->installEventFilter( this );
63 View::~View()
65 delete mFormatter;
68 void View::copySelectedText()
70 kapp->clipboard()->setText( selectedText() );
73 bool View::openUrl( const KUrl &url )
75 if ( url.protocol().toLower() == "about" )
77 showAboutPage();
78 return true;
80 mState = Docu;
81 return KHTMLPart::openUrl( url );
84 void View::saveState( QDataStream &stream )
86 stream << mState;
87 if ( mState == Docu )
88 KHTMLPart::saveState( stream );
91 void View::restoreState( QDataStream &stream )
93 stream >> mState;
94 if ( mState == Docu )
95 KHTMLPart::restoreState( stream );
96 else if ( mState == About )
97 showAboutPage();
100 void View::showAboutPage()
102 QString file = KStandardDirs::locate( "data", "khelpcenter/intro.html.in" );
103 if ( file.isEmpty() )
104 return;
106 QFile f( file );
108 if ( !f.open( QIODevice::ReadOnly ) )
109 return;
111 mState = About;
113 emit started( 0 );
115 QTextStream t( &f );
117 QString res = t.readAll();
119 res = res.arg( i18n("Conquer your Desktop!") )
120 .arg( langLookup( "khelpcenter/konq.css" ) )
121 .arg( langLookup( "khelpcenter/pointers.png" ) )
122 .arg( langLookup( "khelpcenter/khelpcenter.png" ) )
123 .arg( i18n("Help Center") )
124 .arg( langLookup( "khelpcenter/lines.png" ) )
125 .arg( i18n( "Welcome to the K Desktop Environment" ) )
126 .arg( i18n( "The KDE team welcomes you to user-friendly UNIX computing" ) )
127 .arg( i18n( "KDE is a powerful graphical desktop environment for UNIX workstations. A\n"
128 "KDE desktop combines ease of use, contemporary functionality and outstanding\n"
129 "graphical design with the technological superiority of the UNIX operating\n"
130 "system." ) )
131 .arg( i18n( "What is the K Desktop Environment?" ) )
132 .arg( i18n( "Contacting the KDE Project" ) )
133 .arg( i18n( "Supporting the KDE Project" ) )
134 .arg( i18n( "Useful links" ) )
135 .arg( i18n( "Getting the most out of KDE" ) )
136 .arg( i18n( "General Documentation" ) )
137 .arg( i18n( "A Quick Start Guide to the Desktop" ) )
138 .arg( i18n( "KDE Users' guide" ) )
139 .arg( i18n( "Frequently asked questions" ) )
140 .arg( i18n( "Basic Applications" ) )
141 .arg( i18n( "The Kicker Desktop Panel" ) )
142 .arg( i18n( "The KDE Control Center" ) )
143 .arg( i18n( "The Konqueror File manager and Web Browser" ) )
144 .arg( langLookup( "khelpcenter/kdelogo2.png" ) );
145 begin( KUrl( "about:khelpcenter" ) );
146 write( res );
147 end();
148 emit completed();
151 QString View::langLookup( const QString &fname )
153 QStringList search;
155 // assemble the local search paths
156 const QStringList localDoc = KGlobal::dirs()->resourceDirs("html");
158 // look up the different languages
159 for (int id=localDoc.count()-1; id >= 0; --id)
161 QStringList langs = KGlobal::locale()->languageList();
162 langs.append( "en" );
163 langs.removeAll( "C" );
164 QStringList::ConstIterator lang;
165 for (lang = langs.begin(); lang != langs.end(); ++lang)
166 search.append(QString("%1%2/%3").arg(localDoc[id]).arg(*lang).arg(fname));
169 // try to locate the file
170 QStringList::Iterator it;
171 for (it = search.begin(); it != search.end(); ++it)
173 QFileInfo info(*it);
174 if (info.exists() && info.isFile() && info.isReadable())
175 return *it;
177 QString file = (*it).left((*it).lastIndexOf('/')) + "/index.docbook";
178 info.setFile(file);
179 if (info.exists() && info.isFile() && info.isReadable())
180 return *it;
183 return QString();
186 void View::setTitle( const QString &title )
188 mTitle = title;
191 void View::beginSearchResult()
193 mState = Search;
195 begin();
196 mSearchResult = "";
199 void View::writeSearchResult( const QString &str )
201 write( str );
202 mSearchResult += str;
205 void View::endSearchResult()
207 end();
208 if ( !mSearchResult.isEmpty() ) emit searchResultCacheAvailable();
211 void View::beginInternal( const KUrl &url )
213 mInternalUrl = url;
214 begin();
217 KUrl View::internalUrl() const
219 return mInternalUrl;
222 void View::lastSearch()
224 if ( mSearchResult.isEmpty() ) return;
226 mState = Search;
228 begin();
229 write( mSearchResult );
230 end();
233 void View::slotIncFontSizes()
235 setZoomFactor( zoomFactor() + m_zoomStepping );
238 void View::slotDecFontSizes()
240 setZoomFactor( zoomFactor() - m_zoomStepping );
243 void View::showMenu( const QString& url, const QPoint& pos)
245 KMenu pop(view());
247 if (url.isEmpty())
249 QAction *action;
250 action = mActionCollection->action("go_home");
251 if (action) pop.addAction( action );
253 pop.addSeparator();
255 action = mActionCollection->action("prevPage");
256 if (action) pop.addAction( action );
257 action = mActionCollection->action("nextPage");
258 if (action) pop.addAction( action);
260 pop.addSeparator();
262 pop.addAction( History::self().m_backAction );
263 pop.addAction( History::self().m_forwardAction );
265 else
267 QAction *action = pop.addAction(i18n("Copy Link Address"));
268 connect( action, SIGNAL( triggered() ), this, SLOT( slotCopyLink() ) );
270 mCopyURL = completeURL(url).url();
273 pop.exec(pos);
276 void View::slotCopyLink()
278 QApplication::clipboard()->setText(mCopyURL);
281 bool View::prevPage(bool checkOnly)
283 const DOM::HTMLCollection links = htmlDocument().links();
285 // The first link on a page (top-left corner) would be the Prev link.
286 const DOM::Node prevLinkNode = links.item( 0 );
287 KUrl prevURL = urlFromLinkNode( prevLinkNode );
288 if (!prevURL.isValid())
289 return false;
291 if (!checkOnly)
292 openUrl( prevURL );
293 return true;
296 bool View::nextPage(bool checkOnly)
298 const DOM::HTMLCollection links = htmlDocument().links();
300 KUrl nextURL;
302 // If we're on the first page, the "Next" link is the last link
303 if ( baseURL().path().endsWith( "/index.html" ) )
304 nextURL = urlFromLinkNode( links.item( links.length() - 1 ) );
305 else
306 nextURL = urlFromLinkNode( links.item( links.length() - 2 ) );
308 if (!nextURL.isValid())
309 return false;
311 // If we get a mail link instead of a http URL, or the next link points
312 // to an index.html page (a index.html page is always the first page
313 // there can't be a Next link pointing to it!) there's probably nowhere
314 // to go. Next link at all.
315 if ( nextURL.protocol() == "mailto" ||
316 nextURL.path().endsWith( "/index.html" ) )
317 return false;
319 if (!checkOnly)
320 openUrl( nextURL );
321 return true;
324 bool View::eventFilter( QObject *o, QEvent *e )
326 if ( e->type() != QEvent::KeyPress ||
327 htmlDocument().links().length() == 0 )
328 return KHTMLPart::eventFilter( o, e );
330 QKeyEvent *ke = static_cast<QKeyEvent *>( e );
331 if ( ke->modifiers() & Qt::ShiftModifier && ke->key() == Qt::Key_Space ) {
332 // If we're on the first page, it does not make sense to go back.
333 if ( baseURL().path().endsWith( "/index.html" ) )
334 return KHTMLPart::eventFilter( o, e );
336 const QScrollBar * const scrollBar = view()->verticalScrollBar();
337 if ( scrollBar->value() == scrollBar->minimum() ) {
338 if (prevPage())
339 return true;
341 } else if ( ke->key() == Qt::Key_Space ) {
342 const QScrollBar * const scrollBar = view()->verticalScrollBar();
343 if ( scrollBar->value() == scrollBar->maximum() ) {
344 if (nextPage())
345 return true;
348 return KHTMLPart::eventFilter( o, e );
351 KUrl View::urlFromLinkNode( const DOM::Node &n ) const
353 if ( n.isNull() || n.nodeType() != DOM::Node::ELEMENT_NODE )
354 return KUrl();
356 DOM::Element elem = static_cast<DOM::Element>( n );
358 KUrl href ( elem.getAttribute( "href" ).string() );
359 if ( !href.protocol().isNull() )
360 return href;
362 QString path = baseURL().path();
363 path.truncate( path.lastIndexOf( '/' ) + 1 );
364 path += href.url();
366 KUrl url = baseURL();
367 url.setRef( QString() );
368 url.setEncodedPathAndQuery( path );
370 return url;
373 void View::slotReload( const KUrl &url )
375 const_cast<KHTMLSettings *>( settings() )->init( KGlobal::config().data() );
376 KParts::OpenUrlArguments args = arguments();
377 args.setReload( true );
378 setArguments( args );
379 if ( url.isEmpty() )
380 openUrl( baseURL() );
381 else
382 openUrl( url );
385 #include "view.moc"
386 // vim:ts=2:sw=2:et