1
/*****************************************************************
3
Copyright 2010 Anton Kreuzkamp <akreuzkamp@web.de>
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:
12
The above copyright notice and this permission notice shall be included in
13
all copies or substantial portions of the Software.
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.
22
******************************************************************/
24
#include "launcheritem.h"
26
#include <KConfigGroup>
28
#include <KDesktopFile>
31
#include <KMimeTypeTrader>
34
#include <KServiceTypeTrader>
35
#include <KStandardDirs>
36
#include <KToolInvocation>
39
#include <kemailsettings.h> // no camelcase include
42
#include "taskgroup.h"
47
class LauncherItemPrivate
50
LauncherItemPrivate(LauncherItem *launcher)
55
void associateDestroyed(QObject *obj);
62
QSet<QObject *> associates;
65
LauncherItem::LauncherItem(QObject *parent, const KUrl &url)
66
: AbstractGroupableItem(parent),
67
d(new LauncherItemPrivate(this))
69
d->genericName = QString();
72
d->icon = KIcon("unknown");
78
LauncherItem::~LauncherItem()
84
void LauncherItem::associateItemIfMatches(AbstractGroupableItem *item)
86
if (d->associates.contains(item)) {
91
if (item->itemType() == TaskItemType && !item->isStartupItem()) {
92
name = static_cast<TaskItem *>(item)->task()->classClass().toLower();
94
name = item->name().toLower();
101
if (name.compare(d->name, Qt::CaseInsensitive) == 0) {
102
const bool wasEmpty = d->associates.isEmpty();
104
d->associates.insert(item);
105
connect(item, SIGNAL(destroyed(QObject*)), this, SLOT(associateDestroyed(QObject*)));
113
void LauncherItem::removeItemIfAssociated(AbstractGroupableItem *item)
115
disconnect(item, SIGNAL(destroyed(QObect*)), this, SLOT(associateDestroyed(QObject*)));
117
// now let's just pretend it was destroyed
118
d->associateDestroyed(item);
121
bool LauncherItem::shouldShow() const
123
return d->associates.isEmpty();
126
void LauncherItemPrivate::associateDestroyed(QObject *obj)
128
kDebug() << "associate was destroyed" << associates.isEmpty();
129
if (associates.isEmpty()) {
133
associates.remove(obj);
135
if (associates.isEmpty()) {
140
QIcon LauncherItem::icon() const
145
QString LauncherItem::name() const
150
QString LauncherItem::genericName() const
152
return d->genericName;
155
void LauncherItem::setName(const QString& name)
157
//NOTE: preferred is NOT a protocol, it's just a magic string
158
if (d->url.protocol() != "preferred"){
163
void LauncherItem::setGenericName(const QString& genericName)
165
//NOTE: preferred is NOT a protocol, it's just a magic string
166
if (d->url.protocol() != "preferred"){
167
d->genericName = genericName;
171
ItemType LauncherItem::itemType() const
173
return LauncherItemType;
176
bool LauncherItem::isGroupItem() const
181
void LauncherItem::launch()
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);
188
QString desktopFile = KStandardDirs::locate("xdgdata-apps", service->entryPath());
189
if (desktopFile.isNull()){
190
desktopFile = KStandardDirs::locate("apps", service->entryPath());
192
new KRun(desktopFile, 0);
198
void LauncherItem::addMimeData(QMimeData* mimeData ) const
200
mimeData->setData("text/uri-list", d->url.url().toAscii());
203
KUrl LauncherItem::launcherUrl() const
208
//Ugly hack written by Aaron Seigo from plasmagenericshell/scripting/scriptengine.cpp
209
QString LauncherItem::defaultApplication(QString application, bool storageId)
211
if (application.isEmpty()) {
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;
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();
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;
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"));
247
browserApp = storageId ? htmlApp->storageId() : htmlApp->exec();
249
} else if (browserApp.startsWith('!')) {
250
browserApp = browserApp.mid(1);
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");
260
return storageId ? service->storageId() : service->exec();
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();
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()) {
294
void LauncherItem::setLauncherUrl(const KUrl &url)
296
// Takes care of improperly escaped characters and resolves paths
297
// into file:/// URLs
298
KUrl newUrl(url.url());
300
if (newUrl == d->url) {
306
if (d->url.isLocalFile() && KDesktopFile::isDesktopFile(d->url.toLocalFile())) {
307
KDesktopFile f(d->url.toLocalFile());
310
d->icon = KIcon(f.readIcon());
311
d->name = f.readName();
312
d->genericName = f.readGenericName();
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);
323
QString desktopFile = KStandardDirs::locate("xdgdata-apps", service->entryPath());
324
if (desktopFile.isNull()) {
325
desktopFile = KStandardDirs::locate("apps", service->entryPath());
328
KDesktopFile f(desktopFile);
329
KConfigGroup cg(&f, "Desktop Entry");
331
d->icon = KIcon(f.readIcon());
332
QString exec = cg.readEntry("Exec", "");
333
if (!exec.isNull()) {
334
d->name = exec.split(' ').at(0);
336
d->genericName = f.readGenericName();
341
d->icon = KIcon(KMimeType::iconNameForUrl(d->url));
344
if (d->name.isEmpty()) {
345
d->name = d->url.fileName();
348
if (d->icon.isNull()) {
349
d->icon = KIcon("unknown");
353
bool LauncherItem::isValid() const
355
return d->url.isValid();
358
void LauncherItem::setIcon(const QIcon& icon)
360
//NOTE: preferred is NOT a protocol, it's just a magic string
361
if (d->url.protocol() != "preferred"){
366
bool LauncherItem::demandsAttention() const
370
bool LauncherItem::isActionSupported(NET::Action ) const
374
bool LauncherItem::isActive() const
378
bool LauncherItem::isAlwaysOnTop() const
382
bool LauncherItem::isFullScreen() const
386
bool LauncherItem::isKeptBelowOthers() const
390
bool LauncherItem::isMaximized() const
394
bool LauncherItem::isMinimized() const
398
bool LauncherItem::isOnAllDesktops() const
402
bool LauncherItem::isOnCurrentDesktop() const
406
bool LauncherItem::isShaded() const
410
int LauncherItem::desktop() const
415
void LauncherItem::setAlwaysOnTop(bool )
418
void LauncherItem::setFullScreen(bool )
421
void LauncherItem::setKeptBelowOthers(bool )
424
void LauncherItem::setMaximized(bool )
427
void LauncherItem::setMinimized(bool )
430
void LauncherItem::setShaded(bool )
433
void LauncherItem::toDesktop(int )
436
void LauncherItem::toggleAlwaysOnTop()
439
void LauncherItem::toggleFullScreen()
442
void LauncherItem::toggleKeptBelowOthers()
445
void LauncherItem::toggleMaximized()
448
void LauncherItem::toggleMinimized()
451
void LauncherItem::toggleShaded()
454
void LauncherItem::close()
460
} // TaskManager namespace
462
#include "launcheritem.moc"