1 | /* |
2 | Copyright (c) 2010 Tobias Koenig <tokoe@kde.org> |
3 | |
4 | This library is free software; you can redistribute it and/or modify it |
5 | under the terms of the GNU Library General Public License as published by |
6 | the Free Software Foundation; either version 2 of the License, or (at your |
7 | option) any later version. |
8 | |
9 | This library is distributed in the hope that it will be useful, but WITHOUT |
10 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
11 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public |
12 | License for more details. |
13 | |
14 | You should have received a copy of the GNU Library General Public License |
15 | along with this library; see the file COPYING.LIB. If not, write to the |
16 | Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA |
17 | 02110-1301, USA. |
18 | */ |
19 | |
20 | #include "agentactionmanager.h" |
21 | |
22 | #include "agentfilterproxymodel.h" |
23 | #include "agentinstancecreatejob.h" |
24 | #include "agentinstancemodel.h" |
25 | #include "agentmanager.h" |
26 | #include "agenttypedialog.h" |
27 | #include "metatypes.h" |
28 | |
29 | #include <KAction> |
30 | #include <KIcon> |
31 | #include <KActionCollection> |
32 | #include <KDebug> |
33 | #include <KLocalizedString> |
34 | #include <KMessageBox> |
35 | |
36 | #include <QItemSelectionModel> |
37 | #include <QPointer> |
38 | |
39 | #include <boost/static_assert.hpp> |
40 | |
41 | using namespace Akonadi; |
42 | |
43 | //@cond PRIVATE |
44 | |
45 | static const struct { |
46 | const char *name; |
47 | const char *label; |
48 | const char *icon; |
49 | int shortcut; |
50 | const char *slot; |
51 | } agentActionData[] = { |
52 | { "akonadi_agentinstance_create" , I18N_NOOP("&New Agent Instance..." ), |
53 | "folder-new" , 0, SLOT(slotCreateAgentInstance()) |
54 | }, |
55 | { "akonadi_agentinstance_delete" , I18N_NOOP("&Delete Agent Instance" ), |
56 | "edit-delete" , 0, SLOT(slotDeleteAgentInstance()) |
57 | }, |
58 | { "akonadi_agentinstance_configure" , I18N_NOOP("&Configure Agent Instance" ), |
59 | "configure" , 0, SLOT(slotConfigureAgentInstance()) |
60 | } |
61 | }; |
62 | static const int numAgentActionData = sizeof agentActionData / sizeof * agentActionData; |
63 | |
64 | BOOST_STATIC_ASSERT(numAgentActionData == AgentActionManager::LastType); |
65 | |
66 | /** |
67 | * @internal |
68 | */ |
69 | class AgentActionManager::Private |
70 | { |
71 | public: |
72 | Private(AgentActionManager *parent) |
73 | : q(parent) |
74 | , mSelectionModel(0) |
75 | { |
76 | mActions.fill(0, AgentActionManager::LastType); |
77 | |
78 | setContextText(AgentActionManager::CreateAgentInstance, |
79 | AgentActionManager::DialogTitle, |
80 | i18nc("@title:window" , "New Agent Instance" )); |
81 | |
82 | setContextText(AgentActionManager::CreateAgentInstance, |
83 | AgentActionManager::ErrorMessageText, |
84 | ki18n("Could not create agent instance: %1" )); |
85 | |
86 | setContextText(AgentActionManager::CreateAgentInstance, |
87 | AgentActionManager::ErrorMessageTitle, |
88 | i18n("Agent instance creation failed" )); |
89 | |
90 | setContextText(AgentActionManager::DeleteAgentInstance, |
91 | AgentActionManager::MessageBoxTitle, |
92 | i18nc("@title:window" , "Delete Agent Instance?" )); |
93 | |
94 | setContextText(AgentActionManager::DeleteAgentInstance, |
95 | AgentActionManager::MessageBoxText, |
96 | i18n("Do you really want to delete the selected agent instance?" )); |
97 | } |
98 | |
99 | void enableAction(AgentActionManager::Type type, bool enable) |
100 | { |
101 | Q_ASSERT(type >= 0 && type < AgentActionManager::LastType); |
102 | if (mActions[type]) { |
103 | mActions[type]->setEnabled(enable); |
104 | } |
105 | } |
106 | |
107 | void updateActions() |
108 | { |
109 | const AgentInstance::List instances = selectedAgentInstances(); |
110 | |
111 | const bool createActionEnabled = true; |
112 | bool deleteActionEnabled = true; |
113 | bool configureActionEnabled = true; |
114 | |
115 | if (instances.isEmpty()) { |
116 | deleteActionEnabled = false; |
117 | configureActionEnabled = false; |
118 | } |
119 | |
120 | if (instances.count() == 1) { |
121 | const AgentInstance instance = instances.first(); |
122 | if (instance.type().capabilities().contains(QLatin1String("NoConfig" ))) { |
123 | configureActionEnabled = false; |
124 | } |
125 | } |
126 | |
127 | enableAction(CreateAgentInstance, createActionEnabled); |
128 | enableAction(DeleteAgentInstance, deleteActionEnabled); |
129 | enableAction(ConfigureAgentInstance, configureActionEnabled); |
130 | |
131 | emit q->actionStateUpdated(); |
132 | } |
133 | |
134 | AgentInstance::List selectedAgentInstances() const |
135 | { |
136 | AgentInstance::List instances; |
137 | |
138 | if (!mSelectionModel) { |
139 | return instances; |
140 | } |
141 | |
142 | foreach (const QModelIndex &index, mSelectionModel->selectedRows()) { |
143 | const AgentInstance instance = |
144 | index.data(AgentInstanceModel::InstanceRole).value<AgentInstance>(); |
145 | if (instance.isValid()) { |
146 | instances << instance; |
147 | } |
148 | } |
149 | |
150 | return instances; |
151 | } |
152 | |
153 | void slotCreateAgentInstance() |
154 | { |
155 | QPointer<Akonadi::AgentTypeDialog> dlg(new Akonadi::AgentTypeDialog(mParentWidget)); |
156 | dlg->setCaption(contextText(AgentActionManager::CreateAgentInstance, |
157 | AgentActionManager::DialogTitle)); |
158 | |
159 | foreach (const QString &mimeType, mMimeTypeFilter) { |
160 | dlg->agentFilterProxyModel()->addMimeTypeFilter(mimeType); |
161 | } |
162 | |
163 | foreach (const QString &capability, mCapabilityFilter) { |
164 | dlg->agentFilterProxyModel()->addCapabilityFilter(capability); |
165 | } |
166 | |
167 | if (dlg->exec() == QDialog::Accepted && dlg != 0) { |
168 | const AgentType agentType = dlg->agentType(); |
169 | |
170 | if (agentType.isValid()) { |
171 | AgentInstanceCreateJob *job = new AgentInstanceCreateJob(agentType, q); |
172 | q->connect(job, SIGNAL(result(KJob*)), SLOT(slotAgentInstanceCreationResult(KJob*))); |
173 | job->configure(mParentWidget); |
174 | job->start(); |
175 | } |
176 | } |
177 | delete dlg; |
178 | } |
179 | |
180 | void slotDeleteAgentInstance() |
181 | { |
182 | const AgentInstance::List instances = selectedAgentInstances(); |
183 | if (!instances.isEmpty()) { |
184 | if (KMessageBox::questionYesNo( |
185 | mParentWidget, |
186 | contextText(AgentActionManager::DeleteAgentInstance, |
187 | AgentActionManager::MessageBoxText), |
188 | contextText(AgentActionManager::DeleteAgentInstance, |
189 | AgentActionManager::MessageBoxTitle), |
190 | KStandardGuiItem::del(), |
191 | KStandardGuiItem::cancel(), |
192 | QString(), |
193 | KMessageBox::Dangerous) == KMessageBox::Yes) { |
194 | |
195 | foreach (const AgentInstance &instance, instances) { |
196 | AgentManager::self()->removeInstance(instance); |
197 | } |
198 | } |
199 | } |
200 | } |
201 | |
202 | void slotConfigureAgentInstance() |
203 | { |
204 | AgentInstance::List instances = selectedAgentInstances(); |
205 | if (instances.isEmpty()) { |
206 | return; |
207 | } |
208 | |
209 | instances.first().configure(mParentWidget); |
210 | } |
211 | |
212 | void slotAgentInstanceCreationResult(KJob *job) |
213 | { |
214 | if (job->error()) { |
215 | KMessageBox::error( |
216 | mParentWidget, |
217 | contextText(AgentActionManager::CreateAgentInstance, |
218 | AgentActionManager::ErrorMessageText).arg(job->errorString()), |
219 | contextText(AgentActionManager::CreateAgentInstance, |
220 | AgentActionManager::ErrorMessageTitle)); |
221 | } |
222 | } |
223 | |
224 | void setContextText(AgentActionManager::Type type, |
225 | AgentActionManager::TextContext context, const QString &data) |
226 | { |
227 | mContextTexts[type].insert(context, data); |
228 | } |
229 | |
230 | void setContextText(AgentActionManager::Type type, |
231 | AgentActionManager::TextContext context, const KLocalizedString &data) |
232 | { |
233 | |
234 | mContextTexts[type].insert(context, data.toString()); |
235 | } |
236 | |
237 | QString contextText(AgentActionManager::Type type, |
238 | AgentActionManager::TextContext context) const |
239 | { |
240 | return mContextTexts[type].value(context); |
241 | } |
242 | |
243 | AgentActionManager *q; |
244 | KActionCollection *mActionCollection; |
245 | QWidget *mParentWidget; |
246 | QItemSelectionModel *mSelectionModel; |
247 | QVector<KAction *> mActions; |
248 | QStringList mMimeTypeFilter; |
249 | QStringList mCapabilityFilter; |
250 | |
251 | typedef QHash<AgentActionManager::TextContext, QString> ContextTexts; |
252 | QHash<AgentActionManager::Type, ContextTexts> mContextTexts; |
253 | }; |
254 | |
255 | //@endcond |
256 | |
257 | AgentActionManager::AgentActionManager(KActionCollection *actionCollection, QWidget *parent) |
258 | : QObject(parent) |
259 | , d(new Private(this)) |
260 | { |
261 | d->mParentWidget = parent; |
262 | d->mActionCollection = actionCollection; |
263 | } |
264 | |
265 | AgentActionManager::~AgentActionManager() |
266 | { |
267 | delete d; |
268 | } |
269 | |
270 | void AgentActionManager::setSelectionModel(QItemSelectionModel *selectionModel) |
271 | { |
272 | d->mSelectionModel = selectionModel; |
273 | connect(selectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), |
274 | SLOT(updateActions())); |
275 | } |
276 | |
277 | void AgentActionManager::setMimeTypeFilter(const QStringList &mimeTypes) |
278 | { |
279 | d->mMimeTypeFilter = mimeTypes; |
280 | } |
281 | |
282 | void AgentActionManager::setCapabilityFilter(const QStringList &capabilities) |
283 | { |
284 | d->mCapabilityFilter = capabilities; |
285 | } |
286 | |
287 | KAction *AgentActionManager::createAction(Type type) |
288 | { |
289 | Q_ASSERT(type >= 0 && type < LastType); |
290 | Q_ASSERT(agentActionData[type].name); |
291 | if (d->mActions[type]) { |
292 | return d->mActions[type]; |
293 | } |
294 | |
295 | KAction *action = new KAction(d->mParentWidget); |
296 | action->setText(i18n(agentActionData[type].label)); |
297 | |
298 | if (agentActionData[type].icon) { |
299 | action->setIcon(KIcon(QString::fromLatin1(agentActionData[type].icon))); |
300 | } |
301 | |
302 | action->setShortcut(agentActionData[type].shortcut); |
303 | |
304 | if (agentActionData[type].slot) { |
305 | connect(action, SIGNAL(triggered()), agentActionData[type].slot); |
306 | } |
307 | |
308 | d->mActionCollection->addAction(QString::fromLatin1(agentActionData[type].name), action); |
309 | d->mActions[type] = action; |
310 | d->updateActions(); |
311 | |
312 | return action; |
313 | } |
314 | |
315 | void AgentActionManager::createAllActions() |
316 | { |
317 | for (int type = 0; type < LastType; ++type) { |
318 | createAction((Type)type); |
319 | } |
320 | } |
321 | |
322 | KAction *AgentActionManager::action(Type type) const |
323 | { |
324 | Q_ASSERT(type >= 0 && type < LastType); |
325 | return d->mActions[type]; |
326 | } |
327 | |
328 | void AgentActionManager::interceptAction(Type type, bool intercept) |
329 | { |
330 | Q_ASSERT(type >= 0 && type < LastType); |
331 | |
332 | const KAction *action = d->mActions[type]; |
333 | |
334 | if (!action) { |
335 | return; |
336 | } |
337 | |
338 | if (intercept) { |
339 | disconnect(action, SIGNAL(triggered()), this, agentActionData[type].slot); |
340 | } else { |
341 | connect(action, SIGNAL(triggered()), agentActionData[type].slot); |
342 | } |
343 | } |
344 | |
345 | AgentInstance::List AgentActionManager::selectedAgentInstances() const |
346 | { |
347 | return d->selectedAgentInstances(); |
348 | } |
349 | |
350 | void AgentActionManager::setContextText(Type type, TextContext context, const QString &text) |
351 | { |
352 | d->setContextText(type, context, text); |
353 | } |
354 | |
355 | void AgentActionManager::setContextText(Type type, TextContext context, |
356 | const KLocalizedString &text) |
357 | { |
358 | d->setContextText(type, context, text); |
359 | } |
360 | |
361 | #include "moc_agentactionmanager.cpp" |
362 | |