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