00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qlayout.h>
00022 #include <qstyle.h>
00023 #include <qwindowsstyle.h>
00024 #include <qpainter.h>
00025 #include <qapplication.h>
00026 #include <qclipboard.h>
00027
00028 #include "kexicomboboxtableedit.h"
00029 #include <widget/utils/kexicomboboxdropdownbutton.h>
00030 #include "kexicomboboxpopup.h"
00031 #include "kexitableview.h"
00032 #include "kexitableitem.h"
00033 #include "kexi.h"
00034
00035 #include <klineedit.h>
00036
00038 class KexiComboBoxTableEdit::Private
00039 {
00040 public:
00041 Private()
00042 : popup(0)
00043 , currentEditorWidth(0)
00044 , visibleTableViewColumn(0)
00045 , internalEditor(0)
00046 {
00047 }
00048 ~Private()
00049 {
00050 delete internalEditor;
00051 delete visibleTableViewColumn;
00052 }
00053
00054 KPushButton *button;
00055 KexiComboBoxPopup *popup;
00056 int currentEditorWidth;
00057 QSize totalSize;
00058 KexiTableViewColumn* visibleTableViewColumn;
00059 KexiTableEdit* internalEditor;
00060 };
00061
00062
00063
00064 KexiComboBoxTableEdit::KexiComboBoxTableEdit(KexiTableViewColumn &column, QWidget *parent)
00065 : KexiInputTableEdit(column, parent)
00066 , KexiComboBoxBase()
00067 , d(new Private())
00068 {
00069 setName("KexiComboBoxTableEdit");
00070 m_setVisibleValueOnSetValueInternal = true;
00071 d->button = new KexiComboBoxDropDownButton( parentWidget() );
00072 d->button->hide();
00073 d->button->setFocusPolicy( NoFocus );
00074 connect(d->button, SIGNAL(clicked()), this, SLOT(slotButtonClicked()));
00075
00076 connect(m_lineedit, SIGNAL(textChanged(const QString&)), this, SLOT(slotLineEditTextChanged(const QString&)));
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100 }
00101
00102 KexiComboBoxTableEdit::~KexiComboBoxTableEdit()
00103 {
00104 delete d;
00105 }
00106
00107 void KexiComboBoxTableEdit::createInternalEditor(KexiDB::QuerySchema& schema)
00108 {
00109 if (!m_column->visibleLookupColumnInfo || d->visibleTableViewColumn)
00110 return;
00111 const KexiDB::Field::Type t = m_column->visibleLookupColumnInfo->field->type();
00113 KexiCellEditorFactoryItem *item = KexiCellEditorFactory::item(t);
00114 if (!item || item->className()=="KexiInputTableEdit")
00115 return;
00116
00117
00118
00119 KexiDB::QueryColumnInfo *ci = m_column->visibleLookupColumnInfo;
00120 KexiDB::QueryColumnInfo *visibleLookupColumnInfo = 0;
00121 if (ci->indexForVisibleLookupValue() != -1) {
00122
00123 visibleLookupColumnInfo = schema.expandedOrInternalField( ci->indexForVisibleLookupValue() );
00124 }
00125 d->visibleTableViewColumn = new KexiTableViewColumn(schema, *ci, visibleLookupColumnInfo);
00127 d->internalEditor = KexiCellEditorFactory::createEditor(*d->visibleTableViewColumn, 0);
00128 m_lineedit->hide();
00129 }
00130
00131 KexiComboBoxPopup *KexiComboBoxTableEdit::popup() const
00132 {
00133 return d->popup;
00134 }
00135
00136 void KexiComboBoxTableEdit::setPopup(KexiComboBoxPopup *popup)
00137 {
00138 d->popup = popup;
00139 }
00140
00141 void KexiComboBoxTableEdit::showFocus( const QRect& r, bool readOnly )
00142 {
00143
00144 updateFocus( r );
00145 d->button->setEnabled(!readOnly);
00146 if (readOnly)
00147 d->button->hide();
00148 else
00149 d->button->show();
00150 }
00151
00152 void KexiComboBoxTableEdit::resize(int w, int h)
00153 {
00154 d->totalSize = QSize(w,h);
00155 if (!column()->isReadOnly()) {
00156 d->button->resize( h, h );
00157 QWidget::resize(w - d->button->width(), h);
00158 }
00159 m_rightMarginWhenFocused = m_rightMargin + (column()->isReadOnly() ? 0 : d->button->width());
00160 QRect r( pos().x(), pos().y(), w+1, h+1 );
00161 if (m_scrollView)
00162 r.moveBy(m_scrollView->contentsX(), m_scrollView->contentsY());
00163 updateFocus( r );
00164 if (popup()) {
00165 popup()->updateSize();
00166 }
00167 }
00168
00169
00170 void KexiComboBoxTableEdit::updateFocus( const QRect& r )
00171 {
00172 if (!column()->isReadOnly()) {
00173 if (d->button->width() > r.width())
00174 moveChild(d->button, r.right() + 1, r.top());
00175 else
00176 moveChild(d->button, r.right() - d->button->width(), r.top() );
00177 }
00178 }
00179
00180 void KexiComboBoxTableEdit::hideFocus()
00181 {
00182 d->button->hide();
00183 }
00184
00185 QVariant KexiComboBoxTableEdit::visibleValue()
00186 {
00187 return KexiComboBoxBase::visibleValue();
00188
00189
00190
00191
00192
00193 }
00194
00195 void KexiComboBoxTableEdit::clear()
00196 {
00197 m_lineedit->clear();
00198 KexiComboBoxBase::clear();
00199 }
00200
00201 bool KexiComboBoxTableEdit::valueChanged()
00202 {
00203 const tristate res = valueChangedInternal();
00204 if (~res)
00205 return KexiInputTableEdit::valueChanged();
00206 return res == true;
00207 }
00208
00209 void KexiComboBoxTableEdit::paintFocusBorders( QPainter *p, QVariant &, int x, int y, int w, int h )
00210 {
00211
00212 if (!column()->isReadOnly()) {
00213 if (w > d->button->width())
00214 w -= d->button->width();
00215 }
00216 p->drawRect(x, y, w, h);
00217 }
00218
00219 void KexiComboBoxTableEdit::setupContents( QPainter *p, bool focused, const QVariant& val,
00220 QString &txt, int &align, int &x, int &y_offset, int &w, int &h )
00221 {
00222 if (d->internalEditor) {
00223 d->internalEditor->setupContents( p, focused, val, txt, align, x, y_offset, w, h );
00224 }
00225 else {
00226 KexiInputTableEdit::setupContents( p, focused, val, txt, align, x, y_offset, w, h );
00227 }
00228 if (!column()->isReadOnly() && focused && (w > d->button->width()))
00229 w -= (d->button->width() - x);
00230 if (!val.isNull()) {
00231 KexiTableViewData *relData = column()->relatedData();
00232 KexiDB::LookupFieldSchema *lookupFieldSchema = 0;
00233 if (relData) {
00234 int rowToHighlight;
00235 txt = valueForString(val.toString(), &rowToHighlight, 0, 1);
00236 }
00237 else if ((lookupFieldSchema = this->lookupFieldSchema())) {
00238
00239
00240
00241
00242
00243
00244 }
00245 else {
00246
00247 txt = field()->enumHint( val.toInt() );
00248 }
00249 }
00250 }
00251
00252 void KexiComboBoxTableEdit::slotButtonClicked()
00253 {
00254
00255
00256 if (column()->isReadOnly() || !d->button->isEnabled())
00257 return;
00258
00259 if (m_mouseBtnPressedWhenPopupVisible) {
00260 m_mouseBtnPressedWhenPopupVisible = false;
00261 d->button->setOn(false);
00262 return;
00263 }
00264 kdDebug() << "KexiComboBoxTableEdit::slotButtonClicked()" << endl;
00265 if (!popup() || !popup()->isVisible()) {
00266 kdDebug() << "SHOW POPUP" << endl;
00267 showPopup();
00268 d->button->setOn(true);
00269 }
00270 }
00271
00272 void KexiComboBoxTableEdit::slotPopupHidden()
00273 {
00274 d->button->setOn(false);
00275
00276 }
00277
00278 void KexiComboBoxTableEdit::updateButton()
00279 {
00280 d->button->setOn(popup()->isVisible());
00281 }
00282
00283 void KexiComboBoxTableEdit::hide()
00284 {
00285 KexiInputTableEdit::hide();
00286 KexiComboBoxBase::hide();
00287 d->button->setOn(false);
00288 }
00289
00290 void KexiComboBoxTableEdit::show()
00291 {
00292 KexiInputTableEdit::show();
00293 if (!column()->isReadOnly()) {
00294 d->button->show();
00295 }
00296 }
00297
00298 bool KexiComboBoxTableEdit::handleKeyPress( QKeyEvent *ke, bool editorActive )
00299 {
00300 const int k = ke->key();
00301 if ((ke->state()==NoButton && k==Qt::Key_F4)
00302 || (ke->state()==AltButton && k==Qt::Key_Down))
00303 {
00304
00305 slotButtonClicked();
00306 return true;
00307 }
00308 else if (editorActive) {
00309 const bool enterPressed = k==Qt::Key_Enter || k==Qt::Key_Return;
00310 if (enterPressed && m_internalEditorValueChanged) {
00311 createPopup(false);
00312 selectItemForEnteredValueInLookupTable( m_userEnteredValue );
00313 return false;
00314 }
00315
00316 return handleKeyPressForPopup( ke );
00317 }
00318
00319 return false;
00320 }
00321
00322 void KexiComboBoxTableEdit::slotLineEditTextChanged(const QString& s)
00323 {
00324 slotInternalEditorValueChanged(s);
00325 }
00326
00327 int KexiComboBoxTableEdit::widthForValue( QVariant &val, const QFontMetrics &fm )
00328 {
00329 KexiTableViewData *relData = column() ? column()->relatedData() : 0;
00330 if (lookupFieldSchema() || relData) {
00331
00332
00334 return QMAX(KEXITV_MINIMUM_COLUMN_WIDTH, fm.width(val.toString()));
00335 }
00336
00337 QValueVector<QString> hints = field()->enumHints();
00338 bool ok;
00339 int idx = val.toInt(&ok);
00340 if (!ok || idx < 0 || idx > int(hints.size()-1))
00341 return KEXITV_MINIMUM_COLUMN_WIDTH;
00342 QString txt = hints.at( idx, &ok );
00343 if (!ok)
00344 return KEXITV_MINIMUM_COLUMN_WIDTH;
00345 return fm.width( txt );
00346 }
00347
00348 bool KexiComboBoxTableEdit::eventFilter( QObject *o, QEvent *e )
00349 {
00350 if (!column()->isReadOnly() && e->type()==QEvent::MouseButtonPress && m_scrollView) {
00351 QPoint gp = static_cast<QMouseEvent*>(e)->globalPos()
00352 + QPoint(m_scrollView->childX(d->button), m_scrollView->childY(d->button));
00353 QRect r(d->button->mapToGlobal(d->button->geometry().topLeft()),
00354 d->button->mapToGlobal(d->button->geometry().bottomRight()));
00355 if (o==popup() && popup()->isVisible() && r.contains( gp )) {
00356 m_mouseBtnPressedWhenPopupVisible = true;
00357 }
00358 }
00359 return false;
00360 }
00361
00362 QSize KexiComboBoxTableEdit::totalSize() const
00363 {
00364 return d->totalSize;
00365 }
00366
00367 QWidget *KexiComboBoxTableEdit::internalEditor() const
00368 {
00369 return m_lineedit;
00370 }
00371
00372 void KexiComboBoxTableEdit::moveCursorToEndInInternalEditor()
00373 {
00374 moveCursorToEnd();
00375 }
00376
00377 void KexiComboBoxTableEdit::selectAllInInternalEditor()
00378 {
00379 selectAll();
00380 }
00381
00382 void KexiComboBoxTableEdit::moveCursorToEnd()
00383 {
00384 m_lineedit->end(false);
00385 }
00386
00387 void KexiComboBoxTableEdit::moveCursorToStart()
00388 {
00389 m_lineedit->home(false);
00390 }
00391
00392 void KexiComboBoxTableEdit::selectAll()
00393 {
00394 m_lineedit->selectAll();
00395 }
00396
00397 void KexiComboBoxTableEdit::setValueInInternalEditor(const QVariant& value)
00398 {
00399 m_lineedit->setText(value.toString());
00400 }
00401
00402 QVariant KexiComboBoxTableEdit::valueFromInternalEditor()
00403 {
00404 return m_lineedit->text();
00405 }
00406
00407 QPoint KexiComboBoxTableEdit::mapFromParentToGlobal(const QPoint& pos) const
00408 {
00409 KexiTableView *tv = dynamic_cast<KexiTableView*>(m_scrollView);
00410 if (!tv)
00411 return QPoint(-1,-1);
00412 return tv->viewport()->mapToGlobal(pos);
00413 }
00414
00415 int KexiComboBoxTableEdit::popupWidthHint() const
00416 {
00417 return m_lineedit->width() + m_leftMargin + m_rightMarginWhenFocused;
00418 }
00419
00420 void KexiComboBoxTableEdit::handleCopyAction(const QVariant& value, const QVariant& visibleValue)
00421 {
00422 Q_UNUSED(value);
00424 qApp->clipboard()->setText( visibleValue.toString() );
00425 }
00426
00427 void KexiComboBoxTableEdit::handleAction(const QString& actionName)
00428 {
00429 const bool alreadyVisible = m_lineedit->isVisible();
00430
00431 if (actionName=="edit_paste") {
00432 if (!alreadyVisible) {
00433 emit editRequested();
00434 m_lineedit->clear();
00435 }
00437 setValueInInternalEditor( qApp->clipboard()->text() );
00438 }
00439 else
00440 KexiInputTableEdit::handleAction(actionName);
00441 }
00442
00443
00444 KEXI_CELLEDITOR_FACTORY_ITEM_IMPL(KexiComboBoxEditorFactoryItem, KexiComboBoxTableEdit)
00445
00446 #include "kexicomboboxtableedit.moc"