libyui-mga-qt  1.0.2
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 ( currentItemChanged ( QTreeWidgetItem *, QTreeWidgetItem * ) ),
111  this, SLOT ( slotSelected ( QTreeWidgetItem * ) ) );
112 
113  connect ( _qt_listView, SIGNAL ( customContextMenuRequested ( const QPoint & ) ),
114  this, SLOT ( slotContextMenu ( const QPoint & ) ) );
115 
116 }
117 
118 
120 {
121  delete d;
122 }
123 
125 {
126  int column = (d->firstColumnOffset == 1) ? 0 : columns() -1;
127 
128  return column;
129 }
130 
131 
132 
133 void
134 YMGA_QCBTable::setKeepSorting( bool keepSorting )
135 {
136  YMGA_CBTable::setKeepSorting( keepSorting );
137  _qt_listView->setSortByInsertionSequence( keepSorting );
138  _qt_listView->setSortingEnabled( ! keepSorting );
139 }
140 
141 
142 void
143 YMGA_QCBTable::addItem( YItem * yitem )
144 {
145  addItem ( yitem,
146  false, // batchMode
147  true ); // resizeColumnsToContent
148 }
149 
150 
151 void
152 YMGA_QCBTable::addItem( YItem * yitem, bool batchMode, bool resizeColumnsToContent )
153 {
154  YCBTableItem * item = dynamic_cast<YCBTableItem *> ( yitem );
155  YUI_CHECK_PTR ( item );
156 
157  YMGA_CBTable::addItem ( item );
158 
159  YMGA_QCBTableListViewItem * clone = new YMGA_QCBTableListViewItem ( this, _qt_listView, item );
160  YUI_CHECK_NEW ( clone );
161 
162  if ( ! batchMode && item->selected() )
163  {
164  // YTable enforces single selection, if appropriate
165 
166  YQSignalBlocker sigBlocker ( _qt_listView );
167  YMGA_QCBTable::selectItem ( YSelectionWidget::selectedItem(), true );
168  }
169 
170 
171  //
172  // Set column alignment
173  //
174 
175  for ( int col=0; col < columns(); col++ )
176  {
177  switch ( alignment ( col ) )
178  {
179  case YAlignBegin:
180  clone->setTextAlignment ( col, Qt::AlignLeft | Qt::AlignVCenter );
181  break;
182  case YAlignCenter:
183  clone->setTextAlignment ( col, Qt::AlignCenter | Qt::AlignVCenter );
184  break;
185  case YAlignEnd:
186  clone->setTextAlignment ( col, Qt::AlignRight | Qt::AlignVCenter );
187  break;
188 
189  case YAlignUnchanged:
190  break;
191  }
192  }
193 
194  if ( ! batchMode )
195  _qt_listView->sortItems ( 0, Qt::AscendingOrder );
196 
197  if ( resizeColumnsToContent )
198  {
199  for ( int i=0; i < columns(); i++ )
200  _qt_listView->resizeColumnToContents ( i );
201  /* NOTE: resizeColumnToContents(...) is performance-critical ! */
202  }
203 }
204 
205 
206 void
207 YMGA_QCBTable::addItems( const YItemCollection & itemCollection )
208 {
209  YQSignalBlocker sigBlocker ( _qt_listView );
210 
211  for ( YItemConstIterator it = itemCollection.begin();
212  it != itemCollection.end();
213  ++it )
214  {
215  addItem ( *it,
216  true, // batchMode
217  false ); // resizeColumnsToContent
218  /* NOTE: resizeToContents=true would cause a massive performance drop !
219  => resize columns to content only one time at the end of this
220  function */
221  }
222 
223  YItem * sel = YSelectionWidget::selectedItem();
224 
225  if ( sel )
226  YMGA_QCBTable::selectItem ( sel, true );
227 
228  for ( int i=0; i < columns(); i++ )
229  _qt_listView->resizeColumnToContents ( i );
230 }
231 
232 
233 void YMGA_QCBTable::selectItem ( YItem * yitem, bool selected )
234 {
235  YQSignalBlocker sigBlocker ( _qt_listView );
236 
237  YCBTableItem * item = dynamic_cast<YCBTableItem *> ( yitem );
238  YUI_CHECK_PTR ( item );
239 
240  YMGA_QCBTableListViewItem * clone = ( YMGA_QCBTableListViewItem * ) item->data();
241  YUI_CHECK_PTR ( clone );
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  YMGA_CBTable::selectItem ( item, selected );
254  }
255 }
256 
257 void YMGA_QCBTable::checkItem ( YItem* yitem, bool checked )
258 {
259  YQSignalBlocker sigBlocker ( _qt_listView );
260 
261  YCBTableItem * item = dynamic_cast<YCBTableItem *> ( yitem );
262  YUI_CHECK_PTR ( item );
263 
264  YMGA_QCBTableListViewItem * clone = ( YMGA_QCBTableListViewItem * ) item->data();
265  YUI_CHECK_PTR ( clone );
266 
267  item->check(checked);
268  clone->setCheckState ( checkboxItemColumn(), checked ? Qt::CheckState::Checked : Qt::CheckState::Unchecked );
269 }
270 
271 
272 void
274 {
275  YQSignalBlocker sigBlocker( _qt_listView );
276 
277  YMGA_CBTable::deselectAllItems();
278  _qt_listView->clearSelection();
279 }
280 
281 
282 void
284 {
285  _qt_listView->clear();
286  YMGA_CBTable::deleteAllItems();
287 }
288 
289 
290 void
291 YMGA_QCBTable::cellChanged( const YTableCell * cell )
292 {
293  YCBTableItem * item = dynamic_cast<YCBTableItem*>(cell->parent());
294  YUI_CHECK_PTR( item );
295 
296  YMGA_QCBTableListViewItem * clone = (YMGA_QCBTableListViewItem *) item->data();
297  YUI_CHECK_PTR( clone );
298 
299  clone->updateCell( cell );
300 }
301 
302 
303 void YMGA_QCBTable::selectOrigItem( QTreeWidgetItem * listViewItem )
304 {
305  if ( listViewItem )
306  {
307  YMGA_QCBTableListViewItem * tableListViewItem = dynamic_cast<YMGA_QCBTableListViewItem *> ( listViewItem );
308  YUI_CHECK_PTR ( tableListViewItem );
309 
310  YMGA_CBTable::selectItem ( tableListViewItem->origItem(), true );
311  if ( ! hasMultiSelection() )
312  _qt_listView->setCurrentItem( listViewItem );
313  }
314 }
315 
316 
317 void YMGA_QCBTable::slotSelected ( QTreeWidgetItem * listViewItem )
318 {
319  if ( listViewItem )
320  selectOrigItem ( listViewItem );
321  else
322  {
323  // Qt might select nothing if a user clicks outside the items in the widget
324 
325  if ( hasItems() && YSelectionWidget::hasSelectedItem() )
326  YMGA_QCBTable::selectItem ( YSelectionWidget::selectedItem(), true );
327  }
328 
329  if ( immediateMode() )
330  {
331  if ( ! YQUI::ui()->eventPendingFor ( this ) )
332  {
333  // Avoid overwriting a (more important) Activated event with a SelectionChanged event
334 
335  yuiDebug() << "Sending SelectionChanged event" << std::endl;
336  YQUI::ui()->sendEvent ( new YWidgetEvent ( this, YEvent::SelectionChanged ) );
337  }
338  }
339 }
340 
341 void YMGA_QCBTable::slotActivated( QTreeWidgetItem * listViewItem, int column )
342 {
343  selectOrigItem( listViewItem );
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 YMGA_QCBTable::slotcolumnClicked(QTreeWidgetItem* item,
354  int col)
355 {
356  selectOrigItem( item );
357 
358  if ( col == checkboxItemColumn() )
359  {
360  YMGA_QCBTableListViewItem * it = dynamic_cast<YMGA_QCBTableListViewItem*> ( item );
361  Qt::CheckState checked = item->checkState ( col );
362  YCBTableItem *pYCBTableItem = it->origItem();
363 
364  yuiDebug() << "Column is checked: " << (checked == Qt::CheckState::Checked?"yes":"no" ) << std::endl;
365 
366  // it seems items contains old value when signal is emitted
367  pYCBTableItem->check ( checked == Qt::CheckState::Checked );
368 
369  if ( notify() )
370  {
371  YMGA_CBTable::setChangedItem ( pYCBTableItem );
372  YQUI::ui()->sendEvent ( new YWidgetEvent ( this, YEvent::ValueChanged ) );
373  }
374  }
375 }
376 
377 
378 void
380 {
381  _qt_listView->setEnabled( enabled );
382  //FIXME _qt_listView->triggerUpdate();
383  YWidget::setEnabled( enabled );
384 }
385 
386 
387 
388 int
390 {
391  // Arbitrary value.
392  // Use a MinSize widget to set a size that is useful for the application.
393 
394  return 30;
395 }
396 
397 
398 int
400 {
401  // Arbitrary value.
402  // Use a MinSize widget to set a size that is useful for the application.
403 
404  return 100;
405 }
406 
407 
408 void
409 YMGA_QCBTable::setSize( int newWidth, int newHeight )
410 {
411  resize( newWidth, newHeight );
412 }
413 
414 
415 bool
417 {
418  _qt_listView->setFocus();
419 
420  return true;
421 }
422 
423 
424 void
425 YMGA_QCBTable::slotContextMenu ( const QPoint & pos )
426 {
427  if ( ! _qt_listView || ! _qt_listView->viewport() )
428  return;
429 
430  YQUI::yqApp()->setContextMenuPos( _qt_listView->viewport()->mapToGlobal( pos ) );
431  if ( notifyContextMenu() )
432  YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::ContextMenuActivated ) );
433 }
434 
435 
437  QY2ListView * parent,
438  YCBTableItem * origItem )
439  : QY2ListViewItem( parent )
440  , _table( table )
441  , _origItem( origItem )
442 {
443  YUI_CHECK_PTR( _table );
444  YUI_CHECK_PTR( _origItem );
445 
446  _origItem->setData( this );
447 
448  yuiDebug() << "Checkable column is " << table->checkboxItemColumn() << std::endl;
449 
450  int table_columns = _table->columns()-2;
451  setCheckState(table->checkboxItemColumn(), _origItem->checked() ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
452 
453  for ( YTableCellIterator it = _origItem->cellsBegin();
454  it != _origItem->cellsEnd();
455  ++it )
456  {
457  YTableCell * cell = *it;
458  // if someone decided to have more cells for this item
459  if (cell->column() > table_columns)
460  {
461  yuiWarning() << "Item contains too many columns, current is " << cell->column()
462  << " but only " << _table->columns() << " columns are configured" << std::endl;
463  }
464  else
465  updateCell( *it );
466  }
467 }
468 
469 
470 void
471 YMGA_QCBTableListViewItem::updateCell( const YTableCell * cell )
472 {
473  if ( ! cell )
474  return;
475 
476  int column = cell->column();
477  YCBTableMode mode = table()->tableMode();
478  if (mode == YCBTableMode::YCBTableCheckBoxOnFirstColumn)
479  column += 1;
480 
481  //
482  // Set label text
483  //
484 
485  setText( column, fromUTF8( cell->label() ) );
486 
487  //
488  // Set icon (if specified)
489  //
490  if ( cell->hasIconName() )
491  {
492  // _table is checked against 0 in the constructor
493 
494  string iconName = _table->iconFullPath( cell->iconName() );
495  QPixmap icon = QPixmap( iconName.c_str() );
496 
497  if ( icon.isNull() )
498  yuiWarning() << "Can't load icon " << iconName << std::endl;
499  else
500  setData( column, Qt::DecorationRole, icon );
501  }
502  else // No pixmap name
503  {
504  if ( ! data( column, Qt::DecorationRole ).isNull() ) // Was there a pixmap before?
505  {
506  setData( column, Qt::DecorationRole, QPixmap() ); // Set empty pixmap
507  }
508  }
509 }
510 
511 
512 #include "YMGA_QCBTable.moc"
YMGA_QCBTable::Private
Definition: YMGA_QCBTable.cc:42
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:291
YMGA_QCBTable::deleteAllItems
virtual void deleteAllItems()
Delete all items.
Definition: YMGA_QCBTable.cc:283
YMGA_QCBTable::addItems
virtual void addItems(const YItemCollection &itemCollection)
Add multiple items.
Definition: YMGA_QCBTable.cc:207
YMGA_QCBTable::YMGA_QCBTable
YMGA_QCBTable(YWidget *parent, YTableHeader *header, YCBTableMode checkboxMode)
Constructor.
Definition: YMGA_QCBTable.cc:51
YMGA_QCBTable
Definition: YMGA_QCBTable.h:38
YMGA_QCBTable::slotSelected
void slotSelected(QTreeWidgetItem *)
Notification that an item is selected (single click or keyboard).
Definition: YMGA_QCBTable.cc:317
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:212
YMGA_QCBTable::preferredWidth
virtual int preferredWidth()
Preferred width of the widget.
Definition: YMGA_QCBTable.cc:389
YMGA_QCBTable::selectOrigItem
void selectOrigItem(QTreeWidgetItem *listViewItem)
Select the original item (the YCBTableItem) that corresponds to the specified listViewItem.
Definition: YMGA_QCBTable.cc:303
YMGA_QCBTable::deselectAllItems
virtual void deselectAllItems()
Deselect all items.
Definition: YMGA_QCBTable.cc:273
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:134
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:124
YMGA_QCBTable::addItem
virtual void addItem(YItem *item)
Add an item.
Definition: YMGA_QCBTable.cc:143
YMGA_QCBTable::setKeyboardFocus
virtual bool setKeyboardFocus()
Accept the keyboard focus.
Definition: YMGA_QCBTable.cc:416
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:119
YMGA_QCBTable::setSize
virtual void setSize(int newWidth, int newHeight)
Set the new size of the widget.
Definition: YMGA_QCBTable.cc:409
YMGA_QCBTableListViewItem::YMGA_QCBTableListViewItem
YMGA_QCBTableListViewItem(YMGA_QCBTable *table, QY2ListView *parent, YCBTableItem *origItem)
Constructor.
Definition: YMGA_QCBTable.cc:436
YMGA_QCBTable::slotContextMenu
void slotContextMenu(const QPoint &pos)
Propagate a context menu selection.
Definition: YMGA_QCBTable.cc:425
YMGA_QCBTable::checkItem
void checkItem(YItem *item, bool checked=true)
check/uncheck Item from application.
Definition: YMGA_QCBTable.cc:257
YMGA_QCBTable::preferredHeight
virtual int preferredHeight()
Preferred height of the widget.
Definition: YMGA_QCBTable.cc:399
YMGA_QCBTable::setEnabled
virtual void setEnabled(bool enabled)
Set enabled/disabled state.
Definition: YMGA_QCBTable.cc:379
YMGA_QCBTable::slotActivated
void slotActivated(QTreeWidgetItem *listViewItem, int column)
Notification that an item is activated (double click or keyboard).
Definition: YMGA_QCBTable.cc:341
YMGA_QCBTableListViewItem::updateCell
void updateCell(const YTableCell *cell)
Update this item's display with the content of 'cell'.
Definition: YMGA_QCBTable.cc:471
YMGA_QCBTable::selectItem
virtual void selectItem(YItem *item, bool selected=true)
Select or deselect an item.
Definition: YMGA_QCBTable.cc:233