|
|
|
/* This file is part of the KDE project
|
|
|
|
Copyright (C) 2004-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 "kexicomboboxpopup.h"
|
|
|
|
|
|
|
|
#include "kexidatatableview.h"
|
|
|
|
#include "kexitableview_p.h"
|
|
|
|
#include "kexitableitem.h"
|
|
|
|
#include "kexitableedit.h"
|
|
|
|
|
|
|
|
#include <kexidb/lookupfieldschema.h>
|
|
|
|
#include <kexidb/expression.h>
|
|
|
|
#include <kexidb/parser/sqlparser.h>
|
|
|
|
|
|
|
|
#include <kdebug.h>
|
|
|
|
|
|
|
|
#include <tqlayout.h>
|
|
|
|
#include <tqevent.h>
|
|
|
|
|
|
|
|
/*! @internal
|
|
|
|
Helper for KexiComboBoxPopup. */
|
|
|
|
class KexiComboBoxPopup_KexiTableView : public KexiDataTableView
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
KexiComboBoxPopup_KexiTableView(TQWidget* parent=0)
|
|
|
|
: KexiDataTableView(parent, "KexiComboBoxPopup_tv")
|
|
|
|
{
|
|
|
|
init();
|
|
|
|
}
|
|
|
|
void init()
|
|
|
|
{
|
|
|
|
setReadOnly( true );
|
|
|
|
setLineWidth( 0 );
|
|
|
|
d->moveCursorOnMouseRelease = true;
|
|
|
|
KexiTableView::Appearance a(appearance());
|
|
|
|
a.navigatorEnabled = false;
|
|
|
|
//! @todo add option for backgroundAltering??
|
|
|
|
a.backgroundAltering = false;
|
|
|
|
a.fullRowSelection = true;
|
|
|
|
a.rowHighlightingEnabled = true;
|
|
|
|
a.rowMouseOverHighlightingEnabled = true;
|
|
|
|
a.persistentSelections = false;
|
|
|
|
a.rowMouseOverHighlightingColor = tqcolorGroup().highlight();
|
|
|
|
a.rowMouseOverHighlightingTextColor = tqcolorGroup().highlightedText();
|
|
|
|
a.rowHighlightingTextColor = a.rowMouseOverHighlightingTextColor;
|
|
|
|
a.gridEnabled = false;
|
|
|
|
setAppearance(a);
|
|
|
|
setInsertingEnabled( false );
|
|
|
|
setSortingEnabled( false );
|
|
|
|
setVerticalHeaderVisible( false );
|
|
|
|
setHorizontalHeaderVisible( false );
|
|
|
|
setContextMenuEnabled( false );
|
|
|
|
setScrollbarToolTipsEnabled( false );
|
|
|
|
installEventFilter(this);
|
|
|
|
setBottomMarginInternal( - horizontalScrollBar()->tqsizeHint().height() );
|
|
|
|
}
|
|
|
|
virtual void setData( KexiTableViewData *data, bool owner = true )
|
|
|
|
{ KexiTableView::setData( data, owner ); }
|
|
|
|
bool setData(KexiDB::Cursor *cursor)
|
|
|
|
{ return KexiDataTableView::setData( cursor ); }
|
|
|
|
};
|
|
|
|
|
|
|
|
//========================================
|
|
|
|
|
|
|
|
//! @internal
|
|
|
|
class KexiComboBoxPopupPrivate
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
KexiComboBoxPopupPrivate()
|
|
|
|
: int_f(0)
|
|
|
|
, privateQuery(0)
|
|
|
|
{
|
|
|
|
max_rows = KexiComboBoxPopup::defaultMaxRows;
|
|
|
|
}
|
|
|
|
~KexiComboBoxPopupPrivate() {
|
|
|
|
delete int_f;
|
|
|
|
delete privateQuery;
|
|
|
|
}
|
|
|
|
|
|
|
|
KexiComboBoxPopup_KexiTableView *tv;
|
|
|
|
KexiDB::Field *int_f; //TODO: remove this -temporary
|
|
|
|
KexiDB::QuerySchema* privateQuery;
|
|
|
|
int max_rows;
|
|
|
|
};
|
|
|
|
|
|
|
|
//========================================
|
|
|
|
|
|
|
|
const int KexiComboBoxPopup::defaultMaxRows = 8;
|
|
|
|
|
|
|
|
KexiComboBoxPopup::KexiComboBoxPopup(TQWidget* parent, KexiTableViewColumn &column)
|
|
|
|
: TQFrame( parent, "KexiComboBoxPopup", WType_Popup )
|
|
|
|
{
|
|
|
|
init();
|
|
|
|
//setup tv data
|
|
|
|
setData(&column, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
KexiComboBoxPopup::KexiComboBoxPopup(TQWidget* parent, KexiDB::Field &field)
|
|
|
|
: TQFrame( parent, "KexiComboBoxPopup", WType_Popup )
|
|
|
|
{
|
|
|
|
init();
|
|
|
|
//setup tv data
|
|
|
|
setData(0, &field);
|
|
|
|
}
|
|
|
|
|
|
|
|
KexiComboBoxPopup::~KexiComboBoxPopup()
|
|
|
|
{
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiComboBoxPopup::init()
|
|
|
|
{
|
|
|
|
d = new KexiComboBoxPopupPrivate();
|
|
|
|
setPaletteBackgroundColor(palette().color(TQPalette::Active,TQColorGroup::Base));
|
|
|
|
setLineWidth( 1 );
|
|
|
|
setFrameStyle( Box | Plain );
|
|
|
|
|
|
|
|
d->tv = new KexiComboBoxPopup_KexiTableView(this);
|
|
|
|
installEventFilter(this);
|
|
|
|
|
|
|
|
connect(d->tv, TQT_SIGNAL(itemReturnPressed(KexiTableItem*,int,int)),
|
|
|
|
this, TQT_SLOT(slotTVItemAccepted(KexiTableItem*,int,int)));
|
|
|
|
|
|
|
|
connect(d->tv, TQT_SIGNAL(itemMouseReleased(KexiTableItem*,int,int)),
|
|
|
|
this, TQT_SLOT(slotTVItemAccepted(KexiTableItem*,int,int)));
|
|
|
|
|
|
|
|
connect(d->tv, TQT_SIGNAL(itemDblClicked(KexiTableItem*,int,int)),
|
|
|
|
this, TQT_SLOT(slotTVItemAccepted(KexiTableItem*,int,int)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiComboBoxPopup::setData(KexiTableViewColumn *column, KexiDB::Field *field)
|
|
|
|
{
|
|
|
|
if (column && !field)
|
|
|
|
field = column->field();
|
|
|
|
if (!field) {
|
|
|
|
kexiwarn << "KexiComboBoxPopup::setData(): !field" << endl;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// case 1: simple related data
|
|
|
|
if (column && column->relatedData()) {
|
|
|
|
d->tv->setColumnStretchEnabled( true, -1 ); //only needed when using single column
|
|
|
|
setDataInternal( column->relatedData(), false /*!owner*/ );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// case 2: lookup field
|
|
|
|
KexiDB::LookupFieldSchema *lookupFieldSchema = 0;
|
|
|
|
if (field->table())
|
|
|
|
lookupFieldSchema = field->table()->lookupFieldSchema( *field );
|
|
|
|
delete d->privateQuery;
|
|
|
|
d->privateQuery = 0;
|
|
|
|
if (lookupFieldSchema) {
|
|
|
|
const TQValueList<uint> visibleColumns( lookupFieldSchema->visibleColumns() );
|
|
|
|
const bool multipleLookupColumnJoined = visibleColumns.count() > 1;
|
|
|
|
//! @todo support more RowSourceType's, not only table and query
|
|
|
|
KexiDB::Cursor *cursor = 0;
|
|
|
|
switch (lookupFieldSchema->rowSource().type()) {
|
|
|
|
case KexiDB::LookupFieldSchema::RowSource::Table: {
|
|
|
|
KexiDB::TableSchema *lookupTable
|
|
|
|
= field->table()->connection()->tableSchema( lookupFieldSchema->rowSource().name() );
|
|
|
|
if (!lookupTable)
|
|
|
|
//! @todo errmsg
|
|
|
|
return;
|
|
|
|
if (multipleLookupColumnJoined) {
|
|
|
|
kdDebug() << "--- Orig query: " << endl;
|
|
|
|
lookupTable->query()->debug();
|
|
|
|
d->privateQuery = new KexiDB::QuerySchema(*lookupTable->query());
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
cursor = field->table()->connection()->prepareQuery( *lookupTable );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case KexiDB::LookupFieldSchema::RowSource::Query: {
|
|
|
|
KexiDB::QuerySchema *lookupQuery
|
|
|
|
= field->table()->connection()->querySchema( lookupFieldSchema->rowSource().name() );
|
|
|
|
if (!lookupQuery)
|
|
|
|
//! @todo errmsg
|
|
|
|
return;
|
|
|
|
if (multipleLookupColumnJoined) {
|
|
|
|
kdDebug() << "--- Orig query: " << endl;
|
|
|
|
lookupQuery->debug();
|
|
|
|
d->privateQuery = new KexiDB::QuerySchema(*lookupQuery);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
cursor = field->table()->connection()->prepareQuery( *lookupQuery );
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:;
|
|
|
|
}
|
|
|
|
if (d->privateQuery) {
|
|
|
|
// append column computed using multiple columns
|
|
|
|
const KexiDB::QueryColumnInfo::Vector fieldsExpanded( d->privateQuery->fieldsExpanded() );
|
|
|
|
uint fieldsExpandedSize( fieldsExpanded.size() );
|
|
|
|
KexiDB::BaseExpr *expr = 0;
|
|
|
|
int count = visibleColumns.count();
|
|
|
|
for (TQValueList<uint>::ConstIterator it( visibleColumns.at(count-1) ); count>0; count--, --it) {
|
|
|
|
KexiDB::QueryColumnInfo *ci = ((*it) < fieldsExpandedSize) ? fieldsExpanded.at( *it ) : 0;
|
|
|
|
if (!ci) {
|
|
|
|
kdWarning() << "KexiComboBoxPopup::setData(): " << *it << " >= fieldsExpandedSize" << endl;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
KexiDB::VariableExpr *fieldExpr
|
|
|
|
= new KexiDB::VariableExpr( ci->field->table()->name()+"."+ci->field->name() );
|
|
|
|
fieldExpr->field = ci->field;
|
|
|
|
fieldExpr->tablePositionForField = d->privateQuery->tableBoundToColumn( *it );
|
|
|
|
if (expr) {
|
|
|
|
//! @todo " " separator hardcoded...
|
|
|
|
//! @todo use SQL sub-parser here...
|
|
|
|
KexiDB::ConstExpr *constExpr = new KexiDB::ConstExpr(CHARACTER_STRING_LITERAL, " ");
|
|
|
|
expr = new KexiDB::BinaryExpr(KexiDBExpr_Arithm, constExpr, CONCATENATION, expr);
|
|
|
|
expr = new KexiDB::BinaryExpr(KexiDBExpr_Arithm, fieldExpr, CONCATENATION, expr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
expr = fieldExpr;
|
|
|
|
}
|
|
|
|
expr->debug();
|
|
|
|
kdDebug() << expr->toString() << endl;
|
|
|
|
|
|
|
|
KexiDB::Field *f = new KexiDB::Field();
|
|
|
|
f->setExpression( expr );
|
|
|
|
d->privateQuery->addField( f );
|
|
|
|
#if 0 //does not work yet
|
|
|
|
// <remove later>
|
|
|
|
//! @todo temp: improved display by hiding all columns except the computed one
|
|
|
|
const int numColumntoHide = d->privateQuery->fieldsExpanded().count() - 1;
|
|
|
|
for (int i=0; i < numColumntoHide; i++)
|
|
|
|
d->privateQuery->setColumnVisible(i, false);
|
|
|
|
// </remove later>
|
|
|
|
#endif
|
|
|
|
//todo...
|
|
|
|
kdDebug() << "--- Private query: " << endl;
|
|
|
|
d->privateQuery->debug();
|
|
|
|
cursor = field->table()->connection()->prepareQuery( *d->privateQuery );
|
|
|
|
}
|
|
|
|
if (!cursor)
|
|
|
|
//! @todo errmsg
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (d->tv->KexiDataAwareObjectInterface::data())
|
|
|
|
d->tv->KexiDataAwareObjectInterface::data()->disconnect( this );
|
|
|
|
d->tv->setData( cursor );
|
|
|
|
|
|
|
|
connect( d->tv, TQT_SIGNAL(dataRefreshed()), this, TQT_SLOT(slotDataReloadRequested()));
|
|
|
|
updateSize();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
kdWarning() << "KexiComboBoxPopup::setData(KexiTableViewColumn &): no column relatedData \n - moving to setData(KexiDB::Field &)" << endl;
|
|
|
|
|
|
|
|
// case 3: enum hints
|
|
|
|
d->tv->setColumnStretchEnabled( true, -1 ); //only needed when using single column
|
|
|
|
|
|
|
|
//! @todo THIS IS PRIMITIVE: we'd need to employ KexiDB::Reference here!
|
|
|
|
d->int_f = new KexiDB::Field(field->name(), KexiDB::Field::Text);
|
|
|
|
KexiTableViewData *data = new KexiTableViewData();
|
|
|
|
data->addColumn( new KexiTableViewColumn( *d->int_f ) );
|
|
|
|
TQValueVector<TQString> hints = field->enumHints();
|
|
|
|
for(uint i=0; i < hints.size(); i++) {
|
|
|
|
KexiTableItem *item = data->createItem();//new KexiTableItem(1);
|
|
|
|
(*item)[0]=TQVariant(hints[i]);
|
|
|
|
kdDebug() << "added: '" << hints[i] <<"'"<<endl;
|
|
|
|
data->append( item );
|
|
|
|
}
|
|
|
|
setDataInternal( data, true );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiComboBoxPopup::setDataInternal( KexiTableViewData *data, bool owner )
|
|
|
|
{
|
|
|
|
if (d->tv->KexiDataAwareObjectInterface::data())
|
|
|
|
d->tv->KexiDataAwareObjectInterface::data()->disconnect( this );
|
|
|
|
d->tv->setData( data, owner );
|
|
|
|
connect( d->tv, TQT_SIGNAL(dataRefreshed()), this, TQT_SLOT(slotDataReloadRequested()));
|
|
|
|
|
|
|
|
updateSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiComboBoxPopup::updateSize(int minWidth)
|
|
|
|
{
|
|
|
|
const int rows = TQMIN( d->max_rows, d->tv->rows() );
|
|
|
|
|
|
|
|
d->tv->adjustColumnWidthToContents(-1);
|
|
|
|
|
|
|
|
KexiTableEdit *te = dynamic_cast<KexiTableEdit*>(parentWidget());
|
|
|
|
const int width = TQMAX( d->tv->tableSize().width(),
|
|
|
|
(te ? te->totalSize().width() : (parentWidget()?parentWidget()->width():0/*sanity*/)) );
|
|
|
|
kexidbg << "KexiComboBoxPopup::updateSize(): size=" << size() << endl;
|
|
|
|
resize( TQMAX(minWidth, width)/*+(d->tv->columns()>1?2:0)*/ /*(d->updateSizeCalled?0:1)*/, d->tv->rowHeight() * rows +2 );
|
|
|
|
kexidbg << "KexiComboBoxPopup::updateSize(): size after=" << size() << endl;
|
|
|
|
|
|
|
|
//stretch the last column
|
|
|
|
d->tv->setColumnStretchEnabled(true, d->tv->columns()-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
KexiTableView* KexiComboBoxPopup::tableView()
|
|
|
|
{
|
|
|
|
return d->tv;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiComboBoxPopup::resize( int w, int h )
|
|
|
|
{
|
|
|
|
d->tv->horizontalScrollBar()->hide();
|
|
|
|
d->tv->verticalScrollBar()->hide();
|
|
|
|
d->tv->move(1,1);
|
|
|
|
d->tv->resize( w-2, h-2 );
|
|
|
|
TQFrame::resize(w,h);
|
|
|
|
update();
|
|
|
|
updateGeometry();
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiComboBoxPopup::setMaxRows(int r)
|
|
|
|
{
|
|
|
|
d->max_rows = r;
|
|
|
|
}
|
|
|
|
|
|
|
|
int KexiComboBoxPopup::maxRows() const
|
|
|
|
{
|
|
|
|
return d->max_rows;
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiComboBoxPopup::slotTVItemAccepted(KexiTableItem *item, int row, int)
|
|
|
|
{
|
|
|
|
hide();
|
|
|
|
emit rowAccepted(item, row);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool KexiComboBoxPopup::eventFilter( TQObject *o, TQEvent *e )
|
|
|
|
{
|
|
|
|
if (TQT_BASE_OBJECT(o)==TQT_BASE_OBJECT(this) && e->type()==TQEvent::Hide) {
|
|
|
|
emit hidden();
|
|
|
|
}
|
|
|
|
else if (e->type()==TQEvent::MouseButtonPress) {
|
|
|
|
kdDebug() << "TQEvent::MousePress" << endl;
|
|
|
|
}
|
|
|
|
else if (TQT_BASE_OBJECT(o)==TQT_BASE_OBJECT(d->tv)) {
|
|
|
|
if (e->type()==TQEvent::KeyPress) {
|
|
|
|
TQKeyEvent *ke = TQT_TQKEYEVENT(e);
|
|
|
|
const int k = ke->key();
|
|
|
|
if ((ke->state()==Qt::NoButton && (k==Key_Escape || k==Key_F4))
|
|
|
|
|| (ke->state()==AltButton && k==Key_Up))
|
|
|
|
{
|
|
|
|
hide();
|
|
|
|
emit cancelled();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return TQFrame::eventFilter( o, e );
|
|
|
|
}
|
|
|
|
|
|
|
|
void KexiComboBoxPopup::slotDataReloadRequested()
|
|
|
|
{
|
|
|
|
updateSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
#include "kexicomboboxpopup.moc"
|