Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / runtime / khelpcenter / glossary.cpp
blob8518b676e37dfe2149b2b99eec1cf8cf7722deb2
1 /*
2 * This file is part of the KDE Help Center
4 * Copyright (C) 2002 Frerich Raabe (raabe@kde.org)
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 #include "glossary.h"
21 #include "view.h"
23 #include <kapplication.h>
24 #include <kconfig.h>
25 #include <kdebug.h>
26 #include <kiconloader.h>
27 #include <klocale.h>
28 #include <kxmlguiwindow.h>
29 #include <kprocess.h>
30 #include <kstandarddirs.h>
31 #include <kstatusbar.h>
33 #include <Qt3Support/Q3Header>
34 //Added by qt3to4:
35 #include <QFrame>
36 #include <QTextStream>
38 #include <sys/stat.h>
39 #include <kglobal.h>
41 using namespace KHC;
43 class SectionItem : public K3ListViewItem
45 public:
46 SectionItem( Q3ListViewItem *parent, const QString &text )
47 : K3ListViewItem( parent, text )
49 setOpen( false );
52 virtual void setOpen( bool open )
54 K3ListViewItem::setOpen(open);
56 setPixmap( 0, SmallIcon( QLatin1String( open ? "help-contents" : "contents2" ) ) );
61 class EntryItem : public K3ListViewItem
63 public:
64 EntryItem( SectionItem *parent, const QString &term, const QString &id )
65 : K3ListViewItem( parent, term ),
66 m_id( id )
70 QString id() const { return m_id; }
72 private:
73 QString m_id;
76 bool Glossary::m_alreadyWarned = false;
78 Glossary::Glossary( QWidget *parent ) : K3ListView( parent )
80 m_initialized = false;
82 setFrameStyle( QFrame::NoFrame );
84 connect( this, SIGNAL( clicked( Q3ListViewItem * ) ),
85 this, SLOT( treeItemSelected( Q3ListViewItem * ) ) );
86 connect( this, SIGNAL( returnPressed( Q3ListViewItem * ) ),
87 this, SLOT( treeItemSelected( Q3ListViewItem * ) ) );
89 addColumn( QString() );
90 header()->hide();
91 setAllColumnsShowFocus( true );
92 setRootIsDecorated( true );
94 m_byTopicItem = new K3ListViewItem( this, i18n( "By Topic" ) );
95 m_byTopicItem->setPixmap( 0, SmallIcon( "help-contents" ) );
97 m_alphabItem = new K3ListViewItem( this, i18n( "Alphabetically" ) );
98 m_alphabItem->setPixmap( 0, SmallIcon( "character-set" ) );
100 m_cacheFile = KStandardDirs::locateLocal( "cache", "help/glossary.xml" );
102 m_sourceFile = View::langLookup( QLatin1String( "khelpcenter/glossary/index.docbook" ) );
104 m_config = KGlobal::config();
105 //m_config->setGroup( "Glossary" );
109 void Glossary::showEvent(QShowEvent *event)
111 if ( !m_initialized ) {
112 if ( cacheStatus() == NeedRebuild )
113 rebuildGlossaryCache();
114 else
115 buildGlossaryTree();
116 m_initialized = true;
118 K3ListView::showEvent(event);
121 Glossary::~Glossary()
123 qDeleteAll( m_glossEntries );
126 const GlossaryEntry &Glossary::entry( const QString &id ) const
128 return *m_glossEntries[ id ];
131 Glossary::CacheStatus Glossary::cacheStatus() const
133 if ( !QFile::exists( m_cacheFile ) ||
134 m_config->group("Glossary").readPathEntry( "CachedGlossary", QString() ) != m_sourceFile ||
135 m_config->group("Glossary").readEntry( "CachedGlossaryTimestamp" ).toInt() != glossaryCTime() )
136 return NeedRebuild;
138 return CacheOk;
141 int Glossary::glossaryCTime() const
143 struct stat stat_buf;
144 stat( QFile::encodeName( m_sourceFile ).data(), &stat_buf );
146 return stat_buf.st_ctime;
149 void Glossary::rebuildGlossaryCache()
151 KXmlGuiWindow *mainWindow = dynamic_cast<KXmlGuiWindow *>( kapp->activeWindow() );
152 if (mainWindow)
153 mainWindow->statusBar()->showMessage( i18n( "Rebuilding glossary cache..." ) );
155 KProcess *meinproc = new KProcess;
156 connect( meinproc, SIGNAL( finished(int,QProcess::ExitStatus) ),
157 this, SLOT( meinprocFinished(int,QProcess::ExitStatus) ) );
159 *meinproc << KStandardDirs::locate( "exe", QLatin1String( "meinproc4" ) );
160 *meinproc << QLatin1String( "--output" ) << m_cacheFile;
161 *meinproc << QLatin1String( "--stylesheet" )
162 << KStandardDirs::locate( "data", QLatin1String( "khelpcenter/glossary.xslt" ) );
163 *meinproc << m_sourceFile;
165 meinproc->setOutputChannelMode(KProcess::OnlyStderrChannel);
166 meinproc->start();
167 if (!meinproc->waitForStarted()) {
168 kError() << "could not start process" << meinproc->program();
169 if (mainWindow && !m_alreadyWarned) {
170 ; // add warning message box with don't display again option
171 // http://api.kde.org/4.0-api/kdelibs-apidocs/kdeui/html/classKDialog.html
172 m_alreadyWarned = true;
174 delete meinproc;
178 void Glossary::meinprocFinished( int exitCode, QProcess::ExitStatus exitStatus )
180 KProcess *meinproc = static_cast<KProcess *>(sender());
181 KXmlGuiWindow *mainWindow = dynamic_cast<KXmlGuiWindow *>( kapp->activeWindow() );
183 if (exitStatus != QProcess::NormalExit || exitCode != 0) {
184 kError() << "running" << meinproc->program() << "failed with exitCode" << exitCode;
185 kError() << "stderr output:" << meinproc->readAllStandardError();
186 if (mainWindow && !m_alreadyWarned) {
187 ; // add warning message box with don't display again option
188 // http://api.kde.org/4.0-api/kdelibs-apidocs/kdeui/html/classKDialog.html
189 m_alreadyWarned = true;
191 delete meinproc;
192 return;
194 delete meinproc;
196 if ( !QFile::exists( m_cacheFile ) )
197 return;
199 m_config->group("Glossary").writePathEntry( "CachedGlossary", m_sourceFile );
200 m_config->group("Glossary").writeEntry( "CachedGlossaryTimestamp", glossaryCTime() );
201 m_config->sync();
203 m_status = CacheOk;
205 if (mainWindow)
206 mainWindow->statusBar()->showMessage( i18n( "Rebuilding cache... done." ), 2000 );
208 buildGlossaryTree();
211 void Glossary::buildGlossaryTree()
213 QFile cacheFile(m_cacheFile);
214 if ( !cacheFile.open( QIODevice::ReadOnly ) )
215 return;
217 QDomDocument doc;
218 if ( !doc.setContent( &cacheFile ) )
219 return;
221 QDomNodeList sectionNodes = doc.documentElement().elementsByTagName( QLatin1String( "section" ) );
222 for ( int i = 0; i < sectionNodes.count(); i++ ) {
223 QDomElement sectionElement = sectionNodes.item( i ).toElement();
224 QString title = sectionElement.attribute( QLatin1String( "title" ) );
225 SectionItem *topicSection = new SectionItem( m_byTopicItem, title );
227 QDomNodeList entryNodes = sectionElement.elementsByTagName( QLatin1String( "entry" ) );
228 for ( int j = 0; j < entryNodes.count(); j++ ) {
229 QDomElement entryElement = entryNodes.item( j ).toElement();
231 QString entryId = entryElement.attribute( QLatin1String( "id" ) );
232 if ( entryId.isNull() )
233 continue;
235 QDomElement termElement = childElement( entryElement, QLatin1String( "term" ) );
236 QString term = termElement.text().simplified();
238 EntryItem *entry = new EntryItem(topicSection, term, entryId );
239 m_idDict.insert( entryId, entry );
241 SectionItem *alphabSection = 0L;
242 for ( Q3ListViewItemIterator it( m_alphabItem ); it.current(); it++ )
243 if ( it.current()->text( 0 ) == QString( term[ 0 ].toUpper() ) ) {
244 alphabSection = static_cast<SectionItem *>( it.current() );
245 break;
248 if ( !alphabSection )
249 alphabSection = new SectionItem( m_alphabItem, QString( term[ 0 ].toUpper() ) );
251 new EntryItem( alphabSection, term, entryId );
253 QDomElement definitionElement = childElement( entryElement, QLatin1String( "definition" ) );
254 QString definition = definitionElement.text().simplified();
256 GlossaryEntryXRef::List seeAlso;
258 QDomElement referencesElement = childElement( entryElement, QLatin1String( "references" ) );
259 QDomNodeList referenceNodes = referencesElement.elementsByTagName( QLatin1String( "reference" ) );
260 if ( referenceNodes.count() > 0 )
261 for ( int k = 0; k < referenceNodes.count(); k++ ) {
262 QDomElement referenceElement = referenceNodes.item( k ).toElement();
264 QString term = referenceElement.attribute( QLatin1String( "term" ) );
265 QString id = referenceElement.attribute( QLatin1String( "id" ) );
267 seeAlso += GlossaryEntryXRef( term, id );
270 m_glossEntries.insert( entryId, new GlossaryEntry( term, definition, seeAlso ) );
275 void Glossary::treeItemSelected( Q3ListViewItem *item )
277 if ( !item )
278 return;
280 if ( EntryItem *i = dynamic_cast<EntryItem *>( item ) )
281 emit entrySelected( entry( i->id() ) );
283 item->setOpen( !item->isOpen() );
286 QDomElement Glossary::childElement( const QDomElement &element, const QString &name )
288 QDomElement e;
289 for ( e = element.firstChild().toElement(); !e.isNull(); e = e.nextSibling().toElement() )
290 if ( e.tagName() == name )
291 break;
292 return e;
295 QString Glossary::entryToHtml( const GlossaryEntry &entry )
297 QFile htmlFile( KStandardDirs::locate("data", "khelpcenter/glossary.html.in" ) );
298 if (!htmlFile.open(QIODevice::ReadOnly))
299 return QString( "<html><head></head><body><h3>%1</h3>%2</body></html>" )
300 .arg( i18n( "Error" ) )
301 .arg( i18n( "Unable to show selected glossary entry: unable to open "
302 "file 'glossary.html.in'!" ) );
304 QString seeAlso;
305 if (!entry.seeAlso().isEmpty()) {
306 seeAlso = i18n("See also: ");
307 GlossaryEntryXRef::List seeAlsos = entry.seeAlso();
308 GlossaryEntryXRef::List::ConstIterator it = seeAlsos.begin();
309 GlossaryEntryXRef::List::ConstIterator end = seeAlsos.end();
310 for (; it != end; ++it) {
311 seeAlso += QLatin1String("<a href=\"glossentry:");
312 seeAlso += (*it).id();
313 seeAlso += QLatin1String("\">") + (*it).term();
314 seeAlso += QLatin1String("</a>, ");
316 seeAlso = seeAlso.left(seeAlso.length() - 2);
319 QTextStream htmlStream(&htmlFile);
320 return htmlStream.readAll()
321 .arg( i18n( "KDE Glossary" ) )
322 .arg( entry.term() )
323 .arg( View::langLookup( QLatin1String("khelpcenter/konq.css") ) )
324 .arg( View::langLookup( QLatin1String("khelpcenter/pointers.png") ) )
325 .arg( View::langLookup( QLatin1String("khelpcenter/khelpcenter.png") ) )
326 .arg( View::langLookup( QLatin1String("khelpcenter/lines.png") ) )
327 .arg( entry.term() )
328 .arg( entry.definition() )
329 .arg( seeAlso)
330 .arg( View::langLookup( QLatin1String("khelpcenter/kdelogo2.png") ) );
333 void Glossary::slotSelectGlossEntry( const QString &id )
335 if ( !m_idDict.contains( id ) )
336 return;
338 EntryItem *newItem = m_idDict.value( id );
339 EntryItem *curItem = dynamic_cast<EntryItem *>( currentItem() );
340 if ( curItem != 0 ) {
341 if ( curItem->id() == id )
342 return;
343 curItem->parent()->setOpen( false );
346 setCurrentItem( newItem );
347 ensureItemVisible( newItem );
350 #include "glossary.moc"
351 // vim:ts=4:sw=4:et