summaryrefslogtreecommitdiff
path: root/library/applnk.cpp
Unidiff
Diffstat (limited to 'library/applnk.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--library/applnk.cpp582
1 files changed, 447 insertions, 135 deletions
diff --git a/library/applnk.cpp b/library/applnk.cpp
index 9498f84..298581a 100644
--- a/library/applnk.cpp
+++ b/library/applnk.cpp
@@ -1,7 +1,7 @@
1/********************************************************************** 1/**********************************************************************
2** Copyright (C) 2000 Trolltech AS. All rights reserved. 2** Copyright (C) 2000-2002 Trolltech AS. All rights reserved.
3** 3**
4** This file is part of 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
@@ -19,13 +19,17 @@
19**********************************************************************/ 19**********************************************************************/
20 20
21#define QTOPIA_INTERNAL_MIMEEXT 21#define QTOPIA_INTERNAL_MIMEEXT
22#define QTOPIA_INTERNAL_PRELOADACCESS
23#define QTOPIA_INTERNAL_APPLNKASSIGN
22 24
23#include "applnk.h" 25#include "applnk.h"
24 26
25#include <qpe/qpeapplication.h> 27#include <qpe/qpeapplication.h>
26#include <qpe/categories.h> 28#include <qpe/categories.h>
27#include <qpe/categoryselect.h> 29#include <qpe/categoryselect.h>
30#ifdef QWS
28#include <qpe/qcopenvelope_qws.h> 31#include <qpe/qcopenvelope_qws.h>
32#endif
29#include <qpe/global.h> 33#include <qpe/global.h>
30#include <qpe/mimetype.h> 34#include <qpe/mimetype.h>
31#include <qpe/config.h> 35#include <qpe/config.h>
@@ -50,7 +54,7 @@ static int bigSize = 32;
50static QString safeFileName(const QString& n) 54static QString safeFileName(const QString& n)
51{ 55{
52 QString safename=n; 56 QString safename=n;
53 safename.replace(QRegExp("[^0-9A-Za-z.]"),"_"); // Njaard says this is broken 57 safename.replace(QRegExp("[^0-9A-Za-z.]"),"_");
54 safename.replace(QRegExp("^[^A-Za-z]*"),""); 58 safename.replace(QRegExp("^[^A-Za-z]*"),"");
55 if ( safename.isEmpty() ) 59 if ( safename.isEmpty() )
56 safename = "_"; 60 safename = "_";
@@ -71,20 +75,153 @@ static bool prepareDirectories(const QString& lf)
71class AppLnkPrivate 75class AppLnkPrivate
72{ 76{
73public: 77public:
74 QArray<int> mCat; 78 /* the size of the Pixmap */
79 enum Size {Normal = 0, Big };
80 AppLnkPrivate() {
81 /* we want one normal and one big item */
82 mPixmaps = QArray<QPixmap>(2);
83 }
84
85 QStringList mCatList; // always correct
86 QArray<int> mCat; // cached value; correct if not empty
87 QArray<QPixmap> mPixmaps;
88
89 void updateCatListFromArray()
90 {
91 Categories cat( 0 );
92 cat.load( categoryFileName() );
93 mCatList = cat.labels("Document View",mCat);
94 }
95
96 void setCatArrayDirty()
97 {
98 mCat.resize(0);
99 }
100
101 void ensureCatArray()
102 {
103 if ( mCat.count() > 0 || mCatList.count()==0 )
104 return;
105
106 Categories cat( 0 );
107 cat.load( categoryFileName() );
108 mCat.resize( mCatList.count() );
109 int i;
110 QStringList::ConstIterator it;
111 for ( i = 0, it = mCatList.begin(); it != mCatList.end();
112 ++it, i++ ) {
113
114 bool number;
115 int id = (*it).toInt( &number );
116 if ( !number ) {
117 id = cat.id( "Document View", *it );
118 if ( id == 0 )
119 id = cat.addCategory( "Document View", *it );
120 }
121 mCat[i] = id;
122 }
123 }
75}; 124};
76 125
77/*! 126/*!
78 \class AppLnk applnk.h 127 \class AppLnk applnk.h
79 \brief The AppLnk class represents an application available on the system. 128 \brief The AppLnk class represents an application available on the system.
80 129
81 Information about applications are stored in Qtopia as ".desktop" files. 130 Every Qtopia application \e app has a corresponding \e app.desktop
82 When read, these files are stored as AppLnk objects. 131 file. When one of these files is read its data is stored as an
132 AppLnk object.
133
134 The AppLnk class introduces some Qtopia-specific concepts, and
135 provides a variety of functions, as described in the following
136 sections.
137 \tableofcontents
138
139 \target Types
140 \section1 Types
141
142 Every AppLnk object has a \e type. For applications, games and
143 settings the type is \c Application; for documents the
144 type is the document's MIME type.
145
146 \target files-and-links
147 \section1 Files and Links
148
149 When you create an AppLnk (or more likely, a \link doclnk.html
150 DocLnk\endlink), you don't deal directly with filenames in the
151 filesystem. Instead you do this:
152 \code
153 DocLnk d;
154 d.setType("text/plain");
155 d.setName("My Nicely Named Document / Whatever"); // Yes, "/" is legal.
156 \endcode
157 At this point, the file() and linkFile() are unknown. Normally
158 this is uninteresting, and the names become automatically known,
159 and more importantly, becomes reserved, when you ask what they are:
160
161 \code
162 QString fn = d.file();
163 \endcode
164 This invents a filename, and creates the file on disk (an empty
165 reservation file) to prevent the name being used by another
166 application.
167
168 In some circumstances, you don't want to create the file if it
169 doesn't already exist (e.g. in the Document tab, some of the \link
170 doclnk.html DocLnk\endlink objects represented by icons are
171 DocLnk's created just for that view - they don't have
172 corresponding \c .desktop files. To avoid littering empty
173 reservation files around, we check in a few places to see whether
174 the file really needs to exist).
175
176 \section1 Functionality
177
178 AppLnk objects are created by calling the constructor with the
179 name of a \e .desktop file. The object can be checked for validity
180 using isValid().
181
182 The following functions are used to set or retrieve information
183 about the application:
184 \table
185 \header \i Get Function \i Set Function \i Short Description
186 \row \i \l name() \i \l setName() \i application's name
187 \row \i \l pixmap() \i \e none \i application's icon
188 \row \i \l bigPixmap() \i \e none \i application's large icon
189 \row \i \e none \i setIcon() \i sets the icon's filename
190 \row \i \l type() \i \l setType() \i see \link #Types Types\endlink above
191 \row \i \l rotation() \i \e none \i 0, 90, 180 or 270 degrees
192 \row \i \l comment() \i \l setComment() \i text for the Details dialog
193 \row \i \l exec() \i \l setExec() \i executable's filename
194 \row \i \l file() \i \e none \i document's filename
195 \row \i \l linkFile() \i \l setLinkFile()\i \e .desktop filename
196 \row \i \l mimeTypes() \i \e none \i the mime types the application can view or edit
197 \row \i \l categories() \i \l setCategories()\i \e{see the function descriptions}
198 \row \i \l fileKnown() \i \e none \i see \link
199#files-and-links Files and Links\endlink above
200 \row \i \l linkFileKnown() \i \e none \i see \link
201#files-and-links Files and Links\endlink above
202 \row \i \l property() \i \l setProperty()\i any AppLnk property
203 can be retrieved or set (if writeable) using these
204 \endtable
205
206 To save an AppLnk to disk use writeLink(). To execute the
207 application that the AppLnk object refers to, use execute().
208
209 AppLnk's can be deleted from disk using removeLinkFile(). To
210 remove both the link and the application's executable use
211 removeFiles().
212
213 Icon sizes can be globally changed (but only for AppLnk objects
214 created after the calls) with setSmallIconSize() and
215 setBigIconSize().
216
217 \ingroup qtopiaemb
83*/ 218*/
84 219
85/*! 220/*!
86 Sets the size used for small icons to \a small pixels. 221 Sets the size used for small icons to \a small pixels.
87 Only affects AppLnk objects created after the call. 222 Only affects AppLnk objects created after the call.
223
224 \sa smallIconSize() setIcon()
88*/ 225*/
89void AppLnk::setSmallIconSize(int small) 226void AppLnk::setSmallIconSize(int small)
90{ 227{
@@ -93,6 +230,8 @@ void AppLnk::setSmallIconSize(int small)
93 230
94/*! 231/*!
95 Returns the size used for small icons. 232 Returns the size used for small icons.
233
234 \sa setSmallIconSize() setIcon()
96*/ 235*/
97int AppLnk::smallIconSize() 236int AppLnk::smallIconSize()
98{ 237{
@@ -103,6 +242,8 @@ int AppLnk::smallIconSize()
103/*! 242/*!
104 Sets the size used for large icons to \a big pixels. 243 Sets the size used for large icons to \a big pixels.
105 Only affects AppLnk objects created after the call. 244 Only affects AppLnk objects created after the call.
245
246 \sa bigIconSize() setIcon()
106*/ 247*/
107void AppLnk::setBigIconSize(int big) 248void AppLnk::setBigIconSize(int big)
108{ 249{
@@ -111,6 +252,8 @@ void AppLnk::setBigIconSize(int big)
111 252
112/*! 253/*!
113 Returns the size used for large icons. 254 Returns the size used for large icons.
255
256 \sa setBigIconSize() setIcon()
114*/ 257*/
115int AppLnk::bigIconSize() 258int AppLnk::bigIconSize()
116{ 259{
@@ -121,23 +264,33 @@ int AppLnk::bigIconSize()
121/*! 264/*!
122 \fn QString AppLnk::name() const 265 \fn QString AppLnk::name() const
123 266
124 Returns the Name property. 267 Returns the Name property. This is the user-visible name for the
268 document or application, not the filename.
269
270 See \link #files-and-links Files and Links\endlink.
271
272 \sa setName()
125*/ 273*/
126/*! 274/*!
127 \fn QString AppLnk::exec() const 275 \fn QString AppLnk::exec() const
128 276
129 Returns the Exec property. This is the executable program associated 277 Returns the Exec property. This is the name of the executable
130 with the AppLnk. 278 program associated with the AppLnk.
279
280 \sa setExec()
131*/ 281*/
132/*! 282/*!
133 \fn QString AppLnk::rotation() const 283 \fn QString AppLnk::rotation() const
134 284
135 Returns the Rotation property. 285 Returns the Rotation property. The value is 0, 90, 180 or 270
286 degrees.
136*/ 287*/
137/*! 288/*!
138 \fn QString AppLnk::comment() const 289 \fn QString AppLnk::comment() const
139 290
140 Returns the Comment property. 291 Returns the Comment property.
292
293 \sa setComment()
141*/ 294*/
142/*! 295/*!
143 \fn QStringList AppLnk::mimeTypes() const 296 \fn QStringList AppLnk::mimeTypes() const
@@ -149,10 +302,15 @@ int AppLnk::bigIconSize()
149 \fn const QArray<int>& AppLnk::categories() const 302 \fn const QArray<int>& AppLnk::categories() const
150 303
151 Returns the Categories property. 304 Returns the Categories property.
305
306 See the CategoryWidget for more details.
307
308 \sa setCategories()
152*/ 309*/
153 310
154const QArray<int>& AppLnk::categories() const 311const QArray<int>& AppLnk::categories() const
155{ 312{
313 d->ensureCatArray();
156 return d->mCat; 314 return d->mCat;
157} 315}
158 316
@@ -162,12 +320,14 @@ const QArray<int>& AppLnk::categories() const
162 Returns the id of the AppLnk. If the AppLnk is not in an AppLnkSet, 320 Returns the id of the AppLnk. If the AppLnk is not in an AppLnkSet,
163 this value is 0, otherwise it is a value that is unique for the 321 this value is 0, otherwise it is a value that is unique for the
164 duration of the current process. 322 duration of the current process.
323
324 \sa AppLnkSet::find()
165*/ 325*/
166 326
167/*! 327/*!
168 \fn bool AppLnk::isValid() const 328 \fn bool AppLnk::isValid() const
169 329
170 Returns whether this AppLnk is valid. 330 Returns TRUE if this AppLnk is valid; otherwise returns FALSE.
171*/ 331*/
172 332
173/*! 333/*!
@@ -182,7 +342,9 @@ AppLnk::AppLnk()
182} 342}
183 343
184/*! 344/*!
185 Loads \a file as an AppLnk. 345 Loads \a file (e.g. \e app.desktop) as an AppLnk.
346
347 \sa writeLink()
186*/ 348*/
187AppLnk::AppLnk( const QString &file ) 349AppLnk::AppLnk( const QString &file )
188{ 350{
@@ -200,89 +362,150 @@ AppLnk::AppLnk( const QString &file )
200 mIconFile = config.readEntry( "Icon", QString::null ); 362 mIconFile = config.readEntry( "Icon", QString::null );
201 mRotation = config.readEntry( "Rotation", "" ); 363 mRotation = config.readEntry( "Rotation", "" );
202 mComment = config.readEntry( "Comment", QString::null ); 364 mComment = config.readEntry( "Comment", QString::null );
365 // MIME types are case-insensitive.
203 mMimeTypes = config.readListEntry( "MimeType", ';' ); 366 mMimeTypes = config.readListEntry( "MimeType", ';' );
367 for (QStringList::Iterator it=mMimeTypes.begin(); it!=mMimeTypes.end(); ++it)
368 *it = (*it).lower();
204 mMimeTypeIcons = config.readListEntry( "MimeTypeIcons", ';' ); 369 mMimeTypeIcons = config.readListEntry( "MimeTypeIcons", ';' );
205 mLinkFile = file; 370 mLinkFile = file;
206 mFile = config.readEntry("File", QString::null); 371 mFile = config.readEntry("File", QString::null);
207 sl = config.readListEntry("Categories", ';'); 372 if ( mFile[0] != '/' ) {
208 } 373 int slash = file.findRev('/');
209 } 374 if ( slash >= 0 ) {
210 // let's try our darndest to create categories... 375 mFile = file.left(slash) + '/' + mFile;
211 Categories cat( 0 ); 376 }
212 cat.load( categoryFileName() ); 377 }
213 d->mCat.resize( sl.count() ); 378 d->mCatList = config.readListEntry("Categories", ';');
214 int i; 379 if ( d->mCatList[0].toInt() < -1 ) {
215 QStringList::Iterator it; 380 // numeric cats in file! convert to text
216 for ( i = 0, it = sl.begin(); it != sl.end(); 381 Categories cat( 0 );
217 ++it, i++ ) { 382 cat.load( categoryFileName() );
218 383 d->mCat.resize( d->mCatList.count() );
219 bool number; 384 int i;
220 int id = (*it).toInt( &number ); 385 QStringList::ConstIterator it;
221 if ( !number ) { 386 for ( i = 0, it = d->mCatList.begin(); it != d->mCatList.end();
222 // convert from old school... 387 ++it, i++ ) {
223 id = cat.id( "Document Viewer", *it ); 388 bool number;
224 if ( id == 0 ) 389 int id = (*it).toInt( &number );
225 id = cat.addCategory( "Document Viewer", *it ); 390 if ( !number ) {
391 // convert from text
392 id = cat.id( "Document View", *it );
393 if ( id == 0 )
394 id = cat.addCategory( "Document View", *it );
395 }
396 d->mCat[i] = id;
397 }
398 d->updateCatListFromArray();
399 }
226 } 400 }
227 d->mCat[i] = id;
228 } 401 }
229 mId = 0; 402 mId = 0;
230} 403}
231 404
405AppLnk& AppLnk::operator=(const AppLnk &copy)
406{
407 if ( mId )
408 qWarning("Deleting AppLnk that is in an AppLnkSet");
409 if ( d )
410 delete d;
411
412
413 mName = copy.mName;
414
415 /* remove for Qtopia 3.0 -zecke */
416 mPixmap = copy.mPixmap;
417 mBigPixmap = copy.mBigPixmap;
418
419 mExec = copy.mExec;
420 mType = copy.mType;
421 mRotation = copy.mRotation;
422 mComment = copy.mComment;
423 mFile = copy.mFile;
424 mLinkFile = copy.mLinkFile;
425 mIconFile = copy.mIconFile;
426 mMimeTypes = copy.mMimeTypes;
427 mMimeTypeIcons = copy.mMimeTypeIcons;
428 mId = 0;
429 d = new AppLnkPrivate();
430 d->mCat = copy.d->mCat;
431 d->mCatList = copy.d->mCatList;
432 d->mPixmaps = copy.d->mPixmaps;
433
434 return *this;
435}
232/*! 436/*!
233 Returns a small pixmap associated with the application. 437 protected internally to share code
438 should I document that at all?
439 I don't know the TT style for that
234*/ 440*/
235const QPixmap& AppLnk::pixmap() const 441const QPixmap& AppLnk::pixmap( int pos, int size ) const {
236{ 442 if ( d->mPixmaps[pos].isNull() ) {
237 if ( mPixmap.isNull() ) {
238 AppLnk* that = (AppLnk*)this; 443 AppLnk* that = (AppLnk*)this;
239 if ( mIconFile.isEmpty() ) { 444 if ( mIconFile.isEmpty() ) {
240 MimeType mt(type()); 445 MimeType mt(type());
241 that->mPixmap = mt.pixmap(); 446 that->d->mPixmaps[pos] = mt.pixmap();
242 if ( that->mPixmap.isNull() ) 447 if ( that->d->mPixmaps[pos].isNull() )
243 that->mPixmap = Resource::loadPixmap("UnknownDocument-14"); 448 that->d->mPixmaps[pos].convertFromImage(
244 return that->mPixmap; 449 Resource::loadImage("UnknownDocument")
450 .smoothScale( size, size ) );
451 return that->d->mPixmaps[pos];
245 } 452 }
246 QImage unscaledIcon = Resource::loadImage( that->mIconFile ); 453 QImage unscaledIcon = Resource::loadImage( that->mIconFile );
247 that->mPixmap.convertFromImage( unscaledIcon.smoothScale( smallSize, smallSize ) ); 454 if ( unscaledIcon.isNull() ) {
248 that->mBigPixmap.convertFromImage( unscaledIcon.smoothScale( bigSize, bigSize ) ); 455 qDebug( "Cannot find icon: %s", that->mIconFile.latin1() );
249 return that->mPixmap; 456 that->d->mPixmaps[pos].convertFromImage(
457 Resource::loadImage("UnknownDocument")
458 .smoothScale( size, size ) );
459 } else {
460 that->d->mPixmaps[0].convertFromImage( unscaledIcon.smoothScale( smallSize, smallSize ) );
461 that->d->mPixmaps[1].convertFromImage( unscaledIcon.smoothScale( bigSize, bigSize ) );
462 }
463 return that->d->mPixmaps[0];
250 } 464 }
251 return mPixmap; 465 return mPixmap;
252} 466}
253 467
254/*! 468/*!
469 Returns a small pixmap associated with the application.
470
471 \sa bigPixmap() setIcon()
472*/
473const QPixmap& AppLnk::pixmap() const
474{
475 if ( d->mPixmaps[0].isNull() ) {
476 return pixmap(AppLnkPrivate::Normal, smallSize );
477 }
478 return d->mPixmaps[0];
479}
480
481/*!
255 Returns a large pixmap associated with the application. 482 Returns a large pixmap associated with the application.
483
484 \sa pixmap() setIcon()
256*/ 485*/
257const QPixmap& AppLnk::bigPixmap() const 486const QPixmap& AppLnk::bigPixmap() const
258{ 487{
259 if ( mBigPixmap.isNull() ) { 488 if ( d->mPixmaps[1].isNull() ) {
260 AppLnk* that = (AppLnk*)this; 489 return pixmap( AppLnkPrivate::Big, bigSize );
261 if ( mIconFile.isEmpty() ) {
262 MimeType mt(type());
263 that->mBigPixmap = mt.bigPixmap();
264 if ( that->mBigPixmap.isNull() )
265 that->mBigPixmap = Resource::loadPixmap("UnknownDocument");
266 return that->mBigPixmap;
267 }
268 QImage unscaledIcon = Resource::loadImage( that->mIconFile );
269 that->mPixmap.convertFromImage( unscaledIcon.smoothScale( smallSize, smallSize ) );
270 that->mBigPixmap.convertFromImage( unscaledIcon.smoothScale( bigSize, bigSize ) );
271 return that->mBigPixmap;
272 } 490 }
273 return mBigPixmap; 491 return mBigPixmap;
274} 492}
275 493
276/*! 494/*!
277 Returns the type of the application. 495 Returns the type of the AppLnk. For applications, games and
496 settings the type is \c Application; for documents the type is the
497 document's MIME type.
278*/ 498*/
279QString AppLnk::type() const 499QString AppLnk::type() const
280{ 500{
281 if ( mType.isNull() ) { 501 if ( mType.isNull() ) {
282 AppLnk* that = (AppLnk*)this; 502 AppLnk* that = (AppLnk*)this;
283 MimeType mt(file()); 503 QString f = file();
284 that->mType = mt.id(); 504 if ( !f.isNull() ) {
285 return that->mType; 505 MimeType mt(f);
506 that->mType = mt.id();
507 return that->mType;
508 }
286 } 509 }
287 return mType; 510 return mType;
288} 511}
@@ -290,12 +513,12 @@ QString AppLnk::type() const
290/*! 513/*!
291 Returns the file associated with the AppLnk. 514 Returns the file associated with the AppLnk.
292 515
293 \sa exec() 516 \sa exec() name()
294*/ 517*/
295QString AppLnk::file() const 518QString AppLnk::file() const
296{ 519{
297 if ( mFile.isNull() ) { 520 if ( mFile.isNull() ) {
298 AppLnk* that = (AppLnk*)this; // copy? 521 AppLnk* that = (AppLnk*)this;
299 QString ext = MimeType(mType).extension(); 522 QString ext = MimeType(mType).extension();
300 if ( !ext.isEmpty() ) 523 if ( !ext.isEmpty() )
301 ext = "." + ext; 524 ext = "." + ext;
@@ -306,32 +529,35 @@ QString AppLnk::file() const
306 } else if ( mType.contains('/') ) { 529 } else if ( mType.contains('/') ) {
307 that->mFile = 530 that->mFile =
308 QString(getenv("HOME"))+"/Documents/"+mType+"/"+safeFileName(that->mName); 531 QString(getenv("HOME"))+"/Documents/"+mType+"/"+safeFileName(that->mName);
309 if ( QFile::exists(that->mFile+ext) || QFile::exists(that->mFile+".desktop") ) { // a .desktop with the same name exists 532 /*
533 * A file with the same name or a .desktop file already exists
534 */
535 if ( QFile::exists(that->mFile+ext) || QFile::exists(that->mFile+".desktop") ) {
310 int n=1; 536 int n=1;
311 qWarning("AppLnk::file() n=1 %s", that->mFile.latin1() );
312 QString nn; 537 QString nn;
313 while (QFile::exists((nn=(that->mFile+"_"+QString::number(n)))+ext) 538 while (QFile::exists((nn=(that->mFile+"_"+QString::number(n)))+ext)
314 || QFile::exists(nn+".desktop")) 539 || QFile::exists(nn+".desktop"))
315 n++; 540 n++;
316 that->mFile = nn; 541 that->mFile = nn;
317 qWarning("AppLnl::file() now mFile is %s", that->mFile.latin1() );
318 } 542 }
319 that->mLinkFile = that->mFile+".desktop"; 543 that->mLinkFile = that->mFile+".desktop";
320 that->mFile += ext; 544 that->mFile += ext;
321 } 545 }
322 prepareDirectories(that->mFile); 546 prepareDirectories(that->mFile);
323 QFile f(that->mFile); 547 if ( !that->mFile.isEmpty() ) {
324 if ( !f.open(IO_WriteOnly) ) 548 QFile f(that->mFile);
325 that->mFile = QString::null; 549 if ( !f.open(IO_WriteOnly) )
326 return that->mFile; 550 that->mFile = QString::null;
551 return that->mFile;
552 }
327 } 553 }
328 return mFile; 554 return mFile;
329} 555}
330 556
331/*! 557/*!
332 Returns the desktop file coresponding to this AppLnk. 558 Returns the desktop file corresponding to this AppLnk.
333 559
334 \sa file(), exec() 560 \sa file() exec() name()
335*/ 561*/
336QString AppLnk::linkFile() const 562QString AppLnk::linkFile() const
337{ 563{
@@ -340,29 +566,34 @@ QString AppLnk::linkFile() const
340 if ( type().contains('/') ) { 566 if ( type().contains('/') ) {
341 StorageInfo storage; 567 StorageInfo storage;
342 const FileSystem *fs = storage.fileSystemOf( that->mFile ); 568 const FileSystem *fs = storage.fileSystemOf( that->mFile );
343 if ( fs && ( fs->isRemovable() || fs->disk() == "/dev/mtdblock6" || fs->disk() == "tmpfs" ) ) { 569 /* tmpfs + and ramfs are available too but not removable
570 * either we fix storage or add this
571 */
572 if ( fs && ( fs->isRemovable() || fs->disk() == "/dev/mtdblock6" || fs->disk() == "tmpfs") ) {
344 that->mLinkFile = fs->path(); 573 that->mLinkFile = fs->path();
345 } else 574 } else
346 that->mLinkFile = getenv( "HOME" ); 575 that->mLinkFile = getenv( "HOME" );
347 that->mLinkFile += "/Documents/"+type()+"/"+safeFileName(that->mName); 576 that->mLinkFile += "/Documents/"+type()+"/"+safeFileName(that->mName);
348 if ( QFile::exists(that->mLinkFile+".desktop") ) { // ok the file exists lets check if we point to the same file 577
349 int n=1; 578 /* the desktop file exists make sure we don't point to the same file */
350 QString nn; 579 if ( QFile::exists(that->mLinkFile+".desktop") ) {
351 AppLnk lnk( that->mLinkFile+".desktop" ); 580 AppLnk lnk( that->mLinkFile + ".desktop" );
352 if(that->file() != lnk.file() ){ 581
353 qWarning("AppLnk::linkFile exists %s", that->mLinkFile.latin1() ); 582 /* the linked is different */
354 while (QFile::exists((nn=that->mLinkFile+"_"+QString::number(n))+".desktop")){ 583 if(that->file() != lnk.file() ) {
355 n++; 584 int n = 1;
356 AppLnk lnk(nn ); // just to be sure 585 QString nn;
357 if(lnk.file() ==that->file() ){ 586 while (QFile::exists((nn=that->mLinkFile+"_"+QString::number(n))+".desktop")) {
358 break; 587 n++;
359 } 588 /* just to be sure */
360 } 589 AppLnk lnk(nn );
361 that->mLinkFile = nn; 590 if (lnk.file() == that->file() )
362 } 591 break;
592 }
593 that->mLinkFile = nn;
594 }
363 } 595 }
364 that->mLinkFile += ".desktop"; 596 that->mLinkFile += ".desktop";
365 qWarning("AppLnk::linkFile is %s", that->mLinkFile.latin1() );
366 storeLink(); 597 storeLink();
367 } 598 }
368 return that->mLinkFile; 599 return that->mLinkFile;
@@ -390,13 +621,15 @@ AppLnk::AppLnk( const AppLnk &copy )
390 mId = 0; 621 mId = 0;
391 d = new AppLnkPrivate(); 622 d = new AppLnkPrivate();
392 d->mCat = copy.d->mCat; 623 d->mCat = copy.d->mCat;
624 d->mCatList = copy.d->mCatList;
625 d->mPixmaps = copy.d->mPixmaps;
393} 626}
394 627
395/*! 628/*!
396 Destroys the AppLnk. Note that if the AppLnk is current a member of 629 Destroys the AppLnk. Note that if the AppLnk is currently a member
397 an AppLnkSet, this will produce a run-time warning. 630 of an AppLnkSet, this will produce a run-time warning.
398 631
399 \sa AppLnkSet::add(), AppLnkSet::remove() 632 \sa AppLnkSet::add() AppLnkSet::remove()
400*/ 633*/
401AppLnk::~AppLnk() 634AppLnk::~AppLnk()
402{ 635{
@@ -407,7 +640,10 @@ AppLnk::~AppLnk()
407} 640}
408 641
409/*! 642/*!
643 \overload
410 Executes the application associated with this AppLnk. 644 Executes the application associated with this AppLnk.
645
646 \sa exec()
411*/ 647*/
412void AppLnk::execute() const 648void AppLnk::execute() const
413{ 649{
@@ -417,6 +653,8 @@ void AppLnk::execute() const
417/*! 653/*!
418 Executes the application associated with this AppLnk, with 654 Executes the application associated with this AppLnk, with
419 \a args as arguments. 655 \a args as arguments.
656
657 \sa exec()
420*/ 658*/
421void AppLnk::execute(const QStringList& args) const 659void AppLnk::execute(const QStringList& args) const
422{ 660{
@@ -437,7 +675,7 @@ void AppLnk::execute(const QStringList& args) const
437/*! 675/*!
438 Invokes the application associated with this AppLnk, with 676 Invokes the application associated with this AppLnk, with
439 \a args as arguments. Rotation is not taken into account by 677 \a args as arguments. Rotation is not taken into account by
440 this function, you should not call it directly. 678 this function, so you should not call it directly.
441 679
442 \sa execute() 680 \sa execute()
443*/ 681*/
@@ -449,7 +687,7 @@ void AppLnk::invoke(const QStringList& args) const
449/*! 687/*!
450 Sets the Exec property to \a exec. 688 Sets the Exec property to \a exec.
451 689
452 \sa exec() 690 \sa exec() name()
453*/ 691*/
454void AppLnk::setExec( const QString& exec ) 692void AppLnk::setExec( const QString& exec )
455{ 693{
@@ -469,7 +707,7 @@ void AppLnk::setName( const QString& docname )
469/*! 707/*!
470 Sets the File property to \a filename. 708 Sets the File property to \a filename.
471 709
472 \sa file() 710 \sa file() name()
473*/ 711*/
474void AppLnk::setFile( const QString& filename ) 712void AppLnk::setFile( const QString& filename )
475{ 713{
@@ -489,6 +727,9 @@ void AppLnk::setLinkFile( const QString& filename )
489/*! 727/*!
490 Sets the Comment property to \a comment. 728 Sets the Comment property to \a comment.
491 729
730 This text is displayed in the 'Details Dialog', for example if the
731 user uses the 'press-and-hold' gesture.
732
492 \sa comment() 733 \sa comment()
493*/ 734*/
494void AppLnk::setComment( const QString& comment ) 735void AppLnk::setComment( const QString& comment )
@@ -499,6 +740,10 @@ void AppLnk::setComment( const QString& comment )
499/*! 740/*!
500 Sets the Type property to \a type. 741 Sets the Type property to \a type.
501 742
743 For applications, games and settings the type should be \c
744 Application; for documents the type should be the document's MIME
745 type.
746
502 \sa type() 747 \sa type()
503*/ 748*/
504void AppLnk::setType( const QString& type ) 749void AppLnk::setType( const QString& type )
@@ -507,26 +752,38 @@ void AppLnk::setType( const QString& type )
507} 752}
508 753
509/*! 754/*!
510 Sets the Icon property to \a iconname. 755 \fn QString AppLnk::icon() const
756
757 Returns the Icon property.
758
759 \sa setIcon()
760*/
761
762/*!
763 Sets the Icon property to \a iconname. This is the filename from
764 which the pixmap() and bigPixmap() are obtained.
511 765
512 \sa pixmap(), bigPixmap() 766 \sa icon() setSmallIconSize() setBigIconSize()
513*/ 767*/
514void AppLnk::setIcon( const QString& iconname ) 768void AppLnk::setIcon( const QString& iconname )
515{ 769{
516 mIconFile = iconname; 770 mIconFile = iconname;
517 QImage unscaledIcon = Resource::loadImage( mIconFile ); 771 QImage unscaledIcon = Resource::loadImage( mIconFile );
518 mPixmap.convertFromImage( unscaledIcon.smoothScale( smallSize, smallSize ) ); 772 d->mPixmaps[0].convertFromImage( unscaledIcon.smoothScale( smallSize, smallSize ) );
519 mBigPixmap.convertFromImage( unscaledIcon.smoothScale( bigSize, bigSize ) ); 773 d->mPixmaps[1].convertFromImage( unscaledIcon.smoothScale( bigSize, bigSize ) );
520} 774}
521 775
522/*! 776/*!
523 Sets the Categories property to \a c. 777 Sets the Categories property to \a c.
524 778
779 See the CategoryWidget for more details.
780
525 \sa categories() 781 \sa categories()
526*/ 782*/
527void AppLnk::setCategories( const QArray<int>& c ) 783void AppLnk::setCategories( const QArray<int>& c )
528{ 784{
529 d->mCat = c; 785 d->mCat = c;
786 d->updateCatListFromArray();
530} 787}
531 788
532/*! 789/*!
@@ -536,8 +793,11 @@ void AppLnk::setCategories( const QArray<int>& c )
536*/ 793*/
537 794
538/*! 795/*!
539 Attempts to ensure that the link file for this AppLnk exists, including 796 Attempts to ensure that the link file for this AppLnk exists,
540 creating any required directories. Returns TRUE if successful. 797 including creating any required directories. Returns TRUE if
798 successful; otherwise returns FALSE.
799
800 You should not need to use this function.
541*/ 801*/
542bool AppLnk::ensureLinkExists() const 802bool AppLnk::ensureLinkExists() const
543{ 803{
@@ -546,10 +806,11 @@ bool AppLnk::ensureLinkExists() const
546} 806}
547 807
548/*! 808/*!
549 Commits the AppLnk to disk. Returns whether the operation succeeded. 809 Commits the AppLnk to disk. Returns TRUE if the operation succeeded;
810 otherwise returns FALSE.
550 811
551 The "linkChanged(QString)" message is sent to the 812 In addition, the "linkChanged(QString)" message is sent to the
552 "QPE/System" QCop channel as a result. 813 "QPE/System" \link qcop.html QCop\endlink channel.
553*/ 814*/
554bool AppLnk::writeLink() const 815bool AppLnk::writeLink() const
555{ 816{
@@ -561,6 +822,9 @@ bool AppLnk::writeLink() const
561 return TRUE; 822 return TRUE;
562} 823}
563 824
825/*!
826 \internal
827*/
564void AppLnk::storeLink() const 828void AppLnk::storeLink() const
565{ 829{
566 Config config( mLinkFile, Config::File ); 830 Config config( mLinkFile, Config::File );
@@ -569,21 +833,29 @@ void AppLnk::storeLink() const
569 if ( !mIconFile.isNull() ) config.writeEntry("Icon",mIconFile); 833 if ( !mIconFile.isNull() ) config.writeEntry("Icon",mIconFile);
570 config.writeEntry("Type",type()); 834 config.writeEntry("Type",type());
571 if ( !mComment.isNull() ) config.writeEntry("Comment",mComment); 835 if ( !mComment.isNull() ) config.writeEntry("Comment",mComment);
572 config.writeEntry("File",file()); 836 QString f = file();
573 // write out the id... 837 int i = 0;
574 int i; 838 while ( i < (int)f.length() && i < (int)mLinkFile.length() && f[i] == mLinkFile[i] )
575 QStringList sl; 839 i++;
576 for ( i = 0; i < int(d->mCat.count()); i++ ) { 840 while ( i && f[i] != '/' )
577 sl.append( QString::number( d->mCat[i] ) ); 841 i--;
578 } 842 // simple case where in the same directory
579 config.writeEntry( "Categories", sl, ';' ); 843 if ( mLinkFile.find( '/', i + 1 ) < 0 )
580 844 f = f.mid(i+1);
845 // ### could do relative ie ../../otherDocs/file.doc
846 config.writeEntry("File",f);
847 config.writeEntry( "Categories", d->mCatList, ';' );
848
849#ifndef QT_NO_COP
581 QCopEnvelope e("QPE/System", "linkChanged(QString)"); 850 QCopEnvelope e("QPE/System", "linkChanged(QString)");
582 e << mLinkFile; 851 e << mLinkFile;
852#endif
583} 853}
584 854
585/*! 855/*!
586 Sets the property named \a key to \a value. 856 Sets the property named \a key to \a value.
857
858 \sa property()
587*/ 859*/
588void AppLnk::setProperty(const QString& key, const QString& value) 860void AppLnk::setProperty(const QString& key, const QString& value)
589{ 861{
@@ -595,6 +867,8 @@ void AppLnk::setProperty(const QString& key, const QString& value)
595 867
596/*! 868/*!
597 Returns the property named \a key. 869 Returns the property named \a key.
870
871 \sa setProperty()
598*/ 872*/
599QString AppLnk::property(const QString& key) const 873QString AppLnk::property(const QString& key) const
600{ 874{
@@ -605,7 +879,6 @@ QString AppLnk::property(const QString& key) const
605 return cfg.readEntry(key); 879 return cfg.readEntry(key);
606} 880}
607 881
608
609bool AppLnk::isPreloaded() const { 882bool AppLnk::isPreloaded() const {
610 // Preload information is stored in the Launcher config in v1.5. 883 // Preload information is stored in the Launcher config in v1.5.
611 Config cfg("Launcher"); 884 Config cfg("Launcher");
@@ -630,18 +903,22 @@ void AppLnk::setPreloaded(bool yesNo) {
630 903
631 904
632/*! 905/*!
633 Deletes both the linkFile() and file() associated with this AppLnk. 906 Deletes both the linkFile() and the file() associated with this AppLnk.
907
908 \sa removeLinkFile()
634*/ 909*/
635void AppLnk::removeFiles() 910void AppLnk::removeFiles()
636{ 911{
637 bool valid = isValid(); 912 bool valid = isValid();
638 if ( !valid || !linkFileKnown() || QFile::remove(linkFile()) ) { 913 if ( !valid || !linkFileKnown() || QFile::remove(linkFile()) ) {
639 if ( QFile::remove(file()) ) { 914 if ( QFile::remove(file()) ) {
915#ifndef QT_NO_COP
640 QCopEnvelope e("QPE/System", "linkChanged(QString)"); 916 QCopEnvelope e("QPE/System", "linkChanged(QString)");
641 if ( linkFileKnown() ) 917 if ( linkFileKnown() )
642 e << linkFile(); 918 e << linkFile();
643 else 919 else
644 e << file(); 920 e << file();
921#endif
645 } else if ( valid ) { 922 } else if ( valid ) {
646 // restore link 923 // restore link
647 writeLink(); 924 writeLink();
@@ -650,13 +927,17 @@ void AppLnk::removeFiles()
650} 927}
651 928
652/*! 929/*!
653 Delete the linkFile(), leaving any file() untouched. 930 Deletes the linkFile(), leaving any file() untouched.
931
932 \sa removeFiles()
654*/ 933*/
655void AppLnk::removeLinkFile() 934void AppLnk::removeLinkFile()
656{ 935{
657 if ( isValid() && linkFileKnown() && QFile::remove(linkFile()) ) { 936 if ( isValid() && linkFileKnown() && QFile::remove(linkFile()) ) {
937#ifndef QT_NO_COP
658 QCopEnvelope e("QPE/System", "linkChanged(QString)"); 938 QCopEnvelope e("QPE/System", "linkChanged(QString)");
659 e << linkFile(); 939 e << linkFile();
940#endif
660 } 941 }
661} 942}
662 943
@@ -682,7 +963,10 @@ public:
682/*! 963/*!
683 \fn QStringList AppLnkSet::types() const 964 \fn QStringList AppLnkSet::types() const
684 965
685 Returns the list of types in the set. 966 Returns the list of \link applnk.html#Types types\endlink in the set.
967
968 For applications, games and settings the type is \c Application;
969 for documents the type is the document's MIME type.
686 970
687 \sa AppLnk::type(), typeName(), typePixmap(), typeBigPixmap() 971 \sa AppLnk::type(), typeName(), typePixmap(), typeBigPixmap()
688*/ 972*/
@@ -703,11 +987,14 @@ AppLnkSet::AppLnkSet() :
703 987
704/*! 988/*!
705 Constructs an AppLnkSet that contains AppLnk objects representing 989 Constructs an AppLnkSet that contains AppLnk objects representing
706 all the files in a \a directory (recursively). 990 all the files in the given \a directory (and any subdirectories
991 recursively).
707 992
708 The directories may contain ".directory" files which overrides 993 \omit
709 any AppLnk::type() value of AppLnk objects found in the directory. 994 The directories may contain ".directory" files which override
995 any AppLnk::type() values for AppLnk objects found in the directory.
710 This allows simple localization of application types. 996 This allows simple localization of application types.
997 \endomit
711*/ 998*/
712AppLnkSet::AppLnkSet( const QString &directory ) : 999AppLnkSet::AppLnkSet( const QString &directory ) :
713 d(new AppLnkSetPrivate) 1000 d(new AppLnkSetPrivate)
@@ -718,8 +1005,8 @@ AppLnkSet::AppLnkSet( const QString &directory ) :
718} 1005}
719 1006
720/*! 1007/*!
721 Detaches all AppLnk objects from the set. The set become empty 1008 Detaches all AppLnk objects from the set. The set become empty and
722 and the call becomes responsible for deleting the AppLnk objects. 1009 the caller becomes responsible for deleting the AppLnk objects.
723*/ 1010*/
724void AppLnkSet::detachChildren() 1011void AppLnkSet::detachChildren()
725{ 1012{
@@ -733,7 +1020,7 @@ void AppLnkSet::detachChildren()
733} 1020}
734 1021
735/*! 1022/*!
736 Destroys the set, deleting all AppLnk objects it contains. 1023 Destroys the set, deleting all the AppLnk objects it contains.
737 1024
738 \sa detachChildren() 1025 \sa detachChildren()
739*/ 1026*/
@@ -811,7 +1098,8 @@ void AppLnkSet::findChildren(const QString &dr, const QString& typ, const QStrin
811} 1098}
812 1099
813/*! 1100/*!
814 Adds \a f to the set. The set takes over responsibility for deleting \a f. 1101 Adds AppLnk \a f to the set. The set takes responsibility for
1102 deleting \a f.
815 1103
816 \sa remove() 1104 \sa remove()
817*/ 1105*/
@@ -827,8 +1115,9 @@ void AppLnkSet::add( AppLnk *f )
827} 1115}
828 1116
829/*! 1117/*!
830 Removes \a f to the set, returning whether \a f was in the set. 1118 Removes AppLnk \a f to the set. The caller becomes responsible for
831 The caller becomes responsible for deleting \a f. 1119 deleting \a f. Returns TRUE if \a f was in the set; otherwise
1120 returns FALSE.
832 1121
833 \sa add() 1122 \sa add()
834*/ 1123*/
@@ -841,8 +1130,12 @@ bool AppLnkSet::remove( AppLnk *f )
841 return FALSE; 1130 return FALSE;
842} 1131}
843 1132
1133
844/*! 1134/*!
845 Returns the localized name for type \a t. 1135 Returns the localized name for type \a t.
1136
1137 For applications, games and settings the type is \c Application;
1138 for documents the type is the document's MIME type.
846*/ 1139*/
847QString AppLnkSet::typeName( const QString& t ) const 1140QString AppLnkSet::typeName( const QString& t ) const
848{ 1141{
@@ -852,6 +1145,9 @@ QString AppLnkSet::typeName( const QString& t ) const
852 1145
853/*! 1146/*!
854 Returns the small pixmap associated with type \a t. 1147 Returns the small pixmap associated with type \a t.
1148
1149 For applications, games and settings the type is \c Application;
1150 for documents the type is the document's MIME type.
855*/ 1151*/
856QPixmap AppLnkSet::typePixmap( const QString& t ) const 1152QPixmap AppLnkSet::typePixmap( const QString& t ) const
857{ 1153{
@@ -861,6 +1157,9 @@ QPixmap AppLnkSet::typePixmap( const QString& t ) const
861 1157
862/*! 1158/*!
863 Returns the large pixmap associated with type \a t. 1159 Returns the large pixmap associated with type \a t.
1160
1161 For applications, games and settings the type is \c Application;
1162 for documents the type is the document's MIME type.
864*/ 1163*/
865QPixmap AppLnkSet::typeBigPixmap( const QString& t ) const 1164QPixmap AppLnkSet::typeBigPixmap( const QString& t ) const
866{ 1165{
@@ -921,13 +1220,16 @@ DocLnkSet::DocLnkSet()
921} 1220}
922 1221
923/*! 1222/*!
924 Constructs an DocLnkSet that contains DocLnk objects representing 1223 Constructs a DocLnkSet that contains DocLnk objects representing all
925 all the files in a \a directory (recursively). 1224 the files in the \a directory (and any subdirectories, recursively).
926 1225
927 If \a mimefilter is not null, 1226 If \a mimefilter is not null,
928 only documents with a MIME type matching \a mimefilter are selected. 1227 only documents with a MIME type matching \a mimefilter are selected.
929 The value may contain multiple wild-card patterns separated by ";", 1228 The value may contain multiple wild-card patterns separated by ";",
930 such as "*o/mpeg;audio/x-wav". 1229 such as \c{*o/mpeg;audio/x-wav}.
1230
1231 See also \link applnk.html#files-and-links Files and Links\endlink.
1232
931*/ 1233*/
932DocLnkSet::DocLnkSet( const QString &directory, const QString& mimefilter ) : 1234DocLnkSet::DocLnkSet( const QString &directory, const QString& mimefilter ) :
933 AppLnkSet() 1235 AppLnkSet()
@@ -996,14 +1298,22 @@ void DocLnkSet::findChildren(const QString &dr, const QValueList<QRegExp> &mimeF
996 1298
997 QDir dir( dr ); 1299 QDir dir( dr );
998 1300
1301 /* Opie got a different approach
1302 * I guess it's geek vs. consumer
1303 * in this case to be discussed
1304 */
1305 if ( dir.exists( ".Qtopia-ignore" ) )
1306 return;
1307
999 const QFileInfoList *list = dir.entryInfoList(); 1308 const QFileInfoList *list = dir.entryInfoList();
1000 if ( list ) { 1309 if ( list ) {
1001 QFileInfo* fi; 1310 QFileInfo* fi;
1002 for ( QFileInfoListIterator it(*list); (fi=*it); ++it ) { 1311 for ( QFileInfoListIterator it(*list); (fi=*it); ++it ) {
1003 QString bn = fi->fileName(); 1312 QString bn = fi->fileName();
1004 if ( bn[0] != '.' && bn != "CVS" ) { 1313 if ( bn[0] != '.' ) {
1005 if ( fi->isDir() ) { 1314 if ( fi->isDir() ) {
1006 findChildren(fi->filePath(), mimeFilters, reference, depth); 1315 if ( bn != "CVS" && bn != "Qtopia" && bn != "QtPalmtop" )
1316 findChildren(fi->filePath(), mimeFilters, reference, depth);
1007 } else { 1317 } else {
1008 if ( fi->extension(FALSE) == "desktop" ) { 1318 if ( fi->extension(FALSE) == "desktop" ) {
1009 DocLnk* dl = new DocLnk( fi->filePath() ); 1319 DocLnk* dl = new DocLnk( fi->filePath() );
@@ -1058,8 +1368,9 @@ DocLnk::DocLnk( const QString &file ) :
1058 1368
1059/*! 1369/*!
1060 Constructs a DocLnk from a valid .desktop \a file or a new .desktop 1370 Constructs a DocLnk from a valid .desktop \a file or a new .desktop
1061 \a file for other files. If \a may_be_desktopfile is TRUE, then \a file 1371 \a file for other files. If \a may_be_desktopfile is TRUE, then an
1062 is first attempted to be read as a .desktop file. 1372 attempt is made to read \a file as a .desktop file; if that fails it
1373 is read as a normal file.
1063*/ 1374*/
1064DocLnk::DocLnk( const QString &file, bool may_be_desktopfile ) : 1375DocLnk::DocLnk( const QString &file, bool may_be_desktopfile ) :
1065 AppLnk(may_be_desktopfile ? file : QString::null) 1376 AppLnk(may_be_desktopfile ? file : QString::null)
@@ -1088,8 +1399,8 @@ void DocLnk::init(const QString &file)
1088 } 1399 }
1089 } else if ( QFile::exists(file) ) { 1400 } else if ( QFile::exists(file) ) {
1090 QString n = file; 1401 QString n = file;
1091 n.replace(QRegExp("\\..*"),"");
1092 n.replace(QRegExp(".*/"),""); 1402 n.replace(QRegExp(".*/"),"");
1403 n.replace(QRegExp("\\..*"),"");
1093 setName( n ); 1404 setName( n );
1094 setFile( file ); 1405 setFile( file );
1095 } 1406 }
@@ -1106,7 +1417,7 @@ DocLnk::DocLnk()
1106} 1417}
1107 1418
1108/*! 1419/*!
1109 Destroys the DocLnk. As with AppLnk objects, a run-time error 1420 Destroys the DocLnk. Just like AppLnk objects, a run-time error
1110 occurs if the DocLnk is a member of a DocLnkSet (or AppLnkSet). 1421 occurs if the DocLnk is a member of a DocLnkSet (or AppLnkSet).
1111*/ 1422*/
1112DocLnk::~DocLnk() 1423DocLnk::~DocLnk()
@@ -1143,3 +1454,4 @@ void DocLnk::invoke(const QStringList& args) const
1143 } 1454 }
1144} 1455}
1145 1456
1457