summaryrefslogtreecommitdiffstats
path: root/kexi/plugins/forms/kexidatasourcepage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kexi/plugins/forms/kexidatasourcepage.cpp')
-rw-r--r--kexi/plugins/forms/kexidatasourcepage.cpp471
1 files changed, 471 insertions, 0 deletions
diff --git a/kexi/plugins/forms/kexidatasourcepage.cpp b/kexi/plugins/forms/kexidatasourcepage.cpp
new file mode 100644
index 000000000..6c0de8303
--- /dev/null
+++ b/kexi/plugins/forms/kexidatasourcepage.cpp
@@ -0,0 +1,471 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 Jaroslaw Staniek <js@iidea.pl>
+
+ 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 "kexidatasourcepage.h"
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qheader.h>
+
+#include <kiconloader.h>
+#include <klocale.h>
+#include <ktoolbarbutton.h>
+#include <kdebug.h>
+#include <kpopupmenu.h>
+
+#include <widget/kexipropertyeditorview.h>
+#include <widget/kexidatasourcecombobox.h>
+#include <widget/kexifieldlistview.h>
+#include <widget/kexifieldcombobox.h>
+#include <widget/kexismalltoolbutton.h>
+#include <kexidb/connection.h>
+#include <kexiproject.h>
+
+#include <formeditor/commands.h>
+
+#include <koproperty/property.h>
+#include <koproperty/utils.h>
+
+KexiDataSourcePage::KexiDataSourcePage(QWidget *parent, const char *name)
+ : QWidget(parent, name)
+ , m_insideClearDataSourceSelection(false)
+{
+ QVBoxLayout *vlyr = new QVBoxLayout(this);
+ m_objectInfoLabel = new KexiObjectInfoLabel(this, "KexiObjectInfoLabel");
+ vlyr->addWidget(m_objectInfoLabel);
+
+ m_noDataSourceAvailableSingleText = i18n("No data source could be assigned for this widget.");
+ m_noDataSourceAvailableMultiText = i18n("No data source could be assigned for multiple widgets.");
+
+ vlyr->addSpacing(8);
+
+ //Section 1: Form's/Widget's Data Source
+ KoProperty::GroupContainer *container = new KoProperty::GroupContainer(i18n("Data Source"), this);
+ vlyr->addWidget(container);
+
+ QWidget *contents = new QWidget(container);
+ container->setContents(contents);
+ QVBoxLayout *contentsVlyr = new QVBoxLayout(contents);
+
+ m_noDataSourceAvailableLabel = new QLabel(m_noDataSourceAvailableSingleText, contents);
+ m_noDataSourceAvailableLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
+ m_noDataSourceAvailableLabel->setMargin(2);
+ m_noDataSourceAvailableLabel->setAlignment(Qt::WordBreak | Qt::AlignBottom | Qt::AlignLeft);
+ contentsVlyr->addWidget(m_noDataSourceAvailableLabel);
+
+ //-Widget's Data Source
+ QHBoxLayout *hlyr = new QHBoxLayout(contentsVlyr);
+#if 0
+//! @todo unhide this when expression work
+// m_widgetDSLabel = new QLabel(i18n("Table Field, Query Field or Expression", "Source field or expression:"), this);
+#else
+ m_widgetDSLabel = new QLabel(i18n("Table Field or Query Field", "Widget's data source:"), contents);
+#endif
+ m_widgetDSLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
+ m_widgetDSLabel->setMargin(2);
+ m_widgetDSLabel->setMinimumHeight(IconSize(KIcon::Small)+4);
+ m_widgetDSLabel->setAlignment(AlignLeft|AlignBottom);
+ hlyr->addWidget(m_widgetDSLabel);
+
+ m_clearWidgetDSButton = new KexiSmallToolButton(contents, QString::null, "clear_left", "clearWidgetDSButton");
+ m_clearWidgetDSButton->setMinimumHeight(m_widgetDSLabel->minimumHeight());
+ QToolTip::add(m_clearWidgetDSButton, i18n("Clear widget's data source"));
+ hlyr->addWidget(m_clearWidgetDSButton);
+ connect(m_clearWidgetDSButton, SIGNAL(clicked()), this, SLOT(clearWidgetDataSourceSelection()));
+
+ m_sourceFieldCombo = new KexiFieldComboBox(contents, "sourceFieldCombo");
+ m_widgetDSLabel->setBuddy(m_sourceFieldCombo);
+ contentsVlyr->addWidget(m_sourceFieldCombo);
+
+/* m_dataSourceSeparator = new QFrame(contents);
+ m_dataSourceSeparator->setFrameShape(QFrame::HLine);
+ m_dataSourceSeparator->setFrameShadow(QFrame::Sunken);
+ contentsVlyr->addWidget(m_dataSourceSeparator);*/
+
+ contentsVlyr->addSpacing(8);
+
+ //- Form's Data Source
+ hlyr = new QHBoxLayout(contentsVlyr);
+ m_dataSourceLabel = new QLabel(i18n("Form's data source:"), contents);
+ m_dataSourceLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
+ m_dataSourceLabel->setMargin(2);
+ m_dataSourceLabel->setMinimumHeight(IconSize(KIcon::Small)+4);
+ m_dataSourceLabel->setAlignment(AlignLeft|AlignBottom);
+ hlyr->addWidget(m_dataSourceLabel);
+
+ m_gotoButton = new KexiSmallToolButton(contents, QString::null, "goto", "gotoButton");
+ m_gotoButton->setMinimumHeight(m_dataSourceLabel->minimumHeight());
+ QToolTip::add(m_gotoButton, i18n("Go to selected form's data source"));
+ hlyr->addWidget(m_gotoButton);
+ connect(m_gotoButton, SIGNAL(clicked()), this, SLOT(slotGotoSelected()));
+
+ m_clearDSButton = new KexiSmallToolButton(contents, QString::null, "clear_left", "clearDSButton");
+ m_clearDSButton->setMinimumHeight(m_dataSourceLabel->minimumHeight());
+ QToolTip::add(m_clearDSButton, i18n("Clear form's data source"));
+ hlyr->addWidget(m_clearDSButton);
+ connect(m_clearDSButton, SIGNAL(clicked()), this, SLOT(clearDataSourceSelection()));
+
+ m_dataSourceCombo = new KexiDataSourceComboBox(contents, "dataSourceCombo");
+ m_dataSourceLabel->setBuddy(m_dataSourceCombo);
+ contentsVlyr->addWidget(m_dataSourceCombo);
+
+#ifdef KEXI_NO_AUTOFIELD_WIDGET
+ m_availableFieldsLabel = 0;
+ m_addField = 0;
+// m_fieldListView = 0;
+ vlyr->addStretch();
+#else
+ vlyr->addSpacing(fontMetrics().height());
+/* QFrame *separator = new QFrame(this);
+ separator->setFrameShape(QFrame::HLine);
+ separator->setFrameShadow(QFrame::Sunken);
+ vlyr->addWidget(separator);*/
+/*
+ KPopupTitle *title = new KPopupTitle(this);
+ title->setTitle(i18n("Inserting fields"));
+ vlyr->addWidget(title);
+ vlyr->addSpacing(4);*/
+
+
+ //2. Inserting fields
+ container = new KoProperty::GroupContainer(i18n("Inserting Fields"), this);
+ vlyr->addWidget(container, 1);
+
+ //helper info
+//! @todo allow to hide such helpers by adding global option
+ contents = new QWidget(container);
+ container->setContents(contents);
+ contentsVlyr = new QVBoxLayout(contents);
+ hlyr = new QHBoxLayout(contentsVlyr);
+ m_mousePointerLabel = new QLabel(contents);
+ hlyr->addWidget(m_mousePointerLabel);
+ m_mousePointerLabel->setPixmap( SmallIcon("mouse_pointer") );
+ m_mousePointerLabel->setFixedWidth( m_mousePointerLabel->pixmap() ? m_mousePointerLabel->pixmap()->width() : 0);
+ m_availableFieldsDescriptionLabel = new QLabel(
+ i18n("Select fields from the list below and drag them onto a form or click the \"Insert\" button"), contents);
+ m_availableFieldsDescriptionLabel->setAlignment( Qt::AlignAuto | Qt::WordBreak );
+ hlyr->addWidget(m_availableFieldsDescriptionLabel);
+
+ //Available Fields
+ contentsVlyr->addSpacing(4);
+ hlyr = new QHBoxLayout(contentsVlyr);
+ m_availableFieldsLabel = new QLabel(i18n("Available fields:"), contents);
+ m_availableFieldsLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
+ m_availableFieldsLabel->setMargin(2);
+ m_availableFieldsLabel->setMinimumHeight(IconSize(KIcon::Small));
+ hlyr->addWidget(m_availableFieldsLabel);
+
+ m_addField = new KexiSmallToolButton(contents, i18n("Insert selected field into form", "Insert"),
+ "add_field", "addFieldButton");
+ m_addField->setMinimumHeight(m_availableFieldsLabel->minimumHeight());
+// m_addField->setTextPosition(QToolButton::Right);
+ m_addField->setFocusPolicy(StrongFocus);
+ QToolTip::add(m_addField, i18n("Insert selected fields into form"));
+ hlyr->addWidget(m_addField);
+ connect(m_addField, SIGNAL(clicked()), this, SLOT(slotInsertSelectedFields()));
+
+ m_fieldListView = new KexiFieldListView(contents, "fieldListView",
+ KexiFieldListView::ShowDataTypes | KexiFieldListView::AllowMultiSelection );
+ m_fieldListView->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding));
+ m_availableFieldsLabel->setBuddy(m_fieldListView);
+ contentsVlyr->addWidget(m_fieldListView, 1);
+ connect(m_fieldListView, SIGNAL(selectionChanged()), this, SLOT(slotFieldListViewSelectionChanged()));
+ connect(m_fieldListView, SIGNAL(fieldDoubleClicked(const QString&, const QString&, const QString&)),
+ this, SLOT(slotFieldDoubleClicked(const QString&, const QString&, const QString&)));
+#endif
+
+ vlyr->addStretch(1);
+
+ connect(m_dataSourceCombo, SIGNAL(textChanged(const QString &)), this, SLOT(slotDataSourceTextChanged(const QString &)));
+ connect(m_dataSourceCombo, SIGNAL(dataSourceChanged()), this, SLOT(slotDataSourceChanged()));
+ connect(m_sourceFieldCombo, SIGNAL(selected()), this, SLOT(slotFieldSelected()));
+
+ clearDataSourceSelection();
+ slotFieldListViewSelectionChanged();
+}
+
+KexiDataSourcePage::~KexiDataSourcePage()
+{
+}
+
+void KexiDataSourcePage::setProject(KexiProject *prj)
+{
+ m_sourceFieldCombo->setProject(prj);
+ m_dataSourceCombo->setProject(prj);
+}
+
+void KexiDataSourcePage::clearDataSourceSelection(bool alsoClearComboBox)
+{
+ if (m_insideClearDataSourceSelection)
+ return;
+ m_insideClearDataSourceSelection = true;
+ if (alsoClearComboBox && !m_dataSourceCombo->selectedName().isEmpty())
+ m_dataSourceCombo->setDataSource("", "");
+// if (!m_dataSourceCombo->currentText().isEmpty()) {
+// m_dataSourceCombo->setCurrentText("");
+// emit m_dataSourceCombo->dataSourceSelected();
+// }
+ m_clearDSButton->setEnabled(false);
+ m_gotoButton->setEnabled(false);
+#ifndef KEXI_NO_AUTOFIELD_WIDGET
+ m_addField->setEnabled(false);
+ m_fieldListView->clear();
+#endif
+ m_insideClearDataSourceSelection = false;
+}
+
+void KexiDataSourcePage::clearWidgetDataSourceSelection()
+{
+ if (!m_sourceFieldCombo->currentText().isEmpty()) {
+ m_sourceFieldCombo->setCurrentText("");
+ m_sourceFieldCombo->setFieldOrExpression(QString::null);
+ slotFieldSelected();
+ }
+ m_clearWidgetDSButton->setEnabled(false);
+}
+
+void KexiDataSourcePage::slotGotoSelected()
+{
+ QCString mime = m_dataSourceCombo->selectedMimeType().latin1();
+ if (mime=="kexi/table" || mime=="kexi/query") {
+ if (m_dataSourceCombo->isSelectionValid())
+ emit jumpToObjectRequested(mime, m_dataSourceCombo->selectedName().latin1());
+ }
+}
+
+void KexiDataSourcePage::slotInsertSelectedFields()
+{
+#ifndef KEXI_NO_AUTOFIELD_WIDGET
+ QStringList selectedFieldNames(m_fieldListView->selectedFieldNames());
+ if (selectedFieldNames.isEmpty())
+ return;
+
+ emit insertAutoFields(m_fieldListView->schema()->table() ? "kexi/table" : "kexi/query",
+ m_fieldListView->schema()->name(), selectedFieldNames);
+#endif
+}
+
+void KexiDataSourcePage::slotFieldDoubleClicked(const QString& sourceMimeType, const QString& sourceName,
+ const QString& fieldName)
+{
+#ifndef KEXI_NO_AUTOFIELD_WIDGET
+ QStringList selectedFields;
+ selectedFields.append(fieldName);
+ emit insertAutoFields(sourceMimeType, sourceName, selectedFields);
+#endif
+}
+
+void KexiDataSourcePage::slotDataSourceTextChanged(const QString & string)
+{
+ Q_UNUSED(string);
+ const bool enable = m_dataSourceCombo->isSelectionValid(); //!string.isEmpty() && m_dataSourceCombo->selectedName() == string.latin1();
+ if (!enable) {
+ clearDataSourceSelection( m_dataSourceCombo->selectedName().isEmpty()/*alsoClearComboBox*/ );
+ }
+ updateSourceFieldWidgetsAvailability();
+/*#ifndef KEXI_NO_AUTOFIELD_WIDGET
+ m_fieldListView->setEnabled(enable);
+// m_addField->setEnabled(enable);
+ m_availableFieldsLabel->setEnabled(enable);
+#endif*/
+}
+
+void KexiDataSourcePage::slotDataSourceChanged()
+{
+ if (!m_dataSourceCombo->project())
+ return;
+ QCString mime = m_dataSourceCombo->selectedMimeType().latin1();
+ bool dataSourceFound = false;
+ QCString name = m_dataSourceCombo->selectedName().latin1();
+ if ((mime=="kexi/table" || mime=="kexi/query") && m_dataSourceCombo->isSelectionValid()) {
+ KexiDB::TableOrQuerySchema *tableOrQuery = new KexiDB::TableOrQuerySchema(
+ m_dataSourceCombo->project()->dbConnection(), name, mime=="kexi/table");
+ if (tableOrQuery->table() || tableOrQuery->query()) {
+#ifdef KEXI_NO_AUTOFIELD_WIDGET
+ m_tableOrQuerySchema = tableOrQuery;
+#else
+ m_fieldListView->setSchema( tableOrQuery );
+#endif
+ dataSourceFound = true;
+ m_sourceFieldCombo->setTableOrQuery(name, mime=="kexi/table");
+ }
+ else {
+ delete tableOrQuery;
+ }
+ }
+ if (!dataSourceFound) {
+ m_sourceFieldCombo->setTableOrQuery("", true);
+ }
+ //if (m_sourceFieldCombo->hasFocus())
+// m_dataSourceCombo->setFocus();
+ m_clearDSButton->setEnabled(dataSourceFound);
+ m_gotoButton->setEnabled(dataSourceFound);
+ if (dataSourceFound) {
+ slotFieldListViewSelectionChanged();
+ } else {
+#ifndef KEXI_NO_AUTOFIELD_WIDGET
+ m_addField->setEnabled(false);
+#endif
+ }
+ updateSourceFieldWidgetsAvailability();
+ emit formDataSourceChanged(mime, name);
+}
+
+void KexiDataSourcePage::slotFieldSelected()
+{
+ KexiDB::Field::Type dataType = KexiDB::Field::InvalidType;
+#ifdef KEXI_NO_AUTOFIELD_WIDGET
+ KexiDB::Field *field = m_tableOrQuerySchema->field( m_sourceFieldCombo->fieldOrExpression() ); //temp
+#else
+//! @todo this should also work for expressions
+ KexiDB::Field *field = m_fieldListView->schema()->field( m_sourceFieldCombo->fieldOrExpression() );
+#endif
+ if (field)
+ dataType = field->type();
+
+ m_clearWidgetDSButton->setEnabled( !m_sourceFieldCombo->fieldOrExpression().isEmpty() );
+
+ emit dataSourceFieldOrExpressionChanged(
+ m_sourceFieldCombo->fieldOrExpression(),
+ m_sourceFieldCombo->fieldOrExpressionCaption(),
+ dataType
+ );
+}
+
+void KexiDataSourcePage::setDataSource(const QCString& mimeType, const QCString& name)
+{
+ m_dataSourceCombo->setDataSource(mimeType, name);
+}
+
+void KexiDataSourcePage::assignPropertySet(KoProperty::Set* propertySet)
+{
+ QCString objectName;
+ if (propertySet && propertySet->contains("name"))
+ objectName = (*propertySet)["name"].value().toCString();
+ if (!objectName.isEmpty() && objectName == m_currentObjectName)
+ return; //the same object
+ m_currentObjectName = objectName;
+
+ QCString objectClassName;
+ if (propertySet && propertySet->contains("this:className"))
+ objectClassName = (*propertySet)["this:className"].value().toCString();
+/*moved if (propertySet) {
+ QCString iconName;
+ QString objectClassString;
+ if (propertySet->contains("this:iconName"))
+ iconName = (*propertySet)["this:iconName"].value().toCString();
+ if (propertySet->contains("this:classString"))
+ objectClassString = (*propertySet)["this:classString"].value().toString();
+ m_objectInfoLabel->setObjectName(objectName);
+ m_objectInfoLabel->setObjectClassIcon(iconName);
+ m_objectInfoLabel->setObjectClassName(objectClassString);
+ if (propertySet->contains("this:className"))
+ objectClassName = (*propertySet)["this:className"].value().toCString();
+ }*/
+ KexiPropertyEditorView::updateInfoLabelForPropertySet(
+ m_objectInfoLabel, propertySet);
+
+ const bool isForm = objectClassName=="KexiDBForm";
+// kdDebug() << "objectClassName=" << objectClassName << endl;
+// {
+/* //this is top level form's surface: data source means table or query
+ QCString dataSourceMimeType, dataSource;
+ if (buffer->hasProperty("dataSourceMimeType"))
+ dataSourceMimeType = (*buffer)["dataSourceMimeType"].value().toCString();
+ if (buffer->hasProperty("dataSource"))
+ dataSource = (*buffer)["dataSource"].value().toCString();
+ m_dataSourceCombo->setDataSource(dataSourceMimeType, dataSource);*/
+// }
+// else {
+
+ const bool multipleSelection = objectClassName=="special:multiple";
+ const bool hasDataSourceProperty = propertySet && propertySet->contains("dataSource") && !multipleSelection;
+
+ if (!isForm) {
+ //this is a widget
+ QCString dataSource;
+ if (hasDataSourceProperty) {
+ if (propertySet)
+ dataSource = (*propertySet)["dataSource"].value().toCString();
+ m_noDataSourceAvailableLabel->hide();
+ m_sourceFieldCombo->setFieldOrExpression(dataSource);
+ m_sourceFieldCombo->setEnabled(true);
+ m_clearWidgetDSButton->setEnabled(!m_sourceFieldCombo->currentText().isEmpty());
+ m_widgetDSLabel->show();
+ m_clearWidgetDSButton->show();
+ m_sourceFieldCombo->show();
+// m_dataSourceSeparator->hide();
+ updateSourceFieldWidgetsAvailability();
+ }
+ }
+
+ if (isForm) {
+ m_noDataSourceAvailableLabel->hide();
+// m_dataSourceSeparator->hide();
+ }
+ else if (!hasDataSourceProperty) {
+ if (multipleSelection)
+ m_noDataSourceAvailableLabel->setText(m_noDataSourceAvailableMultiText);
+ else
+ m_noDataSourceAvailableLabel->setText(m_noDataSourceAvailableSingleText);
+ m_noDataSourceAvailableLabel->show();
+// m_dataSourceSeparator->show();
+ //make 'No data source could be assigned' label's height the same as the 'source field' combo+label
+ m_noDataSourceAvailableLabel->setMinimumHeight(m_widgetDSLabel->height()
+ + m_sourceFieldCombo->height()/*-m_dataSourceSeparator->height()*/);
+ m_sourceFieldCombo->setCurrentText("");
+ }
+
+ if (isForm || !hasDataSourceProperty) {
+ //no source field can be set
+ m_widgetDSLabel->hide();
+ m_clearWidgetDSButton->hide();
+ m_sourceFieldCombo->hide();
+ }
+}
+
+void KexiDataSourcePage::slotFieldListViewSelectionChanged()
+{
+#ifndef KEXI_NO_AUTOFIELD_WIDGET
+ //update "add field" button's state
+ for (QListViewItemIterator it(m_fieldListView); it.current(); ++it) {
+ if (it.current()->isSelected()) {
+ m_addField->setEnabled(true);
+ return;
+ }
+ }
+ m_addField->setEnabled(false);
+#endif
+}
+
+void KexiDataSourcePage::updateSourceFieldWidgetsAvailability()
+{
+ const bool hasDataSource = m_dataSourceCombo->isSelectionValid(); //!m_dataSourceCombo->selectedName().isEmpty();
+ m_sourceFieldCombo->setEnabled( hasDataSource );
+ m_widgetDSLabel->setEnabled( hasDataSource );
+#ifndef KEXI_NO_AUTOFIELD_WIDGET
+ m_fieldListView->setEnabled( hasDataSource );
+ m_availableFieldsLabel->setEnabled( hasDataSource );
+ m_mousePointerLabel->setEnabled( hasDataSource );
+ m_availableFieldsDescriptionLabel->setEnabled( hasDataSource );
+#endif
+}
+
+#include "kexidatasourcepage.moc"