]> icculus.org git repositories - duncan/yast2-qt4.git/blob - src/YQTree.cc
clicking packages work! so the package selector is now
[duncan/yast2-qt4.git] / src / YQTree.cc
1 /*---------------------------------------------------------------------\
2 |                                                                      |
3 |                      __   __    ____ _____ ____                      |
4 |                      \ \ / /_ _/ ___|_   _|___ \                     |
5 |                       \ V / _` \___ \ | |   __) |                    |
6 |                        | | (_| |___) || |  / __/                     |
7 |                        |_|\__,_|____/ |_| |_____|                    |
8 |                                                                      |
9 |                               core system                            |
10 |                                                        (C) SuSE GmbH |
11 \----------------------------------------------------------------------/
12
13   File:       YQTree.cc
14
15   Author:     Stefan Hundhammer <sh@suse.de>
16
17 /-*/
18
19 #include <QColorGroup>
20 #include <QHeaderView>
21 #include <QLabel>
22 #include <QTreeWidget>
23 #include <QVBoxLayout>
24 #include <QString>
25 //Added by qt3to4:
26 #include <QPixmap>
27 #define y2log_component "qt-ui"
28 #include <ycp/y2log.h>
29
30 using std::min;
31 using std::max;
32
33 #include "YQUI.h"
34 #include "YEvent.h"
35 #include "utf8.h"
36 #include "YQTree.h"
37 #include "YTreeItem.h"
38 #include "YQSignalBlocker.h"
39 #include "YQWidgetCaption.h"
40
41 #define VERBOSE_TREE_ITEMS      0
42
43
44 YQTree::YQTree( YWidget * parent, const string & label )
45     : QFrame( (QWidget *) parent->widgetRep() )
46     , YTree( parent, label )
47 {
48     QVBoxLayout* layout = new QVBoxLayout( this );
49     setLayout( layout );
50
51     setWidgetRep( this );
52
53     layout->setSpacing( YQWidgetSpacing );
54     layout->setMargin ( YQWidgetMargin  );
55
56     _nextSerialNo = 0;
57
58     _caption     = new YQWidgetCaption( this, label );
59     YUI_CHECK_NEW( _caption );
60     layout->addWidget( _caption );
61
62     _qt_listView = new QTreeWidget( this );
63     YUI_CHECK_NEW( _qt_listView );
64     layout->addWidget( _qt_listView );
65
66      //_qt_listView->setHeaderLabel("");
67 //     _qt_listView->addColumn( "" );
68      _qt_listView->header()->hide();
69      // _qt_listView->setHeader(0L);
70      _qt_listView->setRootIsDecorated ( true );
71
72     _caption->setBuddy ( _qt_listView );
73
74     connect( _qt_listView,      SIGNAL( itemSelectionChanged () ),
75              this,              SLOT  ( slotSelectionChanged () ) );
76
77     connect( _qt_listView,      SIGNAL( itemActivated    ( QTreeWidgetItem * , int ) ),
78              this,              SLOT  ( slotActivated    ( QTreeWidgetItem *    ) ) );
79
80     connect( _qt_listView,      SIGNAL( itemDoubleClicked( QTreeWidgetItem *, int ) ),
81              this,              SLOT  ( slotActivated    ( QTreeWidgetItem *    ) ) );
82 }
83
84
85 YQTree::~YQTree()
86 {
87     // NOP
88 }
89
90
91 void YQTree::setLabel( const string & label )
92 {
93     _caption->setText( label );
94     YTree::setLabel( label );
95 }
96
97
98 void YQTree::rebuildTree()
99 {
100     // y2debug( "Rebuilding tree" );
101
102     YQSignalBlocker sigBlocker( _qt_listView );
103     _qt_listView->clear();
104
105     buildDisplayTree( 0, itemsBegin(), itemsEnd() );
106 }
107
108
109 void YQTree::buildDisplayTree( YQTreeItem * parentItem, YItemIterator begin, YItemIterator end )
110 {
111     for ( YItemIterator it = begin; it < end; ++it )
112     {
113         YTreeItem * orig = dynamic_cast<YTreeItem *> (*it);
114         YUI_CHECK_PTR( orig );
115
116         YQTreeItem * clone;
117
118         if ( parentItem )
119             clone = new YQTreeItem( this, parentItem, orig, _nextSerialNo++ );
120         else
121             clone = new YQTreeItem( this, _qt_listView, orig, _nextSerialNo++ );
122
123         YUI_CHECK_NEW( clone );
124
125         if ( orig->hasChildren() )
126             buildDisplayTree( clone, orig->childrenBegin(), orig->childrenEnd() );
127     }
128 }
129
130
131 void YQTree::selectItem( YItem * yItem, bool selected )
132 {
133     YQSignalBlocker sigBlocker( _qt_listView );
134
135     YTreeItem * treeItem = dynamic_cast<YTreeItem *> (yItem);
136     YUI_CHECK_PTR( treeItem );
137
138     YQTreeItem * yqTreeItem = (YQTreeItem *) treeItem->data();
139     YUI_CHECK_PTR( yqTreeItem );
140
141     if ( ! selected && yqTreeItem == _qt_listView->currentItem() )
142     {
143         deselectAllItems();
144     }
145     else
146     {
147         yqTreeItem->setSelected( true );
148         openBranch( yqTreeItem );
149         YTree::selectItem( treeItem, selected );
150     }
151 }
152
153
154 void YQTree::selectItem( YQTreeItem * item )
155 {
156     if ( item )
157     {
158         YQSignalBlocker sigBlocker( _qt_listView );
159
160         item->setSelected( true );
161         openBranch( item );
162         YTree::selectItem( item->origItem(), true );
163
164         y2debug( "selected item: \"%s\"", item->origItem()->label().c_str() );
165     }
166 }
167
168
169 void YQTree::openBranch( QTreeWidgetItem * item )
170 {
171     while ( item )
172     {
173       item->setExpanded( true ); // Takes care of origItem()->setOpen()
174       item = item->parent();
175     }
176 }
177
178
179 void YQTree::deselectAllItems()
180 {
181     YQSignalBlocker sigBlocker( _qt_listView );
182
183     YTree::deselectAllItems();
184     _qt_listView->clearSelection();
185 }
186
187
188 void YQTree::deleteAllItems()
189 {
190     YQSignalBlocker sigBlocker( _qt_listView );
191
192     _qt_listView->clear();
193     YTree::deleteAllItems();
194 }
195
196
197 void YQTree::slotSelectionChanged( )
198 {
199     QList<QTreeWidgetItem *> items = _qt_listView->selectedItems ();
200     QTreeWidgetItem *qItem = items.first();
201     selectItem( dynamic_cast<YQTreeItem *> (qItem) );
202
203     if ( notify() && ! YQUI::ui()->eventPendingFor( this ) )
204         YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::SelectionChanged ) );
205 }
206
207
208 void YQTree::slotActivated( QTreeWidgetItem * qItem )
209 {
210     selectItem( dynamic_cast<YQTreeItem *> (qItem) );
211
212     if ( notify() )
213         YQUI::ui()->sendEvent( new YWidgetEvent( this, YEvent::Activated ) );
214 }
215
216
217 int YQTree::preferredWidth()
218 {
219     int hintWidth = !_caption->isHidden() ? _caption->sizeHint().width() : 0;
220     return max( 200, hintWidth );
221 }
222
223
224 int YQTree::preferredHeight()
225 {
226     // 300 is an arbitrary value.  Use a MinSize or MinHeight widget to set a
227     // size that is useful for the application.
228
229     int hintHeight = !_caption->isHidden() ? _caption->sizeHint().height() : 0;
230
231     return 300 + hintHeight;
232 }
233
234
235 void YQTree::setSize( int newWidth, int newHeight )
236 {
237     resize( newWidth, newHeight );
238 }
239
240
241 void YQTree::setEnabled( bool enabled )
242 {
243     _caption->setEnabled( enabled );
244     _qt_listView->setEnabled( enabled );
245     YWidget::setEnabled( enabled );
246 }
247
248
249 bool YQTree::setKeyboardFocus()
250 {
251     _qt_listView->setFocus();
252
253     return true;
254 }
255
256
257 /*============================================================================*/
258
259
260
261 YQTreeItem::YQTreeItem( YQTree  *       tree,
262                         QTreeWidget *   listView,
263                         YTreeItem *     orig,
264                         int             serial )
265     : QTreeWidgetItem( listView )
266 {
267     init( tree, orig, serial );
268
269 #if VERBOSE_TREE_ITEMS
270     y2debug( "Creating toplevel tree item \"%s\"", orig->label().c_str() );
271 #endif
272 }
273
274
275 YQTreeItem::YQTreeItem( YQTree  *       tree,
276                         YQTreeItem *    parentItem,
277                         YTreeItem *     orig,
278                         int             serial )
279     : QTreeWidgetItem( parentItem )
280 {
281     init( tree, orig, serial );
282 #if VERBOSE_TREE_ITEMS
283     y2debug( "Creating tree item \"%s\" as child of \"%s\"",
284              orig->label().c_str(),
285              parentItem->origItem()->label().c_str() );
286 #endif
287 }
288
289
290 void YQTreeItem::init( YQTree *         tree,
291                        YTreeItem *      orig,
292                        int              serial )
293 {
294     YUI_CHECK_PTR( tree );
295     YUI_CHECK_PTR( orig );
296
297     _tree       = tree;
298     _serialNo   = serial;
299     _origItem   = orig;
300
301     _origItem->setData( this );
302
303     setText( 0, fromUTF8 ( _origItem->label() ) );
304     setOpen( _origItem->isOpen() );
305
306     if ( _origItem->hasIconName() )
307     {
308         string iconName = _tree->iconFullPath( _origItem );
309         QPixmap icon( iconName.c_str() );
310
311         if ( icon.isNull() )
312             y2warning( "Can't load icon %s", iconName.c_str() );
313         else
314             setData( 0, Qt::DecorationRole, icon );
315     }
316 }
317
318
319 void
320 YQTreeItem::setOpen( bool open )
321 {
322     QTreeWidgetItem::setExpanded( open );
323     _origItem->setOpen( open );
324 }
325
326
327
328 QString
329 YQTreeItem::key( int column, bool ascending ) const
330 {
331     /*
332      * Sorting key for QListView internal sorting:
333      *
334      * Always sort tree items by insertion order. The tree widget
335      * cannot maintain a meaningful sorting order of its own: All it
336      * could do is sort by names (ASCII sort). Better let the (YCP)
337      * application handle this.
338      */
339
340     QString strKey;
341     strKey.sprintf( "%08d", _serialNo );
342
343     return strKey;
344 }
345
346
347 #include "YQTree.moc"