2
* Copyright (C) 2003 Waldo Bastian <bastian@kde.org>
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
25
#include <kdesktopfile.h>
29
#include <kstandarddirs.h>
30
#include <kconfiggroup.h>
36
static QStringList *s_newShortcuts = 0;
37
static QStringList *s_freeShortcuts = 0;
38
static QStringList *s_deletedApps = 0;
41
void MenuFolderInfo::add(MenuSeparatorInfo *info, bool initial)
44
initialLayout.append(info);
48
void MenuFolderInfo::add(MenuFolderInfo *info, bool initial)
50
subFolders.append(info);
52
initialLayout.append(info);
55
// Remove sub menu (without deleting it)
56
void MenuFolderInfo::take(MenuFolderInfo *info)
58
subFolders.take(subFolders.findRef(info));
61
// Remove sub menu (without deleting it)
62
bool MenuFolderInfo::takeRecursive(MenuFolderInfo *info)
64
int i = subFolders.findRef(info);
71
for(MenuFolderInfo *subFolderInfo = subFolders.first();
72
subFolderInfo; subFolderInfo = subFolders.next())
74
if (subFolderInfo->takeRecursive(info))
80
// Recursively update all fullIds
81
void MenuFolderInfo::updateFullId(const QString &parentId)
83
fullId = parentId + id;
85
for(MenuFolderInfo *subFolderInfo = subFolders.first();
86
subFolderInfo; subFolderInfo = subFolders.next())
88
subFolderInfo->updateFullId(fullId);
93
void MenuFolderInfo::add(MenuEntryInfo *entry, bool initial)
95
entries.append(entry);
97
initialLayout.append(entry);
101
void MenuFolderInfo::take(MenuEntryInfo *entry)
103
entries.removeRef(entry);
107
// Return a unique sub-menu caption inspired by @p caption
108
QString MenuFolderInfo::uniqueMenuCaption(const QString &caption)
110
QRegExp r("(.*)(?=-\\d+)");
111
QString cap = (r.indexIn(caption) > -1) ? r.cap(1) : caption;
113
QString result = caption;
115
for(int n = 1; ++n; )
118
for(MenuFolderInfo *subFolderInfo = subFolders.first();
119
subFolderInfo; subFolderInfo = subFolders.next())
121
if (subFolderInfo->caption == result)
130
result = cap + QString("-%1").arg(n);
132
return QString(); // Never reached
135
// Return a unique item caption inspired by @p caption
136
QString MenuFolderInfo::uniqueItemCaption(const QString &caption, const QString &exclude)
138
QRegExp r("(.*)(?=-\\d+)");
139
QString cap = (r.indexIn(caption) > -1) ? r.cap(1) : caption;
141
QString result = caption;
143
for(int n = 1; ++n; )
146
if (result == exclude)
148
MenuEntryInfo *entryInfo;
149
for(Q3PtrListIterator<MenuEntryInfo> it(entries);
150
ok && (entryInfo = it.current()); ++it)
152
if (entryInfo->caption == result)
158
result = cap + QString("-%1").arg(n);
160
return QString(); // Never reached
163
// Return a list of existing submenu ids
164
QStringList MenuFolderInfo::existingMenuIds()
167
for(MenuFolderInfo *subFolderInfo = subFolders.first();
168
subFolderInfo; subFolderInfo = subFolders.next())
170
result.append(subFolderInfo->id);
175
void MenuFolderInfo::setDirty()
180
void MenuFolderInfo::save(MenuFile *menuFile)
185
// Remove hotkeys for applications that have been deleted
186
for(QStringList::ConstIterator it = s_deletedApps->constBegin();
187
it != s_deletedApps->constEnd(); ++it)
189
// The shorcut is deleted if we set a empty sequence
190
KHotKeys::changeMenuEntryShortcut(*it, "");
193
delete s_deletedApps;
199
QString local = KDesktopFile::locateLocal(directoryFile);
201
KDesktopFile *df = 0;
202
if (directoryFile != local)
204
KDesktopFile orig("apps", directoryFile);
205
df = orig.copyTo(local);
209
df = new KDesktopFile("apps", directoryFile);
212
KConfigGroup dg( df->desktopGroup() );
213
dg.writeEntry("Name", caption);
214
dg.writeEntry("GenericName", genericname);
215
dg.writeEntry("Comment", comment);
216
dg.writeEntry("Icon", icon);
223
for(MenuFolderInfo *subFolderInfo = subFolders.first();
224
subFolderInfo; subFolderInfo = subFolders.next())
226
subFolderInfo->save(menuFile);
230
MenuEntryInfo *entryInfo;
231
for(Q3PtrListIterator<MenuEntryInfo> it(entries);
232
(entryInfo = it.current()); ++it)
234
if (entryInfo->needInsertion())
235
menuFile->addEntry(fullId, entryInfo->menuId());
240
bool MenuFolderInfo::hasDirt()
242
if (dirty) return true;
245
for(MenuFolderInfo *subFolderInfo = subFolders.first();
246
subFolderInfo; subFolderInfo = subFolders.next())
248
if (subFolderInfo->hasDirt()) return true;
252
MenuEntryInfo *entryInfo;
253
for(Q3PtrListIterator<MenuEntryInfo> it(entries);
254
(entryInfo = it.current()); ++it)
256
if (entryInfo->dirty) return true;
257
if (entryInfo->shortcutDirty) return true;
262
KService::Ptr MenuFolderInfo::findServiceShortcut(const KShortcut&cut)
264
KService::Ptr result;
266
for(MenuFolderInfo *subFolderInfo = subFolders.first();
267
subFolderInfo; subFolderInfo = subFolders.next())
269
result = subFolderInfo->findServiceShortcut(cut);
275
MenuEntryInfo *entryInfo;
276
for(Q3PtrListIterator<MenuEntryInfo> it(entries);
277
(entryInfo = it.current()); ++it)
279
if (entryInfo->shortCut == cut)
280
return entryInfo->service;
282
return KService::Ptr();
285
void MenuFolderInfo::setInUse(bool inUse)
287
// Propagate to sub-menus
288
for(MenuFolderInfo *subFolderInfo = subFolders.first();
289
subFolderInfo; subFolderInfo = subFolders.next())
291
subFolderInfo->setInUse(inUse);
294
// Propagate to entries
295
MenuEntryInfo *entryInfo;
296
for(Q3PtrListIterator<MenuEntryInfo> it(entries);
297
(entryInfo = it.current()); ++it)
299
entryInfo->setInUse(inUse);
307
MenuEntryInfo::~MenuEntryInfo()
309
m_desktopFile->markAsClean();
310
delete m_desktopFile;
313
KDesktopFile *MenuEntryInfo::desktopFile()
317
m_desktopFile = new KDesktopFile(service->entryPath());
319
return m_desktopFile;
322
void MenuEntryInfo::setDirty()
328
QString local = KStandardDirs::locateLocal("xdgdata-apps", service->menuId());
329
if (local != service->entryPath())
331
KDesktopFile *oldDf = desktopFile();
332
m_desktopFile = oldDf->copyTo(local);
337
bool MenuEntryInfo::needInsertion()
339
// If entry is dirty and previously stored under applnk, then we need to be added explicitly
340
return dirty && !service->entryPath().startsWith('/');
343
void MenuEntryInfo::save()
347
m_desktopFile->sync();
353
if( KHotKeys::present())
355
KHotKeys::changeMenuEntryShortcut( service->storageId(), shortCut.toString() );
357
shortcutDirty = false;
362
void MenuEntryInfo::setCaption(const QString &_caption)
364
if (caption == _caption)
368
desktopFile()->desktopGroup().writeEntry("Name", caption);
371
void MenuEntryInfo::setDescription(const QString &_description)
373
if (description == _description)
375
description = _description;
377
desktopFile()->desktopGroup().writeEntry("GenericName", description);
380
void MenuEntryInfo::setIcon(const QString &_icon)
387
desktopFile()->desktopGroup().writeEntry("Icon", icon);
390
KShortcut MenuEntryInfo::shortcut()
395
shortcutLoaded = true;
396
if( KHotKeys::present())
398
shortCut = KShortcut(KHotKeys::getMenuEntryShortcut( service->storageId() ));
405
static void freeShortcut(const KShortcut &shortCut)
407
if (!shortCut.isEmpty())
409
QString shortcutKey = shortCut.toString();
411
s_newShortcuts->removeAll(shortcutKey);
413
if (!s_freeShortcuts)
414
s_freeShortcuts = new QStringList;
416
s_freeShortcuts->append(shortcutKey);
420
static void allocateShortcut(const KShortcut &shortCut)
422
if (!shortCut.isEmpty())
424
QString shortcutKey = shortCut.toString();
426
s_freeShortcuts->removeAll(shortcutKey);
429
s_newShortcuts = new QStringList;
431
s_newShortcuts->append(shortcutKey);
435
void MenuEntryInfo::setShortcut(const KShortcut &_shortcut)
437
if (shortCut == _shortcut)
440
freeShortcut(shortCut);
441
allocateShortcut(_shortcut);
443
shortCut = _shortcut;
444
if (shortCut.isEmpty())
445
shortCut = KShortcut(); // Normalize
447
shortcutLoaded = true;
448
shortcutDirty = true;
451
void MenuEntryInfo::setInUse(bool inUse)
455
KShortcut temp = shortcut();
456
shortCut = KShortcut();
457
if (isShortcutAvailable(temp))
460
shortcutDirty = true;
461
allocateShortcut(shortCut);
464
s_deletedApps->removeAll(service->storageId());
468
freeShortcut(shortcut());
470
// Add to list of deleted apps
472
s_deletedApps = new QStringList;
474
s_deletedApps->append(service->storageId());
478
bool MenuEntryInfo::isShortcutAvailable(const KShortcut &_shortcut)
480
// We only have to check agains not saved local shortcuts.
481
// KKeySequenceWidget checks against all other registered shortcuts.
482
if (shortCut == _shortcut)
485
QString shortcutKey = _shortcut.toString();
486
bool available = true;
487
if (available && s_newShortcuts)
489
available = !s_newShortcuts->contains(shortcutKey);
491
if (!available && s_freeShortcuts)
493
available = s_freeShortcuts->contains(shortcutKey);