00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "kexicomboboxpopup.h"
00021
00022 #include "kexidatatableview.h"
00023 #include "kexitableview_p.h"
00024 #include "kexitableitem.h"
00025 #include "kexitableedit.h"
00026
00027 #include <kexidb/lookupfieldschema.h>
00028 #include <kexidb/expression.h>
00029 #include <kexidb/parser/sqlparser.h>
00030
00031 #include <kdebug.h>
00032
00033 #include <qlayout.h>
00034 #include <qevent.h>
00035
00038 class KexiComboBoxPopup_KexiTableView : public KexiDataTableView
00039 {
00040 public:
00041 KexiComboBoxPopup_KexiTableView(QWidget* parent=0)
00042 : KexiDataTableView(parent, "KexiComboBoxPopup_tv")
00043 {
00044 init();
00045 }
00046 void init()
00047 {
00048 setReadOnly( true );
00049 setLineWidth( 0 );
00050 d->moveCursorOnMouseRelease = true;
00051 KexiTableView::Appearance a(appearance());
00052 a.navigatorEnabled = false;
00054 a.backgroundAltering = false;
00055 a.fullRowSelection = true;
00056 a.rowHighlightingEnabled = true;
00057 a.rowMouseOverHighlightingEnabled = true;
00058 a.persistentSelections = false;
00059 a.rowMouseOverHighlightingColor = colorGroup().highlight();
00060 a.rowMouseOverHighlightingTextColor = colorGroup().highlightedText();
00061 a.rowHighlightingTextColor = a.rowMouseOverHighlightingTextColor;
00062 a.gridEnabled = false;
00063 setAppearance(a);
00064 setInsertingEnabled( false );
00065 setSortingEnabled( false );
00066 setVerticalHeaderVisible( false );
00067 setHorizontalHeaderVisible( false );
00068 setContextMenuEnabled( false );
00069 setScrollbarToolTipsEnabled( false );
00070 installEventFilter(this);
00071 setBottomMarginInternal( - horizontalScrollBar()->sizeHint().height() );
00072 }
00073 virtual void setData( KexiTableViewData *data, bool owner = true )
00074 { KexiTableView::setData( data, owner ); }
00075 bool setData(KexiDB::Cursor *cursor)
00076 { return KexiDataTableView::setData( cursor ); }
00077 };
00078
00079
00080
00082 class KexiComboBoxPopupPrivate
00083 {
00084 public:
00085 KexiComboBoxPopupPrivate()
00086 : int_f(0)
00087 , privateQuery(0)
00088 {
00089 max_rows = KexiComboBoxPopup::defaultMaxRows;
00090 }
00091 ~KexiComboBoxPopupPrivate() {
00092 delete int_f;
00093 delete privateQuery;
00094 }
00095
00096 KexiComboBoxPopup_KexiTableView *tv;
00097 KexiDB::Field *int_f;
00098 KexiDB::QuerySchema* privateQuery;
00099 int max_rows;
00100 };
00101
00102
00103
00104 const int KexiComboBoxPopup::defaultMaxRows = 8;
00105
00106 KexiComboBoxPopup::KexiComboBoxPopup(QWidget* parent, KexiTableViewColumn &column)
00107 : QFrame( parent, "KexiComboBoxPopup", WType_Popup )
00108 {
00109 init();
00110
00111 setData(&column, 0);
00112 }
00113
00114 KexiComboBoxPopup::KexiComboBoxPopup(QWidget* parent, KexiDB::Field &field)
00115 : QFrame( parent, "KexiComboBoxPopup", WType_Popup )
00116 {
00117 init();
00118
00119 setData(0, &field);
00120 }
00121
00122 KexiComboBoxPopup::~KexiComboBoxPopup()
00123 {
00124 delete d;
00125 }
00126
00127 void KexiComboBoxPopup::init()
00128 {
00129 d = new KexiComboBoxPopupPrivate();
00130 setPaletteBackgroundColor(palette().color(QPalette::Active,QColorGroup::Base));
00131 setLineWidth( 1 );
00132 setFrameStyle( Box | Plain );
00133
00134 d->tv = new KexiComboBoxPopup_KexiTableView(this);
00135 installEventFilter(this);
00136
00137 connect(d->tv, SIGNAL(itemReturnPressed(KexiTableItem*,int,int)),
00138 this, SLOT(slotTVItemAccepted(KexiTableItem*,int,int)));
00139
00140 connect(d->tv, SIGNAL(itemMouseReleased(KexiTableItem*,int,int)),
00141 this, SLOT(slotTVItemAccepted(KexiTableItem*,int,int)));
00142
00143 connect(d->tv, SIGNAL(itemDblClicked(KexiTableItem*,int,int)),
00144 this, SLOT(slotTVItemAccepted(KexiTableItem*,int,int)));
00145 }
00146
00147 void KexiComboBoxPopup::setData(KexiTableViewColumn *column, KexiDB::Field *field)
00148 {
00149 if (column && !field)
00150 field = column->field();
00151 if (!field) {
00152 kexiwarn << "KexiComboBoxPopup::setData(): !field" << endl;
00153 return;
00154 }
00155
00156
00157 if (column && column->relatedData()) {
00158 d->tv->setColumnStretchEnabled( true, -1 );
00159 setDataInternal( column->relatedData(), false );
00160 return;
00161 }
00162
00163 KexiDB::LookupFieldSchema *lookupFieldSchema = 0;
00164 if (field->table())
00165 lookupFieldSchema = field->table()->lookupFieldSchema( *field );
00166 delete d->privateQuery;
00167 d->privateQuery = 0;
00168 if (lookupFieldSchema) {
00169 const QValueList<uint> visibleColumns( lookupFieldSchema->visibleColumns() );
00170 const bool multipleLookupColumnJoined = visibleColumns.count() > 1;
00172 KexiDB::Cursor *cursor = 0;
00173 switch (lookupFieldSchema->rowSource().type()) {
00174 case KexiDB::LookupFieldSchema::RowSource::Table: {
00175 KexiDB::TableSchema *lookupTable
00176 = field->table()->connection()->tableSchema( lookupFieldSchema->rowSource().name() );
00177 if (!lookupTable)
00179 return;
00180 if (multipleLookupColumnJoined) {
00181 kdDebug() << "--- Orig query: " << endl;
00182 lookupTable->query()->debug();
00183 d->privateQuery = new KexiDB::QuerySchema(*lookupTable->query());
00184 }
00185 else {
00186 cursor = field->table()->connection()->prepareQuery( *lookupTable );
00187 }
00188 break;
00189 }
00190 case KexiDB::LookupFieldSchema::RowSource::Query: {
00191 KexiDB::QuerySchema *lookupQuery
00192 = field->table()->connection()->querySchema( lookupFieldSchema->rowSource().name() );
00193 if (!lookupQuery)
00195 return;
00196 if (multipleLookupColumnJoined) {
00197 kdDebug() << "--- Orig query: " << endl;
00198 lookupQuery->debug();
00199 d->privateQuery = new KexiDB::QuerySchema(*lookupQuery);
00200 }
00201 else {
00202 cursor = field->table()->connection()->prepareQuery( *lookupQuery );
00203 }
00204 break;
00205 }
00206 default:;
00207 }
00208 if (d->privateQuery) {
00209
00210 const KexiDB::QueryColumnInfo::Vector fieldsExpanded( d->privateQuery->fieldsExpanded() );
00211 uint fieldsExpandedSize( fieldsExpanded.size() );
00212 KexiDB::BaseExpr *expr = 0;
00213 int count = visibleColumns.count();
00214 for (QValueList<uint>::ConstIterator it( visibleColumns.at(count-1) ); count>0; count--, --it) {
00215 KexiDB::QueryColumnInfo *ci = ((*it) < fieldsExpandedSize) ? fieldsExpanded.at( *it ) : 0;
00216 if (!ci) {
00217 kdWarning() << "KexiComboBoxPopup::setData(): " << *it << " >= fieldsExpandedSize" << endl;
00218 continue;
00219 }
00220 KexiDB::VariableExpr *fieldExpr
00221 = new KexiDB::VariableExpr( ci->field->table()->name()+"."+ci->field->name() );
00222 fieldExpr->field = ci->field;
00223 fieldExpr->tablePositionForField = d->privateQuery->tableBoundToColumn( *it );
00224 if (expr) {
00227 KexiDB::ConstExpr *constExpr = new KexiDB::ConstExpr(CHARACTER_STRING_LITERAL, " ");
00228 expr = new KexiDB::BinaryExpr(KexiDBExpr_Arithm, constExpr, CONCATENATION, expr);
00229 expr = new KexiDB::BinaryExpr(KexiDBExpr_Arithm, fieldExpr, CONCATENATION, expr);
00230 }
00231 else
00232 expr = fieldExpr;
00233 }
00234 expr->debug();
00235 kdDebug() << expr->toString() << endl;
00236
00237 KexiDB::Field *f = new KexiDB::Field();
00238 f->setExpression( expr );
00239 d->privateQuery->addField( f );
00240 #if 0 //does not work yet
00241
00243 const int numColumntoHide = d->privateQuery->fieldsExpanded().count() - 1;
00244 for (int i=0; i < numColumntoHide; i++)
00245 d->privateQuery->setColumnVisible(i, false);
00246
00247 #endif
00248
00249 kdDebug() << "--- Private query: " << endl;
00250 d->privateQuery->debug();
00251 cursor = field->table()->connection()->prepareQuery( *d->privateQuery );
00252 }
00253 if (!cursor)
00255 return;
00256
00257 if (d->tv->data())
00258 d->tv->data()->disconnect( this );
00259 d->tv->setData( cursor );
00260
00261 connect( d->tv, SIGNAL(dataRefreshed()), this, SLOT(slotDataReloadRequested()));
00262 updateSize();
00263 return;
00264 }
00265
00266 kdWarning() << "KexiComboBoxPopup::setData(KexiTableViewColumn &): no column relatedData \n - moving to setData(KexiDB::Field &)" << endl;
00267
00268
00269 d->tv->setColumnStretchEnabled( true, -1 );
00270
00272 d->int_f = new KexiDB::Field(field->name(), KexiDB::Field::Text);
00273 KexiTableViewData *data = new KexiTableViewData();
00274 data->addColumn( new KexiTableViewColumn( *d->int_f ) );
00275 QValueVector<QString> hints = field->enumHints();
00276 for(uint i=0; i < hints.size(); i++) {
00277 KexiTableItem *item = data->createItem();
00278 (*item)[0]=QVariant(hints[i]);
00279 kdDebug() << "added: '" << hints[i] <<"'"<<endl;
00280 data->append( item );
00281 }
00282 setDataInternal( data, true );
00283 }
00284
00285 void KexiComboBoxPopup::setDataInternal( KexiTableViewData *data, bool owner )
00286 {
00287 if (d->tv->data())
00288 d->tv->data()->disconnect( this );
00289 d->tv->setData( data, owner );
00290 connect( d->tv, SIGNAL(dataRefreshed()), this, SLOT(slotDataReloadRequested()));
00291
00292 updateSize();
00293 }
00294
00295 void KexiComboBoxPopup::updateSize(int minWidth)
00296 {
00297 const int rows = QMIN( d->max_rows, d->tv->rows() );
00298
00299 d->tv->adjustColumnWidthToContents(-1);
00300
00301 KexiTableEdit *te = dynamic_cast<KexiTableEdit*>(parentWidget());
00302 const int width = QMAX( d->tv->tableSize().width(),
00303 (te ? te->totalSize().width() : (parentWidget()?parentWidget()->width():0)) );
00304 kexidbg << "KexiComboBoxPopup::updateSize(): size=" << size() << endl;
00305 resize( QMAX(minWidth, width) , d->tv->rowHeight() * rows +2 );
00306 kexidbg << "KexiComboBoxPopup::updateSize(): size after=" << size() << endl;
00307
00308
00309 d->tv->setColumnStretchEnabled(true, d->tv->columns()-1);
00310 }
00311
00312 KexiTableView* KexiComboBoxPopup::tableView()
00313 {
00314 return d->tv;
00315 }
00316
00317 void KexiComboBoxPopup::resize( int w, int h )
00318 {
00319 d->tv->horizontalScrollBar()->hide();
00320 d->tv->verticalScrollBar()->hide();
00321 d->tv->move(1,1);
00322 d->tv->resize( w-2, h-2 );
00323 QFrame::resize(w,h);
00324 update();
00325 updateGeometry();
00326 }
00327
00328 void KexiComboBoxPopup::setMaxRows(int r)
00329 {
00330 d->max_rows = r;
00331 }
00332
00333 int KexiComboBoxPopup::maxRows() const
00334 {
00335 return d->max_rows;
00336 }
00337
00338 void KexiComboBoxPopup::slotTVItemAccepted(KexiTableItem *item, int row, int)
00339 {
00340 hide();
00341 emit rowAccepted(item, row);
00342 }
00343
00344 bool KexiComboBoxPopup::eventFilter( QObject *o, QEvent *e )
00345 {
00346 if (o==this && e->type()==QEvent::Hide) {
00347 emit hidden();
00348 }
00349 else if (e->type()==QEvent::MouseButtonPress) {
00350 kdDebug() << "QEvent::MousePress" << endl;
00351 }
00352 else if (o==d->tv) {
00353 if (e->type()==QEvent::KeyPress) {
00354 QKeyEvent *ke = static_cast<QKeyEvent*>(e);
00355 const int k = ke->key();
00356 if ((ke->state()==NoButton && (k==Key_Escape || k==Key_F4))
00357 || (ke->state()==AltButton && k==Key_Up))
00358 {
00359 hide();
00360 emit cancelled();
00361 return true;
00362 }
00363 }
00364 }
00365 return QFrame::eventFilter( o, e );
00366 }
00367
00368 void KexiComboBoxPopup::slotDataReloadRequested()
00369 {
00370 updateSize();
00371 }
00372
00373 #include "kexicomboboxpopup.moc"