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