summaryrefslogtreecommitdiff
path: root/library/global.cpp
Unidiff
Diffstat (limited to 'library/global.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--library/global.cpp21
1 files changed, 15 insertions, 6 deletions
diff --git a/library/global.cpp b/library/global.cpp
index 05d23ac..6c0a66a 100644
--- a/library/global.cpp
+++ b/library/global.cpp
@@ -1,818 +1,827 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of the Qtopia Environment. 4** This file is part of the Qtopia Environment.
5** 5**
6** This file may be distributed and/or modified under the terms of the 6** This file may be distributed and/or modified under the terms of the
7** GNU General Public License version 2 as published by the Free Software 7** GNU General Public License version 2 as published by the Free Software
8** Foundation and appearing in the file LICENSE.GPL included in the 8** Foundation and appearing in the file LICENSE.GPL included in the
9** packaging of this file. 9** packaging of this file.
10** 10**
11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 11** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 12** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13** 13**
14** See http://www.trolltech.com/gpl/ for GPL licensing information. 14** See http://www.trolltech.com/gpl/ for GPL licensing information.
15** 15**
16** Contact info@trolltech.com if any conditions of this licensing are 16** Contact info@trolltech.com if any conditions of this licensing are
17** not clear to you. 17** not clear to you.
18** 18**
19**********************************************************************/ 19**********************************************************************/
20#define QTOPIA_INTERNAL_LANGLIST 20#define QTOPIA_INTERNAL_LANGLIST
21#include <qpe/qpedebug.h> 21#include <qpe/qpedebug.h>
22#include <qpe/global.h> 22#include <qpe/global.h>
23#include <qpe/qdawg.h> 23#include <qpe/qdawg.h>
24#include <qpe/qpeapplication.h> 24#include <qpe/qpeapplication.h>
25#include <qpe/resource.h> 25#include <qpe/resource.h>
26#include <qpe/storage.h> 26#include <qpe/storage.h>
27#include <qpe/applnk.h> 27#include <qpe/applnk.h>
28#include <qpe/qcopenvelope_qws.h> 28#include <qpe/qcopenvelope_qws.h>
29#include <qpe/config.h>
29 30
30#include <qfile.h> 31#include <qfile.h>
31#include <qlabel.h> 32#include <qlabel.h>
32#include <qtimer.h> 33#include <qtimer.h>
33#include <qmap.h> 34#include <qmap.h>
34#include <qdict.h> 35#include <qdict.h>
35#include <qdir.h> 36#include <qdir.h>
36#include <qmessagebox.h> 37#include <qmessagebox.h>
37#include <qregexp.h> 38#include <qregexp.h>
38 39
39#include <stdlib.h> 40#include <stdlib.h>
40#include <sys/stat.h> 41#include <sys/stat.h>
41#include <sys/wait.h> 42#include <sys/wait.h>
42#include <sys/types.h> 43#include <sys/types.h>
43#include <fcntl.h> 44#include <fcntl.h>
44#include <unistd.h> 45#include <unistd.h>
45#include <errno.h> 46#include <errno.h>
46 47
47#include <qwindowsystem_qws.h> // for qwsServer 48#include <qwindowsystem_qws.h> // for qwsServer
48#include <qdatetime.h> 49#include <qdatetime.h>
49 50
50#include <qfile.h> 51#include <qfile.h>
51 52
52namespace { 53namespace {
53 // checks if the storage should be searched 54 // checks if the storage should be searched
54 bool checkStorage(const QString &path ){ // this is a small Config replacement cause config is too limited -zecke 55 bool checkStorage(const QString &path ){ // this is a small Config replacement cause config is too limited -zecke
55 QFile file(path ); 56 QFile file(path );
56 if(!file.open(IO_ReadOnly ) ) 57 if(!file.open(IO_ReadOnly ) )
57 return true; 58 return true;
58 59
59 QByteArray array = file.readAll(); 60 QByteArray array = file.readAll();
60 QStringList list = QStringList::split('\n', QString( array ) ); 61 QStringList list = QStringList::split('\n', QString( array ) );
61 for(QStringList::Iterator it = list.begin(); it != list.end(); ++it ){ 62 for(QStringList::Iterator it = list.begin(); it != list.end(); ++it ){
62 if( (*it).startsWith("autocheck = 0" ) ){ 63 if( (*it).startsWith("autocheck = 0" ) ){
63 return false; 64 return false;
64 }else if( (*it).startsWith("autocheck = 1" ) ){ 65 }else if( (*it).startsWith("autocheck = 1" ) ){
65 return true; 66 return true;
66 } 67 }
67 } 68 }
68 return true; 69 return true;
69 } 70 }
70} 71}
71 72
72//#include "quickexec_p.h" 73//#include "quickexec_p.h"
73 74
74class Emitter : public QObject { 75class Emitter : public QObject {
75 Q_OBJECT 76 Q_OBJECT
76public: 77public:
77 Emitter( QWidget* receiver, const QString& document ) 78 Emitter( QWidget* receiver, const QString& document )
78 { 79 {
79 connect(this, SIGNAL(setDocument(const QString&)), 80 connect(this, SIGNAL(setDocument(const QString&)),
80 receiver, SLOT(setDocument(const QString&))); 81 receiver, SLOT(setDocument(const QString&)));
81 emit setDocument(document); 82 emit setDocument(document);
82 disconnect(this, SIGNAL(setDocument(const QString&)), 83 disconnect(this, SIGNAL(setDocument(const QString&)),
83 receiver, SLOT(setDocument(const QString&))); 84 receiver, SLOT(setDocument(const QString&)));
84 } 85 }
85 86
86signals: 87signals:
87 void setDocument(const QString&); 88 void setDocument(const QString&);
88}; 89};
89 90
90 91
91class StartingAppList : public QObject { 92class StartingAppList : public QObject {
92 Q_OBJECT 93 Q_OBJECT
93public: 94public:
94 static void add( const QString& name ); 95 static void add( const QString& name );
95 static bool isStarting( const QString name ); 96 static bool isStarting( const QString name );
96private slots: 97private slots:
97 void handleNewChannel( const QString &); 98 void handleNewChannel( const QString &);
98private: 99private:
99 StartingAppList( QObject *parent=0, const char* name=0 ) ; 100 StartingAppList( QObject *parent=0, const char* name=0 ) ;
100 101
101 QDict<QTime> dict; 102 QDict<QTime> dict;
102 static StartingAppList *appl; 103 static StartingAppList *appl;
103}; 104};
104 105
105StartingAppList* StartingAppList::appl = 0; 106StartingAppList* StartingAppList::appl = 0;
106 107
107StartingAppList::StartingAppList( QObject *parent, const char* name ) 108StartingAppList::StartingAppList( QObject *parent, const char* name )
108 :QObject( parent, name ) 109 :QObject( parent, name )
109{ 110{
110#if QT_VERSION >= 232 && defined(QWS) 111#if QT_VERSION >= 232 && defined(QWS)
111 connect( qwsServer, SIGNAL( newChannel(const QString&)), 112 connect( qwsServer, SIGNAL( newChannel(const QString&)),
112 this, SLOT( handleNewChannel(const QString&)) ); 113 this, SLOT( handleNewChannel(const QString&)) );
113#endif 114#endif
114 dict.setAutoDelete( TRUE ); 115 dict.setAutoDelete( TRUE );
115} 116}
116 117
117void StartingAppList::add( const QString& name ) 118void StartingAppList::add( const QString& name )
118{ 119{
119#if QT_VERSION >= 232 && !defined(QT_NO_COP) 120#if QT_VERSION >= 232 && !defined(QT_NO_COP)
120 if ( !appl ) 121 if ( !appl )
121 appl = new StartingAppList; 122 appl = new StartingAppList;
122 QTime *t = new QTime; 123 QTime *t = new QTime;
123 t->start(); 124 t->start();
124 appl->dict.insert( "QPE/Application/" + name, t ); 125 appl->dict.insert( "QPE/Application/" + name, t );
125#endif 126#endif
126} 127}
127 128
128bool StartingAppList::isStarting( const QString name ) 129bool StartingAppList::isStarting( const QString name )
129{ 130{
130#if QT_VERSION >= 232 && !defined(QT_NO_COP) 131#if QT_VERSION >= 232 && !defined(QT_NO_COP)
131 if ( appl ) { 132 if ( appl ) {
132 QTime *t = appl->dict.find( "QPE/Application/" + name ); 133 QTime *t = appl->dict.find( "QPE/Application/" + name );
133 if ( !t ) 134 if ( !t )
134 return FALSE; 135 return FALSE;
135 if ( t->elapsed() > 10000 ) { 136 if ( t->elapsed() > 10000 ) {
136 // timeout in case of crash or something 137 // timeout in case of crash or something
137 appl->dict.remove( "QPE/Application/" + name ); 138 appl->dict.remove( "QPE/Application/" + name );
138 return FALSE; 139 return FALSE;
139 } 140 }
140 return TRUE; 141 return TRUE;
141 } 142 }
142#endif 143#endif
143 return FALSE; 144 return FALSE;
144} 145}
145 146
146void StartingAppList::handleNewChannel( const QString & name ) 147void StartingAppList::handleNewChannel( const QString & name )
147{ 148{
148#if QT_VERSION >= 232 && !defined(QT_NO_COP) 149#if QT_VERSION >= 232 && !defined(QT_NO_COP)
149 dict.remove( name ); 150 dict.remove( name );
150#endif 151#endif
151} 152}
152 153
153static bool docDirCreated = FALSE; 154static bool docDirCreated = FALSE;
154static QDawg* fixed_dawg = 0; 155static QDawg* fixed_dawg = 0;
155static QDict<QDawg> *named_dawg = 0; 156static QDict<QDawg> *named_dawg = 0;
156 157
157static QString qpeDir() 158static QString qpeDir()
158{ 159{
159 QString dir = getenv("OPIEDIR"); 160 QString dir = getenv("OPIEDIR");
160 if ( dir.isEmpty() ) dir = ".."; 161 if ( dir.isEmpty() ) dir = "..";
161 return dir; 162 return dir;
162} 163}
163 164
164static QString dictDir() 165static QString dictDir()
165{ 166{
166 return qpeDir() + "/etc/dict"; 167 return qpeDir() + "/etc/dict";
167} 168}
168 169
169/*! 170/*!
170 \class Global global.h 171 \class Global global.h
171 \brief The Global class provides application-wide global functions. 172 \brief The Global class provides application-wide global functions.
172 173
173 The Global functions are grouped as follows: 174 The Global functions are grouped as follows:
174 \tableofcontents 175 \tableofcontents
175 176
176 \section1 User Interface 177 \section1 User Interface
177 178
178 The statusMessage() function provides short-duration messages to the 179 The statusMessage() function provides short-duration messages to the
179 user. The showInputMethod() function shows the current input method, 180 user. The showInputMethod() function shows the current input method,
180 and hideInputMethod() hides the input method. 181 and hideInputMethod() hides the input method.
181 182
182 \section1 Document related 183 \section1 Document related
183 184
184 The findDocuments() function creates a set of \link doclnk.html 185 The findDocuments() function creates a set of \link doclnk.html
185 DocLnk\endlink objects in a particular folder. 186 DocLnk\endlink objects in a particular folder.
186 187
187 \section1 Filesystem related 188 \section1 Filesystem related
188 189
189 Global provides an applicationFileName() function that returns the 190 Global provides an applicationFileName() function that returns the
190 full path of an application-specific file. 191 full path of an application-specific file.
191 192
192 The execute() function runs an application. 193 The execute() function runs an application.
193 194
194 \section1 Word list related 195 \section1 Word list related
195 196
196 A list of words relevant to the current locale is maintained by the 197 A list of words relevant to the current locale is maintained by the
197 system. The list is held in a \link qdawg.html DAWG\endlink 198 system. The list is held in a \link qdawg.html DAWG\endlink
198 (implemented by the QDawg class). This list is used, for example, by 199 (implemented by the QDawg class). This list is used, for example, by
199 the pickboard input method. 200 the pickboard input method.
200 201
201 The global QDawg is returned by fixedDawg(); this cannot be updated. 202 The global QDawg is returned by fixedDawg(); this cannot be updated.
202 An updatable copy of the global QDawg is returned by addedDawg(). 203 An updatable copy of the global QDawg is returned by addedDawg().
203 Applications may have their own word lists stored in \l{QDawg}s 204 Applications may have their own word lists stored in \l{QDawg}s
204 which are returned by dawg(). Use addWords() to add words to the 205 which are returned by dawg(). Use addWords() to add words to the
205 updateable copy of the global QDawg or to named application 206 updateable copy of the global QDawg or to named application
206 \l{QDawg}s. 207 \l{QDawg}s.
207 208
208 \section1 Quoting 209 \section1 Quoting
209 210
210 The shellQuote() function quotes a string suitable for passing to a 211 The shellQuote() function quotes a string suitable for passing to a
211 shell. The stringQuote() function backslash escapes '\' and '"' 212 shell. The stringQuote() function backslash escapes '\' and '"'
212 characters. 213 characters.
213 214
214 \section1 Hardware 215 \section1 Hardware
215 216
216 The implementation of the writeHWClock() function depends on the AlarmServer 217 The implementation of the writeHWClock() function depends on the AlarmServer
217 implementation. If the AlarmServer is using atd the clock will be synced to 218 implementation. If the AlarmServer is using atd the clock will be synced to
218 hardware. If opie-alarm is used the hardware clock will be synced before 219 hardware. If opie-alarm is used the hardware clock will be synced before
219 suspending the device. opie-alarm is used by iPAQ and Zaurii implementation 220 suspending the device. opie-alarm is used by iPAQ and Zaurii implementation
220 221
221 \ingroup qtopiaemb 222 \ingroup qtopiaemb
222*/ 223*/
223 224
224/*! 225/*!
225 \internal 226 \internal
226*/ 227*/
227Global::Global() 228Global::Global()
228{ 229{
229} 230}
230 231
231/*! 232/*!
232 Returns the unchangeable QDawg that contains general 233 Returns the unchangeable QDawg that contains general
233 words for the current locale. 234 words for the current locale.
234 235
235 \sa addedDawg() 236 \sa addedDawg()
236*/ 237*/
237const QDawg& Global::fixedDawg() 238const QDawg& Global::fixedDawg()
238{ 239{
239 if ( !fixed_dawg ) { 240 if ( !fixed_dawg ) {
240 if ( !docDirCreated ) 241 if ( !docDirCreated )
241 createDocDir(); 242 createDocDir();
242 243
243 fixed_dawg = new QDawg; 244 fixed_dawg = new QDawg;
244 QString dawgfilename = dictDir() + "/dawg"; 245 QString dawgfilename = dictDir() + "/dawg";
245 QString words_lang; 246 QString words_lang;
246 QStringList langs = Global::languageList(); 247 QStringList langs = Global::languageList();
247 for (QStringList::ConstIterator it = langs.begin(); it!=langs.end(); ++it) { 248 for (QStringList::ConstIterator it = langs.begin(); it!=langs.end(); ++it) {
248 QString lang = *it; 249 QString lang = *it;
249 words_lang = dictDir() + "/words." + lang; 250 words_lang = dictDir() + "/words." + lang;
250 QString dawgfilename_lang = dawgfilename + "." + lang; 251 QString dawgfilename_lang = dawgfilename + "." + lang;
251 if ( QFile::exists(dawgfilename_lang) || 252 if ( QFile::exists(dawgfilename_lang) ||
252 QFile::exists(words_lang) ) { 253 QFile::exists(words_lang) ) {
253 dawgfilename = dawgfilename_lang; 254 dawgfilename = dawgfilename_lang;
254 break; 255 break;
255 } 256 }
256 } 257 }
257 QFile dawgfile(dawgfilename); 258 QFile dawgfile(dawgfilename);
258 259
259 if ( !dawgfile.exists() ) { 260 if ( !dawgfile.exists() ) {
260 QString fn = dictDir() + "/words"; 261 QString fn = dictDir() + "/words";
261 if ( QFile::exists(words_lang) ) 262 if ( QFile::exists(words_lang) )
262 fn = words_lang; 263 fn = words_lang;
263 QFile in(fn); 264 QFile in(fn);
264 if ( in.open(IO_ReadOnly) ) { 265 if ( in.open(IO_ReadOnly) ) {
265 fixed_dawg->createFromWords(&in); 266 fixed_dawg->createFromWords(&in);
266 dawgfile.open(IO_WriteOnly); 267 dawgfile.open(IO_WriteOnly);
267 fixed_dawg->write(&dawgfile); 268 fixed_dawg->write(&dawgfile);
268 dawgfile.close(); 269 dawgfile.close();
269 } 270 }
270 } else { 271 } else {
271 fixed_dawg->readFile(dawgfilename); 272 fixed_dawg->readFile(dawgfilename);
272 } 273 }
273 } 274 }
274 275
275 return *fixed_dawg; 276 return *fixed_dawg;
276} 277}
277 278
278/*! 279/*!
279 Returns the changeable QDawg that contains general 280 Returns the changeable QDawg that contains general
280 words for the current locale. 281 words for the current locale.
281 282
282 \sa fixedDawg() 283 \sa fixedDawg()
283*/ 284*/
284const QDawg& Global::addedDawg() 285const QDawg& Global::addedDawg()
285{ 286{
286 return dawg("local"); 287 return dawg("local");
287} 288}
288 289
289/*! 290/*!
290 Returns the QDawg with the given \a name. 291 Returns the QDawg with the given \a name.
291 This is an application-specific word list. 292 This is an application-specific word list.
292 293
293 \a name should not contain "/". 294 \a name should not contain "/".
294*/ 295*/
295const QDawg& Global::dawg(const QString& name) 296const QDawg& Global::dawg(const QString& name)
296{ 297{
297 createDocDir(); 298 createDocDir();
298 if ( !named_dawg ) 299 if ( !named_dawg )
299 named_dawg = new QDict<QDawg>; 300 named_dawg = new QDict<QDawg>;
300 QDawg* r = named_dawg->find(name); 301 QDawg* r = named_dawg->find(name);
301 if ( !r ) { 302 if ( !r ) {
302 r = new QDawg; 303 r = new QDawg;
303 named_dawg->insert(name,r); 304 named_dawg->insert(name,r);
304 QString dawgfilename = applicationFileName("Dictionary", name ) + ".dawg"; 305 QString dawgfilename = applicationFileName("Dictionary", name ) + ".dawg";
305 QFile dawgfile(dawgfilename); 306 QFile dawgfile(dawgfilename);
306 if ( dawgfile.open(IO_ReadOnly) ) 307 if ( dawgfile.open(IO_ReadOnly) )
307 r->readFile(dawgfilename); 308 r->readFile(dawgfilename);
308 } 309 }
309 return *r; 310 return *r;
310} 311}
311 312
312/*! 313/*!
313 \overload 314 \overload
314 Adds \a wordlist to the addedDawg(). 315 Adds \a wordlist to the addedDawg().
315 316
316 Note that the addition of words persists between program executions 317 Note that the addition of words persists between program executions
317 (they are saved in the dictionary files), so you should confirm the 318 (they are saved in the dictionary files), so you should confirm the
318 words with the user before adding them. 319 words with the user before adding them.
319*/ 320*/
320void Global::addWords(const QStringList& wordlist) 321void Global::addWords(const QStringList& wordlist)
321{ 322{
322 addWords("local",wordlist); 323 addWords("local",wordlist);
323} 324}
324 325
325/*! 326/*!
326 \overload 327 \overload
327 Adds \a wordlist to the addedDawg(). 328 Adds \a wordlist to the addedDawg().
328 329
329 Note that the addition of words persists between program executions 330 Note that the addition of words persists between program executions
330 (they are saved in the dictionary files), so you should confirm the 331 (they are saved in the dictionary files), so you should confirm the
331 words with the user before adding them. 332 words with the user before adding them.
332*/ 333*/
333void Global::addWords(const QString& dictname, const QStringList& wordlist) 334void Global::addWords(const QString& dictname, const QStringList& wordlist)
334{ 335{
335 QDawg& d = (QDawg&)dawg(dictname); 336 QDawg& d = (QDawg&)dawg(dictname);
336 QStringList all = d.allWords() + wordlist; 337 QStringList all = d.allWords() + wordlist;
337 d.createFromWords(all); 338 d.createFromWords(all);
338 339
339 QString dawgfilename = applicationFileName("Dictionary", dictname) + ".dawg"; 340 QString dawgfilename = applicationFileName("Dictionary", dictname) + ".dawg";
340 QFile dawgfile(dawgfilename); 341 QFile dawgfile(dawgfilename);
341 if ( dawgfile.open(IO_WriteOnly) ) { 342 if ( dawgfile.open(IO_WriteOnly) ) {
342 d.write(&dawgfile); 343 d.write(&dawgfile);
343 dawgfile.close(); 344 dawgfile.close();
344 } 345 }
345 346
346 // #### Re-read the dawg here if we use mmap(). 347 // #### Re-read the dawg here if we use mmap().
347 348
348 // #### Signal other processes to re-read. 349 // #### Signal other processes to re-read.
349} 350}
350 351
351 352
352/*! 353/*!
353 Returns the full path for the application called \a appname, with the 354 Returns the full path for the application called \a appname, with the
354 given \a filename. Returns QString::null if there was a problem creating 355 given \a filename. Returns QString::null if there was a problem creating
355 the directory tree for \a appname. 356 the directory tree for \a appname.
356 If \a filename contains "/", it is the caller's responsibility to 357 If \a filename contains "/", it is the caller's responsibility to
357 ensure that those directories exist. 358 ensure that those directories exist.
358*/ 359*/
359QString Global::applicationFileName(const QString& appname, const QString& filename) 360QString Global::applicationFileName(const QString& appname, const QString& filename)
360{ 361{
361 QDir d; 362 QDir d;
362 QString r = getenv("HOME"); 363 QString r = getenv("HOME");
363 r += "/Applications/"; 364 r += "/Applications/";
364 if ( !QFile::exists( r ) ) 365 if ( !QFile::exists( r ) )
365 if ( d.mkdir(r) == false ) 366 if ( d.mkdir(r) == false )
366 return QString::null; 367 return QString::null;
367 r += appname; 368 r += appname;
368 if ( !QFile::exists( r ) ) 369 if ( !QFile::exists( r ) )
369 if ( d.mkdir(r) == false ) 370 if ( d.mkdir(r) == false )
370 return QString::null; 371 return QString::null;
371 r += "/"; r += filename; 372 r += "/"; r += filename;
372 return r; 373 return r;
373} 374}
374 375
375/*! 376/*!
376 \internal 377 \internal
377*/ 378*/
378void Global::createDocDir() 379void Global::createDocDir()
379{ 380{
380 if ( !docDirCreated ) { 381 if ( !docDirCreated ) {
381 docDirCreated = TRUE; 382 docDirCreated = TRUE;
382 mkdir( QPEApplication::documentDir().latin1(), 0755 ); 383 mkdir( QPEApplication::documentDir().latin1(), 0755 );
383 } 384 }
384} 385}
385 386
386 387
387/*! 388/*!
388 Displays a status \a message to the user. This usually appears 389 Displays a status \a message to the user. This usually appears
389 in the taskbar for a short amount of time, then disappears. 390 in the taskbar for a short amount of time, then disappears.
390*/ 391*/
391void Global::statusMessage(const QString& message) 392void Global::statusMessage(const QString& message)
392{ 393{
393#if !defined(QT_NO_COP) 394#if !defined(QT_NO_COP)
394 QCopEnvelope e( "QPE/TaskBar", "message(QString)" ); 395 QCopEnvelope e( "QPE/TaskBar", "message(QString)" );
395 e << message; 396 e << message;
396#endif 397#endif
397} 398}
398 399
399/*! 400/*!
400 \internal 401 \internal
401*/ 402*/
402void Global::applyStyle() 403void Global::applyStyle()
403{ 404{
404#if !defined(QT_NO_COP) 405#if !defined(QT_NO_COP)
405 QCopChannel::send( "QPE/System", "applyStyle()" ); 406 QCopChannel::send( "QPE/System", "applyStyle()" );
406#else 407#else
407 ((QPEApplication *)qApp)->applyStyle(); // apply without needing QCop for floppy version 408 ((QPEApplication *)qApp)->applyStyle(); // apply without needing QCop for floppy version
408#endif 409#endif
409} 410}
410 411
411/*! 412/*!
412 \internal 413 \internal
413*/ 414*/
414QWidget *Global::shutdown( bool ) 415QWidget *Global::shutdown( bool )
415{ 416{
416#if !defined(QT_NO_COP) 417#if !defined(QT_NO_COP)
417 QCopChannel::send( "QPE/System", "shutdown()" ); 418 QCopChannel::send( "QPE/System", "shutdown()" );
418#endif 419#endif
419 return 0; 420 return 0;
420} 421}
421 422
422/*! 423/*!
423 \internal 424 \internal
424*/ 425*/
425QWidget *Global::restart( bool ) 426QWidget *Global::restart( bool )
426{ 427{
427#if !defined(QT_NO_COP) 428#if !defined(QT_NO_COP)
428 QCopChannel::send( "QPE/System", "restart()" ); 429 QCopChannel::send( "QPE/System", "restart()" );
429#endif 430#endif
430 return 0; 431 return 0;
431} 432}
432 433
433/*! 434/*!
434 Explicitly show the current input method. 435 Explicitly show the current input method.
435 436
436 Input methods are indicated in the taskbar by a small icon. If the 437 Input methods are indicated in the taskbar by a small icon. If the
437 input method is activated (shown) then it takes up some proportion 438 input method is activated (shown) then it takes up some proportion
438 of the bottom of the screen, to allow the user to interact (input 439 of the bottom of the screen, to allow the user to interact (input
439 characters) with it. 440 characters) with it.
440 441
441 \sa hideInputMethod() 442 \sa hideInputMethod()
442*/ 443*/
443void Global::showInputMethod() 444void Global::showInputMethod()
444{ 445{
445#if !defined(QT_NO_COP) 446#if !defined(QT_NO_COP)
446 QCopChannel::send( "QPE/TaskBar", "showInputMethod()" ); 447 QCopChannel::send( "QPE/TaskBar", "showInputMethod()" );
447#endif 448#endif
448} 449}
449 450
450/*! 451/*!
451 Explicitly hide the current input method. 452 Explicitly hide the current input method.
452 453
453 The current input method is still indicated in the taskbar, but no 454 The current input method is still indicated in the taskbar, but no
454 longer takes up screen space, and can no longer be interacted with. 455 longer takes up screen space, and can no longer be interacted with.
455 456
456 \sa showInputMethod() 457 \sa showInputMethod()
457*/ 458*/
458void Global::hideInputMethod() 459void Global::hideInputMethod()
459{ 460{
460#if !defined(QT_NO_COP) 461#if !defined(QT_NO_COP)
461 QCopChannel::send( "QPE/TaskBar", "hideInputMethod()" ); 462 QCopChannel::send( "QPE/TaskBar", "hideInputMethod()" );
462#endif 463#endif
463} 464}
464 465
465 466
466/*! 467/*!
467 \internal 468 \internal
468*/ 469*/
469bool Global::isBuiltinCommand( const QString &name ) 470bool Global::isBuiltinCommand( const QString &name )
470{ 471{
471 if(!builtin) 472 if(!builtin)
472 return FALSE; // yes, it can happen 473 return FALSE; // yes, it can happen
473 for (int i = 0; builtin[i].file; i++) { 474 for (int i = 0; builtin[i].file; i++) {
474 if ( builtin[i].file == name ) { 475 if ( builtin[i].file == name ) {
475 return TRUE; 476 return TRUE;
476 } 477 }
477 } 478 }
478 return FALSE; 479 return FALSE;
479} 480}
480 481
481Global::Command* Global::builtin=0; 482Global::Command* Global::builtin=0;
482QGuardedPtr<QWidget> *Global::running=0; 483QGuardedPtr<QWidget> *Global::running=0;
483 484
484/*! 485/*!
485 \class Global::Command 486 \class Global::Command
486 \brief The Global::Command class is internal. 487 \brief The Global::Command class is internal.
487 \internal 488 \internal
488*/ 489*/
489 490
490/*! 491/*!
491 \internal 492 \internal
492*/ 493*/
493void Global::setBuiltinCommands( Command* list ) 494void Global::setBuiltinCommands( Command* list )
494{ 495{
495 if ( running ) 496 if ( running )
496 delete [] running; 497 delete [] running;
497 498
498 builtin = list; 499 builtin = list;
499 int count = 0; 500 int count = 0;
500 if (!builtin) 501 if (!builtin)
501 return; 502 return;
502 while ( builtin[count].file ) 503 while ( builtin[count].file )
503 count++; 504 count++;
504 505
505 running = new QGuardedPtr<QWidget> [ count ]; 506 running = new QGuardedPtr<QWidget> [ count ];
506} 507}
507 508
508/*! 509/*!
509 \internal 510 \internal
510*/ 511*/
511void Global::setDocument( QWidget* receiver, const QString& document ) 512void Global::setDocument( QWidget* receiver, const QString& document )
512{ 513{
513 Emitter emitter(receiver,document); 514 Emitter emitter(receiver,document);
514} 515}
515 516
516/*! 517/*!
517 \internal 518 \internal
518*/ 519*/
519bool Global::terminateBuiltin( const QString& n ) 520bool Global::terminateBuiltin( const QString& n )
520{ 521{
521 if (!builtin) 522 if (!builtin)
522 return FALSE; 523 return FALSE;
523 for (int i = 0; builtin[i].file; i++) { 524 for (int i = 0; builtin[i].file; i++) {
524 if ( builtin[i].file == n ) { 525 if ( builtin[i].file == n ) {
525 delete running[i]; 526 delete running[i];
526 return TRUE; 527 return TRUE;
527 } 528 }
528 } 529 }
529 return FALSE; 530 return FALSE;
530} 531}
531 532
532/*! 533/*!
533 \internal 534 \internal
534*/ 535*/
535void Global::terminate( const AppLnk* app ) 536void Global::terminate( const AppLnk* app )
536{ 537{
537 //if ( terminateBuiltin(app->exec()) ) return; // maybe? haven't tried this 538 //if ( terminateBuiltin(app->exec()) ) return; // maybe? haven't tried this
538 539
539#ifndef QT_NO_COP 540#ifndef QT_NO_COP
540 QCString channel = "QPE/Application/" + app->exec().utf8(); 541 QCString channel = "QPE/Application/" + app->exec().utf8();
541 if ( QCopChannel::isRegistered(channel) ) { 542 if ( QCopChannel::isRegistered(channel) ) {
542 QCopEnvelope e(channel, "quit()"); 543 QCopEnvelope e(channel, "quit()");
543 } 544 }
544#endif 545#endif
545} 546}
546 547
547/*! 548/*!
548 Low-level function to run command \a c. 549 Low-level function to run command \a c.
549 550
550 \warning Do not use this function. Use execute instead. 551 \warning Do not use this function. Use execute instead.
551 552
552 \sa execute() 553 \sa execute()
553*/ 554*/
554void Global::invoke(const QString &c) 555void Global::invoke(const QString &c)
555{ 556{
556 // Convert the command line in to a list of arguments 557 // Convert the command line in to a list of arguments
557 QStringList list = QStringList::split(QRegExp(" *"),c); 558 QStringList list = QStringList::split(QRegExp(" *"),c);
558 559
559#if !defined(QT_NO_COP) 560#if !defined(QT_NO_COP)
560 QString ap=list[0]; 561 QString ap=list[0];
561 // see if the application is already running 562 // see if the application is already running
562 // XXX should lock file /tmp/qcop-msg-ap 563 // XXX should lock file /tmp/qcop-msg-ap
563 if ( QCopChannel::isRegistered( ("QPE/Application/" + ap).latin1() ) ) { 564 if ( QCopChannel::isRegistered( ("QPE/Application/" + ap).latin1() ) ) {
564 // If the channel is already register, the app is already running, so show it. 565 // If the channel is already register, the app is already running, so show it.
565 { QCopEnvelope env( ("QPE/Application/" + ap).latin1(), "raise()" ); } 566 { QCopEnvelope env( ("QPE/Application/" + ap).latin1(), "raise()" ); }
566 567
567 //QCopEnvelope e("QPE/System", "notBusy(QString)" ); 568 //QCopEnvelope e("QPE/System", "notBusy(QString)" );
568 //e << ap; 569 //e << ap;
569 return; 570 return;
570 } 571 }
571 // XXX should unlock file /tmp/qcop-msg-ap 572 // XXX should unlock file /tmp/qcop-msg-ap
572 //see if it is being started 573 //see if it is being started
573 if ( StartingAppList::isStarting( ap ) ) { 574 if ( StartingAppList::isStarting( ap ) ) {
574 // FIXME take it out for now, since it leads to a much to short showing of wait if 575 // FIXME take it out for now, since it leads to a much to short showing of wait if
575 // some entry is clicked. 576 // some entry is clicked.
576 // Real cause is that ::execute is called twice for document tab. But it would need some larger changes 577 // Real cause is that ::execute is called twice for document tab. But it would need some larger changes
577 // to fix that, and with future syncs with qtopia 1.6 it will change anyway big time since somebody there 578 // to fix that, and with future syncs with qtopia 1.6 it will change anyway big time since somebody there
578 // had the idea that an apploader belongs to the launcher ... 579 // had the idea that an apploader belongs to the launcher ...
579 //QCopEnvelope e("QPE/System", "notBusy(QString)" ); 580 //QCopEnvelope e("QPE/System", "notBusy(QString)" );
580 //e << ap; 581 //e << ap;
581 return; 582 return;
582 } 583 }
583 584
584#endif 585#endif
585 586
586#ifdef QT_NO_QWS_MULTIPROCESS 587#ifdef QT_NO_QWS_MULTIPROCESS
587 QMessageBox::warning( 0, "Error", "Could not find the application " + c, "Ok", 0, 0, 0, 1 ); 588 QMessageBox::warning( 0, "Error", "Could not find the application " + c, "Ok", 0, 0, 0, 1 );
588#else 589#else
589 590
590 QStrList slist; 591 QStrList slist;
591 unsigned int j; 592 unsigned int j;
592 for ( j = 0; j < list.count(); j++ ) 593 for ( j = 0; j < list.count(); j++ )
593 slist.append( list[j].utf8() ); 594 slist.append( list[j].utf8() );
594 595
595 const char **args = new (const char *)[slist.count() + 1]; 596 const char **args = new (const char *)[slist.count() + 1];
596 for ( j = 0; j < slist.count(); j++ ) 597 for ( j = 0; j < slist.count(); j++ )
597 args[j] = slist.at(j); 598 args[j] = slist.at(j);
598 args[j] = NULL; 599 args[j] = NULL;
599 600
600#if !defined(QT_NO_COP) 601#if !defined(QT_NO_COP)
601 // an attempt to show a wait... 602 // an attempt to show a wait...
602 // more logic should be used, but this will be fine for the moment... 603 // more logic should be used, but this will be fine for the moment...
603 QCopEnvelope ( "QPE/System", "busy()" ); 604 QCopEnvelope ( "QPE/System", "busy()" );
604#endif 605#endif
605 606
606#ifdef HAVE_QUICKEXEC 607#ifdef HAVE_QUICKEXEC
607#ifdef Q_OS_MACX 608#ifdef Q_OS_MACX
608 QString libexe = qpeDir()+"/binlib/lib"+args[0] + ".dylib"; 609 QString libexe = qpeDir()+"/binlib/lib"+args[0] + ".dylib";
609#else 610#else
610 QString libexe = qpeDir()+"/binlib/lib"+args[0] + ".so"; 611 QString libexe = qpeDir()+"/binlib/lib"+args[0] + ".so";
611#endif 612#endif
612 qDebug("libfile = %s", libexe.latin1() ); 613 qDebug("libfile = %s", libexe.latin1() );
613 if ( QFile::exists( libexe ) ) { 614 if ( QFile::exists( libexe ) ) {
614 qDebug("calling quickexec %s", libexe.latin1() ); 615 qDebug("calling quickexec %s", libexe.latin1() );
615 quickexecv( libexe.utf8().data(), (const char **)args ); 616 quickexecv( libexe.utf8().data(), (const char **)args );
616 } else 617 } else
617#endif 618#endif
618 { 619 {
619 bool success = false; 620 bool success = false;
620 int pfd [2]; 621 int pfd [2];
621 if ( ::pipe ( pfd ) < 0 ) 622 if ( ::pipe ( pfd ) < 0 )
622 pfd [0] = pfd [1] = -1; 623 pfd [0] = pfd [1] = -1;
623 624
624 pid_t pid = ::fork ( ); 625 pid_t pid = ::fork ( );
625 626
626 if ( pid == 0 ) { // child 627 if ( pid == 0 ) { // child
627 for ( int fd = 3; fd < 100; fd++ ) { 628 for ( int fd = 3; fd < 100; fd++ ) {
628 if ( fd != pfd [1] ) 629 if ( fd != pfd [1] )
629 ::close ( fd ); 630 ::close ( fd );
630 } 631 }
631 ::setpgid ( ::getpid ( ), ::getppid ( )); 632 ::setpgid ( ::getpid ( ), ::getppid ( ));
632 633
633 // Closing of fd[1] indicates that the execvp succeeded! 634 // Closing of fd[1] indicates that the execvp succeeded!
634 if ( pfd [1] >= 0 ) 635 if ( pfd [1] >= 0 )
635 ::fcntl ( pfd [1], F_SETFD, FD_CLOEXEC ); 636 ::fcntl ( pfd [1], F_SETFD, FD_CLOEXEC );
636 637
637 // Try bindir first, so that foo/bar works too 638 // Try bindir first, so that foo/bar works too
638 ::execv ( qpeDir ( ) + "/bin/" + args [0], (char * const *) args ); 639 ::execv ( qpeDir ( ) + "/bin/" + args [0], (char * const *) args );
639 ::execvp ( args [0], (char * const *) args ); 640 ::execvp ( args [0], (char * const *) args );
640 641
641 char resultByte = 1; 642 char resultByte = 1;
642 if ( pfd [1] >= 0 ) 643 if ( pfd [1] >= 0 )
643 ::write ( pfd [1], &resultByte, 1 ); 644 ::write ( pfd [1], &resultByte, 1 );
644 ::_exit ( -1 ); 645 ::_exit ( -1 );
645 } 646 }
646 else if ( pid > 0 ) { 647 else if ( pid > 0 ) {
647 success = true; 648 success = true;
648 649
649 if ( pfd [1] >= 0 ) 650 if ( pfd [1] >= 0 )
650 ::close ( pfd [1] ); 651 ::close ( pfd [1] );
651 if ( pfd [0] >= 0 ) { 652 if ( pfd [0] >= 0 ) {
652 while ( true ) { 653 while ( true ) {
653 char resultByte; 654 char resultByte;
654 int n = ::read ( pfd [0], &resultByte, 1 ); 655 int n = ::read ( pfd [0], &resultByte, 1 );
655 if ( n == 1 ) { 656 if ( n == 1 ) {
656 success = false; 657 success = false;
657 break; 658 break;
658 } 659 }
659 if (( n == -1 ) && (( errno == ECHILD ) || ( errno == EINTR ))) 660 if (( n == -1 ) && (( errno == ECHILD ) || ( errno == EINTR )))
660 continue; 661 continue;
661 662
662 break; // success 663 break; // success
663 } 664 }
664 ::close ( pfd [0] ); 665 ::close ( pfd [0] );
665 } 666 }
666 } 667 }
667 if ( success ) 668 if ( success )
668 StartingAppList::add( list[0] ); 669 StartingAppList::add( list[0] );
669 else 670 else
670 QMessageBox::warning( 0, "Error", "Could not start the application " + c, "Ok", 0, 0, 0, 1 ); 671 QMessageBox::warning( 0, "Error", "Could not start the application " + c, "Ok", 0, 0, 0, 1 );
671 } 672 }
672#endif //QT_NO_QWS_MULTIPROCESS 673#endif //QT_NO_QWS_MULTIPROCESS
673} 674}
674 675
675 676
676/*! 677/*!
677 Executes the application identfied by \a c, passing \a 678 Executes the application identfied by \a c, passing \a
678 document if it isn't null. 679 document if it isn't null.
679 680
680 Note that a better approach might be to send a QCop message to the 681 Note that a better approach might be to send a QCop message to the
681 application's QPE/Application/\e{appname} channel. 682 application's QPE/Application/\e{appname} channel.
682*/ 683*/
683void Global::execute( const QString &c, const QString& document ) 684void Global::execute( const QString &c, const QString& document )
684{ 685{
685 // ask the server to do the work 686 // ask the server to do the work
686#if !defined(QT_NO_COP) 687#if !defined(QT_NO_COP)
687 if ( document.isNull() ) { 688 if ( document.isNull() ) {
688 QCopEnvelope e( "QPE/System", "execute(QString)" ); 689 QCopEnvelope e( "QPE/System", "execute(QString)" );
689 e << c; 690 e << c;
690 } else { 691 } else {
691 QCopEnvelope e( "QPE/System", "execute(QString,QString)" ); 692 QCopEnvelope e( "QPE/System", "execute(QString,QString)" );
692 e << c << document; 693 e << c << document;
693 } 694 }
694#endif 695#endif
695 return; 696 return;
696} 697}
697 698
698/*! 699/*!
699 Returns the string \a s with the characters '\', '"', and '$' quoted 700 Returns the string \a s with the characters '\', '"', and '$' quoted
700 by a preceeding '\'. 701 by a preceeding '\'.
701 702
702 \sa stringQuote() 703 \sa stringQuote()
703*/ 704*/
704QString Global::shellQuote(const QString& s) 705QString Global::shellQuote(const QString& s)
705{ 706{
706 QString r="\""; 707 QString r="\"";
707 for (int i=0; i<(int)s.length(); i++) { 708 for (int i=0; i<(int)s.length(); i++) {
708 char c = s[i].latin1(); 709 char c = s[i].latin1();
709 switch (c) { 710 switch (c) {
710 case '\\': case '"': case '$': 711 case '\\': case '"': case '$':
711 r+="\\"; 712 r+="\\";
712 } 713 }
713 r += s[i]; 714 r += s[i];
714 } 715 }
715 r += "\""; 716 r += "\"";
716 return r; 717 return r;
717} 718}
718 719
719/*! 720/*!
720 Returns the string \a s with the characters '\' and '"' quoted by a 721 Returns the string \a s with the characters '\' and '"' quoted by a
721 preceeding '\'. 722 preceeding '\'.
722 723
723 \sa shellQuote() 724 \sa shellQuote()
724*/ 725*/
725QString Global::stringQuote(const QString& s) 726QString Global::stringQuote(const QString& s)
726{ 727{
727 QString r="\""; 728 QString r="\"";
728 for (int i=0; i<(int)s.length(); i++) { 729 for (int i=0; i<(int)s.length(); i++) {
729 char c = s[i].latin1(); 730 char c = s[i].latin1();
730 switch (c) { 731 switch (c) {
731 case '\\': case '"': 732 case '\\': case '"':
732 r+="\\"; 733 r+="\\";
733 } 734 }
734 r += s[i]; 735 r += s[i];
735 } 736 }
736 r += "\""; 737 r += "\"";
737 return r; 738 return r;
738} 739}
739 740
740/*! 741/*!
741 Finds all documents on the system's document directories which 742 Finds all documents on the system's document directories which
742 match the filter \a mimefilter, and appends the resulting DocLnk 743 match the filter \a mimefilter, and appends the resulting DocLnk
743 objects to \a folder. 744 objects to \a folder.
744*/ 745*/
745void Global::findDocuments(DocLnkSet* folder, const QString &mimefilter) 746void Global::findDocuments(DocLnkSet* folder, const QString &mimefilter)
746{ 747{
747 QString homedocs = QString(getenv("HOME")) + "/Documents"; 748 QString homedocs = QString(getenv("HOME")) + "/Documents";
748 DocLnkSet d(homedocs,mimefilter); 749 DocLnkSet d(homedocs,mimefilter);
749 folder->appendFrom(d); 750 folder->appendFrom(d);
750 /** let's do intellegint way of searching these files 751 /** let's do intellegint way of searching these files
751 * a) the user don't want to check mediums global 752 * a) the user don't want to check mediums global
752 * b) the user wants to check but use the global options for it 753 * b) the user wants to check but use the global options for it
753 * c) the user wants to check it but not this medium 754 * c) the user wants to check it but not this medium
754 * d) the user wants to check and this medium as well 755 * d) the user wants to check and this medium as well
755 * 756 *
756 * In all cases we need to apply a different mimefilter to 757 * In all cases we need to apply a different mimefilter to
757 * the medium. 758 * the medium.
758 * a) mimefilter.isEmpty() we need to apply the responding filter 759 * a) mimefilter.isEmpty() we need to apply the responding filter
759 * either the global or the one on the medium 760 * either the global or the one on the medium
760 * 761 *
761 * b) mimefilter is set to an application we need to find out if the 762 * b) mimefilter is set to an application we need to find out if the
762 * mimetypes are included in the mime mask of the medium 763 * mimetypes are included in the mime mask of the medium
763 */ 764 */
764 StorageInfo storage; 765 StorageInfo storage;
765 const QList<FileSystem> &fs = storage.fileSystems(); 766 const QList<FileSystem> &fs = storage.fileSystems();
766 QListIterator<FileSystem> it ( fs ); 767 QListIterator<FileSystem> it ( fs );
767 for ( ; it.current(); ++it ) { 768 for ( ; it.current(); ++it ) {
768 if ( (*it)->isRemovable() ) { // let's find out if we should search on it 769 if ( (*it)->isRemovable() ) { // let's find out if we should search on it
769 // this is a candidate look at the cf and see if we should search on it 770 // this is a candidate look at the cf and see if we should search on it
770 QString path = (*it)->path(); 771 QString path = (*it)->path();
771 if( !checkStorage((*it)->path() + "/.opiestorage.cf" ) ) 772 if( !checkStorage((*it)->path() + "/.opiestorage.cf" ) )
772 continue; 773 continue;
773 DocLnkSet ide( path, mimefilter ); 774 Config conf((*it)->path() + "/.opiestorage.cf", Config::File );
774 folder->appendFrom(ide); 775 conf.setGroup("subdirs");
776 QStringList subDirs = conf.readListEntry("subdirs",':');
777 if (subDirs.isEmpty()) {
778 subDirs.append("Documents");
779 }
780 for (unsigned c = 0; c < subDirs.count();++c) {
781 DocLnkSet ide( path+"/"+subDirs[c], mimefilter );
782 folder->appendFrom(ide);
783 }
775 } else if ( (*it)->disk() == "/dev/mtdblock6" || (*it)->disk() == "tmpfs" ) { 784 } else if ( (*it)->disk() == "/dev/mtdblock6" || (*it)->disk() == "tmpfs" ) {
776 QString path = (*it)->path() + "/Documents"; 785 QString path = (*it)->path() + "/Documents";
777 DocLnkSet ide( path, mimefilter ); 786 DocLnkSet ide( path, mimefilter );
778 folder->appendFrom(ide); 787 folder->appendFrom(ide);
779 } 788 }
780 } 789 }
781} 790}
782 791
783QStringList Global::languageList() 792QStringList Global::languageList()
784{ 793{
785 QString lang = getenv("LANG"); 794 QString lang = getenv("LANG");
786 QStringList langs; 795 QStringList langs;
787 langs.append(lang); 796 langs.append(lang);
788 int i = lang.find("."); 797 int i = lang.find(".");
789 if ( i > 0 ) 798 if ( i > 0 )
790 lang = lang.left( i ); 799 lang = lang.left( i );
791 i = lang.find( "_" ); 800 i = lang.find( "_" );
792 if ( i > 0 ) 801 if ( i > 0 )
793 langs.append(lang.left(i)); 802 langs.append(lang.left(i));
794 return langs; 803 return langs;
795} 804}
796 805
797QStringList Global::helpPath() 806QStringList Global::helpPath()
798{ 807{
799 QString qpeDir = QPEApplication::qpeDir(); 808 QString qpeDir = QPEApplication::qpeDir();
800 QStringList path; 809 QStringList path;
801 QStringList langs = Global::languageList(); 810 QStringList langs = Global::languageList();
802 for (QStringList::ConstIterator it = langs.fromLast(); it!=langs.end(); --it) { 811 for (QStringList::ConstIterator it = langs.fromLast(); it!=langs.end(); --it) {
803 QString lang = *it; 812 QString lang = *it;
804 if ( !lang.isEmpty() ) 813 if ( !lang.isEmpty() )
805 path += qpeDir + "/help/" + lang + "/html"; 814 path += qpeDir + "/help/" + lang + "/html";
806 } 815 }
807 path += qpeDir + "/pics"; 816 path += qpeDir + "/pics";
808 path += qpeDir + "/help/html"; 817 path += qpeDir + "/help/html";
809 /* we even put english into the en dir so try it as fallback as well for opie */ 818 /* we even put english into the en dir so try it as fallback as well for opie */
810 path += qpeDir + "/help/en/html"; 819 path += qpeDir + "/help/en/html";
811 path += qpeDir + "/docs"; 820 path += qpeDir + "/docs";
812 821
813 822
814 return path; 823 return path;
815} 824}
816 825
817 826
818#include "global.moc" 827#include "global.moc"