summaryrefslogtreecommitdiffstats
path: root/src/gvcore/externaltoolmanager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gvcore/externaltoolmanager.cpp')
-rw-r--r--src/gvcore/externaltoolmanager.cpp294
1 files changed, 294 insertions, 0 deletions
diff --git a/src/gvcore/externaltoolmanager.cpp b/src/gvcore/externaltoolmanager.cpp
new file mode 100644
index 0000000..1df124f
--- /dev/null
+++ b/src/gvcore/externaltoolmanager.cpp
@@ -0,0 +1,294 @@
+// vim: set tabstop=4 shiftwidth=4 noexpandtab
+/*
+Gwenview - A simple image viewer for KDE
+Copyright 2000-2004 Aurélien Gâteau
+
+ 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+// STL
+#include <list>
+
+// Qt
+#include <qdir.h>
+
+// KDE
+#include <kdebug.h>
+#include <kdesktopfile.h>
+#include <kglobal.h>
+#include <kservice.h>
+#include <kstandarddirs.h>
+#include <kurl.h>
+
+// Local
+#include "externaltoolcontext.h"
+#include "externaltoolmanager.h"
+namespace Gwenview {
+
+#undef ENABLE_LOG
+#undef LOG
+//#define ENABLE_LOG
+#ifdef ENABLE_LOG
+#define LOG(x) kdDebug() << k_funcinfo << x << endl
+#else
+#define LOG(x) ;
+#endif
+
+// Helper functions for createContextInternal
+inline bool mimeTypeMatches(const QString& candidate, const QString& reference) {
+ if (reference=="*") return true;
+
+ if (reference.right(1)=="*") {
+ return candidate.startsWith(reference.left(reference.length()-1));
+ } else {
+ return candidate==reference;
+ }
+}
+
+inline bool isSubSetOf(const QStringList& subSet, const QStringList& set) {
+ // Simple implementation, might need some optimization
+ QStringList::ConstIterator itSubSet=subSet.begin();
+ QStringList::ConstIterator itSetBegin=set.begin();
+ QStringList::ConstIterator itSetEnd=set.end();
+
+ for (; itSubSet!=subSet.end(); ++itSubSet) {
+ bool matchFound=false;
+ QStringList::ConstIterator itSet=itSetBegin;
+ for (; itSet!=itSetEnd; ++itSet) {
+ if (mimeTypeMatches(*itSubSet, *itSet)) {
+ matchFound=true;
+ break;
+ }
+ }
+ if (!matchFound) {
+ return false;
+ }
+ }
+ return true;
+}
+
+
+struct ExternalToolManagerPrivate {
+ QDict<KDesktopFile> mDesktopFiles;
+ QPtrList<KService> mServices;
+ QString mUserToolDir;
+
+ /**
+ * Helper function for createContextInternal
+ */
+ static bool compareKServicePtrByName(const KService* s1, const KService* s2) {
+ Q_ASSERT(s1);
+ Q_ASSERT(s2);
+ return s1->name() < s2->name();
+ }
+
+ ExternalToolContext* createContextInternal(
+ QObject* parent, const KURL::List& urls, const QStringList& mimeTypes)
+ {
+ bool onlyOneURL=urls.size()==1;
+
+ // Only add to selectionServices the services which can handle all the
+ // different mime types present in the selection
+ //
+ // We use std::list instead of QValueList because it's not possible to
+ // pass a sort functor to qHeapSort
+ std::list<KService*> selectionServices;
+ QPtrListIterator<KService> it(mServices);
+ for (; it.current(); ++it) {
+ KService* service=it.current();
+ if (!onlyOneURL && !service->allowMultipleFiles()) {
+ continue;
+ }
+
+ QStringList serviceTypes=service->serviceTypes();
+ if (isSubSetOf(mimeTypes, serviceTypes)) {
+ selectionServices.push_back(service);
+ }
+ }
+ selectionServices.sort(compareKServicePtrByName);
+
+ return new ExternalToolContext(parent, selectionServices, urls);
+ }
+
+};
+
+
+// Helper function for ctor
+void loadDesktopFiles(QDict<KDesktopFile>& dict, const QString& dirString) {
+ QDir dir(dirString);
+ QStringList list=dir.entryList("*.desktop");
+ QStringList::ConstIterator it=list.begin();
+ for (; it!=list.end(); ++it) {
+ KDesktopFile* df=new KDesktopFile( dir.filePath(*it) );
+ dict.insert(*it, df);
+ }
+}
+
+inline QString addSlash(const QString& _str) {
+ QString str(_str);
+ if (str.right(1)!="/") str.append('/');
+ return str;
+}
+
+ExternalToolManager::ExternalToolManager() {
+ d=new ExternalToolManagerPrivate;
+
+ // Getting dirs
+ d->mUserToolDir=KGlobal::dirs()->saveLocation("appdata", "tools");
+ d->mUserToolDir=addSlash(d->mUserToolDir);
+ Q_ASSERT(!d->mUserToolDir.isEmpty());
+ LOG("d->mUserToolDir:" << d->mUserToolDir);
+
+ QStringList dirs=KGlobal::dirs()->findDirs("appdata", "tools");
+ LOG("dirs:" << dirs.join(","));
+
+ // Loading desktop files
+ QDict<KDesktopFile> systemDesktopFiles;
+ QStringList::ConstIterator it;
+ for (it=dirs.begin(); it!=dirs.end(); ++it) {
+ if (addSlash(*it)==d->mUserToolDir) {
+ LOG("skipping " << *it);
+ continue;
+ }
+ LOG("loading system desktop files from " << *it);
+ loadDesktopFiles(systemDesktopFiles, *it);
+ }
+ QDict<KDesktopFile> userDesktopFiles;
+ loadDesktopFiles(userDesktopFiles, d->mUserToolDir);
+
+ // Merge system and user desktop files into our KDesktopFile dictionary
+ d->mDesktopFiles=systemDesktopFiles;
+ d->mDesktopFiles.setAutoDelete(true);
+ QDictIterator<KDesktopFile> itDict(userDesktopFiles);
+
+ for (; itDict.current(); ++itDict) {
+ QString name=itDict.currentKey();
+ KDesktopFile* df=itDict.current();
+ if (d->mDesktopFiles.find(name)) {
+ d->mDesktopFiles.remove(name);
+ }
+ if (df->readBoolEntry("Hidden")) {
+ delete df;
+ } else {
+ d->mDesktopFiles.insert(name, df);
+ }
+ }
+
+ d->mServices.setAutoDelete(true);
+ updateServices();
+}
+
+
+ExternalToolManager::~ExternalToolManager() {
+ delete d;
+}
+
+
+ExternalToolManager* ExternalToolManager::instance() {
+ static ExternalToolManager manager;
+ return &manager;
+}
+
+
+void ExternalToolManager::updateServices() {
+ d->mServices.clear();
+ QDictIterator<KDesktopFile> it(d->mDesktopFiles);
+ for (; it.current(); ++it) {
+ KDesktopFile* desktopFile=it.current();
+ // If sync() is not called, KService does not read up to date content
+ desktopFile->sync();
+ KService* service=new KService(desktopFile);
+ d->mServices.append(service);
+ }
+}
+
+
+QDict<KDesktopFile>& ExternalToolManager::desktopFiles() const {
+ return d->mDesktopFiles;
+}
+
+
+void ExternalToolManager::hideDesktopFile(KDesktopFile* desktopFile) {
+ QFileInfo fi(desktopFile->fileName());
+ QString name=QString("%1.desktop").arg( fi.baseName(true) );
+ d->mDesktopFiles.take(name);
+
+ if (desktopFile->isReadOnly()) {
+ delete desktopFile;
+ desktopFile=new KDesktopFile(d->mUserToolDir + "/" + name, false);
+ }
+ desktopFile->writeEntry("Hidden", true);
+ desktopFile->sync();
+ delete desktopFile;
+}
+
+
+KDesktopFile* ExternalToolManager::editSystemDesktopFile(const KDesktopFile* desktopFile) {
+ Q_ASSERT(desktopFile);
+ QFileInfo fi(desktopFile->fileName());
+
+ QString name=fi.baseName(true);
+ d->mDesktopFiles.remove(QString("%1.desktop").arg(name));
+
+ return createUserDesktopFile(name);
+}
+
+
+KDesktopFile* ExternalToolManager::createUserDesktopFile(const QString& name) {
+ Q_ASSERT(!name.isEmpty());
+ KDesktopFile* desktopFile=new KDesktopFile(
+ d->mUserToolDir + "/" + name + ".desktop", false);
+ d->mDesktopFiles.insert(QString("%1.desktop").arg(name), desktopFile);
+
+ return desktopFile;
+}
+
+
+ExternalToolContext* ExternalToolManager::createContext(
+ QObject* parent, const KFileItemList* items)
+{
+ KURL::List urls;
+ QStringList mimeTypes;
+
+ // Create our URL list and a list of the different mime types present in
+ // the selection
+ QPtrListIterator<KFileItem> it(*items);
+ for (; it.current(); ++it) {
+ urls.append(it.current()->url());
+ QString mimeType=it.current()->mimetype();
+ if (!mimeTypes.contains(mimeType)) {
+ mimeTypes.append(mimeType);
+ }
+ }
+
+ return d->createContextInternal(parent, urls, mimeTypes);
+}
+
+
+ExternalToolContext* ExternalToolManager::createContext(
+ QObject* parent, const KURL& url)
+{
+ KURL::List urls;
+ QStringList mimeTypes;
+
+ urls.append(url);
+ QString mimeType=KMimeType::findByURL(url, 0, url.isLocalFile(), true)->name();
+ mimeTypes.append(mimeType);
+
+ return d->createContextInternal(parent, urls, mimeTypes);
+}
+
+
+} // namespace