kdelibs/kutils/kpluginselector.cpp

873 lines
33 KiB
C++
Raw Normal View History

2014-11-13 01:04:59 +02:00
/**
* This file is part of the KDE project
* Copyright (C) 2007, 2006 Rafael Fernández López <ereslibre@kde.org>
* Copyright (C) 2002-2003 Matthias Kretz <kretz@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License version 2 as published by the Free Software Foundation.
*
* 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 "kpluginselector.h"
#include "kpluginselector_p.h"
#include <QtGui/QLabel>
#include <QtGui/QPainter>
#include <QtGui/QBoxLayout>
#include <QtGui/QApplication>
#include <QtGui/QCheckBox>
#include <QtGui/qstyleoption.h>
2014-11-13 01:04:59 +02:00
#include <kdebug.h>
#include <klineedit.h>
#include <kdialog.h>
#include <kurllabel.h>
#include <ktabwidget.h>
#include <kcmoduleinfo.h>
#include <kcmoduleproxy.h>
#include <kmessagebox.h>
#include <kpushbutton.h>
#include <kiconloader.h>
#include <kstandarddirs.h>
#include <klocalizedstring.h>
#include <kcategorydrawer.h>
#include <kcategorizedview.h>
#include <kcategorizedsortfilterproxymodel.h>
#include <kaboutapplicationdialog.h>
#define MARGIN 5
KPluginSelector::Private::Private(KPluginSelector *parent)
: QObject(parent)
, parent(parent)
, listView(0)
, categoryDrawer(new KCategoryDrawer)
, showIcons(false)
{
}
KPluginSelector::Private::~Private()
{
delete categoryDrawer;
}
void KPluginSelector::Private::updateDependencies(PluginEntry *pluginEntry, bool added)
{
if (added) {
QStringList dependencyList = pluginEntry->pluginInfo.dependencies();
if (!dependencyList.count()) {
return;
}
for (int i = 0; i < pluginModel->rowCount(); i++) {
const QModelIndex index = pluginModel->index(i, 0);
PluginEntry *pe = static_cast<PluginEntry*>(index.internalPointer());
if ((pe->pluginInfo.pluginName() != pluginEntry->pluginInfo.pluginName()) &&
dependencyList.contains(pe->pluginInfo.pluginName()) && !pe->checked) {
dependenciesWidget->addDependency(pe->pluginInfo.name(), pluginEntry->pluginInfo.name(), added);
const_cast<QAbstractItemModel*>(index.model())->setData(index, added, Qt::CheckStateRole);
updateDependencies(pe, added);
}
}
} else {
for (int i = 0; i < pluginModel->rowCount(); i++) {
const QModelIndex index = pluginModel->index(i, 0);
PluginEntry *pe = static_cast<PluginEntry*>(index.internalPointer());
if ((pe->pluginInfo.pluginName() != pluginEntry->pluginInfo.pluginName()) &&
pe->pluginInfo.dependencies().contains(pluginEntry->pluginInfo.pluginName()) && pe->checked) {
dependenciesWidget->addDependency(pe->pluginInfo.name(), pluginEntry->pluginInfo.name(), added);
const_cast<QAbstractItemModel*>(index.model())->setData(index, added, Qt::CheckStateRole);
updateDependencies(pe, added);
}
}
}
}
int KPluginSelector::Private::dependantLayoutValue(int value, int width, int totalWidth) const
{
if (listView->layoutDirection() == Qt::LeftToRight) {
return value;
}
return totalWidth - width - value;
}
KPluginSelector::Private::DependenciesWidget::DependenciesWidget(QWidget *parent)
: QWidget(parent)
, addedByDependencies(0)
, removedByDependencies(0)
{
setVisible(false);
details = new QLabel();
QHBoxLayout *layout = new QHBoxLayout;
QVBoxLayout *dataLayout = new QVBoxLayout;
dataLayout->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
layout->setAlignment(Qt::AlignLeft);
QLabel *label = new QLabel();
label->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
label->setPixmap(KIconLoader::global()->loadIcon("dialog-information", KIconLoader::Dialog));
label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
layout->addWidget(label);
KUrlLabel *link = new KUrlLabel();
link->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
link->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
link->setGlowEnabled(false);
link->setUnderline(false);
link->setFloatEnabled(true);
link->setUseCursor(true);
link->setHighlightedColor(palette().color(QPalette::Link));
link->setSelectedColor(palette().color(QPalette::Link));
link->setText(i18n("Automatic changes have been performed due to plugin dependencies. Click here for further information"));
dataLayout->addWidget(link);
dataLayout->addWidget(details);
layout->addLayout(dataLayout);
setLayout(layout);
QObject::connect(link, SIGNAL(leftClickedUrl()), this, SLOT(showDependencyDetails()));
}
KPluginSelector::Private::DependenciesWidget::~DependenciesWidget()
{
}
void KPluginSelector::Private::DependenciesWidget::addDependency(const QString &dependency, const QString &pluginCausant, bool added)
{
if (!isVisible())
setVisible(true);
struct FurtherInfo furtherInfo;
furtherInfo.added = added;
furtherInfo.pluginCausant = pluginCausant;
if (dependencyMap.contains(dependency)) // The dependency moved from added to removed or vice-versa
{
if (added && removedByDependencies)
removedByDependencies--;
else if (addedByDependencies)
addedByDependencies--;
dependencyMap[dependency] = furtherInfo;
}
else
dependencyMap.insert(dependency, furtherInfo);
if (added)
addedByDependencies++;
else
removedByDependencies++;
updateDetails();
}
void KPluginSelector::Private::DependenciesWidget::userOverrideDependency(const QString &dependency)
{
if (dependencyMap.contains(dependency))
{
if (addedByDependencies && dependencyMap[dependency].added)
addedByDependencies--;
else if (removedByDependencies)
removedByDependencies--;
dependencyMap.remove(dependency);
}
updateDetails();
}
void KPluginSelector::Private::DependenciesWidget::clearDependencies()
{
addedByDependencies = 0;
removedByDependencies = 0;
dependencyMap.clear();
updateDetails();
}
void KPluginSelector::Private::DependenciesWidget::showDependencyDetails()
{
QString message = i18n("Automatic changes have been performed in order to satisfy plugin dependencies:\n");
foreach(const QString &dependency, dependencyMap.keys())
{
if (dependencyMap[dependency].added)
message += i18n("\n %1 plugin has been automatically checked because of the dependency of %2 plugin", dependency, dependencyMap[dependency].pluginCausant);
else
message += i18n("\n %1 plugin has been automatically unchecked because of its dependency on %2 plugin", dependency, dependencyMap[dependency].pluginCausant);
}
KMessageBox::information(this, message, i18n("Dependency Check"));
addedByDependencies = 0;
removedByDependencies = 0;
updateDetails();
}
void KPluginSelector::Private::DependenciesWidget::updateDetails()
{
if (!dependencyMap.count())
{
setVisible(false);
return;
}
QString message;
if (addedByDependencies)
message += i18np("%1 plugin automatically added due to plugin dependencies", "%1 plugins automatically added due to plugin dependencies", addedByDependencies);
if (removedByDependencies && !message.isEmpty())
message += i18n(", ");
if (removedByDependencies)
message += i18np("%1 plugin automatically removed due to plugin dependencies", "%1 plugins automatically removed due to plugin dependencies", removedByDependencies);
if (message.isEmpty())
details->setVisible(false);
else
{
details->setVisible(true);
details->setText(message);
}
}
KPluginSelector::KPluginSelector(QWidget *parent)
: QWidget(parent)
, d(new Private(this))
{
QVBoxLayout *layout = new QVBoxLayout;
layout->setMargin(0);
setLayout(layout);
d->lineEdit = new KLineEdit(this);
d->lineEdit->setClearButtonShown(true);
d->lineEdit->setClickMessage(i18n("Search Plugins"));
d->listView = new KCategorizedView(this);
d->listView->setVerticalScrollMode(QListView::ScrollPerPixel);
d->listView->setAlternatingRowColors(true);
d->listView->setCategoryDrawer(d->categoryDrawer);
d->dependenciesWidget = new Private::DependenciesWidget(this);
d->pluginModel = new Private::PluginModel(d, this);
d->proxyModel = new Private::ProxyModel(d, this);
d->proxyModel->setCategorizedModel(true);
d->proxyModel->setSourceModel(d->pluginModel);
d->listView->setModel(d->proxyModel);
d->listView->setAlternatingRowColors(true);
Private::PluginDelegate *pluginDelegate = new Private::PluginDelegate(d, this);
d->listView->setItemDelegate(pluginDelegate);
d->listView->setMouseTracking(true);
d->listView->viewport()->setAttribute(Qt::WA_Hover);
connect(d->lineEdit, SIGNAL(textChanged(QString)), d->proxyModel, SLOT(invalidate()));
connect(pluginDelegate, SIGNAL(changed(bool)), this, SIGNAL(changed(bool)));
connect(pluginDelegate, SIGNAL(configCommitted(QByteArray)), this, SIGNAL(configCommitted(QByteArray)));
layout->addWidget(d->lineEdit);
layout->addWidget(d->listView);
layout->addWidget(d->dependenciesWidget);
}
KPluginSelector::~KPluginSelector()
{
delete d->listView->itemDelegate();
delete d->listView; // depends on some other things in d, make sure this dies first.
delete d;
}
void KPluginSelector::addPlugins(const QList<KPluginInfo> &pluginInfoList,
PluginLoadMethod pluginLoadMethod,
const QString &categoryName,
const QString &categoryKey,
const KSharedConfig::Ptr &config)
{
if (pluginInfoList.isEmpty())
return;
KConfigGroup cfgGroup(config ? config : KGlobal::config(), "Plugins");
kDebug( 702 ) << "cfgGroup = " << &cfgGroup;
d->pluginModel->addPlugins(pluginInfoList, categoryName, categoryKey, cfgGroup, pluginLoadMethod, true /* manually added */);
d->proxyModel->sort(0);
}
void KPluginSelector::load()
{
for (int i = 0; i < d->pluginModel->rowCount(); i++) {
const QModelIndex index = d->pluginModel->index(i, 0);
PluginEntry *pluginEntry = static_cast<PluginEntry*>(index.internalPointer());
pluginEntry->pluginInfo.load(pluginEntry->cfgGroup);
d->pluginModel->setData(index, pluginEntry->pluginInfo.isPluginEnabled(), Qt::CheckStateRole);
}
emit changed(false);
}
void KPluginSelector::save()
{
for (int i = 0; i < d->pluginModel->rowCount(); i++) {
const QModelIndex index = d->pluginModel->index(i, 0);
PluginEntry *pluginEntry = static_cast<PluginEntry*>(index.internalPointer());
pluginEntry->pluginInfo.setPluginEnabled(pluginEntry->checked);
pluginEntry->pluginInfo.save(pluginEntry->cfgGroup);
pluginEntry->cfgGroup.sync();
}
emit changed(false);
}
void KPluginSelector::defaults()
{
for (int i = 0; i < d->pluginModel->rowCount(); i++) {
const QModelIndex index = d->pluginModel->index(i, 0);
PluginEntry *pluginEntry = static_cast<PluginEntry*>(index.internalPointer());
d->pluginModel->setData(index, pluginEntry->pluginInfo.isPluginEnabledByDefault(), Qt::CheckStateRole);
}
emit changed(true);
}
bool KPluginSelector::isDefault() const
{
for (int i = 0; i < d->pluginModel->rowCount(); i++) {
const QModelIndex index = d->pluginModel->index(i, 0);
PluginEntry *pluginEntry = static_cast<PluginEntry*>(index.internalPointer());
if (d->pluginModel->data(index, Qt::CheckStateRole).toBool() != pluginEntry->pluginInfo.isPluginEnabledByDefault()) {
return false;
}
}
return true;
}
void KPluginSelector::updatePluginsState()
{
for (int i = 0; i < d->pluginModel->rowCount(); i++) {
const QModelIndex index = d->pluginModel->index(i, 0);
PluginEntry *pluginEntry = static_cast<PluginEntry*>(index.internalPointer());
if (pluginEntry->manuallyAdded) {
pluginEntry->pluginInfo.setPluginEnabled(pluginEntry->checked);
}
}
}
KPluginSelector::Private::PluginModel::PluginModel(KPluginSelector::Private *pluginSelector_d, QObject *parent)
: QAbstractListModel(parent)
, pluginSelector_d(pluginSelector_d)
{
}
KPluginSelector::Private::PluginModel::~PluginModel()
{
}
void KPluginSelector::Private::PluginModel::addPlugins(const QList<KPluginInfo> &pluginList, const QString &categoryName, const QString &categoryKey, const KConfigGroup &cfgGroup, PluginLoadMethod pluginLoadMethod, bool manuallyAdded)
{
QList<PluginEntry> listToAdd;
foreach (const KPluginInfo &pluginInfo, pluginList) {
PluginEntry pluginEntry;
pluginEntry.category = categoryName;
pluginEntry.pluginInfo = pluginInfo;
if (pluginLoadMethod == ReadConfigFile) {
pluginEntry.pluginInfo.load(cfgGroup);
}
pluginEntry.checked = pluginInfo.isPluginEnabled();
pluginEntry.manuallyAdded = manuallyAdded;
if (cfgGroup.isValid()) {
pluginEntry.cfgGroup = cfgGroup;
} else {
pluginEntry.cfgGroup = pluginInfo.config();
}
// this is where kiosk will set if a plugin is checkable or not (pluginName + "Enabled")
pluginEntry.isCheckable = !pluginInfo.isValid() || !pluginEntry.cfgGroup.isEntryImmutable(pluginInfo.pluginName() + QLatin1String("Enabled"));
if (!pluginEntryList.contains(pluginEntry) && !listToAdd.contains(pluginEntry) &&
(!pluginInfo.property("X-KDE-PluginInfo-Category").isValid() ||
!pluginInfo.property("X-KDE-PluginInfo-Category").toString().compare(categoryKey, Qt::CaseInsensitive)) &&
(pluginInfo.service().isNull() || !pluginInfo.service()->noDisplay())) {
listToAdd << pluginEntry;
if (!pluginSelector_d->showIcons && !pluginInfo.icon().isEmpty()) {
pluginSelector_d->showIcons = true;
}
}
}
if (listToAdd.count()) {
beginInsertRows(QModelIndex(), pluginEntryList.count(), pluginEntryList.count() + listToAdd.count() - 1);
pluginEntryList << listToAdd;
endInsertRows();
}
}
QList<KService::Ptr> KPluginSelector::Private::PluginModel::pluginServices(const QModelIndex &index) const
{
return static_cast<PluginEntry*>(index.internalPointer())->pluginInfo.kcmServices();
}
QModelIndex KPluginSelector::Private::PluginModel::index(int row, int column, const QModelIndex &parent) const
{
Q_UNUSED(parent)
return createIndex(row, column, (row < pluginEntryList.count()) ? (void*) &pluginEntryList.at(row)
: 0);
}
QVariant KPluginSelector::Private::PluginModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || !index.internalPointer()) {
return QVariant();
}
PluginEntry *pluginEntry = static_cast<PluginEntry*>(index.internalPointer());
switch (role) {
case Qt::DisplayRole:
return pluginEntry->pluginInfo.name();
case PluginEntryRole:
return QVariant::fromValue(pluginEntry);
case ServicesCountRole:
return pluginEntry->pluginInfo.kcmServices().count();
case NameRole:
return pluginEntry->pluginInfo.name();
case CommentRole:
return pluginEntry->pluginInfo.comment();
case AuthorRole:
return pluginEntry->pluginInfo.author();
case EmailRole:
return pluginEntry->pluginInfo.email();
case WebsiteRole:
return pluginEntry->pluginInfo.website();
case VersionRole:
return pluginEntry->pluginInfo.version();
case LicenseRole:
return pluginEntry->pluginInfo.license();
case DependenciesRole:
return pluginEntry->pluginInfo.dependencies();
case IsCheckableRole:
return pluginEntry->isCheckable;
case Qt::DecorationRole:
return pluginEntry->pluginInfo.icon();
case Qt::CheckStateRole:
return pluginEntry->checked;
case KCategorizedSortFilterProxyModel::CategoryDisplayRole: // fall through
case KCategorizedSortFilterProxyModel::CategorySortRole:
return pluginEntry->category;
default:
return QVariant();
}
}
bool KPluginSelector::Private::PluginModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (!index.isValid()) {
return false;
}
bool ret = false;
if (role == Qt::CheckStateRole) {
static_cast<PluginEntry*>(index.internalPointer())->checked = value.toBool();
ret = true;
}
if (ret) {
emit dataChanged(index, index);
}
return ret;
}
int KPluginSelector::Private::PluginModel::rowCount(const QModelIndex &parent) const
{
if (parent.isValid()) {
return 0;
}
return pluginEntryList.count();
}
KPluginSelector::Private::ProxyModel::ProxyModel(KPluginSelector::Private *pluginSelector_d, QObject *parent)
: KCategorizedSortFilterProxyModel(parent)
, pluginSelector_d(pluginSelector_d)
{
sort(0);
}
KPluginSelector::Private::ProxyModel::~ProxyModel()
{
}
bool KPluginSelector::Private::ProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
Q_UNUSED(sourceParent)
if (!pluginSelector_d->lineEdit->text().isEmpty()) {
const QModelIndex index = sourceModel()->index(sourceRow, 0);
const KPluginInfo pluginInfo = static_cast<PluginEntry*>(index.internalPointer())->pluginInfo;
return pluginInfo.name().contains(pluginSelector_d->lineEdit->text(), Qt::CaseInsensitive) ||
pluginInfo.comment().contains(pluginSelector_d->lineEdit->text(), Qt::CaseInsensitive);
}
return true;
}
bool KPluginSelector::Private::ProxyModel::subSortLessThan(const QModelIndex &left, const QModelIndex &right) const
{
return static_cast<PluginEntry*>(left.internalPointer())->pluginInfo.name().compare(static_cast<PluginEntry*>(right.internalPointer())->pluginInfo.name(), Qt::CaseInsensitive) < 0;
}
KPluginSelector::Private::PluginDelegate::PluginDelegate(KPluginSelector::Private *pluginSelector_d, QObject *parent)
: KWidgetItemDelegate(pluginSelector_d->listView, parent)
, checkBox(new QCheckBox)
, pushButton(new KPushButton)
, pluginSelector_d(pluginSelector_d)
{
pushButton->setIcon(KIcon("configure")); // only for getting size matters
}
KPluginSelector::Private::PluginDelegate::~PluginDelegate()
{
delete checkBox;
delete pushButton;
}
void KPluginSelector::Private::PluginDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
if (!index.isValid()) {
return;
}
int xOffset = checkBox->sizeHint().width();
bool disabled = !index.model()->data(index, IsCheckableRole).toBool();
painter->save();
QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, &option, painter, 0);
int iconSize = option.rect.height() - MARGIN * 2;
if (pluginSelector_d->showIcons) {
QPixmap pixmap = KIconLoader::global()->loadIcon(index.model()->data(index, Qt::DecorationRole).toString(),
KIconLoader::Desktop, iconSize, disabled ? KIconLoader::DisabledState : KIconLoader::DefaultState);
painter->drawPixmap(QRect(pluginSelector_d->dependantLayoutValue(MARGIN + option.rect.left() + xOffset, iconSize, option.rect.width()), MARGIN + option.rect.top(), iconSize, iconSize), pixmap, QRect(0, 0, iconSize, iconSize));
} else {
iconSize = -MARGIN;
}
QRect contentsRect(pluginSelector_d->dependantLayoutValue(MARGIN * 2 + iconSize + option.rect.left() + xOffset, option.rect.width() - MARGIN * 3 - iconSize - xOffset, option.rect.width()), MARGIN + option.rect.top(), option.rect.width() - MARGIN * 3 - iconSize - xOffset, option.rect.height() - MARGIN * 2);
int lessHorizontalSpace = MARGIN * 2 + pushButton->sizeHint().width();
if (index.model()->data(index, ServicesCountRole).toBool()) {
lessHorizontalSpace += MARGIN + pushButton->sizeHint().width();
}
contentsRect.setWidth(contentsRect.width() - lessHorizontalSpace);
if (option.state & QStyle::State_Selected) {
painter->setPen(option.palette.highlightedText().color());
}
if (pluginSelector_d->listView->layoutDirection() == Qt::RightToLeft) {
contentsRect.translate(lessHorizontalSpace, 0);
}
painter->save();
if (disabled) {
QPalette pal(option.palette);
pal.setCurrentColorGroup(QPalette::Disabled);
painter->setPen(pal.text().color());
}
painter->save();
QFont font = titleFont(option.font);
QFontMetrics fmTitle(font);
painter->setFont(font);
painter->drawText(contentsRect, Qt::AlignLeft | Qt::AlignTop, fmTitle.elidedText(index.model()->data(index, Qt::DisplayRole).toString(), Qt::ElideRight, contentsRect.width()));
painter->restore();
painter->drawText(contentsRect, Qt::AlignLeft | Qt::AlignBottom, option.fontMetrics.elidedText(index.model()->data(index, CommentRole).toString(), Qt::ElideRight, contentsRect.width()));
painter->restore();
painter->restore();
}
QSize KPluginSelector::Private::PluginDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
int i = 5;
int j = 1;
if (index.model()->data(index, ServicesCountRole).toBool()) {
i = 6;
j = 2;
}
if (!pluginSelector_d->showIcons) {
i--;
}
QFont font = titleFont(option.font);
QFontMetrics fmTitle(font);
return QSize(qMax(fmTitle.width(index.model()->data(index, Qt::DisplayRole).toString()),
option.fontMetrics.width(index.model()->data(index, CommentRole).toString())) +
(pluginSelector_d->showIcons ? KIconLoader::SizeMedium : 0) + MARGIN * i + pushButton->sizeHint().width() * j,
qMax(KIconLoader::SizeMedium + MARGIN * 2, fmTitle.height() + option.fontMetrics.height() + MARGIN * 2));
}
QList<QWidget*> KPluginSelector::Private::PluginDelegate::createItemWidgets() const
{
QList<QWidget*> widgetList;
QCheckBox *enabledCheckBox = new QCheckBox;
connect(enabledCheckBox, SIGNAL(clicked(bool)), this, SLOT(slotStateChanged(bool)));
connect(enabledCheckBox, SIGNAL(clicked(bool)), this, SLOT(emitChanged()));
KPushButton *aboutPushButton = new KPushButton;
aboutPushButton->setIcon(KIcon("dialog-information"));
connect(aboutPushButton, SIGNAL(clicked(bool)), this, SLOT(slotAboutClicked()));
KPushButton *configurePushButton = new KPushButton;
configurePushButton->setIcon(KIcon("configure"));
connect(configurePushButton, SIGNAL(clicked(bool)), this, SLOT(slotConfigureClicked()));
setBlockedEventTypes(enabledCheckBox, QList<QEvent::Type>() << QEvent::MouseButtonPress
<< QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick
<< QEvent::KeyPress << QEvent::KeyRelease);
setBlockedEventTypes(aboutPushButton, QList<QEvent::Type>() << QEvent::MouseButtonPress
<< QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick
<< QEvent::KeyPress << QEvent::KeyRelease);
setBlockedEventTypes(configurePushButton, QList<QEvent::Type>() << QEvent::MouseButtonPress
<< QEvent::MouseButtonRelease << QEvent::MouseButtonDblClick
<< QEvent::KeyPress << QEvent::KeyRelease);
widgetList << enabledCheckBox << configurePushButton << aboutPushButton;
return widgetList;
}
void KPluginSelector::Private::PluginDelegate::updateItemWidgets(const QList<QWidget*> widgets,
const QStyleOptionViewItem &option,
const QPersistentModelIndex &index) const
{
QCheckBox *checkBox = static_cast<QCheckBox*>(widgets[0]);
checkBox->resize(checkBox->sizeHint());
checkBox->move(pluginSelector_d->dependantLayoutValue(MARGIN, checkBox->sizeHint().width(), option.rect.width()), option.rect.height() / 2 - checkBox->sizeHint().height() / 2);
KPushButton *aboutPushButton = static_cast<KPushButton*>(widgets[2]);
QSize aboutPushButtonSizeHint = aboutPushButton->sizeHint();
aboutPushButton->resize(aboutPushButtonSizeHint);
aboutPushButton->move(pluginSelector_d->dependantLayoutValue(option.rect.width() - MARGIN - aboutPushButtonSizeHint.width(), aboutPushButtonSizeHint.width(), option.rect.width()), option.rect.height() / 2 - aboutPushButtonSizeHint.height() / 2);
KPushButton *configurePushButton = static_cast<KPushButton*>(widgets[1]);
QSize configurePushButtonSizeHint = configurePushButton->sizeHint();
configurePushButton->resize(configurePushButtonSizeHint);
configurePushButton->move(pluginSelector_d->dependantLayoutValue(option.rect.width() - MARGIN * 2 - configurePushButtonSizeHint.width() - aboutPushButtonSizeHint.width(), configurePushButtonSizeHint.width(), option.rect.width()), option.rect.height() / 2 - configurePushButtonSizeHint.height() / 2);
if (!index.isValid() || !index.internalPointer()) {
checkBox->setVisible(false);
aboutPushButton->setVisible(false);
configurePushButton->setVisible(false);
} else {
checkBox->setChecked(index.model()->data(index, Qt::CheckStateRole).toBool());
checkBox->setEnabled(index.model()->data(index, IsCheckableRole).toBool());
configurePushButton->setVisible(index.model()->data(index, ServicesCountRole).toBool());
configurePushButton->setEnabled(index.model()->data(index, Qt::CheckStateRole).toBool());
}
}
void KPluginSelector::Private::PluginDelegate::slotStateChanged(bool state)
{
if (!focusedIndex().isValid())
return;
const QModelIndex index = focusedIndex();
pluginSelector_d->dependenciesWidget->clearDependencies();
PluginEntry *pluginEntry = index.model()->data(index, PluginEntryRole).value<PluginEntry*>();
pluginSelector_d->updateDependencies(pluginEntry, state);
const_cast<QAbstractItemModel*>(index.model())->setData(index, state, Qt::CheckStateRole);
}
void KPluginSelector::Private::PluginDelegate::emitChanged()
{
emit changed(true);
}
void KPluginSelector::Private::PluginDelegate::slotAboutClicked()
{
const QModelIndex index = focusedIndex();
const QAbstractItemModel *model = index.model();
// Try to retrieve the plugin information from the KComponentData object of the plugin.
// If there is no valid information, go and fetch it from the service itself (the .desktop
// file).
PluginEntry *entry = index.model()->data(index, PluginEntryRole).value<PluginEntry*>();
KService::Ptr entryService = entry->pluginInfo.service();
if (entryService) {
KPluginLoader loader(*entryService);
KPluginFactory *factory = loader.factory();
if (factory) {
const KAboutData *aboutData = factory->componentData().aboutData();
if (!aboutData->programName().isEmpty()) { // Be sure the about data is not completely empty
KAboutApplicationDialog aboutPlugin(aboutData, itemView());
aboutPlugin.setWindowTitle(i18nc("Used only for plugins", "About %1", aboutData->programName()));
2014-11-13 01:04:59 +02:00
aboutPlugin.exec();
return;
}
}
}
const QString name = model->data(index, NameRole).toString();
const QString comment = model->data(index, CommentRole).toString();
const QString author = model->data(index, AuthorRole).toString();
const QString email = model->data(index, EmailRole).toString();
const QString website = model->data(index, WebsiteRole).toString();
const QString version = model->data(index, VersionRole).toString();
const QString license = model->data(index, LicenseRole).toString();
KAboutData aboutData(name.toUtf8(), name.toUtf8(), ki18n(name.toUtf8()), version.toUtf8(), ki18n(comment.toUtf8()), KAboutLicense::byKeyword(license).key());
aboutData.setHomepage(website.toLatin1());
2014-11-13 01:04:59 +02:00
aboutData.setProgramIconName(index.model()->data(index, Qt::DecorationRole).toString());
const QStringList authors = author.split(',');
const QStringList emails = email.split(',');
if (authors.count() == emails.count()) {
int i = 0;
2014-11-13 01:04:59 +02:00
foreach (const QString &author, authors) {
if (!author.isEmpty()) {
aboutData.addAuthor(ki18n(author.toUtf8()), ki18n(QByteArray()), emails[i].toUtf8(), 0);
}
i++;
}
}
KAboutApplicationDialog aboutPlugin(&aboutData, itemView());
aboutPlugin.setWindowTitle(i18nc("Used only for plugins", "About %1", aboutData.programName()));
2014-11-13 01:04:59 +02:00
aboutPlugin.exec();
}
void KPluginSelector::Private::PluginDelegate::slotConfigureClicked()
{
const QModelIndex index = focusedIndex();
const QAbstractItemModel *model = index.model();
PluginEntry *pluginEntry = model->data(index, PluginEntryRole).value<PluginEntry*>();
KPluginInfo pluginInfo = pluginEntry->pluginInfo;
KDialog configDialog(itemView());
configDialog.setWindowTitle(model->data(index, NameRole).toString());
// The number of KCModuleProxies in use determines whether to use a tabwidget
KTabWidget *newTabWidget = 0;
// Widget to use for the setting dialog's main widget,
// either a KTabWidget or a KCModuleProxy
QWidget * mainWidget = 0;
// Widget to use as the KCModuleProxy's parent.
// The first proxy is owned by the dialog itself
QWidget *moduleProxyParentWidget = &configDialog;
foreach (const KService::Ptr &servicePtr, pluginInfo.kcmServices()) {
if(!servicePtr->noDisplay()) {
KCModuleInfo moduleInfo(servicePtr);
KCModuleProxy *currentModuleProxy = new KCModuleProxy(moduleInfo, moduleProxyParentWidget);
if (currentModuleProxy->realModule()) {
moduleProxyList << currentModuleProxy;
if (mainWidget && !newTabWidget) {
// we already created one KCModuleProxy, so we need a tab widget.
// Move the first proxy into the tab widget and ensure this and subsequent
// proxies are in the tab widget
newTabWidget = new KTabWidget(&configDialog);
moduleProxyParentWidget = newTabWidget;
mainWidget->setParent( newTabWidget );
KCModuleProxy *moduleProxy = qobject_cast<KCModuleProxy*>(mainWidget);
if (moduleProxy) {
newTabWidget->addTab(mainWidget, moduleProxy->moduleInfo().moduleName());
mainWidget = newTabWidget;
} else {
delete newTabWidget;
newTabWidget = 0;
moduleProxyParentWidget = &configDialog;
mainWidget->setParent(0);
}
}
if (newTabWidget) {
newTabWidget->addTab(currentModuleProxy, servicePtr->name());
} else {
mainWidget = currentModuleProxy;
}
} else {
delete currentModuleProxy;
}
}
}
// it could happen that we had services to show, but none of them were real modules.
if (moduleProxyList.count()) {
configDialog.setButtons(KDialog::Ok | KDialog::Cancel | KDialog::Default);
QWidget *showWidget = new QWidget(&configDialog);
QVBoxLayout *layout = new QVBoxLayout;
showWidget->setLayout(layout);
layout->addWidget(mainWidget);
layout->insertSpacing(-1, KDialog::marginHint());
configDialog.setMainWidget(showWidget);
connect(&configDialog, SIGNAL(defaultClicked()), this, SLOT(slotDefaultClicked()));
if (configDialog.exec() == QDialog::Accepted) {
foreach (KCModuleProxy *moduleProxy, moduleProxyList) {
QStringList parentComponents = moduleProxy->moduleInfo().service()->property("X-KDE-ParentComponents").toStringList();
moduleProxy->save();
foreach (const QString &parentComponent, parentComponents) {
emit configCommitted(parentComponent.toLatin1());
}
}
} else {
foreach (KCModuleProxy *moduleProxy, moduleProxyList) {
moduleProxy->load();
}
}
qDeleteAll(moduleProxyList);
moduleProxyList.clear();
}
}
void KPluginSelector::Private::PluginDelegate::slotDefaultClicked()
{
foreach (KCModuleProxy *moduleProxy, moduleProxyList) {
moduleProxy->defaults();
}
}
QFont KPluginSelector::Private::PluginDelegate::titleFont(const QFont &baseFont) const
{
QFont retFont(baseFont);
retFont.setBold(true);
return retFont;
}
#include "moc_kpluginselector_p.cpp"
#include "moc_kpluginselector.cpp"