~ubuntu-branches/ubuntu/utopic/kde-workspace/utopic-proposed

« back to all changes in this revision

Viewing changes to libs/taskmanager/launcheritem.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michał Zając
  • Date: 2011-07-09 08:31:15 UTC
  • Revision ID: james.westby@ubuntu.com-20110709083115-ohyxn6z93mily9fc
Tags: upstream-4.6.90
Import upstream version 4.6.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************
 
2
 
 
3
Copyright 2010 Anton Kreuzkamp <akreuzkamp@web.de>
 
4
 
 
5
Permission is hereby granted, free of charge, to any person obtaining a copy
 
6
of this software and associated documentation files (the "Software"), to deal
 
7
in the Software without restriction, including without limitation the rights
 
8
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
9
copies of the Software, and to permit persons to whom the Software is
 
10
furnished to do so, subject to the following conditions:
 
11
 
 
12
The above copyright notice and this permission notice shall be included in
 
13
all copies or substantial portions of the Software.
 
14
 
 
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 
18
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 
19
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
20
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
21
 
 
22
******************************************************************/
 
23
// Own
 
24
#include "launcheritem.h"
 
25
 
 
26
#include <KConfigGroup>
 
27
#include <KDebug>
 
28
#include <KDesktopFile>
 
29
#include <KMimeType>
 
30
#include <QMimeData>
 
31
#include <KMimeTypeTrader>
 
32
#include <KRun>
 
33
#include <KService>
 
34
#include <KServiceTypeTrader>
 
35
#include <KStandardDirs>
 
36
#include <KToolInvocation>
 
37
 
 
38
// KIO
 
39
#include <kemailsettings.h> // no camelcase include
 
40
 
 
41
#include "taskitem.h"
 
42
#include "taskgroup.h"
 
43
 
 
44
namespace TaskManager
 
45
{
 
46
 
 
47
class LauncherItemPrivate
 
48
{
 
49
public:
 
50
    LauncherItemPrivate(LauncherItem *launcher)
 
51
        : q(launcher)
 
52
    {
 
53
    }
 
54
 
 
55
    void associateDestroyed(QObject *obj);
 
56
 
 
57
    LauncherItem *q;
 
58
    KUrl        url;
 
59
    QIcon       icon;
 
60
    QString     name;
 
61
    QString     genericName;
 
62
    QSet<QObject *> associates;
 
63
};
 
64
 
 
65
LauncherItem::LauncherItem(QObject *parent, const KUrl &url)
 
66
    : AbstractGroupableItem(parent),
 
67
    d(new LauncherItemPrivate(this))
 
68
{
 
69
    d->genericName = QString();
 
70
    d->name = QString();
 
71
    if (url.isEmpty()) {
 
72
        d->icon = KIcon("unknown");
 
73
    } else {
 
74
        setLauncherUrl(url);
 
75
    }
 
76
}
 
77
 
 
78
LauncherItem::~LauncherItem()
 
79
{
 
80
    emit destroyed(this);
 
81
    delete d;
 
82
}
 
83
 
 
84
void LauncherItem::associateItemIfMatches(AbstractGroupableItem *item)
 
85
{
 
86
    if (d->associates.contains(item)) {
 
87
        return;
 
88
    }
 
89
 
 
90
    QString name;
 
91
    if (item->itemType() == TaskItemType && !item->isStartupItem()) {
 
92
        name = static_cast<TaskItem *>(item)->task()->classClass().toLower();
 
93
    } else {
 
94
        name = item->name().toLower();
 
95
    }
 
96
 
 
97
    if (name.isEmpty()) {
 
98
        return;
 
99
    }
 
100
 
 
101
    if (name.compare(d->name, Qt::CaseInsensitive) == 0) {
 
102
        const bool wasEmpty = d->associates.isEmpty();
 
103
 
 
104
        d->associates.insert(item);
 
105
        connect(item, SIGNAL(destroyed(QObject*)), this, SLOT(associateDestroyed(QObject*)));
 
106
 
 
107
        if (wasEmpty) {
 
108
            emit show(true);
 
109
        }
 
110
    }
 
111
}
 
112
 
 
113
void LauncherItem::removeItemIfAssociated(AbstractGroupableItem *item)
 
114
{
 
115
    disconnect(item, SIGNAL(destroyed(QObect*)), this, SLOT(associateDestroyed(QObject*)));
 
116
 
 
117
    // now let's just pretend it was destroyed
 
118
    d->associateDestroyed(item);
 
119
}
 
120
 
 
121
bool LauncherItem::shouldShow() const
 
122
{
 
123
    return d->associates.isEmpty();
 
124
}
 
125
 
 
126
void LauncherItemPrivate::associateDestroyed(QObject *obj)
 
127
{
 
128
    kDebug() << "associate was destroyed" << associates.isEmpty();
 
129
    if (associates.isEmpty()) {
 
130
        return;
 
131
    }
 
132
 
 
133
    associates.remove(obj);
 
134
 
 
135
    if (associates.isEmpty()) {
 
136
        emit q->show(false);
 
137
    }
 
138
}
 
139
 
 
140
QIcon LauncherItem::icon() const
 
141
{
 
142
    return d->icon;
 
143
}
 
144
 
 
145
QString LauncherItem::name() const
 
146
{
 
147
    return d->name;
 
148
}
 
149
 
 
150
QString LauncherItem::genericName() const
 
151
{
 
152
    return d->genericName;
 
153
}
 
154
 
 
155
void LauncherItem::setName(const QString& name)
 
156
{
 
157
    //NOTE: preferred is NOT a protocol, it's just a magic string
 
158
    if (d->url.protocol() != "preferred"){
 
159
        d->name = name;
 
160
    }
 
161
}
 
162
 
 
163
void LauncherItem::setGenericName(const QString& genericName)
 
164
{
 
165
    //NOTE: preferred is NOT a protocol, it's just a magic string
 
166
    if (d->url.protocol() != "preferred"){
 
167
        d->genericName = genericName;
 
168
    }
 
169
}
 
170
 
 
171
ItemType LauncherItem::itemType() const
 
172
{
 
173
    return LauncherItemType;
 
174
}
 
175
 
 
176
bool LauncherItem::isGroupItem() const
 
177
{
 
178
    return false;
 
179
}
 
180
 
 
181
void LauncherItem::launch()
 
182
{
 
183
    //NOTE: preferred is NOT a protocol, it's just a magic string
 
184
    if (d->url.protocol() == "preferred") {
 
185
        const QString storageId = defaultApplication(d->url.host(), true);
 
186
        KService::Ptr service = KService::serviceByStorageId(storageId);
 
187
 
 
188
        QString desktopFile = KStandardDirs::locate("xdgdata-apps", service->entryPath());
 
189
        if (desktopFile.isNull()){
 
190
            desktopFile = KStandardDirs::locate("apps", service->entryPath());
 
191
        }
 
192
        new KRun(desktopFile, 0);
 
193
    }else{
 
194
        new KRun(d->url, 0);
 
195
    }
 
196
}
 
197
 
 
198
void LauncherItem::addMimeData(QMimeData* mimeData ) const
 
199
{
 
200
    mimeData->setData("text/uri-list", d->url.url().toAscii());
 
201
}
 
202
 
 
203
KUrl LauncherItem::launcherUrl() const
 
204
{
 
205
    return d->url;
 
206
}
 
207
 
 
208
//Ugly hack written by Aaron Seigo from plasmagenericshell/scripting/scriptengine.cpp
 
209
QString LauncherItem::defaultApplication(QString application, bool storageId)
 
210
{
 
211
    if (application.isEmpty()) {
 
212
        return "";
 
213
    }
 
214
 
 
215
    // FIXME: there are some pretty horrible hacks below, in the sense that they assume a very
 
216
    // specific implementation system. there is much room for improvement here. see
 
217
    // kdebase-runtime/kcontrol/componentchooser/ for all the gory details ;)
 
218
    if (application.compare("mailer", Qt::CaseInsensitive) == 0) {
 
219
        KEMailSettings settings;
 
220
 
 
221
        // in KToolInvocation, the default is kmail; but let's be friendlier :)
 
222
        QString command = settings.getSetting(KEMailSettings::ClientProgram);
 
223
        if (command.isEmpty()) {
 
224
            if (KService::Ptr kontact = KService::serviceByStorageId("kontact")) {
 
225
                return storageId ? kontact->storageId() : kontact->exec();
 
226
            } else if (KService::Ptr kmail = KService::serviceByStorageId("kmail")) {
 
227
                return storageId ? kmail->storageId() : kmail->exec();
 
228
            }
 
229
        }
 
230
 
 
231
        if (!command.isEmpty()) {
 
232
            if (settings.getSetting(KEMailSettings::ClientTerminal) == "true") {
 
233
                KConfigGroup confGroup(KGlobal::config(), "General");
 
234
                const QString preferredTerminal = confGroup.readPathEntry("TerminalApplication",
 
235
                        QString::fromLatin1("konsole"));
 
236
                command = preferredTerminal + QString::fromLatin1(" -e ") + command;
 
237
            }
 
238
 
 
239
            return command;
 
240
        }
 
241
    } else if (application.compare("browser", Qt::CaseInsensitive) == 0) {
 
242
        KConfigGroup config(KGlobal::config(), "General");
 
243
        QString browserApp = config.readPathEntry("BrowserApplication", QString());
 
244
        if (browserApp.isEmpty()) {
 
245
            const KService::Ptr htmlApp = KMimeTypeTrader::self()->preferredService(QLatin1String("text/html"));
 
246
            if (htmlApp) {
 
247
                browserApp = storageId ? htmlApp->storageId() : htmlApp->exec();
 
248
            }
 
249
        } else if (browserApp.startsWith('!')) {
 
250
            browserApp = browserApp.mid(1);
 
251
        }
 
252
 
 
253
        return browserApp;
 
254
    } else if (application.compare("terminal", Qt::CaseInsensitive) == 0) {
 
255
        KConfigGroup confGroup(KGlobal::config(), "General");
 
256
        return confGroup.readPathEntry("TerminalApplication", QString::fromLatin1("konsole"));
 
257
    } else if (application.compare("filemanager", Qt::CaseInsensitive) == 0) {
 
258
        KService::Ptr service = KMimeTypeTrader::self()->preferredService("inode/directory");
 
259
        if (service) {
 
260
            return storageId ? service->storageId() : service->exec();
 
261
        }
 
262
    } else if (application.compare("windowmanager", Qt::CaseInsensitive) == 0) {
 
263
        KConfig cfg("ksmserverrc", KConfig::NoGlobals);
 
264
        KConfigGroup confGroup(&cfg, "General");
 
265
        return confGroup.readEntry("windowManager", QString::fromLatin1("konsole"));
 
266
    } else if (KService::Ptr service = KMimeTypeTrader::self()->preferredService(application)) {
 
267
        return storageId ? service->storageId() : service->exec();
 
268
    } else {
 
269
        // try the files in share/apps/kcm_componentchooser/
 
270
        const QStringList services = KGlobal::dirs()->findAllResources("data","kcm_componentchooser/*.desktop", KStandardDirs::NoDuplicates);
 
271
        //kDebug() << "ok, trying in" << services.count();
 
272
        foreach (const QString &service, services) {
 
273
            KConfig config(service, KConfig::SimpleConfig);
 
274
            KConfigGroup cg = config.group(QByteArray());
 
275
            const QString type = cg.readEntry("valueName", QString());
 
276
            //kDebug() << "    checking" << service << type << application;
 
277
            if (type.compare(application, Qt::CaseInsensitive) == 0) {
 
278
                KConfig store(cg.readPathEntry("storeInFile", "null"));
 
279
                KConfigGroup storeCg(&store, cg.readEntry("valueSection", QString()));
 
280
                const QString exec = storeCg.readPathEntry(cg.readEntry("valueName", "kcm_componenchooser_null"),
 
281
                                                           cg.readEntry("defaultImplementation", QString()));
 
282
                if (!exec.isEmpty()) {
 
283
                    return exec;
 
284
                }
 
285
 
 
286
                break;
 
287
            }
 
288
        }
 
289
    }
 
290
 
 
291
    return "";
 
292
}
 
293
 
 
294
void LauncherItem::setLauncherUrl(const KUrl &url)
 
295
{
 
296
    // Takes care of improperly escaped characters and resolves paths
 
297
    // into file:/// URLs
 
298
    KUrl newUrl(url.url());
 
299
 
 
300
    if (newUrl == d->url) {
 
301
        return;
 
302
    }
 
303
 
 
304
    d->url = newUrl;
 
305
 
 
306
    if (d->url.isLocalFile() && KDesktopFile::isDesktopFile(d->url.toLocalFile())) {
 
307
        KDesktopFile f(d->url.toLocalFile());
 
308
 
 
309
        if (f.tryExec()) {
 
310
            d->icon = KIcon(f.readIcon());
 
311
            d->name = f.readName();
 
312
            d->genericName = f.readGenericName();
 
313
        } else {
 
314
            d->url = KUrl();
 
315
            return;
 
316
        }
 
317
    } else if (d->url.protocol() == "preferred") {
 
318
        //NOTE: preferred is NOT a protocol, it's just a magic string
 
319
        const QString storageId = defaultApplication(d->url.host(), true);
 
320
        const KService::Ptr service = KService::serviceByStorageId(storageId);
 
321
 
 
322
        if (service) {
 
323
            QString desktopFile = KStandardDirs::locate("xdgdata-apps", service->entryPath());
 
324
            if (desktopFile.isNull()) {
 
325
                desktopFile = KStandardDirs::locate("apps", service->entryPath());
 
326
            }
 
327
 
 
328
            KDesktopFile f(desktopFile);
 
329
            KConfigGroup cg(&f, "Desktop Entry");
 
330
 
 
331
            d->icon = KIcon(f.readIcon());
 
332
            QString exec = cg.readEntry("Exec", "");
 
333
            if (!exec.isNull()) {
 
334
                d->name = exec.split(' ').at(0);
 
335
            }
 
336
            d->genericName = f.readGenericName();
 
337
        } else {
 
338
            d->url = KUrl();
 
339
        }
 
340
    } else {
 
341
        d->icon = KIcon(KMimeType::iconNameForUrl(d->url));
 
342
    }
 
343
 
 
344
    if (d->name.isEmpty()) {
 
345
        d->name = d->url.fileName();
 
346
    }
 
347
 
 
348
    if (d->icon.isNull()) {
 
349
        d->icon = KIcon("unknown");
 
350
    }
 
351
}
 
352
 
 
353
bool LauncherItem::isValid() const
 
354
{
 
355
    return d->url.isValid();
 
356
}
 
357
 
 
358
void LauncherItem::setIcon(const QIcon& icon)
 
359
{
 
360
    //NOTE: preferred is NOT a protocol, it's just a magic string
 
361
    if (d->url.protocol() != "preferred"){
 
362
        d->icon = icon;
 
363
    }
 
364
}
 
365
 
 
366
bool LauncherItem::demandsAttention() const
 
367
{
 
368
    return false;
 
369
}
 
370
bool LauncherItem::isActionSupported(NET::Action ) const
 
371
{
 
372
    return false;
 
373
}
 
374
bool LauncherItem::isActive() const
 
375
{
 
376
    return false;
 
377
}
 
378
bool LauncherItem::isAlwaysOnTop() const
 
379
{
 
380
    return false;
 
381
}
 
382
bool LauncherItem::isFullScreen() const
 
383
{
 
384
    return false;
 
385
}
 
386
bool LauncherItem::isKeptBelowOthers() const
 
387
{
 
388
    return false;
 
389
}
 
390
bool LauncherItem::isMaximized() const
 
391
{
 
392
    return false;
 
393
}
 
394
bool LauncherItem::isMinimized() const
 
395
{
 
396
    return false;
 
397
}
 
398
bool LauncherItem::isOnAllDesktops() const
 
399
{
 
400
    return false;
 
401
}
 
402
bool LauncherItem::isOnCurrentDesktop() const
 
403
{
 
404
    return false;
 
405
}
 
406
bool LauncherItem::isShaded() const
 
407
{
 
408
    return false;
 
409
}
 
410
int LauncherItem::desktop() const
 
411
{
 
412
    return 0;
 
413
}
 
414
 
 
415
void LauncherItem::setAlwaysOnTop(bool )
 
416
{
 
417
}
 
418
void LauncherItem::setFullScreen(bool )
 
419
{
 
420
}
 
421
void LauncherItem::setKeptBelowOthers(bool )
 
422
{
 
423
}
 
424
void LauncherItem::setMaximized(bool )
 
425
{
 
426
}
 
427
void LauncherItem::setMinimized(bool )
 
428
{
 
429
}
 
430
void LauncherItem::setShaded(bool )
 
431
{
 
432
}
 
433
void LauncherItem::toDesktop(int )
 
434
{
 
435
}
 
436
void LauncherItem::toggleAlwaysOnTop()
 
437
{
 
438
}
 
439
void LauncherItem::toggleFullScreen()
 
440
{
 
441
}
 
442
void LauncherItem::toggleKeptBelowOthers()
 
443
{
 
444
}
 
445
void LauncherItem::toggleMaximized()
 
446
{
 
447
}
 
448
void LauncherItem::toggleMinimized()
 
449
{
 
450
}
 
451
void LauncherItem::toggleShaded()
 
452
{
 
453
}
 
454
void LauncherItem::close()
 
455
{
 
456
}
 
457
//END
 
458
 
 
459
 
 
460
} // TaskManager namespace
 
461
 
 
462
#include "launcheritem.moc"