diff --git a/src/formeditor/kexiactionselectiondialog.cpp b/src/formeditor/kexiactionselectiondialog.cpp index d46f0ead9..df51b37f0 100644 --- a/src/formeditor/kexiactionselectiondialog.cpp +++ b/src/formeditor/kexiactionselectiondialog.cpp @@ -1,775 +1,775 @@ /* This file is part of the KDE project Copyright (C) 2005-2006 Jarosław Staniek Copyright (C) 2012 Adam Pigg This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library 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 "kexiactionselectiondialog.h" #include "kexiactionselectiondialog_p.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class ActionSelectorDialogTreeItem : public QTreeWidgetItem { public: enum ActionRole{ ActionCategoryRole = Qt::UserRole + 1, ActionDataRole, ActionPluginIdRole }; ActionSelectorDialogTreeItem(QString label, QTreeWidget *parent) : QTreeWidgetItem(parent) { setText(0, label); } ActionSelectorDialogTreeItem(QString label, QTreeWidgetItem *parent) : QTreeWidgetItem(parent) { setText(0, label); } using QTreeWidgetItem::data; QVariant data(ActionRole role) const { return QTreeWidgetItem::data(0, role); }; using QTreeWidgetItem::setData; void setData(ActionRole role, QVariant value) { QTreeWidgetItem::setData(0, role, value); } QIcon icon() const { return QTreeWidgetItem::icon(0); } void setIcon(const QIcon& icon) { QTreeWidgetItem::setIcon(0, icon); } }; //--------------------------------------- ActionsListViewBase::ActionsListViewBase(QWidget* parent) : QTreeWidget(parent) { setColumnCount(1); setHeaderHidden(true); setRootIsDecorated(false); } ActionsListViewBase::~ActionsListViewBase() { } QTreeWidgetItem *ActionsListViewBase::itemForAction(const QString& actionName, QTreeWidgetItem* parent) { Q_UNUSED(parent); QTreeWidgetItemIterator it(this); while (*it) { ActionSelectorDialogTreeItem* itm = dynamic_cast(*it); if (itm && itm->data(ActionSelectorDialogTreeItem::ActionDataRole).toString() == actionName) return itm; ++it; } return 0; } void ActionsListViewBase::selectAction(const QString& actionName) { //qDebug() << "Selecting action:" << actionName; QTreeWidgetItem *itm = itemForAction(actionName); if (itm) { setCurrentItem(itm); itm->setSelected(true); } } //--------------------------------------- KActionsListViewBase::KActionsListViewBase(QWidget* parent) : ActionsListViewBase(parent) { } KActionsListViewBase::~KActionsListViewBase() {} void KActionsListViewBase::init() { const QPixmap noIcon(KexiUtils::emptyIcon(KIconLoader::Small)); QList sharedActions(KexiMainWindowIface::global()->allActions()); const Kexi::ActionCategories *acat = Kexi::actionCategories(); foreach(QAction *action, sharedActions) { // qDebug() << (*it)->name() << (*it)->text(); //! @todo group actions //! @todo: store QAction * here? const int actionCategories = acat->actionCategories(action->objectName().toLatin1()); if (actionCategories == -1) { qWarning() << "no category declared for action \"" << action->objectName() << "\"! Fix this!"; continue; } if (!isActionVisible(action->objectName().toLatin1(), actionCategories)) continue; QString actionName; if (!action->toolTip().isEmpty()) { actionName = action->toolTip().remove("").remove(""); } else { actionName = action->text().remove('&'); } ActionSelectorDialogTreeItem *pitem = new ActionSelectorDialogTreeItem( actionName, this); pitem->setData(ActionSelectorDialogTreeItem::ActionCategoryRole, "kaction"); pitem->setData(ActionSelectorDialogTreeItem::ActionDataRole, action->objectName()); pitem->setIcon(action->icon()); if (pitem->icon().isNull()) pitem->setIcon(noIcon); } setSortingEnabled(true); } //--------------------------------------- //! @internal Used to display KActions (in column 2) class KActionsListView : public KActionsListViewBase { Q_OBJECT public: explicit KActionsListView(QWidget* parent) : KActionsListViewBase(parent) { } virtual ~KActionsListView() {} virtual bool isActionVisible(const char* actionName, int actionCategories) const { Q_UNUSED(actionName); return actionCategories & Kexi::GlobalActionCategory; } }; //! @internal Used to display KActions (in column 2) class CurrentFormActionsListView : public KActionsListViewBase { Q_OBJECT public: explicit CurrentFormActionsListView(QWidget* parent) : KActionsListViewBase(parent) { } virtual ~CurrentFormActionsListView() {} virtual bool isActionVisible(const char* actionName, int actionCategories) const { return actionCategories & Kexi::WindowActionCategory && Kexi::actionCategories()->actionSupportsObjectType(actionName, KexiPart::FormObjectType); } }; //! @internal a list view displaying action categories user can select from (column 1) class ActionCategoriesListView : public ActionsListViewBase { Q_OBJECT public: explicit ActionCategoriesListView(QWidget* parent) : ActionsListViewBase(parent) { ActionSelectorDialogTreeItem *itm = new ActionSelectorDialogTreeItem(xi18n("No action"), this ); itm->setData(ActionSelectorDialogTreeItem::ActionCategoryRole, "noaction"); itm->setData(ActionSelectorDialogTreeItem::ActionDataRole, "noaction"); const QPixmap noIcon(KexiUtils::emptyIcon(KIconLoader::Small)); itm->setIcon(noIcon); itm = new ActionSelectorDialogTreeItem(xi18n("Application actions"), this ); itm->setData(ActionSelectorDialogTreeItem::ActionCategoryRole, "kaction"); itm->setData(ActionSelectorDialogTreeItem::ActionDataRole, "kaction"); itm->setIcon(koIcon("kexi")); KexiPart::PartInfoList *pl = Kexi::partManager().infoList(); if (pl) { foreach(KexiPart::Info *info, *pl) { KexiPart::Part *part = Kexi::partManager().part(info); if (!info->isVisibleInNavigator() || !part) continue; itm = new ActionSelectorDialogTreeItem(part->info()->name(), this ); itm->setData(ActionSelectorDialogTreeItem::ActionCategoryRole, "navObject"); itm->setData(ActionSelectorDialogTreeItem::ActionDataRole, info->typeName()); itm->setData(ActionSelectorDialogTreeItem::ActionPluginIdRole, info->pluginId()); itm->setIcon(QIcon::fromTheme(part->info()->iconName())); } } QTreeWidgetItem *fitm = itemForAction("form"); if (fitm) { itm = new ActionSelectorDialogTreeItem(xi18nc("Current form's actions", "Current"), fitm); } else { itm = new ActionSelectorDialogTreeItem(xi18nc("Current form's actions", "Current"), this); } itm->setData(ActionSelectorDialogTreeItem::ActionCategoryRole, "currentForm"); itm->setData(ActionSelectorDialogTreeItem::ActionDataRole, "currentForm"); itm->setIcon(KexiIcon("form")); expandAll(); setSortingEnabled(false); } ~ActionCategoriesListView() { } }; //! @internal Used to display list of actions available to executing (column 3) class ActionToExecuteListView : public ActionsListViewBase { Q_OBJECT public: explicit ActionToExecuteListView(QWidget* parent) : ActionsListViewBase(parent) { } ~ActionToExecuteListView() { } //! Updates actions void showActionsForPluginId(const QString& pluginId) { if (m_currentPluginId == pluginId) return; m_currentPluginId = pluginId; clear(); KexiPart::Part *part = Kexi::partManager().partForPluginId(m_currentPluginId); if (!part) return; Kexi::ViewModes supportedViewModes = part->info()->supportedViewModes(); ActionSelectorDialogTreeItem *itm; const QPixmap noIcon(KexiUtils::emptyIcon(KIconLoader::Small)); if (supportedViewModes & Kexi::DataViewMode) { itm = new ActionSelectorDialogTreeItem(xi18n("Open in Data View"), this); itm->setData(ActionSelectorDialogTreeItem::ActionDataRole , "open"); - itm->setIcon(koIcon("document-open")); + itm->setIcon(KexiIcon("mode-selector-edit")); } if (part->info()->isExecuteSupported()) { itm = new ActionSelectorDialogTreeItem(xi18n("Execute"), this); itm->setData(ActionSelectorDialogTreeItem::ActionDataRole , "execute"); itm->setIcon(koIcon("media-playback-start")); } #ifdef KEXI_QUICK_PRINTING_SUPPORT if (part->info()->isPrintingSupported()) { ActionSelectorDialogListItem *printItem = new ActionSelectorDialogListItem( "print", this, futureI18n("Print")); printItem->setPixmap(0, koIcon("document-print")); QAction *a = KStandardAction::printPreview(0, 0, 0); item = new ActionSelectorDialogListItem("printPreview", printItem, a->text().remove('&').remove("...")); item->setPixmap(0, a->icon().pixmap(16)); delete a; item = new ActionSelectorDialogListItem( "pageSetup", printItem, futureI18n("Show Page Setup")); item->setPixmap(0, noIcon); setOpen(printItem, true); printItem->setExpandable(false); } #endif if (part->info()->isDataExportSupported()) { itm = new ActionSelectorDialogTreeItem( xi18nc("Note: use multiple rows if needed", "Export to File\nAs Data Table"), this); itm->setData(ActionSelectorDialogTreeItem::ActionDataRole , "exportToCSV"); itm->setIcon(KexiIcon("table")); QTreeWidgetItem *eitem = itm; itm = new ActionSelectorDialogTreeItem(xi18nc("Note: use multiple rows if needed", "Copy to Clipboard\nAs Data Table"), eitem); itm->setData(ActionSelectorDialogTreeItem::ActionDataRole , "copyToClipboardAsCSV"); itm->setIcon(KexiIcon("table")); } itm = new ActionSelectorDialogTreeItem(xi18n("Create New Object (%1)", part->info()->name().toLower()), this); itm->setData(ActionSelectorDialogTreeItem::ActionDataRole , "new"); itm->setIcon(koIcon("document-new")); if (supportedViewModes & Kexi::DesignViewMode) { itm = new ActionSelectorDialogTreeItem(xi18n("Open in Design View"), this); itm->setData(ActionSelectorDialogTreeItem::ActionDataRole , "design"); - itm->setIcon(koIcon("document-properties")); + itm->setIcon(KexiIcon("mode-selector-design")); } if (supportedViewModes & Kexi::TextViewMode) { QString actionText; QString iconName; KexiPart::getTextViewAction(pluginId, &actionText, &iconName); itm = new ActionSelectorDialogTreeItem(actionText, this); itm->setData(ActionSelectorDialogTreeItem::ActionDataRole , "editText"); itm->setIcon(iconName.isEmpty() ? noIcon : QIcon::fromTheme(iconName)); } itm = new ActionSelectorDialogTreeItem( xi18n("Close View"), this); itm->setData(ActionSelectorDialogTreeItem::ActionDataRole , "close"); itm->setIcon(koIcon("window-close")); expandAll(); setSortingEnabled(true); } QString m_currentPluginId; }; //------------------------------------- //! @internal class Q_DECL_HIDDEN KexiActionSelectionDialog::Private { public: Private() : kactionPageWidget(0), kactionListView(0), objectsListView(0) , currentFormActionsPageWidget(0) , currentFormActionsListView(0) , secondAnd3rdColumnMainWidget(0) , hideActionToExecuteListView(false) { } void raiseWidget(QWidget *w) { secondAnd3rdColumnStack->setCurrentWidget(w); } QString selectActionToBeExecutedMessage(const QString& actionType) const { if (actionType == "noaction") return QString(); if (actionType == "kaction" || actionType == "currentForm") return xi18n("&Select action to be executed after clicking %1 button:", actionWidgetName); // hardcoded, but it's not that bad if (actionType == "org.kexi-project.macro") return xi18n("&Select macro to be executed after clicking %1 button:", actionWidgetName); if (actionType == "org.kexi-project.script") return xi18n("&Select script to be executed after clicking %1 button:", actionWidgetName); //default: org.kexi-project.table/query/form/report... return xi18n("&Select object to be opened after clicking %1 button:", actionWidgetName); } // changes 3rd column visibility void setActionToExecuteSectionVisible(bool visible) { actionToExecuteListView->setVisible(visible); actionToExecuteLbl->setVisible(visible); } QString actionWidgetName; ActionCategoriesListView* actionCategoriesListView; //!< for column #1 QWidget *kactionPageWidget; KActionsListView* kactionListView; //!< for column #2 KexiProjectNavigator* objectsListView; //!< for column #2 QWidget *currentFormActionsPageWidget; //!< for column #2 CurrentFormActionsListView* currentFormActionsListView; //!< for column #2 QWidget *emptyWidget; QLabel *selectActionToBeExecutedLabel; QLabel *kactionPageLabel; QLabel *currentFormActionsPageLabel; ActionToExecuteListView* actionToExecuteListView; QLabel *actionToExecuteLbl; QWidget *secondAnd3rdColumnMainWidget; QGridLayout *glyr; QGridLayout *secondAnd3rdColumnGrLyr; QStackedWidget *secondAnd3rdColumnStack; //, *secondColumnStack; bool hideActionToExecuteListView; QDialogButtonBox *buttonBox; }; //------------------------------------- static QLabel *createSelectActionLabel(QWidget *parent, QWidget *buddy) { QLabel *lbl = new QLabel(parent); lbl->setBuddy(buddy); lbl->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); lbl->setAlignment(Qt::AlignTop | Qt::AlignLeft); lbl->setWordWrap(true); lbl->setMinimumHeight(lbl->fontMetrics().height()*2); return lbl; } //------------------------------------- KexiActionSelectionDialog::KexiActionSelectionDialog( QWidget *parent, const KexiFormEventAction::ActionData& action, const QString& actionWidgetName) : QDialog(parent) , d(new Private()) { setModal(true); setObjectName("actionSelectorDialog"); setWindowTitle(xi18nc("@title:window", "Assigning Action to Button")); // layout QVBoxLayout *mainLayout = new QVBoxLayout; setLayout(mainLayout); QWidget *mainWidget = new QWidget(this); mainWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); mainLayout->addWidget(mainWidget); /* lbl 1 +------------+ +-------------------------------+ | | | [a] | | 1st column | | +----------- + +------------+ | | | | | 2nd column | | 3rd column | | | | | + + + + | | | | +------------+ +------------+ | +------------+ +-------------------------------+ \______________________________________________/ glyr [a]- QStackedWidget *secondAnd3rdColumnStack, - for displaying KActions, the stack contains d->kactionPageWidget QWidget - for displaying objects, the stack contains secondAnd3rdColumnMainWidget QWidget and QGridLayout *secondAnd3rdColumnGrLyr - kactionPageWidget contains only a QVBoxLayout and label+kactionListView */ d->glyr = new QGridLayout(mainWidget); // 2x2 KexiUtils::setStandardMarginsAndSpacing(d->glyr); d->glyr->setRowStretch(1, 1); // 1st column: action types d->actionCategoriesListView = new ActionCategoriesListView(mainWidget); d->actionCategoriesListView->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); d->glyr->addWidget(d->actionCategoriesListView, 1, 0); connect(d->actionCategoriesListView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(slotActionCategorySelected(QTreeWidgetItem*))); QLabel *lbl = new QLabel(xi18n("Action category:"), mainWidget); lbl->setBuddy(d->actionCategoriesListView); lbl->setMinimumHeight(lbl->fontMetrics().height()*2); lbl->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); lbl->setAlignment(Qt::AlignTop | Qt::AlignLeft); lbl->setWordWrap(true); d->glyr->addWidget(lbl, 0, 0, Qt::AlignTop | Qt::AlignLeft); // widget stack for 2nd and 3rd column d->secondAnd3rdColumnStack = new QStackedWidget(mainWidget); d->secondAnd3rdColumnStack->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); d->glyr->addWidget(d->secondAnd3rdColumnStack, 0, 1, 2, 1); d->secondAnd3rdColumnMainWidget = new QWidget(d->secondAnd3rdColumnStack); d->secondAnd3rdColumnMainWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); d->secondAnd3rdColumnGrLyr = new QGridLayout(d->secondAnd3rdColumnMainWidget); //! @todo KEXI3 QDialog::resizeLayout(d->secondAnd3rdColumnGrLyr, 0, KexiUtils::spacingHint()); d->secondAnd3rdColumnGrLyr->setRowStretch(1, 2); d->secondAnd3rdColumnStack->addWidget(d->secondAnd3rdColumnMainWidget); // 2nd column: list of actions/objects d->objectsListView = new KexiProjectNavigator(d->secondAnd3rdColumnMainWidget, KexiProjectNavigator::Borders); d->secondAnd3rdColumnGrLyr->addWidget(d->objectsListView, 1, 0); d->secondAnd3rdColumnGrLyr->setColumnStretch(0,1); d->secondAnd3rdColumnGrLyr->setColumnStretch(1,1); connect(d->objectsListView, SIGNAL(selectionChanged(KexiPart::Item*)), this, SLOT(slotItemForOpeningOrExecutingSelected(KexiPart::Item*))); d->selectActionToBeExecutedLabel = createSelectActionLabel(d->secondAnd3rdColumnMainWidget, 0); d->secondAnd3rdColumnGrLyr->addWidget( d->selectActionToBeExecutedLabel, 0, 0, Qt::AlignTop | Qt::AlignLeft); d->emptyWidget = new QWidget(d->secondAnd3rdColumnStack); d->secondAnd3rdColumnStack->addWidget(d->emptyWidget); // 3rd column: actions to execute d->actionToExecuteListView = new ActionToExecuteListView(d->secondAnd3rdColumnMainWidget); d->actionToExecuteListView->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); connect(d->actionToExecuteListView, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(slotActionToExecuteItemExecuted(QTreeWidgetItem*))); connect(d->actionToExecuteListView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(slotActionToExecuteItemSelected(QTreeWidgetItem*))); d->secondAnd3rdColumnGrLyr->addWidget(d->actionToExecuteListView, 1, 1); d->actionToExecuteLbl = createSelectActionLabel(d->secondAnd3rdColumnMainWidget, d->actionToExecuteListView); d->actionToExecuteLbl->setText(xi18n("Action to execute:")); d->secondAnd3rdColumnGrLyr->addWidget(d->actionToExecuteLbl, 0, 1, Qt::AlignTop | Qt::AlignLeft); // buttons d->buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel); QPushButton *okButton = d->buttonBox->button(QDialogButtonBox::Ok); okButton->setDefault(true); okButton->setShortcut(Qt::CTRL | Qt::Key_Return); connect(d->buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(d->buttonBox, SIGNAL(rejected()), this, SLOT(reject())); d->actionWidgetName = actionWidgetName; d->buttonBox->button(QDialogButtonBox::Ok)->setText(xi18nc("Assign action", "&Assign")); //buttonBox->button(QDialogButtonBox::Ok)->setIcon(koIconName("dialog-ok")); d->buttonBox->button(QDialogButtonBox::Ok)->setToolTip(xi18n("Assign action")); mainLayout->addWidget(d->buttonBox); // temporary show all sections to avoid resizing the dialog in the future d->actionCategoriesListView->selectAction("table"); d->setActionToExecuteSectionVisible(true); adjustSize(); resize(qMax(700, width()), qMax(450, height())); bool ok; QString actionType, actionArg; KexiPart::Info* partInfo = action.decodeString(actionType, actionArg, &ok); if (ok) { d->actionCategoriesListView->selectAction(actionType); if (actionType == "kaction") { d->kactionListView->selectAction(actionArg); d->kactionListView->setFocus(); } else if (actionType == "currentForm") { d->currentFormActionsListView->selectAction(actionArg); d->currentFormActionsListView->setFocus(); } else if (partInfo && Kexi::partManager().part(partInfo)) // We use the Part Manager // to determine whether the Kexi-plugin is installed and whether we like to show // it in our list of actions. { KexiPart::Item *item = KexiMainWindowIface::global()->project()->item( partInfo, actionArg); if (d->objectsListView && item) { d->objectsListView->selectItem(*item); slotItemForOpeningOrExecutingSelected(item); QString actionOption(action.option); if (actionOption.isEmpty()) { actionOption = "open"; // for backward compatibility } d->actionToExecuteListView->selectAction(actionOption); d->objectsListView->setFocus(); } } } else {//invalid assignment or 'noaction' d->actionCategoriesListView->selectAction("noaction"); d->actionCategoriesListView->setFocus(); } } KexiActionSelectionDialog::~KexiActionSelectionDialog() { delete d; } void KexiActionSelectionDialog::slotKActionItemExecuted(QTreeWidgetItem*) { accept(); } void KexiActionSelectionDialog::slotKActionItemSelected(QTreeWidgetItem*) { d->setActionToExecuteSectionVisible(false); updateOKButtonStatus(); } void KexiActionSelectionDialog::slotCurrentFormActionItemExecuted(QTreeWidgetItem*) { accept(); } void KexiActionSelectionDialog::slotCurrentFormActionItemSelected(QTreeWidgetItem*) { d->setActionToExecuteSectionVisible(false); updateOKButtonStatus(); } void KexiActionSelectionDialog::slotItemForOpeningOrExecutingSelected(KexiPart::Item* item) { d->setActionToExecuteSectionVisible(item); } void KexiActionSelectionDialog::slotActionToExecuteItemExecuted(QTreeWidgetItem* item) { if (!item) return; ActionSelectorDialogTreeItem *listItem = dynamic_cast(item); if (listItem && listItem->data(ActionSelectorDialogTreeItem::ActionDataRole).isValid()) accept(); } void KexiActionSelectionDialog::slotActionToExecuteItemSelected(QTreeWidgetItem*) { //qDebug(); updateOKButtonStatus(); } void KexiActionSelectionDialog::slotActionCategorySelected(QTreeWidgetItem* item) { ActionSelectorDialogTreeItem *categoryItm = dynamic_cast(item); // simple case: part-less item, e.g. kaction: if (categoryItm) { if (categoryItm->data(ActionSelectorDialogTreeItem::ActionCategoryRole).toString() == "kaction") { if (!d->kactionPageWidget) { //create lbl+list view with a vlayout d->kactionPageWidget = new QWidget(); d->kactionPageWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); QVBoxLayout *vlyr = new QVBoxLayout(d->kactionPageWidget); vlyr->setSpacing(KexiUtils::spacingHint()); d->kactionListView = new KActionsListView(d->kactionPageWidget); d->kactionListView->init(); d->kactionPageLabel = createSelectActionLabel(d->kactionPageWidget, d->kactionListView); vlyr->addWidget(d->kactionPageLabel); vlyr->addWidget(d->kactionListView); KexiUtils::setMargins(vlyr, 0); d->secondAnd3rdColumnStack->addWidget(d->kactionPageWidget); connect(d->kactionListView, SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)), this, SLOT(slotKActionItemExecuted(QTreeWidgetItem*))); connect(d->kactionListView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(slotKActionItemSelected(QTreeWidgetItem*))); } d->kactionPageLabel->setText( d->selectActionToBeExecutedMessage(categoryItm->data(ActionSelectorDialogTreeItem::ActionDataRole).toString())); d->setActionToExecuteSectionVisible(false); d->raiseWidget(d->kactionPageWidget); slotKActionItemSelected(d->kactionListView->currentItem()); //to refresh column #3 } else if (categoryItm->data(ActionSelectorDialogTreeItem::ActionCategoryRole).toString() == "currentForm") { if (!d->currentFormActionsPageWidget) { //create lbl+list view with a vlayout d->currentFormActionsPageWidget = new QWidget(); d->currentFormActionsPageWidget->setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Minimum); QVBoxLayout *vlyr = new QVBoxLayout(d->currentFormActionsPageWidget); vlyr->setSpacing(KexiUtils::spacingHint()); d->currentFormActionsListView = new CurrentFormActionsListView( d->currentFormActionsPageWidget); d->currentFormActionsListView->init(); d->currentFormActionsPageLabel = createSelectActionLabel( d->currentFormActionsPageWidget, d->currentFormActionsListView); vlyr->addWidget(d->currentFormActionsPageLabel); vlyr->addWidget(d->currentFormActionsListView); d->secondAnd3rdColumnStack->addWidget(d->currentFormActionsPageWidget); KexiUtils::setMargins(vlyr, 0); connect(d->currentFormActionsListView, SIGNAL(itemActivated(QTreeWidgetItem*,int)), this, SLOT(slotCurrentFormActionItemExecuted(QTreeWidgetItem*))); connect(d->currentFormActionsListView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), this, SLOT(slotCurrentFormActionItemSelected(QTreeWidgetItem*))); } d->currentFormActionsPageLabel->setText( d->selectActionToBeExecutedMessage(categoryItm->data(ActionSelectorDialogTreeItem::ActionDataRole).toString())); d->setActionToExecuteSectionVisible(false); d->raiseWidget(d->currentFormActionsPageWidget); slotCurrentFormActionItemSelected(d->currentFormActionsListView->currentItem()); //to refresh column #3 } else if (categoryItm->data(ActionSelectorDialogTreeItem::ActionCategoryRole).toString() == "noaction") { d->raiseWidget(d->emptyWidget); d->objectsListView->clearSelection(); //hide column #3 d->setActionToExecuteSectionVisible(false); } else if (categoryItm->data(ActionSelectorDialogTreeItem::ActionCategoryRole).toString() == "navObject") { QString pluginId = categoryItm->data(ActionSelectorDialogTreeItem::ActionPluginIdRole).toString(); d->selectActionToBeExecutedLabel->setText(d->selectActionToBeExecutedMessage(pluginId)); if (d->objectsListView->itemsPluginId() != pluginId) { QString errorString; d->objectsListView->setProject(KexiMainWindowIface::global()->project(), pluginId, &errorString, false); d->actionToExecuteListView->showActionsForPluginId(pluginId); d->setActionToExecuteSectionVisible(false); } if (d->secondAnd3rdColumnStack->currentWidget() != d->secondAnd3rdColumnMainWidget) { d->raiseWidget(d->secondAnd3rdColumnMainWidget); d->objectsListView->clearSelection(); d->setActionToExecuteSectionVisible(false); } else { d->raiseWidget(d->secondAnd3rdColumnMainWidget); } d->selectActionToBeExecutedLabel->setBuddy(d->secondAnd3rdColumnMainWidget); } d->actionCategoriesListView->update(); updateOKButtonStatus(); return; } d->actionCategoriesListView->update(); d->actionToExecuteListView->update(); updateOKButtonStatus(); } KexiFormEventAction::ActionData KexiActionSelectionDialog::currentAction() const { KexiFormEventAction::ActionData data; ActionSelectorDialogTreeItem *categoryItm = dynamic_cast(d->actionCategoriesListView->currentItem()); if (categoryItm) { const QString actionCategory = categoryItm->data(ActionSelectorDialogTreeItem::ActionCategoryRole).toString(); if (actionCategory == "kaction") { const ActionSelectorDialogTreeItem* actionToExecute = dynamic_cast( d->kactionListView->currentItem()); if (actionToExecute) { data.string = QString("kaction:") + actionToExecute->data(ActionSelectorDialogTreeItem::ActionDataRole).toString(); return data; } } else if (actionCategory == "currentForm") { const ActionSelectorDialogTreeItem *actionToExecute = dynamic_cast( d->currentFormActionsListView->currentItem()); if (actionToExecute) { data.string = QString("currentForm:") + actionToExecute->data(ActionSelectorDialogTreeItem::ActionDataRole).toString(); return data; } } else if (actionCategory == "noaction") { return data; } else if (actionCategory == "navObject") { const ActionSelectorDialogTreeItem *actionToExecute = dynamic_cast( d->actionToExecuteListView->currentItem()); if (d->objectsListView && actionToExecute && !actionToExecute->data(ActionSelectorDialogTreeItem::ActionDataRole).toString().isEmpty()) { KexiPart::Item* partItem = d->objectsListView->selectedPartItem(); KexiPart::Info* partInfo = partItem ? Kexi::partManager().infoForPluginId(partItem->pluginId()) : 0; if (partInfo) { // opening or executing: table:name, query:name, form:name, macro:name, script:name, etc. data.string = QString("%1:%2").arg(partInfo->typeName()).arg(partItem->name()); data.option = actionToExecute->data(ActionSelectorDialogTreeItem::ActionDataRole).toString(); return data; } } } else { qWarning() << "No current category item"; } } return data; // No Action } void KexiActionSelectionDialog::updateOKButtonStatus() { ActionSelectorDialogTreeItem *itm = dynamic_cast(d->actionCategoriesListView->currentItem()); //qDebug() << "Current Action:" << currentAction().string << ":" << currentAction().option; QPushButton *btn = d->buttonBox->button(QDialogButtonBox::Ok); btn->setEnabled((itm && itm->data(ActionSelectorDialogTreeItem::ActionCategoryRole).toString() == "noaction") || !currentAction().isEmpty()); } #include "kexiactionselectiondialog.moc" diff --git a/src/plugins/scripting/kexiscripting/kexiscriptdesignview.cpp b/src/plugins/scripting/kexiscripting/kexiscriptdesignview.cpp index 2e64a29af..92b5e18ef 100644 --- a/src/plugins/scripting/kexiscripting/kexiscriptdesignview.cpp +++ b/src/plugins/scripting/kexiscripting/kexiscriptdesignview.cpp @@ -1,504 +1,504 @@ /* This file is part of the KDE project Copyright (C) 2003 Lucijan Busch Copyright (C) 2004-2012 Jarosław Staniek Copyright (C) 2005 Cedric Pasteur Copyright (C) 2005 Sebastian Sauer This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kexiscriptdesignview.h" #include "kexiscripteditor.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include /// @internal class KexiScriptDesignViewPrivate { public: QSplitter* splitter; /** * The \a Kross::Action instance which provides * us access to the scripting framework Kross. */ Kross::Action* scriptaction; /// The \a KexiScriptEditor to edit the scripting code. KexiScriptEditor* editor; /// The \a KPropertySet used in the propertyeditor. KPropertySet* properties; /// Boolean flag to avoid infinite recursion. bool updatesProperties; /// Used to display statusmessages. QTextBrowser* statusbrowser; /** The type of script * executable = regular script that can be executed by the user * module = a script which doesn't contain a 'main', only * functions that can be used by other scripts * object = a script which contains code to be loaded into another object such as a report or form */ QString scriptType; }; KexiScriptDesignView::KexiScriptDesignView( QWidget *parent, Kross::Action* scriptaction) : KexiView(parent) , d(new KexiScriptDesignViewPrivate()) { setObjectName("KexiScriptDesignView"); d->scriptaction = scriptaction; d->updatesProperties = false; d->splitter = new QSplitter(this); d->splitter->setOrientation(Qt::Vertical); d->editor = new KexiScriptEditor(d->splitter); d->splitter->addWidget(d->editor); d->editor->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); d->splitter->setStretchFactor(d->splitter->indexOf(d->editor), 3); d->splitter->setFocusProxy(d->editor); //addChildView(d->editor); setViewWidget(d->splitter); d->statusbrowser = new QTextBrowser(d->splitter); d->splitter->addWidget(d->statusbrowser); d->splitter->setStretchFactor(d->splitter->indexOf(d->statusbrowser), 1); d->statusbrowser->setObjectName("ScriptStatusBrowser"); d->statusbrowser->setReadOnly(true); //d->browser->setWordWrap(QTextEdit::WidgetWidth); d->statusbrowser->installEventFilter(this); /* plugSharedAction( "data_execute", this, SLOT(execute()) ); if(KexiEditor::isAdvancedEditor()) // the configeditor is only in advanced mode avaiable. plugSharedAction( "script_config_editor", d->editor, SLOT(slotConfigureEditor()) ); */ // setup local actions QList viewActions; { QAction *a = new QAction(koIcon("system-run"), xi18n("Execute"), this); a->setObjectName("script_execute"); a->setToolTip(xi18n("Execute the scripting code")); a->setWhatsThis(xi18n("Executes the scripting code.")); connect(a, SIGNAL(triggered()), this, SLOT(execute())); viewActions << a; } QAction *a = new QAction(this); a->setSeparator(true); viewActions << a; - KActionMenu *menu = new KActionMenu(koIcon("document-properties"), xi18n("Edit"), this); + KActionMenu *menu = new KActionMenu(koIcon("document-edit"), xi18n("Edit"), this); menu->setObjectName("script_edit_menu"); menu->setToolTip(xi18n("Edit actions")); menu->setWhatsThis(xi18n("Provides Edit menu.")); menu->setDelayed(false); foreach(QAction *a, d->editor->defaultContextMenu()->actions()) { menu->addAction(a); } if (KexiEditor::isAdvancedEditor()) { // the configeditor is only in advanced mode available. menu->addSeparator(); QAction *a = new QAction(koIcon("configure"), xi18n("Configure Editor..."), this); a->setObjectName("script_config_editor"); a->setToolTip(xi18n("Configure the scripting editor")); a->setWhatsThis(xi18n("Configures the scripting editor.")); connect(a, SIGNAL(triggered()), d->editor, SLOT(slotConfigureEditor())); menu->addAction(a); } viewActions << menu; setViewActions(viewActions); // setup main menu actions QList mainMenuActions; a = new QAction(koIcon("document-import"), xi18n("&Import..."), this); a->setObjectName("script_import"); a->setToolTip(xi18n("Import script")); a->setWhatsThis(xi18n("Imports script from a file.")); connect(a, SIGNAL(triggered(bool)), this, SLOT(slotImport())); mainMenuActions << a; a = new QAction(this); a->setSeparator(true); mainMenuActions << a; //a = new QAction(this); //a->setObjectName("project_saveas"); // placeholder for real? a = sharedAction("project_saveas"); mainMenuActions << a; a = new QAction(koIcon("document-export"), xi18n("&Export..."), this); a->setObjectName("script_export"); a->setToolTip(xi18n("Export script")); a->setWhatsThis(xi18n("Exports script to a file.")); connect(a, SIGNAL(triggered(bool)), this, SLOT(slotExport())); mainMenuActions << a; setMainMenuActions(mainMenuActions); loadData(); d->properties = new KPropertySet(this); connect(d->properties, SIGNAL(propertyChanged(KPropertySet&,KProperty&)), this, SLOT(slotPropertyChanged(KPropertySet&,KProperty&))); // To schedule the initialize fixes a crasher in Kate. QTimer::singleShot(50, this, SLOT(initialize())); } KexiScriptDesignView::~KexiScriptDesignView() { delete d->properties; delete d; } Kross::Action* KexiScriptDesignView::scriptAction() const { return d->scriptaction; } void KexiScriptDesignView::initialize() { setDirty(false); updateProperties(); d->editor->initialize(d->scriptaction); connect(d->editor, SIGNAL(textChanged()), this, SLOT(setDirty())); d->splitter->setSizes( QList() << height() * 2 / 3 << height() * 1 / 3 ); } void KexiScriptDesignView::slotImport() { QStringList filters; foreach(const QString &interpreter, Kross::Manager::self().interpreters()) { filters << Kross::Manager::self().interpreterInfo(interpreter)->mimeTypes(); } //! @todo KEXI3 add equivalent of kfiledialog:/// //! @todo KEXI3 multiple filters // for now support jsut one filter QString filterString; if (filters.count() == 1) { const QMimeDatabase db; const QString filterString = db.mimeTypeForName(filters.first()).filterString(); } //QUrl("kfiledialog:///kexiscriptingdesigner"), const QUrl result = QFileDialog::getOpenFileUrl(this, xi18nc("@title:window", "Import Script"), QUrl(), filterString); if (!result.isValid()) { return; } //! @todo support remote files? QFile f(result.toLocalFile()); if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) { KMessageBox::sorry(this, xi18nc("@info", "Could not read %1.", file)); return; } d->editor->setText(f.readAll()); f.close(); } void KexiScriptDesignView::slotExport() { QStringList filters; foreach(const QString &interpreter, Kross::Manager::self().interpreters()) { filters << Kross::Manager::self().interpreterInfo(interpreter)->mimeTypes(); } const QString file = KFileDialog::getSaveFileName( QUrl("kfiledialog:///kexiscriptingdesigner"), filters.join(" "), this, xi18nc("@title:window", "Export Script")); if (file.isEmpty()) return; QFile f(file); if (! f.open(QIODevice::WriteOnly | QIODevice::Text)) { KMessageBox::sorry(this, xi18nc("@info", "Could not write %1.", file)); return; } f.write(d->editor->text().toUtf8()); f.close(); } void KexiScriptDesignView::updateProperties() { if (d->updatesProperties) return; d->updatesProperties = true; Kross::Manager* manager = &Kross::Manager::self(); QString interpretername = d->scriptaction->interpreter(); Kross::InterpreterInfo* info = interpretername.isEmpty() ? 0 : manager->interpreterInfo(interpretername); if (!info) { // if interpreter isn't defined or invalid, try to fallback. foreach (const QString& interpretername, QStringList() << "python" << "ruby" << "qtscript" << "javascript" << "java") { info = manager->interpreterInfo(interpretername); if (info) { d->scriptaction->setInterpreter(interpretername); break; } } } if (!info) { d->updatesProperties = false; return; } d->properties->clear(); QStringList types; types << "executable" << "module" << "object"; KPropertyListData* typelist = new KPropertyListData(types, types); KProperty* t = new KProperty( "type", // name typelist, // ListData (d->scriptType.isEmpty() ? "executable" : d->scriptType), // value xi18n("Script Type"), // caption xi18n("The type of script"), // description KProperty::List // type ); d->properties->addProperty(t); QStringList interpreters = manager->interpreters(); //qDebug() << interpreters; KPropertyListData* proplist = new KPropertyListData(interpreters, interpreters); KProperty* prop = new KProperty( "language", // name proplist, // ListData d->scriptaction->interpreter(), // value xi18n("Interpreter"), // caption xi18n("The used scripting interpreter."), // description KProperty::List // type ); d->properties->addProperty(prop); Kross::InterpreterInfo::Option::Map options = info->options(); Kross::InterpreterInfo::Option::Map::ConstIterator it, end(options.constEnd()); for (it = options.constBegin(); it != end; ++it) { Kross::InterpreterInfo::Option* option = it.value(); KProperty* prop = new KProperty( it.key().toLatin1(), // name d->scriptaction->option(it.key(), option->value), // value it.key(), // caption option->comment, // description KProperty::Auto // type ); d->properties->addProperty(prop); } //propertySetSwitched(); propertySetReloaded(true); d->updatesProperties = false; } KPropertySet* KexiScriptDesignView::propertySet() { return d->properties; } void KexiScriptDesignView::slotPropertyChanged(KPropertySet& /*set*/, KProperty& property) { qDebug(); if (property.isNull()) return; if (property.name() == "language") { QString language = property.value().toString(); //qDebug() << "language:" << language; d->scriptaction->setInterpreter(language); // We assume Kross and the HighlightingInterface are using same // names for the support languages... d->editor->setHighlightMode(language); updateProperties(); } else if (property.name() == "type") { d->scriptType = property.value().toString(); } else { bool ok = d->scriptaction->setOption(property.name(), property.value()); if (! ok) { qWarning() << "unknown property:" << property.name(); return; } } setDirty(true); } void KexiScriptDesignView::execute() { d->statusbrowser->clear(); QTime time; time.start(); d->statusbrowser->append(xi18nc("@info", "Execution of the script %1 started.", d->scriptaction->name())); d->scriptaction->trigger(); if (d->scriptaction->hadError()) { QString errormessage = d->scriptaction->errorMessage(); d->statusbrowser->append(QString("%2
").arg(errormessage.toHtmlEscaped())); QString tracedetails = d->scriptaction->errorTrace(); d->statusbrowser->append(tracedetails.toHtmlEscaped()); long lineno = d->scriptaction->errorLineNo(); if (lineno >= 0) d->editor->setLineNo(lineno); } else { // xgettext: no-c-format d->statusbrowser->append(xi18n("Successfully executed. Time elapsed: %1ms", time.elapsed())); } } bool KexiScriptDesignView::loadData() { QString data; if (!loadDataBlock(&data)) { //qDebug() << "no DataBlock"; return false; } QString errMsg; int errLine; int errCol; QDomDocument domdoc; bool parsed = domdoc.setContent(data, false, &errMsg, &errLine, &errCol); if (! parsed) { //qDebug() << "XML parsing error line:" << errLine << "col:" << errCol << "message:" << errMsg; return false; } QDomElement scriptelem = domdoc.namedItem("script").toElement(); if (scriptelem.isNull()) { //qDebug() << "script domelement is null"; return false; } d->scriptType = scriptelem.attribute("scripttype"); if (d->scriptType.isEmpty()) { d->scriptType = "executable"; } QString interpretername = scriptelem.attribute("language"); Kross::Manager* manager = &Kross::Manager::self(); Kross::InterpreterInfo* info = interpretername.isEmpty() ? 0 : manager->interpreterInfo(interpretername); if (info) { d->scriptaction->setInterpreter(interpretername); Kross::InterpreterInfo::Option::Map options = info->options(); Kross::InterpreterInfo::Option::Map::ConstIterator it, end = options.constEnd(); for (it = options.constBegin(); it != end; ++it) { QString value = scriptelem.attribute(it.key()); if (! value.isNull()) { QVariant v(value); if (v.convert(it.value()->value.type())) // preserve the QVariant's type d->scriptaction->setOption(it.key(), v); } } } d->scriptaction->setCode(scriptelem.text().toUtf8()); return true; } KDbObject* KexiScriptDesignView::storeNewData(const KDbObject& object, KexiView::StoreNewDataOptions options, bool *cancel) { KDbObject *s = KexiView::storeNewData(object, options, cancel); if (!s || *cancel) { delete s; return 0; } //qDebug() << "new id:" << s->id(); if (! storeData()) { qWarning() << "Failed to store the data."; //failure: remove object's object data to avoid garbage KDbConnection *conn = KexiMainWindowIface::global()->project()->dbConnection(); conn->removeObject(s->id()); delete s; return 0; } return s; } tristate KexiScriptDesignView::storeData(bool /*dontAsk*/) { qDebug(); //<< window()->partItem()->name() << "[" << window()->id() << "]"; QDomDocument domdoc("script"); QDomElement scriptelem = domdoc.createElement("script"); domdoc.appendChild(scriptelem); QString language = d->scriptaction->interpreter(); scriptelem.setAttribute("language", language); //! @todo move different types to their own part?? scriptelem.setAttribute("scripttype", d->scriptType); Kross::InterpreterInfo* info = Kross::Manager::self().interpreterInfo(language); if (info) { Kross::InterpreterInfo::Option::Map defoptions = info->options(); QMap options = d->scriptaction->options(); QMap::ConstIterator it, end(options.constEnd()); for (it = options.constBegin(); it != end; ++it) if (defoptions.contains(it.key())) // only remember options which the InterpreterInfo knows about... scriptelem.setAttribute(it.key(), it.value().toString()); } QDomText scriptcode = domdoc.createTextNode(d->scriptaction->code()); scriptelem.appendChild(scriptcode); return storeDataBlock(domdoc.toString()); } diff --git a/src/widget/navigator/KexiProjectNavigator.cpp b/src/widget/navigator/KexiProjectNavigator.cpp index 29f054743..9d358ec44 100644 --- a/src/widget/navigator/KexiProjectNavigator.cpp +++ b/src/widget/navigator/KexiProjectNavigator.cpp @@ -1,773 +1,773 @@ /* This file is part of the KDE project Copyright (C) 2002, 2003 Lucijan Busch Copyright (C) 2003-2016 Jarosław Staniek Copyright (C) 2010 Adam Pigg This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library 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 "KexiProjectNavigator.h" #include "KexiProjectTreeView.h" #include "KexiProjectModel.h" #include "KexiProjectModelItem.h" #include "KexiProjectItemDelegate.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class Q_DECL_HIDDEN KexiProjectNavigator::Private { public: Private(Features features_, KexiProjectNavigator *qq) : features(features_) , q(qq) , emptyStateLabel(0) , prevSelectedPartInfo(0) , readOnly(false) { } ~Private() { delete model; } void clearSelectionIfNeeded() { if (features & ClearSelectionAfterAction) { list->selectionModel()->clear(); } } Features features; KexiProjectNavigator *q; QVBoxLayout *lyr; KexiProjectTreeView *list; QLabel *emptyStateLabel; KActionCollection *actions; KexiItemMenu *itemMenu; KexiGroupMenu *partMenu; QAction *deleteAction, *renameAction, *newObjectAction, *openAction, *designAction, *editTextAction, *executeAction, *dataExportToClipboardAction, *dataExportToFileAction; #ifdef KEXI_QUICK_PRINTING_SUPPORT QAction *printAction, *pageSetupAction; #endif KActionMenu* exportActionMenu; QAction *itemMenuTitle, *partMenuTitle, *exportActionMenu_sep, *pageSetupAction_sep; KexiPart::Info *prevSelectedPartInfo; bool readOnly; KexiProjectModel *model; QString itemsPluginId; }; KexiProjectNavigator::KexiProjectNavigator(QWidget* parent, Features features) : QWidget(parent) , d(new Private(features, this)) { d->actions = new KActionCollection(this); setObjectName("KexiProjectNavigator"); setWindowTitle(xi18nc("@title:window", "Project Navigator")); setWindowIcon(KexiMainWindowIface::global()->thisWidget()->windowIcon()); d->lyr = new QVBoxLayout(this); d->lyr->setContentsMargins(0, 0, 0, 0); d->list = new KexiProjectTreeView(this); if (d->features & Borders) { d->list->setAlternatingRowColors(true); } else { d->list->setFrameStyle(QFrame::NoFrame); QPalette pal(d->list->palette()); pal.setColor(QPalette::Base, Qt::transparent); d->list->setPalette(pal); d->list->setIndentation(0); } d->model = new KexiProjectModel(); connect(d->model, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SLOT(slotUpdateEmptyStateLabel())); connect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SLOT(slotUpdateEmptyStateLabel())); d->list->setModel(d->model); KexiProjectItemDelegate *delegate = new KexiProjectItemDelegate(d->list); d->list->setItemDelegate(delegate); d->lyr->addWidget(d->list); //! @todo KEXI3 port from KGlobalSettings::Private::_k_slotNotifyChange: // connect(KGlobalSettings::self(), SIGNAL(settingsChanged(int)), SLOT(slotSettingsChanged(int))); // slotSettingsChanged(0); connect(d->list->selectionModel(), &QItemSelectionModel::currentChanged, this, &KexiProjectNavigator::slotSelectionChanged); if ((d->features & AllowSingleClickForOpeningItems) && KexiUtils::activateItemsOnSingleClick(d->list)) { connect(d->list, SIGNAL(clicked(QModelIndex)), this, SLOT(slotExecuteItem(QModelIndex))); } else { connect(d->list, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(slotExecuteItem(QModelIndex))); } // actions d->openAction = addAction("open_object", koIcon("document-open"), xi18n("&Open"), xi18n("Open object"), xi18n("Opens object selected in the list."), SLOT(slotOpenObject())); if (KexiMainWindowIface::global() && KexiMainWindowIface::global()->userMode()) { //! @todo some of these actions can be supported once we deliver ACLs... d->deleteAction = 0; d->renameAction = 0; d->designAction = 0; d->editTextAction = 0; d->newObjectAction = 0; } else { d->deleteAction = addAction("edit_delete", koIcon("edit-delete"), xi18n("&Delete..."), xi18n("Delete object"), xi18n("Deletes the object selected in the list."), SLOT(slotRemove())); d->renameAction = addAction("edit_rename", koIcon("edit-rename"), xi18n("&Rename..."), xi18n("Rename object"), xi18n("Renames the object selected in the list."), SLOT(slotRename())); //! @todo enable, doesn't work now: d->renameAction->setShortcut(QKeySequence(Qt::Key_F2)); #ifdef KEXI_SHOW_UNIMPLEMENTED //! @todo plugSharedAction("edit_cut",SLOT(slotCut())); //! @todo plugSharedAction("edit_copy",SLOT(slotCopy())); //! @todo plugSharedAction("edit_paste",SLOT(slotPaste())); #endif - d->designAction = addAction("design_object", koIcon("document-properties"), xi18n("&Design"), + d->designAction = addAction("design_object", KexiIcon("mode-selector-design"), xi18n("&Design"), xi18n("Design object"), xi18n("Starts designing of the object selected in the list."), SLOT(slotDesignObject())); d->editTextAction = addAction("editText_object", QIcon(), "Design in Text View", // <- no icon, no i18n, will be updated before use xi18n("Design object in text view"), xi18n("Starts designing of the object in the list in text view."), SLOT(slotEditTextObject())); d->newObjectAction = addAction("new_object", koIcon("document-new"), QString(),QString(), QString(), SLOT(slotNewObject())); } d->executeAction = addAction("data_execute", koIcon("system-run"), xi18n("Execute"), //! @todo tooltip, what's this QString(), QString(), SLOT(slotExecuteObject())); d->actions->addAction("export_object", d->exportActionMenu = new KActionMenu(xi18n("Export"), this)); d->dataExportToClipboardAction = addAction("exportToClipboardAsDataTable", koIcon("edit-copy"), xi18nc("Export->To Clipboard as Data... ", "To &Clipboard..."), xi18n("Export data to clipboard"), xi18n("Exports data from the currently selected table or query to clipboard."), SLOT(slotExportToClipboardAsDataTable())); d->exportActionMenu->addAction(d->dataExportToClipboardAction); d->dataExportToFileAction = addAction("exportToFileAsDataTable", KexiIcon("table"), xi18nc("Export->To File As Data &Table... ", "To &File As Data Table..."), xi18n("Export data to a file"), xi18n("Exports data from the currently selected table or query to a file."), SLOT(slotExportToFileAsDataTable())); d->exportActionMenu->addAction(d->dataExportToFileAction); #ifdef KEXI_QUICK_PRINTING_SUPPORT d->printAction = addAction("print_object", koIcon("document-print"), futureI18n("&Print..."), futureI18n("Print data"), futureI18n("Prints data from the currently selected table or query."), SLOT(slotPrintObject())); //! @todo document-page-setup could be a better icon d->pageSetupAction = addAction("pageSetupForObject", koIcon("configure"), futureI18n("Page Setup..."), futureI18n("Page setup for data"), futureI18n("Shows page setup for printing the active table or query."), SLOT(slotPageSetupForObject())); #endif if (KexiMainWindowIface::global() && KexiMainWindowIface::global()->userMode()) { //! @todo some of these actions can be supported once we deliver ACLs... d->partMenu = 0; } else { d->partMenu = new KexiGroupMenu(this, d->actions); } if (d->features & ContextMenus) { d->itemMenu = new KexiItemMenu(this, d->actions); } else { d->itemMenu = 0; } if (!(d->features & Writable)) { setReadOnly(true); } slotSelectionChanged(QModelIndex()); } void KexiProjectNavigator::setProject(KexiProject* prj, const QString& itemsPartClass, QString* partManagerErrorMessages, bool addAsSearchableModel) { d->itemsPluginId = itemsPartClass; d->model->setProject(prj, itemsPartClass, partManagerErrorMessages); if (addAsSearchableModel) { KexiMainWindowIface::global()->addSearchableModel(d->model); } d->list->expandAll(); d->list->setRootIsDecorated(false); slotUpdateEmptyStateLabel(); // Select and set current to first item d->list->setCurrentIndex(d->model->firstPartItem()); d->list->selectionModel()->select(d->list->currentIndex(), QItemSelectionModel::Rows); } QString KexiProjectNavigator::itemsPluginId() const { return d->itemsPluginId; } KexiProjectNavigator::~KexiProjectNavigator() { delete d; } QAction * KexiProjectNavigator::addAction(const QString& name, const QIcon& icon, const QString& text, const QString& toolTip, const QString& whatsThis, const char* slot) { QAction *action = new QAction(icon, text, this); d->actions->addAction(name, action); action->setToolTip(toolTip); action->setWhatsThis(whatsThis); connect(action, SIGNAL(triggered()), this, slot); return action; } void KexiProjectNavigator::contextMenuEvent(QContextMenuEvent* event) { if (!d->list->currentIndex().isValid() || !(d->features & ContextMenus)) return; QModelIndex pointedIndex = d->list->indexAt(d->list->mapFromGlobal(event->globalPos())); KexiProjectModelItem *bit = static_cast(pointedIndex.internalPointer()); if (!bit || !bit->partItem() /*no menu for group*/) { return; } QMenu *pm = 0; if (bit->partItem()) { pm = d->itemMenu; KexiProjectModelItem *par_it = static_cast(bit->parent()); if (par_it->partInfo() && bit->partItem()) { d->itemMenu->update(*par_it->partInfo(), *bit->partItem()); } } if (pm) { pm->exec(event->globalPos()); } event->setAccepted(true); d->clearSelectionIfNeeded(); } void KexiProjectNavigator::slotExecuteItem(const QModelIndex& vitem) { KexiProjectModelItem *it = static_cast(vitem.internalPointer()); if (!it) { qWarning() << "No internal pointer"; return; } if (it->partInfo()->isExecuteSupported()) emit executeItem(it->partItem()); else emit openOrActivateItem(it->partItem(), Kexi::DataViewMode); d->clearSelectionIfNeeded(); } void KexiProjectNavigator::slotSelectionChanged(const QModelIndex& i) { KexiProjectModelItem *it = static_cast(i.internalPointer()); if (!it) { if (KexiMainWindowIface::global() && !KexiMainWindowIface::global()->userMode()) { d->openAction->setEnabled(false); d->designAction->setEnabled(false); d->deleteAction->setEnabled(false); } return; } const bool gotitem = it->partItem(); //! @todo also check if the item is not read only if (d->deleteAction) { d->deleteAction->setEnabled(gotitem && !d->readOnly); } #ifdef KEXI_SHOW_UNIMPLEMENTED //! @todo setAvailable("edit_cut",gotitem); //! @todo setAvailable("edit_copy",gotitem); //! @todo setAvailable("edit_edititem",gotitem); #endif if ( KexiMainWindowIface::global() && !KexiMainWindowIface::global()->userMode() ) { d->openAction->setEnabled(gotitem && (it->partInfo()->supportedViewModes() & Kexi::DataViewMode)); if (d->designAction) { d->designAction->setEnabled(gotitem && (it->partInfo()->supportedViewModes() & Kexi::DesignViewMode)); } if (d->editTextAction) d->editTextAction->setEnabled(gotitem && (it->partInfo()->supportedViewModes() & Kexi::TextViewMode)); if (d->prevSelectedPartInfo != it->partInfo()) { d->prevSelectedPartInfo = it->partInfo(); if (d->newObjectAction) { d->newObjectAction->setText( xi18n("&Create Object: %1...", it->partInfo()->name() )); d->newObjectAction->setIcon(QIcon::fromTheme(it->partInfo()->iconName())); } #if 0 } else { if (d->newObjectAction) { d->newObjectAction->setText(xi18n("&Create Object...")); } #endif } } emit selectionChanged(it->partItem()); } void KexiProjectNavigator::slotRemove() { if (!d->deleteAction || !d->deleteAction->isEnabled() || !(d->features & Writable)) return; KexiProjectModelItem *it = static_cast(d->list->currentIndex().internalPointer()); if (!it || !it->partItem()) return; emit removeItem(it->partItem()); } void KexiProjectNavigator::slotNewObject() { if (!d->newObjectAction || !(d->features & Writable)) return; KexiProjectModelItem *it = static_cast(d->list->currentIndex().internalPointer()); if (!it || !it->partInfo()) return; emit newItem(it->partInfo()); } void KexiProjectNavigator::slotOpenObject() { KexiProjectModelItem *it = static_cast(d->list->currentIndex().internalPointer()); if (!it || !it->partItem()) return; emit openItem(it->partItem(), Kexi::DataViewMode); } void KexiProjectNavigator::slotDesignObject() { if (!d->designAction) return; KexiProjectModelItem *it = static_cast(d->list->currentIndex().internalPointer()); if (!it || !it->partItem()) return; emit openItem(it->partItem(), Kexi::DesignViewMode); } void KexiProjectNavigator::slotEditTextObject() { if (!d->editTextAction) return; KexiProjectModelItem *it = static_cast(d->list->currentIndex().internalPointer()); if (!it || !it->partItem()) return; emit openItem(it->partItem(), Kexi::TextViewMode); } void KexiProjectNavigator::slotCut() { if (!(d->features & Writable)) return; //! @todo } void KexiProjectNavigator::slotCopy() { //! @todo } void KexiProjectNavigator::slotPaste() { if (!(d->features & Writable)) return; //! @todo } void KexiProjectNavigator::slotRename() { if (!d->renameAction || !(d->features & Writable)) return; KexiPart::Item* partItem = selectedPartItem(); if (!partItem) { return; } KexiProjectModelItem *partModelItem = d->model->modelItemFromItem(*partItem); if (!partModelItem) { return; } KexiPart::Info *info = partModelItem->partInfo(); KexiPart::Part *part = Kexi::partManager().partForPluginId(partItem->pluginId()); if (!info || !part) { return; } KexiNameDialog dialog( xi18nc("@info Rename object %1:", "Rename %1:", partItem->name()), this); dialog.buttonBox()->button(QDialogButtonBox::Ok)->setText(xi18nc("@action:button Rename object", "Rename")); if (!d->model->project()) { qWarning() << "No KexiProject assigned!"; return; } dialog.widget()->addNameSubvalidator( //check if new name is allowed new KDbObjectNameValidator(d->model->project()->dbConnection()->driver())); dialog.widget()->setCaptionText(partItem->caption()); dialog.widget()->setNameText(partItem->name()); dialog.setWindowTitle( xi18nc("@title:window Rename Object %1.", "Rename %1", partItem->name())); dialog.setDialogIcon(info->iconName()); dialog.setAllowOverwriting(true); bool overwriteNeeded; if (dialog.execAndCheckIfObjectExists(*d->model->project(), *part, &overwriteNeeded) != QDialog::Accepted) { return; } if (dialog.widget()->nameText() != dialog.widget()->originalNameText() && !d->model->renameItem(partItem, dialog.widget()->nameText())) { return; } d->model->setItemCaption(partItem, dialog.widget()->captionText()); } void KexiProjectNavigator::setFocus() { if (!d->list->currentIndex().isValid()) { // select first QModelIndex first = d->model->firstPartItem(); d->list->setCurrentIndex(first); } d->list->setFocus(); } void KexiProjectNavigator::updateItemName(KexiPart::Item& item, bool dirty) { if (!(d->features & Writable)) return; d->model->updateItemName(item, dirty); } void KexiProjectNavigator::selectItem(KexiPart::Item& item) { KexiProjectModelItem *bitem = d->model->modelItemFromItem(item); if (!bitem) return; QModelIndex idx = d->model->indexFromItem(bitem); d->list->setCurrentIndex(idx); d->list->scrollTo(idx); } void KexiProjectNavigator::clearSelection() { d->list->clearSelection(); d->list->scrollToTop(); } void KexiProjectNavigator::slotExecuteObject() { if (!d->executeAction) return; KexiPart::Item* item = selectedPartItem(); if (item) { emit executeItem(item); d->clearSelectionIfNeeded(); } } void KexiProjectNavigator::slotExportToClipboardAsDataTable() { if (!d->dataExportToClipboardAction) return; KexiPart::Item* item = selectedPartItem(); if (item) emit exportItemToClipboardAsDataTable(item); } void KexiProjectNavigator::slotExportToFileAsDataTable() { if (!d->dataExportToFileAction) return; KexiPart::Item* item = selectedPartItem(); if (item) emit exportItemToFileAsDataTable(item); } KexiPart::Item* KexiProjectNavigator::selectedPartItem() const { KexiProjectModelItem *it = static_cast(d->list->currentIndex().internalPointer()); return it ? it->partItem() : 0; } KexiPart::Item* KexiProjectNavigator::partItemWithSearchHighlight() const { KexiProjectModelItem *it = static_cast(d->model->itemWithSearchHighlight().internalPointer()); return it ? it->partItem() : 0; } bool KexiProjectNavigator::actionEnabled(const QString& actionName) const { if (actionName == "project_export_data_table" && (d->features & ContextMenus)) return d->exportActionMenu->isVisible(); qWarning() << "no such action:" << actionName; return false; } void KexiProjectNavigator::slotPrintObject() { #ifdef KEXI_QUICK_PRINTING_SUPPORT if (!d->printAction) return; KexiPart::Item* item = selectedPartItem(); if (item) emit printItem(item); #endif } void KexiProjectNavigator::slotPageSetupForObject() { #ifdef KEXI_QUICK_PRINTING_SUPPORT if (!d->pageSetupAction) return; KexiPart::Item* item = selectedPartItem(); if (item) emit pageSetupForItem(item); #endif } void KexiProjectNavigator::setReadOnly(bool set) { d->readOnly = set; if (d->deleteAction) d->deleteAction->setEnabled(!d->readOnly); if (d->renameAction) d->renameAction->setEnabled(!d->readOnly); if (d->newObjectAction) { d->newObjectAction->setEnabled(!d->readOnly); } } bool KexiProjectNavigator::isReadOnly() const { return d->readOnly; } void KexiProjectNavigator::clear() { d->model->clear(); } KexiProjectModel* KexiProjectNavigator::model() const { return d->model; } void KexiProjectNavigator::slotUpdateEmptyStateLabel() { if (d->model->objectsCount() == 0) { // handle the empty state with care... http://www.pinterest.com/romanyakimovich/ui-empty-states/ if (!d->emptyStateLabel) { QString imgPath = KIconLoader::global()->iconPath(KexiIconName("document-empty"), - KIconLoader::SizeLarge); //qDebug() << imgPath; d->emptyStateLabel = new QLabel( xi18nc("@info Message for empty state in project navigator", "" "" "" "Your project is empty..." "" "Why not create something?", imgPath), this); d->emptyStateLabel->setPalette( KexiUtils::paletteWithDimmedColor(d->emptyStateLabel->palette(), QPalette::WindowText)); d->emptyStateLabel->setAlignment(Qt::AlignCenter); d->emptyStateLabel->setTextFormat(Qt::RichText); d->emptyStateLabel->setWordWrap(true); QFont f(d->emptyStateLabel->font()); f.setItalic(true); f.setFamily("Times"); f.setPointSize(f.pointSize() * 4 / 3); //d->emptyStateLabel->setFont(f); d->lyr->insertWidget(0, d->emptyStateLabel); } d->emptyStateLabel->show(); } else { delete d->emptyStateLabel; d->emptyStateLabel = 0; } } //-------------------------------------------- KexiMenuBase::KexiMenuBase(QWidget* parent, KActionCollection *col) : QMenu(parent) , m_actionCollection(col) { } KexiMenuBase::~KexiMenuBase() { } QAction* KexiMenuBase::addAction(const QString& actionName) { QAction* action = m_actionCollection->action(actionName); if (action) QMenu::addAction(action); return action; } //-------------------------------------------- KexiItemMenu::KexiItemMenu(QWidget* parent, KActionCollection *col) : KexiMenuBase(parent, col) { } KexiItemMenu::~KexiItemMenu() { } void KexiItemMenu::update(const KexiPart::Info& partInfo, const KexiPart::Item& partItem) { clear(); addSection(QString()); KexiContextMenuUtils::updateTitle(this, partItem.name(), partInfo.name(), partInfo.iconName()); if (m_actionCollection->action("open_object") && m_actionCollection->action("open_object")->isEnabled() && (partInfo.supportedViewModes() & Kexi::DataViewMode)) { addAction("open_object"); } if (m_actionCollection->action("design_object") && m_actionCollection->action("design_object")->isEnabled() && (partInfo.supportedViewModes() & Kexi::DesignViewMode)) { addAction("design_object"); } QAction *a = m_actionCollection->action("editText_object"); if (a && a->isEnabled() && (partInfo.supportedViewModes() & Kexi::TextViewMode)) { QString actionText; QString iconName; KexiPart::getTextViewAction(partInfo.id(), &actionText, &iconName); a->setText(actionText); a->setIcon(QIcon::fromTheme(iconName)); QMenu::addAction(a); } addSeparator(); #ifdef KEXI_SHOW_UNIMPLEMENTED //! @todo plugSharedAction("edit_cut", m_itemMenu); //! @todo plugSharedAction("edit_copy", m_itemMenu); //! @todo addSeparator(); #endif bool addSep = false; if (partInfo.isExecuteSupported()) { addAction("data_execute"); addSep = true; } if (partInfo.isDataExportSupported()) { addAction("export_object"); addSep = true; } if (addSep) addSeparator(); #ifdef KEXI_QUICK_PRINTING_SUPPORT if (partInfo.isPrintingSupported()) addAction("print_object"); if (partInfo.isPrintingSupported()) addAction("pageSetupForObject"); if (m_actionCollection->action("edit_rename") || m_actionCollection->action("edit_delete")) addSeparator(); #endif addAction("edit_rename"); addAction("edit_delete"); } //-------------------------------------------- KexiGroupMenu::KexiGroupMenu(QWidget* parent, KActionCollection *col) : KexiMenuBase(parent, col) { } KexiGroupMenu::~KexiGroupMenu() { } void KexiGroupMenu::update(KexiPart::Info* partInfo) { Q_UNUSED(partInfo); clear(); addAction("new_object"); } diff --git a/src/widget/relations/KexiRelationsView.cpp b/src/widget/relations/KexiRelationsView.cpp index 6168f262f..c4b63b257 100644 --- a/src/widget/relations/KexiRelationsView.cpp +++ b/src/widget/relations/KexiRelationsView.cpp @@ -1,483 +1,483 @@ /* This file is part of the KDE project Copyright (C) 2002 Lucijan Busch Copyright (C) 2003 Joseph Wenninger Copyright (C) 2003-2007 Jarosław Staniek This program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 program; see the file COPYING. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KexiRelationsView.h" #include #include #include #include #include #include "KexiRelationsScrollArea.h" #include "KexiRelationsConnection.h" #include #include #include #include #include #include #include #include #include #include #include //! @internal class Q_DECL_HIDDEN KexiRelationsView::Private { public: Private() { } KComboBox *tableCombo; QPushButton *btnAdd; KexiRelationsScrollArea *scrollArea; KDbConnection *conn; QMenu *tableQueryPopup; //!< over table/query QMenu *connectionPopup; //!< over connection QMenu *areaPopup; //!< over outer area QAction *openSelectedTableAction, *designSelectedTableAction, *appendSelectedFieldAction, *appendSelectedFieldsAction, *hideTableAction; }; //--------------- KexiRelationsView::KexiRelationsView(QWidget *parent) : KexiView(parent) , d(new Private) { QWidget *mainWidget = new QWidget(this); QGridLayout *g = new QGridLayout(mainWidget); g->setContentsMargins(0, 0, 0, 0); g->setSpacing(KexiUtils::spacingHint()); QWidget *horWidget = new QWidget(mainWidget); QHBoxLayout *hlyr = new QHBoxLayout(horWidget); hlyr->setContentsMargins(0, 0, 0, 0); g->addWidget(horWidget, 0, 0); d->tableCombo = new KComboBox(horWidget); d->tableCombo->setObjectName("tables_combo"); d->tableCombo->setMinimumWidth(QFontMetrics(font()).width("w")*20); d->tableCombo->setInsertPolicy(QComboBox::NoInsert); d->tableCombo->setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred)); QLabel *lbl = new QLabel(xi18n("Table:"), horWidget); lbl->setBuddy(d->tableCombo); lbl->setIndent(3); hlyr->addWidget(lbl); hlyr->addWidget(d->tableCombo); d->btnAdd = new QPushButton(xi18nc("Insert table/query into relations view", "&Insert"), horWidget); hlyr->addWidget(d->btnAdd); hlyr->addStretch(1); connect(d->btnAdd, SIGNAL(clicked()), this, SLOT(slotAddTable())); d->scrollArea = new KexiRelationsScrollArea(mainWidget); d->scrollArea->setObjectName("scroll_area"); KexiStyle::setupFrame(d->scrollArea); setViewWidget(mainWidget, false/* no focus proxy */); setFocusProxy(d->scrollArea); g->addWidget(d->scrollArea, 1, 0); //actions d->tableQueryPopup = new QMenu(this); d->tableQueryPopup->setObjectName("tableQueryPopup"); connect(d->tableQueryPopup, SIGNAL(aboutToShow()), this, SLOT(aboutToShowPopupMenu())); d->hideTableAction = plugSharedAction("edit_delete", xi18n("&Hide Table"), d->tableQueryPopup); if (d->hideTableAction) d->hideTableAction->setIcon(QIcon()); d->connectionPopup = new QMenu(this); d->connectionPopup->setObjectName("connectionPopup"); connect(d->connectionPopup, SIGNAL(aboutToShow()), this, SLOT(aboutToShowPopupMenu())); //! @todo areaPopup d->areaPopup = new QMenu(this); d->areaPopup->setObjectName("areaPopup"); d->appendSelectedFieldAction = new QAction(KexiIcon("add-field"), xi18n("&Append Field"), this); d->appendSelectedFieldAction->setObjectName("relationsview_appendField"); connect(d->appendSelectedFieldAction, SIGNAL(triggered()), this, SLOT(appendSelectedFields())); d->appendSelectedFieldsAction = new QAction(KexiIcon("add-field"), xi18n("&Append Fields"), this); d->appendSelectedFieldsAction->setObjectName("relationsview_appendFields"); connect(d->appendSelectedFieldsAction, SIGNAL(triggered()), this, SLOT(appendSelectedFields())); d->openSelectedTableAction = new QAction(koIcon("document-open"), xi18n("&Open Table"), this); d->openSelectedTableAction->setObjectName("relationsview_openTable"); connect(d->openSelectedTableAction, SIGNAL(triggered()), this, SLOT(openSelectedTable())); - d->designSelectedTableAction = new QAction(koIcon("document-properties"), xi18n("&Design Table"), this); + d->designSelectedTableAction = new QAction(KexiIcon("mode-selector-design"), xi18n("&Design Table"), this); connect(d->designSelectedTableAction, SIGNAL(triggered()), this, SLOT(designSelectedTable())); d->designSelectedTableAction->setObjectName("relationsview_designTable"); plugSharedAction("edit_delete", this, SLOT(removeSelectedObject())); connect(d->scrollArea, SIGNAL(tableViewGotFocus()), this, SLOT(tableViewGotFocus())); connect(d->scrollArea, SIGNAL(connectionViewGotFocus()), this, SLOT(connectionViewGotFocus())); connect(d->scrollArea, SIGNAL(emptyAreaGotFocus()), this, SLOT(emptyAreaGotFocus())); connect(d->scrollArea, SIGNAL(tableContextMenuRequest(QPoint)), this, SLOT(tableContextMenuRequest(QPoint))); connect(d->scrollArea, SIGNAL(connectionContextMenuRequest(QPoint)), this, SLOT(connectionContextMenuRequest(QPoint))); connect(d->scrollArea, SIGNAL(tableHidden(KDbTableSchema*)), this, SLOT(slotTableHidden(KDbTableSchema*))); connect(d->scrollArea, SIGNAL(tablePositionChanged(KexiRelationsTableContainer*)), this, SIGNAL(tablePositionChanged(KexiRelationsTableContainer*))); connect(d->scrollArea, SIGNAL(aboutConnectionRemove(KexiRelationsConnection*)), this, SIGNAL(aboutConnectionRemove(KexiRelationsConnection*))); //! @todo #if 0 if (!embedd) { /*todo setContextHelp(xi18n("Relations"), xi18n("To create a relationship simply drag the source field onto the target field. " "An arrowhead is used to show which table is the parent (master) and which table is the child (slave) in the relationship."));*/ } #endif #ifdef TESTING_KexiRelationWidget for (int i = 0;i < (int)d->db->tableNames().count();i++) QTimer::singleShot(100, this, SLOT(slotAddTable())); #endif invalidateActions(); } KexiRelationsView::~KexiRelationsView() { delete d; } TablesHash* KexiRelationsView::tables() const { return d->scrollArea->tables(); } KexiRelationsTableContainer* KexiRelationsView::table(const QString& name) const { return d->scrollArea->tables()->value(name); } const QSet* KexiRelationsView::relationsConnections() const { return d->scrollArea->relationsConnections(); } void KexiRelationsView::slotAddTable() { if (d->tableCombo->currentIndex() == -1) return; const QString tname = d->tableCombo->itemText(d->tableCombo->currentIndex()); KDbTableSchema *t = d->conn->tableSchema(tname); addTable(t); } void KexiRelationsView::addTable(KDbTableSchema *t, const QRect &rect) { if (!t) return; if (!d->scrollArea->tableContainer(t)) { KexiRelationsTableContainer *c = d->scrollArea->addTableContainer(t, rect); //qDebug() << "adding table" << t->name(); if (!c) return; connect(c, SIGNAL(fieldsDoubleClicked(KDbTableOrQuerySchema&,QStringList)), this, SIGNAL(appendFields(KDbTableOrQuerySchema&,QStringList))); } const QString tname = t->name().toLower(); const int count = d->tableCombo->count(); int i = 0; for (; i < count; i++) { if (d->tableCombo->itemText(i).toLower() == tname) break; } if (i < count) { int oi = d->tableCombo->currentIndex(); //qDebug() << "removing a table from the combo box"; d->tableCombo->removeItem(i); if (d->tableCombo->count() > 0) { if (oi >= d->tableCombo->count()) { oi = d->tableCombo->count() - 1; } d->tableCombo->setCurrentIndex(oi); } else { d->tableCombo->setEnabled(false); d->btnAdd->setEnabled(false); } } emit tableAdded(t); } void KexiRelationsView::addConnection(const SourceConnection& conn) { d->scrollArea->addConnection(conn); } void KexiRelationsView::addTable(const QString& t) { for (int i = 0; i < d->tableCombo->count(); i++) { if (d->tableCombo->itemText(i) == t) { d->tableCombo->setCurrentIndex(i); slotAddTable(); } } } void KexiRelationsView::tableViewGotFocus() { invalidateActions(); } void KexiRelationsView::connectionViewGotFocus() { invalidateActions(); } void KexiRelationsView::emptyAreaGotFocus() { invalidateActions(); } void KexiRelationsView::tableContextMenuRequest(const QPoint& pos) { invalidateActions(); executePopup(pos); } void KexiRelationsView::connectionContextMenuRequest(const QPoint& pos) { invalidateActions(); executePopup(pos); } void KexiRelationsView::emptyAreaContextMenuRequest(const QPoint& /*pos*/) { invalidateActions(); //! @todo } void KexiRelationsView::invalidateActions() { setAvailable("edit_delete", d->scrollArea->selectedConnection() || d->scrollArea->focusedTableContainer()); } void KexiRelationsView::executePopup(QPoint pos) { if (pos == QPoint(-1, -1)) { pos = mapToGlobal( d->scrollArea->focusedTableContainer() ? d->scrollArea->focusedTableContainer()->pos() + d->scrollArea->focusedTableContainer()->rect().center() : rect().center()); } if (d->scrollArea->focusedTableContainer()) d->tableQueryPopup->exec(pos); else if (d->scrollArea->selectedConnection()) d->connectionPopup->exec(pos); } void KexiRelationsView::removeSelectedObject() { d->scrollArea->removeSelectedObject(); } void KexiRelationsView::appendSelectedFields() { KexiRelationsTableContainer* currentTableContainer = d->scrollArea->focusedTableContainer(); if (!currentTableContainer) return; emit appendFields(*currentTableContainer->schema(), currentTableContainer->selectedFieldNames()); } void KexiRelationsView::openSelectedTable() { /*! @todo what about query? */ if (!d->scrollArea->focusedTableContainer() || !d->scrollArea->focusedTableContainer()->schema()->table()) return; bool openingCancelled; KexiMainWindowIface::global()->openObject( "kexi/table", d->scrollArea->focusedTableContainer()->schema()->name(), Kexi::DataViewMode, &openingCancelled); } void KexiRelationsView::designSelectedTable() { /*! @todo what about query? */ if (!d->scrollArea->focusedTableContainer() || !d->scrollArea->focusedTableContainer()->schema()->table()) return; bool openingCancelled; KexiMainWindowIface::global()->openObject( "kexi/table", d->scrollArea->focusedTableContainer()->schema()->name(), Kexi::DesignViewMode, &openingCancelled); } QSize KexiRelationsView::sizeHint() const { return d->scrollArea->sizeHint(); } void KexiRelationsView::slotTableHidden(KDbTableSchema* table) { const QString &t = table->name().toLower(); int i; for (i = 0; i < d->tableCombo->count() && t > d->tableCombo->itemText(i).toLower(); i++) { } d->tableCombo->insertItem(i, table->name()); if (!d->tableCombo->isEnabled()) { d->tableCombo->setCurrentIndex(0); d->tableCombo->setEnabled(true); d->btnAdd->setEnabled(true); } emit tableHidden(table); } void KexiRelationsView::aboutToShowPopupMenu() { KexiRelationsTableContainer* currentTableContainer = d->scrollArea->focusedTableContainer(); if (currentTableContainer /*&& currentTableContainer->schema()->table()*/) { /*! @todo what about query? */ d->tableQueryPopup->clear(); d->tableQueryPopup->addSection(KexiIcon("table"), QString(d->scrollArea->focusedTableContainer()->schema()->name()) + " : " + xi18n("Table")); QStringList selectedFieldNames(currentTableContainer->selectedFieldNames()); if (currentTableContainer && !selectedFieldNames.isEmpty()) { if (selectedFieldNames.count() > 1 || selectedFieldNames.first() == "*") //multiple d->tableQueryPopup->addAction(d->appendSelectedFieldsAction); else d->tableQueryPopup->addAction(d->appendSelectedFieldAction); d->tableQueryPopup->addSeparator(); } d->tableQueryPopup->addAction(d->openSelectedTableAction); d->tableQueryPopup->addAction(d->designSelectedTableAction); d->tableQueryPopup->addSeparator(); d->tableQueryPopup->addAction(d->hideTableAction); } else if (d->scrollArea->selectedConnection()) { unplugSharedAction("edit_delete", d->connectionPopup); d->connectionPopup->clear(); d->connectionPopup->addSection(QIcon(), d->scrollArea->selectedConnection()->toString() + " : " + xi18n("Relationship")); plugSharedAction("edit_delete", d->connectionPopup); } } bool KexiRelationsView::clear() { d->scrollArea->clear(); return setConnection(d->conn); } /*! Removes all coonections from the view. */ void KexiRelationsView::removeAllConnections() { d->scrollArea->removeAllConnections(); } bool KexiRelationsView::setConnection(KDbConnection *conn) { d->tableCombo->clear(); d->conn = conn; if (conn) { bool ok; QStringList result = d->conn->tableNames(false/*no system tables*/, &ok); if (!ok) { return false; } result.sort(); d->tableCombo->addItems(result); } return true; } void KexiRelationsView::objectCreated(const QString &mime, const QString& name) { if (mime == "kexi/table" || mime == "kexi/query") { //! @todo query? const int count = d->tableCombo->count(); QString strName(name); int i = 0; for (; i < count && d->tableCombo->itemText(i) <= strName; i++) { } d->tableCombo->insertItem(i, name); } } void KexiRelationsView::objectDeleted(const QString &mime, const QString& name) { if (mime == "kexi/table" || mime == "kexi/query") { for (int i = 0; i < d->tableCombo->count(); i++) { //! @todo query? if (d->tableCombo->itemText(i) == name) { d->tableCombo->removeItem(i); if (d->tableCombo->currentIndex() == i) { if (i == (d->tableCombo->count() - 1)) d->tableCombo->setCurrentIndex(i - 1); else d->tableCombo->setCurrentIndex(i); } break; } } } } void KexiRelationsView::objectRenamed(const QString &mime, const QString& name, const QString& newName) { if (mime == "kexi/table" || mime == "kexi/query") { const int count = d->tableCombo->count(); for (int i = 0; i < count; i++) { //! @todo query? if (d->tableCombo->itemText(i) == name) { d->tableCombo->removeItem(i); int j = 0; for (; j < count && d->tableCombo->itemText(j) <= newName; j++) { } d->tableCombo->insertItem(j, newName); break; } } } } void KexiRelationsView::hideAllTablesExcept(QList* tables) { d->scrollArea->hideAllTablesExcept(tables); }