|
|
|
/* This file is part of the KDE project
|
|
|
|
Copyright (C) 2006-2007 Jaroslaw Staniek <js@iidea.pl>
|
|
|
|
|
|
|
|
This program 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 program 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 program; see the file COPYING. If not, write to
|
|
|
|
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
* Boston, MA 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "lookupfieldschema.h"
|
|
|
|
#include "utils.h"
|
|
|
|
|
|
|
|
#include <tqdom.h>
|
|
|
|
#include <tqvariant.h>
|
|
|
|
#include <kdebug.h>
|
|
|
|
|
|
|
|
using namespace KexiDB;
|
|
|
|
|
|
|
|
|
|
|
|
LookupFieldSchema::RowSource::RowSource()
|
|
|
|
: m_type(NoType)
|
|
|
|
, m_values(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
LookupFieldSchema::RowSource::~RowSource()
|
|
|
|
{
|
|
|
|
delete m_values;
|
|
|
|
}
|
|
|
|
|
|
|
|
void LookupFieldSchema::RowSource::setName(const TQString& name)
|
|
|
|
{
|
|
|
|
m_name = name;
|
|
|
|
if (m_values)
|
|
|
|
m_values->clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString LookupFieldSchema::RowSource::typeName() const
|
|
|
|
{
|
|
|
|
switch (m_type) {
|
|
|
|
case Table: return "table";
|
|
|
|
case Query: return "query";
|
|
|
|
case SQLStatement: return "sql";
|
|
|
|
case ValueList: return "valuelist";
|
|
|
|
case FieldList: return "fieldlist";
|
|
|
|
default:;
|
|
|
|
}
|
|
|
|
return TQString();
|
|
|
|
}
|
|
|
|
|
|
|
|
void LookupFieldSchema::RowSource::setTypeByName( const TQString& typeName )
|
|
|
|
{
|
|
|
|
if (typeName=="table")
|
|
|
|
setType( Table );
|
|
|
|
else if (typeName=="query")
|
|
|
|
setType( Query );
|
|
|
|
else if (typeName=="sql")
|
|
|
|
setType( SQLStatement );
|
|
|
|
else if (typeName=="valuelist")
|
|
|
|
setType( ValueList );
|
|
|
|
else if (typeName=="fieldlist")
|
|
|
|
setType( FieldList );
|
|
|
|
else
|
|
|
|
setType( NoType );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQStringList LookupFieldSchema::RowSource::values() const
|
|
|
|
{
|
|
|
|
return m_values ? *m_values : TQStringList();
|
|
|
|
}
|
|
|
|
|
|
|
|
void LookupFieldSchema::RowSource::setValues(const TQStringList& values)
|
|
|
|
{
|
|
|
|
m_name = TQString();
|
|
|
|
if (m_values)
|
|
|
|
*m_values = values;
|
|
|
|
else
|
|
|
|
m_values = new TQStringList(values);
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString LookupFieldSchema::RowSource::debugString() const
|
|
|
|
{
|
|
|
|
return TQString("rowSourceType:'%1' rowSourceName:'%2' rowSourceValues:'%3'\n")
|
|
|
|
.tqarg(typeName()).tqarg(name()).tqarg(m_values ? m_values->join("|") : TQString());
|
|
|
|
}
|
|
|
|
|
|
|
|
void LookupFieldSchema::RowSource::debug() const
|
|
|
|
{
|
|
|
|
KexiDBDbg << debugString() << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
//---------------------------------------
|
|
|
|
|
|
|
|
LookupFieldSchema::LookupFieldSchema()
|
|
|
|
: m_boundColumn(-1)
|
|
|
|
, m_maximumListRows(KEXIDB_LOOKUP_FIELD_DEFAULT_LIST_ROWS)
|
|
|
|
, m_displayWidget(KEXIDB_LOOKUP_FIELD_DEFAULT_DISPLAY_WIDGET)
|
|
|
|
, m_columnHeadersVisible(KEXIDB_LOOKUP_FIELD_DEFAULT_HEADERS_VISIBLE)
|
|
|
|
, m_limitToList(KEXIDB_LOOKUP_FIELD_DEFAULT_LIMIT_TO_LIST)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
LookupFieldSchema::~LookupFieldSchema()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void LookupFieldSchema::setMaximumListRows(uint rows)
|
|
|
|
{
|
|
|
|
if (rows==0)
|
|
|
|
m_maximumListRows = KEXIDB_LOOKUP_FIELD_DEFAULT_LIST_ROWS;
|
|
|
|
else if (rows>KEXIDB_LOOKUP_FIELD_MAX_LIST_ROWS)
|
|
|
|
m_maximumListRows = KEXIDB_LOOKUP_FIELD_MAX_LIST_ROWS;
|
|
|
|
else
|
|
|
|
m_maximumListRows = rows;
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString LookupFieldSchema::debugString() const
|
|
|
|
{
|
|
|
|
TQString columnWidthsStr;
|
|
|
|
foreach (TQValueList<int>::ConstIterator, it, m_columnWidths) {
|
|
|
|
if (!columnWidthsStr.isEmpty())
|
|
|
|
columnWidthsStr.append(";");
|
|
|
|
columnWidthsStr.append( TQString::number(*it) );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString visibleColumnsString;
|
|
|
|
foreach (TQValueList<uint>::ConstIterator, it, m_visibleColumns) {
|
|
|
|
if (!visibleColumnsString.isEmpty())
|
|
|
|
visibleColumnsString.append(";");
|
|
|
|
visibleColumnsString.append(TQString::number(*it));
|
|
|
|
}
|
|
|
|
|
|
|
|
return TQString("LookupFieldSchema( %1\n"
|
|
|
|
" boundColumn:%2 visibleColumns:%3 maximumListRows:%4 displayWidget:%5\n"
|
|
|
|
" columnHeadersVisible:%6 limitToList:%7\n"
|
|
|
|
" columnWidths:%8 )")
|
|
|
|
.tqarg(m_rowSource.debugString())
|
|
|
|
.tqarg(m_boundColumn).tqarg(visibleColumnsString).tqarg(m_maximumListRows)
|
|
|
|
.tqarg( m_displayWidget==ComboBox ? "ComboBox" : "ListBox")
|
|
|
|
.tqarg(m_columnHeadersVisible).tqarg(m_limitToList)
|
|
|
|
.tqarg(columnWidthsStr);
|
|
|
|
}
|
|
|
|
|
|
|
|
void LookupFieldSchema::debug() const
|
|
|
|
{
|
|
|
|
KexiDBDbg << debugString() << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
LookupFieldSchema *LookupFieldSchema::loadFromDom(const TQDomElement& lookupEl)
|
|
|
|
{
|
|
|
|
LookupFieldSchema *lookupFieldSchema = new LookupFieldSchema();
|
|
|
|
for (TQDomNode node = lookupEl.firstChild(); !node.isNull(); node = node.nextSibling()) {
|
|
|
|
TQDomElement el = node.toElement();
|
|
|
|
TQString name( el.tagName() );
|
|
|
|
if (name=="row-source") {
|
|
|
|
/*<row-source>
|
|
|
|
empty
|
|
|
|
| <type>table|query|sql|valuelist|fieldlist</type> #required because there can be table and query with the same name
|
|
|
|
"fieldlist" (basically a list of column names of a table/query,
|
|
|
|
"Field List" as in MSA)
|
|
|
|
<name>string</name> #table/query name, etc. or KEXISQL SELECT TQUERY
|
|
|
|
<values><value>...</value> #for "valuelist" type
|
|
|
|
<value>...</value>
|
|
|
|
</values>
|
|
|
|
</row-source> */
|
|
|
|
for (el = el.firstChild().toElement(); !el.isNull(); el=el.nextSibling().toElement()) {
|
|
|
|
if (el.tagName()=="type")
|
|
|
|
lookupFieldSchema->rowSource().setTypeByName( el.text() );
|
|
|
|
else if (el.tagName()=="name")
|
|
|
|
lookupFieldSchema->rowSource().setName( el.text() );
|
|
|
|
//! @todo handle fieldlist (retrieve from external table or so?), use lookupFieldSchema.rowSource().setValues()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (name=="bound-column") {
|
|
|
|
/* <bound-column>
|
|
|
|
<number>number</number> #in later implementation there can be more columns
|
|
|
|
</bound-column> */
|
|
|
|
const TQVariant val = KexiDB::loadPropertyValueFromDom( el.firstChild() );
|
|
|
|
if (val.type()==TQVariant::Int)
|
|
|
|
lookupFieldSchema->setBoundColumn( val.toInt() );
|
|
|
|
}
|
|
|
|
else if (name=="visible-column") {
|
|
|
|
/* <visible-column> #a column that has to be visible in the combo box
|
|
|
|
<number>number 1</number>
|
|
|
|
<number>number 2</number>
|
|
|
|
[..]
|
|
|
|
</visible-column> */
|
|
|
|
TQValueList<uint> list;
|
|
|
|
for (TQDomNode childNode = el.firstChild(); !childNode.isNull(); childNode = childNode.nextSibling()) {
|
|
|
|
const TQVariant val = KexiDB::loadPropertyValueFromDom( childNode );
|
|
|
|
if (val.type()==TQVariant::Int)
|
|
|
|
list.append( val.toUInt() );
|
|
|
|
}
|
|
|
|
lookupFieldSchema->setVisibleColumns( list );
|
|
|
|
}
|
|
|
|
else if (name=="column-widths") {
|
|
|
|
/* <column-widths> #column widths, -1 means 'default'
|
|
|
|
<number>int</number>
|
|
|
|
...
|
|
|
|
<number>int</number>
|
|
|
|
</column-widths> */
|
|
|
|
TQVariant val;
|
|
|
|
TQValueList<int> columnWidths;
|
|
|
|
for (el = el.firstChild().toElement(); !el.isNull(); el=el.nextSibling().toElement()) {
|
|
|
|
TQVariant val = KexiDB::loadPropertyValueFromDom( el );
|
|
|
|
if (val.type()==TQVariant::Int)
|
|
|
|
columnWidths.append(val.toInt());
|
|
|
|
}
|
|
|
|
lookupFieldSchema->setColumnWidths( columnWidths );
|
|
|
|
}
|
|
|
|
else if (name=="show-column-headers") {
|
|
|
|
/* <show-column-headers>
|
|
|
|
<bool>true/false</bool>
|
|
|
|
</show-column-headers> */
|
|
|
|
const TQVariant val = KexiDB::loadPropertyValueFromDom( el.firstChild() );
|
|
|
|
if (val.type()==TQVariant::Bool)
|
|
|
|
lookupFieldSchema->setColumnHeadersVisible( val.toBool() );
|
|
|
|
}
|
|
|
|
else if (name=="list-rows") {
|
|
|
|
/* <list-rows>
|
|
|
|
<number>1..100</number>
|
|
|
|
</list-rows> */
|
|
|
|
const TQVariant val = KexiDB::loadPropertyValueFromDom( el.firstChild() );
|
|
|
|
if (val.type()==TQVariant::Int)
|
|
|
|
lookupFieldSchema->setMaximumListRows( val.toUInt() );
|
|
|
|
}
|
|
|
|
else if (name=="limit-to-list") {
|
|
|
|
/* <limit-to-list>
|
|
|
|
<bool>true/false</bool>
|
|
|
|
</limit-to-list> */
|
|
|
|
const TQVariant val = KexiDB::loadPropertyValueFromDom( el.firstChild() );
|
|
|
|
if (val.type()==TQVariant::Bool)
|
|
|
|
lookupFieldSchema->setLimitToList( val.toBool() );
|
|
|
|
}
|
|
|
|
else if (name=="display-widget") {
|
|
|
|
if (el.text()=="combobox")
|
|
|
|
lookupFieldSchema->setDisplayWidget( LookupFieldSchema::ComboBox );
|
|
|
|
else if (el.text()=="listbox")
|
|
|
|
lookupFieldSchema->setDisplayWidget( LookupFieldSchema::ListBox );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return lookupFieldSchema;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static */
|
|
|
|
void LookupFieldSchema::saveToDom(LookupFieldSchema& lookupSchema, TQDomDocument& doc, TQDomElement& parentEl)
|
|
|
|
{
|
|
|
|
TQDomElement lookupColumnEl, rowSourceEl, rowSourceTypeEl, nameEl;
|
|
|
|
if (!lookupSchema.rowSource().name().isEmpty()) {
|
|
|
|
lookupColumnEl = doc.createElement("lookup-column");
|
|
|
|
parentEl.appendChild( lookupColumnEl );
|
|
|
|
|
|
|
|
rowSourceEl = doc.createElement("row-source");
|
|
|
|
lookupColumnEl.appendChild( rowSourceEl );
|
|
|
|
|
|
|
|
rowSourceTypeEl = doc.createElement("type");
|
|
|
|
rowSourceEl.appendChild( rowSourceTypeEl );
|
|
|
|
rowSourceTypeEl.appendChild( doc.createTextNode(lookupSchema.rowSource().typeName()) ); //can be empty
|
|
|
|
|
|
|
|
nameEl = doc.createElement("name");
|
|
|
|
rowSourceEl.appendChild( nameEl );
|
|
|
|
nameEl.appendChild( doc.createTextNode(lookupSchema.rowSource().name()) );
|
|
|
|
}
|
|
|
|
|
|
|
|
const TQStringList& values( lookupSchema.rowSource().values() );
|
|
|
|
if (!values.isEmpty()) {
|
|
|
|
TQDomElement valuesEl( doc.createElement("values") );
|
|
|
|
rowSourceEl.appendChild( valuesEl );
|
|
|
|
for (TQStringList::ConstIterator it = values.constBegin(); it!=values.constEnd(); ++it) {
|
|
|
|
TQDomElement valueEl( doc.createElement("value") );
|
|
|
|
valuesEl.appendChild( valueEl );
|
|
|
|
valueEl.appendChild( doc.createTextNode(*it) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lookupSchema.boundColumn()>=0)
|
|
|
|
KexiDB::saveNumberElementToDom(doc, lookupColumnEl, "bound-column", lookupSchema.boundColumn());
|
|
|
|
|
|
|
|
TQValueList<uint> visibleColumns(lookupSchema.visibleColumns());
|
|
|
|
if (!visibleColumns.isEmpty()) {
|
|
|
|
TQDomElement visibleColumnEl( doc.createElement("visible-column") );
|
|
|
|
lookupColumnEl.appendChild( visibleColumnEl );
|
|
|
|
foreach (TQValueList<uint>::ConstIterator, it, visibleColumns) {
|
|
|
|
TQDomElement numberEl( doc.createElement("number") );
|
|
|
|
visibleColumnEl.appendChild( numberEl );
|
|
|
|
numberEl.appendChild( doc.createTextNode( TQString::number(*it) ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const TQValueList<int> columnWidths(lookupSchema.columnWidths());
|
|
|
|
if (!columnWidths.isEmpty()) {
|
|
|
|
TQDomElement columnWidthsEl( doc.createElement("column-widths") );
|
|
|
|
lookupColumnEl.appendChild( columnWidthsEl );
|
|
|
|
for (TQValueList<int>::ConstIterator it = columnWidths.constBegin(); it!=columnWidths.constEnd(); ++it) {
|
|
|
|
TQDomElement columnWidthEl( doc.createElement("number") );
|
|
|
|
columnWidthsEl.appendChild( columnWidthEl );
|
|
|
|
columnWidthEl.appendChild( doc.createTextNode( TQString::number(*it) ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lookupSchema.columnHeadersVisible()!=KEXIDB_LOOKUP_FIELD_DEFAULT_HEADERS_VISIBLE)
|
|
|
|
KexiDB::saveBooleanElementToDom(doc, lookupColumnEl, "show-column-headers", lookupSchema.columnHeadersVisible());
|
|
|
|
if (lookupSchema.maximumListRows()!=KEXIDB_LOOKUP_FIELD_DEFAULT_LIST_ROWS)
|
|
|
|
KexiDB::saveNumberElementToDom(doc, lookupColumnEl, "list-rows", lookupSchema.maximumListRows());
|
|
|
|
if (lookupSchema.limitToList()!=KEXIDB_LOOKUP_FIELD_DEFAULT_LIMIT_TO_LIST)
|
|
|
|
KexiDB::saveBooleanElementToDom(doc, lookupColumnEl, "limit-to-list", lookupSchema.limitToList());
|
|
|
|
|
|
|
|
if (lookupSchema.displayWidget()!=KEXIDB_LOOKUP_FIELD_DEFAULT_DISPLAY_WIDGET) {
|
|
|
|
TQDomElement displayWidgetEl( doc.createElement("display-widget") );
|
|
|
|
lookupColumnEl.appendChild( displayWidgetEl );
|
|
|
|
displayWidgetEl.appendChild(
|
|
|
|
doc.createTextNode( (lookupSchema.displayWidget()==ListBox) ? "listbox" : "combobox" ) );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//static
|
|
|
|
bool LookupFieldSchema::setProperty(
|
|
|
|
LookupFieldSchema& lookup, const TQCString& propertyName, const TQVariant& value )
|
|
|
|
{
|
|
|
|
bool ok;
|
|
|
|
if ("rowSource" == propertyName || "rowSourceType" == propertyName || "rowSourceValues" == propertyName) {
|
|
|
|
LookupFieldSchema::RowSource rowSource( lookup.rowSource() );
|
|
|
|
if ("rowSource" == propertyName)
|
|
|
|
rowSource.setName(value.toString());
|
|
|
|
else if ("rowSourceType" == propertyName)
|
|
|
|
rowSource.setTypeByName(value.toString());
|
|
|
|
else if ("rowSourceValues" == propertyName)
|
|
|
|
rowSource.setValues(value.toStringList());
|
|
|
|
lookup.setRowSource(rowSource);
|
|
|
|
}
|
|
|
|
else if ("boundColumn" == propertyName ) {
|
|
|
|
const int ival = value.toInt(&ok);
|
|
|
|
if (!ok)
|
|
|
|
return false;
|
|
|
|
lookup.setBoundColumn( ival );
|
|
|
|
}
|
|
|
|
else if ("visibleColumn" == propertyName ) {
|
|
|
|
TQValueList<TQVariant> variantList;
|
|
|
|
if (value.type()==TQVariant::Int) {
|
|
|
|
//! @todo Remove this case: it's for backward compatibility with Kexi's 1.1.2 table designer GUI
|
|
|
|
//! supporting only single lookup column.
|
|
|
|
variantList.append( value.toInt() );
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
variantList = value.toList();
|
|
|
|
}
|
|
|
|
TQValueList<uint> visibleColumns;
|
|
|
|
foreach (TQValueList<TQVariant>::ConstIterator, it, variantList) {
|
|
|
|
const uint ival = (*it).toUInt(&ok);
|
|
|
|
if (!ok)
|
|
|
|
return false;
|
|
|
|
visibleColumns.append( ival );
|
|
|
|
}
|
|
|
|
lookup.setVisibleColumns( visibleColumns );
|
|
|
|
}
|
|
|
|
else if ("columnWidths" == propertyName ) {
|
|
|
|
TQValueList<TQVariant> variantList( value.toList() );
|
|
|
|
TQValueList<int> widths;
|
|
|
|
foreach (TQValueList<TQVariant>::ConstIterator, it, variantList) {
|
|
|
|
const uint ival = (*it).toInt(&ok);
|
|
|
|
if (!ok)
|
|
|
|
return false;
|
|
|
|
widths.append( ival );
|
|
|
|
}
|
|
|
|
lookup.setColumnWidths( widths );
|
|
|
|
}
|
|
|
|
else if ("showColumnHeaders" == propertyName ) {
|
|
|
|
lookup.setColumnHeadersVisible( value.toBool() );
|
|
|
|
}
|
|
|
|
else if ("listRows" == propertyName ) {
|
|
|
|
lookup.setMaximumListRows( value.toBool() );
|
|
|
|
}
|
|
|
|
else if ("limitToList" == propertyName ) {
|
|
|
|
lookup.setLimitToList( value.toBool() );
|
|
|
|
}
|
|
|
|
else if ("displayWidget" == propertyName ) {
|
|
|
|
const uint ival = value.toUInt(&ok);
|
|
|
|
if (!ok || ival > LookupFieldSchema::ListBox)
|
|
|
|
return false;
|
|
|
|
lookup.setDisplayWidget((LookupFieldSchema::DisplayWidget)ival);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|