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