Add (and install) svg for the new krunner interface.
[kdebase/uwolfer.git] / workspace / kmenuedit / menuinfo.cpp
blob4e4e74c6f9fed9240b3c61b843ef9b8bb6373766
1 /*
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.
20 #include "menuinfo.h"
21 #include "menufile.h"
23 #include <QRegExp>
25 #include <kdesktopfile.h>
26 #include <khotkeys.h>
27 #include <kstandarddirs.h>
28 #include <kconfiggroup.h>
31 // MenuFolderInfo
34 static QStringList *s_allShortcuts = 0;
35 static QStringList *s_newShortcuts = 0;
36 static QStringList *s_freeShortcuts = 0;
37 static QStringList *s_deletedApps = 0;
39 // Add separator
40 void MenuFolderInfo::add(MenuSeparatorInfo *info, bool initial)
42 if (initial)
43 initialLayout.append(info);
46 // Add sub menu
47 void MenuFolderInfo::add(MenuFolderInfo *info, bool initial)
49 subFolders.append(info);
50 if (initial)
51 initialLayout.append(info);
54 // Remove sub menu (without deleting it)
55 void MenuFolderInfo::take(MenuFolderInfo *info)
57 subFolders.take(subFolders.findRef(info));
60 // Remove sub menu (without deleting it)
61 bool MenuFolderInfo::takeRecursive(MenuFolderInfo *info)
63 int i = subFolders.findRef(info);
64 if (i >= 0)
66 subFolders.take(i);
67 return true;
70 for(MenuFolderInfo *subFolderInfo = subFolders.first();
71 subFolderInfo; subFolderInfo = subFolders.next())
73 if (subFolderInfo->takeRecursive(info))
74 return true;
76 return false;
79 // Recursively update all fullIds
80 void MenuFolderInfo::updateFullId(const QString &parentId)
82 fullId = parentId + id;
84 for(MenuFolderInfo *subFolderInfo = subFolders.first();
85 subFolderInfo; subFolderInfo = subFolders.next())
87 subFolderInfo->updateFullId(fullId);
91 // Add entry
92 void MenuFolderInfo::add(MenuEntryInfo *entry, bool initial)
94 entries.append(entry);
95 if (initial)
96 initialLayout.append(entry);
99 // Remove entry
100 void MenuFolderInfo::take(MenuEntryInfo *entry)
102 entries.removeRef(entry);
106 // Return a unique sub-menu caption inspired by @p caption
107 QString MenuFolderInfo::uniqueMenuCaption(const QString &caption)
109 QRegExp r("(.*)(?=-\\d+)");
110 QString cap = (r.indexIn(caption) > -1) ? r.cap(1) : caption;
112 QString result = caption;
114 for(int n = 1; ++n; )
116 bool ok = true;
117 for(MenuFolderInfo *subFolderInfo = subFolders.first();
118 subFolderInfo; subFolderInfo = subFolders.next())
120 if (subFolderInfo->caption == result)
122 ok = false;
123 break;
126 if (ok)
127 return result;
129 result = cap + QString("-%1").arg(n);
131 return QString(); // Never reached
134 // Return a unique item caption inspired by @p caption
135 QString MenuFolderInfo::uniqueItemCaption(const QString &caption, const QString &exclude)
137 QRegExp r("(.*)(?=-\\d+)");
138 QString cap = (r.indexIn(caption) > -1) ? r.cap(1) : caption;
140 QString result = caption;
142 for(int n = 1; ++n; )
144 bool ok = true;
145 if (result == exclude)
146 ok = false;
147 MenuEntryInfo *entryInfo;
148 for(Q3PtrListIterator<MenuEntryInfo> it(entries);
149 ok && (entryInfo = it.current()); ++it)
151 if (entryInfo->caption == result)
152 ok = false;
154 if (ok)
155 return result;
157 result = cap + QString("-%1").arg(n);
159 return QString(); // Never reached
162 // Return a list of existing submenu ids
163 QStringList MenuFolderInfo::existingMenuIds()
165 QStringList result;
166 for(MenuFolderInfo *subFolderInfo = subFolders.first();
167 subFolderInfo; subFolderInfo = subFolders.next())
169 result.append(subFolderInfo->id);
171 return result;
174 void MenuFolderInfo::setDirty()
176 dirty = true;
179 void MenuFolderInfo::save(MenuFile *menuFile)
181 if (s_deletedApps)
183 // Remove hotkeys for applications that have been deleted
184 for(QStringList::ConstIterator it = s_deletedApps->begin();
185 it != s_deletedApps->end(); ++it)
187 KHotKeys::menuEntryDeleted(*it);
189 delete s_deletedApps;
190 s_deletedApps = 0;
193 if (dirty)
195 QString local = KDesktopFile::locateLocal(directoryFile);
197 KDesktopFile *df = 0;
198 if (directoryFile != local)
200 KDesktopFile orig("apps", directoryFile);
201 df = orig.copyTo(local);
203 else
205 df = new KDesktopFile("apps", directoryFile);
208 KConfigGroup dg( df->desktopGroup() );
209 dg.writeEntry("Name", caption);
210 dg.writeEntry("GenericName", genericname);
211 dg.writeEntry("Comment", comment);
212 dg.writeEntry("Icon", icon);
213 dg.sync();
214 delete df;
215 dirty = false;
218 // Save sub-menus
219 for(MenuFolderInfo *subFolderInfo = subFolders.first();
220 subFolderInfo; subFolderInfo = subFolders.next())
222 subFolderInfo->save(menuFile);
225 // Save entries
226 MenuEntryInfo *entryInfo;
227 for(Q3PtrListIterator<MenuEntryInfo> it(entries);
228 (entryInfo = it.current()); ++it)
230 if (entryInfo->needInsertion())
231 menuFile->addEntry(fullId, entryInfo->menuId());
232 entryInfo->save();
236 bool MenuFolderInfo::hasDirt()
238 if (dirty) return true;
240 // Check sub-menus
241 for(MenuFolderInfo *subFolderInfo = subFolders.first();
242 subFolderInfo; subFolderInfo = subFolders.next())
244 if (subFolderInfo->hasDirt()) return true;
247 // Check entries
248 MenuEntryInfo *entryInfo;
249 for(Q3PtrListIterator<MenuEntryInfo> it(entries);
250 (entryInfo = it.current()); ++it)
252 if (entryInfo->dirty) return true;
253 if (entryInfo->shortcutDirty) return true;
255 return false;
258 KService::Ptr MenuFolderInfo::findServiceShortcut(const KShortcut&cut)
260 KService::Ptr result;
261 // Check sub-menus
262 for(MenuFolderInfo *subFolderInfo = subFolders.first();
263 subFolderInfo; subFolderInfo = subFolders.next())
265 result = subFolderInfo->findServiceShortcut(cut);
266 if (result)
267 return result;
270 // Check entries
271 MenuEntryInfo *entryInfo;
272 for(Q3PtrListIterator<MenuEntryInfo> it(entries);
273 (entryInfo = it.current()); ++it)
275 if (entryInfo->shortCut == cut)
276 return entryInfo->service;
278 return KService::Ptr();
281 void MenuFolderInfo::setInUse(bool inUse)
283 // Propagate to sub-menus
284 for(MenuFolderInfo *subFolderInfo = subFolders.first();
285 subFolderInfo; subFolderInfo = subFolders.next())
287 subFolderInfo->setInUse(inUse);
290 // Propagate to entries
291 MenuEntryInfo *entryInfo;
292 for(Q3PtrListIterator<MenuEntryInfo> it(entries);
293 (entryInfo = it.current()); ++it)
295 entryInfo->setInUse(inUse);
300 // MenuEntryInfo
303 MenuEntryInfo::~MenuEntryInfo()
305 m_desktopFile->markAsClean();
306 delete m_desktopFile;
309 KDesktopFile *MenuEntryInfo::desktopFile()
311 if (!m_desktopFile)
313 m_desktopFile = new KDesktopFile(service->entryPath());
315 return m_desktopFile;
318 void MenuEntryInfo::setDirty()
320 if (dirty) return;
322 dirty = true;
324 QString local = KStandardDirs::locateLocal("xdgdata-apps", service->menuId());
325 if (local != service->entryPath())
327 KDesktopFile *oldDf = desktopFile();
328 m_desktopFile = oldDf->copyTo(local);
329 delete oldDf;
333 bool MenuEntryInfo::needInsertion()
335 // If entry is dirty and previously stored under applnk, then we need to be added explicitly
336 return dirty && !service->entryPath().startsWith('/');
339 void MenuEntryInfo::save()
341 if (dirty)
343 m_desktopFile->sync();
344 dirty = false;
347 if (shortcutDirty)
349 if( KHotKeys::present())
351 KHotKeys::changeMenuEntryShortcut( service->storageId(), shortCut.toString() );
353 shortcutDirty = false;
357 void MenuEntryInfo::setCaption(const QString &_caption)
359 if (caption == _caption)
360 return;
361 caption = _caption;
362 setDirty();
363 desktopFile()->desktopGroup().writeEntry("Name", caption);
366 void MenuEntryInfo::setDescription(const QString &_description)
368 if (description == _description)
369 return;
370 description = _description;
371 setDirty();
372 desktopFile()->desktopGroup().writeEntry("GenericName", description);
375 void MenuEntryInfo::setIcon(const QString &_icon)
377 if (icon == _icon)
378 return;
380 icon = _icon;
381 setDirty();
382 desktopFile()->desktopGroup().writeEntry("Icon", icon);
385 KShortcut MenuEntryInfo::shortcut()
387 if (!shortcutLoaded)
389 shortcutLoaded = true;
390 if( KHotKeys::present())
392 shortCut = KShortcut(KHotKeys::getMenuEntryShortcut( service->storageId() ));
395 return shortCut;
398 static void freeShortcut(const KShortcut &shortCut)
400 if (!shortCut.isEmpty())
402 QString shortcutKey = shortCut.toString();
403 if (s_newShortcuts)
404 s_newShortcuts->removeAll(shortcutKey);
406 if (!s_freeShortcuts)
407 s_freeShortcuts = new QStringList;
409 s_freeShortcuts->append(shortcutKey);
413 static void allocateShortcut(const KShortcut &shortCut)
415 if (!shortCut.isEmpty())
417 QString shortcutKey = shortCut.toString();
418 if (s_freeShortcuts)
419 s_freeShortcuts->removeAll(shortcutKey);
421 if (!s_newShortcuts)
422 s_newShortcuts = new QStringList;
424 s_newShortcuts->append(shortcutKey);
428 void MenuEntryInfo::setShortcut(const KShortcut &_shortcut)
430 if (shortCut == _shortcut)
431 return;
433 freeShortcut(shortCut);
434 allocateShortcut(_shortcut);
436 shortCut = _shortcut;
437 if (shortCut.isEmpty())
438 shortCut = KShortcut(); // Normalize
440 shortcutLoaded = true;
441 shortcutDirty = true;
444 void MenuEntryInfo::setInUse(bool inUse)
446 if (inUse)
448 KShortcut temp = shortcut();
449 shortCut = KShortcut();
450 if (isShortcutAvailable(temp))
451 shortCut = temp;
452 else
453 shortcutDirty = true;
454 allocateShortcut(shortCut);
456 if (s_deletedApps)
457 s_deletedApps->removeAll(service->storageId());
459 else
461 freeShortcut(shortcut());
463 // Add to list of deleted apps
464 if (!s_deletedApps)
465 s_deletedApps = new QStringList;
467 s_deletedApps->append(service->storageId());
471 bool MenuEntryInfo::isShortcutAvailable(const KShortcut &_shortcut)
473 if (shortCut == _shortcut)
474 return true;
476 QString shortcutKey = _shortcut.toString();
477 bool available = true;
478 if (!s_allShortcuts)
480 s_allShortcuts = new QStringList(KHotKeys::allShortCuts());
482 available = !s_allShortcuts->contains(shortcutKey);
483 if (available && s_newShortcuts)
485 available = !s_newShortcuts->contains(shortcutKey);
487 if (!available && s_freeShortcuts)
489 available = s_freeShortcuts->contains(shortcutKey);
491 return available;