You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
polkit-agent-tde/src/AuthDialog.cpp

378 lines
13 KiB

/* This file is part of the KDE project
Copyright (C) 2007-2008 Gökçen Eraslan <gokcen@pardus.org.tr>
Copyright (C) 2008 Dirk Mueller <mueller@kde.org>
Copyright (C) 2008 Daniel Nicoletti <dantti85-pk@yahoo.com.br>
Copyright (C) 2008-2010 Dario Freddi <drf@kde.org>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "AuthDialog.h"
#include <TQtCore/TQProcess>
#include <TQtGui/TQPainter>
#include <TQtGui/TQStandardItemModel>
#include <KDebug>
#include <KToolInvocation>
#include <KUser>
#include <PolkitTQt1/Authority>
#include <PolkitTQt1/Details>
#include <KWindowSystem>
#include <KNotification>
AuthDialog::AuthDialog(const TQString &actionId,
const TQString &message,
const TQString &iconName,
const PolkitTQt1::Details &details,
const PolkitTQt1::Identity::List &identities,
WId parent)
: KDialog(0)
{
// KAuth is able to circumvent polkit's limitations, and manages to send the wId to the auth agent.
// If we received it, we use KWindowSystem to associate this dialog correctly.
if (parent > 0) {
kDebug() << "Associating the dialog with " << parent << " this dialog is " << winId();
// Set the parent
KWindowSystem::setMainWindow(this, parent);
// Set modal
KWindowSystem::setState(winId(), NET::Modal);
}
setupUi(mainWidget());
setButtons(Ok | Cancel | Details);
if (message.isEmpty()) {
kWarning() << "Could not get action message for action.";
lblHeader->hide();
} else {
kDebug() << "Message of action: " << message;
lblHeader->setText("<h3>" + message + "</h3>");
setCaption(message);
m_message = message;
}
// loads the standard key icon
TQPixmap icon = KIconLoader::global()->loadIcon("dialog-password",
KIconLoader::NoGroup,
KIconLoader::SizeHuge,
KIconLoader::DefaultState);
// create a painter to paint the action icon over the key icon
TQPainter painter(&icon);
const int iconSize = icon.size().width();
// the the emblem icon to size 32
int overlaySize = 32;
// try to load the action icon
const TQPixmap pixmap = KIconLoader::global()->loadIcon(iconName,
KIconLoader::NoGroup,
overlaySize,
KIconLoader::DefaultState,
TQStringList(),
0,
true);
// if we're able to load the action icon paint it over the
// key icon.
if (!pixmap.isNull()) {
TQPoint startPoint;
// bottom right corner
startPoint = TQPoint(iconSize - overlaySize - 2,
iconSize - overlaySize - 2);
painter.drawPixmap(startPoint, pixmap);
}
setWindowIcon(icon);
lblPixmap->setPixmap(icon);
// find action description for actionId
foreach(const PolkitTQt1::ActionDescription &desc, PolkitTQt1::Authority::instance()->enumerateActionsSync()) {
if (actionId == desc.actionId()) {
m_actionDescription = desc;
kDebug() << "Action description has been found" ;
break;
}
}
AuthDetails *detailsDialog = new AuthDetails(details, m_actionDescription, m_appname, this);
setDetailsWidget(detailsDialog);
userCB->hide();
lePassword->setFocus();
errorMessageKTW->hide();
// If there is more than 1 identity we will show the combobox for user selection
if (identities.size() > 1) {
connect(userCB, SIGNAL(currentIndexChanged(int)),
this, SLOT(on_userCB_currentIndexChanged(int)));
createUserCB(identities);
} else {
userCB->addItem("", TQVariant(identities[0].toString()));
userCB->setCurrentIndex(0);
}
}
AuthDialog::~AuthDialog()
{
}
void AuthDialog::accept()
{
// Do nothing, do not close the dialog. This is needed so that the dialog stays
lePassword->setEnabled(false);
return;
}
void AuthDialog::setRequest(const TQString &request, bool requiresAdmin)
{
kDebug() << request;
PolkitTQt1::Identity identity = adminUserSelected();
if (request.startsWith(TQLatin1String("password:"), TQt::CaseInsensitive)) {
if (requiresAdmin) {
if (!identity.isValid()) {
lblPassword->setText(i18n("Password for root:"));
} else {
lblPassword->setText(i18n("Password for %1:",
identity.toString().remove("unix-user:")));
}
} else {
lblPassword->setText(i18n("Password:"));
}
} else if (request.startsWith(TQLatin1String("password or swipe finger:"),
TQt::CaseInsensitive)) {
if (requiresAdmin) {
if (!identity.isValid()) {
lblPassword->setText(i18n("Password or swipe finger for root:"));
} else {
lblPassword->setText(i18n("Password or swipe finger for %1:",
identity.toString().remove("unix-user:")));
}
} else {
lblPassword->setText(i18n("Password or swipe finger:"));
}
} else {
lblPassword->setText(request);
}
}
void AuthDialog::setOptions()
{
lblContent->setText(i18n("An application is attempting to perform an action that requires privileges."
" Authentication is required to perform this action."));
}
void AuthDialog::createUserCB(const PolkitTQt1::Identity::List &identities)
{
/* if we've already built the list of admin users once, then avoid
* doing it again.. (this is mainly used when the user entered the
* wrong password and the dialog is recycled)
*/
if (identities.count() && (userCB->count() - 1) != identities.count()) {
// Clears the combobox in the case some user be added
userCB->clear();
// Adds a Dummy user
userCB->addItem(i18n("Select User"), qVariantFromValue<TQString> (TQString()));
qobject_cast<TQStandardItemModel *>(userCB->model())->item(userCB->count()-1)->setEnabled(false);
// For each user
int index = 1; // Start at 1 because of the "Select User" entry
int currentUserIndex = -1;
const KUser currentUser;
foreach(const PolkitTQt1::Identity &identity, identities) {
// First check to see if the user is valid
kDebug() << "User: " << identity.toString();
const KUser user(identity.toString().remove("unix-user:"));
if (!user.isValid()) {
kWarning() << "User invalid: " << user.loginName();
continue;
}
// Display user Full Name IF available
TQString display;
if (!user.property(KUser::FullName).toString().isEmpty()) {
display = i18nc("%1 is the full user name, %2 is the user login name", "%1 (%2)", user.property(KUser::FullName).toString(), user.loginName());
} else {
display = user.loginName();
}
KIcon icon;
// load user icon face
if (!user.faceIconPath().isEmpty()) {
icon = KIcon(user.faceIconPath());
} else {
icon = KIcon("user-identity");
}
// appends the user item
userCB->addItem(icon, display, qVariantFromValue<TQString> (identity.toString()));
if (user == currentUser) {
currentUserIndex = index;
}
++index;
}
// Show the widget and set focus
if (currentUserIndex != -1) {
userCB->setCurrentIndex(currentUserIndex);
}
userCB->show();
}
}
PolkitTQt1::Identity AuthDialog::adminUserSelected() const
{
if (userCB->currentIndex() == -1)
return PolkitTQt1::Identity();
TQString id = userCB->itemData(userCB->currentIndex()).toString();
if (id.isEmpty())
return PolkitTQt1::Identity();
return PolkitTQt1::Identity::fromString(id);
}
void AuthDialog::on_userCB_currentIndexChanged(int /*index*/)
{
PolkitTQt1::Identity identity = adminUserSelected();
// itemData is Null when "Select user" is selected
if (!identity.isValid()) {
lePassword->setEnabled(false);
lblPassword->setEnabled(false);
enableButtonOk(false);
} else {
lePassword->setEnabled(true);
lblPassword->setEnabled(true);
enableButtonOk(true);
// We need this to restart the auth with the new user
emit adminUserSelected(identity);
// git password label focus
lePassword->setFocus();
}
}
TQString AuthDialog::password() const
{
return lePassword->text();
}
void AuthDialog::authenticationFailure()
{
errorMessageKTW->setText(i18n("Authentication failure, please try again."), KTitleWidget::ErrorMessage);
TQFont bold = font();
bold.setBold(true);
lblPassword->setFont(bold);
lePassword->setEnabled(true);
lePassword->clear();
lePassword->setFocus();
}
void AuthDialog::showEvent(TQShowEvent *event)
{
KDialog::showEvent(event);
if (winId() != KWindowSystem::activeWindow())
{
KNotification *notification = new KNotification("authenticate", this,
KNotification::Persistent | KNotification::CloseWhenWidgetActivated);
kDebug() << "Notificate: " << notification->eventId();
notification->setText(m_message);
TQPixmap icon = KIconLoader::global()->loadIcon("dialog-password",
KIconLoader::NoGroup,
KIconLoader::SizeHuge,
KIconLoader::DefaultState);
notification->setPixmap(icon);
notification->setActions(TQStringList() << i18n("Switch to dialog") << i18n("Cancel"));
connect(notification, SIGNAL(activated(uint)), this, SLOT(notificationActivated(uint)));
notification->sendEvent();
}
}
void AuthDialog::notificationActivated(unsigned int action)
{
kDebug() << "notificationActivated: " << action;
if (action == 1)
{
KWindowSystem::forceActiveWindow(winId());
}
}
AuthDetails::AuthDetails(const PolkitTQt1::Details &details,
const PolkitTQt1::ActionDescription &actionDescription,
const TQString &appname,
TQWidget *parent)
: TQWidget(parent)
{
setupUi(this);
app_label->setText(appname);
foreach(const TQString &key, details.keys()) { //krazy:exclude=foreach (Details is not a map/hash, but rather a method)
int row = gridLayout->rowCount() + 1;
TQLabel *keyLabel = new TQLabel(this);
keyLabel->setText(i18nc("%1 is the name of a detail about the current action "
"provided by polkit", "%1:", key));
gridLayout->addWidget(keyLabel, row, 0);
TQLabel *valueLabel = new TQLabel(this);
valueLabel->setText(details.lookup(key));
gridLayout->addWidget(valueLabel, row, 1);
}
action_label->setText(actionDescription.description());
action_label->setTipText(i18n("Click to edit %1", actionDescription.actionId()));
action_label->setUrl(actionDescription.actionId());
TQString vendor = actionDescription.vendorName();
TQString vendorUrl = actionDescription.vendorUrl();
if (!vendor.isEmpty()) {
vendorUL->setText(vendor);
vendorUL->setTipText(i18n("Click to open %1", vendorUrl));
vendorUL->setUrl(vendorUrl);
} else if (!vendorUrl.isEmpty()) {
vendorUL->setText(vendorUrl);
vendorUL->setTipText(i18n("Click to open %1", vendorUrl));
vendorUL->setUrl(vendorUrl);
} else {
vendorL->hide();
vendorUL->hide();
}
connect(vendorUL, SIGNAL(leftClickedUrl(TQString)), SLOT(openUrl(TQString)));
connect(action_label, SIGNAL(leftClickedUrl(TQString)), SLOT(openAction(TQString)));
}
void AuthDetails::openUrl(const TQString& url)
{
KToolInvocation::invokeBrowser(url);
}
void AuthDetails::openAction(const TQString &url)
{
TQProcess::startDetached("polkit-kde-authorization", TQStringList() << url);
}
#include "AuthDialog.moc"