libyui-qt  2.56.2
YQTable.cc
1 /*
2  Copyright (C) 2000-2012 Novell, Inc
3  This library is free software; you can redistribute it and/or modify
4  it under the terms of the GNU Lesser General Public License as
5  published by the Free Software Foundation; either version 2.1 of the
6  License, or (at your option) version 3.0 of the License. This library
7  is distributed in the hope that it will be useful, but WITHOUT ANY
8  WARRANTY; without even the implied warranty of MERCHANTABILITY or
9  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
10  License for more details. You should have received a copy of the GNU
11  Lesser General Public License along with this library; if not, write
12  to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
13  Floor, Boston, MA 02110-1301 USA
14 */
15 
16 
17 /*-/
18 
19  File: YQTable.cc
20 
21  Author: Stefan Hundhammer <shundhammer@suse.de>
22 
23 /-*/
24 
25 
26 #define YUILogComponent "qt-ui"
27 #include <yui/YUILog.h>
28 
29 #include <QHeaderView>
30 #include <QVBoxLayout>
31 #include <QString>
32 
33 #include "utf8.h"
34 #include "YQUI.h"
35 #include <yui/YEvent.h>
36 #include "YQSignalBlocker.h"
37 #include <yui/YUIException.h>
38 
39 #include "QY2ListView.h"
40 #include "YQTable.h"
41 #include "YQApplication.h"
42 
43 
44 #define INDENTATION_WIDTH 10
45 
46 using std::endl;
47 
48 
49 
50 YQTable::YQTable( YWidget * parent,
51  YTableHeader * tableHeader,
52  bool multiSelectionMode )
53  : QFrame( (QWidget *) parent->widgetRep() )
54  , YTable( parent, tableHeader, multiSelectionMode )
55 {
56  setWidgetRep( this );
57  QVBoxLayout* layout = new QVBoxLayout( this );
58  layout->setSpacing( 0 );
59  setLayout( layout );
60 
61  layout->setMargin( YQWidgetMargin );
62 
63  _qt_listView = new QY2ListView( this );
64  YUI_CHECK_NEW( _qt_listView );
65  layout->addWidget( _qt_listView );
66  _qt_listView->setAllColumnsShowFocus( true );
67  _qt_listView->setIndentation( INDENTATION_WIDTH );
68  _qt_listView->header()->setStretchLastSection( false );
69 
70  setKeepSorting( keepSorting() );
71 
72  if ( multiSelectionMode )
73  _qt_listView->setSelectionMode( QAbstractItemView::ExtendedSelection );
74 
75  _qt_listView->setContextMenuPolicy( Qt::CustomContextMenu );
76 
77  //
78  // Add columns
79  //
80 
81  QStringList headers;
82  _qt_listView->setColumnCount( columns() );
83 
84  for ( int i=0; i < columns(); i++ )
85  {
86  headers << fromUTF8( header(i) );
87  }
88 
89  _qt_listView->setHeaderLabels( headers );
90  _qt_listView->header()->setSectionResizeMode( QHeaderView::Interactive );
91  _qt_listView->sortItems( 0, Qt::AscendingOrder);
92 
93 
94  //
95  // Connect signals and slots
96  //
97 
98  connect( _qt_listView, &pclass(_qt_listView)::itemDoubleClicked,
99  this, &pclass(this)::slotActivated );
100 
101  connect( _qt_listView, &pclass(_qt_listView)::customContextMenuRequested,
102  this, &pclass(this)::slotContextMenu );
103 
104  connect( _qt_listView, &pclass(_qt_listView)::itemExpanded,
105  this, &pclass(this)::slotItemExpanded );
106 
107  connect( _qt_listView, &pclass(_qt_listView)::itemCollapsed,
108  this, &pclass(this)::slotItemCollapsed );
109 
110  if ( multiSelectionMode )
111  {
112  // This is the exceptional case - avoid performance drop in the normal case
113  connect( _qt_listView, &pclass(_qt_listView)::itemSelectionChanged,
114  this, &pclass(this)::slotSelectionChanged );
115  }
116  else
117  {
118  connect( _qt_listView, &pclass(_qt_listView)::currentItemChanged,
119  this, &pclass(this)::slotSelected );
120  }
121 }
122 
123 
125 {
126  // NOP
127 }
128 
129 
130 void
131 YQTable::setKeepSorting( bool keepSorting )
132 {
133  YTable::setKeepSorting( keepSorting );
134  _qt_listView->setSortByInsertionSequence( keepSorting );
135  _qt_listView->setSortingEnabled( ! keepSorting );
136 }
137 
138 
139 void
140 YQTable::addItem( YItem * yitem )
141 {
142  addItem( yitem,
143  false, // batchMode
144  true ); // resizeColumnsToContent
145 }
146 
147 
148 void
149 YQTable::addItem( YItem * yitem, bool batchMode, bool resizeColumnsToContent )
150 {
151  YTableItem * item = dynamic_cast<YTableItem *> (yitem);
152  YUI_CHECK_PTR( item );
153 
154  YTable::addItem( item );
155 
156  YQTableListViewItem * clone = new YQTableListViewItem( this, _qt_listView, item );
157  YUI_CHECK_NEW( clone );
158 
159  if ( ! batchMode && item->selected() )
160  {
161  // YTable enforces single selection, if appropriate
162 
163  YQSignalBlocker sigBlocker( _qt_listView );
164  YQTable::selectItem( YSelectionWidget::selectedItem(), true );
165  }
166 
167  if ( item->hasChildren() )
168  {
169  cloneChildItems( item, clone );
170  _qt_listView->setRootIsDecorated( true );
171  }
172 
173  if ( ! batchMode )
174  _qt_listView->sortItems( 0, Qt::AscendingOrder);
175 
176  if ( resizeColumnsToContent )
177  {
178  for ( int i=0; i < columns(); i++ )
179  _qt_listView->resizeColumnToContents( i );
180  // NOTE: resizeColumnToContents() is performance-critical!
181  }
182 }
183 
184 
185 void
186 YQTable::cloneChildItems( YTableItem * parentItem, YQTableListViewItem * parentItemClone )
187 {
188  for ( YItemIterator it = parentItem->childrenBegin();
189  it != parentItem->childrenEnd();
190  ++it )
191  {
192  YTableItem * childItem = dynamic_cast<YTableItem *>( *it );
193 
194  if ( childItem )
195  {
196  YQTableListViewItem * childClone = new YQTableListViewItem( this, parentItemClone, childItem );
197  YUI_CHECK_NEW( childClone );
198 
199  cloneChildItems( childItem, childClone );
200  }
201  }
202 }
203 
204 
205 void
206 YQTable::addItems( const YItemCollection & itemCollection )
207 {
208  YQSignalBlocker sigBlocker( _qt_listView );
209 
210  for ( YItemConstIterator it = itemCollection.begin();
211  it != itemCollection.end();
212  ++it )
213  {
214  addItem( *it,
215  true, // batchMode
216  false ); // resizeColumnsToContent
217  // NOTE: resizeToContents = true would cause a massive performance drop!
218  // => resize columns to content only once at the end of this function
219  }
220 
221  YItem * sel = YSelectionWidget::selectedItem();
222 
223  if ( sel )
224  YQTable::selectItem( sel, true );
225 
226  for ( int i=0; i < columns(); i++ )
227  _qt_listView->resizeColumnToContents( i );
228 }
229 
230 
231 void
232 YQTable::selectItem( YItem * yitem, bool selected )
233 {
234  YQSignalBlocker sigBlocker( _qt_listView );
235 
236  YTableItem * item = dynamic_cast<YTableItem *> (yitem);
237  YUI_CHECK_PTR( item );
238 
239  YQTableListViewItem * clone = (YQTableListViewItem *) item->data();
240  YUI_CHECK_PTR( clone );
241 
242 
243  if ( ! selected && clone == _qt_listView->currentItem() )
244  {
246  }
247  else
248  {
249  if ( ! hasMultiSelection() )
250  _qt_listView->setCurrentItem( clone ); // This deselects all other items!
251 
252  clone->setSelected( true );
253  YTable::selectItem( item, selected );
254  }
255 }
256 
257 
258 void
259 YQTable::slotItemExpanded( QTreeWidgetItem * qItem )
260 {
261  YQTableListViewItem * item = dynamic_cast<YQTableListViewItem *> (qItem);
262 
263  if ( item )
264  item->origItem()->setOpen( true );
265 
266  _qt_listView->resizeColumnToContents( 0 );
267 }
268 
269 
270 void YQTable::slotItemCollapsed( QTreeWidgetItem * qItem )
271 {
272  YQTableListViewItem * item = dynamic_cast<YQTableListViewItem *> (qItem);
273 
274  if ( item )
275  item->origItem()->setOpen( false );
276 
277  _qt_listView->resizeColumnToContents( 0 );
278 }
279 
280 
281 void
283 {
284  YQSignalBlocker sigBlocker( _qt_listView );
285 
286  YTable::deselectAllItems();
287  _qt_listView->clearSelection();
288 }
289 
290 
291 void
293 {
294  _qt_listView->clear();
295  YTable::deleteAllItems();
296 }
297 
298 
299 void
300 YQTable::cellChanged( const YTableCell * cell )
301 {
302  YTableItem * item = cell->parent();
303  YUI_CHECK_PTR( item );
304 
305  YQTableListViewItem * clone = (YQTableListViewItem *) item->data();
306  YUI_CHECK_PTR( clone );
307 
308  clone->updateCell( cell );
309 }
310 
311 
312 void
313 YQTable::selectOrigItem( QTreeWidgetItem * listViewItem )
314 {
315  if ( listViewItem )
316  {
317  YQTableListViewItem * tableListViewItem = dynamic_cast<YQTableListViewItem *> (listViewItem);
318  YUI_CHECK_PTR( tableListViewItem );
319 
320  YTable::selectItem( tableListViewItem->origItem(), true );
321  }
322 }
323 
324 
325 void
326 YQTable::slotSelected( QTreeWidgetItem * listViewItem )
327 {
328  if ( listViewItem )
329  selectOrigItem( listViewItem );
330  else
331  {
332  // Qt might select nothing if a user clicks outside the items in the widget
333 
334  if ( hasItems() && YSelectionWidget::hasSelectedItem() )
335  YQTable::selectItem( YSelectionWidget::selectedItem(), true );
336  }
337 
338  if ( immediateMode() )
339  {
340  if ( ! YQUI::ui()->eventPendingFor( this ) )
341  {
342  // Avoid overwriting a (more important) Activated event with a SelectionChanged event
343 
344  yuiDebug() << "Sending SelectionChanged event" << endl;
345  YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::SelectionChanged ) );
346  }
347  }
348 }
349 
350 
351 void
353 {
354  YSelectionWidget::deselectAllItems();
355  yuiDebug() << endl;
356 
357  QList<QTreeWidgetItem *> selItems = _qt_listView->selectedItems();
358 
359  for ( QList<QTreeWidgetItem *>::iterator it = selItems.begin();
360  it != selItems.end();
361  ++it )
362  {
363  YQTableListViewItem * tableListViewItem = dynamic_cast<YQTableListViewItem *> (*it);
364 
365  if ( tableListViewItem )
366  {
367  tableListViewItem->origItem()->setSelected( true );
368 
369  yuiDebug() << "Selected item: " << tableListViewItem->origItem()->label() << endl;
370  }
371  }
372 
373  if ( immediateMode() )
374  {
375  if ( ! YQUI::ui()->eventPendingFor( this ) )
376  {
377  // Avoid overwriting a (more important) Activated event with a SelectionChanged event
378 
379  yuiDebug() << "Sending SelectionChanged event" << endl;
380  YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::SelectionChanged ) );
381  }
382  }
383 }
384 
385 
386 void
387 YQTable::slotActivated( QTreeWidgetItem * listViewItem )
388 {
389  selectOrigItem( listViewItem );
390 
391  if ( notify() )
392  {
393  yuiDebug() << "Sending Activated event" << endl;
394  YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::Activated ) );
395  }
396 }
397 
398 
399 void
400 YQTable::setEnabled( bool enabled )
401 {
402  _qt_listView->setEnabled( enabled );
403  // FIXME _qt_listView->triggerUpdate();
404  YWidget::setEnabled( enabled );
405 }
406 
407 
408 
409 int
411 {
412  // Arbitrary value.
413  // Use a MinSize widget to set a size that is useful for the application.
414 
415  return 30;
416 }
417 
418 
419 int
421 {
422  // Arbitrary value.
423  // Use a MinSize widget to set a size that is useful for the application.
424 
425  return 30;
426 }
427 
428 
429 void
430 YQTable::setSize( int newWidth, int newHeight )
431 {
432  resize( newWidth, newHeight );
433 }
434 
435 
436 bool
438 {
439  _qt_listView->setFocus();
440 
441  return true;
442 }
443 
444 
445 void
446 YQTable::slotContextMenu ( const QPoint & pos )
447 {
448  if ( ! _qt_listView || ! _qt_listView->viewport() )
449  return;
450 
451  YQUI::yqApp()->setContextMenuPos( _qt_listView->viewport()->mapToGlobal( pos ) );
452  if ( notifyContextMenu() )
453  YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::ContextMenuActivated ) );
454 }
455 
456 
457 
458 
459 
461  QY2ListView * parent,
462  YTableItem * origItem )
463  : QY2ListViewItem( parent )
464  , _table( table )
465  , _origItem( origItem )
466 {
467  init();
468 }
469 
470 
472  YQTableListViewItem * parentItemClone,
473  YTableItem * origItem )
474  : QY2ListViewItem( parentItemClone )
475  , _table( table )
476  , _origItem( origItem )
477 {
478  init();
479 }
480 
481 
482 void
484 {
485  YUI_CHECK_PTR( _table );
486  YUI_CHECK_PTR( _origItem );
487 
488  _origItem->setData( this );
489  updateCells();
490  setColAlignment();
491 
492  if ( _origItem->isOpen() && _origItem->hasChildren() )
493  setExpanded( true );
494 }
495 
496 
497 void
499 {
500  for ( YTableCellIterator it = _origItem->cellsBegin();
501  it != _origItem->cellsEnd();
502  ++it )
503  {
504  updateCell( *it );
505  }
506 }
507 
508 
509 void
510 YQTableListViewItem::updateCell( const YTableCell * cell )
511 {
512  if ( ! cell )
513  return;
514 
515  int column = cell->column();
516 
517  //
518  // Set label text
519  //
520 
521  setText( column, fromUTF8( cell->label() ) );
522 
523 
524  //
525  // Set icon (if specified)
526  //
527 
528  if ( cell->hasIconName() )
529  {
530  // _table is checked against 0 in the constructor
531  QIcon icon = YQUI::ui()->loadIcon( cell->iconName() );
532 
533  if ( ! icon.isNull() )
534  setData( column, Qt::DecorationRole, icon );
535  }
536  else // No icon name
537  {
538  if ( ! data( column, Qt::DecorationRole ).isNull() ) // Was there an icon before?
539  {
540  setData( column, Qt::DecorationRole, QIcon() ); // Set empty icon
541  }
542  }
543 }
544 
545 
546 void
548 {
549  YUI_CHECK_PTR( _table );
550 
551  for ( int col=0; col < _table->columns(); col++ )
552  {
553  switch ( _table->alignment( col ) )
554  {
555  case YAlignBegin: setTextAlignment( col, Qt::AlignLeft | Qt::AlignVCenter ); break;
556  case YAlignCenter: setTextAlignment( col, Qt::AlignCenter | Qt::AlignVCenter ); break;
557  case YAlignEnd: setTextAlignment( col, Qt::AlignRight | Qt::AlignVCenter ); break;
558 
559  case YAlignUnchanged: break;
560  }
561  }
562 }
563 
564 
565 QString
567 {
568  const YTableCell* tableCell = origItem()->cell(column);
569 
570  if (tableCell && tableCell->hasSortKey())
571  return QString::fromUtf8(tableCell->sortKey().c_str());
572  else
573  return text(column).trimmed();
574 }
YQSignalBlocker
Helper class to block Qt signals for QWidgets or QObjects as long as this object exists.
Definition: YQSignalBlocker.h:37
YQTable::setSize
virtual void setSize(int newWidth, int newHeight)
Set the new size of the widget.
Definition: YQTable.cc:430
YQTableListViewItem::setColAlignment
void setColAlignment()
Set the alignment for each column according to the YTable parent's alignment.
Definition: YQTable.cc:547
YQUI::sendEvent
void sendEvent(YEvent *event)
Widget event handlers (slots) call this when an event occured that should be the answer to a UserInpu...
Definition: YQUI.cc:480
YQTable::deleteAllItems
virtual void deleteAllItems()
Delete all items.
Definition: YQTable.cc:292
YQTable::slotContextMenu
void slotContextMenu(const QPoint &pos)
Propagate a context menu selection.
Definition: YQTable.cc:446
YQTableListViewItem::init
void init()
Common initializations for all constructors.
Definition: YQTable.cc:483
YQTable::setEnabled
virtual void setEnabled(bool enabled)
Set enabled/disabled state.
Definition: YQTable.cc:400
YQTableListViewItem::YQTableListViewItem
YQTableListViewItem(YQTable *table, QY2ListView *parent, YTableItem *origItem)
Constructor for toplevel items.
Definition: YQTable.cc:460
YQTable::slotSelectionChanged
void slotSelectionChanged()
Notification that the item selection changed (relevant for multiSelection mode).
Definition: YQTable.cc:352
YQTable::preferredWidth
virtual int preferredWidth()
Preferred width of the widget.
Definition: YQTable.cc:410
YQTable::~YQTable
virtual ~YQTable()
Destructor.
Definition: YQTable.cc:124
YQTable::cellChanged
virtual void cellChanged(const YTableCell *cell)
Notification that a cell (its text and/or its icon) was changed from the outside.
Definition: YQTable.cc:300
YQTableListViewItem::smartSortKey
virtual QString smartSortKey(int column) const override
The text of the table cell or the sort-key if available.
Definition: YQTable.cc:566
YQTable::slotItemExpanded
void slotItemExpanded(QTreeWidgetItem *item)
Propagate an "item expanded" event to the underlying YTableItem.
Definition: YQTable.cc:259
YQTableListViewItem::updateCell
void updateCell(const YTableCell *cell)
Update this item's display with the content of 'cell'.
Definition: YQTable.cc:510
YQTable::deselectAllItems
virtual void deselectAllItems()
Deselect all items.
Definition: YQTable.cc:282
YQTableListViewItem::origItem
YTableItem * origItem() const
Return the corresponding YTableItem.
Definition: YQTable.h:243
YQTable::slotActivated
void slotActivated(QTreeWidgetItem *)
Notification that an item is activated (double click or keyboard).
Definition: YQTable.cc:387
YQTable::setKeyboardFocus
virtual bool setKeyboardFocus()
Accept the keyboard focus.
Definition: YQTable.cc:437
QY2ListView::clear
virtual void clear()
Reimplemented from Q3ListView: Adjust header sizes after clearing contents.
Definition: QY2ListView.cc:102
YQUI::ui
static YQUI * ui()
Access the global Qt-UI.
Definition: YQUI.h:83
YQTable::selectItem
virtual void selectItem(YItem *item, bool selected=true)
Select or deselect an item.
Definition: YQTable.cc:232
YQTable::addItems
virtual void addItems(const YItemCollection &itemCollection)
Add multiple items.
Definition: YQTable.cc:206
YQTable::YQTable
YQTable(YWidget *parent, YTableHeader *header, bool multiSelection)
Constructor.
Definition: YQTable.cc:50
YQTable::cloneChildItems
void cloneChildItems(YTableItem *parentItem, YQTableListViewItem *parentItemClone)
Clone (create Qt item counterparts) for all child items of 'parentItem'.
Definition: YQTable.cc:186
YQTable::slotItemCollapsed
void slotItemCollapsed(QTreeWidgetItem *item)
Propagate an "item collapsed" event to the underlying YTableItem.
Definition: YQTable.cc:270
YQUI::yqApp
static YQApplication * yqApp()
Return the global YApplication object as YQApplication.
Definition: YQUI.cc:268
YQTable
Definition: YQTable.h:39
YQTable::selectOrigItem
void selectOrigItem(QTreeWidgetItem *listViewItem)
Select the original item (the YTableItem) that corresponds to the specified listViewItem.
Definition: YQTable.cc:313
YQTable::slotSelected
void slotSelected(QTreeWidgetItem *)
Notification that an item is selected (single click or keyboard).
Definition: YQTable.cc:326
YQTable::preferredHeight
virtual int preferredHeight()
Preferred height of the widget.
Definition: YQTable.cc:420
QY2ListView
Enhanced QTreeWidget.
Definition: QY2ListView.h:48
YQTable::setKeepSorting
virtual void setKeepSorting(bool keepSorting)
Switch between sorting by item insertion order (keepSorting: true) or allowing the user to sort by an...
Definition: YQTable.cc:131
YQTable::addItem
virtual void addItem(YItem *item)
Add an item.
Definition: YQTable.cc:140
QY2ListView::setSortByInsertionSequence
virtual void setSortByInsertionSequence(bool sortByInsertionSequence)
Enforce sorting by item insertion order (true) or let user change sorting by clicking on a column hea...
Definition: QY2ListView.cc:355
YQApplication::setContextMenuPos
virtual void setContextMenuPos(QPoint contextMenuPos)
Sets the position of the context menu (in gloabl coordinates)
Definition: YQApplication.cc:773
YQTableListViewItem::updateCells
void updateCells()
Update all columns of this item with the content of the original item.
Definition: YQTable.cc:498
QY2ListViewItem
Enhanced QTreeWidgetItem.
Definition: QY2ListView.h:234
YQTableListViewItem
Visual representation of a YTableItem.
Definition: YQTable.h:218
YQUI::loadIcon
QIcon loadIcon(const string &iconName) const
Load an icon.
Definition: YQUI.cc:708