summaryrefslogtreecommitdiffstats
path: root/kmenuedit/menuinfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kmenuedit/menuinfo.cpp')
-rw-r--r--kmenuedit/menuinfo.cpp502
1 files changed, 502 insertions, 0 deletions
diff --git a/kmenuedit/menuinfo.cpp b/kmenuedit/menuinfo.cpp
new file mode 100644
index 000000000..1fa4cb436
--- /dev/null
+++ b/kmenuedit/menuinfo.cpp
@@ -0,0 +1,502 @@
+/*
+ * Copyright (C) 2003 Waldo Bastian <bastian@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "menuinfo.h"
+#include "menufile.h"
+
+#include <qregexp.h>
+
+#include <kdesktopfile.h>
+#include <khotkeys.h>
+#include <kstandarddirs.h>
+
+//
+// MenuFolderInfo
+//
+
+static QStringList *s_allShortcuts = 0;
+static QStringList *s_newShortcuts = 0;
+static QStringList *s_freeShortcuts = 0;
+static QStringList *s_deletedApps = 0;
+
+// Add separator
+void MenuFolderInfo::add(MenuSeparatorInfo *info, bool initial)
+{
+ if (initial)
+ initialLayout.append(info);
+}
+
+// Add sub menu
+void MenuFolderInfo::add(MenuFolderInfo *info, bool initial)
+{
+ subFolders.append(info);
+ if (initial)
+ initialLayout.append(info);
+}
+
+// Remove sub menu (without deleting it)
+void MenuFolderInfo::take(MenuFolderInfo *info)
+{
+ subFolders.take(subFolders.findRef(info));
+}
+
+// Remove sub menu (without deleting it)
+bool MenuFolderInfo::takeRecursive(MenuFolderInfo *info)
+{
+ int i = subFolders.findRef(info);
+ if (i >= 0)
+ {
+ subFolders.take(i);
+ return true;
+ }
+
+ for(MenuFolderInfo *subFolderInfo = subFolders.first();
+ subFolderInfo; subFolderInfo = subFolders.next())
+ {
+ if (subFolderInfo->takeRecursive(info))
+ return true;
+ }
+ return false;
+}
+
+// Recursively update all fullIds
+void MenuFolderInfo::updateFullId(const QString &parentId)
+{
+ fullId = parentId + id;
+
+ for(MenuFolderInfo *subFolderInfo = subFolders.first();
+ subFolderInfo; subFolderInfo = subFolders.next())
+ {
+ subFolderInfo->updateFullId(fullId);
+ }
+}
+
+// Add entry
+void MenuFolderInfo::add(MenuEntryInfo *entry, bool initial)
+{
+ entries.append(entry);
+ if (initial)
+ initialLayout.append(entry);
+}
+
+// Remove entry
+void MenuFolderInfo::take(MenuEntryInfo *entry)
+{
+ entries.removeRef(entry);
+}
+
+
+// Return a unique sub-menu caption inspired by @p caption
+QString MenuFolderInfo::uniqueMenuCaption(const QString &caption)
+{
+ QRegExp r("(.*)(?=-\\d+)");
+ QString cap = (r.search(caption) > -1) ? r.cap(1) : caption;
+
+ QString result = caption;
+
+ for(int n = 1; ++n; )
+ {
+ bool ok = true;
+ for(MenuFolderInfo *subFolderInfo = subFolders.first();
+ subFolderInfo; subFolderInfo = subFolders.next())
+ {
+ if (subFolderInfo->caption == result)
+ {
+ ok = false;
+ break;
+ }
+ }
+ if (ok)
+ return result;
+
+ result = cap + QString("-%1").arg(n);
+ }
+ return QString::null; // Never reached
+}
+
+// Return a unique item caption inspired by @p caption
+QString MenuFolderInfo::uniqueItemCaption(const QString &caption, const QString &exclude)
+{
+ QRegExp r("(.*)(?=-\\d+)");
+ QString cap = (r.search(caption) > -1) ? r.cap(1) : caption;
+
+ QString result = caption;
+
+ for(int n = 1; ++n; )
+ {
+ bool ok = true;
+ if (result == exclude)
+ ok = false;
+ MenuEntryInfo *entryInfo;
+ for(QPtrListIterator<MenuEntryInfo> it(entries);
+ ok && (entryInfo = it.current()); ++it)
+ {
+ if (entryInfo->caption == result)
+ ok = false;
+ }
+ if (ok)
+ return result;
+
+ result = cap + QString("-%1").arg(n);
+ }
+ return QString::null; // Never reached
+}
+
+// Return a list of existing submenu ids
+QStringList MenuFolderInfo::existingMenuIds()
+{
+ QStringList result;
+ for(MenuFolderInfo *subFolderInfo = subFolders.first();
+ subFolderInfo; subFolderInfo = subFolders.next())
+ {
+ result.append(subFolderInfo->id);
+ }
+ return result;
+}
+
+void MenuFolderInfo::setDirty()
+{
+ dirty = true;
+}
+
+void MenuFolderInfo::save(MenuFile *menuFile)
+{
+ if (s_deletedApps)
+ {
+ // Remove hotkeys for applications that have been deleted
+ for(QStringList::ConstIterator it = s_deletedApps->begin();
+ it != s_deletedApps->end(); ++it)
+ {
+ KHotKeys::menuEntryDeleted(*it);
+ }
+ delete s_deletedApps;
+ s_deletedApps = 0;
+ }
+
+ if (dirty)
+ {
+ QString local = KDesktopFile::locateLocal(directoryFile);
+
+ KConfig *df = 0;
+ if (directoryFile != local)
+ {
+ KConfig orig(directoryFile, true, false, "apps");
+ df = orig.copyTo(local);
+ }
+ else
+ {
+ df = new KConfig(directoryFile, false, false, "apps");
+ }
+
+ df->setDesktopGroup();
+ df->writeEntry("Name", caption);
+ df->writeEntry("GenericName", genericname);
+ df->writeEntry("Comment", comment);
+ df->writeEntry("Icon", icon);
+ df->sync();
+ delete df;
+ dirty = false;
+ }
+
+ // Save sub-menus
+ for(MenuFolderInfo *subFolderInfo = subFolders.first();
+ subFolderInfo; subFolderInfo = subFolders.next())
+ {
+ subFolderInfo->save(menuFile);
+ }
+
+ // Save entries
+ MenuEntryInfo *entryInfo;
+ for(QPtrListIterator<MenuEntryInfo> it(entries);
+ (entryInfo = it.current()); ++it)
+ {
+ if (entryInfo->needInsertion())
+ menuFile->addEntry(fullId, entryInfo->menuId());
+ entryInfo->save();
+ }
+}
+
+bool MenuFolderInfo::hasDirt()
+{
+ if (dirty) return true;
+
+ // Check sub-menus
+ for(MenuFolderInfo *subFolderInfo = subFolders.first();
+ subFolderInfo; subFolderInfo = subFolders.next())
+ {
+ if (subFolderInfo->hasDirt()) return true;
+ }
+
+ // Check entries
+ MenuEntryInfo *entryInfo;
+ for(QPtrListIterator<MenuEntryInfo> it(entries);
+ (entryInfo = it.current()); ++it)
+ {
+ if (entryInfo->dirty) return true;
+ if (entryInfo->shortcutDirty) return true;
+ }
+ return false;
+}
+
+KService::Ptr MenuFolderInfo::findServiceShortcut(const KShortcut&cut)
+{
+ KService::Ptr result;
+ // Check sub-menus
+ for(MenuFolderInfo *subFolderInfo = subFolders.first();
+ subFolderInfo; subFolderInfo = subFolders.next())
+ {
+ result = subFolderInfo->findServiceShortcut(cut);
+ if (result)
+ return result;
+ }
+
+ // Check entries
+ MenuEntryInfo *entryInfo;
+ for(QPtrListIterator<MenuEntryInfo> it(entries);
+ (entryInfo = it.current()); ++it)
+ {
+ if (entryInfo->shortCut == cut)
+ return entryInfo->service;
+ }
+ return 0;
+}
+
+void MenuFolderInfo::setInUse(bool inUse)
+{
+ // Propagate to sub-menus
+ for(MenuFolderInfo *subFolderInfo = subFolders.first();
+ subFolderInfo; subFolderInfo = subFolders.next())
+ {
+ subFolderInfo->setInUse(inUse);
+ }
+
+ // Propagate to entries
+ MenuEntryInfo *entryInfo;
+ for(QPtrListIterator<MenuEntryInfo> it(entries);
+ (entryInfo = it.current()); ++it)
+ {
+ entryInfo->setInUse(inUse);
+ }
+}
+
+//
+// MenuEntryInfo
+//
+
+MenuEntryInfo::~MenuEntryInfo()
+{
+ df->rollback(false);
+ delete df;
+}
+
+KDesktopFile *MenuEntryInfo::desktopFile()
+{
+ if (!df)
+ {
+ df = new KDesktopFile(service->desktopEntryPath());
+ }
+ return df;
+}
+
+void MenuEntryInfo::setDirty()
+{
+ if (dirty) return;
+
+ dirty = true;
+
+ QString local = locateLocal("xdgdata-apps", service->menuId());
+ if (local != service->desktopEntryPath())
+ {
+ KDesktopFile *oldDf = desktopFile();
+ df = oldDf->copyTo(local);
+ df->setDesktopGroup();
+ delete oldDf;
+ }
+}
+
+bool MenuEntryInfo::needInsertion()
+{
+ // If entry is dirty and previously stored under applnk, then we need to be added explicity
+ return dirty && !service->desktopEntryPath().startsWith("/");
+}
+
+void MenuEntryInfo::save()
+{
+ if (dirty)
+ {
+ df->sync();
+ dirty = false;
+ }
+
+ if (shortcutDirty)
+ {
+ if( KHotKeys::present())
+ {
+ KHotKeys::changeMenuEntryShortcut( service->storageId(), shortCut.toStringInternal() );
+ }
+ shortcutDirty = false;
+ }
+}
+
+void MenuEntryInfo::setCaption(const QString &_caption)
+{
+ if (caption == _caption)
+ return;
+ caption = _caption;
+ setDirty();
+ desktopFile()->writeEntry("Name", caption);
+}
+
+void MenuEntryInfo::setDescription(const QString &_description)
+{
+ if (description == _description)
+ return;
+ description = _description;
+ setDirty();
+ desktopFile()->writeEntry("GenericName", description);
+}
+
+void MenuEntryInfo::setIcon(const QString &_icon)
+{
+ if (icon == _icon)
+ return;
+
+ icon = _icon;
+ setDirty();
+ desktopFile()->writeEntry("Icon", icon);
+}
+
+KShortcut MenuEntryInfo::shortcut()
+{
+ if (!shortcutLoaded)
+ {
+ shortcutLoaded = true;
+ if( KHotKeys::present())
+ {
+ shortCut = KHotKeys::getMenuEntryShortcut( service->storageId() );
+ }
+ }
+ return shortCut;
+}
+
+static bool isEmpty(const KShortcut &shortCut)
+{
+ for(int i = shortCut.count(); i--;)
+ {
+ if (!shortCut.seq(i).isNull())
+ return false;
+ }
+ return true;
+}
+
+static void freeShortcut(const KShortcut &shortCut)
+{
+ if (!isEmpty(shortCut))
+ {
+ QString shortcutKey = shortCut.toString();
+ if (s_newShortcuts)
+ s_newShortcuts->remove(shortcutKey);
+
+ if (!s_freeShortcuts)
+ s_freeShortcuts = new QStringList;
+
+ s_freeShortcuts->append(shortcutKey);
+ }
+}
+
+static void allocateShortcut(const KShortcut &shortCut)
+{
+ if (!isEmpty(shortCut))
+ {
+ QString shortcutKey = shortCut.toString();
+ if (s_freeShortcuts)
+ s_freeShortcuts->remove(shortcutKey);
+
+ if (!s_newShortcuts)
+ s_newShortcuts = new QStringList;
+
+ s_newShortcuts->append(shortcutKey);
+ }
+}
+
+void MenuEntryInfo::setShortcut(const KShortcut &_shortcut)
+{
+ if (shortCut == _shortcut)
+ return;
+
+ freeShortcut(shortCut);
+ allocateShortcut(_shortcut);
+
+ shortCut = _shortcut;
+ if (isEmpty(shortCut))
+ shortCut = KShortcut(); // Normalize
+
+ shortcutLoaded = true;
+ shortcutDirty = true;
+}
+
+void MenuEntryInfo::setInUse(bool inUse)
+{
+ if (inUse)
+ {
+ KShortcut temp = shortcut();
+ shortCut = KShortcut();
+ if (isShortcutAvailable(temp))
+ shortCut = temp;
+ else
+ shortcutDirty = true;
+ allocateShortcut(shortCut);
+
+ if (s_deletedApps)
+ s_deletedApps->remove(service->storageId());
+ }
+ else
+ {
+ freeShortcut(shortcut());
+
+ // Add to list of deleted apps
+ if (!s_deletedApps)
+ s_deletedApps = new QStringList;
+
+ s_deletedApps->append(service->storageId());
+ }
+}
+
+bool MenuEntryInfo::isShortcutAvailable(const KShortcut &_shortcut)
+{
+ if (shortCut == _shortcut)
+ return true;
+
+ QString shortcutKey = _shortcut.toString();
+ bool available = true;
+ if (!s_allShortcuts)
+ {
+ s_allShortcuts = new QStringList(KHotKeys::allShortCuts());
+ }
+ available = !s_allShortcuts->contains(shortcutKey);
+ if (available && s_newShortcuts)
+ {
+ available = !s_newShortcuts->contains(shortcutKey);
+ }
+ if (!available && s_freeShortcuts)
+ {
+ available = s_freeShortcuts->contains(shortcutKey);
+ }
+ return available;
+}