kexi

kexidatasourcepage.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2005 Jaroslaw Staniek <js@iidea.pl>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18*/
19
20#include "kexidatasourcepage.h"
21
22#include <tqlabel.h>
23#include <tqlayout.h>
24#include <tqtooltip.h>
25#include <tqheader.h>
26
27#include <kiconloader.h>
28#include <tdelocale.h>
29#include <tdetoolbarbutton.h>
30#include <kdebug.h>
31#include <tdepopupmenu.h>
32
33#include <widget/kexipropertyeditorview.h>
34#include <widget/kexidatasourcecombobox.h>
35#include <widget/kexifieldlistview.h>
36#include <widget/kexifieldcombobox.h>
37#include <widget/kexismalltoolbutton.h>
38#include <kexidb/connection.h>
39#include <kexiproject.h>
40
41#include <formeditor/commands.h>
42
43#include <koproperty/property.h>
44#include <koproperty/utils.h>
45
46KexiDataSourcePage::KexiDataSourcePage(TQWidget *parent, const char *name)
47 : TQWidget(parent, name)
48 , m_insideClearDataSourceSelection(false)
49{
50 TQVBoxLayout *vlyr = new TQVBoxLayout(this);
51 m_objectInfoLabel = new KexiObjectInfoLabel(this, "KexiObjectInfoLabel");
52 vlyr->addWidget(m_objectInfoLabel);
53
54 m_noDataSourceAvailableSingleText = i18n("No data source could be assigned for this widget.");
55 m_noDataSourceAvailableMultiText = i18n("No data source could be assigned for multiple widgets.");
56
57 vlyr->addSpacing(8);
58
59 //Section 1: Form's/Widget's Data Source
60 KoProperty::GroupContainer *container = new KoProperty::GroupContainer(i18n("Data Source"), this);
61 vlyr->addWidget(container);
62
63 TQWidget *contents = new TQWidget(container);
64 container->setContents(contents);
65 TQVBoxLayout *contentsVlyr = new TQVBoxLayout(contents);
66
67 m_noDataSourceAvailableLabel = new TQLabel(m_noDataSourceAvailableSingleText, contents);
68 m_noDataSourceAvailableLabel->setSizePolicy(TQSizePolicy::Preferred, TQSizePolicy::Fixed);
69 m_noDataSourceAvailableLabel->setMargin(2);
70 m_noDataSourceAvailableLabel->setAlignment(TQt::WordBreak | TQt::AlignBottom | TQt::AlignLeft);
71 contentsVlyr->addWidget(m_noDataSourceAvailableLabel);
72
73 //-Widget's Data Source
74 TQHBoxLayout *hlyr = new TQHBoxLayout(contentsVlyr);
75#if 0
77// m_widgetDSLabel = new TQLabel(i18n("Table Field, Query Field or Expression", "Source field or expression:"), this);
78#else
79 m_widgetDSLabel = new TQLabel(i18n("Table Field or Query Field", "Widget's data source:"), contents);
80#endif
81 m_widgetDSLabel->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Fixed);
82 m_widgetDSLabel->setMargin(2);
83 m_widgetDSLabel->setMinimumHeight(IconSize(TDEIcon::Small)+4);
84 m_widgetDSLabel->setAlignment(AlignLeft|AlignBottom);
85 hlyr->addWidget(m_widgetDSLabel);
86
87 m_clearWidgetDSButton = new KexiSmallToolButton(contents, TQString(), "clear_left", "clearWidgetDSButton");
88 m_clearWidgetDSButton->setMinimumHeight(m_widgetDSLabel->minimumHeight());
89 TQToolTip::add(m_clearWidgetDSButton, i18n("Clear widget's data source"));
90 hlyr->addWidget(m_clearWidgetDSButton);
91 connect(m_clearWidgetDSButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(clearWidgetDataSourceSelection()));
92
93 m_sourceFieldCombo = new KexiFieldComboBox(contents, "sourceFieldCombo");
94 m_widgetDSLabel->setBuddy(m_sourceFieldCombo);
95 contentsVlyr->addWidget(m_sourceFieldCombo);
96
97/* m_dataSourceSeparator = new TQFrame(contents);
98 m_dataSourceSeparator->setFrameShape(TQFrame::HLine);
99 m_dataSourceSeparator->setFrameShadow(TQFrame::Sunken);
100 contentsVlyr->addWidget(m_dataSourceSeparator);*/
101
102 contentsVlyr->addSpacing(8);
103
104 //- Form's Data Source
105 hlyr = new TQHBoxLayout(contentsVlyr);
106 m_dataSourceLabel = new TQLabel(i18n("Form's data source:"), contents);
107 m_dataSourceLabel->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Fixed);
108 m_dataSourceLabel->setMargin(2);
109 m_dataSourceLabel->setMinimumHeight(IconSize(TDEIcon::Small)+4);
110 m_dataSourceLabel->setAlignment(AlignLeft|AlignBottom);
111 hlyr->addWidget(m_dataSourceLabel);
112
113 m_gotoButton = new KexiSmallToolButton(contents, TQString(), "goto", "gotoButton");
114 m_gotoButton->setMinimumHeight(m_dataSourceLabel->minimumHeight());
115 TQToolTip::add(m_gotoButton, i18n("Go to selected form's data source"));
116 hlyr->addWidget(m_gotoButton);
117 connect(m_gotoButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotGotoSelected()));
118
119 m_clearDSButton = new KexiSmallToolButton(contents, TQString(), "clear_left", "clearDSButton");
120 m_clearDSButton->setMinimumHeight(m_dataSourceLabel->minimumHeight());
121 TQToolTip::add(m_clearDSButton, i18n("Clear form's data source"));
122 hlyr->addWidget(m_clearDSButton);
123 connect(m_clearDSButton, TQ_SIGNAL(clicked()), this, TQ_SLOT(clearDataSourceSelection()));
124
125 m_dataSourceCombo = new KexiDataSourceComboBox(contents, "dataSourceCombo");
126 m_dataSourceLabel->setBuddy(m_dataSourceCombo);
127 contentsVlyr->addWidget(m_dataSourceCombo);
128
129#ifdef KEXI_NO_AUTOFIELD_WIDGET
130 m_availableFieldsLabel = 0;
131 m_addField = 0;
132// m_fieldListView = 0;
133 vlyr->addStretch();
134#else
135 vlyr->addSpacing(fontMetrics().height());
136/* TQFrame *separator = new TQFrame(this);
137 separator->setFrameShape(TQFrame::HLine);
138 separator->setFrameShadow(TQFrame::Sunken);
139 vlyr->addWidget(separator);*/
140/*
141 TDEPopupTitle *title = new TDEPopupTitle(this);
142 title->setTitle(i18n("Inserting fields"));
143 vlyr->addWidget(title);
144 vlyr->addSpacing(4);*/
145
146
147 //2. Inserting fields
148 container = new KoProperty::GroupContainer(i18n("Inserting Fields"), this);
149 vlyr->addWidget(container, 1);
150
151 //helper info
153 contents = new TQWidget(container);
154 container->setContents(contents);
155 contentsVlyr = new TQVBoxLayout(contents);
156 hlyr = new TQHBoxLayout(contentsVlyr);
157 m_mousePointerLabel = new TQLabel(contents);
158 hlyr->addWidget(m_mousePointerLabel);
159 m_mousePointerLabel->setPixmap( SmallIcon("mouse_pointer") );
160 m_mousePointerLabel->setFixedWidth( m_mousePointerLabel->pixmap() ? m_mousePointerLabel->pixmap()->width() : 0);
161 m_availableFieldsDescriptionLabel = new TQLabel(
162 i18n("Select fields from the list below and drag them onto a form or click the \"Insert\" button"), contents);
163 m_availableFieldsDescriptionLabel->setAlignment( TQt::AlignAuto | TQt::WordBreak );
164 hlyr->addWidget(m_availableFieldsDescriptionLabel);
165
166 //Available Fields
167 contentsVlyr->addSpacing(4);
168 hlyr = new TQHBoxLayout(contentsVlyr);
169 m_availableFieldsLabel = new TQLabel(i18n("Available fields:"), contents);
170 m_availableFieldsLabel->setSizePolicy(TQSizePolicy::Minimum, TQSizePolicy::Fixed);
171 m_availableFieldsLabel->setMargin(2);
172 m_availableFieldsLabel->setMinimumHeight(IconSize(TDEIcon::Small));
173 hlyr->addWidget(m_availableFieldsLabel);
174
175 m_addField = new KexiSmallToolButton(contents, i18n("Insert selected field into form", "Insert"),
176 "add_field", "addFieldButton");
177 m_addField->setMinimumHeight(m_availableFieldsLabel->minimumHeight());
178// m_addField->setTextPosition(TQToolButton::Right);
179 m_addField->setFocusPolicy(TQWidget::StrongFocus);
180 TQToolTip::add(m_addField, i18n("Insert selected fields into form"));
181 hlyr->addWidget(m_addField);
182 connect(m_addField, TQ_SIGNAL(clicked()), this, TQ_SLOT(slotInsertSelectedFields()));
183
184 m_fieldListView = new KexiFieldListView(contents, "fieldListView",
186 m_fieldListView->setSizePolicy(TQSizePolicy(TQSizePolicy::Preferred, TQSizePolicy::Expanding));
187 m_availableFieldsLabel->setBuddy(m_fieldListView);
188 contentsVlyr->addWidget(m_fieldListView, 1);
189 connect(m_fieldListView, TQ_SIGNAL(selectionChanged()), this, TQ_SLOT(slotFieldListViewSelectionChanged()));
190 connect(m_fieldListView, TQ_SIGNAL(fieldDoubleClicked(const TQString&, const TQString&, const TQString&)),
191 this, TQ_SLOT(slotFieldDoubleClicked(const TQString&, const TQString&, const TQString&)));
192#endif
193
194 vlyr->addStretch(1);
195
196 connect(m_dataSourceCombo, TQ_SIGNAL(textChanged(const TQString &)), this, TQ_SLOT(slotDataSourceTextChanged(const TQString &)));
197 connect(m_dataSourceCombo, TQ_SIGNAL(dataSourceChanged()), this, TQ_SLOT(slotDataSourceChanged()));
198 connect(m_sourceFieldCombo, TQ_SIGNAL(selected()), this, TQ_SLOT(slotFieldSelected()));
199
200 clearDataSourceSelection();
201 slotFieldListViewSelectionChanged();
202}
203
204KexiDataSourcePage::~KexiDataSourcePage()
205{
206}
207
208void KexiDataSourcePage::setProject(KexiProject *prj)
209{
210 m_sourceFieldCombo->setProject(prj);
211 m_dataSourceCombo->setProject(prj);
212}
213
214void KexiDataSourcePage::clearDataSourceSelection(bool alsoClearComboBox)
215{
216 if (m_insideClearDataSourceSelection)
217 return;
218 m_insideClearDataSourceSelection = true;
219 if (alsoClearComboBox && !m_dataSourceCombo->selectedName().isEmpty())
220 m_dataSourceCombo->setDataSource("", "");
221// if (!m_dataSourceCombo->currentText().isEmpty()) {
222// m_dataSourceCombo->setCurrentText("");
223// emit m_dataSourceCombo->dataSourceSelected();
224// }
225 m_clearDSButton->setEnabled(false);
226 m_gotoButton->setEnabled(false);
227#ifndef KEXI_NO_AUTOFIELD_WIDGET
228 m_addField->setEnabled(false);
229 m_fieldListView->clear();
230#endif
231 m_insideClearDataSourceSelection = false;
232}
233
234void KexiDataSourcePage::clearWidgetDataSourceSelection()
235{
236 if (!m_sourceFieldCombo->currentText().isEmpty()) {
237 m_sourceFieldCombo->setCurrentText("");
238 m_sourceFieldCombo->setFieldOrExpression(TQString());
240 }
241 m_clearWidgetDSButton->setEnabled(false);
242}
243
244void KexiDataSourcePage::slotGotoSelected()
245{
246 TQCString mime = m_dataSourceCombo->selectedMimeType().latin1();
247 if (mime=="kexi/table" || mime=="kexi/query") {
248 if (m_dataSourceCombo->isSelectionValid())
249 emit jumpToObjectRequested(mime, m_dataSourceCombo->selectedName().latin1());
250 }
251}
252
253void KexiDataSourcePage::slotInsertSelectedFields()
254{
255#ifndef KEXI_NO_AUTOFIELD_WIDGET
256 TQStringList selectedFieldNames(m_fieldListView->selectedFieldNames());
257 if (selectedFieldNames.isEmpty())
258 return;
259
260 emit insertAutoFields(m_fieldListView->schema()->table() ? "kexi/table" : "kexi/query",
261 m_fieldListView->schema()->name(), selectedFieldNames);
262#endif
263}
264
265void KexiDataSourcePage::slotFieldDoubleClicked(const TQString& sourceMimeType, const TQString& sourceName,
266 const TQString& fieldName)
267{
268#ifndef KEXI_NO_AUTOFIELD_WIDGET
269 TQStringList selectedFields;
270 selectedFields.append(fieldName);
271 emit insertAutoFields(sourceMimeType, sourceName, selectedFields);
272#endif
273}
274
276{
277 Q_UNUSED(string);
278 const bool enable = m_dataSourceCombo->isSelectionValid();
279 if (!enable) {
280 clearDataSourceSelection( m_dataSourceCombo->selectedName().isEmpty()/*alsoClearComboBox*/ );
281 }
283/*#ifndef KEXI_NO_AUTOFIELD_WIDGET
284 m_fieldListView->setEnabled(enable);
285// m_addField->setEnabled(enable);
286 m_availableFieldsLabel->setEnabled(enable);
287#endif*/
288}
289
290void KexiDataSourcePage::slotDataSourceChanged()
291{
292 if (!m_dataSourceCombo->project())
293 return;
294 TQCString mime = m_dataSourceCombo->selectedMimeType().latin1();
295 bool dataSourceFound = false;
296 TQCString name = m_dataSourceCombo->selectedName().latin1();
297 if ((mime=="kexi/table" || mime=="kexi/query") && m_dataSourceCombo->isSelectionValid()) {
299 m_dataSourceCombo->project()->dbConnection(), name, mime=="kexi/table");
300 if (tableOrQuery->table() || tableOrQuery->query()) {
301#ifdef KEXI_NO_AUTOFIELD_WIDGET
302 m_tableOrQuerySchema = tableOrQuery;
303#else
304 m_fieldListView->setSchema( tableOrQuery );
305#endif
306 dataSourceFound = true;
307 m_sourceFieldCombo->setTableOrQuery(name, mime=="kexi/table");
308 }
309 else {
310 delete tableOrQuery;
311 }
312 }
313 if (!dataSourceFound) {
314 m_sourceFieldCombo->setTableOrQuery("", true);
315 }
316 //if (m_sourceFieldCombo->hasFocus())
317// m_dataSourceCombo->setFocus();
318 m_clearDSButton->setEnabled(dataSourceFound);
319 m_gotoButton->setEnabled(dataSourceFound);
320 if (dataSourceFound) {
321 slotFieldListViewSelectionChanged();
322 } else {
323#ifndef KEXI_NO_AUTOFIELD_WIDGET
324 m_addField->setEnabled(false);
325#endif
326 }
328 emit formDataSourceChanged(mime, name);
329}
330
332{
334#ifdef KEXI_NO_AUTOFIELD_WIDGET
335 KexiDB::Field *field = m_tableOrQuerySchema->field( m_sourceFieldCombo->fieldOrExpression() ); //temp
336#else
338 KexiDB::Field *field = m_fieldListView->schema()->field( m_sourceFieldCombo->fieldOrExpression() );
339#endif
340 if (field)
341 dataType = field->type();
342
343 m_clearWidgetDSButton->setEnabled( !m_sourceFieldCombo->fieldOrExpression().isEmpty() );
344
346 m_sourceFieldCombo->fieldOrExpression(),
347 m_sourceFieldCombo->fieldOrExpressionCaption(),
348 dataType
349 );
350}
351
352void KexiDataSourcePage::setDataSource(const TQCString& mimeType, const TQCString& name)
353{
354 m_dataSourceCombo->setDataSource(mimeType, name);
355}
356
357void KexiDataSourcePage::assignPropertySet(KoProperty::Set* propertySet)
358{
359 TQCString objectName;
360 if (propertySet && propertySet->contains("name"))
361 objectName = (*propertySet)["name"].value().toCString();
362 if (!objectName.isEmpty() && objectName == m_currentObjectName)
363 return; //the same object
364 m_currentObjectName = objectName;
365
366 TQCString objectClassName;
367 if (propertySet && propertySet->contains("this:className"))
368 objectClassName = (*propertySet)["this:className"].value().toCString();
369/*moved if (propertySet) {
370 TQCString iconName;
371 TQString objectClassString;
372 if (propertySet->contains("this:iconName"))
373 iconName = (*propertySet)["this:iconName"].value().toCString();
374 if (propertySet->contains("this:classString"))
375 objectClassString = (*propertySet)["this:classString"].value().toString();
376 m_objectInfoLabel->setObjectName(objectName);
377 m_objectInfoLabel->setObjectClassIcon(iconName);
378 m_objectInfoLabel->setObjectClassName(objectClassString);
379 if (propertySet->contains("this:className"))
380 objectClassName = (*propertySet)["this:className"].value().toCString();
381 }*/
383 m_objectInfoLabel, propertySet);
384
385 const bool isForm = objectClassName=="KexiDBForm";
386// kdDebug() << "objectClassName=" << objectClassName << endl;
387// {
388/* //this is top level form's surface: data source means table or query
389 TQCString dataSourceMimeType, dataSource;
390 if (buffer->hasProperty("dataSourceMimeType"))
391 dataSourceMimeType = (*buffer)["dataSourceMimeType"].value().toCString();
392 if (buffer->hasProperty("dataSource"))
393 dataSource = (*buffer)["dataSource"].value().toCString();
394 m_dataSourceCombo->setDataSource(dataSourceMimeType, dataSource);*/
395// }
396// else {
397
398 const bool multipleSelection = objectClassName=="special:multiple";
399 const bool hasDataSourceProperty = propertySet && propertySet->contains("dataSource") && !multipleSelection;
400
401 if (!isForm) {
402 //this is a widget
403 TQCString dataSource;
404 if (hasDataSourceProperty) {
405 if (propertySet)
406 dataSource = (*propertySet)["dataSource"].value().toCString();
407 m_noDataSourceAvailableLabel->hide();
408 m_sourceFieldCombo->setFieldOrExpression(dataSource.data());
409 m_sourceFieldCombo->setEnabled(true);
410 m_clearWidgetDSButton->setEnabled(!m_sourceFieldCombo->currentText().isEmpty());
411 m_widgetDSLabel->show();
412 m_clearWidgetDSButton->show();
413 m_sourceFieldCombo->show();
414// m_dataSourceSeparator->hide();
416 }
417 }
418
419 if (isForm) {
420 m_noDataSourceAvailableLabel->hide();
421// m_dataSourceSeparator->hide();
422 }
423 else if (!hasDataSourceProperty) {
424 if (multipleSelection)
425 m_noDataSourceAvailableLabel->setText(m_noDataSourceAvailableMultiText);
426 else
427 m_noDataSourceAvailableLabel->setText(m_noDataSourceAvailableSingleText);
428 m_noDataSourceAvailableLabel->show();
429// m_dataSourceSeparator->show();
430 //make 'No data source could be assigned' label's height the same as the 'source field' combo+label
431 m_noDataSourceAvailableLabel->setMinimumHeight(m_widgetDSLabel->height()
432 + m_sourceFieldCombo->height()/*-m_dataSourceSeparator->height()*/);
433 m_sourceFieldCombo->setCurrentText("");
434 }
435
436 if (isForm || !hasDataSourceProperty) {
437 //no source field can be set
438 m_widgetDSLabel->hide();
439 m_clearWidgetDSButton->hide();
440 m_sourceFieldCombo->hide();
441 }
442}
443
444void KexiDataSourcePage::slotFieldListViewSelectionChanged()
445{
446#ifndef KEXI_NO_AUTOFIELD_WIDGET
447 //update "add field" button's state
448 for (TQListViewItemIterator it(m_fieldListView); it.current(); ++it) {
449 if (it.current()->isSelected()) {
450 m_addField->setEnabled(true);
451 return;
452 }
453 }
454 m_addField->setEnabled(false);
455#endif
456}
457
459{
460 const bool hasDataSource = m_dataSourceCombo->isSelectionValid();
461 m_sourceFieldCombo->setEnabled( hasDataSource );
462 m_widgetDSLabel->setEnabled( hasDataSource );
463#ifndef KEXI_NO_AUTOFIELD_WIDGET
464 m_fieldListView->setEnabled( hasDataSource );
465 m_availableFieldsLabel->setEnabled( hasDataSource );
466 m_mousePointerLabel->setEnabled( hasDataSource );
467 m_availableFieldsDescriptionLabel->setEnabled( hasDataSource );
468#endif
469}
470
471#include "kexidatasourcepage.moc"
Meta-data for a field.
Definition field.h:73
Type type() const
Definition field.cpp:134
@ InvalidType
Definition field.h:84
QuerySchema * query() const
TableSchema * table() const
A combo box listing availabe data sources (tables and queries) with icons.
KexiProject * project() const
void formDataSourceChanged(const TQCString &mime, const TQCString &name)
Signal emitted when form's data source has been changed. It's connected to the Form Manager.
void dataSourceFieldOrExpressionChanged(const TQString &string, const TQString &caption, KexiDB::Field::Type type)
void assignPropertySet(KoProperty::Set *propertySet)
Receives a pointer to a new property set (from KexiFormView::managerPropertyChanged()).
TQCString m_currentObjectName
Used only in assignPropertySet() to check whether we already have the set assigned.
void setDataSource(const TQCString &mimeType, const TQCString &name)
void jumpToObjectRequested(const TQCString &mime, const TQCString &name)
Signal emitted when helper button 'go to selected data source' is clicked.
void insertAutoFields(const TQString &sourceMimeType, const TQString &sourceName, const TQStringList &fields)
void slotDataSourceTextChanged(const TQString &string)
KexiDataSourcePage(TQWidget *parent, const char *name=0)
@ ShowDataTypes
if set, 'data type' column is added
@ AllowMultiSelection
if set, multiple selection is allowed
void setSchema(KexiDB::TableOrQuerySchema *schema)
Helper class displaying small icon with class name and object name.
A project's main controller.
Definition kexiproject.h:68
KexiDB::Connection * dbConnection() const
static void updateInfoLabelForPropertySet(KexiObjectInfoLabel *infoLabel, KoProperty::Set *set, const TQString &textToDisplayForNullSet=TQString())
A small tool button with icon and optional text.