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