File indexing completed on 2024-04-28 11:33:52

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 2009-2012 Dario Freddi <drf@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "objectdecorator.h"
0009 
0010 #include "action.h"
0011 #include "executejob.h"
0012 #include "kauthdebug.h"
0013 
0014 #include <QAbstractButton>
0015 #include <QAction>
0016 #include <QIcon>
0017 
0018 namespace KAuth
0019 {
0020 class ObjectDecoratorPrivate
0021 {
0022 public:
0023     ObjectDecoratorPrivate(ObjectDecorator *parent)
0024         : q(parent)
0025         , decoratedObject(parent->parent())
0026     {
0027     }
0028 
0029     ObjectDecorator *const q;
0030 
0031     QObject *const decoratedObject;
0032     KAuth::Action authAction;
0033     // TODO: Remove whenever QIcon overlays will get fixed
0034     QIcon oldIcon;
0035 
0036     void connectDecorated();
0037     void linkActionToWidget();
0038     void slotActivated();
0039     void authStatusChanged(KAuth::Action::AuthStatus status);
0040 };
0041 
0042 void ObjectDecoratorPrivate::connectDecorated()
0043 {
0044     if (auto *button = qobject_cast<QAbstractButton *>(decoratedObject)) {
0045         q->connect(button, &QAbstractButton::clicked, q, [this] {
0046             slotActivated();
0047         });
0048         return;
0049     }
0050 
0051     if (auto *action = qobject_cast<QAction *>(decoratedObject)) {
0052         q->connect(action, &QAction::triggered, q, [this] {
0053             slotActivated();
0054         });
0055         return;
0056     }
0057 
0058     qCWarning(KAUTH) << Q_FUNC_INFO << "We're not decorating an action or a button";
0059 }
0060 
0061 void ObjectDecoratorPrivate::linkActionToWidget()
0062 {
0063     QWidget *widget = qobject_cast<QWidget *>(decoratedObject);
0064     if (widget) {
0065         authAction.setParentWidget(widget);
0066         return;
0067     }
0068 
0069     QAction *action = qobject_cast<QAction *>(decoratedObject);
0070     if (action) {
0071         authAction.setParentWidget(action->parentWidget());
0072         return;
0073     }
0074 
0075     qCWarning(KAUTH) << Q_FUNC_INFO << "We're not decorating an action or a widget";
0076 }
0077 
0078 void ObjectDecoratorPrivate::slotActivated()
0079 {
0080     if (authAction.isValid()) {
0081         KAuth::ExecuteJob *job = authAction.execute(KAuth::Action::AuthorizeOnlyMode);
0082         q->connect(job, &KAuth::ExecuteJob::statusChanged, q, [this](KAuth::Action::AuthStatus status) {
0083             authStatusChanged(status);
0084         });
0085 
0086         if (job->exec()) {
0087             Q_EMIT q->authorized(authAction);
0088         } else {
0089             decoratedObject->setProperty("enabled", false);
0090         }
0091     }
0092 }
0093 
0094 void ObjectDecoratorPrivate::authStatusChanged(KAuth::Action::AuthStatus status)
0095 {
0096     switch (status) {
0097     case KAuth::Action::AuthorizedStatus:
0098         decoratedObject->setProperty("enabled", true);
0099         if (!oldIcon.isNull()) {
0100             decoratedObject->setProperty("icon", QVariant::fromValue(oldIcon));
0101             oldIcon = QIcon();
0102         }
0103         break;
0104     case KAuth::Action::AuthRequiredStatus:
0105         decoratedObject->setProperty("enabled", true);
0106         oldIcon = decoratedObject->property("icon").value<QIcon>();
0107         decoratedObject->setProperty("icon", QIcon::fromTheme(QLatin1String("dialog-password")));
0108         break;
0109     default:
0110         decoratedObject->setProperty("enabled", false);
0111         if (!oldIcon.isNull()) {
0112             decoratedObject->setProperty("icon", QVariant::fromValue(oldIcon));
0113             oldIcon = QIcon();
0114         }
0115     }
0116 }
0117 
0118 ObjectDecorator::ObjectDecorator(QObject *parent)
0119     : QObject(parent)
0120     , d(new ObjectDecoratorPrivate(this))
0121 {
0122     d->connectDecorated();
0123 }
0124 
0125 ObjectDecorator::~ObjectDecorator() = default;
0126 
0127 KAuth::Action ObjectDecorator::authAction() const
0128 {
0129     return d->authAction;
0130 }
0131 
0132 void ObjectDecorator::setAuthAction(const QString &actionName)
0133 {
0134     if (actionName.isEmpty()) {
0135         setAuthAction(KAuth::Action());
0136     } else {
0137         setAuthAction(KAuth::Action(actionName));
0138     }
0139 }
0140 
0141 void ObjectDecorator::setAuthAction(const KAuth::Action &action)
0142 {
0143     if (d->authAction == action) {
0144         return;
0145     }
0146 
0147     if (d->authAction.isValid()) {
0148         if (!d->oldIcon.isNull()) {
0149             d->decoratedObject->setProperty("icon", QVariant::fromValue(d->oldIcon));
0150             d->oldIcon = QIcon();
0151         }
0152     }
0153 
0154     if (action.isValid()) {
0155         d->authAction = action;
0156 
0157         // Set the parent widget
0158         d->linkActionToWidget();
0159 
0160         d->authStatusChanged(d->authAction.status());
0161     }
0162 }
0163 
0164 } // namespace KAuth
0165 
0166 #include "moc_objectdecorator.cpp"