]> icculus.org git repositories - duncan/yast2-qt4.git/blob - src/pkg/YQPkgPatternList.cc
clicking packages work! so the package selector is now
[duncan/yast2-qt4.git] / src / pkg / YQPkgPatternList.cc
1 /*---------------------------------------------------------------------\
2 |                                                                      |
3 |                      __   __    ____ _____ ____                      |
4 |                      \ \ / /_ _/ ___|_   _|___ \                     |
5 |                       \ V / _` \___ \ | |   __) |                    |
6 |                        | | (_| |___) || |  / __/                     |
7 |                        |_|\__,_|____/ |_| |_____|                    |
8 |                                                                      |
9 |                               core system                            |
10 |                                                        (C) SuSE GmbH |
11 \----------------------------------------------------------------------/
12
13   File:       YQPkgPatternList.cc
14
15   Author:     Stefan Hundhammer <sh@suse.de>
16
17   Textdomain "packages-qt"
18
19 /-*/
20
21 #define y2log_component "qt-pkg"
22 #include <ycp/y2log.h>
23 #include <QRegExp>
24 #include <zypp/ZYppFactory.h>
25 #include <zypp/Resolver.h>
26 #include <QPainter>
27 #include <QHeaderView>
28 #include <zypp/ui/PatternContents.h>
29
30 #include "YQi18n.h"
31 #include "utf8.h"
32 #include "YQPkgPatternList.h"
33 #include "YQIconPool.h"
34 #include "YQApplication.h"
35 #include "YQUI.h"
36
37
38 #define CATEGORY_BACKGROUND     QColor( 0xFF, 0xC0, 0x50 )
39
40
41 YQPkgPatternList::YQPkgPatternList( QWidget * parent, bool autoFill, bool autoFilter )
42     : YQPkgObjList( parent )
43 {
44     y2debug( "Creating pattern list" );
45
46     int numCol = 0;
47     QStringList headers;
48     headers << "";      _statusCol      = numCol++;
49
50     // Translators: "Pattern" refers to so-called "installation patterns",
51     // i.e., specific task-oriented groups of packages, like "everything that
52     // is needed to run a web server". The idea of patterns is that they also
53     // include the configuration workflow needed for that task, such of
54     // configuring the web server. For the scope of the package selector, this
55     // is only of little relevance, though.
56
57     headers << _( "Pattern" );  _summaryCol     = numCol++;
58
59     setHeaderLabels(headers);
60     // Can use the same colum for "broken" and "satisfied":
61     // Both states are mutually exclusive
62
63     _satisfiedIconCol   = _summaryCol;
64     _brokenIconCol      = _summaryCol;
65
66 //     header()->setStretchEnabled( _statusCol , false );
67 //     header()->setStretchEnabled( _summaryCol, true  );
68
69     setAllColumnsShowFocus( true );
70     //setTreeStepSize( 0 );
71
72     if ( autoFilter )
73     {
74         connect( this, SIGNAL( currentItemChanged( QTreeWidgetItem *, QTreeWidgetItem * ) ),
75                  this, SLOT  ( filter()                            ) );
76     }
77
78     if ( autoFill )
79     {
80         fillList();
81         selectSomething();
82     }
83     y2debug( "Creating pattern list done" );
84 }
85
86
87 YQPkgPatternList::~YQPkgPatternList()
88 {
89     // NOP
90 }
91
92
93 void
94 YQPkgPatternList::fillList()
95 {
96     clear();
97     y2debug( "Filling pattern list" );
98
99
100     for ( ZyppPoolIterator it = zyppPatternsBegin();
101           it != zyppPatternsEnd();
102           ++it )
103     {
104         ZyppPattern zyppPattern = tryCastToZyppPattern( (*it)->theObj() );
105
106         if ( zyppPattern )
107         {
108             if ( zyppPattern->userVisible() )
109             {
110                 addPatternItem( *it, zyppPattern );
111             }
112             else
113                 y2debug( "Pattern %s is not user-visible", zyppPattern->name().c_str() );
114         }
115         else
116         {
117             y2error( "Found non-Pattern selectable" );
118         }
119     }
120
121     y2debug( "Pattern list filled" );
122 }
123
124
125 YQPkgPatternCategoryItem *
126 YQPkgPatternList::category( const QString & categoryName )
127 {
128     if ( categoryName.isEmpty() )
129         return 0;
130
131     YQPkgPatternCategoryItem * cat = _categories[ categoryName ];
132
133     if ( ! cat )
134     {
135         y2debug( "New pattern category \"%s\"", qPrintable(categoryName) );
136
137         cat = new YQPkgPatternCategoryItem( this, categoryName );
138         Q_CHECK_PTR( cat );
139         _categories.insert( categoryName, cat );
140     }
141
142
143     return cat;
144 }
145
146
147 void
148 YQPkgPatternList::filterIfVisible()
149 {
150     if ( isVisible() )
151         filter();
152 }
153
154
155 void
156 YQPkgPatternList::filter()
157 {
158     emit filterStart();
159
160     if ( selection() )  // The seleted QListViewItem
161     {
162         ZyppPattern zyppPattern = selection()->zyppPattern();
163
164         if ( zyppPattern )
165         {
166             zypp::ui::PatternContents patternContents( zyppPattern );
167             set<string> wanted = patternContents.install_packages();
168
169             for ( ZyppPoolIterator it = zyppPkgBegin();
170                   it != zyppPkgEnd();
171                   ++it )
172             {
173                 string name = (*it)->theObj()->name();
174
175                 if ( contains( wanted, name ) )
176                 {
177                     ZyppPkg zyppPkg = tryCastToZyppPkg( (*it)->theObj() );
178
179                     if ( zyppPkg )
180                     {
181                         emit filterMatch( *it, zyppPkg );
182                     }
183                 }
184             }
185         }
186     }
187
188     emit filterFinished();
189 }
190
191
192 void
193 YQPkgPatternList::addPatternItem( ZyppSel       selectable,
194                                   ZyppPattern   zyppPattern )
195 {
196     if ( ! selectable )
197     {
198         y2error( "NULL ZyppSelectable!" );
199         return;
200     }
201
202     YQPkgPatternCategoryItem * cat = category( fromUTF8( zyppPattern->category() ) );
203     YQPkgPatternListItem * item = 0;
204
205     if ( cat )
206         item = new YQPkgPatternListItem( this, cat, selectable, zyppPattern );
207     else
208         item = new YQPkgPatternListItem( this, selectable, zyppPattern );
209
210     addTopLevelItem(item);
211     applyExcludeRules( item );
212 }
213
214
215 YQPkgPatternListItem *
216 YQPkgPatternList::selection() const
217 {
218     QTreeWidgetItem * item = currentItem();
219
220     if ( ! item )
221         return 0;
222
223     return dynamic_cast<YQPkgPatternListItem *> (item);
224 }
225
226
227 void
228 YQPkgPatternList::pkgObjClicked( int                    button,
229                                  QTreeWidgetItem *      listViewItem,
230                                  int                    col,
231                                  const QPoint &         pos )
232 {
233     YQPkgPatternCategoryItem * categoryItem
234         = dynamic_cast<YQPkgPatternCategoryItem *> (listViewItem);
235
236     if ( categoryItem )
237     {
238         if ( button == Qt::LeftButton )
239         {
240             if ( col == statusCol() )
241             {
242                 categoryItem->setExpanded( ! categoryItem->isExpanded() );
243             }
244         }
245     }
246     else
247     {
248         YQPkgObjList::pkgObjClicked( button, listViewItem, col, pos );
249     }
250 }
251
252
253 void
254 YQPkgPatternList::selectSomething()
255 {
256 #if FIXME
257     QTreeWidgetItemIterator it( this );
258
259     while ( *it )
260     {
261         QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (*it);
262         YQPkgPatternCategoryItem * categoryItem =
263             dynamic_cast<YQPkgPatternCategoryItem *> (*it);
264
265         if ( item && item->isSelectable() && ! categoryItem )
266         {
267             setSelected( item, true ); // emits signal, too
268             return;
269         }
270
271         ++it;
272     }
273 #endif
274 }
275
276 void YQPkgPatternList::drawRow ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
277 {
278     painter->setFont( YQUI::yqApp()->headingFont() );
279     QTreeWidget::drawRow ( painter, option, index );
280 }
281
282 YQPkgPatternListItem::YQPkgPatternListItem( YQPkgPatternList *  patternList,
283                                             ZyppSel             selectable,
284                                             ZyppPattern         zyppPattern )
285     : YQPkgObjListItem( patternList, selectable, zyppPattern )
286     , _patternList( patternList )
287     , _zyppPattern( zyppPattern )
288 {
289     init();
290 }
291
292
293 YQPkgPatternListItem::YQPkgPatternListItem( YQPkgPatternList *          patternList,
294                                             YQPkgPatternCategoryItem *  parentCategory,
295                                             ZyppSel                     selectable,
296                                             ZyppPattern                 zyppPattern )
297     : YQPkgObjListItem( patternList, parentCategory, selectable, zyppPattern )
298     , _patternList( patternList )
299     , _zyppPattern( zyppPattern )
300 {
301     init();
302     parentCategory->addPattern( _zyppPattern );
303 }
304
305
306 void
307 YQPkgPatternListItem::init()
308 {
309     if ( ! _zyppPattern )
310         _zyppPattern = tryCastToZyppPattern( selectable()->theObj() );
311
312     setStatusIcon();
313 }
314
315
316
317 YQPkgPatternListItem::~YQPkgPatternListItem()
318 {
319     // NOP
320 }
321
322
323 void
324 YQPkgPatternListItem::applyChanges()
325 {
326     solveResolvableCollections();
327 }
328
329
330 bool YQPkgPatternListItem::operator< ( const QTreeWidgetItem & otherListViewItem ) const
331 {
332     const YQPkgPatternListItem * otherPatternListitem    = dynamic_cast<const YQPkgPatternListItem     *>(&otherListViewItem);
333
334     if ( _zyppPattern && otherPatternListitem && otherPatternListitem->zyppPattern() )
335         return _zyppPattern->order().compare( otherPatternListitem->zyppPattern()->order() );
336
337     const YQPkgPatternCategoryItem * otherCategoryItem = dynamic_cast<const YQPkgPatternCategoryItem *>(&otherListViewItem);
338
339     if ( otherCategoryItem )    // Patterns without category should always be sorted
340         return true;            // before any category
341
342     return QTreeWidgetItem::operator<( otherListViewItem );
343 }
344
345
346
347
348
349
350 YQPkgPatternCategoryItem::YQPkgPatternCategoryItem( YQPkgPatternList *  patternList,
351                                                     const QString &     category        )
352     : QY2ListViewItem( patternList )
353     , _patternList( patternList )
354 {
355     setText( _patternList->summaryCol(), category );
356     setBackgroundColor( CATEGORY_BACKGROUND );
357     setExpanded( true );
358     setTreeIcon();
359 }
360
361
362 YQPkgPatternCategoryItem::~YQPkgPatternCategoryItem()
363 {
364     // NOP
365 }
366
367 void
368 YQPkgPatternCategoryItem::addPattern( ZyppPattern pattern )
369 {
370     if ( ! _firstPattern )
371     {
372         _firstPattern = pattern;
373     }
374     else
375     {
376         if ( _firstPattern->order().compare( pattern->order() ) < 0 )
377             _firstPattern = pattern;
378     }
379 }
380
381
382 void
383 YQPkgPatternCategoryItem::setExpanded( bool open )
384 {
385     QTreeWidgetItem::setExpanded( open );
386     setTreeIcon();
387 }
388
389
390 void
391 YQPkgPatternCategoryItem::setTreeIcon()
392 {
393     setData( _patternList->statusCol(), Qt::DecorationRole,
394                isExpanded() ?
395                YQIconPool::treeMinus() :
396                YQIconPool::treePlus()   );
397
398 }
399
400
401 bool YQPkgPatternCategoryItem::operator< ( const QTreeWidgetItem & otherListViewItem ) const
402 {
403     const YQPkgPatternCategoryItem * otherCategoryItem = dynamic_cast<const YQPkgPatternCategoryItem *>(&otherListViewItem);
404
405     if ( _firstPattern && otherCategoryItem && otherCategoryItem->firstPattern() )
406         return _firstPattern->order().compare( otherCategoryItem->firstPattern()->order() );
407
408
409     const YQPkgPatternListItem * otherPatternListitem    = dynamic_cast<const YQPkgPatternListItem *>(&otherListViewItem);
410
411     if ( otherPatternListitem ) // Patterns without category should always be sorted
412         return true;            // before any category
413
414     return QTreeWidgetItem::operator<( otherListViewItem );
415 }
416
417
418
419 #include "YQPkgPatternList.moc"