kexi

lookupfieldschema.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2006-2007 Jaroslaw Staniek <js@iidea.pl>
3
4 This program 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 program 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 program; see the file COPYING. 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 "lookupfieldschema.h"
21#include "utils.h"
22
23#include <tqdom.h>
24#include <tqvariant.h>
25#include <kdebug.h>
26
27using namespace KexiDB;
28
29
30LookupFieldSchema::RowSource::RowSource()
31: m_type(NoType)
32, m_values(0)
33{
34}
35
36LookupFieldSchema::RowSource::~RowSource()
37{
38 delete m_values;
39}
40
42{
43 m_name = name;
44 if (m_values)
45 m_values->clear();
46}
47
49{
50 switch (m_type) {
51 case Table: return "table";
52 case Query: return "query";
53 case SQLStatement: return "sql";
54 case ValueList: return "valuelist";
55 case FieldList: return "fieldlist";
56 default:;
57 }
58 return TQString();
59}
60
62{
63 if (typeName=="table")
64 setType( Table );
65 else if (typeName=="query")
66 setType( Query );
67 else if (typeName=="sql")
69 else if (typeName=="valuelist")
71 else if (typeName=="fieldlist")
73 else
74 setType( NoType );
75}
76
78{
79 return m_values ? *m_values : TQStringList();
80}
81
83{
84 m_name = TQString();
85 if (m_values)
86 *m_values = values;
87 else
88 m_values = new TQStringList(values);
89}
90
92{
93 return TQString("rowSourceType:'%1' rowSourceName:'%2' rowSourceValues:'%3'\n")
94 .arg(typeName()).arg(name()).arg(m_values ? m_values->join("|") : TQString());
95}
96
98{
99 KexiDBDbg << debugString() << endl;
100}
101
102//---------------------------------------
103
104LookupFieldSchema::LookupFieldSchema()
105 : m_boundColumn(-1)
106 , m_maximumListRows(KEXIDB_LOOKUP_FIELD_DEFAULT_LIST_ROWS)
107 , m_displayWidget(KEXIDB_LOOKUP_FIELD_DEFAULT_DISPLAY_WIDGET)
108 , m_columnHeadersVisible(KEXIDB_LOOKUP_FIELD_DEFAULT_HEADERS_VISIBLE)
109 , m_limitToList(KEXIDB_LOOKUP_FIELD_DEFAULT_LIMIT_TO_LIST)
110{
111}
112
113LookupFieldSchema::~LookupFieldSchema()
114{
115}
116
118{
119 if (rows==0)
120 m_maximumListRows = KEXIDB_LOOKUP_FIELD_DEFAULT_LIST_ROWS;
121 else if (rows>KEXIDB_LOOKUP_FIELD_MAX_LIST_ROWS)
122 m_maximumListRows = KEXIDB_LOOKUP_FIELD_MAX_LIST_ROWS;
123 else
124 m_maximumListRows = rows;
125}
126
128{
129 TQString columnWidthsStr;
130 foreach (TQValueList<int>::ConstIterator, it, m_columnWidths) {
131 if (!columnWidthsStr.isEmpty())
132 columnWidthsStr.append(";");
133 columnWidthsStr.append( TQString::number(*it) );
134 }
135
136 TQString visibleColumnsString;
137 foreach (TQValueList<uint>::ConstIterator, it, m_visibleColumns) {
138 if (!visibleColumnsString.isEmpty())
139 visibleColumnsString.append(";");
140 visibleColumnsString.append(TQString::number(*it));
141 }
142
143 return TQString("LookupFieldSchema( %1\n"
144 " boundColumn:%2 visibleColumns:%3 maximumListRows:%4 displayWidget:%5\n"
145 " columnHeadersVisible:%6 limitToList:%7\n"
146 " columnWidths:%8 )")
147 .arg(m_rowSource.debugString())
148 .arg(m_boundColumn).arg(visibleColumnsString).arg(m_maximumListRows)
149 .arg( m_displayWidget==ComboBox ? "ComboBox" : "ListBox")
150 .arg(m_columnHeadersVisible).arg(m_limitToList)
151 .arg(columnWidthsStr);
152}
153
155{
156 KexiDBDbg << debugString() << endl;
157}
158
159/* static */
160LookupFieldSchema *LookupFieldSchema::loadFromDom(const TQDomElement& lookupEl)
161{
162 LookupFieldSchema *lookupFieldSchema = new LookupFieldSchema();
163 for (TQDomNode node = lookupEl.firstChild(); !node.isNull(); node = node.nextSibling()) {
164 TQDomElement el = node.toElement();
165 TQString name( el.tagName() );
166 if (name=="row-source") {
167 /*<row-source>
168 empty
169 | <type>table|query|sql|valuelist|fieldlist</type> #required because there can be table and query with the same name
170 "fieldlist" (basically a list of column names of a table/query,
171 "Field List" as in MSA)
172 <name>string</name> #table/query name, etc. or KEXISQL SELECT QUERY
173 <values><value>...</value> #for "valuelist" type
174 <value>...</value>
175 </values>
176 </row-source> */
177 for (el = el.firstChild().toElement(); !el.isNull(); el=el.nextSibling().toElement()) {
178 if (el.tagName()=="type")
179 lookupFieldSchema->rowSource().setTypeByName( el.text() );
180 else if (el.tagName()=="name")
181 lookupFieldSchema->rowSource().setName( el.text() );
183 }
184 }
185 else if (name=="bound-column") {
186 /* <bound-column>
187 <number>number</number> #in later implementation there can be more columns
188 </bound-column> */
189 const TQVariant val = KexiDB::loadPropertyValueFromDom( el.firstChild() );
190 if (val.type()==TQVariant::Int)
191 lookupFieldSchema->setBoundColumn( val.toInt() );
192 }
193 else if (name=="visible-column") {
194 /* <visible-column> #a column that has to be visible in the combo box
195 <number>number 1</number>
196 <number>number 2</number>
197 [..]
198 </visible-column> */
199 TQValueList<uint> list;
200 for (TQDomNode childNode = el.firstChild(); !childNode.isNull(); childNode = childNode.nextSibling()) {
201 const TQVariant val = KexiDB::loadPropertyValueFromDom( childNode );
202 if (val.type()==TQVariant::Int)
203 list.append( val.toUInt() );
204 }
205 lookupFieldSchema->setVisibleColumns( list );
206 }
207 else if (name=="column-widths") {
208 /* <column-widths> #column widths, -1 means 'default'
209 <number>int</number>
210 ...
211 <number>int</number>
212 </column-widths> */
213 TQVariant val;
214 TQValueList<int> columnWidths;
215 for (el = el.firstChild().toElement(); !el.isNull(); el=el.nextSibling().toElement()) {
216 TQVariant val = KexiDB::loadPropertyValueFromDom( el );
217 if (val.type()==TQVariant::Int)
218 columnWidths.append(val.toInt());
219 }
220 lookupFieldSchema->setColumnWidths( columnWidths );
221 }
222 else if (name=="show-column-headers") {
223 /* <show-column-headers>
224 <bool>true/false</bool>
225 </show-column-headers> */
226 const TQVariant val = KexiDB::loadPropertyValueFromDom( el.firstChild() );
227 if (val.type()==TQVariant::Bool)
228 lookupFieldSchema->setColumnHeadersVisible( val.toBool() );
229 }
230 else if (name=="list-rows") {
231 /* <list-rows>
232 <number>1..100</number>
233 </list-rows> */
234 const TQVariant val = KexiDB::loadPropertyValueFromDom( el.firstChild() );
235 if (val.type()==TQVariant::Int)
236 lookupFieldSchema->setMaximumListRows( val.toUInt() );
237 }
238 else if (name=="limit-to-list") {
239 /* <limit-to-list>
240 <bool>true/false</bool>
241 </limit-to-list> */
242 const TQVariant val = KexiDB::loadPropertyValueFromDom( el.firstChild() );
243 if (val.type()==TQVariant::Bool)
244 lookupFieldSchema->setLimitToList( val.toBool() );
245 }
246 else if (name=="display-widget") {
247 if (el.text()=="combobox")
248 lookupFieldSchema->setDisplayWidget( LookupFieldSchema::ComboBox );
249 else if (el.text()=="listbox")
250 lookupFieldSchema->setDisplayWidget( LookupFieldSchema::ListBox );
251 }
252 }
253 return lookupFieldSchema;
254}
255
256/* static */
257void LookupFieldSchema::saveToDom(LookupFieldSchema& lookupSchema, TQDomDocument& doc, TQDomElement& parentEl)
258{
259 TQDomElement lookupColumnEl, rowSourceEl, rowSourceTypeEl, nameEl;
260 if (!lookupSchema.rowSource().name().isEmpty()) {
261 lookupColumnEl = doc.createElement("lookup-column");
262 parentEl.appendChild( lookupColumnEl );
263
264 rowSourceEl = doc.createElement("row-source");
265 lookupColumnEl.appendChild( rowSourceEl );
266
267 rowSourceTypeEl = doc.createElement("type");
268 rowSourceEl.appendChild( rowSourceTypeEl );
269 rowSourceTypeEl.appendChild( doc.createTextNode(lookupSchema.rowSource().typeName()) ); //can be empty
270
271 nameEl = doc.createElement("name");
272 rowSourceEl.appendChild( nameEl );
273 nameEl.appendChild( doc.createTextNode(lookupSchema.rowSource().name()) );
274 }
275
276 const TQStringList& values( lookupSchema.rowSource().values() );
277 if (!values.isEmpty()) {
278 TQDomElement valuesEl( doc.createElement("values") );
279 rowSourceEl.appendChild( valuesEl );
280 for (TQStringList::ConstIterator it = values.constBegin(); it!=values.constEnd(); ++it) {
281 TQDomElement valueEl( doc.createElement("value") );
282 valuesEl.appendChild( valueEl );
283 valueEl.appendChild( doc.createTextNode(*it) );
284 }
285 }
286
287 if (lookupSchema.boundColumn()>=0)
288 KexiDB::saveNumberElementToDom(doc, lookupColumnEl, "bound-column", lookupSchema.boundColumn());
289
290 TQValueList<uint> visibleColumns(lookupSchema.visibleColumns());
291 if (!visibleColumns.isEmpty()) {
292 TQDomElement visibleColumnEl( doc.createElement("visible-column") );
293 lookupColumnEl.appendChild( visibleColumnEl );
294 foreach (TQValueList<uint>::ConstIterator, it, visibleColumns) {
295 TQDomElement numberEl( doc.createElement("number") );
296 visibleColumnEl.appendChild( numberEl );
297 numberEl.appendChild( doc.createTextNode( TQString::number(*it) ) );
298 }
299 }
300
301 const TQValueList<int> columnWidths(lookupSchema.columnWidths());
302 if (!columnWidths.isEmpty()) {
303 TQDomElement columnWidthsEl( doc.createElement("column-widths") );
304 lookupColumnEl.appendChild( columnWidthsEl );
305 for (TQValueList<int>::ConstIterator it = columnWidths.constBegin(); it!=columnWidths.constEnd(); ++it) {
306 TQDomElement columnWidthEl( doc.createElement("number") );
307 columnWidthsEl.appendChild( columnWidthEl );
308 columnWidthEl.appendChild( doc.createTextNode( TQString::number(*it) ) );
309 }
310 }
311
312 if (lookupSchema.columnHeadersVisible()!=KEXIDB_LOOKUP_FIELD_DEFAULT_HEADERS_VISIBLE)
313 KexiDB::saveBooleanElementToDom(doc, lookupColumnEl, "show-column-headers", lookupSchema.columnHeadersVisible());
314 if (lookupSchema.maximumListRows()!=KEXIDB_LOOKUP_FIELD_DEFAULT_LIST_ROWS)
315 KexiDB::saveNumberElementToDom(doc, lookupColumnEl, "list-rows", lookupSchema.maximumListRows());
316 if (lookupSchema.limitToList()!=KEXIDB_LOOKUP_FIELD_DEFAULT_LIMIT_TO_LIST)
317 KexiDB::saveBooleanElementToDom(doc, lookupColumnEl, "limit-to-list", lookupSchema.limitToList());
318
319 if (lookupSchema.displayWidget()!=KEXIDB_LOOKUP_FIELD_DEFAULT_DISPLAY_WIDGET) {
320 TQDomElement displayWidgetEl( doc.createElement("display-widget") );
321 lookupColumnEl.appendChild( displayWidgetEl );
322 displayWidgetEl.appendChild(
323 doc.createTextNode( (lookupSchema.displayWidget()==ListBox) ? "listbox" : "combobox" ) );
324 }
325}
326
327//static
329 LookupFieldSchema& lookup, const TQCString& propertyName, const TQVariant& value )
330{
331 bool ok;
332 if ("rowSource" == propertyName || "rowSourceType" == propertyName || "rowSourceValues" == propertyName) {
334 if ("rowSource" == propertyName)
335 rowSource.setName(value.toString());
336 else if ("rowSourceType" == propertyName)
337 rowSource.setTypeByName(value.toString());
338 else if ("rowSourceValues" == propertyName)
339 rowSource.setValues(value.toStringList());
340 lookup.setRowSource(rowSource);
341 }
342 else if ("boundColumn" == propertyName ) {
343 const int ival = value.toInt(&ok);
344 if (!ok)
345 return false;
346 lookup.setBoundColumn( ival );
347 }
348 else if ("visibleColumn" == propertyName ) {
349 TQValueList<TQVariant> variantList;
350 if (value.type()==TQVariant::Int) {
353 variantList.append( value.toInt() );
354 }
355 else {
356 variantList = value.toList();
357 }
358 TQValueList<uint> visibleColumns;
359 foreach (TQValueList<TQVariant>::ConstIterator, it, variantList) {
360 const uint ival = (*it).toUInt(&ok);
361 if (!ok)
362 return false;
363 visibleColumns.append( ival );
364 }
366 }
367 else if ("columnWidths" == propertyName ) {
368 TQValueList<TQVariant> variantList( value.toList() );
369 TQValueList<int> widths;
370 foreach (TQValueList<TQVariant>::ConstIterator, it, variantList) {
371 const uint ival = (*it).toInt(&ok);
372 if (!ok)
373 return false;
374 widths.append( ival );
375 }
376 lookup.setColumnWidths( widths );
377 }
378 else if ("showColumnHeaders" == propertyName ) {
379 lookup.setColumnHeadersVisible( value.toBool() );
380 }
381 else if ("listRows" == propertyName ) {
382 lookup.setMaximumListRows( value.toBool() );
383 }
384 else if ("limitToList" == propertyName ) {
385 lookup.setLimitToList( value.toBool() );
386 }
387 else if ("displayWidget" == propertyName ) {
388 const uint ival = value.toUInt(&ok);
389 if (!ok || ival > LookupFieldSchema::ListBox)
390 return false;
392 }
393 return true;
394}
Row source information that can be specified for the lookup field schema.
void setValues(const TQStringList &values)
void setTypeByName(const TQString &typeName)
@ Table
table as lookup row source
@ ValueList
a fixed list of values as lookup row source
@ Query
named query as lookup row source
@ FieldList
a list of column names from a table/query will be displayed
@ SQLStatement
anonymous query as lookup row source
static LookupFieldSchema * loadFromDom(const TQDomElement &lookupEl)
void setDisplayWidget(DisplayWidget widget)
void setVisibleColumns(const TQValueList< uint > &list)
DisplayWidget displayWidget() const
void setRowSource(const RowSource &rowSource)
static bool setProperty(LookupFieldSchema &lookup, const TQCString &propertyName, const TQVariant &value)
void setColumnWidths(const TQValueList< int > &widths)
DisplayWidget
used in displayWidget()
@ ListBox
listbox widget should be displayed in forms for this lookup field
@ ComboBox
(the default) combobox widget should be displayed in forms for this lookup field
static void saveToDom(LookupFieldSchema &lookupSchema, TQDomDocument &doc, TQDomElement &parentEl)
void setColumnHeadersVisible(bool set)
const TQValueList< int > columnWidths() const
TQValueList< uint > visibleColumns() const
High-level database connectivity library with database backend drivers.
KEXI_DB_EXPORT TQDomElement saveBooleanElementToDom(TQDomDocument &doc, TQDomElement &parentEl, const TQString &elementName, bool value)
KEXI_DB_EXPORT TQVariant loadPropertyValueFromDom(const TQDomNode &node)
KEXI_DB_EXPORT TQDomElement saveNumberElementToDom(TQDomDocument &doc, TQDomElement &parentEl, const TQString &elementName, int value)