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 
00032 #include <widget/kexipropertyeditorview.h>
00033 #include <widget/kexidatasourcecombobox.h>
00034 #include <widget/kexifieldlistview.h>
00035 #include <widget/kexifieldcombobox.h>
00036 #include <kexidb/connection.h>
00037 #include <kexiproject.h>
00038 
00039 #include <formeditor/commands.h>
00040 
00041 #include <koproperty/set.h>
00042 #include <koproperty/property.h>
00043 
00044 KexiDataSourcePage::KexiDataSourcePage(QWidget *parent, const char *name)
00045  : QWidget(parent, name)
00046  , m_insideClearDataSourceSelection(false)
00047 {
00048     QVBoxLayout *vlyr = new QVBoxLayout(this);
00049     m_objectInfoLabel = new KexiObjectInfoLabel(this, "KexiObjectInfoLabel");
00050     vlyr->addWidget(m_objectInfoLabel);
00051 
00052     m_noDataSourceAvailableSingleText = i18n("No data source could be assigned for this widget.");
00053     m_noDataSourceAvailableMultiText = i18n("No data source could be assigned for multiple widgets.");
00054     m_noDataSourceAvailableLabel = new QLabel(m_noDataSourceAvailableSingleText, this);
00055     m_noDataSourceAvailableLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
00056     m_noDataSourceAvailableLabel->setMargin(2);
00057     m_noDataSourceAvailableLabel->setAlignment(Qt::WordBreak | Qt::AlignBottom | Qt::AlignLeft);
00058     vlyr->addWidget(m_noDataSourceAvailableLabel);
00059 
00060     //Widget's Data Source
00061     QHBoxLayout *hlyr = new QHBoxLayout(vlyr);
00062 #if 0
00063 
00064 //  m_widgetDSLabel = new QLabel(i18n("Table Field, Query Field or Expression", "Source field or expression:"), this);
00065 #else
00066     m_widgetDSLabel = new QLabel(i18n("Table Field or Query Field", "Source field:"), this);
00067 #endif
00068     m_widgetDSLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
00069     m_widgetDSLabel->setMargin(2);
00070     m_widgetDSLabel->setMinimumHeight(IconSize(KIcon::Small)+4);
00071     m_widgetDSLabel->setAlignment(AlignLeft|AlignBottom);
00072     hlyr->addWidget(m_widgetDSLabel);
00073 
00074     m_clearWidgetDSButton = new QToolButton(this, "clearWidgetDSButton");
00075     m_clearWidgetDSButton->setIconSet(SmallIconSet("clear_left"));
00076     m_clearWidgetDSButton->setMinimumHeight(m_widgetDSLabel->minimumHeight());
00077     m_clearWidgetDSButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
00078     m_clearWidgetDSButton->setAutoRaise(true);
00079     m_clearWidgetDSButton->setPaletteBackgroundColor(palette().active().background());
00080     QToolTip::add(m_clearWidgetDSButton, i18n("Clear widget's data source"));
00081     hlyr->addWidget(m_clearWidgetDSButton);
00082     connect(m_clearWidgetDSButton, SIGNAL(clicked()), this, SLOT(clearWidgetDataSourceSelection()));
00083 
00084     m_sourceFieldCombo = new KexiFieldComboBox(this, "sourceFieldCombo");
00085     vlyr->addWidget(m_sourceFieldCombo);
00086 
00087     vlyr->addSpacing(8);
00088 
00089     m_dataSourceSeparator = new QFrame(this);
00090     m_dataSourceSeparator->setFrameShape(QFrame::HLine);
00091     m_dataSourceSeparator->setFrameShadow(QFrame::Sunken);
00092     vlyr->addWidget(m_dataSourceSeparator);
00093 
00094     //Form's Data Source
00095     hlyr = new QHBoxLayout(vlyr);
00096     m_dataSourceLabel = new QLabel(i18n("Form's data source:"), this);
00097     m_dataSourceLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
00098     m_dataSourceLabel->setMargin(2);
00099     m_dataSourceLabel->setMinimumHeight(IconSize(KIcon::Small)+4);
00100     m_dataSourceLabel->setAlignment(AlignLeft|AlignBottom);
00101     hlyr->addWidget(m_dataSourceLabel);
00102 
00103     m_gotoButton = new QToolButton(this, "gotoButton");
00104     m_gotoButton->setIconSet(SmallIconSet("goto"));
00105     m_gotoButton->setMinimumHeight(m_dataSourceLabel->minimumHeight());
00106     m_gotoButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
00107     m_gotoButton->setAutoRaise(true);
00108     m_gotoButton->setPaletteBackgroundColor(palette().active().background());
00109     QToolTip::add(m_gotoButton, i18n("Go to selected data source"));
00110     hlyr->addWidget(m_gotoButton);
00111     connect(m_gotoButton, SIGNAL(clicked()), this, SLOT(slotGotoSelected()));
00112 
00113     m_clearDSButton = new QToolButton(this, "clearDSButton");
00114     m_clearDSButton->setIconSet(SmallIconSet("clear_left"));
00115     m_clearDSButton->setMinimumHeight(m_dataSourceLabel->minimumHeight());
00116     m_clearDSButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
00117     m_clearDSButton->setAutoRaise(true);
00118     m_clearDSButton->setPaletteBackgroundColor(palette().active().background());
00119     QToolTip::add(m_clearDSButton, i18n("Clear data source"));
00120     hlyr->addWidget(m_clearDSButton);
00121     connect(m_clearDSButton, SIGNAL(clicked()), this, SLOT(clearDataSourceSelection()));
00122     
00123     m_dataSourceCombo = new KexiDataSourceComboBox(this, "dataSourceCombo");
00124     m_dataSourceLabel->setBuddy(m_dataSourceCombo);
00125     vlyr->addWidget(m_dataSourceCombo);
00126 
00127 #ifdef KEXI_NO_AUTOFIELD_WIDGET
00128     m_availableFieldsLabel = 0;
00129     m_addField = 0;
00130 //  m_fieldListView = 0;
00131     vlyr->addStretch();
00132 #else
00133     vlyr->addSpacing(8);
00134     QFrame *separator = new QFrame(this);
00135     separator->setFrameShape(QFrame::HLine);
00136     separator->setFrameShadow(QFrame::Sunken);
00137     vlyr->addWidget(separator);
00138 
00139     //helper info
00141     hlyr = new QHBoxLayout(vlyr);
00142     m_mousePointerLabel = new QLabel(this);
00143     hlyr->addWidget(m_mousePointerLabel);
00144     m_mousePointerLabel->setPixmap( SmallIcon("mouse_pointer") );
00145     m_mousePointerLabel->setFixedWidth( m_mousePointerLabel->pixmap() ? m_mousePointerLabel->pixmap()->width() : 0);
00146     m_availableFieldsDescriptionLabel = new QLabel(i18n("Select fields from the list below and drag them onto a form or click the \"Insert\" button"), this);
00147     m_availableFieldsDescriptionLabel->setAlignment( Qt::AlignAuto | Qt::WordBreak );
00148     hlyr->addWidget(m_availableFieldsDescriptionLabel);
00149 
00150     //Available Fields
00151     vlyr->addSpacing(4);
00152     hlyr = new QHBoxLayout(vlyr);
00153     m_availableFieldsLabel = new QLabel(i18n("Available fields:"), this);
00154     m_availableFieldsLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
00155     m_availableFieldsLabel->setMargin(2);
00156     m_availableFieldsLabel->setMinimumHeight(IconSize(KIcon::Small));
00157     hlyr->addWidget(m_availableFieldsLabel);
00158 
00159     m_addField = new QToolButton(this, "addFieldButton");
00160     m_addField->setUsesTextLabel(true);
00161     m_addField->setTextPosition(QToolButton::Right);
00162     m_addField->setTextLabel(i18n("Insert selected field into form", "Insert"));
00163     m_addField->setIconSet(SmallIconSet("add_field"));
00164     m_addField->setMinimumHeight(m_availableFieldsLabel->minimumHeight());
00165     m_addField->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
00166     m_addField->setAutoRaise(true);
00167     m_addField->setPaletteBackgroundColor(palette().active().background());
00168     QToolTip::add(m_addField, i18n("Insert selected fields into form"));
00169     hlyr->addWidget(m_addField);
00170     connect(m_addField, SIGNAL(clicked()), this, SLOT(slotInsertSelectedFields()));
00171 
00172     m_fieldListView = new KexiFieldListView(this, "fieldListView", 
00173         KexiFieldListView::ShowDataTypes | KexiFieldListView::AllowMultiSelection );
00174 //  m_fieldListView->header()->show();
00175     m_fieldListView->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding));
00176     vlyr->addWidget(m_fieldListView);
00177     connect(m_fieldListView, SIGNAL(selectionChanged()), this, SLOT(slotFieldListViewSelectionChanged()));
00178 #endif
00179 
00180     connect(m_dataSourceCombo, SIGNAL(textChanged(const QString &)), this, SLOT(slotDataSourceTextChanged(const QString &)));
00181     connect(m_dataSourceCombo, SIGNAL(dataSourceSelected()), this, SLOT(slotDataSourceSelected()));
00182     connect(m_sourceFieldCombo, SIGNAL(selected()), this, SLOT(slotFieldSelected()));
00183 
00184     clearDataSourceSelection();
00185     slotFieldListViewSelectionChanged();
00186 }
00187 
00188 KexiDataSourcePage::~KexiDataSourcePage()
00189 {
00190 }
00191 
00192 void KexiDataSourcePage::setProject(KexiProject *prj)
00193 {
00194     m_sourceFieldCombo->setProject(prj);
00195     m_dataSourceCombo->setProject(prj);
00196 }
00197 
00198 void KexiDataSourcePage::clearDataSourceSelection()
00199 {
00200     if (m_insideClearDataSourceSelection)
00201         return;
00202     m_insideClearDataSourceSelection = true;
00203     if (!m_dataSourceCombo->selectedName().isEmpty())
00204         m_dataSourceCombo->setDataSource("", ""); 
00205 //  if (!m_dataSourceCombo->currentText().isEmpty()) {
00206 //      m_dataSourceCombo->setCurrentText("");
00207 //      emit m_dataSourceCombo->dataSourceSelected();
00208 //  }
00209     m_clearDSButton->setEnabled(false);
00210     m_gotoButton->setEnabled(false);
00211 #ifndef KEXI_NO_AUTOFIELD_WIDGET
00212     m_addField->setEnabled(false);
00213     m_fieldListView->clear();
00214 #endif
00215     m_insideClearDataSourceSelection = false;
00216 }
00217 
00218 void KexiDataSourcePage::clearWidgetDataSourceSelection()
00219 {
00220     if (!m_sourceFieldCombo->currentText().isEmpty())
00221         m_sourceFieldCombo->setCurrentText("");
00222     m_clearWidgetDSButton->setEnabled(false);
00223 }
00224 
00225 void KexiDataSourcePage::slotGotoSelected()
00226 {
00227     QCString mime = m_dataSourceCombo->selectedMimeType();
00228     if (mime=="kexi/table" || mime=="kexi/query") {
00229         QCString name = m_dataSourceCombo->selectedName();
00230         if (name.isEmpty())
00231             return;
00232         emit jumpToObjectRequested(mime, name);
00233     }
00234 }
00235 
00236 void KexiDataSourcePage::slotInsertSelectedFields()
00237 {
00238 #ifndef KEXI_NO_AUTOFIELD_WIDGET
00239     if (!m_fieldListView->schema())
00240         return;
00241     QStringList selectedFields;
00242     for (QListViewItemIterator it(m_fieldListView); it.current(); ++it) {
00243         if (it.current()->isSelected()) {
00245             selectedFields.append(it.current()->text(0));
00246         }
00247     }
00248     if (selectedFields.isEmpty())
00249         return;
00250 
00251     emit insertAutoFields(m_fieldListView->schema()->table() ? "kexi/table" : "kexi/query", 
00252         m_fieldListView->schema()->name(), selectedFields);
00253 #endif
00254 }
00255 
00256 void KexiDataSourcePage::slotDataSourceTextChanged(const QString & string)
00257 {
00258     const bool enable = !string.isEmpty();
00259     if (!enable) {
00260         clearDataSourceSelection();
00261     }
00262     updateSourceFieldWidgetsAvailability();
00263 /*#ifndef KEXI_NO_AUTOFIELD_WIDGET
00264     m_fieldListView->setEnabled(enable);
00265 //  m_addField->setEnabled(enable);
00266     m_availableFieldsLabel->setEnabled(enable);
00267 #endif*/
00268 }
00269 
00270 void KexiDataSourcePage::slotDataSourceSelected()
00271 {
00272     if (!m_dataSourceCombo->project())
00273         return;
00274     QCString mime = m_dataSourceCombo->selectedMimeType();
00275     bool dataSourceFound = false;
00276     QCString name = m_dataSourceCombo->selectedName();
00277     if ((mime=="kexi/table" || mime=="kexi/query") && !name.isEmpty()) {
00278         KexiDB::TableOrQuerySchema *tableOrQuery = new KexiDB::TableOrQuerySchema(
00279             m_dataSourceCombo->project()->dbConnection(), name, mime=="kexi/table");
00280         if (tableOrQuery->table() || tableOrQuery->query()) {
00281 #ifdef KEXI_NO_AUTOFIELD_WIDGET
00282             m_tableOrQuerySchema = tableOrQuery;
00283 #else
00284             m_fieldListView->setSchema( tableOrQuery );
00285 #endif
00286             dataSourceFound = true;
00287             m_sourceFieldCombo->setTableOrQuery(name, mime=="kexi/table");
00288         }
00289         else {
00290             delete tableOrQuery;
00291         }
00292     }
00293     if (!dataSourceFound) {
00294         m_sourceFieldCombo->setTableOrQuery("", true);
00295     }
00296     if (m_sourceFieldCombo->hasFocus())
00297         m_dataSourceCombo->setFocus();
00298     m_clearDSButton->setEnabled(dataSourceFound);
00299     m_gotoButton->setEnabled(dataSourceFound);
00300     if (dataSourceFound) {
00301         slotFieldListViewSelectionChanged();
00302     } else {
00303 #ifndef KEXI_NO_AUTOFIELD_WIDGET
00304         m_addField->setEnabled(false);
00305 #endif
00306     }
00307     updateSourceFieldWidgetsAvailability();
00308     emit formDataSourceChanged(mime, name);
00309 }
00310 
00311 void KexiDataSourcePage::slotFieldSelected()
00312 {
00313     KexiDB::Field::Type dataType = KexiDB::Field::InvalidType;
00314 #ifdef KEXI_NO_AUTOFIELD_WIDGET
00315     KexiDB::Field *field = m_tableOrQuerySchema->field( m_sourceFieldCombo->fieldOrExpression() ); //temp
00316 #else
00317 
00318     KexiDB::Field *field = m_fieldListView->schema()->field( m_sourceFieldCombo->fieldOrExpression() );
00319 #endif
00320     if (field)
00321         dataType = field->type();
00322     
00323     emit dataSourceFieldOrExpressionChanged(
00324         m_sourceFieldCombo->fieldOrExpression(), 
00325         m_sourceFieldCombo->fieldOrExpressionCaption(), 
00326         dataType
00327     );
00328 }
00329 
00330 void KexiDataSourcePage::setDataSource(const QCString& mimeType, const QCString& name)
00331 {
00332     m_dataSourceCombo->setDataSource(mimeType, name);
00333 }
00334 
00335 void KexiDataSourcePage::assignPropertySet(KoProperty::Set* propertySet)
00336 {
00337     QCString objectClassName;
00338     if (propertySet) {
00339         QCString objectName, iconName;
00340         QString objectClassString;
00341         if (propertySet->contains("name"))
00342             objectName = (*propertySet)["name"].value().toCString();
00343         if (propertySet->contains("this:iconName"))
00344             iconName = (*propertySet)["this:iconName"].value().toCString();
00345         if (propertySet->contains("this:classString"))
00346             objectClassString = (*propertySet)["this:classString"].value().toString();
00347         m_objectInfoLabel->setObjectName(objectName);
00348         m_objectInfoLabel->setObjectClassIcon(iconName);
00349         m_objectInfoLabel->setObjectClassName(objectClassString);
00350         if (propertySet->contains("this:className"))
00351             objectClassName = (*propertySet)["this:className"].value().toCString();
00352     }
00353 
00354 
00355     const bool isForm = objectClassName=="KexiDBForm";
00356 //  kdDebug() << "objectClassName=" << objectClassName << endl;
00357 //  {
00358 /*      //this is top level form's surface: data source means table or query
00359         QCString dataSourceMimeType, dataSource;
00360         if (buffer->hasProperty("dataSourceMimeType"))
00361             dataSourceMimeType = (*buffer)["dataSourceMimeType"].value().toCString();
00362         if (buffer->hasProperty("dataSource"))
00363             dataSource = (*buffer)["dataSource"].value().toCString();
00364         m_dataSourceCombo->setDataSource(dataSourceMimeType, dataSource);*/
00365 //  }
00366 //  else {
00367 
00368     const bool hasDataSourceProperty = propertySet && propertySet->contains("dataSource");
00369 
00370     if (!isForm) {
00371         //this is a widget
00372         QCString dataSource;
00373         if (hasDataSourceProperty) {
00374             if (propertySet)
00375                 dataSource = (*propertySet)["dataSource"].value().toCString();
00376             m_noDataSourceAvailableLabel->hide();
00377             m_sourceFieldCombo->setFieldOrExpression(dataSource);
00378             m_sourceFieldCombo->setEnabled(true);
00379             m_clearWidgetDSButton->setEnabled(!m_sourceFieldCombo->currentText().isEmpty());
00380             m_widgetDSLabel->show();
00381             m_clearWidgetDSButton->show();
00382             m_sourceFieldCombo->show();
00383             m_dataSourceSeparator->hide();
00384             updateSourceFieldWidgetsAvailability();
00385         }
00386     }
00387 
00388     if (isForm) {
00389         m_noDataSourceAvailableLabel->hide();
00390         m_dataSourceSeparator->hide();
00391     }
00392     else if (!hasDataSourceProperty) {
00393         if (objectClassName=="special:multiple")
00394             m_noDataSourceAvailableLabel->setText(m_noDataSourceAvailableMultiText);
00395         else
00396             m_noDataSourceAvailableLabel->setText(m_noDataSourceAvailableSingleText);
00397         m_noDataSourceAvailableLabel->show();
00398         m_dataSourceSeparator->show();
00399         //make 'No data source could be assigned' label's height the same as the 'source field' combo+label
00400         m_noDataSourceAvailableLabel->setMinimumHeight(m_widgetDSLabel->height()
00401             + m_sourceFieldCombo->height()-m_dataSourceSeparator->height());
00402         m_sourceFieldCombo->setCurrentText("");
00403     }
00404 
00405     if (isForm || !hasDataSourceProperty) {
00406         //no source field can be set
00407         m_widgetDSLabel->hide();
00408         m_clearWidgetDSButton->hide();
00409         m_sourceFieldCombo->hide();
00410     }
00411 }
00412 
00413 void KexiDataSourcePage::slotFieldListViewSelectionChanged()
00414 {
00415 #ifndef KEXI_NO_AUTOFIELD_WIDGET
00416     //update "add field" button's state
00417     for (QListViewItemIterator it(m_fieldListView); it.current(); ++it) {
00418         if (it.current()->isSelected()) {
00419             m_addField->setEnabled(true);
00420             return;
00421         }
00422     }
00423     m_addField->setEnabled(false);
00424 #endif
00425 }
00426 
00427 void KexiDataSourcePage::updateSourceFieldWidgetsAvailability()
00428 {
00429     const bool hasDataSource = !m_dataSourceCombo->selectedName().isEmpty();
00430     m_sourceFieldCombo->setEnabled( hasDataSource );
00431     m_widgetDSLabel->setEnabled( hasDataSource );
00432 #ifndef KEXI_NO_AUTOFIELD_WIDGET
00433     m_fieldListView->setEnabled( hasDataSource );
00434     m_availableFieldsLabel->setEnabled( hasDataSource );
00435     m_mousePointerLabel->setEnabled( hasDataSource );
00436     m_availableFieldsDescriptionLabel->setEnabled( hasDataSource );
00437 #endif
00438 }
00439 
00440 #include "kexidatasourcepage.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys