1Design for a possible reimplementation of the KDE help center 2============================================================= 3 4Preludium 5--------- 6This document presents an alternative design for a 'help center' applicaiton 7in KDE. Lines which start with a # are supposed to be thoughts I had while 8writing this, much like the stuff you write on the side of a page when reading 9a book. 10 11Lines starting with ## were added by my as further comments - Cornelius 12 13And I'll have the ### lines - Lauri 14 15General 16------- 17- main() instantiates a KHC::Application 18- KHC::Application() deals with parsing the commandline parameters and 19 instantiates a KHC::MainWindow 20- KHC::MainWindow creates the main UI, setting up actions, using a QSplitter 21 as it's mainwidget to separate a KHC::Navigator at the left from a KHC::View 22 at the right 23 24That's the simple part. ;-) 25 26## Apparently already done ;-) 27 28KHC::Navigator 29-------------- 30 31KHC::Navigator inherits QTabWidget and provides, on two tabs, a 32KHC::ContentsTab object and a KHC::SearchTab object. 33 34## KHC::Navigator shouldn't inherit from QTabWidget. This limits flexibility. 35## It can create a QTabWidget instance as aggregate just as well. 36 37# I fear premature generalization ("We could need that bit of flexibility one 38# day), aggregation adds a level of indirection through a pointer variable as 39# well. I would prefer not making the system more complex as long as we cannot 40# predict changes which justify doing so. 41 421.) KHC::ContentsTab provides the following entires: 43 - Welcome to KDE 44 - KDE user's manual 45 - KDE FAQ 46 - Contact information 47 - Supporting KDE 48 49# Should we create an extra item for these five and put them in there? 50# Something like "General KDE" or so? OTOH that makes them less visible, and 51# these are really ought to be seen. - Frerich 52 53## The items are ok, in principle, but we should have a look at the content of 54## the documents they point at. This document could benefit from some attention. 55 56### Yes, they would. Also, there are license issues with one of them. 57### I'd personally like to do an entire rewrite of the User Manual, 58### without GPL encumbrance and sans the content that hasn't changed since 59### KDE 1.x days. The odds of me getting this done before KDE 3.1, slim to fair. 60 61 62 - Application manuals 63 - Tutorials 64 - UNIX man pages 65 - UNIX info pages 66 - Glossary 67 68# Do we really need this "Tutorials" item at all? right now it holds only two 69# items, perhaps we can get rid of it. - Frerich 70 71## Yes, please. 72 73### There should be a "General" area, where documentation that isn't 74### attached directly to an application can go. Tutorials might not be 75### the best name for it I agree, but there is now some further content to 76### add (the DCOP tutorial, for example, or any of the numerous tutorials 77### on the websites, documenting things that aren't in the handbooks.q 78 79# Alright, after some talk on IRC this structure evolved: 80# 81# - Tasks - contains short, three to four paragraph documents about how to 82# solve an everyday task, examples: 83# Browsing the web 84# Send and receive email 85# How to view images 86# Playing sound files 87# Installing new KDE themes 88# How to configure KDE fonts 89# Getting in touch with KDE contributors 90# Supporting the KDE team 91# 92# - Guides - slightly longer, Mini-HOWTO style guides (about three to four 93# pages long, perhaps) which talk about tackling jobs which don't 94# occur very often, examples: 95### I don't know about limiting the length. Some of these topics can stand 96### a much longer document, but one of the things that differentiates them 97### from the references is that they are not specific to a single application, 98### nor are they complete references in the manner of the "KDE User Guide" 99### Specificaly, the dcop tutorial we have is about 15 pages already, but if 100### the user is interested in the topic, that isn't over much, and it's full of 101### examples 102# How to debug KDE programs 103# Sending useful KDE bug reports 104# Extending KDE's service menus 105# Taking advantage of KDE's DCOP facilities 106# Creating panel applets 107# Phrasing questions most effectively 108# 109# - References - references. :-) 110# KDE API reference 111# KDE application manuals 112# Info pages 113# Man pages 114# FAQ 115# User's manual 116# 117# - Glossary - same as always. 118# - By topic 119# - Alphabetically 120# 121# My primary argument for such a structure is that it resembles a 122# task-oriented interface much more closely than the simple list of 123# application manuals. Imagine a user new to KDE who has a fairly precise 124# description of what he's trying to do in mind (think "I want to view an 125# image file") but no idea what tool to use for the job. The current list of 126# application manuals requires the user to browse all the manuals which seem 127# relevant, searching for the information he seeks. A task-oriented list 128# solves that issue. 129# This effectively enables people new to KDE in less time to become productive 130# (a task-oriented list isn't so useful for peoplew ho are familiar with KDE's 131# applications, of course). 132# Implementation-wise, we should perhaps stop using a K3ListView and use a 133# KOffice-style component selection widget like koshell has at the left? 134 135The first five items are generated by KHC::Navigator itself and are direct 136links to KDE documentations. The work of generating each of the last four 137items is (with one exception) delegated to four helper classes, which inherit a 138'KHC::TreeBuilder' class which has the following interface: 139 140class KHC::TreeBuilder 141 virtual void build( K3ListViewItem *parent ) = 0; 142 143## What about the trees generated as children of the contents list view? 144 145# Oops, that's a typo, what you mean is what I originally intented: a 146# TreeBuilder should take a 'K3ListView' as it's parent, subclasses can then 147# overload that method (such as the KHC::TOCBuilder which will want to provide 148# a build( K3ListViewItem *parent ) method). 149 150# This concept of using a TreeBuilder baseclass might make it possible to turn 151# all the classes which use that interface into plugins. That way we could 152# e.g. have a ScrollKeeper plugin. - Frerich 153 154## What exactly do you mean by plugin? A shared library loaded at run time or 155## the desktop file based insertion of documents into the help center? 156 157# The former. 158 159The classes which inherit this interface are: 160 - KHC::ManualTreeBuilder: responsible for generating the tree below the 161 "Application manuals" item 162 - KHC::TOCBuilder: responsible for generating a TOC tree below each of the 163 manual trees items, so that you can choose Application 164 Manuals->Editors->KWrite->Using KWrite->Menu bar transparently. This is 165 the only builder which is not instantiated by KHC::ContentsTab but 166 instead instantiated by KHC::ManualTreeBuilder 167 - KHC::TutorialTreeBuilder: responsible for generating the tree below the 168 "Tutorials" item 169 - KHC::ManTreeBuilder: responsible for building the tree below the "UNIX 170 man pages" item 171 - KHC::InfoTreeBuilder: responsible for building the tree below the "UNIX 172 info pages" item 173 - KHC::GlossaryTreeBuilder: guess what 174 175## - KHC::ScrollkeeperTreeBuilder 176 177## It's certainly a good idea to move stuff like the info and man pages and 178## scrollkeeper support to its own classes. What I consider as important is 179## that the concept of representing the documentation by desktop meta files is 180## used as far as possible. This makes the system very flexible and extandable. 181 1822.) KHC::SearchTab provides a widget which lets the search through all 183available help repositories, also defining some flags such as 'Search by 184regexp' or 'Search case sensitive'. 185 186# I think this means that we have to create a 'DataCollection' class which 187# gets inherited by all classes which are "searchable". DataCollections should 188# also be able to contains multiple child DataCollection, so that we have e.g. 189# one DataCollection per application manual, and one "Manuals" collection 190# which contains all the application manual collections. 191# We'd probably also need a DataCollection for the info pages and man pages. 192# And later, in the far future, we might extent this concept to web searches, 193# so that e.g. Google represents a DataCollection which we can query. 194# I'm not yet decided how to do that properly, perhaps using multiple 195# inheritance, so that each TOCBuilder is a DataCollection - naw, we'd rather 196# have a "TableOfContents" class which contains a TOCBuilder, and is a 197# datacollection? Hm, not sure. 198# In any case DataCollections should some sort of plugins, so that we can add 199# e.g. new web search interfaces lateron. 200# - Frerich 201 202## What you call a DataCollection is currently represented by the DocEntry 203## objects. Each DocEntry object represents a document or a collection of 204## documents. It has information about the name and description of the 205## document, the location and how it can be searched. 206## 207## Currently this information is based on URLs or file names and is optimized 208## to be used by scripts, e.g. CGI scripts. A little exception from this is 209## the htdig support where just a keyword "SearchMethod=htdig" is put in the 210## desktop file and the help center figures out how to perform that search by 211## using a special class. This could be extended to cover other search methods 212## like web searches or special search methods optimized for certain kind of 213## documents. 214 215# I just thought about it - isn't that a bit overkill for the web search 216# stuff? I just thought about it - all we need to do is to copy the .desktop 217# files (at least some of them, like the ones for google, yahoo and excite) 218# from the enhanced browsing thing and treat those as plugin .desktop files. 219# We could show them in a listview on the Search tab, each found search engine 220# being represented by a checkable listview item. So, we just let the user 221# enter a term, replace the \{@} placeholder in the URIs specified in the 222# selected .desktop files with that term, send out a request via KIO and show 223# the results in our KHTMLPart (after all KHC::View is a KHTMLPart already). A 224# problem with this: How to display the multiple HTML pages returned by the 225# selected search engines? Using a QSplitter to split multiple KHTMLParts? 226# Hmm... just wondered... perhaps we can work around that by not showing the 227# returned HTML data at all but rather use a XSLT script (that is, one XSLT 228# script per web search) which transforms the returned search results into a 229# common format - that way, we could also filter out duplicates and then 230# transform that filtered output into a nice, uniform HTML page. How about 231# that? 232 233# I like this idea very much, I just thought it and noticed you wrote this 234# down already. What I thought of was having a .desktop/.xslt file pair per 235# search engine: each .desktop file holds at least the name of the engine (for 236# the listview) and a search URI with a placeholder, just like in your scenario. 237# In additionl there could be a X-KHelpCenter-XSLT key which defines which .xslt 238# stylesheet to use for that particular search engine. We then query that search 239# engine by replacing the placeholder in the URI with whatever the user entered 240# and hand it to KIO. All the HTML returned by the various search engines gets 241# then transformed into a custom, intermediate, XML dialect, using the XSLT 242# stylesheets define in the .desktop files. Using that intermediate step we 243# can nicely drop duplicate hits, for example, or create a list of hits in the 244# sidebar (much like https://www.copernic.com/ does). After that, we can use 245# another XSLT stylesheet to transform that cleaned XML tree into HTML which 246# we then feed to our KHTMLView. Since we then have one unified output, we don't 247# need to worry about having multiple KHTMLParts, and it's also nice because 248# the user doesn't see which search engine returned which hit. 249 250# A problem with this would be that we cannot tell how a particular search 251# engine treats boolean expressions (e.g. some search engines use 'foo AND bar', 252# others use '+foo +bar', a third variation is '"foo bar"'). We thus cannot 253# replace the placeholder in the URI but first have to translate the syntax 254# entered by the user into a syntax which is appropriate for each single news 255# engine. Right now I don't know how we could do this with just a .desktop/.xslt 256# pair. We could always use fullblown C++ plugins which hold code which is able 257# to do that translation, but I would really prefer to stick with .desktop files 258# now since they're much easier to create. 259 260# Another thing which would speak in favor of C++ plugins: different search 261# engines support different features (like, google can search more than just the 262# web, and you can sometimes tell a search engine to list only results in a 263# certain language, or with a certain encoding), so it would be nice if we could 264# let the user access those features: through a dialog which has to be tailored 265# to the possibilities of the respective search engine. I wonder whether we 266# could have some sort of XML tree which defines how an UI should look like, and 267# then let KHelpCenter create a dialog using that XML markup, but that idea is 268# very vague right now. 269 270# Hmm, I just tried it and the XSLT idea didn't really take off: the problem 271# is that many HTML pages returned by Google, Yahoo & co. don't seem to be 272# valid XML, which is why tools such as meinproc or xsltproc refuse to process 273# themm. :-/ 274 275KHC::View 276--------- 277KHC::View inherits KHTMLPart and does the actual job of showing some sort of 278document. Most importantly, it has a slot which passes it a KUrl pointing to a 279document to show. KHC::View will invoke kio_help if necessary (if the URL's 280protocol == "help") by itself and otherwise use the plain URL. 281 282# TODO: Things I didn't really think about yet: the interface between the 283# navigator and the view. I think this has to be a bidirectional association 284# since the navigator can change the view (e.g. by clicking on a manual which 285# shows it in the view), but the view can also change the navigator (think of 286# clicking on a 'See also' link in the glossary which should also scroll to 287# the corresponding entry in the navigator). 288 289## That's a very important aspect. We should have one central place where all 290## document requests are processed and the necessary actions (like updating 291## the navigator, loading a new page, caching the search results, etc.) are 292## done. 293## 294## The TreeBuilder might need some interface to tell, if a certain URL exist 295## in their tree, to make it possible to select content entries which aren't 296## created yet, because they are only created on demand (like the application 297## manuals). 298 299# Very good idea. Perhaps I think iterating over a list of TreeBuilder 300# instances and doing something like 'if ((*it)->canHandle(url)) 301# (*it)->selectItem(url)' which checks whether a TreeBuilder provides an item 302# which corresponds to an URL (hmm, this makes me think, TreeBuilder is a bad 303# name. Perhaps just 'Tree'?) and selects it (using 304# QListView::ensureItemVisible() or so) if requested. This probably implies. 305# that a TreeBuilder needs an internal QMap<KUrl, QListViewItem *>. 306 307# Also, the whole search engine needs more thought, that DataCollection idea 308# seems promising to me but I'm not yet decided on how to do it properly. 309 310## See above. We already have something which isn't too bad, I think. 311 312# I just thought about this a bit, I think KHC::MainWindow should act as the 313# interface between KHC::Navigator and KHC::View. 314 315## I would prefer to have an extra class which does no GUI stuff, but passes 316## URL requests around, does the needed processing and stores data, if needed 317## (e.g. caching search results). 318 319# Agreed. 320 321## One very important aspect of the help center is that it has to be fast. It's 322## not acceptable to wait several seconds after clicking on the Help menu of an 323## application. We should think about that. Perhaps we can do some tricks like 324## showing the main window before creating the other widgets and processing data 325## or something similar. We could also think about creating more stuff only on 326## demand. 327 328# My perception is that filling the Navigator's listview takes a significant 329# amount of time, just like setting up the KHTML view (loading the stylesheet, 330# showing the welcome page). We could easily do taht in the background - show 331# the mainwindow, then tell the TreeBuilders to start populating (using a 332# QTimer with a timeout of 0, for a snappy GUI). Since they're collapsed at 333# the start, the users won't even notice (and we can "fake" that they're 334# already populated by calling setExpandable(true) for all of them (or letting 335# them do that themselves) at the start. 336 337## Finally a crazy idea: Wouldn't it be cool, if we would make the manuals more 338## interactive. So when you read about a certain menu or a certain dialog of an 339## application you can click on a link in the manual and the menu or dialog gets 340## opened in the real application, or some widgets get highlghted in the real 341## application. Such a feature could also be used to create interactive 342## tutorials, where you have a small helpcenter window and the application next 343## to each other on the screen and you can go through the tutorial step by step 344## and practice with the real application while reading the instructions. 345## With the help of DCOP it shouldn't be too hard to implement such an 346## interactive help system. Maybe it's even possible to do it in a general way 347## in the libs, so that application authors don't have to think about that 348## feature. 349 350# Hmm, that's an interesting idea. That takes KHelpCenter way beyond what it's 351# currently doing. I can imagine this: we introduce a virtual "dcop" protocol, 352# so that e.g. <ulink url="dcop:/kfortune/KFortuneIface/nextFortune"/> 353# represents the DCOP call 'dcop kfortune KFortuneIface nextfortune'. 354# KHelpCenter catches that protocol (oh dear, a lot of special cases with 355# gloss, info etc. already - guess another one won't hurt). That looks like a 356# good way for encapsulating DCOP calls. 357# Now, the problem is - the application has to provide a dedicated 358# "documentation" DCOP interface for this, with lots of calls for highlighting 359# the various widgets (hm, this probably means taht we can skip the first two 360# parts in our 'dcop' URL syntax, the application is known anyway, and the 361# interface is hardcoded in KHelpCenter). 362# So, what could happen is this: We have a piece of HTML in the documentation 363# for our SuperApp application which goes like 'The 364# <a href="dcop:highlightConnectButton">button labelled Connect</a> makes 365# SuperApp establish a connection.' - the user clicks on that link, 366# KHelpCenter catches a dcop: URL, checks whether SuperApp has already been 367# started. If not, it starts a SuperApp process and does the dcop call 'dcop 368# SuperApp DocIface highlightConnectButton' and SuperApp starts highlighting 369# that connect button. The thing is that this requires a lot of work on the 370# application side. The idea is very cool, but we'd have to think about 371# outsourceing parts of that functionality, either to KHelpCenter, or to 372# kdelibs. 373 374## And another idea: The WhatsThis help texts describe all widgets of an 375## application (provided that the texts are set by the developers). Currently 376## they aren't accessible very easily. You have to go to a special mode and 377## can then click on one widget after another to get the help, if there is one. 378## There is no visual indication which widgets have help and which not. But the 379## application knows about the WhatsThis helps. Perhaps it's possible to use 380## the Qt object inspection stuff to extract all the texts and put them on an 381## automatically generated screenshot of the corresponding dialog and put this 382## graphic into the docs. Maybe it's even possible to do this at run-time and 383## decorate dialogs with all WhatsThis helps at once, if the user triggers this 384## mode. 385 386# Hmm yes, that should be possible. Take the toplevel widget, use 387# QObject::children() and iterate over all children, use QToolTip::textFor() to 388# check whether the given qwidget has a tooltip and if so, use QToolTip::tip() 389# to show the tooltip. 390# One could probably add a standard dcop call to KMainWindow, like 391# "showAllToolTips". KSnapShot could get a QCheckBox "Show all tooltips", and 392# if that box is checked it tells the selected window to show all it's 393# tooltips via that DCOP call right before it does the snapshot. The thing is 394# - is it possible to map the WinID of the window the user clicked on to 395# the process name we should send your DCOP call to? 396 397## One thing we should also keep in mind is that it might be useful to provide 398## the help center as a component. FOr example KDevelop has a very similar 399## thing. It would be much nicer, if it could reuse the KHelpcenter code. This 400## would probbaly also mean to at a DoxygenTreeBuilder or something similar. 401 402# That probably implies that instead of a QSplitter which holds the Navigator 403# and the View, we'd have a KHC::MainWidget KPart which in turn aggregates the 404# splitter. The DoxygenTreeBuilder sounds like a reason to make TreeBuilders 405# real plugins, with dynamically loaded libraries, so that KDevelop or other 406# "IDE"-like applications (perhaps a KOffice help system?) can have their 407# customized tree builders. 408 409Font Configuration 410------------------ 411 412### Many bug reports on KHelpCenter not honouring KHTML font settings, 413### which is odd, because the stylesheet is intentionally loose, 414### specifying only "sans-serif" as the font face. 415 416### Ideas to fix: 417 418### Help pages already make heavy use of the cascading feature of CSS, we 419### ought to be able to leverage that by writing to perhaps the 420### kde-localized.css file or a copy of it in $KDEHOME. There is already 421### code in KControl to create a user CSS stylesheet, and we probably only 422### need to configure the size and the face for KHC. 423 424### Or, fix whatever is the reason KHC doesn't follow the rules. It could 425### be encoding related, the help pages specify utf-8 as the encoding, and 426### previous incarnations of the KHTML settings allowed fonts set on a 427### per-encoding basis (at which time, this was apparently working, the bug 428### reports dropped off, and only returned post KDE 3.0 429 430# FWIW I added a simple font configuration facility a while back, which should 431# IMHO be sufficient for the vast majority of users. 432 433// vim:tw=78 434