libyui-mga-qt  1.1.0
YMGA_QCBTable.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: YMGA_QCBTable.cc
20 
21  Author: Angelo Naselli <anaselli@linux.it>
22 
23 /-*/
24 
25 #include <QHeaderView>
26 #include <QVBoxLayout>
27 #include <QString>
28 #define YUILogComponent "mga-qt-ui"
29 #include <yui/YUILog.h>
30 
31 #include <yui/qt/utf8.h>
32 
33 #include <yui/qt/YQUI.h>
34 #include <yui/YEvent.h>
35 #include <yui/qt/YQSignalBlocker.h>
36 #include <yui/YUIException.h>
37 
38 #include "YMGA_QCBTable.h"
39 #include <yui/qt/YQApplication.h>
40 
41 
43 {
44  ///< offset to first YCell
45  /// usually 1 if checkbox Enabled and mode is YCBTableCheckBoxOnFirstColumn
46  /// 0 otherwise
47  unsigned int firstColumnOffset;
48 };
49 
50 
51 YMGA_QCBTable::YMGA_QCBTable( YWidget * parent, YTableHeader * tableHeader, YCBTableMode tableMode )
52  : QFrame( (QWidget *) parent->widgetRep() )
53  , YMGA_CBTable( parent, tableHeader, tableMode ), _qt_listView(0), d(new Private)
54 {
55  YUI_CHECK_NEW ( d );
56 
57  setWidgetRep ( this );
58  QVBoxLayout* layout = new QVBoxLayout ( this );
59  layout->setSpacing ( 0 );
60  setLayout ( layout );
61 
62  layout->setMargin ( YQWidgetMargin );
63 
64  _qt_listView = new QY2ListView ( this );
65  YUI_CHECK_NEW ( _qt_listView );
66  layout->addWidget ( _qt_listView );
67  _qt_listView->setAllColumnsShowFocus ( true );
68  _qt_listView->header()->setStretchLastSection ( false );
69 
70  setKeepSorting ( keepSorting() );
71 
72  d->firstColumnOffset = 0;
73 
74  yuiMilestone() << " Slection mode " << tableMode << std::endl;
75 
76  if ( tableMode == YCBTableCheckBoxOnFirstColumn )
77  {
78  d->firstColumnOffset = 1;
79  }
80 
81  _qt_listView->setContextMenuPolicy ( Qt::CustomContextMenu );
82 
83  //
84  // Add columns
85  //
86 
87  QStringList headers;
88  _qt_listView->setColumnCount ( columns() );
89 
90  // YCBTable needs header also for the checkable column
91  for ( int i=0; i < columns(); i++ )
92  {
93  headers << fromUTF8 ( header ( i ) );
94  }
95 
96  _qt_listView->setHeaderLabels ( headers );
97  _qt_listView->header()->setSectionResizeMode ( QHeaderView::Interactive );
98  _qt_listView->sortItems ( 0, Qt::AscendingOrder );
99 
100  //
101  // Connect signals and slots
102  //
103 
104  connect ( _qt_listView, SIGNAL ( itemDoubleClicked ( QTreeWidgetItem *, int ) ),
105  this, SLOT ( slotActivated ( QTreeWidgetItem *, int ) ) );
106 
107  connect ( _qt_listView, SIGNAL ( itemClicked ( QTreeWidgetItem *, int ) ),
108  this, SLOT ( slotcolumnClicked ( QTreeWidgetItem *, int ) ) );
109 
110  connect ( _qt_listView, SIGNAL ( itemChanged ( QTreeWidgetItem *, int ) ),
111  this, SLOT ( slotcolumnClicked ( QTreeWidgetItem *, int ) ) );
112 
113 
114  connect ( _qt_listView, SIGNAL ( currentItemChanged ( QTreeWidgetItem *, QTreeWidgetItem * ) ),
115  this, SLOT ( slotSelected ( QTreeWidgetItem * ) ) );
116 
117  connect ( _qt_listView, SIGNAL ( customContextMenuRequested ( const QPoint & ) ),
118  this, SLOT ( slotContextMenu ( const QPoint & ) ) );
119 
120 }
121 
122 
124 {
125  delete d;
126 }
127 
129 {
130  int column = (d->firstColumnOffset == 1) ? 0 : columns() -1;
131 
132  return column;
133 }
134 
135 
136 
137 void
138 YMGA_QCBTable::setKeepSorting( bool keepSorting )
139 {
140  YMGA_CBTable::setKeepSorting( keepSorting );
141  _qt_listView->setSortByInsertionSequence( keepSorting );
142  _qt_listView->setSortingEnabled( ! keepSorting );
143 }
144 
145 
146 void
147 YMGA_QCBTable::addItem( YItem * yitem )
148 {
149  addItem ( yitem,
150  false, // batchMode
151  true ); // resizeColumnsToContent
152 }
153 
154 
155 void
156 YMGA_QCBTable::addItem( YItem * yitem, bool batchMode, bool resizeColumnsToContent )
157 {
158  YCBTableItem * item = dynamic_cast<YCBTableItem *> ( yitem );
159  YUI_CHECK_PTR ( item );
160 
161  YMGA_CBTable::addItem ( item );
162 
163  YMGA_QCBTableListViewItem * clone = new YMGA_QCBTableListViewItem ( this, _qt_listView, item );
164  YUI_CHECK_NEW ( clone );
165 
166  if ( ! batchMode && item->selected() )
167  {
168  // YTable enforces single selection, if appropriate
169 
170  YQSignalBlocker sigBlocker ( _qt_listView );
171  YMGA_QCBTable::selectItem ( YSelectionWidget::selectedItem(), true );
172  }
173 
174 
175  //
176  // Set column alignment
177  //
178 
179  for ( int col=0; col < columns(); col++ )
180  {
181  switch ( alignment ( col ) )
182  {
183  case YAlignBegin:
184  clone->setTextAlignment ( col, Qt::AlignLeft | Qt::AlignVCenter );
185  break;
186  case YAlignCenter:
187  clone->setTextAlignment ( col, Qt::AlignCenter | Qt::AlignVCenter );
188  break;
189  case YAlignEnd:
190  clone->setTextAlignment ( col, Qt::AlignRight | Qt::AlignVCenter );
191  break;
192 
193  case YAlignUnchanged:
194  break;
195  }
196  }
197 
198  if ( ! batchMode )
199  _qt_listView->sortItems ( 0, Qt::AscendingOrder );
200 
201  if ( resizeColumnsToContent )
202  {
203  for ( int i=0; i < columns(); i++ )
204  _qt_listView->resizeColumnToContents ( i );
205  /* NOTE: resizeColumnToContents(...) is performance-critical ! */
206  }
207 }
208 
209 
210 void
211 YMGA_QCBTable::addItems( const YItemCollection & itemCollection )
212 {
213  YQSignalBlocker sigBlocker ( _qt_listView );
214 
215  for ( YItemConstIterator it = itemCollection.begin();
216  it != itemCollection.end();
217  ++it )
218  {
219  addItem ( *it,
220  true, // batchMode
221  false ); // resizeColumnsToContent
222  /* NOTE: resizeToContents=true would cause a massive performance drop !
223  => resize columns to content only one time at the end of this
224  function */
225  }
226 
227  YItem * sel = YSelectionWidget::selectedItem();
228 
229  if ( sel )
230  YMGA_QCBTable::selectItem ( sel, true );
231 
232  for ( int i=0; i < columns(); i++ )
233  _qt_listView->resizeColumnToContents ( i );
234 }
235 
236 
237 void YMGA_QCBTable::selectItem ( YItem * yitem, bool selected )
238 {
239  YQSignalBlocker sigBlocker ( _qt_listView );
240 
241  YCBTableItem * item = dynamic_cast<YCBTableItem *> ( yitem );
242  YUI_CHECK_PTR ( item );
243 
244  YMGA_QCBTableListViewItem * clone = ( YMGA_QCBTableListViewItem * ) item->data();
245  YUI_CHECK_PTR ( clone );
246 
247  if ( ! selected && clone == _qt_listView->currentItem() )
248  {
250  }
251  else
252  {
253  if ( ! hasMultiSelection() )
254  _qt_listView->setCurrentItem ( clone ); // This deselects all other items!
255 
256  clone->setSelected ( true );
257  YMGA_CBTable::selectItem ( item, selected );
258  }
259 }
260 
261 void YMGA_QCBTable::checkItem ( YItem* yitem, bool checked )
262 {
263  YQSignalBlocker sigBlocker ( _qt_listView );
264 
265  YCBTableItem * item = dynamic_cast<YCBTableItem *> ( yitem );
266  YUI_CHECK_PTR ( item );
267 
268  YMGA_QCBTableListViewItem * clone = ( YMGA_QCBTableListViewItem * ) item->data();
269  YUI_CHECK_PTR ( clone );
270 
271  item->check(checked);
272  clone->setCheckState ( checkboxItemColumn(), checked ? Qt::CheckState::Checked : Qt::CheckState::Unchecked );
273 }
274 
275 
276 void
278 {
279  YQSignalBlocker sigBlocker( _qt_listView );
280 
281  YMGA_CBTable::deselectAllItems();
282  _qt_listView->clearSelection();
283 }
284 
285 
286 void
288 {
289  _qt_listView->clear();
290  YMGA_CBTable::deleteAllItems();
291 }
292 
293 
294 void
295 YMGA_QCBTable::cellChanged( const YTableCell * cell )
296 {
297  YCBTableItem * item = dynamic_cast<YCBTableItem*>(cell->parent());
298  YUI_CHECK_PTR( item );
299 
300  YMGA_QCBTableListViewItem * clone = (YMGA_QCBTableListViewItem *) item->data();
301  YUI_CHECK_PTR( clone );
302 
303  clone->updateCell( cell );
304 }
305 
306 
307 void YMGA_QCBTable::selectOrigItem( QTreeWidgetItem * listViewItem )
308 {
309  if ( listViewItem )
310  {
311  YMGA_QCBTableListViewItem * tableListViewItem = dynamic_cast<YMGA_QCBTableListViewItem *> ( listViewItem );
312  YUI_CHECK_PTR ( tableListViewItem );
313 
314  YMGA_CBTable::selectItem ( tableListViewItem->origItem(), true );
315  if ( ! hasMultiSelection() )
316  _qt_listView->setCurrentItem( listViewItem );
317  }
318 }
319 
320 
321 void YMGA_QCBTable::slotSelected ( QTreeWidgetItem * listViewItem )
322 {
323  if ( listViewItem )
324  selectOrigItem ( listViewItem );
325  else
326  {
327  // Qt might select nothing if a user clicks outside the items in the widget
328 
329  if ( hasItems() && YSelectionWidget::hasSelectedItem() )
330  YMGA_QCBTable::selectItem ( YSelectionWidget::selectedItem(), true );
331  }
332 
333  if ( immediateMode() )
334  {
335  if ( ! YQUI::ui()->eventPendingFor ( this ) )
336  {
337  // Avoid overwriting a (more important) Activated event with a SelectionChanged event
338 
339  yuiDebug() << "Sending SelectionChanged event" << std::endl;
340  YQUI::ui()->sendEvent ( new YWidgetEvent ( this, YEvent::SelectionChanged ) );
341  }
342  }
343 }
344 
345 void YMGA_QCBTable::slotActivated( QTreeWidgetItem * listViewItem, int column )
346 {
347  selectOrigItem( listViewItem );
348  if ( notify() )
349  {
350  yuiDebug() << "Sending Activated event" << std::endl;
351  YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::Activated ) );
352  }
353 }
354 
355 
356 void
357 YMGA_QCBTable::slotcolumnClicked(QTreeWidgetItem* item,
358  int col)
359 {
360  selectOrigItem( item );
361 
362  if ( col == checkboxItemColumn() )
363  {
364  YMGA_QCBTableListViewItem * it = dynamic_cast<YMGA_QCBTableListViewItem*> ( item );
365  Qt::CheckState checked = item->checkState ( col );
366  YCBTableItem *pYCBTableItem = it->origItem();
367 
368  yuiDebug() << "Column is checked: " << (checked == Qt::CheckState::Checked?"yes":"no" ) << std::endl;
369 
370  // it seems items contains old value when signal is emitted
371  pYCBTableItem->check ( checked == Qt::CheckState::Checked );
372 
373  if ( notify() )
374  {
375  YMGA_CBTable::setChangedItem ( pYCBTableItem );
376  YQUI::ui()->sendEvent ( new YWidgetEvent ( this, YEvent::ValueChanged ) );
377  }
378  }
379 }
380 
381 
382 void
384 {
385  _qt_listView->setEnabled( enabled );
386  //FIXME _qt_listView->triggerUpdate();
387  YWidget::setEnabled( enabled );
388 }
389 
390 
391 
392 int
394 {
395  // Arbitrary value.
396  // Use a MinSize widget to set a size that is useful for the application.
397 
398  return 30;
399 }
400 
401 
402 int
404 {
405  // Arbitrary value.
406  // Use a MinSize widget to set a size that is useful for the application.
407 
408  return 100;
409 }
410 
411 
412 void
413 YMGA_QCBTable::setSize( int newWidth, int newHeight )
414 {
415  resize( newWidth, newHeight );
416 }
417 
418 
419 bool
421 {
422  _qt_listView->setFocus();
423 
424  return true;
425 }
426 
427 
428 void
429 YMGA_QCBTable::slotContextMenu ( const QPoint & pos )
430 {
431  if ( ! _qt_listView || ! _qt_listView->viewport() )
432  return;
433 
434  YQUI::yqApp()->setContextMenuPos( _qt_listView->viewport()->mapToGlobal( pos ) );
435  if ( notifyContextMenu() )
436  YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::ContextMenuActivated ) );
437 }
438 
439 
441  QY2ListView * parent,
442  YCBTableItem * origItem )
443  : QY2ListViewItem( parent )
444  , _table( table )
445  , _origItem( origItem )
446 {
447  YUI_CHECK_PTR( _table );
448  YUI_CHECK_PTR( _origItem );
449 
450  _origItem->setData( this );
451 
452  yuiDebug() << "Checkable column is " << table->checkboxItemColumn() << std::endl;
453 
454  int table_columns = _table->columns()-2;
455  setCheckState(table->checkboxItemColumn(), _origItem->checked() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
456 
457  for ( YTableCellIterator it = _origItem->cellsBegin();
458  it != _origItem->cellsEnd();
459  ++it )
460  {
461  YTableCell * cell = *it;
462  // if someone decided to have more cells for this item
463  if (cell->column() > table_columns)
464  {
465  yuiWarning() << "Item contains too many columns, current is " << cell->column()
466  << " but only " << _table->columns() << " columns are configured" << std::endl;
467  }
468  else
469  updateCell( *it );
470  }
471 }
472 
473 
474 void
475 YMGA_QCBTableListViewItem::updateCell( const YTableCell * cell )
476 {
477  if ( ! cell )
478  return;
479 
480  int column = cell->column();
481  YCBTableMode mode = table()->tableMode();
482  if (mode == YCBTableMode::YCBTableCheckBoxOnFirstColumn)
483  column += 1;
484 
485  //
486  // Set label text
487  //
488 
489  setText( column, fromUTF8( cell->label() ) );
490 
491  //
492  // Set icon (if specified)
493  //
494  if ( cell->hasIconName() )
495  {
496  // _table is checked against 0 in the constructor
497 
498  string iconName = _table->iconFullPath( cell->iconName() );
499  QPixmap icon = QPixmap( iconName.c_str() );
500 
501  if ( icon.isNull() )
502  yuiWarning() << "Can't load icon " << iconName << std::endl;
503  else
504  setData( column, Qt::DecorationRole, icon );
505  }
506  else // No pixmap name
507  {
508  if ( ! data( column, Qt::DecorationRole ).isNull() ) // Was there a pixmap before?
509  {
510  setData( column, Qt::DecorationRole, QPixmap() ); // Set empty pixmap
511  }
512  }
513 }
514 
515 
516 #include "YMGA_QCBTable.moc"
YMGA_QCBTable::Private
Definition: YMGA_QCBTable.cc:43
YMGA_QCBTable::cellChanged
virtual void cellChanged(const YTableCell *cell)
Notification that a cell (its text and/or its icon) was changed from the outside.
Definition: YMGA_QCBTable.cc:295
YMGA_QCBTable::deleteAllItems
virtual void deleteAllItems()
Delete all items.
Definition: YMGA_QCBTable.cc:287
YMGA_QCBTable::addItems
virtual void addItems(const YItemCollection &itemCollection)
Add multiple items.
Definition: YMGA_QCBTable.cc:211
YMGA_QCBTable::YMGA_QCBTable
YMGA_QCBTable(YWidget *parent, YTableHeader *header, YCBTableMode checkboxMode)
Constructor.
Definition: YMGA_QCBTable.cc:51
YMGA_QCBTable
Definition: YMGA_QCBTable.h:39
YMGA_QCBTable::slotSelected
void slotSelected(QTreeWidgetItem *)
Notification that an item is selected (single click or keyboard).
Definition: YMGA_QCBTable.cc:321
YMGA_QCBTableListViewItem::table
YMGA_QCBTable * table() const
Return the parent table widget.
Definition: YMGA_QCBTable.h:226
YMGA_QCBTableListViewItem
Visual representation of a YCBTableItem.
Definition: YMGA_QCBTable.h:213
YMGA_QCBTable::preferredWidth
virtual int preferredWidth()
Preferred width of the widget.
Definition: YMGA_QCBTable.cc:393
YMGA_QCBTable::selectOrigItem
void selectOrigItem(QTreeWidgetItem *listViewItem)
Select the original item (the YCBTableItem) that corresponds to the specified listViewItem.
Definition: YMGA_QCBTable.cc:307
YMGA_QCBTable::deselectAllItems
virtual void deselectAllItems()
Deselect all items.
Definition: YMGA_QCBTable.cc:277
YMGA_QCBTable::setKeepSorting
virtual void setKeepSorting(bool keepSorting)
Switch between sorting by item insertion order (keepSorting: true) or allowing the user to sort by an...
Definition: YMGA_QCBTable.cc:138
YMGA_QCBTableListViewItem::origItem
YCBTableItem * origItem() const
Return the corresponding YCBTableItem.
Definition: YMGA_QCBTable.h:231
YMGA_QCBTable::checkboxItemColumn
int checkboxItemColumn()
returns which column is managed by checkboxes, if any -1 otherwise
Definition: YMGA_QCBTable.cc:128
YMGA_QCBTable::addItem
virtual void addItem(YItem *item)
Add an item.
Definition: YMGA_QCBTable.cc:147
YMGA_QCBTable::setKeyboardFocus
virtual bool setKeyboardFocus()
Accept the keyboard focus.
Definition: YMGA_QCBTable.cc:420
YMGA_QCBTable::Private::firstColumnOffset
unsigned int firstColumnOffset
< offset to first YCell usually 1 if checkbox Enabled and mode is YCBTableCheckBoxOnFirstColumn 0 oth...
Definition: YMGA_QCBTable.cc:47
YMGA_QCBTable::~YMGA_QCBTable
virtual ~YMGA_QCBTable()
Destructor.
Definition: YMGA_QCBTable.cc:123
YMGA_QCBTable::setSize
virtual void setSize(int newWidth, int newHeight)
Set the new size of the widget.
Definition: YMGA_QCBTable.cc:413
YMGA_QCBTableListViewItem::YMGA_QCBTableListViewItem
YMGA_QCBTableListViewItem(YMGA_QCBTable *table, QY2ListView *parent, YCBTableItem *origItem)
Constructor.
Definition: YMGA_QCBTable.cc:440
YMGA_QCBTable::slotContextMenu
void slotContextMenu(const QPoint &pos)
Propagate a context menu selection.
Definition: YMGA_QCBTable.cc:429
YMGA_QCBTable::checkItem
void checkItem(YItem *item, bool checked=true)
check/uncheck Item from application.
Definition: YMGA_QCBTable.cc:261
YMGA_QCBTable::preferredHeight
virtual int preferredHeight()
Preferred height of the widget.
Definition: YMGA_QCBTable.cc:403
YMGA_QCBTable::setEnabled
virtual void setEnabled(bool enabled)
Set enabled/disabled state.
Definition: YMGA_QCBTable.cc:383
YMGA_QCBTable::slotActivated
void slotActivated(QTreeWidgetItem *listViewItem, int column)
Notification that an item is activated (double click or keyboard).
Definition: YMGA_QCBTable.cc:345
YMGA_QCBTableListViewItem::updateCell
void updateCell(const YTableCell *cell)
Update this item's display with the content of 'cell'.
Definition: YMGA_QCBTable.cc:475
YMGA_QCBTable::selectItem
virtual void selectItem(YItem *item, bool selected=true)
Select or deselect an item.
Definition: YMGA_QCBTable.cc:237