File indexing completed on 2024-05-12 16:39:50

0001 /* This file is part of the KDE project
0002    Copyright (C) 2005-2006 Jarosław Staniek <staniek@kde.org>
0003    Copyright (C) 2012 Adam Pigg <adam@piggz.co.uk>
0004 
0005    This library is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU Library General Public
0007    License as published by the Free Software Foundation; either
0008    version 2 of the License, or (at your option) any later version.
0009 
0010    This library is distributed in the hope that it will be useful,
0011    but WITHOUT ANY WARRANTY; without even the implied warranty of
0012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013    Library General Public License for more details.
0014 
0015    You should have received a copy of the GNU Library General Public License
0016    along with this library; see the file COPYING.LIB.  If not, write to
0017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018  * Boston, MA 02110-1301, USA.
0019 */
0020 
0021 #include "kexiactionselectiondialog.h"
0022 #include "kexiactionselectiondialog_p.h"
0023 
0024 #include <kexipartitem.h>
0025 #include <kexiproject.h>
0026 #include <kexipartinfo.h>
0027 #include <kexipart.h>
0028 #include <kexipartmanager.h>
0029 #include <kexiactioncategories.h>
0030 #include <KexiMainWindowIface.h>
0031 #include <KexiIcon.h>
0032 
0033 #include <QDebug>
0034 
0035 #include <QLabel>
0036 #include <QPushButton>
0037 #include <QGridLayout>
0038 #include <QVBoxLayout>
0039 #include <QPixmap>
0040 #include <QStackedWidget>
0041 #include <QDialogButtonBox>
0042 #include <QAction>
0043 
0044 #include <widget/navigator/KexiProjectNavigator.h>
0045 #include <widget/navigator/KexiProjectModel.h>
0046 #include <kexiutils/utils.h>
0047 #include <kexi_global.h>
0048 
0049 class ActionSelectorDialogTreeItem : public QTreeWidgetItem
0050 {
0051 public:
0052   enum ActionRole{
0053     ActionCategoryRole = Qt::UserRole + 1,
0054     ActionDataRole,
0055     ActionPluginIdRole
0056   };
0057 
0058   ActionSelectorDialogTreeItem(const QString &label, QTreeWidget *parent)
0059   : QTreeWidgetItem(parent) {
0060       setText(0, label);
0061 
0062   }
0063 
0064   ActionSelectorDialogTreeItem(const QString &label, QTreeWidgetItem *parent)
0065           : QTreeWidgetItem(parent) {
0066               setText(0, label);
0067 
0068   }
0069 
0070   using QTreeWidgetItem::data;
0071   QVariant data(ActionRole role) const
0072   {
0073       return QTreeWidgetItem::data(0, role);
0074   };
0075 
0076   using QTreeWidgetItem::setData;
0077   void setData(ActionRole role, const QVariant &value) {
0078       QTreeWidgetItem::setData(0, role, value);
0079   }
0080 
0081   QIcon icon() const {
0082       return QTreeWidgetItem::icon(0);
0083   }
0084 
0085   void setIcon(const QIcon& icon) {
0086       QTreeWidgetItem::setIcon(0, icon);
0087   }
0088 
0089 };
0090 
0091 //---------------------------------------
0092 
0093 ActionsListViewBase::ActionsListViewBase(QWidget* parent)
0094         : QTreeWidget(parent)
0095 {
0096     setColumnCount(1);
0097     setHeaderHidden(true);
0098     setRootIsDecorated(false);
0099 }
0100 
0101 ActionsListViewBase::~ActionsListViewBase()
0102 {
0103 }
0104 
0105 QTreeWidgetItem *ActionsListViewBase::itemForAction(const QString& actionName, QTreeWidgetItem* parent)
0106 {
0107     Q_UNUSED(parent);
0108     QTreeWidgetItemIterator it(this);
0109     while (*it) {
0110         ActionSelectorDialogTreeItem* itm = dynamic_cast<ActionSelectorDialogTreeItem*>(*it);
0111         if (itm && itm->data(ActionSelectorDialogTreeItem::ActionDataRole).toString() == actionName)
0112             return itm;
0113         ++it;
0114     }
0115 
0116     return 0;
0117 }
0118 
0119 void ActionsListViewBase::selectAction(const QString& actionName)
0120 {
0121   //qDebug() << "Selecting action:" << actionName;
0122   QTreeWidgetItem *itm = itemForAction(actionName);
0123   if (itm) {
0124     setCurrentItem(itm);
0125     itm->setSelected(true);
0126   }
0127 }
0128 
0129 //---------------------------------------
0130 
0131 KActionsListViewBase::KActionsListViewBase(QWidget* parent)
0132         : ActionsListViewBase(parent)
0133 {
0134 }
0135 
0136 KActionsListViewBase::~KActionsListViewBase() {}
0137 
0138 void KActionsListViewBase::init()
0139 {
0140     const QPixmap noIcon(KexiUtils::emptyIcon(KIconLoader::Small));
0141     QList<QAction*> sharedActions(KexiMainWindowIface::global()->allActions());
0142     const Kexi::ActionCategories *acat = Kexi::actionCategories();
0143     foreach(QAction *action, sharedActions) {
0144 //   qDebug() << (*it)->name() << " " << (*it)->text();
0145         //! @todo group actions
0146         //! @todo: store QAction * here?
0147         const int actionCategories = acat->actionCategories(action->objectName().toLatin1());
0148         if (actionCategories == -1) {
0149             qWarning() << "no category declared for action \""
0150                 << action->objectName() << "\"! Fix this!";
0151             continue;
0152         }
0153         if (!isActionVisible(action->objectName().toLatin1(), actionCategories))
0154             continue;
0155         QString actionName;
0156         if (!action->toolTip().isEmpty()) {
0157             actionName = action->toolTip().remove("<html>").remove("</html>");
0158         } else {
0159             actionName = action->text().remove('&');
0160         }
0161         ActionSelectorDialogTreeItem *pitem = new ActionSelectorDialogTreeItem(
0162             actionName, this);
0163 
0164         pitem->setData(ActionSelectorDialogTreeItem::ActionCategoryRole, "kaction");
0165         pitem->setData(ActionSelectorDialogTreeItem::ActionDataRole, action->objectName());
0166 
0167         pitem->setIcon(action->icon());
0168         if (pitem->icon().isNull())
0169             pitem->setIcon(noIcon);
0170     }
0171     setSortingEnabled(true);
0172 }
0173 
0174 //---------------------------------------
0175 
0176 //! @internal Used to display KActions (in column 2)
0177 class KActionsListView : public KActionsListViewBase
0178 {
0179     Q_OBJECT
0180 public:
0181     explicit KActionsListView(QWidget* parent)
0182             : KActionsListViewBase(parent) {
0183     }
0184     virtual ~KActionsListView() {}
0185 
0186     virtual bool isActionVisible(const char* actionName, int actionCategories) const override {
0187         Q_UNUSED(actionName);
0188         return actionCategories & Kexi::GlobalActionCategory;
0189     }
0190 };
0191 
0192 //! @internal Used to display KActions (in column 2)
0193 class CurrentFormActionsListView : public KActionsListViewBase
0194 {
0195     Q_OBJECT
0196 public:
0197     explicit CurrentFormActionsListView(QWidget* parent)
0198             : KActionsListViewBase(parent) {
0199     }
0200     virtual ~CurrentFormActionsListView() {}
0201 
0202     virtual bool isActionVisible(const char* actionName, int actionCategories) const override {
0203         return actionCategories & Kexi::WindowActionCategory
0204                && Kexi::actionCategories()->actionSupportsObjectType(actionName, KexiPart::FormObjectType);
0205     }
0206 };
0207 
0208 //! @internal a list view displaying action categories user can select from (column 1)
0209 class ActionCategoriesListView : public ActionsListViewBase
0210 {
0211     Q_OBJECT
0212 public:
0213     explicit ActionCategoriesListView(QWidget* parent)
0214             : ActionsListViewBase(parent) {
0215         ActionSelectorDialogTreeItem *itm = new ActionSelectorDialogTreeItem(xi18n("No action"), this );
0216         itm->setData(ActionSelectorDialogTreeItem::ActionCategoryRole, "noaction");
0217         itm->setData(ActionSelectorDialogTreeItem::ActionDataRole, "noaction");
0218         const QPixmap noIcon(KexiUtils::emptyIcon(KIconLoader::Small));
0219         itm->setIcon(noIcon);
0220 
0221         itm = new ActionSelectorDialogTreeItem(xi18n("Application actions"), this );
0222         itm->setData(ActionSelectorDialogTreeItem::ActionCategoryRole, "kaction");
0223         itm->setData(ActionSelectorDialogTreeItem::ActionDataRole, "kaction");
0224         itm->setIcon(koIcon("kexi"));
0225 
0226         KexiPart::PartInfoList *pl = Kexi::partManager().infoList();
0227         if (pl) {
0228             foreach(KexiPart::Info *info, *pl) {
0229                 KexiPart::Part *part = Kexi::partManager().part(info);
0230                 if (!info->isVisibleInNavigator() || !part)
0231                     continue;
0232                 itm = new ActionSelectorDialogTreeItem(part->info()->name(), this );
0233                 itm->setData(ActionSelectorDialogTreeItem::ActionCategoryRole, "navObject");
0234                 itm->setData(ActionSelectorDialogTreeItem::ActionDataRole, info->typeName());
0235                 itm->setData(ActionSelectorDialogTreeItem::ActionPluginIdRole, info->pluginId());
0236                 itm->setIcon(QIcon::fromTheme(part->info()->iconName()));
0237             }
0238         }
0239 
0240         QTreeWidgetItem *fitm = itemForAction("form");
0241         if (fitm) {
0242             itm = new ActionSelectorDialogTreeItem(xi18nc("Current form's actions", "Current"), fitm);
0243         } else {
0244             itm = new ActionSelectorDialogTreeItem(xi18nc("Current form's actions", "Current"), this);
0245         }
0246 
0247         itm->setData(ActionSelectorDialogTreeItem::ActionCategoryRole, "currentForm");
0248         itm->setData(ActionSelectorDialogTreeItem::ActionDataRole, "currentForm");
0249         itm->setIcon(KexiIcon("form"));
0250 
0251         expandAll();
0252         setSortingEnabled(false);
0253     }
0254 
0255     ~ActionCategoriesListView() {
0256     }
0257 
0258 };
0259 
0260 //! @internal Used to display list of actions available to executing (column 3)
0261 class ActionToExecuteListView : public ActionsListViewBase
0262 {
0263     Q_OBJECT
0264 public:
0265     explicit ActionToExecuteListView(QWidget* parent)
0266             : ActionsListViewBase(parent) {
0267     }
0268 
0269     ~ActionToExecuteListView() {
0270     }
0271 
0272     //! Updates actions
0273     void showActionsForPluginId(const QString& pluginId) {
0274         if (m_currentPluginId == pluginId)
0275             return;
0276         m_currentPluginId = pluginId;
0277         clear();
0278         KexiPart::Part *part = Kexi::partManager().partForPluginId(m_currentPluginId);
0279         if (!part)
0280             return;
0281         Kexi::ViewModes supportedViewModes = part->info()->supportedViewModes();
0282         ActionSelectorDialogTreeItem *itm;
0283         const QPixmap noIcon(KexiUtils::emptyIcon(KIconLoader::Small));
0284         if (supportedViewModes & Kexi::DataViewMode) {
0285             itm = new ActionSelectorDialogTreeItem(xi18n("Open in Data View"), this);
0286             itm->setData(ActionSelectorDialogTreeItem::ActionDataRole , "open");
0287             itm->setIcon(koIcon("document-open"));
0288         }
0289         if (part->info()->isExecuteSupported()) {
0290             itm = new ActionSelectorDialogTreeItem(xi18n("Execute"), this);
0291             itm->setData(ActionSelectorDialogTreeItem::ActionDataRole , "execute");
0292             itm->setIcon(koIcon("media-playback-start"));
0293         }
0294 #ifdef KEXI_QUICK_PRINTING_SUPPORT
0295         if (part->info()->isPrintingSupported()) {
0296             itm = new ActionSelectorDialogTreeItem(futureI18n("Print"), this);
0297             itm->setData(ActionSelectorDialogTreeItem::ActionDataRole , "print");
0298             itm->setIcon(koIcon("document-print"));
0299             QAction *a = KStandardAction::printPreview(0, 0, 0);
0300             itm = new ActionSelectorDialogTreeItem(a->text().remove('&').remove("..."),
0301                                                    this);
0302             itm->setData(ActionSelectorDialogTreeItem::ActionDataRole , "printPreview");
0303             itm->setIcon(a->icon());
0304             delete a;
0305             itm = new ActionSelectorDialogTreeItem(futureI18n("Show Page Setup"), this);
0306             itm->setData(ActionSelectorDialogTreeItem::ActionDataRole , "pageSetup");
0307             itm->setIcon(noIcon);
0308             setItemExpanded(itm, true);
0309         }
0310 #endif
0311         if (part->info()->isDataExportSupported()) {
0312             itm = new ActionSelectorDialogTreeItem(
0313                 xi18nc("Note: use multiple rows if needed", "Export to File\nAs Data Table"), this);
0314             itm->setData(ActionSelectorDialogTreeItem::ActionDataRole , "exportToCSV");
0315             itm->setIcon(KexiIcon("table"));
0316 
0317             QTreeWidgetItem *eitem = itm;
0318 
0319             itm = new ActionSelectorDialogTreeItem(xi18nc("Note: use multiple rows if needed", "Copy to Clipboard\nAs Data Table"), eitem);
0320             itm->setData(ActionSelectorDialogTreeItem::ActionDataRole , "copyToClipboardAsCSV");
0321             itm->setIcon(KexiIcon("table"));
0322         }
0323 
0324         itm = new ActionSelectorDialogTreeItem(xi18n("Create New Object (%1)", part->info()->name().toLower()), this);
0325         itm->setData(ActionSelectorDialogTreeItem::ActionDataRole , "new");
0326         itm->setIcon(koIcon("document-new"));
0327 
0328         if (supportedViewModes & Kexi::DesignViewMode) {
0329             itm = new ActionSelectorDialogTreeItem(xi18n("Open in Design View"), this);
0330             itm->setData(ActionSelectorDialogTreeItem::ActionDataRole , "design");
0331             itm->setIcon(koIcon("document-properties"));
0332         }
0333         if (supportedViewModes & Kexi::TextViewMode) {
0334             itm = new ActionSelectorDialogTreeItem(xi18n("Open in Text View"), this);
0335             itm->setData(ActionSelectorDialogTreeItem::ActionDataRole , "editText");
0336             itm->setIcon(noIcon);
0337         }
0338 
0339         itm = new ActionSelectorDialogTreeItem( xi18n("Close View"), this);
0340         itm->setData(ActionSelectorDialogTreeItem::ActionDataRole , "close");
0341         itm->setIcon(koIcon("window-close"));
0342 
0343         expandAll();
0344         setSortingEnabled(true);
0345     }
0346 
0347     QString m_currentPluginId;
0348 };
0349 
0350 //-------------------------------------
0351 
0352 //! @internal
0353 class Q_DECL_HIDDEN KexiActionSelectionDialog::Private
0354 {
0355 public:
0356     Private()
0357             : kactionPageWidget(0), kactionListView(0), objectsListView(0)
0358             , currentFormActionsPageWidget(0)
0359             , currentFormActionsListView(0)
0360             , secondAnd3rdColumnMainWidget(0)
0361             , hideActionToExecuteListView(false) {
0362     }
0363 
0364     void raiseWidget(QWidget *w) {
0365         secondAnd3rdColumnStack->setCurrentWidget(w);
0366     }
0367 
0368     QString selectActionToBeExecutedMessage(const QString& actionType) const {
0369         if (actionType == "noaction")
0370             return QString();
0371         if (actionType == "kaction" || actionType == "currentForm")
0372             return xi18n("&Select action to be executed after clicking <resource>%1</resource> button:",
0373                         actionWidgetName);
0374         // hardcoded, but it's not that bad
0375         if (actionType == "org.kexi-project.macro")
0376             return xi18n("&Select macro to be executed after clicking <resource>%1</resource> button:",
0377                         actionWidgetName);
0378         if (actionType == "org.kexi-project.script")
0379             return xi18n("&Select script to be executed after clicking <resource>%1</resource> button:",
0380                         actionWidgetName);
0381         //default: org.kexi-project.table/query/form/report...
0382         return xi18n("&Select object to be opened after clicking <resource>%1</resource> button:",
0383                     actionWidgetName);
0384     }
0385 
0386     // changes 3rd column visibility
0387     void setActionToExecuteSectionVisible(bool visible) {
0388         actionToExecuteListView->setVisible(visible);
0389         actionToExecuteLbl->setVisible(visible);
0390     }
0391 
0392     QString actionWidgetName;
0393     ActionCategoriesListView* actionCategoriesListView; //!< for column #1
0394     QWidget *kactionPageWidget;
0395     KActionsListView* kactionListView;  //!< for column #2
0396     KexiProjectNavigator* objectsListView; //!< for column #2
0397     QWidget *currentFormActionsPageWidget; //!< for column #2
0398     CurrentFormActionsListView* currentFormActionsListView; //!< for column #2
0399     QWidget *emptyWidget;
0400     QLabel *selectActionToBeExecutedLabel;
0401     QLabel *kactionPageLabel;
0402     QLabel *currentFormActionsPageLabel;
0403     ActionToExecuteListView* actionToExecuteListView;
0404     QLabel *actionToExecuteLbl;
0405     QWidget *secondAnd3rdColumnMainWidget;
0406     QGridLayout *glyr;
0407     QGridLayout *secondAnd3rdColumnGrLyr;
0408     QStackedWidget *secondAnd3rdColumnStack; //, *secondColumnStack;
0409     bool hideActionToExecuteListView;
0410     QDialogButtonBox *buttonBox;
0411 };
0412 
0413 //-------------------------------------
0414 
0415 static QLabel *createSelectActionLabel(QWidget *parent, QWidget *buddy)
0416 {
0417     QLabel *lbl = new QLabel(parent);
0418     lbl->setBuddy(buddy);
0419     lbl->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
0420     lbl->setAlignment(Qt::AlignTop | Qt::AlignLeft);
0421     lbl->setWordWrap(true);
0422     lbl->setMinimumHeight(lbl->fontMetrics().height()*2);
0423     return lbl;
0424 }
0425 
0426 //-------------------------------------
0427 
0428 KexiActionSelectionDialog::KexiActionSelectionDialog(
0429     QWidget *parent, const KexiFormEventAction::ActionData& action,
0430     const QString& actionWidgetName)
0431         : QDialog(parent)
0432         , d(new Private())
0433 {
0434     setModal(true);
0435     setObjectName("actionSelectorDialog");
0436     setWindowTitle(xi18nc("@title:window", "Assigning Action to Button"));
0437 
0438     // layout
0439     QVBoxLayout *mainLayout = new QVBoxLayout;
0440     setLayout(mainLayout);
0441     QWidget *mainWidget = new QWidget(this);
0442     mainWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
0443     mainLayout->addWidget(mainWidget);
0444 
0445     /*    lbl 1
0446        +------------+ +-------------------------------+
0447        |            | |              [a]              |
0448        | 1st column | | +----------- + +------------+ |
0449        |            | | | 2nd column | | 3rd column | |
0450        |            | | +            + +            + |
0451        |            | | +------------+ +------------+ |
0452        +------------+ +-------------------------------+
0453        \______________________________________________/
0454                             glyr
0455       [a]- QStackedWidget *secondAnd3rdColumnStack,
0456         - for displaying KActions, the stack contains d->kactionPageWidget QWidget
0457         - for displaying objects, the stack contains secondAnd3rdColumnMainWidget QWidget and
0458           QGridLayout *secondAnd3rdColumnGrLyr
0459        - kactionPageWidget contains only a QVBoxLayout and label+kactionListView
0460     */
0461     d->glyr = new QGridLayout(mainWidget); // 2x2
0462     KexiUtils::setStandardMarginsAndSpacing(d->glyr);
0463     d->glyr->setRowStretch(1, 1);
0464 
0465     // 1st column: action types
0466     d->actionCategoriesListView = new ActionCategoriesListView(mainWidget);
0467     d->actionCategoriesListView->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
0468     d->glyr->addWidget(d->actionCategoriesListView, 1, 0);
0469     connect(d->actionCategoriesListView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
0470             this, SLOT(slotActionCategorySelected(QTreeWidgetItem*)));
0471 
0472     QLabel *lbl = new QLabel(xi18n("Action category:"), mainWidget);
0473     lbl->setBuddy(d->actionCategoriesListView);
0474     lbl->setMinimumHeight(lbl->fontMetrics().height()*2);
0475     lbl->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
0476     lbl->setAlignment(Qt::AlignTop | Qt::AlignLeft);
0477     lbl->setWordWrap(true);
0478 
0479     d->glyr->addWidget(lbl, 0, 0, Qt::AlignTop | Qt::AlignLeft);
0480 
0481     // widget stack for 2nd and 3rd column
0482     d->secondAnd3rdColumnStack = new QStackedWidget(mainWidget);
0483     d->secondAnd3rdColumnStack->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
0484     d->glyr->addWidget(d->secondAnd3rdColumnStack, 0, 1, 2, 1);
0485 
0486     d->secondAnd3rdColumnMainWidget = new QWidget(d->secondAnd3rdColumnStack);
0487     d->secondAnd3rdColumnMainWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
0488     d->secondAnd3rdColumnGrLyr = new QGridLayout(d->secondAnd3rdColumnMainWidget);
0489     //! @todo KEXI3 QDialog::resizeLayout(d->secondAnd3rdColumnGrLyr, 0, KexiUtils::spacingHint());
0490     d->secondAnd3rdColumnGrLyr->setRowStretch(1, 2);
0491     d->secondAnd3rdColumnStack->addWidget(d->secondAnd3rdColumnMainWidget);
0492 
0493     // 2nd column: list of actions/objects
0494     d->objectsListView = new KexiProjectNavigator(d->secondAnd3rdColumnMainWidget,
0495                                                   KexiProjectNavigator::Borders);
0496     d->secondAnd3rdColumnGrLyr->addWidget(d->objectsListView, 1, 0);
0497     d->secondAnd3rdColumnGrLyr->setColumnStretch(0,1);
0498     d->secondAnd3rdColumnGrLyr->setColumnStretch(1,1);
0499     connect(d->objectsListView, SIGNAL(selectionChanged(KexiPart::Item*)),
0500             this, SLOT(slotItemForOpeningOrExecutingSelected(KexiPart::Item*)));
0501 
0502     d->selectActionToBeExecutedLabel = createSelectActionLabel(d->secondAnd3rdColumnMainWidget, 0);
0503     d->secondAnd3rdColumnGrLyr->addWidget(
0504         d->selectActionToBeExecutedLabel, 0, 0, Qt::AlignTop | Qt::AlignLeft);
0505 
0506     d->emptyWidget = new QWidget(d->secondAnd3rdColumnStack);
0507     d->secondAnd3rdColumnStack->addWidget(d->emptyWidget);
0508 
0509     // 3rd column: actions to execute
0510     d->actionToExecuteListView = new ActionToExecuteListView(d->secondAnd3rdColumnMainWidget);
0511     d->actionToExecuteListView->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
0512 
0513     connect(d->actionToExecuteListView, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
0514             this, SLOT(slotActionToExecuteItemExecuted(QTreeWidgetItem*)));
0515     connect(d->actionToExecuteListView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
0516             this, SLOT(slotActionToExecuteItemSelected(QTreeWidgetItem*)));
0517 
0518     d->secondAnd3rdColumnGrLyr->addWidget(d->actionToExecuteListView, 1, 1);
0519 
0520     d->actionToExecuteLbl = createSelectActionLabel(d->secondAnd3rdColumnMainWidget,
0521                                                     d->actionToExecuteListView);
0522     d->actionToExecuteLbl->setText(xi18n("Action to execute:"));
0523     d->secondAnd3rdColumnGrLyr->addWidget(d->actionToExecuteLbl, 0, 1, Qt::AlignTop | Qt::AlignLeft);
0524 
0525     // buttons
0526     d->buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
0527     QPushButton *okButton = d->buttonBox->button(QDialogButtonBox::Ok);
0528     okButton->setDefault(true);
0529     okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
0530     connect(d->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
0531     connect(d->buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
0532     d->actionWidgetName = actionWidgetName;
0533     d->buttonBox->button(QDialogButtonBox::Ok)->setText(xi18nc("Assign action", "&Assign"));
0534     //buttonBox->button(QDialogButtonBox::Ok)->setIcon(koIconName("dialog-ok"));
0535     d->buttonBox->button(QDialogButtonBox::Ok)->setToolTip(xi18n("Assign action"));
0536     mainLayout->addWidget(d->buttonBox);
0537 
0538     // temporary show all sections to avoid resizing the dialog in the future
0539     d->actionCategoriesListView->selectAction("table");
0540     d->setActionToExecuteSectionVisible(true);
0541     adjustSize();
0542     resize(qMax(700, width()), qMax(450, height()));
0543 
0544     bool ok;
0545     QString actionType, actionArg;
0546     KexiPart::Info* partInfo = action.decodeString(actionType, actionArg, &ok);
0547     if (ok) {
0548         d->actionCategoriesListView->selectAction(actionType);
0549         if (actionType == "kaction") {
0550             d->kactionListView->selectAction(actionArg);
0551             d->kactionListView->setFocus();
0552         } else if (actionType == "currentForm") {
0553             d->currentFormActionsListView->selectAction(actionArg);
0554             d->currentFormActionsListView->setFocus();
0555         } else if (partInfo
0556                    && Kexi::partManager().part(partInfo)) // We use the Part Manager
0557             // to determine whether the Kexi-plugin is installed and whether we like to show
0558             // it in our list of actions.
0559         {
0560             KexiPart::Item *item = KexiMainWindowIface::global()->project()->item(
0561                                        partInfo, actionArg);
0562             if (d->objectsListView && item) {
0563                 d->objectsListView->selectItem(*item);
0564                 slotItemForOpeningOrExecutingSelected(item);
0565 
0566                 QString actionOption(action.option);
0567                 if (actionOption.isEmpty()) {
0568                     actionOption = "open"; // for backward compatibility
0569                 }
0570                 d->actionToExecuteListView->selectAction(actionOption);
0571                 d->objectsListView->setFocus();
0572             }
0573         }
0574     } else {//invalid assignment or 'noaction'
0575         d->actionCategoriesListView->selectAction("noaction");
0576         d->actionCategoriesListView->setFocus();
0577     }
0578 }
0579 
0580 KexiActionSelectionDialog::~KexiActionSelectionDialog()
0581 {
0582     delete d;
0583 }
0584 
0585 void KexiActionSelectionDialog::slotKActionItemExecuted(QTreeWidgetItem*)
0586 {
0587     accept();
0588 }
0589 
0590 void KexiActionSelectionDialog::slotKActionItemSelected(QTreeWidgetItem*)
0591 {
0592     d->setActionToExecuteSectionVisible(false);
0593     updateOKButtonStatus();
0594 }
0595 
0596 void KexiActionSelectionDialog::slotCurrentFormActionItemExecuted(QTreeWidgetItem*)
0597 {
0598     accept();
0599 }
0600 
0601 void KexiActionSelectionDialog::slotCurrentFormActionItemSelected(QTreeWidgetItem*)
0602 {
0603     d->setActionToExecuteSectionVisible(false);
0604     updateOKButtonStatus();
0605 }
0606 
0607 void KexiActionSelectionDialog::slotItemForOpeningOrExecutingSelected(KexiPart::Item* item)
0608 {
0609     d->setActionToExecuteSectionVisible(item);
0610 }
0611 
0612 void KexiActionSelectionDialog::slotActionToExecuteItemExecuted(QTreeWidgetItem* item)
0613 {
0614     if (!item)
0615         return;
0616     ActionSelectorDialogTreeItem *listItem = dynamic_cast<ActionSelectorDialogTreeItem*>(item);
0617     if (listItem && listItem->data(ActionSelectorDialogTreeItem::ActionDataRole).isValid())
0618         accept();
0619 }
0620 
0621 void KexiActionSelectionDialog::slotActionToExecuteItemSelected(QTreeWidgetItem*)
0622 {
0623     updateOKButtonStatus();
0624 }
0625 
0626 void KexiActionSelectionDialog::slotActionCategorySelected(QTreeWidgetItem* item)
0627 {
0628     ActionSelectorDialogTreeItem *categoryItm = dynamic_cast<ActionSelectorDialogTreeItem*>(item);
0629     // simple case: part-less item, e.g. kaction:
0630     if (categoryItm) {
0631         if (categoryItm->data(ActionSelectorDialogTreeItem::ActionCategoryRole).toString() == "kaction") {
0632             if (!d->kactionPageWidget) {
0633                 //create lbl+list view with a vlayout
0634                 d->kactionPageWidget = new QWidget();
0635                 d->kactionPageWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
0636                 QVBoxLayout *vlyr = new QVBoxLayout(d->kactionPageWidget);
0637                 vlyr->setSpacing(KexiUtils::spacingHint());
0638                 d->kactionListView = new KActionsListView(d->kactionPageWidget);
0639                 d->kactionListView->init();
0640                 d->kactionPageLabel  = createSelectActionLabel(d->kactionPageWidget, d->kactionListView);
0641                 vlyr->addWidget(d->kactionPageLabel);
0642                 vlyr->addWidget(d->kactionListView);
0643                 KexiUtils::setMargins(vlyr, 0);
0644                 d->secondAnd3rdColumnStack->addWidget(d->kactionPageWidget);
0645                 connect(d->kactionListView, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
0646                         this, SLOT(slotKActionItemExecuted(QTreeWidgetItem*)));
0647                 connect(d->kactionListView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
0648                         this, SLOT(slotKActionItemSelected(QTreeWidgetItem*)));
0649             }
0650             d->kactionPageLabel->setText(
0651                 d->selectActionToBeExecutedMessage(categoryItm->data(ActionSelectorDialogTreeItem::ActionDataRole).toString()));
0652             d->setActionToExecuteSectionVisible(false);
0653             d->raiseWidget(d->kactionPageWidget);
0654             slotKActionItemSelected(d->kactionListView->currentItem()); //to refresh column #3
0655         } else if (categoryItm->data(ActionSelectorDialogTreeItem::ActionCategoryRole).toString() == "currentForm") {
0656             if (!d->currentFormActionsPageWidget) {
0657                 //create lbl+list view with a vlayout
0658                 d->currentFormActionsPageWidget = new QWidget();
0659                 d->currentFormActionsPageWidget->setSizePolicy(
0660                     QSizePolicy::Minimum, QSizePolicy::Minimum);
0661                 QVBoxLayout *vlyr = new QVBoxLayout(d->currentFormActionsPageWidget);
0662                 vlyr->setSpacing(KexiUtils::spacingHint());
0663                 d->currentFormActionsListView = new CurrentFormActionsListView(
0664                     d->currentFormActionsPageWidget);
0665                 d->currentFormActionsListView->init();
0666                 d->currentFormActionsPageLabel = createSelectActionLabel(
0667                             d->currentFormActionsPageWidget, d->currentFormActionsListView);
0668                 vlyr->addWidget(d->currentFormActionsPageLabel);
0669                 vlyr->addWidget(d->currentFormActionsListView);
0670                 d->secondAnd3rdColumnStack->addWidget(d->currentFormActionsPageWidget);
0671                 KexiUtils::setMargins(vlyr, 0);
0672                 connect(d->currentFormActionsListView, SIGNAL(itemActivated(QTreeWidgetItem*,int)),
0673                         this, SLOT(slotCurrentFormActionItemExecuted(QTreeWidgetItem*)));
0674                 connect(d->currentFormActionsListView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
0675                         this, SLOT(slotCurrentFormActionItemSelected(QTreeWidgetItem*)));
0676             }
0677             d->currentFormActionsPageLabel->setText(
0678                 d->selectActionToBeExecutedMessage(categoryItm->data(ActionSelectorDialogTreeItem::ActionDataRole).toString()));
0679             d->setActionToExecuteSectionVisible(false);
0680             d->raiseWidget(d->currentFormActionsPageWidget);
0681             slotCurrentFormActionItemSelected(d->currentFormActionsListView->currentItem()); //to refresh column #3
0682         } else if (categoryItm->data(ActionSelectorDialogTreeItem::ActionCategoryRole).toString() == "noaction") {
0683             d->raiseWidget(d->emptyWidget);
0684             d->objectsListView->clearSelection();
0685             //hide column #3
0686             d->setActionToExecuteSectionVisible(false);
0687         } else if (categoryItm->data(ActionSelectorDialogTreeItem::ActionCategoryRole).toString() == "navObject") {
0688             QString pluginId = categoryItm->data(ActionSelectorDialogTreeItem::ActionPluginIdRole).toString();
0689             d->selectActionToBeExecutedLabel->setText(d->selectActionToBeExecutedMessage(pluginId));
0690             if (d->objectsListView->itemsPluginId() != pluginId) {
0691                 QString errorString;
0692                 d->objectsListView->setProject(KexiMainWindowIface::global()->project(), pluginId, &errorString, false);
0693                 d->actionToExecuteListView->showActionsForPluginId(pluginId);
0694                 d->setActionToExecuteSectionVisible(false);
0695             }
0696             if (d->secondAnd3rdColumnStack->currentWidget() != d->secondAnd3rdColumnMainWidget) {
0697                 d->raiseWidget(d->secondAnd3rdColumnMainWidget);
0698                 d->objectsListView->clearSelection();
0699                 d->setActionToExecuteSectionVisible(false);
0700             } else {
0701                 d->raiseWidget(d->secondAnd3rdColumnMainWidget);
0702             }
0703             d->selectActionToBeExecutedLabel->setBuddy(d->secondAnd3rdColumnMainWidget);
0704         }
0705 
0706         d->actionCategoriesListView->update();
0707         updateOKButtonStatus();
0708         return;
0709     }
0710     d->actionCategoriesListView->update();
0711     d->actionToExecuteListView->update();
0712     updateOKButtonStatus();
0713 }
0714 
0715 KexiFormEventAction::ActionData KexiActionSelectionDialog::currentAction() const
0716 {
0717     KexiFormEventAction::ActionData data;
0718     ActionSelectorDialogTreeItem *categoryItm = dynamic_cast<ActionSelectorDialogTreeItem*>(d->actionCategoriesListView->currentItem());
0719 
0720     if (categoryItm) {
0721         const QString actionCategory = categoryItm->data(ActionSelectorDialogTreeItem::ActionCategoryRole).toString();
0722 
0723         if (actionCategory == "kaction") {
0724             const ActionSelectorDialogTreeItem* actionToExecute = dynamic_cast<ActionSelectorDialogTreeItem*>(
0725                                                     d->kactionListView->currentItem());
0726             if (actionToExecute) {
0727                 data.string = QString("kaction:")
0728                     + actionToExecute->data(ActionSelectorDialogTreeItem::ActionDataRole).toString();
0729                 return data;
0730             }
0731         } else if (actionCategory == "currentForm") {
0732             const ActionSelectorDialogTreeItem *actionToExecute = dynamic_cast<ActionSelectorDialogTreeItem*>(
0733                                                     d->currentFormActionsListView->currentItem());
0734             if (actionToExecute) {
0735                 data.string = QString("currentForm:")
0736                     + actionToExecute->data(ActionSelectorDialogTreeItem::ActionDataRole).toString();
0737                 return data;
0738             }
0739         } else if (actionCategory == "noaction") {
0740           return data;
0741         } else if (actionCategory == "navObject") {
0742             const ActionSelectorDialogTreeItem *actionToExecute = dynamic_cast<ActionSelectorDialogTreeItem*>(
0743                                                 d->actionToExecuteListView->currentItem());
0744             if (d->objectsListView && actionToExecute && !actionToExecute->data(ActionSelectorDialogTreeItem::ActionDataRole).toString().isEmpty()) {
0745                 KexiPart::Item* partItem = d->objectsListView->selectedPartItem();
0746                 KexiPart::Info* partInfo = partItem ? Kexi::partManager().infoForPluginId(partItem->pluginId()) : 0;
0747                 if (partInfo) {
0748                     // opening or executing: table:name, query:name, form:name, macro:name, script:name, etc.
0749                     data.string = QString("%1:%2").arg(partInfo->typeName()).arg(partItem->name());
0750                     data.option = actionToExecute->data(ActionSelectorDialogTreeItem::ActionDataRole).toString();
0751                     return data;
0752                 }
0753             }
0754         } else {
0755             qWarning() << "No current category item";
0756         }
0757     }
0758 
0759     return data; // No Action
0760 }
0761 
0762 void KexiActionSelectionDialog::updateOKButtonStatus()
0763 {
0764     ActionSelectorDialogTreeItem *itm = dynamic_cast<ActionSelectorDialogTreeItem*>(d->actionCategoriesListView->currentItem());
0765 
0766     //qDebug() << "Current Action:" << currentAction().string << ":" << currentAction().option;
0767     QPushButton *btn = d->buttonBox->button(QDialogButtonBox::Ok);
0768     btn->setEnabled((itm && itm->data(ActionSelectorDialogTreeItem::ActionCategoryRole).toString() == "noaction") || !currentAction().isEmpty());
0769 }
0770 
0771 #include "kexiactionselectiondialog.moc"