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>
27 #include <kstandarddirs.h>
28 #include <kconfiggroup.h>
34 static QStringList
*s_allShortcuts
= 0;
35 static QStringList
*s_newShortcuts
= 0;
36 static QStringList
*s_freeShortcuts
= 0;
37 static QStringList
*s_deletedApps
= 0;
40 void MenuFolderInfo::add(MenuSeparatorInfo
*info
, bool initial
)
43 initialLayout
.append(info
);
47 void MenuFolderInfo::add(MenuFolderInfo
*info
, bool initial
)
49 subFolders
.append(info
);
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
);
70 for(MenuFolderInfo
*subFolderInfo
= subFolders
.first();
71 subFolderInfo
; subFolderInfo
= subFolders
.next())
73 if (subFolderInfo
->takeRecursive(info
))
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
);
92 void MenuFolderInfo::add(MenuEntryInfo
*entry
, bool initial
)
94 entries
.append(entry
);
96 initialLayout
.append(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
; )
117 for(MenuFolderInfo
*subFolderInfo
= subFolders
.first();
118 subFolderInfo
; subFolderInfo
= subFolders
.next())
120 if (subFolderInfo
->caption
== 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
; )
145 if (result
== exclude
)
147 MenuEntryInfo
*entryInfo
;
148 for(Q3PtrListIterator
<MenuEntryInfo
> it(entries
);
149 ok
&& (entryInfo
= it
.current()); ++it
)
151 if (entryInfo
->caption
== 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()
166 for(MenuFolderInfo
*subFolderInfo
= subFolders
.first();
167 subFolderInfo
; subFolderInfo
= subFolders
.next())
169 result
.append(subFolderInfo
->id
);
174 void MenuFolderInfo::setDirty()
179 void MenuFolderInfo::save(MenuFile
*menuFile
)
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
;
195 QString local
= KDesktopFile::locateLocal(directoryFile
);
197 KDesktopFile
*df
= 0;
198 if (directoryFile
!= local
)
200 KDesktopFile
orig("apps", directoryFile
);
201 df
= orig
.copyTo(local
);
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
);
219 for(MenuFolderInfo
*subFolderInfo
= subFolders
.first();
220 subFolderInfo
; subFolderInfo
= subFolders
.next())
222 subFolderInfo
->save(menuFile
);
226 MenuEntryInfo
*entryInfo
;
227 for(Q3PtrListIterator
<MenuEntryInfo
> it(entries
);
228 (entryInfo
= it
.current()); ++it
)
230 if (entryInfo
->needInsertion())
231 menuFile
->addEntry(fullId
, entryInfo
->menuId());
236 bool MenuFolderInfo::hasDirt()
238 if (dirty
) return true;
241 for(MenuFolderInfo
*subFolderInfo
= subFolders
.first();
242 subFolderInfo
; subFolderInfo
= subFolders
.next())
244 if (subFolderInfo
->hasDirt()) return true;
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;
258 KService::Ptr
MenuFolderInfo::findServiceShortcut(const KShortcut
&cut
)
260 KService::Ptr result
;
262 for(MenuFolderInfo
*subFolderInfo
= subFolders
.first();
263 subFolderInfo
; subFolderInfo
= subFolders
.next())
265 result
= subFolderInfo
->findServiceShortcut(cut
);
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
);
303 MenuEntryInfo::~MenuEntryInfo()
305 m_desktopFile
->markAsClean();
306 delete m_desktopFile
;
309 KDesktopFile
*MenuEntryInfo::desktopFile()
313 m_desktopFile
= new KDesktopFile(service
->entryPath());
315 return m_desktopFile
;
318 void MenuEntryInfo::setDirty()
324 QString local
= KStandardDirs::locateLocal("xdgdata-apps", service
->menuId());
325 if (local
!= service
->entryPath())
327 KDesktopFile
*oldDf
= desktopFile();
328 m_desktopFile
= oldDf
->copyTo(local
);
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()
343 m_desktopFile
->sync();
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
)
363 desktopFile()->desktopGroup().writeEntry("Name", caption
);
366 void MenuEntryInfo::setDescription(const QString
&_description
)
368 if (description
== _description
)
370 description
= _description
;
372 desktopFile()->desktopGroup().writeEntry("GenericName", description
);
375 void MenuEntryInfo::setIcon(const QString
&_icon
)
382 desktopFile()->desktopGroup().writeEntry("Icon", icon
);
385 KShortcut
MenuEntryInfo::shortcut()
389 shortcutLoaded
= true;
390 if( KHotKeys::present())
392 shortCut
= KShortcut(KHotKeys::getMenuEntryShortcut( service
->storageId() ));
398 static void freeShortcut(const KShortcut
&shortCut
)
400 if (!shortCut
.isEmpty())
402 QString shortcutKey
= shortCut
.toString();
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();
419 s_freeShortcuts
->removeAll(shortcutKey
);
422 s_newShortcuts
= new QStringList
;
424 s_newShortcuts
->append(shortcutKey
);
428 void MenuEntryInfo::setShortcut(const KShortcut
&_shortcut
)
430 if (shortCut
== _shortcut
)
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
)
448 KShortcut temp
= shortcut();
449 shortCut
= KShortcut();
450 if (isShortcutAvailable(temp
))
453 shortcutDirty
= true;
454 allocateShortcut(shortCut
);
457 s_deletedApps
->removeAll(service
->storageId());
461 freeShortcut(shortcut());
463 // Add to list of deleted apps
465 s_deletedApps
= new QStringList
;
467 s_deletedApps
->append(service
->storageId());
471 bool MenuEntryInfo::isShortcutAvailable(const KShortcut
&_shortcut
)
473 if (shortCut
== _shortcut
)
476 QString shortcutKey
= _shortcut
.toString();
477 bool available
= true;
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
);