libyui-qt  2.43.5
/usr/src/RPM/BUILD/libyui-qt-2.43.5/src/YQMultiSelectionBox.cc
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"
 All Classes Functions Variables