/* This file is part of the Polkit-qt project SPDX-FileCopyrightText: 2009 Daniel Nicoletti SPDX-FileCopyrightText: 2009 Dario Freddi SPDX-FileCopyrightText: 2009 Jaroslav Reznik SPDX-License-Identifier: LGPL-2.0-or-later */ #include "polkitqt1-gui-action.h" #include "polkitqt1-authority.h" #include "polkitqt1-subject.h" #include namespace PolkitQt1 { namespace Gui { /** * \internal */ class Q_DECL_HIDDEN Action::Private { public: Private(Action *p); Action *parent; QString actionId; Authority::Result pkResult; qint64 targetPID; void updateAction(); bool computePkResult(); void configChanged(); bool initiallyChecked; // states data bool selfBlockedVisible; bool selfBlockedEnabled; QString selfBlockedText; QString selfBlockedWhatsThis; QString selfBlockedToolTip; QIcon selfBlockedIcon; bool noVisible; bool noEnabled; QString noText; QString noWhatsThis; QString noToolTip; QIcon noIcon; bool authVisible; bool authEnabled; QString authText; QString authWhatsThis; QString authToolTip; QIcon authIcon; bool yesVisible; bool yesEnabled; QString yesText; QString yesWhatsThis; QString yesToolTip; QIcon yesIcon; }; Action::Private::Private(Action *p) : parent(p) , targetPID(getpid()) { initiallyChecked = false; // Set the default values selfBlockedVisible = true; selfBlockedEnabled = false; noVisible = true; noEnabled = false; authVisible = true; authEnabled = true; yesVisible = true; yesEnabled = true; } Action::Action(const QString &actionId, QObject *parent) : QAction(parent) , d(new Private(this)) { // this must be called AFTER the values initialization setPolkitAction(actionId); // track the config changes to update the action connect(Authority::instance(), SIGNAL(configChanged()), this, SLOT(configChanged())); // for now we call config changed.. connect(Authority::instance(), SIGNAL(consoleKitDBChanged()), this, SLOT(configChanged())); } Action::~Action() { delete d; } bool Action::activate() { switch (d->pkResult) { case Authority::Yes: case Authority::Challenge: // just Q_EMIT the 'activated' signal Q_EMIT authorized(); return true; break; default: case Authority::No: if (d->noEnabled) { /* If PolicyKit says no... and we got here.. it means * that the user set the property "no-enabled" to * TRUE.. * * Hence, they probably have a good reason for doing * this so do let the 'activate' signal propagate.. */ Q_EMIT authorized(); return true; } break; } return false; } void Action::setChecked(bool checked) { // We store this as initiallyChecked // to be able to undo changes in case the auth fails d->initiallyChecked = checked; QAction::setChecked(checked); } void Action::Private::updateAction() { if (Authority::instance()->hasError()) { return; } switch (pkResult) { default: case Authority::Unknown: case Authority::No: qobject_cast(parent)->setVisible(noVisible); qobject_cast(parent)->setEnabled(noEnabled); qobject_cast(parent)->setText(noText); if (!noWhatsThis.isNull()) { qobject_cast(parent)->setWhatsThis(noWhatsThis); } if (!noToolTip.isNull()) { qobject_cast(parent)->setToolTip(noToolTip); } qobject_cast(parent)->setIcon(noIcon); break; case Authority::Challenge: qobject_cast(parent)->setVisible(authVisible); qobject_cast(parent)->setEnabled(authEnabled); qobject_cast(parent)->setText(authText); if (!authWhatsThis.isNull()) { qobject_cast(parent)->setWhatsThis(authWhatsThis); } if (!authToolTip.isNull()) { qobject_cast(parent)->setToolTip(authToolTip); } qobject_cast(parent)->setIcon(authIcon); break; case Authority::Yes: qobject_cast(parent)->setVisible(yesVisible); qobject_cast(parent)->setEnabled(yesEnabled); qobject_cast(parent)->setText(yesText); if (!yesWhatsThis.isNull()) { qobject_cast(parent)->setWhatsThis(yesWhatsThis); } if (!yesToolTip.isNull()) { qobject_cast(parent)->setToolTip(yesToolTip); } qobject_cast(parent)->setIcon(yesIcon); if (parent->isCheckable()) { qobject_cast(parent)->setChecked(!initiallyChecked); } break; } Q_EMIT parent->dataChanged(); } void Action::Private::configChanged() { bool result_changed; result_changed = computePkResult(); if (result_changed) { updateAction(); } } bool Action::Private::computePkResult() { Authority::Result old_result; UnixProcessSubject subject(parent->targetPID()); old_result = pkResult; pkResult = Authority::Unknown; pkResult = Authority::instance()->checkAuthorizationSync(actionId, subject, Authority::None); return old_result != pkResult; } qint64 Action::targetPID() const { if (d->targetPID != 0) { return d->targetPID; } else { return QCoreApplication::applicationPid(); } } void Action::setTargetPID(qint64 pid) { d->targetPID = pid; d->computePkResult(); d->updateAction(); } bool Action::isAllowed() const { return d->pkResult == Authority::Yes; } bool Action::is(const QString &other) const { return d->actionId == other; } void Action::revoke() { /*TODO: implement it? no negative authorizations available, no authorization db*/ } void Action::setText(const QString &text, States states) { if (states & All) { d->selfBlockedText = text; d->noText = text; d->authText = text; d->yesText = text; } else if (states & Auth) { d->authText = text; } else if (states & No) { d->noText = text; } else if (states & SelfBlocked) { d->selfBlockedText = text; } else if (states & Yes) { d->yesText = text; } d->updateAction(); } QString Action::text(Action::State state) const { switch (state) { case Yes: return d->yesText; case No: return d->noText; case Auth: return d->authText; case SelfBlocked: return d->selfBlockedText; case None: return QAction::text(); default: return QString(); } } void Action::setToolTip(const QString &toolTip, States states) { if (states & All) { d->selfBlockedToolTip = toolTip; d->noToolTip = toolTip; d->authToolTip = toolTip; d->yesToolTip = toolTip; } else if (states & Auth) { d->authToolTip = toolTip; } else if (states & No) { d->noToolTip = toolTip; } else if (states & SelfBlocked) { d->selfBlockedToolTip = toolTip; } else if (states & Yes) { d->yesToolTip = toolTip; } d->updateAction(); } QString Action::toolTip(Action::State state) const { switch (state) { case Yes: return d->yesToolTip; case No: return d->noToolTip; case Auth: return d->authToolTip; case SelfBlocked: return d->selfBlockedToolTip; case None: return QAction::toolTip(); default: return QString(); } } void Action::setWhatsThis(const QString &whatsThis, States states) { if (states & All) { d->selfBlockedWhatsThis = whatsThis; d->noWhatsThis = whatsThis; d->authWhatsThis = whatsThis; d->yesWhatsThis = whatsThis; } else if (states & Auth) { d->authWhatsThis = whatsThis; } else if (states & No) { d->noWhatsThis = whatsThis; } else if (states & SelfBlocked) { d->selfBlockedWhatsThis = whatsThis; } else if (states & Yes) { d->yesWhatsThis = whatsThis; } d->updateAction(); } QString Action::whatsThis(Action::State state) const { switch (state) { case Yes: return d->yesWhatsThis; case No: return d->noWhatsThis; case Auth: return d->authWhatsThis; case SelfBlocked: return d->selfBlockedWhatsThis; case None: return QAction::whatsThis(); default: return QString(); } } void Action::setIcon(const QIcon &icon, States states) { if (states & All) { d->selfBlockedIcon = icon; d->noIcon = icon; d->authIcon = icon; d->yesIcon = icon; } else if (states & Auth) { d->authIcon = icon; } else if (states & No) { d->noIcon = icon; } else if (states & SelfBlocked) { d->selfBlockedIcon = icon; } else if (states & Yes) { d->yesIcon = icon; } d->updateAction(); } QIcon Action::icon(Action::State state) const { switch (state) { case Yes: return d->yesIcon; case No: return d->noIcon; case Auth: return d->authIcon; case SelfBlocked: return d->selfBlockedIcon; case None: return QAction::icon(); default: return QIcon(); } } void Action::setEnabled(bool enabled, States states) { if (states & All) { d->selfBlockedEnabled = enabled; d->noEnabled = enabled; d->authEnabled = enabled; d->yesEnabled = enabled; } else if (states & Auth) { d->authEnabled = enabled; } else if (states & No) { d->noEnabled = enabled; } else if (states & SelfBlocked) { d->selfBlockedEnabled = enabled; } else if (states & Yes) { d->yesEnabled = enabled; } d->updateAction(); } bool Action::isEnabled(Action::State state) const { switch (state) { case Yes: return d->yesEnabled; case No: return d->noEnabled; case Auth: return d->authEnabled; case SelfBlocked: return d->selfBlockedEnabled; case None: return QAction::isEnabled(); default: return false; } } void Action::setVisible(bool visible, States states) { if (states & All) { d->selfBlockedVisible = visible; d->noVisible = visible; d->authVisible = visible; d->yesVisible = visible; } else if (states & Auth) { d->authVisible = visible; } else if (states & No) { d->noVisible = visible; } else if (states & SelfBlocked) { d->selfBlockedVisible = visible; } else if (states & Yes) { d->yesVisible = visible; } d->updateAction(); } bool Action::isVisible(Action::State state) const { switch (state) { case Yes: return d->yesVisible; case No: return d->noVisible; case Auth: return d->authVisible; case SelfBlocked: return d->selfBlockedVisible; case None: return QAction::isVisible(); default: return false; } } void Action::setPolkitAction(const QString &actionId) { //TODO: d->actionId = actionId; d->computePkResult(); d->updateAction(); } //-------------------------------------------------- QString Action::actionId() const { return d->actionId; } } } #include "moc_polkitqt1-gui-action.cpp"