libyui-qt  2.43.5
/usr/src/RPM/BUILD/libyui-qt-2.43.5/src/YQTable.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:       YQTable.cc
00020 
00021   Author:     Stefan Hundhammer <sh@suse.de>
00022 
00023 /-*/
00024 
00025 #include <QHeaderView>
00026 #include <QVBoxLayout>
00027 #include <QString>
00028 #define YUILogComponent "qt-ui"
00029 #include <yui/YUILog.h>
00030 
00031 #include "utf8.h"
00032 #include "YQUI.h"
00033 #include <yui/YEvent.h>
00034 #include "YQSignalBlocker.h"
00035 #include <yui/YUIException.h>
00036 
00037 #include "QY2ListView.h"
00038 #include "YQTable.h"
00039 #include "YQApplication.h"
00040 
00041 
00042 
00043 YQTable::YQTable( YWidget * parent, YTableHeader * tableHeader, bool multiSelectionMode )
00044     : QFrame( (QWidget *) parent->widgetRep() )
00045     , YTable( parent, tableHeader, multiSelectionMode )
00046 {
00047     setWidgetRep( this );
00048     QVBoxLayout* layout = new QVBoxLayout( this );
00049     layout->setSpacing( 0 );
00050     setLayout( layout );
00051 
00052     layout->setMargin( YQWidgetMargin );
00053 
00054     _qt_listView = new QY2ListView( this );
00055     YUI_CHECK_NEW( _qt_listView );
00056     layout->addWidget( _qt_listView );
00057     _qt_listView->setAllColumnsShowFocus( true );
00058     _qt_listView->header()->setStretchLastSection( false );
00059 
00060     setKeepSorting(  keepSorting() );
00061 
00062     if ( multiSelectionMode )
00063         _qt_listView->setSelectionMode( QAbstractItemView::ExtendedSelection );
00064 
00065     _qt_listView->setContextMenuPolicy( Qt::CustomContextMenu );
00066 
00067     //
00068     // Add columns
00069     //
00070 
00071     QStringList headers;
00072     _qt_listView->setColumnCount( columns() );
00073 
00074     for ( int i=0; i < columns(); i++ )
00075     {
00076         headers << fromUTF8( header(i) );
00077     }
00078 
00079     _qt_listView->setHeaderLabels( headers );
00080     _qt_listView->header()->setResizeMode( QHeaderView::Interactive );
00081     _qt_listView->sortItems( 0, Qt::AscendingOrder);
00082 
00083 
00084     //
00085     // Connect signals and slots
00086     //
00087 
00088     connect( _qt_listView,      SIGNAL( itemDoubleClicked ( QTreeWidgetItem *, int ) ),
00089              this,              SLOT  ( slotActivated     ( QTreeWidgetItem * ) ) );
00090 
00091     connect( _qt_listView,      SIGNAL( currentItemChanged ( QTreeWidgetItem *, QTreeWidgetItem * ) ),
00092              this,              SLOT  ( slotSelected       ( QTreeWidgetItem * ) ) );
00093 
00094     connect( _qt_listView,      SIGNAL( customContextMenuRequested ( const QPoint & ) ),
00095              this,              SLOT  ( slotContextMenu ( const QPoint & ) ) );
00096 
00097 
00098     if ( multiSelectionMode )
00099     {
00100         // This is the exceptional case - avoid performance drop in the normal case
00101 
00102         connect( _qt_listView,  SIGNAL( itemSelectionChanged() ),
00103                  this,          SLOT  ( slotSelectionChanged() ) );
00104 
00105     }
00106 }
00107 
00108 
00109 YQTable::~YQTable()
00110 {
00111     // NOP
00112 }
00113 
00114 
00115 void
00116 YQTable::setKeepSorting( bool keepSorting )
00117 {
00118     YTable::setKeepSorting( keepSorting );
00119     _qt_listView->setSortByInsertionSequence( keepSorting );
00120     _qt_listView->setSortingEnabled( ! keepSorting );
00121 }
00122 
00123 
00124 void
00125 YQTable::addItem( YItem * yitem )
00126 {
00127     addItem( yitem,
00128              false, // batchMode
00129              true); // resizeColumnsToContent
00130 }
00131 
00132 
00133 void
00134 YQTable::addItem( YItem * yitem, bool batchMode, bool resizeColumnsToContent )
00135 {
00136     YTableItem * item = dynamic_cast<YTableItem *> (yitem);
00137     YUI_CHECK_PTR( item );
00138 
00139     YTable::addItem( item );
00140 
00141     YQTableListViewItem * clone = new YQTableListViewItem( this, _qt_listView, item );
00142     YUI_CHECK_NEW( clone );
00143 
00144     if ( ! batchMode && item->selected() )
00145     {
00146         // YTable enforces single selection, if appropriate
00147 
00148         YQSignalBlocker sigBlocker( _qt_listView );
00149         YQTable::selectItem( YSelectionWidget::selectedItem(), true );
00150     }
00151 
00152 
00153     //
00154     // Set column alignment
00155     //
00156 
00157     for ( int col=0; col < columns(); col++ )
00158     {
00159         switch ( alignment( col ) )
00160         {
00161             case YAlignBegin:   clone->setTextAlignment( col, Qt::AlignLeft   | Qt::AlignVCenter );     break;
00162             case YAlignCenter:  clone->setTextAlignment( col, Qt::AlignCenter | Qt::AlignVCenter );     break;
00163             case YAlignEnd:     clone->setTextAlignment( col, Qt::AlignRight  | Qt::AlignVCenter );     break;
00164 
00165             case YAlignUnchanged: break;
00166         }
00167     }
00168 
00169     if ( ! batchMode )
00170         _qt_listView->sortItems( 0, Qt::AscendingOrder);
00171 
00172     if ( resizeColumnsToContent )
00173     {
00174         for ( int i=0; i < columns(); i++ )
00175             _qt_listView->resizeColumnToContents( i );
00176         /* NOTE: resizeColumnToContents(...) is performance-critical ! */
00177     }
00178 }
00179 
00180 
00181 void
00182 YQTable::addItems( const YItemCollection & itemCollection )
00183 {
00184     YQSignalBlocker sigBlocker( _qt_listView );
00185 
00186     for ( YItemConstIterator it = itemCollection.begin();
00187           it != itemCollection.end();
00188           ++it )
00189     {
00190         addItem( *it,
00191                  true,    // batchMode
00192                  false ); // resizeColumnsToContent
00193         /* NOTE: resizeToContents=true would cause a massive performance drop !
00194                  => resize columns to content only one time at the end of this
00195                     function                                                 */
00196     }
00197 
00198     YItem * sel = YSelectionWidget::selectedItem();
00199 
00200     if ( sel )
00201         YQTable::selectItem( sel, true );
00202 
00203     for ( int i=0; i < columns(); i++ )
00204         _qt_listView->resizeColumnToContents( i );
00205 }
00206 
00207 
00208 void
00209 YQTable::selectItem( YItem * yitem, bool selected )
00210 {
00211     YQSignalBlocker sigBlocker( _qt_listView );
00212 
00213     YTableItem * item = dynamic_cast<YTableItem *> (yitem);
00214     YUI_CHECK_PTR( item );
00215 
00216     YQTableListViewItem * clone = (YQTableListViewItem *) item->data();
00217     YUI_CHECK_PTR( clone );
00218 
00219 
00220     if ( ! selected && clone == _qt_listView->currentItem() )
00221     {
00222         deselectAllItems();
00223     }
00224     else
00225     {
00226         if ( ! hasMultiSelection() )
00227             _qt_listView->setCurrentItem( clone ); // This deselects all other items!
00228 
00229         clone->setSelected( true );
00230         YTable::selectItem( item, selected );
00231     }
00232 }
00233 
00234 
00235 void
00236 YQTable::deselectAllItems()
00237 {
00238     YQSignalBlocker sigBlocker( _qt_listView );
00239 
00240     YTable::deselectAllItems();
00241     _qt_listView->clearSelection();
00242 }
00243 
00244 
00245 void
00246 YQTable::deleteAllItems()
00247 {
00248     _qt_listView->clear();
00249     YTable::deleteAllItems();
00250 }
00251 
00252 
00253 void
00254 YQTable::cellChanged( const YTableCell * cell )
00255 {
00256     YTableItem * item = cell->parent();
00257     YUI_CHECK_PTR( item );
00258 
00259     YQTableListViewItem * clone = (YQTableListViewItem *) item->data();
00260     YUI_CHECK_PTR( clone );
00261 
00262     clone->updateCell( cell );
00263 }
00264 
00265 
00266 void
00267 YQTable::selectOrigItem( QTreeWidgetItem * listViewItem )
00268 {
00269     if ( listViewItem )
00270     {
00271         YQTableListViewItem * tableListViewItem = dynamic_cast<YQTableListViewItem *> (listViewItem);
00272         YUI_CHECK_PTR( tableListViewItem );
00273 
00274         YTable::selectItem( tableListViewItem->origItem(), true );
00275     }
00276 }
00277 
00278 
00279 void
00280 YQTable::slotSelected( QTreeWidgetItem * listViewItem  )
00281 {
00282     if ( listViewItem && _qt_listView->selectedItems().count() > 0 )
00283         selectOrigItem( listViewItem );
00284     else
00285     {
00286         // Qt might select nothing if a user clicks outside the items in the widget
00287 
00288         if ( hasItems() && YSelectionWidget::hasSelectedItem() )
00289             YQTable::selectItem( YSelectionWidget::selectedItem(), true );
00290     }
00291 
00292     if ( immediateMode() )
00293     {
00294         if ( ! YQUI::ui()->eventPendingFor( this ) )
00295         {
00296             // Avoid overwriting a (more important) Activated event with a SelectionChanged event
00297 
00298             yuiDebug() << "Sending SelectionChanged event" << std::endl;
00299             YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::SelectionChanged ) );
00300         }
00301     }
00302 }
00303 
00304 
00305 void
00306 YQTable::slotSelectionChanged()
00307 {
00308     YSelectionWidget::deselectAllItems();
00309     yuiDebug() << std::endl;
00310 
00311     QList<QTreeWidgetItem *> selItems = _qt_listView->selectedItems();
00312 
00313     for ( QList<QTreeWidgetItem *>::iterator it = selItems.begin();
00314           it != selItems.end();
00315           ++it )
00316     {
00317         YQTableListViewItem * tableListViewItem = dynamic_cast<YQTableListViewItem *> (*it);
00318 
00319         if ( tableListViewItem )
00320         {
00321             tableListViewItem->origItem()->setSelected( true );
00322 
00323             yuiDebug() << "Selected item: " << tableListViewItem->origItem()->label() << std::endl;
00324         }
00325     }
00326 
00327     if ( immediateMode() )
00328     {
00329         if ( ! YQUI::ui()->eventPendingFor( this ) )
00330         {
00331             // Avoid overwriting a (more important) Activated event with a SelectionChanged event
00332 
00333             yuiDebug() << "Sending SelectionChanged event" << std::endl;
00334             YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::SelectionChanged ) );
00335         }
00336     }
00337 }
00338 
00339 
00340 void
00341 YQTable::slotActivated( QTreeWidgetItem * listViewItem )
00342 {
00343     selectOrigItem( listViewItem );
00344 
00345     if ( notify() )
00346     {
00347         yuiDebug() << "Sending Activated event" << std::endl;
00348         YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::Activated ) );
00349     }
00350 }
00351 
00352 
00353 void
00354 YQTable::setEnabled( bool enabled )
00355 {
00356     _qt_listView->setEnabled( enabled );
00357     //FIXME _qt_listView->triggerUpdate();
00358     YWidget::setEnabled( enabled );
00359 }
00360 
00361 
00362 
00363 int
00364 YQTable::preferredWidth()
00365 {
00366     // Arbitrary value.
00367     // Use a MinSize widget to set a size that is useful for the application.
00368 
00369     return 30;
00370 }
00371 
00372 
00373 int
00374 YQTable::preferredHeight()
00375 {
00376     // Arbitrary value.
00377     // Use a MinSize widget to set a size that is useful for the application.
00378 
00379     return 30;
00380 }
00381 
00382 
00383 void
00384 YQTable::setSize( int newWidth, int newHeight )
00385 {
00386     resize( newWidth, newHeight );
00387 }
00388 
00389 
00390 bool
00391 YQTable::setKeyboardFocus()
00392 {
00393     _qt_listView->setFocus();
00394 
00395     return true;
00396 }
00397 
00398 
00399 void
00400 YQTable::slotContextMenu ( const QPoint & pos )
00401 {
00402     if  ( ! _qt_listView ||  ! _qt_listView->viewport() )
00403         return;
00404 
00405     YQUI::yqApp()->setContextMenuPos( _qt_listView->viewport()->mapToGlobal( pos ) );
00406     if ( notifyContextMenu() )
00407         YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::ContextMenuActivated ) );
00408 }
00409 
00410 
00411 
00412 
00413 
00414 YQTableListViewItem::YQTableListViewItem( YQTable *     table,
00415                                           QY2ListView * parent,
00416                                           YTableItem *  origItem )
00417     : QY2ListViewItem( parent )
00418     , _table( table )
00419     , _origItem( origItem )
00420 {
00421     YUI_CHECK_PTR( _table );
00422     YUI_CHECK_PTR( _origItem );
00423 
00424     _origItem->setData( this );
00425 
00426     for ( YTableCellIterator it = _origItem->cellsBegin();
00427           it != _origItem->cellsEnd();
00428           ++it )
00429     {
00430         updateCell( *it );
00431     }
00432 }
00433 
00434 
00435 void
00436 YQTableListViewItem::updateCell( const YTableCell * cell )
00437 {
00438     if ( ! cell )
00439         return;
00440 
00441     int column = cell->column();
00442 
00443     //
00444     // Set label text
00445     //
00446 
00447     setText( column, fromUTF8( cell->label() ) );
00448 
00449 
00450     //
00451     // Set icon (if specified)
00452     //
00453 
00454     if ( cell->hasIconName() )
00455     {
00456         // _table is checked against 0 in the constructor
00457 
00458         string  iconName = _table->iconFullPath( cell->iconName() );
00459         QPixmap icon     = QPixmap( iconName.c_str() );
00460 
00461         if ( icon.isNull() )
00462             yuiWarning() << "Can't load icon " << iconName << std::endl;
00463         else
00464             setData( column, Qt::DecorationRole, icon );
00465     }
00466     else // No pixmap name
00467     {
00468         if ( ! data( column, Qt::DecorationRole ).isNull() ) // Was there a pixmap before?
00469         {
00470             setData( column, Qt::DecorationRole, QPixmap() ); // Set empty pixmap
00471         }
00472     }
00473 }
00474 
00475 
00476 #include "YQTable.moc"
 All Classes Functions Variables