kexi

kexicomboboxbase.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2002 Peter Simonsson <psn@linux.se>
00003    Copyright (C) 2003-2007 Jaroslaw Staniek <js@iidea.pl>
00004 
00005    This program is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Library General Public
00007    License as published by the Free Software Foundation; either
00008    version 2 of the License, or (at your option) any later version.
00009 
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this program; see the file COPYING.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018  * Boston, MA 02110-1301, USA.
00019  */
00020 
00021 #include <qlayout.h>
00022 #include <qstyle.h>
00023 #include <qwindowsstyle.h>
00024 #include <qpainter.h>
00025 
00026 #include "kexicomboboxbase.h"
00027 #include <widget/utils/kexicomboboxdropdownbutton.h>
00028 #include "kexicomboboxpopup.h"
00029 #include "kexitableview.h"
00030 #include "kexitableitem.h"
00031 #include "kexi.h"
00032 
00033 #include <klineedit.h>
00034 
00035 KexiComboBoxBase::KexiComboBoxBase()
00036 {
00037     m_internalEditorValueChanged = false; //user has text or other value inside editor
00038     m_slotInternalEditorValueChanged_enabled = true;
00039     m_mouseBtnPressedWhenPopupVisible = false;
00040     m_insideCreatePopup = false;
00041     m_setValueOrTextInInternalEditor_enabled = true;
00042     m_updatePopupSelectionOnShow = true;
00043     m_moveCursorToEndInInternalEditor_enabled = true;
00044     m_selectAllInInternalEditor_enabled = true;
00045     m_setValueInInternalEditor_enabled = true;
00046     m_setVisibleValueOnSetValueInternal = false;
00047 }
00048 
00049 KexiComboBoxBase::~KexiComboBoxBase()
00050 {
00051 }
00052 
00053 KexiDB::LookupFieldSchema *KexiComboBoxBase::lookupFieldSchema() const
00054 {
00055     if (field() && field()->table()) {
00056         KexiDB::LookupFieldSchema *lookupFieldSchema = field()->table()->lookupFieldSchema( *field() );
00057         if (lookupFieldSchema && !lookupFieldSchema->rowSource().name().isEmpty())
00058             return lookupFieldSchema;
00059     }
00060     return 0;
00061 }
00062 
00063 int KexiComboBoxBase::rowToHighlightForLookupTable() const
00064 {
00065     if (!popup())
00066         return -1;//err
00067     KexiDB::LookupFieldSchema *lookupFieldSchema = this->lookupFieldSchema();
00068     if (!lookupFieldSchema)
00069         return -1;
00070     if (lookupFieldSchema->boundColumn()==-1)
00071         return -1; //err
00072     bool ok;
00073     const int rowUid = origValue().toInt();
00075     KexiTableViewData *tvData = popup()->tableView()->data();
00076     const int boundColumn = lookupFieldSchema->boundColumn();
00077     KexiTableViewData::Iterator it(tvData->iterator());
00078     int row=0;
00079     for (;it.current();++it, row++)
00080     {
00081         if (it.current()->at(boundColumn).toInt(&ok) == rowUid && ok || !ok)
00082             break;
00083     }
00084     if (!ok || !it.current()) //item not found: highlight 1st row, if available
00085         return -1;
00086     return row;
00087 }
00088 
00089 void KexiComboBoxBase::setValueInternal(const QVariant& add_, bool removeOld)
00090 {
00091     Q_UNUSED(removeOld);
00092     m_mouseBtnPressedWhenPopupVisible = false;
00093     m_updatePopupSelectionOnShow = true;
00094     QString add(add_.toString());
00095     if (add.isEmpty()) {
00096         KexiTableViewData *relData = column() ? column()->relatedData() : 0;
00097         QVariant valueToSet;
00098         bool hasValueToSet = true;
00099         int rowToHighlight = -1;
00100         KexiDB::LookupFieldSchema *lookupFieldSchema = this->lookupFieldSchema();
00101         if (lookupFieldSchema) {
00102             //use 'lookup field' model
00104             if (lookupFieldSchema->boundColumn()==-1)
00106                 return;
00107             if (m_setVisibleValueOnSetValueInternal) {
00108                 //only for table views
00109                 if (!popup())
00110                     createPopup(false);
00111             }
00112             if (popup()) {
00113                 const int rowToHighlight = rowToHighlightForLookupTable();
00114                 popup()->tableView()->setHighlightedRow(rowToHighlight);
00115 
00116                 const int visibleColumn = lookupFieldSchema->visibleColumn( popup()->tableView()->data()->columnsCount() );
00117                 if (m_setVisibleValueOnSetValueInternal && -1!=visibleColumn) {
00118                     //only for table views
00119                     KexiTableItem *it = popup()->tableView()->highlightedItem();
00120                     if (it)
00121                         valueToSet = it->at( visibleColumn );
00122                 }
00123                 else {
00124                     hasValueToSet = false;
00125                 }
00126             }
00127         }
00128         else if (relData) {
00129             //use 'related table data' model
00130             valueToSet = valueForString(origValue().toString(), &rowToHighlight, 0, 1);
00131         }
00132         else {
00133             //use 'enum hints' model
00134             const int row = origValue().toInt();
00135             valueToSet = field()->enumHint(row).stripWhiteSpace();
00136         }
00137         if (hasValueToSet)
00138             setValueOrTextInInternalEditor( valueToSet );
00139         /*impl.*/moveCursorToEndInInternalEditor();
00140         /*impl.*/selectAllInInternalEditor();
00141         
00142         if (popup()) {
00143             if (origValue().isNull()) {
00144                 popup()->tableView()->clearSelection();
00145                 popup()->tableView()->setHighlightedRow(0);
00146             } else {
00147                 if (relData) {
00148                     if (rowToHighlight!=-1)
00149                         popup()->tableView()->setHighlightedRow(rowToHighlight);
00150                 }
00151                 else if (!lookupFieldSchema) {
00152                     //popup()->tableView()->selectRow(origValue().toInt());
00153                     popup()->tableView()->setHighlightedRow(origValue().toInt());
00154                 }
00155             }
00156         }
00157     }
00158     else {
00159         //todo: autocompl.?
00160         if (popup())
00161             popup()->tableView()->clearSelection();
00162         /*impl.*/setValueInInternalEditor(add); //not setLineEditText(), because 'add' is entered by user!
00163         //setLineEditText( add );
00164         /*impl.*/moveCursorToEndInInternalEditor();
00165     }
00166 }
00167 
00168 KexiTableItem* KexiComboBoxBase::selectItemForEnteredValueInLookupTable(const QVariant& v)
00169 {
00170     KexiDB::LookupFieldSchema *lookupFieldSchema = this->lookupFieldSchema();
00171     if (!popup() || !lookupFieldSchema)
00172         return 0; //safety
00173 //-not effective for large sets: please cache it!
00174 //.stripWhiteSpace() is not generic!
00175 
00176     const bool valueIsText = v.type()==QVariant::String || v.type()==QVariant::CString; //most common case
00177     const QString txt( valueIsText ? v.toString().stripWhiteSpace().lower() : QString::null );
00178     KexiTableViewData *lookupData = popup()->tableView()->data();
00179     const int visibleColumn = lookupFieldSchema->visibleColumn( lookupData->columnsCount() );
00180     if (-1 == visibleColumn)
00181         return 0;
00182     KexiTableViewData::Iterator it(lookupData->iterator());
00183     int row;
00184     for (row = 0;it.current();++it, row++) {
00185         if (valueIsText) {
00186             if (it.current()->at(visibleColumn).toString().stripWhiteSpace().lower() == txt)
00187                 break;
00188         }
00189         else {
00190             if (it.current()->at(visibleColumn) == v)
00191                 break;
00192         }
00193     }
00194 
00195     m_setValueOrTextInInternalEditor_enabled = false; // <-- this is the entered value, 
00196                                                       //     so do not change the internal editor's contents
00197     if (it.current())
00198         popup()->tableView()->selectRow(row);
00199     else
00200         popup()->tableView()->clearSelection();
00201 
00202     m_setValueOrTextInInternalEditor_enabled = true;
00203 
00204     return it.current();
00205 }
00206 
00207 QString KexiComboBoxBase::valueForString(const QString& str, int* row, 
00208     uint lookInColumn, uint returnFromColumn, bool allowNulls)
00209 {
00210     KexiTableViewData *relData = column() ? column()->relatedData() : 0;
00211     if (!relData)
00212         return QString::null; //safety
00213     //use 'related table data' model
00214     //-not effective for large sets: please cache it!
00215     //.stripWhiteSpace() is not generic!
00216 
00217     const QString txt = str.stripWhiteSpace().lower();
00218     KexiTableViewData::Iterator it( relData->iterator() );
00219     for (*row = 0;it.current();++it, (*row)++) {
00220         if (it.current()->at(lookInColumn).toString().stripWhiteSpace().lower()==txt)
00221             break;
00222     }
00223     if (it.current())
00224         return it.current()->at(returnFromColumn).toString();
00225 
00226     *row = -1;
00227 
00228     if (column() && column()->relatedDataEditable())
00229         return str; //new value entered and that's allowed
00230 
00231     kexiwarn << "KexiComboBoxBase::valueForString(): no related row found, ID will be painted!" << endl;
00232     if (allowNulls)
00233         return QString::null;
00234     return str; //for sanity but it's weird to show id to the user
00235 }
00236 
00237 QVariant KexiComboBoxBase::value()
00238 {
00239     KexiTableViewData *relData = column() ? column()->relatedData() : 0;
00240     KexiDB::LookupFieldSchema *lookupFieldSchema = 0;
00241     if (relData) {
00242         if (m_internalEditorValueChanged) {
00243             //we've user-entered text: look for id
00244 //TODO: make error if matching text not found?
00245             int rowToHighlight;
00246             return valueForString(m_userEnteredValue.toString(), &rowToHighlight, 1, 0, true/*allowNulls*/);
00247         }
00248         else {
00249             //use 'related table data' model
00250             KexiTableItem *it = popup() ? popup()->tableView()->selectedItem() : 0;
00251             return it ? it->at(0) : origValue();//QVariant();
00252         }
00253     }
00254     else if ((lookupFieldSchema = this->lookupFieldSchema()))
00255     {
00256         if (lookupFieldSchema->boundColumn()==-1)
00257             return origValue();
00258         KexiTableItem *it = popup() ? popup()->tableView()->selectedItem() : 0;
00259         if ( m_internalEditorValueChanged && !m_userEnteredValue.toString().isEmpty()) { //
00260             //try to select a row using the user-entered text
00261             if (!popup()) {
00262                 QVariant prevUserEnteredValue = m_userEnteredValue;
00263                 createPopup(false);
00264                 m_userEnteredValue = prevUserEnteredValue;
00265             }
00266             it = selectItemForEnteredValueInLookupTable( m_userEnteredValue );
00267         }
00268         return it ? it->at( lookupFieldSchema->boundColumn() ) : QVariant();
00269     }
00270     else if (popup()) {
00271         //use 'enum hints' model
00272         const int row = popup()->tableView()->currentRow();
00273         if (row>=0)
00274             return QVariant( row );
00275     }
00276 
00277     if (valueFromInternalEditor().toString().isEmpty())
00278         return QVariant();
00281     return origValue(); //unchanged
00282 }
00283 
00284 QVariant KexiComboBoxBase::visibleValueForLookupField()
00285 {
00286     KexiDB::LookupFieldSchema *lookupFieldSchema = this->lookupFieldSchema();
00287     if (!popup() || !lookupFieldSchema)
00288         return QVariant();
00289     const int visibleColumn = lookupFieldSchema->visibleColumn( popup()->tableView()->data()->columnsCount() );
00290     if (-1 == visibleColumn)
00291         return QVariant();
00292     KexiTableItem *it = popup()->tableView()->selectedItem();
00293     return it ? it->at( QMIN( (uint)visibleColumn, it->count()-1)/*sanity*/ ) : QVariant();
00294 }
00295 
00296 QVariant KexiComboBoxBase::visibleValue()
00297 {
00298     return m_visibleValue;
00299 }
00300 
00301 void KexiComboBoxBase::clear()
00302 {
00303     if (popup())
00304         popup()->hide();
00305     slotInternalEditorValueChanged(QVariant());
00306 }
00307 
00308 tristate KexiComboBoxBase::valueChangedInternal()
00309 {
00310     //avoid comparing values:
00311     KexiTableViewData *relData = column() ? column()->relatedData() : 0;
00312     KexiDB::LookupFieldSchema *lookupFieldSchema = this->lookupFieldSchema();
00313     if (relData || lookupFieldSchema) {
00314         if (m_internalEditorValueChanged)
00315             return true;
00316 
00317         //use 'related table data' model
00318         KexiTableItem *it = popup() ? popup()->tableView()->selectedItem() : 0;
00319         if (!it)
00320             return false;
00321     }
00322     else {
00323         //use 'enum hints' model
00324         const int row = popup() ? popup()->tableView()->currentRow() : -1;
00325         if (row<0 && !m_internalEditorValueChanged/*true if text box is cleared*/)
00326             return false;
00327     }
00328 
00329     return cancelled;
00330 }
00331 
00332 bool KexiComboBoxBase::valueIsNull()
00333 {
00334 //  bool ok;
00335     QVariant v( value() );
00336     return v.isNull();
00337 //  return !ok || v.isNull();
00338 }
00339 
00340 bool KexiComboBoxBase::valueIsEmpty()
00341 {
00342     return valueIsNull();
00343 }
00344 
00345 void KexiComboBoxBase::showPopup()
00346 {
00347     createPopup(true);
00348 }
00349 
00350 void KexiComboBoxBase::createPopup(bool show)
00351 {
00352     if (!field())
00353         return;
00354     m_insideCreatePopup = true;
00355     QWidget* thisWidget = dynamic_cast<QWidget*>(this);
00356     QWidget *widgetToFocus = internalEditor() ? internalEditor() : thisWidget;
00357     if (!popup()) {
00358         setPopup( column() ? new KexiComboBoxPopup(thisWidget, *column()) 
00359             : new KexiComboBoxPopup(thisWidget, *field()) );
00360         QObject::connect(popup(), SIGNAL(rowAccepted(KexiTableItem*,int)), 
00361             thisWidget, SLOT(slotRowAccepted(KexiTableItem*,int)));
00362         QObject::connect(popup()->tableView(), SIGNAL(itemSelected(KexiTableItem*)),
00363             thisWidget, SLOT(slotItemSelected(KexiTableItem*)));
00364 
00365         popup()->setFocusProxy( widgetToFocus );    
00366         popup()->tableView()->setFocusProxy( widgetToFocus );
00367         popup()->installEventFilter(thisWidget);
00368 
00369         if (origValue().isNull())
00370             popup()->tableView()->clearSelection();
00371         else {
00372             popup()->tableView()->selectRow( 0 );
00373             popup()->tableView()->setHighlightedRow( 0 );
00374         }
00375     }
00376     if (show && internalEditor() && !internalEditor()->isVisible())
00377         /*emit*/editRequested();
00378 
00379     QPoint posMappedToGlobal = mapFromParentToGlobal(thisWidget->pos());
00380     if (posMappedToGlobal != QPoint(-1,-1)) {
00382         popup()->move( posMappedToGlobal + QPoint(0, thisWidget->height()) );
00383         //to avoid flickering: first resize to 0-height, then show and resize back to prev. height
00384         const int w = popupWidthHint();
00385         popup()->resize(w, 0);
00386         if (show)
00387             popup()->show();
00388         popup()->updateSize(w);
00389         if (m_updatePopupSelectionOnShow) {
00390             int rowToHighlight = -1;
00391             KexiDB::LookupFieldSchema *lookupFieldSchema = this->lookupFieldSchema();
00392             KexiTableViewData *relData = column() ? column()->relatedData() : 0;
00393             if (lookupFieldSchema) {
00394                 rowToHighlight = rowToHighlightForLookupTable();
00395             }
00396             else if (relData) {
00397                 (void)valueForString(origValue().toString(), &rowToHighlight, 0, 1);
00398             }
00399             else //enum hint
00400                 rowToHighlight = origValue().toInt();
00401 
00402 /*-->*/ m_moveCursorToEndInInternalEditor_enabled = show;
00403             m_selectAllInInternalEditor_enabled = show;
00404             m_setValueInInternalEditor_enabled = show;
00405             if (rowToHighlight==-1) {
00406                 rowToHighlight = QMAX( popup()->tableView()->highlightedRow(), 0);
00407                 setValueInInternalEditor(QVariant());
00408             }
00409             popup()->tableView()->selectRow( rowToHighlight );
00410             popup()->tableView()->setHighlightedRow( rowToHighlight );
00411             if (rowToHighlight < popup()->tableView()->rowsPerPage())
00412                 popup()->tableView()->ensureCellVisible( 0, -1 );
00413 
00414 /*-->*/ m_moveCursorToEndInInternalEditor_enabled = true;
00415             m_selectAllInInternalEditor_enabled = true;
00416             m_setValueInInternalEditor_enabled = true;
00417         }
00418     }
00419 
00420     if (show) {
00421         moveCursorToEndInInternalEditor();
00422         selectAllInInternalEditor();
00423         widgetToFocus->setFocus();
00424     }
00425     m_insideCreatePopup = false;
00426 }
00427 
00428 void KexiComboBoxBase::hide()
00429 {
00430     if (popup())
00431         popup()->hide();
00432 }
00433 
00434 void KexiComboBoxBase::slotRowAccepted(KexiTableItem * item, int row)
00435 {
00436     Q_UNUSED(row);
00437     //update our value
00438     //..nothing to do?
00439     updateButton();
00440     slotItemSelected(item);
00441     /*emit*/acceptRequested();
00442 }
00443 
00444 void KexiComboBoxBase::acceptPopupSelection()
00445 {
00446     if (!popup())
00447         return;
00448     KexiTableItem *item = popup()->tableView()->highlightedItem();
00449     if (item) {
00450         popup()->tableView()->selectRow( popup()->tableView()->highlightedRow() );
00451         slotRowAccepted(item, -1);
00452     }
00453     popup()->hide();
00454 }
00455 
00456 void KexiComboBoxBase::slotItemSelected(KexiTableItem*)
00457 {
00458     kexidbg << "KexiComboBoxBase::slotItemSelected(): m_visibleValue = " << m_visibleValue << endl;
00459 
00460     QVariant valueToSet;
00461     KexiTableViewData *relData = column() ? column()->relatedData() : 0;
00462     KexiDB::LookupFieldSchema *lookupFieldSchema = this->lookupFieldSchema();
00463 
00464     m_visibleValue = lookupFieldSchema ? visibleValueForLookupField() : QVariant();
00465 
00466     if (relData) {
00467         //use 'related table data' model
00468         KexiTableItem *item = popup()->tableView()->selectedItem();
00469         if (item)
00470             valueToSet = item->at(1);
00471     }
00472     else if (lookupFieldSchema) {
00473         KexiTableItem *item = popup()->tableView()->selectedItem();
00474         const int visibleColumn = lookupFieldSchema->visibleColumn( popup()->tableView()->data()->columnsCount() );
00475         if (item && visibleColumn!=-1 /* && (int)item->size() >= visibleColumn --already checked*/) {
00476             valueToSet = item->at( QMIN( (uint)visibleColumn, item->count()-1)/*sanity*/ );
00477         }
00478     }
00479     else {
00480         //use 'enum hints' model
00481         valueToSet = field()->enumHint( popup()->tableView()->currentRow() );
00482         if (valueToSet.toString().isEmpty() && !m_insideCreatePopup) {
00483             clear();
00484             QWidget* thisWidget = dynamic_cast<QWidget*>(this);
00485             thisWidget->parentWidget()->setFocus();
00486             return;
00487         }
00488     }
00489     setValueOrTextInInternalEditor( valueToSet );
00490     if (m_setValueOrTextInInternalEditor_enabled) {
00491         moveCursorToEndInInternalEditor();
00492         selectAllInInternalEditor();
00493     }
00494     // a new (temp) popup table index is selected: do not update selection next time:
00495     m_updatePopupSelectionOnShow = false;
00496 }
00497 
00498 void KexiComboBoxBase::slotInternalEditorValueChanged(const QVariant& v)
00499 {
00500     if (!m_slotInternalEditorValueChanged_enabled)
00501         return;
00502     m_userEnteredValue = v;
00503     m_internalEditorValueChanged = true;
00504     if (v.toString().isEmpty()) {
00505         if (popup()) {
00506             popup()->tableView()->clearSelection();
00507         }
00508         return;
00509     }
00510 }
00511 
00512 void KexiComboBoxBase::setValueOrTextInInternalEditor(const QVariant& value)
00513 {
00514     if (!m_setValueOrTextInInternalEditor_enabled)
00515         return;
00516     setValueInInternalEditor( value );
00517     //this text is not entered by hand:
00518     m_userEnteredValue = QVariant();
00519     m_internalEditorValueChanged = false;
00520 }
00521 
00522 bool KexiComboBoxBase::handleKeyPressForPopup( QKeyEvent *ke )
00523 {
00524     const int k = ke->key();
00525     int highlightedOrSelectedRow = popup() ? popup()->tableView()->highlightedRow() : -1;
00526     if (popup() && highlightedOrSelectedRow < 0)
00527         highlightedOrSelectedRow = popup()->tableView()->currentRow();
00528 
00529     const bool enterPressed = k==Qt::Key_Enter || k==Qt::Key_Return;
00530 
00531     // The editor may be active but the pull down menu not existant/visible,
00532     // e.g. when the user has pressed a normal button to activate the editor
00533     // Don't handle the event here in that case.
00534     if (!popup() || (!enterPressed && !popup()->isVisible())) {
00535         return false;
00536     }
00537 
00538     switch (k) {
00539     case Qt::Key_Up:
00540             popup()->tableView()->setHighlightedRow( 
00541                 QMAX(highlightedOrSelectedRow-1, 0) );
00542             updateTextForHighlightedRow();
00543             return true;
00544     case Qt::Key_Down:
00545             popup()->tableView()->setHighlightedRow( 
00546                 QMIN(highlightedOrSelectedRow+1, popup()->tableView()->rows()-1) );
00547             updateTextForHighlightedRow();
00548             return true;
00549     case Qt::Key_PageUp:
00550             popup()->tableView()->setHighlightedRow( 
00551                 QMAX(highlightedOrSelectedRow-popup()->tableView()->rowsPerPage(), 0) );
00552             updateTextForHighlightedRow();
00553             return true;
00554     case Qt::Key_PageDown:
00555             popup()->tableView()->setHighlightedRow( 
00556                 QMIN(highlightedOrSelectedRow+popup()->tableView()->rowsPerPage(), 
00557                  popup()->tableView()->rows()-1) );
00558             updateTextForHighlightedRow();
00559             return true;
00560     case Qt::Key_Home:
00561             popup()->tableView()->setHighlightedRow( 0 );
00562             updateTextForHighlightedRow();
00563             return true;
00564     case Qt::Key_End:
00565             popup()->tableView()->setHighlightedRow( popup()->tableView()->rows()-1 );
00566             updateTextForHighlightedRow();
00567             return true;
00568     case Qt::Key_Enter:
00569     case Qt::Key_Return: //accept
00570             //select row that is highlighted
00571             if (popup()->tableView()->highlightedRow()>=0)
00572                 popup()->tableView()->selectRow( popup()->tableView()->highlightedRow() );
00573             //do not return true: allow to process event
00574     default: ;
00575     }
00576     return false;
00577 }
00578 
00579 void KexiComboBoxBase::updateTextForHighlightedRow()
00580 {
00581     KexiTableItem *item = popup() ? popup()->tableView()->highlightedItem() : 0;
00582     if (item)
00583         slotItemSelected(item);
00584 }
00585 
00586 void KexiComboBoxBase::undoChanges()
00587 {
00588     KexiDB::LookupFieldSchema *lookupFieldSchema = this->lookupFieldSchema();
00589     if (lookupFieldSchema) {
00590 //      kexidbg << "KexiComboBoxBase::undoChanges(): m_visibleValue BEFORE = " << m_visibleValue << endl;
00591         if (popup())
00592             popup()->tableView()->selectRow( popup()->tableView()->highlightedRow() );
00593         m_visibleValue = visibleValueForLookupField();
00594 //      kexidbg << "KexiComboBoxBase::undoChanges(): m_visibleValue AFTER = " << m_visibleValue << endl;
00595         setValueOrTextInInternalEditor( m_visibleValue );
00596     }
00597 }
KDE Home | KDE Accessibility Home | Description of Access Keys