~ubuntu-branches/debian/jessie/basket/jessie

« back to all changes in this revision

Viewing changes to src/itemfactory.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Sune Vuorela
  • Date: 2008-06-25 20:11:23 UTC
  • mfrom: (4.1.11 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080625201123-06wsi9dla3rs3486
Tags: 1.0.2-5
* Also allow automake 1.10 usage - and just build-dep on automake i
  (Closes: #487981)
* Bye bye ana

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***************************************************************************
2
 
 *   Copyright (C) 2003 by S�bastien Lao�t                                 *
3
 
 *   sebastien.laout@tuxfamily.org                                         *
4
 
 *                                                                         *
5
 
 *   This program is free software; you can redistribute it and/or modify  *
6
 
 *   it under the terms of the GNU General Public License as published by  *
7
 
 *   the Free Software Foundation; either version 2 of the License, or     *
8
 
 *   (at your option) any later version.                                   *
9
 
 *                                                                         *
10
 
 *   This program is distributed in the hope that it will be useful,       *
11
 
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12
 
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13
 
 *   GNU General Public License for more details.                          *
14
 
 *                                                                         *
15
 
 *   You should have received a copy of the GNU General Public License     *
16
 
 *   along with this program; if not, write to the                         *
17
 
 *   Free Software Foundation, Inc.,                                       *
18
 
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19
 
 ***************************************************************************/
20
 
 
21
 
#include <qstring.h>
22
 
#include <kurl.h>
23
 
#include <qpixmap.h>
24
 
#include <qcolor.h>
25
 
#include <qregexp.h>
26
 
#include <kcolordrag.h>
27
 
#include <kurldrag.h>
28
 
#include <qstylesheet.h>
29
 
#include <qdir.h>
30
 
#include <kmimetype.h>
31
 
#include <kmessagebox.h>
32
 
#include <klocale.h>
33
 
#include <kdesktopfile.h>
34
 
#include <kapplication.h>
35
 
#include <qfile.h>
36
 
#include <kfilemetainfo.h>
37
 
#include <kio/jobclasses.h>
38
 
#include <qtextcodec.h>
39
 
#include <kopenwith.h>
40
 
#include <kfiledialog.h>
41
 
#include <kicondialog.h>
42
 
#include <kiconloader.h>
43
 
#include <qfileinfo.h>
44
 
#include <kpopupmenu.h>
45
 
#include <kstandarddirs.h>
46
 
#include <kurifilter.h>
47
 
 
48
 
#include "basket.h"
49
 
#include "item.h"
50
 
#include "itemfactory.h"
51
 
#include "itemdrag.h"
52
 
#include "linklabel.h"
53
 
#include "global.h"
54
 
#include "settings.h"
55
 
#include "keyboard.h"
56
 
 
57
 
#include "debugwindow.h"
58
 
 
59
 
/** Create items from scratch (just a content) */
60
 
 
61
 
Item* ItemFactory::createItemText(const QString &text, Basket *parent, const QString &annotations)
62
 
{
63
 
        Item *item = new Item(createFileForNewItem(parent, "txt"), Settings::defTextFont(), Settings::defTextColor(),
64
 
                              annotations, false, parent);
65
 
        item->setText(text);
66
 
        parent->insertItem(item);
67
 
        parent->save();
68
 
 
69
 
        return item;
70
 
}
71
 
 
72
 
Item* ItemFactory::createItemHtml(const QString &html, Basket *parent, const QString &annotations)
73
 
{
74
 
        Item *item = new Item(createFileForNewItem(parent, "html"), //Settings::defHtmlShowSource(),
75
 
                              annotations, false, parent);
76
 
        item->setHtml(html);
77
 
        parent->insertItem(item);
78
 
        parent->save();
79
 
 
80
 
        return item;
81
 
}
82
 
 
83
 
Item* ItemFactory::createItemLink(const KURL &url, Basket *parent, const QString &annotations)
84
 
{
85
 
        Item *item = new Item(url, titleForURL(url), iconForURL(url), true, true,
86
 
                              annotations, false, parent);
87
 
        parent->insertItem(item);
88
 
        parent->save();
89
 
 
90
 
        return item;
91
 
}
92
 
 
93
 
// FIXME: , title = QString(), ???
94
 
 
95
 
// The same as ItemFactory::createItemLink but with a defined title :
96
 
Item* ItemFactory::createItemLink(const KURL &url, const QString &title, Basket *parent, const QString &annotations)
97
 
{
98
 
        Item *item = new Item(url, title, iconForURL(url), /*autoTitle=*/false, true,
99
 
                              annotations, false, parent);
100
 
        parent->insertItem(item);
101
 
        parent->save();
102
 
 
103
 
        return item;
104
 
}
105
 
 
106
 
Item* ItemFactory::createItemImage(const QPixmap &image, Basket *parent, const QString &annotations)
107
 
{
108
 
        Item *item = new Item(createFileForNewItem(parent, "png"), Item::Image, // Take care of image format
109
 
                              annotations, false, parent);
110
 
        item->setPixmap(image);
111
 
        parent->insertItem(item);
112
 
        parent->save();
113
 
 
114
 
        return item;
115
 
}
116
 
 
117
 
Item* ItemFactory::createItemColor(const QColor &color, Basket *parent, const QString &annotations)
118
 
{
119
 
        Item *item = new Item(color,
120
 
                              annotations, false, parent);
121
 
        parent->insertItem(item);
122
 
        parent->save();
123
 
 
124
 
        return item;
125
 
}
126
 
 
127
 
/** Return a string list containing {url1, title1, url2, title2, url3, title3...}
128
 
  */
129
 
QStringList ItemFactory::textToURLList(const QString &text)
130
 
{
131
 
        // List to return:
132
 
        QStringList list;
133
 
 
134
 
        // Split lines:
135
 
        QStringList texts = QStringList::split('\n', text);
136
 
 
137
 
        // For each lines:
138
 
        QStringList::iterator it;
139
 
        for (it = texts.begin(); it != texts.end(); ++it) {
140
 
                // Strip white spaces:
141
 
                (*it) = (*it).stripWhiteSpace();
142
 
 
143
 
                // Don't care of empty entries:
144
 
                if ((*it).isEmpty())
145
 
                        continue;
146
 
 
147
 
                // Compute lower case equivalent:
148
 
                QString ltext = (*it).lower();
149
 
 
150
 
                /* Search for mail address ("*@*.*" ; "*" can contain '_', '-', or '.') and add protocol to it */
151
 
                QString mailExpString = "[\\w-\\.]+@[\\w-\\.]+\\.[\\w]+";
152
 
                QRegExp mailExp("^"+mailExpString+"$");
153
 
                if (mailExp.search(ltext) != -1) {
154
 
                        ltext.insert(0, "mailto:");
155
 
                        (*it).insert(0, "mailto:");
156
 
                }
157
 
 
158
 
                // TODO: Recognize "<link>" (link between '<' and '>')
159
 
                // TODO: Replace " at " by "@" and " dot " by "." to look for e-mail addresses
160
 
 
161
 
                /* Search for mail address like "Name <address@provider.net>" */
162
 
                QRegExp namedMailExp("^([\\w\\s]+)\\s<("+mailExpString+")>$");
163
 
                //namedMailExp.setCaseSensitive(true); // For the name to be keeped with uppercases // DOESN'T WORK !
164
 
                if (namedMailExp.search(ltext) != -1) {
165
 
                        QString name    = namedMailExp.cap(1);
166
 
                        QString address = "mailto:" + namedMailExp.cap(2);
167
 
                        // Threat it NOW, as it's an exception (it have a title):
168
 
                        list.append(address);
169
 
                        list.append(name);
170
 
                        continue;
171
 
                }
172
 
 
173
 
                /* Search for an url and create an URL item */
174
 
                if ( ltext.startsWith("/") && ltext[1] != '/' && ltext[1] != '*' || // Take files but not C/C++/... comments !
175
 
                         ltext.startsWith("file:")   ||
176
 
                         ltext.startsWith("http://") ||
177
 
                         ltext.startsWith("www.")    ||
178
 
                         ltext.startsWith("ftp")     ||
179
 
                         ltext.startsWith("mailto:")    ) {
180
 
 
181
 
                        // First, correct the text to use the good format for the url
182
 
                        if (ltext.startsWith( "/"))
183
 
                                (*it).insert(0, "file:");
184
 
                        if (ltext.startsWith("www."))
185
 
                                (*it).insert(0, "http://");
186
 
                        if (ltext.startsWith("ftp."))
187
 
                                (*it).insert(0, "ftp://");
188
 
 
189
 
                        // And create the Url item (or launcher if URL point a .desktop file)
190
 
                        list.append(*it);
191
 
                        list.append(""); // We don't have any title
192
 
                } else
193
 
                        return QStringList(); // FAILED: treat the text as a text, and not as a URL list!
194
 
        }
195
 
        return list;
196
 
}
197
 
 
198
 
Item* ItemFactory::createItem(const QString &text, Basket *parent, const QString &annotations)
199
 
{
200
 
        /* Search for a color (#RGB , #RRGGBB , #RRRGGGBBB , #RRRRGGGGBBBB) and create a color item */
201
 
        QRegExp exp("^#(?:[a-fA-F\\d]{3}){1,4}$");
202
 
        if ( exp.search(text) != -1 )
203
 
                return createItemColor(QColor(text), parent, annotations);
204
 
 
205
 
        /* Try to convert the text as a URL or a list of URLs */
206
 
        QStringList uriList = textToURLList(text);
207
 
        if ( ! uriList.isEmpty() ) {
208
 
                Item *lastItem = 0L;
209
 
                //bool insertAfter  = parent->m_insertAfter; // To past all URLS at the same place (and not one in the right place
210
 
                                                           //  and the others at begin or end)
211
 
                QStringList::iterator it;
212
 
                for (it = uriList.begin(); it != uriList.end(); ++it) {
213
 
                        QString url = (*it);
214
 
                        ++it;
215
 
                        QString title = (*it);
216
 
                        if (title.isEmpty())
217
 
                                lastItem = createItemLinkOrLauncher(KURL(url), parent);
218
 
                        else
219
 
                                lastItem = createItemLink(KURL(url), title, parent);
220
 
                        // After last item was inserted, the insert position is reseted : re-set it
221
 
                        parent->m_insertAtItem = lastItem;
222
 
                        parent->m_insertAfter  = true;
223
 
                }
224
 
                return lastItem; // It don't return ALL inserted items !
225
 
        }
226
 
 
227
 
        QString newText = text.stripWhiteSpace(); // The text for a new item, without useless spaces
228
 
        /* Else, it's a text or an HTML item, so, create it */
229
 
        if (QStyleSheet::mightBeRichText(newText))   // ISITUSEFULL: Verify all lines ?
230
 
                return createItemHtml(newText, parent, annotations);
231
 
        else
232
 
                return createItemText(newText, parent, annotations);
233
 
}
234
 
 
235
 
Item* ItemFactory::createItemLauncher(const KURL &url, Basket *parent)
236
 
{
237
 
        if (url.isEmpty())
238
 
                return createItemLauncher("", "", "", parent);
239
 
        else
240
 
                return copyFileAndLoad(url, parent);
241
 
}
242
 
 
243
 
Item* ItemFactory::createItemLauncher(const QString &command, const QString &name, const QString &icon, Basket *parent)
244
 
{
245
 
        QString fileName = createItemLauncherFile(command, name, icon, parent);
246
 
        if (fileName.isEmpty())
247
 
                return 0L;
248
 
        else
249
 
                return loadFile(fileName, parent);
250
 
}
251
 
 
252
 
QString ItemFactory::createItemLauncherFile(const QString &command, const QString &name, const QString &icon, Basket *parent)
253
 
{
254
 
        QString content = QString(
255
 
                "[Desktop Entry]\n"
256
 
                "Exec=%1\n"
257
 
                "Name=%2\n"
258
 
                "Icon=%3\n"
259
 
                "Encoding=UTF-8\n"
260
 
                "Type=Application\n").arg(command, name, icon.isEmpty() ? "exec" : icon);
261
 
        QString fileName = fileNameForNewItem(parent, "launcher.desktop");
262
 
        QString fullPath = parent->fullPathForFileName(fileName);
263
 
        parent->dontCareOfCreation(fullPath);
264
 
        QFile file(fullPath);
265
 
        if ( file.open(IO_WriteOnly) ) {
266
 
                QTextStream stream(&file);
267
 
                stream.setEncoding(QTextStream::UnicodeUTF8);
268
 
                stream << content;
269
 
                file.close();
270
 
                return fileName;
271
 
        } else
272
 
                return QString();
273
 
}
274
 
 
275
 
Item* ItemFactory::createItemLinkOrLauncher(const KURL &url, Basket *parent)
276
 
{
277
 
        // IMPORTANT: we create the service ONLY if the extension is ".desktop".
278
 
        //            Otherwise, KService take a long time to analyse all the file
279
 
        //            and output such things to stdout:
280
 
        //            "Invalid entry (missing '=') at /my/file.ogg:11984"
281
 
        //            "Invalid entry (missing ']') at /my/file.ogg:11984"...
282
 
        KService::Ptr service;
283
 
        if (url.fileName().endsWith(".desktop"))
284
 
                service = new KService(Item::urlWithoutProtocol(url));
285
 
 
286
 
        // If link point to a .desktop file then add a launcher, otherwise it's a link
287
 
        if (service && service->isValid())
288
 
                return createItemLauncher(url, parent);
289
 
        else
290
 
                return createItemLink(url, parent);
291
 
}
292
 
 
293
 
#include <qstrlist.h>
294
 
#include <qimage.h>
295
 
 
296
 
void ItemFactory::dropItem(QMimeSource *source, Basket *parent, bool fromDrop, QDropEvent::Action action, Item *itemSource)
297
 
{
298
 
        Item *item = 0L;
299
 
 
300
 
        /* No data */
301
 
        if (source->format(0) == 0L) {
302
 
                // TODO: add a parameter to say if it's from a clipboard paste, a selection paste, or a drop
303
 
                //       To be able to say "The clipboard/selection/drop is empty".
304
 
//              KMessageBox::error(parent, i18n("There is no data to insert."), i18n("No Data"));
305
 
                return;
306
 
        }
307
 
 
308
 
        /* Debug */
309
 
        if (Global::debugWindow) {
310
 
                *Global::debugWindow << "<b>Drop :</b>";
311
 
                for(int i = 0; source->format(i); ++i)
312
 
                        if ( *(source->format(i)) )
313
 
                                *Global::debugWindow << "\t[" + QString::number(i) + "] " + QString(source->format(i));
314
 
                switch (action) { // The source want that we:
315
 
                        case QDropEvent::Copy:       *Global::debugWindow << ">> Drop action: Copy";       break;
316
 
                        case QDropEvent::Move:       *Global::debugWindow << ">> Drop action: Move";       break;
317
 
                        case QDropEvent::Link:       *Global::debugWindow << ">> Drop action: Link";       break;
318
 
                        case QDropEvent::Private:    *Global::debugWindow << ">> Drop action: Private";    break; // What is it? (Copy?)
319
 
                        case QDropEvent::UserAction: *Global::debugWindow << ">> Drop action: UserAction"; break; // Not currently
320
 
                        default:                     *Global::debugWindow << ">> Drop action: Unknown";           //  supported by QT!
321
 
                }
322
 
        }
323
 
 
324
 
        /* Copy or move an Item */
325
 
        if (ItemDrag::canDecode(source)) {
326
 
                if (Global::debugWindow)
327
 
                        *Global::debugWindow << ">> Drop an item";
328
 
 
329
 
                if ( action == QDropEvent::Move && itemSource != 0 &&     // We *move* an *item* : just reinsert it to well place
330
 
                     ! itemSource->parentBasket()->isLocked()    ) { //  Unless parent source is locked : then it's a copy
331
 
                                                                          //  TODO: Copy the file ??? Not for the moment !
332
 
                        if (itemSource->parentBasket() == parent) { // If drop in the same basket : keep the file and just move the item
333
 
                                if (Global::debugWindow)
334
 
                                        *Global::debugWindow << ">> DROP : Just move the item to its new position";
335
 
                                parent->changeItemPlace(itemSource); //Just remove and reinsert
336
 
                                return;
337
 
                        } else { // Drop to another basket
338
 
                                 // Another way to do the thing : move the file (eventually rename it) : will be deleted
339
 
                                 //  for the original basket (so, old item deleted) and insert the new item.
340
 
                                if (Global::debugWindow)
341
 
                                        *Global::debugWindow << ">> DROP : Move to another basket";
342
 
                                item = ItemDrag::decode(source, parent, /*move=*/true); // Filename will be kept
343
 
                                parent->insertItem(item);                               // (eventualy with a number added)
344
 
                                parent->save();
345
 
                                //if (!item->useFile()) // If useFile(), ItemDrag::decode() will move the file!
346
 
                                // FIXME: text/html/image items aren't managed the same way other useFile() items are :-/
347
 
                                if (item->type() != Item::Animation && item->type() != Item::Sound    &&
348
 
                                    item->type() != Item::File      && item->type() != Item::Launcher &&
349
 
                                    item->type() != Item::Unknow)
350
 
                                        ((Item*)itemSource)->parentBasket()->delItem(itemSource, false); // Delete the item, & file whereas it's a mirror
351
 
                                return;
352
 
                        }
353
 
                } // Else, at this point it's a copy (link an item not supported : act as a copy !)
354
 
 
355
 
                // Do not try to copy the file, because if it is a cut and paste, item file could be deleted and then re-created
356
 
                item = ItemDrag::decode(source, parent, /*move=*/false);
357
 
                parent->insertItem(item);
358
 
                parent->save();
359
 
                return;
360
 
        }
361
 
 
362
 
        /* Else : Drop object to item */
363
 
 
364
 
        QPixmap pixmap;
365
 
        if ( QImageDrag::decode(source, pixmap) ) {
366
 
                createItemImage(pixmap, parent);
367
 
                return;
368
 
        }
369
 
 
370
 
        // KColorDrag::decode() is buggy and can trheat strings like "#include <foo.h>" as a black color
371
 
        // The correct "ideal" code:
372
 
        /*QColor color;
373
 
        if ( KColorDrag::decode(source, color) ) {
374
 
                createItemColor(color, parent);
375
 
                return;
376
 
        }*/
377
 
        // And then the hack (if provide color MIME type or a text that contains color), using createItem Color RegExp:
378
 
        QString hack;
379
 
        QRegExp exp("^#(?:[a-fA-F\\d]{3}){1,4}$");
380
 
        if (source->provides("application/x-color") ||
381
 
             (QTextDrag::decode(source, hack) && (exp.search(hack) != -1)) ) {
382
 
                QColor color;
383
 
                if ( KColorDrag::decode(source, color) )
384
 
                        if (createItemColor(color, parent))
385
 
                                return;
386
 
                        // Theorically it should be returned. If not, continue by dropping other things
387
 
        }
388
 
 
389
 
        KURL::List urls;
390
 
        if ( KURLDrag::decode(source, urls) ) {
391
 
                if (!fromDrop) // If it's a Paste, we should know if files should be copied (copy&paste) or moved (cut&paste)
392
 
                        if (source->provides("application/x-kde-cutselection")) {
393
 
                                QByteArray array = source->encodedData("application/x-kde-cutselection");
394
 
                                if ( !array.isEmpty() && QCString(array.data(), array.size() + 1).at(0) == '1' )
395
 
                                        action = QDropEvent::Move;
396
 
                        }
397
 
                dropURLs(urls, parent, action, fromDrop);
398
 
                return;
399
 
        }
400
 
 
401
 
        // FIXME: use dropURLs() also from Mozilla?
402
 
 
403
 
        /*
404
 
         * Mozilla's stuff sometimes uses utf-16-le - little-endian UTF-16.
405
 
         *
406
 
         * This has the property that for the ASCII subset case (And indeed, the
407
 
         * ISO-8859-1 subset, I think), if you treat it as a C-style string,
408
 
         * it'll come out to one character long in most cases, since it looks
409
 
         * like:
410
 
         *
411
 
         * "<\0H\0T\0M\0L\0>\0"
412
 
         *
413
 
         * A strlen() call on that will give you 1, which simply isn't correct.
414
 
         * That might, I suppose, be the answer, or something close.
415
 
         *
416
 
         * Also, Mozilla's drag/drop code predates the use of MIME types in XDnD
417
 
         * - hence it'll throw about STRING and UTF8_STRING quite happily, hence
418
 
         * the odd named types.
419
 
         *
420
 
         * Thanks to Dave Cridland for having said me that.
421
 
         */
422
 
        if (source->provides("text/x-moz-url")) { // FOR MOZILLA
423
 
                // Get the array and create a QChar array of 1/2 of the size
424
 
                QByteArray mozilla = source->encodedData("text/x-moz-url");
425
 
                QMemArray<QChar> chars( mozilla.count() / 2 );
426
 
                // A small debug work to know the value of each bytes
427
 
                if (Global::debugWindow)
428
 
                        for (uint i = 0; i < mozilla.count(); i++)
429
 
                                *Global::debugWindow << QString("'") + QChar(mozilla[i]) + "' " + QString::number(int(mozilla[i]));
430
 
                // text/x-moz-url give the URL followed by the link title and separed by OxOA (10 decimal: new line?)
431
 
                uint size   = 0;
432
 
                QChar *name = 0L;
433
 
                // For each little endian mozilla chars, copy it to the array of QChars
434
 
                for (uint i = 0; i < mozilla.count(); i += 2) {
435
 
                        chars[i/2] = QChar(mozilla[i], mozilla[i+1]);
436
 
                        if (mozilla[i] == 0x0A) {
437
 
                                size = i/2;
438
 
                                name = &(chars[i/2+1]);
439
 
                        }
440
 
                }
441
 
                // Create a QString that take the address of the first QChar and a length
442
 
                if (name == 0L) { // We haven't found name (FIXME: Is it possible ?)
443
 
                        QString normalHtml(&(chars[0]), chars.size());
444
 
                        createItemLink(normalHtml, parent);
445
 
                } else {
446
 
                        QString normalHtml(  &(chars[0]), size               );
447
 
                        QString normalTitle( name,        chars.size()-size-1);
448
 
                        createItemLink(normalHtml, normalTitle, parent);
449
 
                }
450
 
                return;
451
 
        }
452
 
 
453
 
        if (source->provides("text/html")) {
454
 
                QString html;
455
 
                QCString subtype("html");
456
 
                // If the text/html comes from Mozilla or GNOME it can be UTF-16 encoded: we need ExtendedTextDrag to check that
457
 
                ExtendedTextDrag::decode(source, html, subtype);
458
 
                createItemHtml(html, parent);
459
 
                return;
460
 
        }
461
 
 
462
 
        QString text;
463
 
        // If the text/plain comes from GEdit or GNOME it can be empty: we need ExtendedTextDrag to check other MIME types
464
 
        if ( ExtendedTextDrag::decode(source, text) ) {
465
 
                createItem(text, parent);
466
 
                return;
467
 
        }
468
 
 
469
 
        /* Unsucceful drop */
470
 
        createItemUnknow(source, parent, "");
471
 
        QString message = i18n("<p>BasKet doesn't support the data you've dropped.<br>"
472
 
                               "It however created a generic item, allowing you to drag or copy "
473
 
                               "them to an application that understand them.</p>"
474
 
                               "If you want BasKet to support them, please contact developer or visit the "
475
 
                               "<a href=\"http://basket.kde.org/dropdb.php\">BasKet Drop Database</a>.</p>");
476
 
        KMessageBox::information(parent, message, i18n("Unsupported MIME Type(s)"),
477
 
                                 "unsupportedDropInfo", KMessageBox::AllowLink);
478
 
        return;
479
 
}
480
 
 
481
 
Item* ItemFactory::createItemUnknow(QMimeSource *source, Basket *parent, const QString &annotations)
482
 
{
483
 
        // Save the MimeSource in a file: create and open the file:
484
 
        QString fileName = createFileForNewItem(parent, "unknow");
485
 
        QFile file(parent->fullPath() + fileName);
486
 
        if ( ! file.open(IO_WriteOnly) )
487
 
                return 0L;
488
 
        QDataStream stream(&file);
489
 
 
490
 
        // Echo MIME types:
491
 
        for (int i = 0; source->format(i); ++i)
492
 
                if ( *(source->format(i)) )
493
 
                        stream << QString(source->format(i)); // Output the '\0'-terminated format name string
494
 
 
495
 
        // Echo end of MIME types list delimiter:
496
 
        stream << "";
497
 
 
498
 
        // Echo the length (in bytes) and then the data, and then same for next MIME type:
499
 
        for (int i = 0; source->format(i); ++i)
500
 
                if ( *(source->format(i)) ) {
501
 
                        QByteArray data = source->encodedData(source->format(i));
502
 
                        stream << (Q_UINT32)data.count();
503
 
                        stream.writeRawBytes(data.data(), data.count());
504
 
                }
505
 
        file.close();
506
 
 
507
 
        Item *item = new Item(fileName, Item::Unknow, annotations, false, parent);
508
 
        item->loadContent(); // FIXME: Why not loadContent() in the contructor ???????????? I think I should
509
 
        parent->insertItem(item);
510
 
        parent->save();
511
 
 
512
 
        return item;
513
 
}
514
 
 
515
 
void ItemFactory::dropURLs(KURL::List urls, Basket *parent, QDropEvent::Action action, bool fromDrop)
516
 
{
517
 
        Item *item;
518
 
 
519
 
        // Drop ONLY LINKS for this type of basket!
520
 
        // This prevent cutting a file in Konqueror to be immediatly pasted into BasKet!!
521
 
        if (parent->isAClipboard()) {
522
 
                for ( KURL::List::iterator it = urls.begin(); it != urls.end(); ++it ) {
523
 
                        item = createItemLinkOrLauncher(*it, parent);
524
 
                        // After last item was inserted, the insert position is reseted : re-set it
525
 
                        parent->m_insertAtItem = item;
526
 
                        parent->m_insertAfter  = true;
527
 
                }
528
 
                return;
529
 
        }
530
 
 
531
 
        // TODO: Basket::insertItems(QPtrList<Item> items) or Basket::insertItemAndDon'tReset(Item *item)
532
 
        //bool insertAfter  = parent->m_insertAfter; // To past all URLS at the same place (and not one in the right place
533
 
                                                   //  and the others at begin or end)
534
 
        // BEGIN Insertion work
535
 
        int shouldAsk = 0; // shouldAsk==0: don't ask ; shouldAsk==1: ask for "file" ; shouldAsk>=2: ask for "files"
536
 
        bool shiftPressed = Keyboard::shiftPressed();
537
 
        bool ctrlPressed  = Keyboard::controlPressed();
538
 
        bool modified = fromDrop && (shiftPressed || ctrlPressed);
539
 
 
540
 
        if (modified) // Then no menu + modified action
541
 
                ; // action is already set: no work to do
542
 
        else if (fromDrop) { // Compute if user should be asked or not
543
 
                for ( KURL::List::iterator it = urls.begin(); it != urls.end(); ++it )
544
 
                        if ((*it).protocol() != "mailto") { // Do not ask when dropping mail address :-)
545
 
                                shouldAsk++;
546
 
                                if (shouldAsk == 1/*2*/) // Sufficient
547
 
                                        break;
548
 
                        }
549
 
                if (shouldAsk) {
550
 
                        KPopupMenu menu(parent);
551
 
                        menu.insertItem( SmallIconSet("goto"),     i18n("&Move Here"), 0 );
552
 
                        menu.insertItem( SmallIconSet("editcopy"), i18n("&Copy Here"), 1 );
553
 
                        menu.insertItem( SmallIconSet("html"),     i18n("&Link Here"), 2 );
554
 
                        menu.insertSeparator();
555
 
                        menu.insertItem( SmallIconSet("cancel"),   i18n("C&ancel"),    3 );
556
 
                        int id = menu.exec(QCursor::pos());
557
 
                        switch (id) {
558
 
                                case 0: action = QDropEvent::Move; break;
559
 
                                case 1: action = QDropEvent::Copy; break;
560
 
                                case 2: action = QDropEvent::Link; break;
561
 
                                default: return;
562
 
                        }
563
 
                        modified = true;
564
 
                }
565
 
        } else { // fromPaste
566
 
                ;
567
 
        }
568
 
 
569
 
        /* Policy of drops of URL:
570
 
         *   Email: [Modifier keys: Useless]
571
 
         +    - Link mail address
572
 
         *   Remote URL: [Modifier keys: {Copy,Link}]
573
 
         +    - Download as Image, Animation and Launcher
574
 
         +    - Link other URLs
575
 
         *   Local URL: [Modifier keys: {Copy,Move,Link}]
576
 
         *    - Copy as Image, Animation and Launcher (or mirror?) [Modifier keys: {Copy,Move,Link}]
577
 
         *    - Link directory [Modifier keys: Useless]
578
 
         *    - Make Launcher of executable [Modifier keys: {Copy_exec,Move_exec,Link_Launcher}]
579
 
         *    - Ask for file (if use want to copy and it is a sound: make Sound)
580
 
         * Policy of pastes of URL: [NO modifier keys]
581
 
         *   - Same as drops
582
 
         *   - But copy when ask should be done
583
 
         *   - Unless cut-selection is true: move files instead
584
 
         * Policy of file created in the basket dir: [NO modifier keys]
585
 
         *   - View as Image, Animation, Sound, Launcher
586
 
         *   - View as File
587
 
         */
588
 
        for ( KURL::List::iterator it = urls.begin(); it != urls.end(); ++it ) {
589
 
                if ( ((*it).protocol() == "mailto") ||
590
 
                     (action == QDropEvent::Link)    )
591
 
                        item = createItemLinkOrLauncher(*it, parent);
592
 
                else if (!(*it).isLocalFile()) {
593
 
                        if ( action != QDropEvent::Link && (maybeImageOrAnimation(*it)/* || maybeSound(*it)*/) )
594
 
                                item = copyFileAndLoad(*it, parent);
595
 
                        else
596
 
                                item = createItemLinkOrLauncher(*it, parent);
597
 
                } else {
598
 
                        if (action == QDropEvent::Copy)
599
 
                                item = copyFileAndLoad(*it, parent);
600
 
                        else if (action == QDropEvent::Move)
601
 
                                item = moveFileAndLoad(*it, parent);
602
 
                        else
603
 
                                item = createItemLinkOrLauncher(*it, parent);
604
 
                }
605
 
 
606
 
                // END Insertion work
607
 
                // After last item was inserted, the insert position is reseted : re-set it
608
 
                parent->m_insertAtItem = item;
609
 
                parent->m_insertAfter  = true;
610
 
        }
611
 
}
612
 
 
613
 
// mayBeLauncher: url.url().endsWith(".desktop");
614
 
 
615
 
bool ItemFactory::maybeText(const KURL &url)
616
 
{
617
 
        QString path = url.url().lower();
618
 
        return path.endsWith(".txt");
619
 
}
620
 
 
621
 
bool ItemFactory::maybeHtml(const KURL &url)
622
 
{
623
 
        QString path = url.url().lower();
624
 
        return path.endsWith(".html") || path.endsWith(".htm");
625
 
}
626
 
 
627
 
bool ItemFactory::maybeImageOrAnimation(const KURL &url)
628
 
{
629
 
        /* Examples on my machine:
630
 
                QImageDrag can understands
631
 
                        {"image/png", "image/bmp", "image/jpeg", "image/pgm", "image/ppm", "image/xbm", "image/xpm"}
632
 
                QImageIO::inputFormats() returns
633
 
                        {"BMP", "GIF", "JPEG", "MNG", "PBM", "PGM", "PNG", "PPM", "XBM", "XPM"}
634
 
                QImageDecoder::inputFormats():
635
 
                        {"GIF", "MNG", "PNG"} */
636
 
        QStrList list = QImageIO::inputFormats();
637
 
        list.prepend("jpg"); // Since QImageDrag return only "JPEG" and extensions can be "JPG"; preprend for heuristic optim.
638
 
        char *s;
639
 
        QString path = url.url().lower();
640
 
        for (s = list.first(); s; s = list.next())
641
 
                if (path.endsWith(QString(".") + QString(s).lower()))
642
 
                        return true;
643
 
        // TODO: Search real MIME type for local files?
644
 
        return false;
645
 
}
646
 
 
647
 
bool ItemFactory::maybeAnimation(const KURL &url)
648
 
{
649
 
        QString path = url.url().lower();
650
 
        return path.endsWith(".mng") || path.endsWith(".gif");
651
 
}
652
 
 
653
 
bool ItemFactory::maybeSound(const KURL &url)
654
 
{
655
 
        QString path = url.url().lower();
656
 
        return path.endsWith(".mp3") || path.endsWith(".ogg");
657
 
}
658
 
 
659
 
bool ItemFactory::maybeLauncher(const KURL &url)
660
 
{
661
 
        QString path = url.url().lower();
662
 
        return path.endsWith(".desktop");
663
 
}
664
 
 
665
 
////////////// NEW:
666
 
 
667
 
Item* ItemFactory::copyFileAndLoad(const KURL &url, Basket *parent)
668
 
{
669
 
        QString fileName = fileNameForNewItem(parent, url.fileName());
670
 
        QString fullPath = parent->fullPathForFileName(fileName);
671
 
 
672
 
        if (Global::debugWindow)
673
 
                *Global::debugWindow << "copyFileAndLoad: " + url.prettyURL() + " to " + fullPath;
674
 
 
675
 
        QString annotations = i18n("Original file: %1").arg(url.prettyURL());
676
 
        parent->dontCareOfCreation(fullPath);
677
 
        KIO::CopyJob *copyJob = KIO::copy(url, KURL(fullPath));
678
 
        parent->connect( copyJob,  SIGNAL(copyingDone(KIO::Job *, const KURL &, const KURL &, bool, bool)),
679
 
                         parent, SLOT(slotCopyingDone(KIO::Job *, const KURL &, const KURL &, bool, bool)) );
680
 
 
681
 
        Item::Type type = typeForURL(url, parent); // Use the type of the original file because the target doesn't exist yet
682
 
        Item *item = new Item(fileName, type, annotations, false, parent);
683
 
        parent->insertItem(item);
684
 
        parent->save();
685
 
 
686
 
        return item;
687
 
}
688
 
 
689
 
Item* ItemFactory::moveFileAndLoad(const KURL &url, Basket *parent)
690
 
{
691
 
        // Globally the same as copyFileAndLoad() but move instead of copy (KIO::move())
692
 
        QString fileName = fileNameForNewItem(parent, url.fileName());
693
 
        QString fullPath = parent->fullPathForFileName(fileName);
694
 
 
695
 
        if (Global::debugWindow)
696
 
                *Global::debugWindow << "moveFileAndLoad: " + url.prettyURL() + " to " + fullPath;
697
 
 
698
 
        QString annotations = i18n("Original file: %1").arg(url.prettyURL());
699
 
        parent->dontCareOfCreation(fullPath);
700
 
        KIO::CopyJob *copyJob = KIO::move(url, KURL(fullPath));
701
 
        parent->connect( copyJob,  SIGNAL(copyingDone(KIO::Job *, const KURL &, const KURL &, bool, bool)),
702
 
                         parent, SLOT(slotCopyingDone(KIO::Job *, const KURL &, const KURL &, bool, bool)) );
703
 
 
704
 
        Item::Type type = typeForURL(url, parent); // Use the type of the original file because the target doesn't exist yet
705
 
        Item *item = new Item(fileName, type, annotations, false, parent);
706
 
        parent->insertItem(item);
707
 
        parent->save();
708
 
 
709
 
        return item;
710
 
}
711
 
 
712
 
Item* ItemFactory::loadFile(const QString &fileName, Basket *parent, const QString &annotations)
713
 
{
714
 
        Item *item = 0L;
715
 
 
716
 
        // The file MUST exists
717
 
        QFileInfo file( Item::urlWithoutProtocol(parent->fullPathForFileName(fileName)) );
718
 
        if ( ! file.exists() )
719
 
                return 0L;
720
 
 
721
 
        Item::Type type = typeForURL(parent->fullPathForFileName(fileName), parent);
722
 
        item = new Item(fileName, type, annotations, false, parent);
723
 
        item->loadContent();
724
 
        parent->insertItem(item);
725
 
        parent->save();
726
 
 
727
 
        return item;
728
 
}
729
 
 
730
 
Item::Type ItemFactory::typeForURL(const KURL &url, Basket *parent)
731
 
{
732
 
/*      KMimeType::Ptr kMimeType = KMimeType::findByURL(url);
733
 
        if (Global::debugWindow)
734
 
                *Global::debugWindow << "typeForURL: " + kMimeType->parentMimeType();//property("MimeType").toString();*/
735
 
        bool viewText  = parent->viewFileContent(Basket::FileText);
736
 
        bool viewHTML  = parent->viewFileContent(Basket::FileHTML);
737
 
        bool viewImage = parent->viewFileContent(Basket::FileImage);
738
 
        bool viewSound = parent->viewFileContent(Basket::FileSound);
739
 
 
740
 
        KFileMetaInfo metaInfo(url);
741
 
        if (Global::debugWindow && metaInfo.isEmpty())
742
 
                *Global::debugWindow << "typeForURL: metaInfo is empty for " + url.prettyURL();
743
 
        if (metaInfo.isEmpty()) { // metaInfo is empty for GIF files on my machine !
744
 
                if      (viewText  && maybeText(url))             return Item::Text;
745
 
                else if (viewHTML  && (maybeHtml(url)))           return Item::Html;
746
 
                else if (viewImage && maybeAnimation(url))        return Item::Animation; // See Item::movieStatus(int)
747
 
                else if (viewImage && maybeImageOrAnimation(url)) return Item::Image;     //  for more explanations
748
 
                else if (viewSound && maybeSound(url))            return Item::Sound;
749
 
                else if (maybeLauncher(url))                      return Item::Launcher;
750
 
                else                                              return Item::File;
751
 
        }
752
 
        QString mimeType = metaInfo.mimeType();
753
 
 
754
 
        if (Global::debugWindow)
755
 
                *Global::debugWindow << "typeForURL: " + url.prettyURL() + " ; MIME type = " + mimeType;
756
 
 
757
 
        if      (mimeType == "application/x-desktop")            return Item::Launcher;
758
 
        else if (viewText  && mimeType.startsWith("text/plain")) return Item::Text;
759
 
        else if (viewHTML  && mimeType.startsWith("text/html"))  return Item::Html;
760
 
        else if (viewImage && mimeType == "movie/x-mng")         return Item::Animation;
761
 
        else if (viewImage && mimeType == "image/gif")           return Item::Animation;
762
 
        else if (viewImage && mimeType.startsWith("image/"))     return Item::Image;
763
 
        else if (viewSound && mimeType.startsWith("audio/"))     return Item::Sound;
764
 
        else                                                     return Item::File;
765
 
}
766
 
 
767
 
QString ItemFactory::fileNameForNewFile(const QString &wantedName, const QString &destFolder)
768
 
{
769
 
        QString fileName  = wantedName;
770
 
        QString fullName  = destFolder + fileName;
771
 
        QString extension = "";
772
 
        int     number    = 2;
773
 
        QDir    dir;
774
 
 
775
 
        // First check if the file do not exists yet (simplier and more often case)
776
 
        dir = QDir(fullName);
777
 
        if ( ! dir.exists(fullName) )
778
 
                return fileName;
779
 
 
780
 
        // Find the file extension, if it exists : Split fileName in fileName and extension
781
 
        // Example : fileName == "item5-3.txt" => fileName = "item5-3" and extension = ".txt"
782
 
        int extIndex = fileName.findRev('.');
783
 
        if (extIndex != -1 && extIndex != int(fileName.length()-1))  { // Extension found and fileName do not ends with '.' !
784
 
                extension = fileName.mid(extIndex);
785
 
                fileName.truncate(extIndex);
786
 
        } // else fileName = fileName and extension = ""
787
 
 
788
 
        // Find the file number, if it exists : Split fileName in fileName and number
789
 
        // Example : fileName == "item5-3" => fileName = "item5" and number = 3
790
 
        int extNumber = fileName.findRev('-');
791
 
        if (extNumber != -1 && extNumber != int(fileName.length()-1))  { // Number found and fileName do not ends with '-' !
792
 
                bool isANumber;
793
 
                int  theNumber = fileName.mid(extNumber + 1).toInt(&isANumber);
794
 
                if (isANumber) {
795
 
                        number = theNumber;
796
 
                        fileName.truncate(extNumber);
797
 
                } // else :
798
 
        } // else fileName = fileName and number = 2 (because if the file already exists, the genereated name is at last the 2nd)
799
 
 
800
 
        QString finalName;
801
 
        for (/*int number = 2*/; ; ++number) { // TODO: FIXME: If overflow ???
802
 
                finalName = fileName + "-" + QString::number(number) + extension;
803
 
                fullName = destFolder + finalName;
804
 
                dir = QDir(fullName);
805
 
                if ( ! dir.exists(fullName) )
806
 
                        break;
807
 
        }
808
 
 
809
 
        return finalName;
810
 
}
811
 
 
812
 
QString ItemFactory::fileNameForNewItem(Basket *parent, const QString &wantedName)
813
 
{
814
 
        return fileNameForNewFile(wantedName, parent->fullPath());
815
 
}
816
 
 
817
 
// Create a file to store a new item in Basket parent and with extension extension.
818
 
// If wantedName is provided, the function will first try to use this file name, or derive it if it's impossible
819
 
//  (extension willn't be used for that case)
820
 
QString ItemFactory::createFileForNewItem(Basket *parent, const QString &extension, const QString &wantedName)
821
 
{
822
 
        static int nb = 1;
823
 
 
824
 
        QString fileName;
825
 
        QString fullName;
826
 
 
827
 
        if (wantedName.isEmpty()) {
828
 
                QDir dir;
829
 
                for (/*int nb = 1*/; ; ++nb) { // TODO: FIXME: If overflow ???
830
 
                        fileName = "item" + QString::number(nb)/*.rightJustify(5, '0')*/ + "." + extension;
831
 
                        fullName = parent->fullPath() + fileName;
832
 
                        dir = QDir(fullName);
833
 
                        if ( ! dir.exists(fullName) )
834
 
                                break;
835
 
                }
836
 
        } else {
837
 
                fileName = fileNameForNewItem(parent, wantedName);
838
 
                fullName = parent->fullPath() + fileName;
839
 
        }
840
 
 
841
 
        // Create the file
842
 
        parent->dontCareOfCreation(fullName);
843
 
        QFile file(fullName);
844
 
        file.open(IO_WriteOnly);
845
 
        file.close();
846
 
 
847
 
        return fileName;
848
 
}
849
 
 
850
 
QFont ItemFactory::fontForFontType(int type)
851
 
{
852
 
        QFont font;
853
 
 
854
 
        switch (type) {
855
 
                case 1:  font.setFamily("SansSerif"); break;
856
 
                case 2:  font.setFamily("Serif");     break;
857
 
                case 3:  font.setFamily("Courier");   break;
858
 
                default: font.setFamily("System");           // case O or another illegal type...
859
 
        }
860
 
 
861
 
        return font;
862
 
}
863
 
 
864
 
QString ItemFactory::titleForURL(const KURL &url)
865
 
{
866
 
        QString title = url.prettyURL();
867
 
        QString home  = "file:" + QDir::homeDirPath() + "/";
868
 
 
869
 
        if (title.startsWith("mailto:"))
870
 
                return title.remove(0, 7);
871
 
 
872
 
        if (title.startsWith(home))
873
 
                title = "~/" + title.remove(0, home.length());
874
 
 
875
 
        if (title.startsWith("file:/"))
876
 
                title = title.remove(0, 5); // 5 == QString("file:").length() - 1
877
 
        else if (title.startsWith("http://"))
878
 
                title = title.remove(0, 7); // 7 == QString("http://").length() - 1
879
 
 
880
 
        if ( ! url.isLocalFile() ) {
881
 
                if (title.endsWith("/index.html") && title.length() > 11)
882
 
                        title.truncate(title.length() - 11); // 11 == QString("/index.html").length()
883
 
                else if (title.endsWith("/index.htm") && title.length() > 10)
884
 
                        title.truncate(title.length() - 10); // 10 == QString("/index.htm").length()
885
 
                else if (title.endsWith("/index.xhtml") && title.length() > 12)
886
 
                        title.truncate(title.length() - 12); // 12 == QString("/index.xhtml").length()
887
 
                else if (title.endsWith("/index.php") && title.length() > 10)
888
 
                        title.truncate(title.length() - 10); // 10 == QString("/index.php").length()
889
 
                else if (title.endsWith("/index.php3") && title.length() > 11)
890
 
                        title.truncate(title.length() - 11); // 11 == QString("/index.php3").length()
891
 
                else if (title.endsWith("/index.php4") && title.length() > 11)
892
 
                        title.truncate(title.length() - 11); // 11 == QString("/index.php4").length()
893
 
                else if (title.endsWith("/index.php5") && title.length() > 11)
894
 
                        title.truncate(title.length() - 11); // 11 == QString("/index.php5").length()
895
 
        }
896
 
 
897
 
        if (title.length() > 2 && title.endsWith("/")) // length > 2 because "/" and "~/" shouldn't be transformed to "" and "~"
898
 
                title.truncate(title.length() - 1); // eg. transform "www.kde.org/" to "www.kde.org"
899
 
 
900
 
        return title;
901
 
}
902
 
 
903
 
QString ItemFactory::iconForURL(const KURL &url)
904
 
{
905
 
        QString icon = KMimeType::iconForURL(url.url());
906
 
        if ( url.protocol() == "mailto" )
907
 
                icon = "message";
908
 
        return icon;
909
 
}
910
 
 
911
 
// TODO: Can I add "autoTitle" and "autoIcon" entries to .desktop files? or just store them in basket, as now...
912
 
 
913
 
/* Try our better to find an icon suited to the command line
914
 
 * eg. "/usr/bin/kwrite-3.2 ~/myfile.txt /home/other/file.xml"
915
 
 * will give the "kwrite" icon!
916
 
 */
917
 
QString ItemFactory::iconForCommand(const QString &command)
918
 
{
919
 
        QString icon;
920
 
 
921
 
        // 1. Use first word as icon (typically the program without argument)
922
 
        icon = QStringList::split(' ', command).first();
923
 
        // 2. If the command is a full path, take only the program file name
924
 
        icon = icon.mid(icon.findRev('/') + 1); // strip path if given [But it doesn't care of such
925
 
                                                           // "myprogram /my/path/argument" -> return "argument". Would
926
 
                                                           // must first strip first word and then strip path... Useful ??
927
 
        // 3. Use characters before any '-' (e.g. use "gimp" icon if run command is "gimp-1.3")
928
 
        if ( ! isIconExist(icon) )
929
 
                icon = QStringList::split('-', icon).first();
930
 
        // 4. If the icon still not findable, use a generic icon
931
 
        if ( ! isIconExist(icon) )
932
 
                icon = "exec";
933
 
 
934
 
        return icon;
935
 
}
936
 
 
937
 
bool ItemFactory::isIconExist(const QString &icon)
938
 
{
939
 
        return ! kapp->iconLoader()->loadIcon(icon, KIcon::NoGroup, 16, KIcon::DefaultState, 0L, true).isNull();
940
 
}
941
 
 
942
 
void ItemFactory::insertEmpty(int type, Basket *parent)
943
 
{
944
 
        Item    *item = 0L;
945
 
        QPixmap *pixmap;
946
 
 
947
 
        switch (type) {
948
 
                case Item::Text:
949
 
                        item = ItemFactory::createItemText("", parent);
950
 
                        break;
951
 
                case Item::Html:
952
 
                        item = ItemFactory::createItemHtml("", parent);
953
 
                        break;
954
 
                case Item::Image:
955
 
                        pixmap = new QPixmap( QSize(Settings::defImageX(), Settings::defImageY()) );
956
 
                        pixmap->fill();
957
 
                        pixmap->setMask(pixmap->createHeuristicMask());
958
 
                        item = ItemFactory::createItemImage(*pixmap, parent);
959
 
                        break;
960
 
                case Item::Link:
961
 
                        item = ItemFactory::createItemLink(KURL(), parent);
962
 
                        break;
963
 
                case Item::Launcher:
964
 
                        item = ItemFactory::createItemLauncher(KURL(), parent);
965
 
                        break;
966
 
                case Item::Color:
967
 
                        item = ItemFactory::createItemColor(Qt::black, parent);
968
 
                        break;
969
 
        }
970
 
        if (item) {
971
 
                parent->ensureVisibleItem(item);
972
 
                parent->unselectAllBut(item);
973
 
                parent->setFocusedItem(item);
974
 
                item->slotEdit();
975
 
        }
976
 
}
977
 
 
978
 
void ItemFactory::insertWizard(int type, Basket *parent)
979
 
{
980
 
        KOpenWithDlg *dlg = 0L;
981
 
        QString       iconName;
982
 
        KURL          url;
983
 
        Item         *item = 0L;
984
 
 
985
 
        switch (type) {
986
 
                case 1: // importKmenuLauncher
987
 
                        dlg = new KOpenWithDlg(parent);
988
 
                        dlg->setSaveNewApplications(true); // To create temp file, needed by createItemLauncher()
989
 
                        dlg->exec();
990
 
                        if (dlg->service()) {
991
 
                                // * locateLocal() return a local file even if it is a system wide one (local one doesn't exists)
992
 
                                // * desktopEntryPath() returns the full path for system wide ressources, but relative path if in home
993
 
                                QString serviceUrl = dlg->service()->desktopEntryPath();
994
 
                                if ( ! serviceUrl.startsWith("/") )
995
 
                                        serviceUrl = dlg->service()->locateLocal(); //locateLocal("xdgdata-apps", serviceUrl);
996
 
                                item = createItemLauncher(serviceUrl, parent);
997
 
                        }
998
 
                        break;
999
 
                case 2: // importIcon
1000
 
                        iconName = KIconDialog::getIcon( KIcon::Desktop, KIcon::Application, false, Settings::defIconSize() );
1001
 
                        if ( ! iconName.isEmpty() )
1002
 
                                item = createItemImage( DesktopIcon(iconName, Settings::defIconSize()),
1003
 
                                                        parent, i18n("Icon name: %1").arg(iconName) );
1004
 
                                                        // TODO: wantedName = iconName !!!!!!!!!!!!!!
1005
 
                        break;
1006
 
                case 3: //loadFromFile
1007
 
                        url = KFileDialog::getOpenURL( QString::null, QString::null, parent,
1008
 
                                                       i18n("Load a File Content into an Item") );
1009
 
                        if ( ! url.isEmpty() )
1010
 
                                item = copyFileAndLoad(url, parent);
1011
 
                        break;
1012
 
                case 4: // mirrorFile
1013
 
                        url = KFileDialog::getOpenURL( QString::null, QString::null, parent,
1014
 
                                                       i18n("Mirror a File Content into an Item") );
1015
 
                        if ( ! url.isEmpty() )
1016
 
                                item = loadFile(Item::urlWithoutProtocol(url), parent);
1017
 
                        break;
1018
 
        }
1019
 
        if (item) {
1020
 
                parent->ensureVisibleItem(item);
1021
 
                parent->unselectAllBut(item);
1022
 
                parent->setFocusedItem(item);
1023
 
        }
1024
 
}