libyui-qt  2.46.1
 All Classes Functions Variables
YQTree.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: YQTree.cc
20 
21  Author: Stefan Hundhammer <sh@suse.de>
22 
23 /-*/
24 
25 #include <QHeaderView>
26 #include <QLabel>
27 #include <QTreeWidget>
28 #include <QVBoxLayout>
29 #include <QString>
30 #include <QPixmap>
31 #define YUILogComponent "qt-ui"
32 #include <yui/YUILog.h>
33 
34 using std::min;
35 using std::max;
36 
37 #include "YQUI.h"
38 #include <yui/YEvent.h>
39 #include "utf8.h"
40 #include "YQTree.h"
41 #include <yui/YTreeItem.h>
42 #include "YQSignalBlocker.h"
43 #include "YQWidgetCaption.h"
44 #include "YQApplication.h"
45 
46 
47 #define VERBOSE_TREE_ITEMS 0
48 
49 
50 YQTree::YQTree( YWidget * parent, const std::string & label, bool multiSelectionMode, bool recursiveSelectionMode )
51  : QFrame( (QWidget *) parent->widgetRep() )
52  , YTree( parent, label, multiSelectionMode, recursiveSelectionMode )
53 {
54  QVBoxLayout* layout = new QVBoxLayout( this );
55  setLayout( layout );
56 
57  setWidgetRep( this );
58 
59  layout->setSpacing( YQWidgetSpacing );
60  layout->setMargin ( YQWidgetMargin );
61 
62  _nextSerialNo = 0;
63 
64  _caption = new YQWidgetCaption( this, label );
65  YUI_CHECK_NEW( _caption );
66  layout->addWidget( _caption );
67 
68  _qt_treeWidget = new QTreeWidget( this );
69  YUI_CHECK_NEW( _qt_treeWidget );
70  layout->addWidget( _qt_treeWidget );
71 
72  // _qt_treeWidget->setHeaderLabel("");
73  // _qt_treeWidget->addColumn( "" );
74  _qt_treeWidget->header()->hide();
75  // _qt_treeWidget->setHeader(0L);
76  _qt_treeWidget->setRootIsDecorated ( true );
77 
78  _qt_treeWidget->setContextMenuPolicy( Qt::CustomContextMenu );
79 
80  _caption->setBuddy ( _qt_treeWidget );
81 
82  connect( _qt_treeWidget, &pclass(_qt_treeWidget)::itemSelectionChanged,
83  this, &pclass(this)::slotSelectionChanged );
84 
85  connect( _qt_treeWidget, &pclass(_qt_treeWidget)::itemClicked,
86  this, &pclass(this)::slotItemClicked );
87 
88 // connect( _qt_treeWidget, &pclass(_qt_treeWidget)::itemChanged,
89 // this, &pclass(this)::slotItemChanged );
90 
91  connect( _qt_treeWidget, &pclass(_qt_treeWidget)::itemChanged,
92  this, &pclass(this)::slotItemChanged );
93 
94  connect( _qt_treeWidget, &pclass(_qt_treeWidget)::itemDoubleClicked,
95  this, &pclass(this)::slotActivated );
96 
97  connect( _qt_treeWidget, &pclass(_qt_treeWidget)::itemExpanded,
98  this, &pclass(this)::slotItemExpanded );
99 
100  connect( _qt_treeWidget, &pclass(_qt_treeWidget)::itemCollapsed,
101  this, &pclass(this)::slotItemCollapsed );
102 
103  connect( _qt_treeWidget, &pclass(_qt_treeWidget)::customContextMenuRequested,
104  this, &pclass(this)::slotContextMenu );
105 
106 }
107 
108 
110 {
111  // NOP
112 }
113 
114 
115 void YQTree::setLabel( const std::string & label )
116 {
117  _caption->setText( label );
118  YTree::setLabel( label );
119 }
120 
121 
123 {
124  YQSignalBlocker sigBlocker( _qt_treeWidget );
125  _qt_treeWidget->clear();
126 
127  buildDisplayTree( 0, itemsBegin(), itemsEnd() );
128  _qt_treeWidget->resizeColumnToContents( 0 );
129 }
130 
131 
132 void YQTree::buildDisplayTree( YQTreeItem * parentItem, YItemIterator begin, YItemIterator end )
133 {
134  for ( YItemIterator it = begin; it < end; ++it )
135  {
136  YTreeItem * orig = dynamic_cast<YTreeItem *> (*it);
137  YUI_CHECK_PTR( orig );
138 
139  YQTreeItem * clone;
140 
141  if ( parentItem )
142  clone = new YQTreeItem( this, parentItem, orig, _nextSerialNo++ );
143  else
144  clone = new YQTreeItem( this, _qt_treeWidget, orig, _nextSerialNo++ );
145 
146  YUI_CHECK_NEW( clone );
147 
148  if ( orig->hasChildren() )
149  buildDisplayTree( clone, orig->childrenBegin(), orig->childrenEnd() );
150  }
151 }
152 
153 
154 void YQTree::selectItem( YItem * yItem, bool selected )
155 {
156  YQSignalBlocker sigBlocker( _qt_treeWidget );
157 
158  // yuiDebug() << "Selecting item \"" << yItem->label() << "\" " << std::boolalpha << selected << std::endl;
159  YTreeItem * treeItem = dynamic_cast<YTreeItem *> (yItem);
160  YUI_CHECK_PTR( treeItem );
161 
162  YQTreeItem * yqTreeItem = (YQTreeItem *) treeItem->data();
163  YUI_CHECK_PTR( yqTreeItem );
164 
165 
166  if ( selected )
167  {
168  selectItem( yqTreeItem );
169  }
170  else if ( yqTreeItem == _qt_treeWidget->currentItem() )
171  {
173  }
174 }
175 
176 
178 {
179  if ( item )
180  {
181  YQSignalBlocker sigBlocker( _qt_treeWidget );
182 
183  _qt_treeWidget->setCurrentItem( item );
184  item->setSelected( true );
185 
186  if ( hasMultiSelection() )
187  item->setCheckState( 0, Qt::Checked );
188 
189  if ( item->parent() )
190  openBranch( (YQTreeItem *) item->parent() );
191 
192  YTree::selectItem( item->origItem(), true );
193 
194  // yuiDebug() << "selected item: \"" << item->origItem()->label() << "\"" << std::endl;
195 
196  }
197 }
198 
199 
201 {
202  while ( item )
203  {
204  item->setOpen( true ); // Takes care of origItem()->setOpen()
205  item = (YQTreeItem *) item->parent();
206  }
207 }
208 
209 void YQTree::slotItemExpanded( QTreeWidgetItem * qItem )
210 {
211  YQTreeItem * item = dynamic_cast<YQTreeItem *> (qItem);
212 
213  if ( item )
214  item->setOpen( true );
215 
216  _qt_treeWidget->resizeColumnToContents( 0 );
217 }
218 
219 
220 void YQTree::slotItemCollapsed( QTreeWidgetItem * qItem )
221 {
222  YQTreeItem * item = dynamic_cast<YQTreeItem *> (qItem);
223 
224  if ( item )
225  item->setOpen( false );
226 
227  _qt_treeWidget->resizeColumnToContents( 0 );
228 }
229 
230 
232 {
233  YQSignalBlocker sigBlocker( _qt_treeWidget );
234 
235  YTree::deselectAllItems();
236  _qt_treeWidget->clearSelection();
237 
238  if ( hasMultiSelection() )
239  {
240  QTreeWidgetItemIterator it( _qt_treeWidget);
241  while (*it)
242  {
243  YQTreeItem * treeItem = dynamic_cast<YQTreeItem *> (*it);
244 
245  if ( treeItem )
246  {
247  treeItem->setCheckState( 0, Qt::Unchecked );
248  treeItem->origItem()->setSelected( false );
249  }
250  ++it;
251  }
252  }
253 
254 }
255 
256 
258 {
259  YQSignalBlocker sigBlocker( _qt_treeWidget );
260 
261  _qt_treeWidget->clear();
262  YTree::deleteAllItems();
263 }
264 
265 
266 void YQTree::selectItem(QTreeWidgetItem * item, bool selected, bool recursive)
267 {
268 
269  YQTreeItem * treeItem = dynamic_cast<YQTreeItem *> (item);
270 
271  if ( ! treeItem )
272  return;
273 
274  YSelectionWidget::selectItem( treeItem->origItem(), selected );
275 
276  if ( recursive )
277  {
278  for (int i=0; i < item->childCount(); ++i)
279  {
280  QTreeWidgetItem* child = item->child(i);
281  child->setCheckState(0, ( selected )? Qt::Checked : Qt::Unchecked );
282  YQTree::selectItem( child, selected, recursive );
283  }
284  }
285 
286 }
287 
288 
289 void YQTree::slotItemChanged( QTreeWidgetItem * item )
290 {
291 
292  YQSignalBlocker sigBlocker( _qt_treeWidget );
293 
294  if ( hasMultiSelection() )
295  {
296  if ( recursiveSelection() )
297  YQUI::ui()->busyCursor();
298 
299  if ( item->checkState(0) == Qt::Checked )
300  YQTree::selectItem( item, true, recursiveSelection() );
301  else
302  YQTree::selectItem( item, false, recursiveSelection() );
303 
304 
305  if ( recursiveSelection() )
306  YQUI::ui()->normalCursor();
307 
308  }
309  else
310  {
311  QList<QTreeWidgetItem *> items = _qt_treeWidget->selectedItems ();
312 
313  if ( ! items.empty() )
314  {
315  QTreeWidgetItem *qItem = items.first();
316  selectItem( dynamic_cast<YQTreeItem *> (qItem) );
317  }
318  }
319 
320 
321 
322  if ( notify() && ! YQUI::ui()->eventPendingFor( this ) )
323  YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::ValueChanged ) );
324 
325 
326 }
327 
328 
329 void YQTree::slotItemClicked( QTreeWidgetItem * item, int column )
330 {
331  _qt_treeWidget->setCurrentItem( item );
332 
333  if ( notify() && ! YQUI::ui()->eventPendingFor( this ) )
334  YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::SelectionChanged ) );
335 }
336 
337 
338 
339 
341 {
342  QList<QTreeWidgetItem *> items = _qt_treeWidget->selectedItems ();
343 
344  if ( ! hasMultiSelection() && ! items.empty() )
345  {
346  QTreeWidgetItem *qItem = items.first();
347  selectItem( dynamic_cast<YQTreeItem *> (qItem) );
348  }
349 
350 
351  if ( notify() && ! YQUI::ui()->eventPendingFor( this ) )
352  YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::SelectionChanged ) );
353 }
354 
355 
356 void YQTree::slotActivated( QTreeWidgetItem * qItem )
357 {
358  selectItem( dynamic_cast<YQTreeItem *> (qItem) );
359 
360  if ( notify() )
361  YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::Activated ) );
362 }
363 
364 
366 {
367  int hintWidth = !_caption->isHidden() ? _caption->sizeHint().width() : 0;
368  return max( 80, hintWidth );
369 }
370 
371 
373 {
374  int hintHeight = !_caption->isHidden() ? _caption->sizeHint().height() : 0;
375 
376  // 80 is an arbitrary value. Use a MinSize or MinHeight widget to set a
377  // size that is useful for the application.
378 
379  return 80 + hintHeight;
380 }
381 
382 
383 void YQTree::setSize( int newWidth, int newHeight )
384 {
385  resize( newWidth, newHeight );
386 }
387 
388 
389 void YQTree::setEnabled( bool enabled )
390 {
391  _caption->setEnabled( enabled );
392  _qt_treeWidget->setEnabled( enabled );
393  YWidget::setEnabled( enabled );
394 }
395 
396 
398 {
399  _qt_treeWidget->setFocus();
400 
401  return true;
402 }
403 
404 
405 void YQTree::slotContextMenu ( const QPoint & pos )
406 {
407  if ( ! _qt_treeWidget || ! _qt_treeWidget->viewport() )
408  return;
409 
410  YQUI::yqApp()->setContextMenuPos( _qt_treeWidget->viewport()->mapToGlobal( pos ) );
411  if ( notifyContextMenu() )
412  YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::ContextMenuActivated ) );
413 }
414 
415 
416 YTreeItem *
418 {
419 
420  QTreeWidgetItem * currentQItem = _qt_treeWidget->currentItem();
421 
422  if ( currentQItem )
423  {
424  YQTreeItem * item = dynamic_cast<YQTreeItem *> (currentQItem);
425 
426  if ( item )
427  return item->origItem();
428  }
429 
430  return 0;
431 }
432 
433 
434 
435 /*============================================================================*/
436 
437 
438 
440  QTreeWidget * listView,
441  YTreeItem * orig,
442  int serial )
443  : QTreeWidgetItem( listView )
444 {
445  init( tree, orig, serial );
446 
447 #if VERBOSE_TREE_ITEMS
448  yuiDebug() << "Creating toplevel tree item \"" << orig->label() << "\"" << std::endl;
449 #endif
450 
451 }
452 
453 
455  YQTreeItem * parentItem,
456  YTreeItem * orig,
457  int serial )
458  : QTreeWidgetItem( parentItem )
459 {
460  init( tree, orig, serial );
461 #if VERBOSE_TREE_ITEMS
462  yuiDebug() << "Creating tree item \"" << orig->label()
463  << "\" as child of \"" << parentItem->origItem()->label() << "\""
464  << std::endl;
465 
466 #endif
467 
468 
469 
470 }
471 
472 
473 void YQTreeItem::init( YQTree * tree,
474  YTreeItem * orig,
475  int serial )
476 {
477  YUI_CHECK_PTR( tree );
478  YUI_CHECK_PTR( orig );
479 
480  _tree = tree;
481  _serialNo = serial;
482  _origItem = orig;
483 
484  _origItem->setData( this );
485 
486  setText( 0, fromUTF8 ( _origItem->label() ) );
487  setOpen( _origItem->isOpen() );
488 
489  if ( _origItem->hasIconName() )
490  {
491  string iconName = _tree->iconFullPath( _origItem );
492  QPixmap icon( iconName.c_str() );
493 
494  if ( icon.isNull() )
495  yuiWarning() << "Can't load icon " << iconName << std::endl;
496  else
497  setData( 0, Qt::DecorationRole, icon );
498  }
499 
500  if ( tree->hasMultiSelection() )
501  setCheckState(0,Qt::Unchecked);
502 }
503 
504 
505 void
507 {
508  QTreeWidgetItem::setExpanded( open );
509  _origItem->setOpen( open );
510 }
511 
512 
513 
514 QString
515 YQTreeItem::key( int column, bool ascending ) const
516 {
517  /*
518  * Sorting key for QListView internal sorting:
519  *
520  * Always sort tree items by insertion order. The tree widget cannot
521  * maintain a meaningful sorting order of its own: All it could do is sort
522  * by names (ASCII sort). Better let the application handle this.
523  */
524 
525  QString strKey;
526  strKey.sprintf( "%08d", _serialNo );
527 
528  return strKey;
529 }
530 
531 
532 #include "YQTree.moc"
static YQApplication * yqApp()
Definition: YQUI.cc:284
void slotItemChanged(QTreeWidgetItem *item)
Definition: YQTree.cc:289
virtual void setText(const std::string &newText)
virtual int preferredWidth()
Definition: YQTree.cc:365
virtual void setOpen(bool open)
Definition: YQTree.cc:506
virtual void rebuildTree()
Definition: YQTree.cc:122
virtual YTreeItem * currentItem()
Definition: YQTree.cc:417
YQTree(YWidget *parent, const std::string &label, bool multiSelection, bool recursiveSelection)
Definition: YQTree.cc:50
Definition: YQTree.h:38
void openBranch(YQTreeItem *item)
Definition: YQTree.cc:200
void slotItemExpanded(QTreeWidgetItem *item)
Definition: YQTree.cc:209
virtual void setLabel(const std::string &label)
Definition: YQTree.cc:115
void slotItemCollapsed(QTreeWidgetItem *item)
Definition: YQTree.cc:220
virtual void deselectAllItems()
Definition: YQTree.cc:231
virtual ~YQTree()
Definition: YQTree.cc:109
virtual void setContextMenuPos(QPoint contextMenuPos)
void sendEvent(YEvent *event)
Definition: YQUI.cc:477
virtual void setSize(int newWidth, int newHeight)
Definition: YQTree.cc:383
virtual void selectItem(YItem *item, bool selected=true)
Definition: YQTree.cc:154
YQTreeItem(YQTree *tree, QTreeWidget *parent, YTreeItem *origItem, int serial)
Definition: YQTree.cc:439
YTreeItem * origItem()
Definition: YQTree.h:243
void busyCursor()
Definition: YQUI.cc:559
void slotSelectionChanged()
Definition: YQTree.cc:340
virtual void deleteAllItems()
Definition: YQTree.cc:257
virtual void setEnabled(bool enabled)
Definition: YQTree.cc:389
QString key(int column, bool ascending) const
Definition: YQTree.cc:515
void slotActivated(QTreeWidgetItem *item)
Definition: YQTree.cc:356
void normalCursor()
Definition: YQUI.cc:565
void buildDisplayTree(YQTreeItem *parentItem, YItemIterator begin, YItemIterator end)
Definition: YQTree.cc:132
static YQUI * ui()
Definition: YQUI.h:81
virtual int preferredHeight()
Definition: YQTree.cc:372
virtual bool setKeyboardFocus()
Definition: YQTree.cc:397
void slotContextMenu(const QPoint &pos)
Definition: YQTree.cc:405