libyui-qt
2.43.5
|
00001 /* 00002 Copyright (C) 2000-2012 Novell, Inc 00003 This library is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU Lesser General Public License as 00005 published by the Free Software Foundation; either version 2.1 of the 00006 License, or (at your option) version 3.0 of the License. This library 00007 is distributed in the hope that it will be useful, but WITHOUT ANY 00008 WARRANTY; without even the implied warranty of MERCHANTABILITY or 00009 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 00010 License for more details. You should have received a copy of the GNU 00011 Lesser General Public License along with this library; if not, write 00012 to the Free Software Foundation, Inc., 51 Franklin Street, Fifth 00013 Floor, Boston, MA 02110-1301 USA 00014 */ 00015 00016 00017 /*-/ 00018 00019 File: YQMultiSelectionBox.cc 00020 00021 Author: Stefan Hundhammer <sh@suse.de> 00022 00023 /-*/ 00024 00025 #include <limits.h> 00026 #include <QString> 00027 #include <QLabel> 00028 #include <QVBoxLayout> 00029 #include <QHeaderView> 00030 #include <QDebug> 00031 #define YUILogComponent "qt-ui" 00032 #include <yui/YUILog.h> 00033 00034 using std::max; 00035 00036 #include "utf8.h" 00037 #include "YQUI.h" 00038 #include <yui/YEvent.h> 00039 #include "YQMultiSelectionBox.h" 00040 #include "YQSignalBlocker.h" 00041 #include "YQWidgetCaption.h" 00042 00043 #define DEFAULT_VISIBLE_LINES 5 00044 #define SHRINKABLE_VISIBLE_LINES 2 00045 00046 00047 YQMultiSelectionBox::YQMultiSelectionBox( YWidget * parent, 00048 const std::string & label ) 00049 : QFrame( (QWidget *) parent->widgetRep() ) 00050 , YMultiSelectionBox( parent, label ) 00051 { 00052 QVBoxLayout* layout = new QVBoxLayout( this ); 00053 setLayout( layout ); 00054 00055 setWidgetRep( this ); 00056 00057 layout->setSpacing( YQWidgetSpacing ); 00058 layout->setMargin( YQWidgetMargin ); 00059 00060 _caption = new YQWidgetCaption( this, label ); 00061 YUI_CHECK_NEW( _caption ); 00062 layout->addWidget( _caption ); 00063 00064 _qt_listView = new QTreeWidget( this ); 00065 YUI_CHECK_NEW( _qt_listView ); 00066 layout->addWidget( _qt_listView ); 00067 00068 _qt_listView->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); 00069 _qt_listView->setHeaderLabel(""); // QListView doesn't have one single column by default! 00070 _qt_listView->setSortingEnabled( false ); 00071 00072 _qt_listView->header()->hide(); 00073 _qt_listView->setRootIsDecorated ( false ); 00074 _caption->setBuddy( _qt_listView ); 00075 00076 // Very small default size if specified 00077 00078 connect( _qt_listView, SIGNAL( itemSelectionChanged() ), 00079 this, SLOT ( slotSelected() ) ); 00080 00081 connect( this, SIGNAL( valueChanged() ), 00082 this, SLOT ( slotValueChanged() ) ); 00083 00084 connect( _qt_listView, SIGNAL( itemChanged( QTreeWidgetItem*, int ) ), 00085 this, SLOT ( slotItemChanged( QTreeWidgetItem*, int ) ) ); 00086 } 00087 00088 00089 YQMultiSelectionBox::~YQMultiSelectionBox() 00090 { 00091 // NOP 00092 } 00093 00094 00095 void 00096 YQMultiSelectionBox::setLabel( const std::string & label ) 00097 { 00098 _caption->setText( label ); 00099 YMultiSelectionBox::setLabel( label ); 00100 } 00101 00102 00103 void 00104 YQMultiSelectionBox::addItem( YItem * yItem ) 00105 { 00106 YQSignalBlocker sigBlocker( _qt_listView ); 00107 YMultiSelectionBox::addItem( yItem ); // will also check for NULL 00108 00109 YQMultiSelectionBoxItem * msbItem = new YQMultiSelectionBoxItem( this, _qt_listView, yItem ); 00110 00111 YUI_CHECK_NEW( msbItem ); 00112 00113 // Take care of the item's check box 00114 00115 msbItem->setCheckState(0, yItem->selected() ? Qt::Checked : Qt::Unchecked ); 00116 00117 // Take care of the QListView's keyboard focus 00118 00119 if ( ! _qt_listView->currentItem() ) 00120 _qt_listView->setCurrentItem( msbItem ); 00121 } 00122 00123 00124 void YQMultiSelectionBox::selectItem( YItem * yItem, bool selected ) 00125 { 00126 YMultiSelectionBox::selectItem( yItem, selected ); 00127 YQMultiSelectionBoxItem * msbItem = findItem( yItem ); 00128 00129 if ( msbItem ) 00130 msbItem->setCheckState( 0, selected ? Qt::Checked : Qt::Unchecked ); 00131 } 00132 00133 00134 void 00135 YQMultiSelectionBox::deselectAllItems() 00136 { 00137 YQSignalBlocker sigBlocker( _qt_listView ); 00138 YMultiSelectionBox::deselectAllItems(); 00139 00140 QTreeWidgetItemIterator it( _qt_listView ); 00141 00142 while ( *it ) 00143 { 00144 YQMultiSelectionBoxItem * item = dynamic_cast<YQMultiSelectionBoxItem *> (*it); 00145 00146 if ( item ) 00147 item->setCheckState(0, Qt::Unchecked); 00148 00149 ++it; 00150 } 00151 } 00152 00153 00154 void 00155 YQMultiSelectionBox::deleteAllItems() 00156 { 00157 YQSignalBlocker sigBlocker( _qt_listView ); 00158 00159 YMultiSelectionBox::deleteAllItems(); 00160 _qt_listView->clear(); 00161 } 00162 00163 00164 YItem * 00165 YQMultiSelectionBox::currentItem() 00166 { 00167 // QListView::currentItem() is very similar, but not exactly the same as 00168 // QListView::selectedItem(), and it is NOT to be confused with an item's 00169 // "selected" state in a YQMultiSelectionBox (the item's check box): 00170 // 00171 // QListView::currentItem() is the item that currently has the keyboard 00172 // focus. By default, it is displayed with a faint dotted outline. 00173 // 00174 // QListView::selectedItem() is the item that is selected in the QListView 00175 // widget. It is displayed in a very visible way with inverted colors 00176 // (typically blue backround). If there is a selected item, it is also the 00177 // current item. if there is no selected item, there might still be a 00178 // current item, though. 00179 // 00180 // The Y(Q)MultiSelectionBox item's "selected" state is completely 00181 // independent of all this: It only depends on the item's check 00182 // box. QListView::selectedItem() and QListView::currentItem() are just 00183 // mechanisms for keyboard navigation to show the user which item's check 00184 // box will be toggled when he hits the space bar. 00185 // 00186 // For the purpose of this function, QListView::currentItem() is the 00187 // minimum requirement. 00188 00189 QTreeWidgetItem * currentQItem = _qt_listView->currentItem(); 00190 00191 if ( currentQItem ) 00192 { 00193 YQMultiSelectionBoxItem * item = dynamic_cast<YQMultiSelectionBoxItem *> (currentQItem); 00194 00195 if ( item ) 00196 return item->yItem(); 00197 } 00198 00199 return 0; 00200 } 00201 00202 00203 void 00204 YQMultiSelectionBox::setCurrentItem( YItem * yItem ) 00205 { 00206 // See also explanations about QListView::currentItem() vs. 00207 // QListView::selectedItem() above 00208 // 00209 // This function uses QListView::selectedItem() for better visibility. 00210 // This implicitly also changes QListView::currentItem(). 00211 00212 YQSignalBlocker sigBlocker( _qt_listView ); 00213 00214 if ( ! yItem ) 00215 { 00216 _qt_listView->clearSelection(); 00217 } 00218 else 00219 { 00220 YQMultiSelectionBoxItem * msbItem = findItem( yItem ); 00221 00222 if ( msbItem ) 00223 _qt_listView->setCurrentItem( msbItem ); 00224 00225 // This does NOT change the item's check box! 00226 // (see explanations in YQMultiSelectionBox::currentItem() avove) 00227 } 00228 } 00229 00230 00231 void 00232 YQMultiSelectionBox::setEnabled( bool enabled ) 00233 { 00234 _caption->setEnabled( enabled ); 00235 _qt_listView->setEnabled( enabled ); 00236 //_qt_listView->triggerUpdate(); 00237 YWidget::setEnabled( enabled ); 00238 } 00239 00240 00241 int YQMultiSelectionBox::preferredWidth() 00242 { 00243 int hintWidth = (!_caption->isHidden()) ? 00244 _caption->sizeHint().width() + frameWidth() : 0; 00245 00246 return max( 80, hintWidth ); 00247 } 00248 00249 00250 int YQMultiSelectionBox::preferredHeight() 00251 { 00252 int hintHeight = (!_caption->isHidden()) ? _caption->sizeHint().height() : 0; 00253 int visibleLines = shrinkable() ? SHRINKABLE_VISIBLE_LINES : DEFAULT_VISIBLE_LINES; 00254 hintHeight += visibleLines * _qt_listView->fontMetrics().lineSpacing(); 00255 hintHeight += _qt_listView->frameWidth() * 2; 00256 00257 return max( 80, hintHeight ); 00258 } 00259 00260 00261 void 00262 YQMultiSelectionBox::setSize( int newWidth, int newHeight ) 00263 { 00264 resize( newWidth, newHeight ); 00265 } 00266 00267 00268 bool 00269 YQMultiSelectionBox::setKeyboardFocus() 00270 { 00271 _qt_listView->setFocus(); 00272 00273 return true; 00274 } 00275 00276 00277 void 00278 YQMultiSelectionBox::slotSelected() 00279 { 00280 if ( notify() ) 00281 { 00282 if ( ! YQUI::ui()->eventPendingFor( this ) ) 00283 { 00284 // Avoid overwriting a (more important) ValueChanged event with a SelectionChanged event 00285 00286 YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::SelectionChanged ) ); 00287 } 00288 } 00289 } 00290 00291 00292 void 00293 YQMultiSelectionBox::slotValueChanged() 00294 { 00295 if ( notify() ) 00296 YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::ValueChanged ) ); 00297 } 00298 00299 00300 void 00301 YQMultiSelectionBox::slotItemChanged ( QTreeWidgetItem * _item, int ) 00302 { 00303 YQMultiSelectionBoxItem * item = dynamic_cast<YQMultiSelectionBoxItem *> (_item); 00304 bool selected = item->checkState( 0 ); 00305 item->yItem()->setSelected( selected ); 00306 emit valueChanged(); 00307 } 00308 00309 YQMultiSelectionBoxItem * 00310 YQMultiSelectionBox::findItem( YItem * wantedItem ) 00311 { 00312 // FIXME: Don't search through all items, use the YItem::data() pointer instead 00313 QTreeWidgetItemIterator it( _qt_listView ); 00314 00315 while ( *it ) 00316 { 00317 YQMultiSelectionBoxItem * item = dynamic_cast<YQMultiSelectionBoxItem *> (*it); 00318 00319 if ( item && item->yItem() == wantedItem ) 00320 return item; 00321 00322 ++it; 00323 } 00324 00325 return 0; 00326 } 00327 00328 00329 int YQMultiSelectionBoxItem::_item_count = 0; 00330 00331 00332 00333 YQMultiSelectionBoxItem::YQMultiSelectionBoxItem( YQMultiSelectionBox * parent, 00334 QTreeWidget * listView, 00335 YItem * yItem ) 00336 : QTreeWidgetItem( listView ) 00337 , _yItem( yItem ) 00338 , _multiSelectionBox( parent ) 00339 { 00340 YUI_CHECK_PTR( yItem ); 00341 setFlags( Qt::ItemIsUserCheckable | Qt::ItemIsEnabled ); 00342 setText(0, fromUTF8( yItem->label() )); 00343 setCheckState( 0, Qt::Unchecked ); 00344 _serial = _item_count++; 00345 00346 if ( yItem->hasIconName() ) 00347 { 00348 // _table is checked against 0 in the constructor 00349 00350 string iconName = parent->iconFullPath( yItem->iconName() ); 00351 QPixmap icon = QPixmap( iconName.c_str() ); 00352 00353 if ( icon.isNull() ) 00354 yuiWarning() << "Can't load icon " << iconName << std::endl; 00355 else 00356 setIcon( 0 /* column */, icon ); 00357 } 00358 /* 00359 else // No pixmap name 00360 { 00361 if ( ! data( column, Qt::DecorationRole ).isNull() ) // Was there a pixmap before? 00362 { 00363 setData( column, Qt::DecorationRole, QPixmap() ); // Set empty pixmap 00364 } 00365 } 00366 */ 00367 } 00368 00369 #include "YQMultiSelectionBox.moc"