keditlistbox.cpp
00001 /* This file is part of the KDE libraries 00002 Copyright (C) 2000 David Faure <faure@kde.org>, Alexander Neundorf <neundorf@kde.org> 00003 2000, 2002 Carsten Pfeiffer <pfeiffer@kde.org> 00004 00005 This library 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 library 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 library; see the file COPYING.LIB. 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 <tqstringlist.h> 00022 #include <tqpushbutton.h> 00023 #include <tqlayout.h> 00024 #include <tqgroupbox.h> 00025 #include <tqlistbox.h> 00026 #include <tqwhatsthis.h> 00027 #include <tqlabel.h> 00028 00029 #include <kcombobox.h> 00030 #include <kdebug.h> 00031 #include <kdialog.h> 00032 #include <klineedit.h> 00033 #include <tdelocale.h> 00034 #include <tdeapplication.h> 00035 #include <knotifyclient.h> 00036 00037 #include "keditlistbox.h" 00038 00039 #include <assert.h> 00040 00041 class KEditListBoxPrivate 00042 { 00043 public: 00044 bool m_checkAtEntering; 00045 uint buttons; 00046 }; 00047 00048 KEditListBox::KEditListBox(TQWidget *parent, const char *name, 00049 bool checkAtEntering, int buttons ) 00050 :TQGroupBox(parent, name ), d(new KEditListBoxPrivate) 00051 { 00052 init( checkAtEntering, buttons ); 00053 } 00054 00055 KEditListBox::KEditListBox(const TQString& title, TQWidget *parent, 00056 const char *name, bool checkAtEntering, int buttons) 00057 :TQGroupBox(title, parent, name ), d(new KEditListBoxPrivate) 00058 { 00059 init( checkAtEntering, buttons ); 00060 } 00061 00062 KEditListBox::KEditListBox(const TQString& title, const CustomEditor& custom, 00063 TQWidget *parent, const char *name, 00064 bool checkAtEntering, int buttons) 00065 :TQGroupBox(title, parent, name ), d(new KEditListBoxPrivate) 00066 { 00067 m_lineEdit = custom.lineEdit(); 00068 init( checkAtEntering, buttons, custom.representationWidget() ); 00069 } 00070 00071 KEditListBox::~KEditListBox() 00072 { 00073 delete d; 00074 } 00075 00076 void KEditListBox::init( bool checkAtEntering, int buttons, 00077 TQWidget *representationWidget ) 00078 { 00079 d->m_checkAtEntering = checkAtEntering; 00080 00081 servNewButton = servRemoveButton = servUpButton = servDownButton = 0L; 00082 setSizePolicy(TQSizePolicy(TQSizePolicy::MinimumExpanding, 00083 TQSizePolicy::MinimumExpanding)); 00084 00085 TQGridLayout * grid = new TQGridLayout(this, 7, 2, 00086 KDialog::marginHint(), 00087 KDialog::spacingHint()); 00088 grid->addRowSpacing(0, fontMetrics().lineSpacing()); 00089 grid->setRowStretch( 6, 1 ); 00090 00091 grid->setMargin(15); 00092 00093 if ( representationWidget ) 00094 representationWidget->reparent( this, TQPoint(0,0) ); 00095 else 00096 m_lineEdit=new KLineEdit(this); 00097 00098 m_listBox = new TQListBox(this); 00099 00100 TQWidget *editingWidget = representationWidget ? 00101 representationWidget : m_lineEdit; 00102 grid->addMultiCellWidget(editingWidget,1,1,0,1); 00103 grid->addMultiCellWidget(m_listBox, 2, 6, 0, 0); 00104 00105 d->buttons = 0; 00106 setButtons( buttons ); 00107 00108 connect(m_lineEdit,TQT_SIGNAL(textChanged(const TQString&)),this,TQT_SLOT(typedSomething(const TQString&))); 00109 m_lineEdit->setTrapReturnKey(true); 00110 connect(m_lineEdit,TQT_SIGNAL(returnPressed()),this,TQT_SLOT(addItem())); 00111 connect(m_listBox, TQT_SIGNAL(highlighted(int)), TQT_SLOT(enableMoveButtons(int))); 00112 00113 // maybe supplied lineedit has some text already 00114 typedSomething( m_lineEdit->text() ); 00115 } 00116 00117 void KEditListBox::setButtons( uint buttons ) 00118 { 00119 if ( d->buttons == buttons ) 00120 return; 00121 00122 TQGridLayout* grid = static_cast<TQGridLayout *>( layout() ); 00123 if ( ( buttons & Add ) && !servNewButton ) { 00124 servNewButton = new TQPushButton(i18n("&Add"), this); 00125 servNewButton->setEnabled(false); 00126 servNewButton->show(); 00127 connect(servNewButton, TQT_SIGNAL(clicked()), TQT_SLOT(addItem())); 00128 00129 grid->addWidget(servNewButton, 2, 1); 00130 } else if ( ( buttons & Add ) == 0 && servNewButton ) { 00131 delete servNewButton; 00132 servNewButton = 0; 00133 } 00134 00135 if ( ( buttons & Remove ) && !servRemoveButton ) { 00136 servRemoveButton = new TQPushButton(i18n("&Remove"), this); 00137 servRemoveButton->setEnabled(false); 00138 servRemoveButton->show(); 00139 connect(servRemoveButton, TQT_SIGNAL(clicked()), TQT_SLOT(removeItem())); 00140 00141 grid->addWidget(servRemoveButton, 3, 1); 00142 } else if ( ( buttons & Remove ) == 0 && servRemoveButton ) { 00143 delete servRemoveButton; 00144 servRemoveButton = 0; 00145 } 00146 00147 if ( ( buttons & UpDown ) && !servUpButton ) { 00148 servUpButton = new TQPushButton(i18n("Move &Up"), this); 00149 servUpButton->setEnabled(false); 00150 servUpButton->show(); 00151 connect(servUpButton, TQT_SIGNAL(clicked()), TQT_SLOT(moveItemUp())); 00152 00153 servDownButton = new TQPushButton(i18n("Move &Down"), this); 00154 servDownButton->setEnabled(false); 00155 servDownButton->show(); 00156 connect(servDownButton, TQT_SIGNAL(clicked()), TQT_SLOT(moveItemDown())); 00157 00158 grid->addWidget(servUpButton, 4, 1); 00159 grid->addWidget(servDownButton, 5, 1); 00160 } else if ( ( buttons & UpDown ) == 0 && servUpButton ) { 00161 delete servUpButton; servUpButton = 0; 00162 delete servDownButton; servDownButton = 0; 00163 } 00164 00165 d->buttons = buttons; 00166 } 00167 00168 void KEditListBox::typedSomething(const TQString& text) 00169 { 00170 if(currentItem() >= 0) { 00171 if(currentText() != m_lineEdit->text()) 00172 { 00173 // IMHO changeItem() shouldn't do anything with the value 00174 // of currentItem() ... like changing it or emitting signals ... 00175 // but TT disagree with me on this one (it's been that way since ages ... grrr) 00176 bool block = m_listBox->signalsBlocked(); 00177 m_listBox->blockSignals( true ); 00178 m_listBox->changeItem(text, currentItem()); 00179 m_listBox->blockSignals( block ); 00180 emit changed(); 00181 } 00182 } 00183 00184 if ( !servNewButton ) 00185 return; 00186 00187 if (!d->m_checkAtEntering) 00188 servNewButton->setEnabled(!text.isEmpty()); 00189 else 00190 { 00191 if (text.isEmpty()) 00192 { 00193 servNewButton->setEnabled(false); 00194 } 00195 else 00196 { 00197 StringComparisonMode mode = (StringComparisonMode) (ExactMatch | CaseSensitive ); 00198 bool enable = (!m_listBox->findItem( text, mode )); 00199 servNewButton->setEnabled( enable ); 00200 } 00201 } 00202 } 00203 00204 void KEditListBox::moveItemUp() 00205 { 00206 if (!m_listBox->isEnabled()) 00207 { 00208 KNotifyClient::beep(); 00209 return; 00210 } 00211 00212 const unsigned int selIndex = m_listBox->currentItem(); 00213 if (selIndex == 0) 00214 { 00215 KNotifyClient::beep(); 00216 return; 00217 } 00218 00219 TQListBoxItem *selItem = m_listBox->item(selIndex); 00220 m_listBox->takeItem(selItem); 00221 m_listBox->insertItem(selItem, selIndex-1); 00222 m_listBox->setCurrentItem(selIndex - 1); 00223 00224 emit changed(); 00225 } 00226 00227 void KEditListBox::moveItemDown() 00228 { 00229 if (!m_listBox->isEnabled()) 00230 { 00231 KNotifyClient::beep(); 00232 return; 00233 } 00234 00235 unsigned int selIndex = m_listBox->currentItem(); 00236 if (selIndex == m_listBox->count() - 1) 00237 { 00238 KNotifyClient::beep(); 00239 return; 00240 } 00241 00242 TQListBoxItem *selItem = m_listBox->item(selIndex); 00243 m_listBox->takeItem(selItem); 00244 m_listBox->insertItem(selItem, selIndex+1); 00245 m_listBox->setCurrentItem(selIndex + 1); 00246 00247 emit changed(); 00248 } 00249 00250 void KEditListBox::addItem() 00251 { 00252 // when m_checkAtEntering is true, the add-button is disabled, but this 00253 // slot can still be called through Key_Return/Key_Enter. So we guard 00254 // against this. 00255 if ( !servNewButton || !servNewButton->isEnabled() ) 00256 return; 00257 00258 const TQString& currentTextLE=m_lineEdit->text(); 00259 bool alreadyInList(false); 00260 //if we didn't check for dupes at the inserting we have to do it now 00261 if (!d->m_checkAtEntering) 00262 { 00263 // first check current item instead of dumb iterating the entire list 00264 if ( m_listBox->currentText() == currentTextLE ) 00265 alreadyInList = true; 00266 else 00267 { 00268 StringComparisonMode mode = (StringComparisonMode) (ExactMatch | CaseSensitive ); 00269 alreadyInList =(m_listBox->findItem(currentTextLE, mode) ); 00270 } 00271 } 00272 00273 if ( servNewButton ) 00274 servNewButton->setEnabled(false); 00275 00276 bool block = m_lineEdit->signalsBlocked(); 00277 m_lineEdit->blockSignals(true); 00278 m_lineEdit->clear(); 00279 m_lineEdit->blockSignals(block); 00280 00281 m_listBox->setSelected(currentItem(), false); 00282 00283 if (!alreadyInList) 00284 { 00285 block = m_listBox->signalsBlocked(); 00286 m_listBox->blockSignals( true ); 00287 m_listBox->insertItem(currentTextLE); 00288 m_listBox->blockSignals( block ); 00289 emit changed(); 00290 emit added( currentTextLE ); 00291 } 00292 } 00293 00294 int KEditListBox::currentItem() const 00295 { 00296 int nr = m_listBox->currentItem(); 00297 if(nr >= 0 && !m_listBox->item(nr)->isSelected()) return -1; 00298 return nr; 00299 } 00300 00301 void KEditListBox::removeItem() 00302 { 00303 int selected = m_listBox->currentItem(); 00304 00305 if ( selected >= 0 ) 00306 { 00307 TQString removedText = m_listBox->currentText(); 00308 00309 m_listBox->removeItem( selected ); 00310 if ( count() > 0 ) 00311 m_listBox->setSelected( TQMIN( selected, count() - 1 ), true ); 00312 00313 emit changed(); 00314 emit removed( removedText ); 00315 } 00316 00317 if ( servRemoveButton && m_listBox->currentItem() == -1 ) 00318 servRemoveButton->setEnabled(false); 00319 } 00320 00321 void KEditListBox::enableMoveButtons(int index) 00322 { 00323 // Update the lineEdit when we select a different line. 00324 if(currentText() != m_lineEdit->text()) 00325 m_lineEdit->setText(currentText()); 00326 00327 bool moveEnabled = servUpButton && servDownButton; 00328 00329 if (moveEnabled ) 00330 { 00331 if (m_listBox->count() <= 1) 00332 { 00333 servUpButton->setEnabled(false); 00334 servDownButton->setEnabled(false); 00335 } 00336 else if ((uint) index == (m_listBox->count() - 1)) 00337 { 00338 servUpButton->setEnabled(true); 00339 servDownButton->setEnabled(false); 00340 } 00341 else if (index == 0) 00342 { 00343 servUpButton->setEnabled(false); 00344 servDownButton->setEnabled(true); 00345 } 00346 else 00347 { 00348 servUpButton->setEnabled(true); 00349 servDownButton->setEnabled(true); 00350 } 00351 } 00352 00353 if ( servRemoveButton ) 00354 servRemoveButton->setEnabled(true); 00355 } 00356 00357 void KEditListBox::clear() 00358 { 00359 m_lineEdit->clear(); 00360 m_listBox->clear(); 00361 emit changed(); 00362 } 00363 00364 void KEditListBox::insertStringList(const TQStringList& list, int index) 00365 { 00366 m_listBox->insertStringList(list,index); 00367 } 00368 00369 void KEditListBox::insertStrList(const TQStrList* list, int index) 00370 { 00371 m_listBox->insertStrList(list,index); 00372 } 00373 00374 void KEditListBox::insertStrList(const TQStrList& list, int index) 00375 { 00376 m_listBox->insertStrList(list,index); 00377 } 00378 00379 void KEditListBox::insertStrList(const char ** list, int numStrings, int index) 00380 { 00381 m_listBox->insertStrList(list,numStrings,index); 00382 } 00383 00384 TQStringList KEditListBox::items() const 00385 { 00386 TQStringList list; 00387 for (TQListBoxItem const * i = m_listBox->firstItem(); i != 0; i = i->next() ) 00388 list.append( i->text()); 00389 00390 return list; 00391 } 00392 00393 void KEditListBox::setItems(const TQStringList& items) 00394 { 00395 m_listBox->clear(); 00396 m_listBox->insertStringList(items, 0); 00397 } 00398 00399 int KEditListBox::buttons() const 00400 { 00401 return d->buttons; 00402 } 00403 00404 void KEditListBox::virtual_hook( int, void* ) 00405 { /*BASE::virtual_hook( id, data );*/ } 00406 00407 00410 00411 KEditListBox::CustomEditor::CustomEditor( KComboBox *combo ) 00412 { 00413 m_representationWidget = combo; 00414 m_lineEdit = tqt_dynamic_cast<KLineEdit*>( combo->lineEdit() ); 00415 assert( m_lineEdit ); 00416 } 00417 00418 #include "keditlistbox.moc"