1 /* This file is part of the KDE project
2    Copyright (C) 1998, 1999, 2000 Torben Weis <weis@kde.org>
3    Copyright (C) 2001 David Faure <faure@kde.org>
4 
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Library General Public
7    License as published by the Free Software Foundation; either
8    version 2 of the License, or (at your option) any later version.
9 
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Library General Public License for more details.
14 
15    You should have received a copy of the GNU Library General Public License
16    along with this library; see the file COPYING.LIB.  If not, write to
17    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18    Boston, MA 02110-1301, USA.
19 */
20 
21 #include "kdatatool.h"
22 
23 #include <kactioncollection.h>
24 
25 #include <kservicetypetrader.h>
26 
27 #include <QPixmap>
28 #include <QFile>
29 #include <QDebug>
30 
31 /*************************************************
32  *
33  * KDataToolInfo
34  *
35  *************************************************/
36 class Q_DECL_HIDDEN KDataToolInfo::KDataToolInfoPrivate
37 {
38 public:
KDataToolInfoPrivate()39     KDataToolInfoPrivate()
40         : service(nullptr)
41     {}
42 
43     KService::Ptr service;
44     QString componentName;
45 };
46 
KDataToolInfo()47 KDataToolInfo::KDataToolInfo()
48     : d(new KDataToolInfoPrivate)
49 {
50 }
51 
KDataToolInfo(const KService::Ptr & service,const QString & componentName)52 KDataToolInfo::KDataToolInfo(const KService::Ptr &service, const QString &componentName)
53     : d(new KDataToolInfoPrivate)
54 {
55     d->service = service;
56     d->componentName = componentName;
57 
58     if (!d->service && !d->service->serviceTypes().contains("KDataTool")) {
59         /*qDebug() << "The service" << d->service->name()
60                        << "does not feature the service type KDataTool";*/
61         d->service = nullptr;
62     }
63 }
64 
KDataToolInfo(const KDataToolInfo & info)65 KDataToolInfo::KDataToolInfo(const KDataToolInfo &info)
66     : d(new KDataToolInfoPrivate)
67 {
68     d->service = info.service();
69     d->componentName = info.componentName();
70 }
71 
operator =(const KDataToolInfo & info)72 KDataToolInfo &KDataToolInfo::operator= (const KDataToolInfo &info)
73 {
74     d->service = info.service();
75     d->componentName = info.componentName();
76     return *this;
77 }
78 
~KDataToolInfo()79 KDataToolInfo::~KDataToolInfo()
80 {
81     delete d;
82 }
83 
dataType() const84 QString KDataToolInfo::dataType() const
85 {
86     if (!d->service) {
87         return QString();
88     }
89 
90     return d->service->property("DataType").toString();
91 }
92 
mimeTypes() const93 QStringList KDataToolInfo::mimeTypes() const
94 {
95     if (!d->service) {
96         return QStringList();
97     }
98 
99     return d->service->property("DataMimeTypes").toStringList();
100 }
101 
isReadOnly() const102 bool KDataToolInfo::isReadOnly() const
103 {
104     if (!d->service) {
105         return true;
106     }
107 
108     return d->service->property("ReadOnly").toBool();
109 }
110 
iconName() const111 QString KDataToolInfo::iconName() const
112 {
113     if (!d->service) {
114         return QString();
115     }
116     return d->service->icon();
117 }
118 
commands() const119 QStringList KDataToolInfo::commands() const
120 {
121     if (!d->service) {
122         return QStringList();
123     }
124 
125     return d->service->property("Commands").toStringList();
126 }
127 
userCommands() const128 QStringList KDataToolInfo::userCommands() const
129 {
130     if (!d->service) {
131         return QStringList();
132     }
133 
134     return d->service->comment().split(',', QString::SkipEmptyParts);
135 }
136 
createTool(QObject * parent) const137 KDataTool *KDataToolInfo::createTool(QObject *parent) const
138 {
139     if (!d->service) {
140         return nullptr;
141     }
142 
143     KDataTool *tool = d->service->createInstance<KDataTool>(parent);
144     if (tool) {
145         tool->setComponentName(d->componentName);
146     }
147     return tool;
148 }
149 
service() const150 KService::Ptr KDataToolInfo::service() const
151 {
152     return d->service;
153 }
154 
componentName() const155 QString KDataToolInfo::componentName() const
156 {
157     return d->componentName;
158 }
159 
query(const QString & datatype,const QString & mimetype,const QString & componentName)160 QList<KDataToolInfo> KDataToolInfo::query(const QString &datatype, const QString &mimetype, const QString &componentName)
161 {
162     QList<KDataToolInfo> lst;
163 
164     QString constr;
165 
166     if (!datatype.isEmpty()) {
167         constr = QString::fromLatin1("DataType == '%1'").arg(datatype);
168     }
169     if (!mimetype.isEmpty()) {
170         QString tmp = QString::fromLatin1("'%1' in DataMimeTypes").arg(mimetype);
171         if (constr.isEmpty()) {
172             constr = tmp;
173         } else {
174             constr = constr + " and " + tmp;
175         }
176     }
177     /* Bug in KServiceTypeTrader ? Test with HEAD-kdelibs!
178         if (!componentName.isEmpty())
179         {
180             QString tmp = QString::fromLatin1( "not ('%1' in ExcludeFrom)" ).arg(componentName);
181             if ( constr.isEmpty() )
182                 constr = tmp;
183             else
184                 constr = constr + " and " + tmp;
185         } */
186 
187     // Query the trader
188     //qDebug() << constr;
189     const KService::List offers = KServiceTypeTrader::self()->query("KDataTool", constr);
190 
191     KService::List::ConstIterator it = offers.begin();
192     for (; it != offers.end(); ++it) {
193         // Temporary replacement for the non-working trader query above
194         if (componentName.isEmpty() || !(*it)->property("ExcludeFrom").toStringList()
195                 .contains(componentName)) {
196             lst.append(KDataToolInfo(*it, componentName));
197         } else {
198             //qDebug() << (*it)->entryPath() << " excluded.";
199         }
200     }
201 
202     return lst;
203 }
204 
isValid() const205 bool KDataToolInfo::isValid() const
206 {
207     return (d->service);
208 }
209 
210 /*************************************************
211  *
212  * KDataToolAction
213  *
214  *************************************************/
215 class Q_DECL_HIDDEN KDataToolAction::KDataToolActionPrivate
216 {
217 public:
KDataToolActionPrivate()218     KDataToolActionPrivate() {}
219 
220     QString command;
221     KDataToolInfo info;
222 };
223 
KDataToolAction(const QString & text,const KDataToolInfo & info,const QString & command,QObject * parent)224 KDataToolAction::KDataToolAction(const QString &text, const KDataToolInfo &info, const QString &command,
225                                  QObject *parent)
226     : QAction(text, parent),
227       d(new KDataToolActionPrivate)
228 {
229     setIcon(QIcon::fromTheme(info.iconName()));
230     d->command = command;
231     d->info = info;
232 }
233 
~KDataToolAction()234 KDataToolAction::~KDataToolAction()
235 {
236     delete d;
237 }
238 
slotActivated()239 void KDataToolAction::slotActivated()
240 {
241     emit toolActivated(d->info, d->command);
242 }
243 
dataToolActionList(const QList<KDataToolInfo> & tools,const QObject * receiver,const char * slot,KActionCollection * parent)244 QList<QAction *> KDataToolAction::dataToolActionList(const QList<KDataToolInfo> &tools, const QObject *receiver, const char *slot, KActionCollection *parent)
245 {
246     QList<QAction *> actionList;
247     if (tools.isEmpty()) {
248         return actionList;
249     }
250 
251     QAction *sep_action = new QAction(parent);
252     sep_action->setSeparator(true);
253     actionList.append(sep_action);
254     QList<KDataToolInfo>::ConstIterator entry = tools.begin();
255     for (; entry != tools.end(); ++entry) {
256         const QStringList userCommands = (*entry).userCommands();
257         const QStringList commands = (*entry).commands();
258         Q_ASSERT(!commands.isEmpty());
259         if (commands.count() != userCommands.count())
260             qWarning() << "KDataTool desktop file error (" << (*entry).service()->entryPath()
261                        << ")." << commands.count() << "commands and"
262                        << userCommands.count() << " descriptions.";
263         QStringList::ConstIterator uit = userCommands.begin();
264         QStringList::ConstIterator cit = commands.begin();
265         for (; uit != userCommands.end() && cit != commands.end(); ++uit, ++cit) {
266             //qDebug() << "creating action " << *uit << " " << *cit;
267             const QString name = (*entry).service()->entryPath(); // something unique
268             KDataToolAction *action = new KDataToolAction(*uit, *entry, *cit, parent);
269             parent->addAction(name, action);
270             connect(action, SIGNAL(toolActivated(KDataToolInfo,QString)),
271                     receiver, slot);
272             actionList.append(action);
273         }
274     }
275 
276     return actionList;
277 }
278 
279 /*************************************************
280  *
281  * KDataTool
282  *
283  *************************************************/
284 class Q_DECL_HIDDEN KDataTool::KDataToolPrivate
285 {
286 public:
KDataToolPrivate()287     KDataToolPrivate() {}
288 
289     QString componentName;
290 };
291 
KDataTool(QObject * parent)292 KDataTool::KDataTool(QObject *parent)
293     : QObject(parent), d(new KDataToolPrivate)
294 {
295 }
296 
~KDataTool()297 KDataTool::~KDataTool()
298 {
299     delete d;
300 }
301 
setComponentName(const QString & componentName)302 void KDataTool::setComponentName(const QString &componentName)
303 {
304     d->componentName = componentName;
305 }
306 
componentName() const307 QString KDataTool::componentName() const
308 {
309     return d->componentName;
310 }
311 
312