kexi

kexidatasourcepage.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2005 Jaroslaw Staniek <js@iidea.pl>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation; either
00007    version 2 of the License, or (at your option) any later version.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "kexidatasourcepage.h"
00021 
00022 #include <qlabel.h>
00023 #include <qlayout.h>
00024 #include <qtooltip.h>
00025 #include <qheader.h>
00026 
00027 #include <kiconloader.h>
00028 #include <klocale.h>
00029 #include <ktoolbarbutton.h>
00030 #include <kdebug.h>
00031 #include <kpopupmenu.h>
00032 
00033 #include <widget/kexipropertyeditorview.h>
00034 #include <widget/kexidatasourcecombobox.h>
00035 #include <widget/kexifieldlistview.h>
00036 #include <widget/kexifieldcombobox.h>
00037 #include <widget/kexismalltoolbutton.h>
00038 #include <kexidb/connection.h>
00039 #include <kexiproject.h>
00040 
00041 #include <formeditor/commands.h>
00042 
00043 #include <koproperty/property.h>
00044 #include <koproperty/utils.h>
00045 
00046 KexiDataSourcePage::KexiDataSourcePage(QWidget *parent, const char *name)
00047  : QWidget(parent, name)
00048  , m_insideClearDataSourceSelection(false)
00049 {
00050     QVBoxLayout *vlyr = new QVBoxLayout(this);
00051     m_objectInfoLabel = new KexiObjectInfoLabel(this, "KexiObjectInfoLabel");
00052     vlyr->addWidget(m_objectInfoLabel);
00053 
00054     m_noDataSourceAvailableSingleText = i18n("No data source could be assigned for this widget.");
00055     m_noDataSourceAvailableMultiText = i18n("No data source could be assigned for multiple widgets.");
00056 
00057     vlyr->addSpacing(8);
00058 
00059     //Section 1: Form's/Widget's Data Source
00060     KoProperty::GroupContainer *container = new KoProperty::GroupContainer(i18n("Data Source"), this);
00061     vlyr->addWidget(container);
00062 
00063     QWidget *contents = new QWidget(container);
00064     container->setContents(contents);
00065     QVBoxLayout *contentsVlyr = new QVBoxLayout(contents);
00066 
00067     m_noDataSourceAvailableLabel = new QLabel(m_noDataSourceAvailableSingleText, contents);
00068     m_noDataSourceAvailableLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
00069     m_noDataSourceAvailableLabel->setMargin(2);
00070     m_noDataSourceAvailableLabel->setAlignment(Qt::WordBreak | Qt::AlignBottom | Qt::AlignLeft);
00071     contentsVlyr->addWidget(m_noDataSourceAvailableLabel);
00072 
00073     //-Widget's Data Source
00074     QHBoxLayout *hlyr = new QHBoxLayout(contentsVlyr);
00075 #if 0
00077 //  m_widgetDSLabel = new QLabel(i18n("Table Field, Query Field or Expression", "Source field or expression:"), this);
00078 #else
00079     m_widgetDSLabel = new QLabel(i18n("Table Field or Query Field", "Widget's data source:"), contents);
00080 #endif
00081     m_widgetDSLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
00082     m_widgetDSLabel->setMargin(2);
00083     m_widgetDSLabel->setMinimumHeight(IconSize(KIcon::Small)+4);
00084     m_widgetDSLabel->setAlignment(AlignLeft|AlignBottom);
00085     hlyr->addWidget(m_widgetDSLabel);
00086 
00087     m_clearWidgetDSButton = new KexiSmallToolButton(contents, QString::null, "clear_left", "clearWidgetDSButton");
00088     m_clearWidgetDSButton->setMinimumHeight(m_widgetDSLabel->minimumHeight());
00089     QToolTip::add(m_clearWidgetDSButton, i18n("Clear widget's data source"));
00090     hlyr->addWidget(m_clearWidgetDSButton);
00091     connect(m_clearWidgetDSButton, SIGNAL(clicked()), this, SLOT(clearWidgetDataSourceSelection()));
00092 
00093     m_sourceFieldCombo = new KexiFieldComboBox(contents, "sourceFieldCombo");
00094     m_widgetDSLabel->setBuddy(m_sourceFieldCombo);
00095     contentsVlyr->addWidget(m_sourceFieldCombo);
00096 
00097 /*  m_dataSourceSeparator = new QFrame(contents);
00098     m_dataSourceSeparator->setFrameShape(QFrame::HLine);
00099     m_dataSourceSeparator->setFrameShadow(QFrame::Sunken);
00100     contentsVlyr->addWidget(m_dataSourceSeparator);*/
00101 
00102     contentsVlyr->addSpacing(8);
00103 
00104     //- Form's Data Source
00105     hlyr = new QHBoxLayout(contentsVlyr);
00106     m_dataSourceLabel = new QLabel(i18n("Form's data source:"), contents);
00107     m_dataSourceLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
00108     m_dataSourceLabel->setMargin(2);
00109     m_dataSourceLabel->setMinimumHeight(IconSize(KIcon::Small)+4);
00110     m_dataSourceLabel->setAlignment(AlignLeft|AlignBottom);
00111     hlyr->addWidget(m_dataSourceLabel);
00112 
00113     m_gotoButton = new KexiSmallToolButton(contents, QString::null, "goto", "gotoButton");
00114     m_gotoButton->setMinimumHeight(m_dataSourceLabel->minimumHeight());
00115     QToolTip::add(m_gotoButton, i18n("Go to selected form's data source"));
00116     hlyr->addWidget(m_gotoButton);
00117     connect(m_gotoButton, SIGNAL(clicked()), this, SLOT(slotGotoSelected()));
00118 
00119     m_clearDSButton = new KexiSmallToolButton(contents, QString::null, "clear_left", "clearDSButton");
00120     m_clearDSButton->setMinimumHeight(m_dataSourceLabel->minimumHeight());
00121     QToolTip::add(m_clearDSButton, i18n("Clear form's data source"));
00122     hlyr->addWidget(m_clearDSButton);
00123     connect(m_clearDSButton, SIGNAL(clicked()), this, SLOT(clearDataSourceSelection()));
00124 
00125     m_dataSourceCombo = new KexiDataSourceComboBox(contents, "dataSourceCombo");
00126     m_dataSourceLabel->setBuddy(m_dataSourceCombo);
00127     contentsVlyr->addWidget(m_dataSourceCombo);
00128 
00129 #ifdef KEXI_NO_AUTOFIELD_WIDGET
00130     m_availableFieldsLabel = 0;
00131     m_addField = 0;
00132 //  m_fieldListView = 0;
00133     vlyr->addStretch();
00134 #else
00135     vlyr->addSpacing(fontMetrics().height());
00136 /*  QFrame *separator = new QFrame(this);
00137     separator->setFrameShape(QFrame::HLine);
00138     separator->setFrameShadow(QFrame::Sunken);
00139     vlyr->addWidget(separator);*/
00140 /*
00141     KPopupTitle *title = new KPopupTitle(this);
00142     title->setTitle(i18n("Inserting fields"));
00143     vlyr->addWidget(title);
00144     vlyr->addSpacing(4);*/
00145 
00146 
00147     //2. Inserting fields
00148     container = new KoProperty::GroupContainer(i18n("Inserting Fields"), this);
00149     vlyr->addWidget(container, 1);
00150 
00151     //helper info
00153     contents = new QWidget(container);
00154     container->setContents(contents);
00155     contentsVlyr = new QVBoxLayout(contents);
00156     hlyr = new QHBoxLayout(contentsVlyr);
00157     m_mousePointerLabel = new QLabel(contents);
00158     hlyr->addWidget(m_mousePointerLabel);
00159     m_mousePointerLabel->setPixmap( SmallIcon("mouse_pointer") );
00160     m_mousePointerLabel->setFixedWidth( m_mousePointerLabel->pixmap() ? m_mousePointerLabel->pixmap()->width() : 0);
00161     m_availableFieldsDescriptionLabel = new QLabel(
00162         i18n("Select fields from the list below and drag them onto a form or click the \"Insert\" button"), contents);
00163     m_availableFieldsDescriptionLabel->setAlignment( Qt::AlignAuto | Qt::WordBreak );
00164     hlyr->addWidget(m_availableFieldsDescriptionLabel);
00165 
00166     //Available Fields
00167     contentsVlyr->addSpacing(4);
00168     hlyr = new QHBoxLayout(contentsVlyr);
00169     m_availableFieldsLabel = new QLabel(i18n("Available fields:"), contents);
00170     m_availableFieldsLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
00171     m_availableFieldsLabel->setMargin(2);
00172     m_availableFieldsLabel->setMinimumHeight(IconSize(KIcon::Small));
00173     hlyr->addWidget(m_availableFieldsLabel);
00174 
00175     m_addField = new KexiSmallToolButton(contents, i18n("Insert selected field into form", "Insert"), 
00176         "add_field", "addFieldButton");
00177     m_addField->setMinimumHeight(m_availableFieldsLabel->minimumHeight());
00178 //  m_addField->setTextPosition(QToolButton::Right);
00179     m_addField->setFocusPolicy(StrongFocus);
00180     QToolTip::add(m_addField, i18n("Insert selected fields into form"));
00181     hlyr->addWidget(m_addField);
00182     connect(m_addField, SIGNAL(clicked()), this, SLOT(slotInsertSelectedFields()));
00183 
00184     m_fieldListView = new KexiFieldListView(contents, "fieldListView",
00185         KexiFieldListView::ShowDataTypes | KexiFieldListView::AllowMultiSelection );
00186     m_fieldListView->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding));
00187     m_availableFieldsLabel->setBuddy(m_fieldListView);
00188     contentsVlyr->addWidget(m_fieldListView, 1);
00189     connect(m_fieldListView, SIGNAL(selectionChanged()), this, SLOT(slotFieldListViewSelectionChanged()));
00190     connect(m_fieldListView, SIGNAL(fieldDoubleClicked(const QString&, const QString&, const QString&)),
00191         this, SLOT(slotFieldDoubleClicked(const QString&, const QString&, const QString&)));
00192 #endif
00193 
00194     vlyr->addStretch(1);
00195 
00196     connect(m_dataSourceCombo, SIGNAL(textChanged(const QString &)), this, SLOT(slotDataSourceTextChanged(const QString &)));
00197     connect(m_dataSourceCombo, SIGNAL(dataSourceChanged()), this, SLOT(slotDataSourceChanged()));
00198     connect(m_sourceFieldCombo, SIGNAL(selected()), this, SLOT(slotFieldSelected()));
00199 
00200     clearDataSourceSelection();
00201     slotFieldListViewSelectionChanged();
00202 }
00203 
00204 KexiDataSourcePage::~KexiDataSourcePage()
00205 {
00206 }
00207 
00208 void KexiDataSourcePage::setProject(KexiProject *prj)
00209 {
00210     m_sourceFieldCombo->setProject(prj);
00211     m_dataSourceCombo->setProject(prj);
00212 }
00213 
00214 void KexiDataSourcePage::clearDataSourceSelection(bool alsoClearComboBox)
00215 {
00216     if (m_insideClearDataSourceSelection)
00217         return;
00218     m_insideClearDataSourceSelection = true;
00219     if (alsoClearComboBox && !m_dataSourceCombo->selectedName().isEmpty())
00220         m_dataSourceCombo->setDataSource("", "");
00221 //  if (!m_dataSourceCombo->currentText().isEmpty()) {
00222 //      m_dataSourceCombo->setCurrentText("");
00223 //      emit m_dataSourceCombo->dataSourceSelected();
00224 //  }
00225     m_clearDSButton->setEnabled(false);
00226     m_gotoButton->setEnabled(false);
00227 #ifndef KEXI_NO_AUTOFIELD_WIDGET
00228     m_addField->setEnabled(false);
00229     m_fieldListView->clear();
00230 #endif
00231     m_insideClearDataSourceSelection = false;
00232 }
00233 
00234 void KexiDataSourcePage::clearWidgetDataSourceSelection()
00235 {
00236     if (!m_sourceFieldCombo->currentText().isEmpty()) {
00237         m_sourceFieldCombo->setCurrentText("");
00238         m_sourceFieldCombo->setFieldOrExpression(QString::null);
00239         slotFieldSelected();
00240     }
00241     m_clearWidgetDSButton->setEnabled(false);
00242 }
00243 
00244 void KexiDataSourcePage::slotGotoSelected()
00245 {
00246     QCString mime = m_dataSourceCombo->selectedMimeType().latin1();
00247     if (mime=="kexi/table" || mime=="kexi/query") {
00248         if (m_dataSourceCombo->isSelectionValid())
00249             emit jumpToObjectRequested(mime, m_dataSourceCombo->selectedName().latin1());
00250     }
00251 }
00252 
00253 void KexiDataSourcePage::slotInsertSelectedFields()
00254 {
00255 #ifndef KEXI_NO_AUTOFIELD_WIDGET
00256     QStringList selectedFieldNames(m_fieldListView->selectedFieldNames());
00257     if (selectedFieldNames.isEmpty())
00258         return;
00259 
00260     emit insertAutoFields(m_fieldListView->schema()->table() ? "kexi/table" : "kexi/query",
00261         m_fieldListView->schema()->name(), selectedFieldNames);
00262 #endif
00263 }
00264 
00265 void KexiDataSourcePage::slotFieldDoubleClicked(const QString& sourceMimeType, const QString& sourceName,
00266     const QString& fieldName)
00267 {
00268 #ifndef KEXI_NO_AUTOFIELD_WIDGET
00269     QStringList selectedFields;
00270     selectedFields.append(fieldName);
00271     emit insertAutoFields(sourceMimeType, sourceName, selectedFields);
00272 #endif
00273 }
00274 
00275 void KexiDataSourcePage::slotDataSourceTextChanged(const QString & string)
00276 {
00277     Q_UNUSED(string);
00278     const bool enable = m_dataSourceCombo->isSelectionValid(); 
00279     if (!enable) {
00280         clearDataSourceSelection( m_dataSourceCombo->selectedName().isEmpty()/*alsoClearComboBox*/ );
00281     }
00282     updateSourceFieldWidgetsAvailability();
00283 /*#ifndef KEXI_NO_AUTOFIELD_WIDGET
00284     m_fieldListView->setEnabled(enable);
00285 //  m_addField->setEnabled(enable);
00286     m_availableFieldsLabel->setEnabled(enable);
00287 #endif*/
00288 }
00289 
00290 void KexiDataSourcePage::slotDataSourceChanged()
00291 {
00292     if (!m_dataSourceCombo->project())
00293         return;
00294     QCString mime = m_dataSourceCombo->selectedMimeType().latin1();
00295     bool dataSourceFound = false;
00296     QCString name = m_dataSourceCombo->selectedName().latin1();
00297     if ((mime=="kexi/table" || mime=="kexi/query") && m_dataSourceCombo->isSelectionValid()) {
00298         KexiDB::TableOrQuerySchema *tableOrQuery = new KexiDB::TableOrQuerySchema(
00299             m_dataSourceCombo->project()->dbConnection(), name, mime=="kexi/table");
00300         if (tableOrQuery->table() || tableOrQuery->query()) {
00301 #ifdef KEXI_NO_AUTOFIELD_WIDGET
00302             m_tableOrQuerySchema = tableOrQuery;
00303 #else
00304             m_fieldListView->setSchema( tableOrQuery );
00305 #endif
00306             dataSourceFound = true;
00307             m_sourceFieldCombo->setTableOrQuery(name, mime=="kexi/table");
00308         }
00309         else {
00310             delete tableOrQuery;
00311         }
00312     }
00313     if (!dataSourceFound) {
00314         m_sourceFieldCombo->setTableOrQuery("", true);
00315     }
00316     //if (m_sourceFieldCombo->hasFocus())
00317 //      m_dataSourceCombo->setFocus();
00318     m_clearDSButton->setEnabled(dataSourceFound);
00319     m_gotoButton->setEnabled(dataSourceFound);
00320     if (dataSourceFound) {
00321         slotFieldListViewSelectionChanged();
00322     } else {
00323 #ifndef KEXI_NO_AUTOFIELD_WIDGET
00324         m_addField->setEnabled(false);
00325 #endif
00326     }
00327     updateSourceFieldWidgetsAvailability();
00328     emit formDataSourceChanged(mime, name);
00329 }
00330 
00331 void KexiDataSourcePage::slotFieldSelected()
00332 {
00333     KexiDB::Field::Type dataType = KexiDB::Field::InvalidType;
00334 #ifdef KEXI_NO_AUTOFIELD_WIDGET
00335     KexiDB::Field *field = m_tableOrQuerySchema->field( m_sourceFieldCombo->fieldOrExpression() ); //temp
00336 #else
00338     KexiDB::Field *field = m_fieldListView->schema()->field( m_sourceFieldCombo->fieldOrExpression() );
00339 #endif
00340     if (field)
00341         dataType = field->type();
00342 
00343     m_clearWidgetDSButton->setEnabled( !m_sourceFieldCombo->fieldOrExpression().isEmpty() );
00344 
00345     emit dataSourceFieldOrExpressionChanged(
00346         m_sourceFieldCombo->fieldOrExpression(),
00347         m_sourceFieldCombo->fieldOrExpressionCaption(),
00348         dataType
00349     );
00350 }
00351 
00352 void KexiDataSourcePage::setDataSource(const QCString& mimeType, const QCString& name)
00353 {
00354     m_dataSourceCombo->setDataSource(mimeType, name);
00355 }
00356 
00357 void KexiDataSourcePage::assignPropertySet(KoProperty::Set* propertySet)
00358 {
00359     QCString objectName;
00360     if (propertySet && propertySet->contains("name"))
00361         objectName = (*propertySet)["name"].value().toCString();
00362     if (!objectName.isEmpty() && objectName == m_currentObjectName)
00363         return; //the same object
00364     m_currentObjectName = objectName;
00365 
00366     QCString objectClassName;
00367     if (propertySet && propertySet->contains("this:className"))
00368         objectClassName = (*propertySet)["this:className"].value().toCString();
00369 /*moved if (propertySet) {
00370         QCString iconName;
00371         QString objectClassString;
00372         if (propertySet->contains("this:iconName"))
00373             iconName = (*propertySet)["this:iconName"].value().toCString();
00374         if (propertySet->contains("this:classString"))
00375             objectClassString = (*propertySet)["this:classString"].value().toString();
00376         m_objectInfoLabel->setObjectName(objectName);
00377         m_objectInfoLabel->setObjectClassIcon(iconName);
00378         m_objectInfoLabel->setObjectClassName(objectClassString);
00379         if (propertySet->contains("this:className"))
00380             objectClassName = (*propertySet)["this:className"].value().toCString();
00381     }*/
00382     KexiPropertyEditorView::updateInfoLabelForPropertySet(
00383         m_objectInfoLabel, propertySet);
00384 
00385     const bool isForm = objectClassName=="KexiDBForm";
00386 //  kdDebug() << "objectClassName=" << objectClassName << endl;
00387 //  {
00388 /*      //this is top level form's surface: data source means table or query
00389         QCString dataSourceMimeType, dataSource;
00390         if (buffer->hasProperty("dataSourceMimeType"))
00391             dataSourceMimeType = (*buffer)["dataSourceMimeType"].value().toCString();
00392         if (buffer->hasProperty("dataSource"))
00393             dataSource = (*buffer)["dataSource"].value().toCString();
00394         m_dataSourceCombo->setDataSource(dataSourceMimeType, dataSource);*/
00395 //  }
00396 //  else {
00397 
00398     const bool multipleSelection = objectClassName=="special:multiple";
00399     const bool hasDataSourceProperty = propertySet && propertySet->contains("dataSource") && !multipleSelection;
00400 
00401     if (!isForm) {
00402         //this is a widget
00403         QCString dataSource;
00404         if (hasDataSourceProperty) {
00405             if (propertySet)
00406                 dataSource = (*propertySet)["dataSource"].value().toCString();
00407             m_noDataSourceAvailableLabel->hide();
00408             m_sourceFieldCombo->setFieldOrExpression(dataSource);
00409             m_sourceFieldCombo->setEnabled(true);
00410             m_clearWidgetDSButton->setEnabled(!m_sourceFieldCombo->currentText().isEmpty());
00411             m_widgetDSLabel->show();
00412             m_clearWidgetDSButton->show();
00413             m_sourceFieldCombo->show();
00414 //          m_dataSourceSeparator->hide();
00415             updateSourceFieldWidgetsAvailability();
00416         }
00417     }
00418 
00419     if (isForm) {
00420         m_noDataSourceAvailableLabel->hide();
00421 //      m_dataSourceSeparator->hide();
00422     }
00423     else if (!hasDataSourceProperty) {
00424         if (multipleSelection)
00425             m_noDataSourceAvailableLabel->setText(m_noDataSourceAvailableMultiText);
00426         else
00427             m_noDataSourceAvailableLabel->setText(m_noDataSourceAvailableSingleText);
00428         m_noDataSourceAvailableLabel->show();
00429 //      m_dataSourceSeparator->show();
00430         //make 'No data source could be assigned' label's height the same as the 'source field' combo+label
00431         m_noDataSourceAvailableLabel->setMinimumHeight(m_widgetDSLabel->height()
00432             + m_sourceFieldCombo->height()/*-m_dataSourceSeparator->height()*/);
00433         m_sourceFieldCombo->setCurrentText("");
00434     }
00435 
00436     if (isForm || !hasDataSourceProperty) {
00437         //no source field can be set
00438         m_widgetDSLabel->hide();
00439         m_clearWidgetDSButton->hide();
00440         m_sourceFieldCombo->hide();
00441     }
00442 }
00443 
00444 void KexiDataSourcePage::slotFieldListViewSelectionChanged()
00445 {
00446 #ifndef KEXI_NO_AUTOFIELD_WIDGET
00447     //update "add field" button's state
00448     for (QListViewItemIterator it(m_fieldListView); it.current(); ++it) {
00449         if (it.current()->isSelected()) {
00450             m_addField->setEnabled(true);
00451             return;
00452         }
00453     }
00454     m_addField->setEnabled(false);
00455 #endif
00456 }
00457 
00458 void KexiDataSourcePage::updateSourceFieldWidgetsAvailability()
00459 {
00460     const bool hasDataSource = m_dataSourceCombo->isSelectionValid(); 
00461     m_sourceFieldCombo->setEnabled( hasDataSource );
00462     m_widgetDSLabel->setEnabled( hasDataSource );
00463 #ifndef KEXI_NO_AUTOFIELD_WIDGET
00464     m_fieldListView->setEnabled( hasDataSource );
00465     m_availableFieldsLabel->setEnabled( hasDataSource );
00466     m_mousePointerLabel->setEnabled( hasDataSource );
00467     m_availableFieldsDescriptionLabel->setEnabled( hasDataSource );
00468 #endif
00469 }
00470 
00471 #include "kexidatasourcepage.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys