Akonadi

agentactionmanager.cpp
1/*
2 SPDX-FileCopyrightText: 2010 Tobias Koenig <tokoe@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "agentactionmanager.h"
8
9#include "agentconfigurationdialog.h"
10#include "agentfilterproxymodel.h"
11#include "agentinstancecreatejob.h"
12#include "agentinstancemodel.h"
13#include "agentmanager.h"
14#include "agenttypedialog.h"
15
16#include <KActionCollection>
17#include <KLocalizedString>
18#include <KMessageBox>
19#include <QAction>
20#include <QIcon>
21
22#include <KLazyLocalizedString>
23#include <QItemSelectionModel>
24#include <QPointer>
25
26using namespace Akonadi;
27
28/// @cond PRIVATE
29
30static const struct {
31 const char *name;
33 const char *icon;
34 int shortcut;
35 const char *slot;
36} agentActionData[] = {{"akonadi_agentinstance_create", kli18n("&New Agent Instance..."), "folder-new", 0, SLOT(slotCreateAgentInstance())},
37 {"akonadi_agentinstance_delete", kli18n("&Delete Agent Instance"), "edit-delete", 0, SLOT(slotDeleteAgentInstance())},
38 {"akonadi_agentinstance_configure", kli18n("&Configure Agent Instance"), "configure", 0, SLOT(slotConfigureAgentInstance())}};
39static const int numAgentActionData = sizeof agentActionData / sizeof *agentActionData;
40
41static_assert(numAgentActionData == AgentActionManager::LastType, "agentActionData table does not match AgentActionManager types");
42
43/**
44 * @internal
45 */
46class Akonadi::AgentActionManagerPrivate
47{
48public:
49 explicit AgentActionManagerPrivate(AgentActionManager *parent)
50 : q(parent)
51 {
52 mActions.fill(nullptr, AgentActionManager::LastType);
53
54 setContextText(AgentActionManager::CreateAgentInstance, AgentActionManager::DialogTitle, i18nc("@title:window", "New Agent Instance"));
55
56 setContextText(AgentActionManager::CreateAgentInstance, AgentActionManager::ErrorMessageText, ki18n("Could not create agent instance: %1"));
57
60 i18nc("@title:window", "Agent Instance Creation Failed"));
61
62 setContextText(AgentActionManager::DeleteAgentInstance, AgentActionManager::MessageBoxTitle, i18nc("@title:window", "Delete Agent Instance?"));
63
66 i18n("Do you really want to delete the selected agent instance?"));
67 }
68
69 void enableAction(AgentActionManager::Type type, bool enable)
70 {
71 Q_ASSERT(type >= 0 && type < AgentActionManager::LastType);
72 if (QAction *act = mActions[type]) {
73 act->setEnabled(enable);
74 }
75 }
76
77 void updateActions()
78 {
79 const AgentInstance::List instances = selectedAgentInstances();
80
81 const bool createActionEnabled = true;
82 bool deleteActionEnabled = true;
83 bool configureActionEnabled = true;
84
85 if (instances.isEmpty()) {
86 deleteActionEnabled = false;
87 configureActionEnabled = false;
88 }
89
90 if (instances.count() == 1) {
91 const AgentInstance &instance = instances.first();
92 if (instance.type().capabilities().contains(QLatin1StringView("NoConfig"))) {
93 configureActionEnabled = false;
94 }
95 }
96
97 enableAction(AgentActionManager::CreateAgentInstance, createActionEnabled);
98 enableAction(AgentActionManager::DeleteAgentInstance, deleteActionEnabled);
99 enableAction(AgentActionManager::ConfigureAgentInstance, configureActionEnabled);
100
101 Q_EMIT q->actionStateUpdated();
102 }
103
104 AgentInstance::List selectedAgentInstances() const
105 {
106 AgentInstance::List instances;
107
108 if (!mSelectionModel) {
109 return instances;
110 }
111
112 const QModelIndexList lstModelIndex = mSelectionModel->selectedRows();
113 for (const QModelIndex &index : lstModelIndex) {
114 const auto instance = index.data(AgentInstanceModel::InstanceRole).value<AgentInstance>();
115 if (instance.isValid()) {
116 instances << instance;
117 }
118 }
119
120 return instances;
121 }
122
123 void slotCreateAgentInstance()
124 {
125 QPointer<Akonadi::AgentTypeDialog> dlg(new Akonadi::AgentTypeDialog(mParentWidget));
127
128 for (const QString &mimeType : std::as_const(mMimeTypeFilter)) {
129 dlg->agentFilterProxyModel()->addMimeTypeFilter(mimeType);
130 }
131
132 for (const QString &capability : std::as_const(mCapabilityFilter)) {
133 dlg->agentFilterProxyModel()->addCapabilityFilter(capability);
134 }
135
136 if (dlg->exec() == QDialog::Accepted) {
137 const AgentType agentType = dlg->agentType();
138
139 if (agentType.isValid()) {
140 auto job = new AgentInstanceCreateJob(agentType, q);
141 q->connect(job, &KJob::result, q, [this, job](KJob *) {
142 if (job->error()) {
143 slotAgentInstanceCreationResult(job);
144 return;
145 }
146
147 auto configureDialog = new Akonadi::AgentConfigurationDialog(job->instance(), mParentWidget);
148 configureDialog->setAttribute(Qt::WA_DeleteOnClose);
149 q->connect(configureDialog, &QDialog::rejected, q, [instance = job->instance()] {
150 Akonadi::AgentManager::self()->removeInstance(instance);
151 });
152 configureDialog->show();
153 });
154 job->start();
155 }
156 }
157 delete dlg;
158 }
159
160 void slotDeleteAgentInstance()
161 {
162 const AgentInstance::List instances = selectedAgentInstances();
163 if (!instances.isEmpty()) {
164 if (KMessageBox::questionTwoActions(mParentWidget,
169 QString(),
171 == KMessageBox::ButtonCode::PrimaryAction) {
172 for (const AgentInstance &instance : instances) {
173 AgentManager::self()->removeInstance(instance);
174 }
175 }
176 }
177 }
178
179 void slotConfigureAgentInstance()
180 {
181 AgentInstance::List instances = selectedAgentInstances();
182 if (instances.isEmpty()) {
183 return;
184 }
185
186 auto configureDialog = new Akonadi::AgentConfigurationDialog(instances.first(), mParentWidget);
187 configureDialog->setAttribute(Qt::WA_DeleteOnClose);
188 configureDialog->show();
189 }
190
191 void slotAgentInstanceCreationResult(KJob *job)
192 {
193 if (job->error()) {
194 KMessageBox::error(mParentWidget,
197 }
198 }
199
200 void setContextText(AgentActionManager::Type type, AgentActionManager::TextContext context, const QString &data)
201 {
202 mContextTexts[type].insert(context, data);
203 }
204
205 void setContextText(AgentActionManager::Type type, AgentActionManager::TextContext context, const KLocalizedString &data)
206 {
207 mContextTexts[type].insert(context, data.toString());
208 }
209
210 QString contextText(AgentActionManager::Type type, AgentActionManager::TextContext context) const
211 {
212 return mContextTexts[type].value(context);
213 }
214
215 AgentActionManager *const q;
216 KActionCollection *mActionCollection = nullptr;
217 QWidget *mParentWidget = nullptr;
218 QItemSelectionModel *mSelectionModel = nullptr;
219 QList<QAction *> mActions;
220 QStringList mMimeTypeFilter;
221 QStringList mCapabilityFilter;
222
223 using ContextTexts = QHash<AgentActionManager::TextContext, QString>;
224 QHash<AgentActionManager::Type, ContextTexts> mContextTexts;
225};
226
227/// @endcond
228
230 : QObject(parent)
231 , d(new AgentActionManagerPrivate(this))
232{
233 d->mParentWidget = parent;
234 d->mActionCollection = actionCollection;
235}
236
238
240{
241 d->mSelectionModel = selectionModel;
242 connect(selectionModel, &QItemSelectionModel::selectionChanged, this, [this]() {
243 d->updateActions();
244 });
245}
246
248{
249 d->mMimeTypeFilter = mimeTypes;
250}
251
253{
254 d->mCapabilityFilter = capabilities;
255}
256
258{
259 Q_ASSERT(type >= 0 && type < LastType);
260 Q_ASSERT(agentActionData[type].name);
261 if (QAction *act = d->mActions[type]) {
262 return act;
263 }
264
265 auto action = new QAction(d->mParentWidget);
266 action->setText(agentActionData[type].label.toString());
267
268 if (agentActionData[type].icon) {
269 action->setIcon(QIcon::fromTheme(QString::fromLatin1(agentActionData[type].icon)));
270 }
271
272 action->setShortcut(agentActionData[type].shortcut);
273
274 if (agentActionData[type].slot) {
275 connect(action, SIGNAL(triggered()), agentActionData[type].slot);
276 }
277
278 d->mActionCollection->addAction(QString::fromLatin1(agentActionData[type].name), action);
279 d->mActions[type] = action;
280 d->updateActions();
281
282 return action;
283}
284
286{
287 for (int type = 0; type < LastType; ++type) {
288 auto action = createAction(static_cast<Type>(type));
289 Q_UNUSED(action)
290 }
291}
292
294{
295 Q_ASSERT(type >= 0 && type < LastType);
296 return d->mActions[type];
297}
298
300{
301 Q_ASSERT(type >= 0 && type < LastType);
302
303 const QAction *action = d->mActions[type];
304
305 if (!action) {
306 return;
307 }
308
309 if (intercept) {
310 disconnect(action, SIGNAL(triggered()), this, agentActionData[type].slot);
311 } else {
312 connect(action, SIGNAL(triggered()), agentActionData[type].slot);
313 }
314}
315
317{
318 return d->selectedAgentInstances();
319}
320
322{
323 d->setContextText(type, context, text);
324}
325
327{
328 d->setContextText(type, context, text);
329}
330
331#include "moc_agentactionmanager.cpp"
~AgentActionManager() override
Destroys the agent action manager.
void setContextText(Type type, TextContext context, const QString &text)
Sets the text of the action type for the given context.
void interceptAction(Type type, bool intercept=true)
Sets whether the default implementation for the given action type shall be executed when the action i...
Akonadi::AgentInstance::List selectedAgentInstances() const
Returns the list of agent instances that are currently selected.
void setCapabilityFilter(const QStringList &capabilities)
Sets the capability filter that will be used when creating new agent instances.
Type
Describes the supported actions.
@ CreateAgentInstance
Creates an agent instance.
@ ConfigureAgentInstance
Configures the selected agent instance.
@ DeleteAgentInstance
Deletes the selected agent instance.
void createAllActions()
Convenience method to create all standard actions.
QAction * createAction(Type type)
Creates the action of the given type and adds it to the action collection specified in the constructo...
AgentActionManager(KActionCollection *actionCollection, QWidget *parent=nullptr)
Creates a new agent action manager.
void setMimeTypeFilter(const QStringList &mimeTypes)
Sets the mime type filter that will be used when creating new agent instances.
void setSelectionModel(QItemSelectionModel *model)
Sets the agent selection model based on which the actions should operate.
QAction * action(Type type) const
Returns the action of the given type, 0 if it has not been created (yet).
TextContext
Describes the text context that can be customized.
@ DialogTitle
The window title of a dialog.
@ MessageBoxText
The text of a message box.
@ ErrorMessageTitle
The window title of an error message.
@ MessageBoxTitle
The window title of a message box.
@ ErrorMessageText
The text of an error message.
@ InstanceRole
The agent instance itself.
QList< AgentInstance > List
Describes a list of agent instances.
virtual QString errorString() const
int error() const
void result(KJob *job)
QString toString() const
KLocalizedString KI18N_EXPORT ki18n(const char *text)
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
Helper integration between Akonadi and Qt.
QString name(const QVariant &location)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
ButtonCode questionTwoActions(QWidget *parent, const QString &text, const QString &title, const KGuiItem &primaryAction, const KGuiItem &secondaryAction, const QString &dontAskAgainName=QString(), Options options=Notify)
VehicleSection::Type type(QStringView coachNumber, QStringView coachClassification)
KGuiItem cancel()
KGuiItem del()
QString label(StandardShortcut id)
const QList< QKeySequence > & shortcut(StandardShortcut id)
void rejected()
QIcon fromTheme(const QString &name)
void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
QObject(QObject *parent)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool disconnect(const QMetaObject::Connection &connection)
QObject * parent() const const
QString fromLatin1(QByteArrayView str)
WA_DeleteOnClose
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Apr 11 2025 11:52:15 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.