libyui-qt  2.52.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 <sh@suse.de>
22 
23 /-*/
24 
25 #include <QHeaderView>
26 #include <QVBoxLayout>
27 #include <QString>
28 #define YUILogComponent "qt-ui"
29 #include <yui/YUILog.h>
30 
31 #include "utf8.h"
32 #include "YQUI.h"
33 #include <yui/YEvent.h>
34 #include "YQSignalBlocker.h"
35 #include <yui/YUIException.h>
36 
37 #include "QY2ListView.h"
38 #include "YQTable.h"
39 #include "YQApplication.h"
40 
41 
42 
43 YQTable::YQTable( YWidget * parent,
44  YTableHeader * tableHeader,
45  bool multiSelectionMode )
46  : QFrame( (QWidget *) parent->widgetRep() )
47  , YTable( parent, tableHeader, multiSelectionMode )
48 {
49  setWidgetRep( this );
50  QVBoxLayout* layout = new QVBoxLayout( this );
51  layout->setSpacing( 0 );
52  setLayout( layout );
53 
54  layout->setMargin( YQWidgetMargin );
55 
56  _qt_listView = new QY2ListView( this );
57  YUI_CHECK_NEW( _qt_listView );
58  layout->addWidget( _qt_listView );
59  _qt_listView->setAllColumnsShowFocus( true );
60  _qt_listView->header()->setStretchLastSection( false );
61 
62  setKeepSorting( keepSorting() );
63 
64  if ( multiSelectionMode )
65  _qt_listView->setSelectionMode( QAbstractItemView::ExtendedSelection );
66 
67  _qt_listView->setContextMenuPolicy( Qt::CustomContextMenu );
68 
69  //
70  // Add columns
71  //
72 
73  QStringList headers;
74  _qt_listView->setColumnCount( columns() );
75 
76  for ( int i=0; i < columns(); i++ )
77  {
78  headers << fromUTF8( header(i) );
79  }
80 
81  _qt_listView->setHeaderLabels( headers );
82  _qt_listView->header()->setSectionResizeMode( QHeaderView::Interactive );
83  _qt_listView->sortItems( 0, Qt::AscendingOrder);
84 
85 
86  //
87  // Connect signals and slots
88  //
89 
90  connect( _qt_listView, &pclass(_qt_listView)::itemDoubleClicked,
91  this, &pclass(this)::slotActivated );
92 
93  connect( _qt_listView, &pclass(_qt_listView)::customContextMenuRequested,
94  this, &pclass(this)::slotContextMenu );
95 
96  if ( multiSelectionMode )
97  {
98  // This is the exceptional case - avoid performance drop in the normal case
99  connect( _qt_listView, &pclass(_qt_listView)::itemSelectionChanged,
100  this, &pclass(this)::slotSelectionChanged );
101  }
102  else
103  {
104  connect( _qt_listView, &pclass(_qt_listView)::currentItemChanged,
105  this, &pclass(this)::slotSelected );
106  }
107 }
108 
109 
111 {
112  // NOP
113 }
114 
115 
116 void
117 YQTable::setKeepSorting( bool keepSorting )
118 {
119  YTable::setKeepSorting( keepSorting );
120  _qt_listView->setSortByInsertionSequence( keepSorting );
121  _qt_listView->setSortingEnabled( ! keepSorting );
122 }
123 
124 
125 void
126 YQTable::addItem( YItem * yitem )
127 {
128  addItem( yitem,
129  false, // batchMode
130  true); // resizeColumnsToContent
131 }
132 
133 
134 void
135 YQTable::addItem( YItem * yitem, bool batchMode, bool resizeColumnsToContent )
136 {
137  YTableItem * item = dynamic_cast<YTableItem *> (yitem);
138  YUI_CHECK_PTR( item );
139 
140  YTable::addItem( item );
141 
142  YQTableListViewItem * clone = new YQTableListViewItem( this, _qt_listView, item );
143  YUI_CHECK_NEW( clone );
144 
145  if ( ! batchMode && item->selected() )
146  {
147  // YTable enforces single selection, if appropriate
148 
149  YQSignalBlocker sigBlocker( _qt_listView );
150  YQTable::selectItem( YSelectionWidget::selectedItem(), true );
151  }
152 
153 
154  //
155  // Set column alignment
156  //
157 
158  for ( int col=0; col < columns(); col++ )
159  {
160  switch ( alignment( col ) )
161  {
162  case YAlignBegin: clone->setTextAlignment( col, Qt::AlignLeft | Qt::AlignVCenter ); break;
163  case YAlignCenter: clone->setTextAlignment( col, Qt::AlignCenter | Qt::AlignVCenter ); break;
164  case YAlignEnd: clone->setTextAlignment( col, Qt::AlignRight | Qt::AlignVCenter ); break;
165 
166  case YAlignUnchanged: break;
167  }
168  }
169 
170  if ( ! batchMode )
171  _qt_listView->sortItems( 0, Qt::AscendingOrder);
172 
173  if ( resizeColumnsToContent )
174  {
175  for ( int i=0; i < columns(); i++ )
176  _qt_listView->resizeColumnToContents( i );
177  /* NOTE: resizeColumnToContents(...) is performance-critical ! */
178  }
179 }
180 
181 
182 void
183 YQTable::addItems( const YItemCollection & itemCollection )
184 {
185  YQSignalBlocker sigBlocker( _qt_listView );
186 
187  for ( YItemConstIterator it = itemCollection.begin();
188  it != itemCollection.end();
189  ++it )
190  {
191  addItem( *it,
192  true, // batchMode
193  false ); // resizeColumnsToContent
194  /* NOTE: resizeToContents=true would cause a massive performance drop !
195  => resize columns to content only one time at the end of this
196  function */
197  }
198 
199  YItem * sel = YSelectionWidget::selectedItem();
200 
201  if ( sel )
202  YQTable::selectItem( sel, true );
203 
204  for ( int i=0; i < columns(); i++ )
205  _qt_listView->resizeColumnToContents( i );
206 }
207 
208 
209 void
210 YQTable::selectItem( YItem * yitem, bool selected )
211 {
212  YQSignalBlocker sigBlocker( _qt_listView );
213 
214  YTableItem * item = dynamic_cast<YTableItem *> (yitem);
215  YUI_CHECK_PTR( item );
216 
217  YQTableListViewItem * clone = (YQTableListViewItem *) item->data();
218  YUI_CHECK_PTR( clone );
219 
220 
221  if ( ! selected && clone == _qt_listView->currentItem() )
222  {
224  }
225  else
226  {
227  if ( ! hasMultiSelection() )
228  _qt_listView->setCurrentItem( clone ); // This deselects all other items!
229 
230  clone->setSelected( true );
231  YTable::selectItem( item, selected );
232  }
233 }
234 
235 
236 void
238 {
239  YQSignalBlocker sigBlocker( _qt_listView );
240 
241  YTable::deselectAllItems();
242  _qt_listView->clearSelection();
243 }
244 
245 
246 void
248 {
249  _qt_listView->clear();
250  YTable::deleteAllItems();
251 }
252 
253 
254 void
255 YQTable::cellChanged( const YTableCell * cell )
256 {
257  YTableItem * item = cell->parent();
258  YUI_CHECK_PTR( item );
259 
260  YQTableListViewItem * clone = (YQTableListViewItem *) item->data();
261  YUI_CHECK_PTR( clone );
262 
263  clone->updateCell( cell );
264 }
265 
266 
267 void
268 YQTable::selectOrigItem( QTreeWidgetItem * listViewItem )
269 {
270  if ( listViewItem )
271  {
272  YQTableListViewItem * tableListViewItem = dynamic_cast<YQTableListViewItem *> (listViewItem);
273  YUI_CHECK_PTR( tableListViewItem );
274 
275  YTable::selectItem( tableListViewItem->origItem(), true );
276  }
277 }
278 
279 
280 void
281 YQTable::slotSelected( QTreeWidgetItem * listViewItem )
282 {
283  if ( listViewItem )
284  selectOrigItem( listViewItem );
285  else
286  {
287  // Qt might select nothing if a user clicks outside the items in the widget
288 
289  if ( hasItems() && YSelectionWidget::hasSelectedItem() )
290  YQTable::selectItem( YSelectionWidget::selectedItem(), true );
291  }
292 
293  if ( immediateMode() )
294  {
295  if ( ! YQUI::ui()->eventPendingFor( this ) )
296  {
297  // Avoid overwriting a (more important) Activated event with a SelectionChanged event
298 
299  yuiDebug() << "Sending SelectionChanged event" << endl;
300  YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::SelectionChanged ) );
301  }
302  }
303 }
304 
305 
306 void
308 {
309  YSelectionWidget::deselectAllItems();
310  yuiDebug() << endl;
311 
312  QList<QTreeWidgetItem *> selItems = _qt_listView->selectedItems();
313 
314  for ( QList<QTreeWidgetItem *>::iterator it = selItems.begin();
315  it != selItems.end();
316  ++it )
317  {
318  YQTableListViewItem * tableListViewItem = dynamic_cast<YQTableListViewItem *> (*it);
319 
320  if ( tableListViewItem )
321  {
322  tableListViewItem->origItem()->setSelected( true );
323 
324  yuiDebug() << "Selected item: " << tableListViewItem->origItem()->label() << endl;
325  }
326  }
327 
328  if ( immediateMode() )
329  {
330  if ( ! YQUI::ui()->eventPendingFor( this ) )
331  {
332  // Avoid overwriting a (more important) Activated event with a SelectionChanged event
333 
334  yuiDebug() << "Sending SelectionChanged event" << endl;
335  YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::SelectionChanged ) );
336  }
337  }
338 }
339 
340 
341 void
342 YQTable::slotActivated( QTreeWidgetItem * listViewItem )
343 {
344  selectOrigItem( listViewItem );
345 
346  if ( notify() )
347  {
348  yuiDebug() << "Sending Activated event" << endl;
349  YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::Activated ) );
350  }
351 }
352 
353 
354 void
355 YQTable::setEnabled( bool enabled )
356 {
357  _qt_listView->setEnabled( enabled );
358  //FIXME _qt_listView->triggerUpdate();
359  YWidget::setEnabled( enabled );
360 }
361 
362 
363 
364 int
366 {
367  // Arbitrary value.
368  // Use a MinSize widget to set a size that is useful for the application.
369 
370  return 30;
371 }
372 
373 
374 int
376 {
377  // Arbitrary value.
378  // Use a MinSize widget to set a size that is useful for the application.
379 
380  return 30;
381 }
382 
383 
384 void
385 YQTable::setSize( int newWidth, int newHeight )
386 {
387  resize( newWidth, newHeight );
388 }
389 
390 
391 bool
393 {
394  _qt_listView->setFocus();
395 
396  return true;
397 }
398 
399 
400 void
401 YQTable::slotContextMenu ( const QPoint & pos )
402 {
403  if ( ! _qt_listView || ! _qt_listView->viewport() )
404  return;
405 
406  YQUI::yqApp()->setContextMenuPos( _qt_listView->viewport()->mapToGlobal( pos ) );
407  if ( notifyContextMenu() )
408  YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::ContextMenuActivated ) );
409 }
410 
411 
412 
413 
414 
416  QY2ListView * parent,
417  YTableItem * origItem )
418  : QY2ListViewItem( parent )
419  , _table( table )
420  , _origItem( origItem )
421 {
422  YUI_CHECK_PTR( _table );
423  YUI_CHECK_PTR( _origItem );
424 
425  _origItem->setData( this );
426 
427  for ( YTableCellIterator it = _origItem->cellsBegin();
428  it != _origItem->cellsEnd();
429  ++it )
430  {
431  updateCell( *it );
432  }
433 }
434 
435 
436 void
437 YQTableListViewItem::updateCell( const YTableCell * cell )
438 {
439  if ( ! cell )
440  return;
441 
442  int column = cell->column();
443 
444  //
445  // Set label text
446  //
447 
448  setText( column, fromUTF8( cell->label() ) );
449 
450 
451  //
452  // Set icon (if specified)
453  //
454 
455  if ( cell->hasIconName() )
456  {
457  // _table is checked against 0 in the constructor
458  QIcon icon = YQUI::ui()->loadIcon( cell->iconName() );
459 
460  if ( ! icon.isNull() )
461  setData( column, Qt::DecorationRole, icon );
462  }
463  else // No icon name
464  {
465  if ( ! data( column, Qt::DecorationRole ).isNull() ) // Was there an icon before?
466  {
467  setData( column, Qt::DecorationRole, QIcon() ); // Set empty icon
468  }
469  }
470 }
471 
472 
473 QString
475 {
476  const YTableCell* tableCell = origItem()->cell(column);
477 
478  if (tableCell->hasSortKey())
479  return QString::fromUtf8(tableCell->sortKey().c_str());
480  else
481  return text(column).trimmed();
482 }
Helper class to block Qt signals for QWidgets or QObjects as long as this object exists.
virtual void selectItem(YItem *item, bool selected=true)
Select or deselect an item.
Definition: YQTable.cc:210
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
virtual void addItem(YItem *item)
Add an item.
Definition: YQTable.cc:126
static YQApplication * yqApp()
Return the global YApplication object as YQApplication.
Definition: YQUI.cc:268
void slotContextMenu(const QPoint &pos)
Propagate a context menu selection.
Definition: YQTable.cc:401
virtual bool setKeyboardFocus()
Accept the keyboard focus.
Definition: YQTable.cc:392
YQTableListViewItem(YQTable *table, QY2ListView *parent, YTableItem *origItem)
Constructor.
Definition: YQTable.cc:415
void slotSelected(QTreeWidgetItem *)
Notification that an item is selected (single click or keyboard).
Definition: YQTable.cc:281
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:117
virtual void clear()
Reimplemented from Q3ListView: Adjust header sizes after clearing contents.
Definition: QY2ListView.cc:102
virtual void deleteAllItems()
Delete all items.
Definition: YQTable.cc:247
void selectOrigItem(QTreeWidgetItem *listViewItem)
Select the original item (the YTableItem) that corresponds to the specified listViewItem.
Definition: YQTable.cc:268
virtual void setEnabled(bool enabled)
Set enabled/disabled state.
Definition: YQTable.cc:355
Visual representation of a YTableItem.
Definition: YQTable.h:198
QIcon loadIcon(const string &iconName) const
Load an icon.
Definition: YQUI.cc:708
YTableItem * origItem() const
Return the corresponding YTableItem.
Definition: YQTable.h:217
virtual void deselectAllItems()
Deselect all items.
Definition: YQTable.cc:237
virtual void setContextMenuPos(QPoint contextMenuPos)
Sets the position of the context menu (in gloabl coordinates)
virtual void cellChanged(const YTableCell *cell)
Notification that a cell (its text and/or its icon) was changed from the outside. ...
Definition: YQTable.cc:255
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(YWidget *parent, YTableHeader *header, bool multiSelection)
Constructor.
Definition: YQTable.cc:43
virtual ~YQTable()
Destructor.
Definition: YQTable.cc:110
void updateCell(const YTableCell *cell)
Update this item&#39;s display with the content of &#39;cell&#39;.
Definition: YQTable.cc:437
Enhanced QTreeWidget.
Definition: QY2ListView.h:47
virtual void setSize(int newWidth, int newHeight)
Set the new size of the widget.
Definition: YQTable.cc:385
void slotActivated(QTreeWidgetItem *)
Notification that an item is activated (double click or keyboard).
Definition: YQTable.cc:342
virtual void addItems(const YItemCollection &itemCollection)
Add multiple items.
Definition: YQTable.cc:183
virtual int preferredWidth()
Preferred width of the widget.
Definition: YQTable.cc:365
Enhanced QTreeWidgetItem.
Definition: QY2ListView.h:233
virtual QString smartSortKey(int column) const override
The text of the table cell or the sort-key if available.
Definition: YQTable.cc:474
virtual int preferredHeight()
Preferred height of the widget.
Definition: YQTable.cc:375
void slotSelectionChanged()
Notification that the item selection changed (relevant for multiSelection mode).
Definition: YQTable.cc:307
static YQUI * ui()
Access the global Qt-UI.
Definition: YQUI.h:83