libyui-qt-pkg  2.47.5
YQPkgPatternList.cc
1 /**************************************************************************
2 Copyright (C) 2000 - 2010 Novell, Inc.
3 All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 
19 **************************************************************************/
20 
21 
22 /*---------------------------------------------------------------------\
23 | |
24 | __ __ ____ _____ ____ |
25 | \ \ / /_ _/ ___|_ _|___ \ |
26 | \ V / _` \___ \ | | __) | |
27 | | | (_| |___) || | / __/ |
28 | |_|\__,_|____/ |_| |_____| |
29 | |
30 | core system |
31 | (C) SuSE GmbH |
32 \----------------------------------------------------------------------/
33 
34  File: YQPkgPatternList.cc
35 
36  Author: Stefan Hundhammer <sh@suse.de>
37 
38  Textdomain "qt-pkg"
39 
40 /-*/
41 
42 #define YUILogComponent "qt-pkg"
43 #include "YUILog.h"
44 #include <QRegExp>
45 #include <zypp/ZYppFactory.h>
46 #include <zypp/Resolver.h>
47 #include <QPainter>
48 #include <QHeaderView>
49 #include <QLabel>
50 #include <QLayout>
51 #include <QItemDelegate>
52 
53 #include "YQi18n.h"
54 #include "utf8.h"
55 #include "YQPackageSelector.h"
56 #include "YQPkgPatternList.h"
57 #include "YQIconPool.h"
58 #include "YQApplication.h"
59 #include "YQUI.h"
60 
61 using std::string;
62 using std::set;
63 
64 
65 class YQPkgPatternItemDelegate : public QItemDelegate
66 {
67  YQPkgPatternList *_view;
68 
69 public:
70 
71  YQPkgPatternItemDelegate( YQPkgPatternList *parent ) : QItemDelegate( parent ), _view( parent )
72  {
73  }
74 
75 
76  virtual void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
77  {
78  painter->save();
79 
80  YQPkgPatternCategoryItem *citem = dynamic_cast<YQPkgPatternCategoryItem *>(_view->itemFromIndex(index));
81 
82  // special painting for category items
83  if ( citem )
84  {
85  QFont f = painter->font();
86  f.setWeight( QFont::Bold );
87  QFontMetrics fm(f);
88  f.setPixelSize( (int) ( fm.height() * 1.1 ) );
89  citem->setFont( _view->summaryCol(), f );
90 
91  QItemDelegate::paint( painter, option, index );
92  painter->restore();
93  return;
94  }
95 
96  YQPkgPatternListItem *item = dynamic_cast<YQPkgPatternListItem *>( _view->itemFromIndex( index ) );
97 
98  if ( item )
99  {
100  //if ( index.column() == _view->howmanyCol() )
101  if ( false )
102  {
103  QColor background = option.palette.color(QPalette::Window);
104  painter->setBackground( background );
105 
106  float percent = (item->totalPackages() > 0)
107  ? (((float)item->installedPackages()*100) / (float)item->totalPackages())
108  : 0;
109 
110  QColor fillColor = option.palette.color(QPalette::Mid);
111 
112  if ( percent > 100.0 ) percent = 100.0;
113  if ( percent < 0.0 ) percent = 0.0;
114  int x = option.rect.left() + 1;
115  int y = option.rect.top() + 1;
116  int w = option.rect.width() - 2;
117  int h = (int) ( ( (float) option.rect.height() )/2 );
118  int fillWidth = 0;
119  if ( w > 0 )
120  {
121  fillWidth = (int) ( w * percent / 100.0 );
122 
123  // Fill the desired percentage.
124 
125  painter->fillRect( x, y, fillWidth, h, fillColor );
126 
127  QString percentageText = QString( "%1/%2" )
128  .arg( item->installedPackages() )
129  .arg( item->totalPackages() );
130 
131  painter->setPen( _view->palette().color( QPalette::Base ) );
132  painter->drawText( QRect( x, y,
133  w, h ),
134  Qt::AlignHCenter, percentageText );
135  painter->restore();
136  }
137  painter->restore();
138  return;
139 
140  }
141  else
142  {
143  painter->restore();
144  QItemDelegate::paint( painter, option, index );
145  }
146  }
147  }
148 };
149 
150 
151 YQPkgPatternList::YQPkgPatternList( QWidget * parent, bool autoFill, bool autoFilter )
152  : YQPkgObjList( parent )
153  , _howmanyCol(0)
154 {
155  yuiDebug() << "Creating pattern list" << std::endl;
156 
157  int numCol = 0;
158  QStringList headers;
159  //headers << "";
160  headers << ""; _statusCol = numCol++;
161 
162  // Translators: "Pattern" refers to so-called "installation patterns",
163  // i.e., specific task-oriented groups of packages, like "everything that
164  // is needed to run a web server". The idea of patterns is that they also
165  // include the configuration workflow needed for that task, such of
166  // configuring the web server. For the scope of the package selector, this
167  // is only of little relevance, though.
168 
169  headers << ""; _iconCol = numCol++;
170  headers << _( "Pattern" ); _summaryCol = numCol++;
171 
172  //headers << ""; _howmanyCol = numCol++;
173 
174  setColumnCount( numCol );
175  setHeaderLabels(headers);
176 
177  setIndentation(0);
178 
179  setItemDelegateForColumn( _iconCol, new YQPkgPatternItemDelegate( this ) );
180  setItemDelegateForColumn( _statusCol, new YQPkgPatternItemDelegate( this ) );
181  setItemDelegateForColumn( _summaryCol, new YQPkgPatternItemDelegate( this ) );
182  //setItemDelegateForColumn( _howmanyCol, new YQPkgPatternItemDelegate(this) );
183 
184  // Can use the same colum for "broken" and "satisfied":
185  // Both states are mutually exclusive
186 
187  _satisfiedIconCol = -42;
188  _brokenIconCol = -42;
189 
190 // header()->setStretchEnabled( _statusCol , false );
191 // header()->setStretchEnabled( _summaryCol, true );
192 
193  setSortingEnabled( true );
194  sortByColumn( summaryCol(), Qt::AscendingOrder );
195 
196  setAllColumnsShowFocus( true );
197 
198  header()->setSectionResizeMode( statusCol(), QHeaderView::Fixed );
199  header()->setSectionResizeMode( summaryCol(), QHeaderView::Stretch );
200  header()->setSectionResizeMode( howmanyCol(), QHeaderView::Fixed );
201 
202  header()->resizeSection( statusCol(), 25 );
203  setColumnWidth( statusCol(), 25 );
204  setColumnWidth( summaryCol(), 100 );
205  setColumnWidth( howmanyCol(), 15 );
206 
207  //header()->resizeSection( 0, 0 );
208 
209  //header()->setMinimumSectionSize( 25 );
210 
211  if ( autoFilter )
212  {
213  connect( this, SIGNAL( currentItemChanged( QTreeWidgetItem *,
214  QTreeWidgetItem * ) ),
215  this, SLOT ( filter() ) );
216  }
217 
218  setIconSize(QSize(32,32));
219  header()->resizeSection( iconCol(), 34 );
220  //header()->resizeSection( howmanyCol(), 15 );
221 
222  if ( autoFill )
223  {
224  fillList();
225  selectSomething();
226  }
227 
228  yuiDebug() << "Creating pattern list done" << std::endl;
229 }
230 
231 
233 {
234  // NOP
235 }
236 
237 
238 void
240 {
241  _categories.clear();
242 
243  clear();
244  yuiDebug() << "Filling pattern list" << std::endl;
245 
246  for ( ZyppPoolIterator it = zyppPatternsBegin();
247  it != zyppPatternsEnd();
248  ++it )
249  {
250  ZyppPattern zyppPattern = tryCastToZyppPattern( (*it)->theObj() );
251 
252  if ( zyppPattern )
253  {
254  if ( zyppPattern->userVisible() )
255  {
256  addPatternItem( *it, zyppPattern );
257  }
258  else
259  yuiDebug() << "Pattern " << zyppPattern->name()
260  << " is not user-visible" << std::endl;
261  }
262  else
263  {
264  yuiError() << "Found non-Pattern selectable" << std::endl;
265  }
266  }
267 
268  yuiDebug() << "Pattern list filled" << std::endl;
269  resizeColumnToContents(_iconCol);
270  resizeColumnToContents(_statusCol);
271  resizeColumnToContents(_howmanyCol);
272 }
273 
274 
276 YQPkgPatternList::category( const QString & categoryName )
277 {
278  if ( categoryName.isEmpty() )
279  return 0;
280 
281  YQPkgPatternCategoryItem * cat = _categories[ categoryName ];
282 
283  if ( ! cat )
284  {
285  yuiDebug() << "New pattern category \""<< categoryName << "\"" << std::endl;
286 
287  cat = new YQPkgPatternCategoryItem( this, categoryName );
288  Q_CHECK_PTR( cat );
289  _categories.insert( categoryName, cat );
290  }
291 
292  return cat;
293 }
294 
295 
296 
297 void
299 {
300  if ( isVisible() )
301  filter();
302 }
303 
304 
305 void
307 {
308  emit filterStart();
309 
310  if ( selection() ) // The seleted QListViewItem
311  {
312  ZyppPattern zyppPattern = selection()->zyppPattern();
313 
314  if ( zyppPattern )
315  {
316  int total = 0;
317  int installed = 0;
318 
319  zypp::Pattern::Contents c(zyppPattern->contents());
320  for ( zypp::Pattern::Contents::Selectable_iterator it = c.selectableBegin();
321  it != c.selectableEnd();
322  ++it )
323  {
324  ZyppPkg zyppPkg = tryCastToZyppPkg( (*it)->theObj() );
325  if ( zyppPkg )
326  {
327  if ( (*it)->installedSize() > 0 )
328  ++installed;
329  ++total;
330 
331  emit filterMatch( *it, zyppPkg );
332  }
333  }
334  selection()->setInstalledPackages(installed);
335  selection()->setTotalPackages(total);
336  selection()->resetToolTip();
337  }
338  }
339 
340  emit filterFinished();
341  resizeColumnToContents(_howmanyCol);
342 }
343 
344 
345 void
347  ZyppPattern zyppPattern )
348 {
349  if ( ! selectable )
350  {
351  yuiError() << "NULL ZyppSelectable!" << std::endl;
352  return;
353  }
354 
355  YQPkgPatternCategoryItem * cat = category( fromUTF8( zyppPattern->category() ) );
356  YQPkgPatternListItem * item = 0;
357 
358  if ( cat )
359  {
360  item = new YQPkgPatternListItem( this, cat, selectable, zyppPattern );
361  }
362  else
363  {
364  item = new YQPkgPatternListItem( this, selectable, zyppPattern );
365  }
366 
367  resizeColumnToContents(_howmanyCol);
368  resizeColumnToContents(_summaryCol);
369 
370  addTopLevelItem(item);
371  applyExcludeRules( item );
372 }
373 
374 
377 {
378  QTreeWidgetItem * item = currentItem();
379 
380  if ( ! item )
381  return 0;
382 
383  return dynamic_cast<YQPkgPatternListItem *> (item);
384 }
385 
386 
387 void
389  QTreeWidgetItem * listViewItem,
390  int col,
391  const QPoint & pos )
392 {
393  YQPkgPatternCategoryItem * categoryItem
394  = dynamic_cast<YQPkgPatternCategoryItem *> (listViewItem);
395 
396  if ( categoryItem )
397  {
398  if ( button == Qt::LeftButton )
399  {
400  if ( col == 0 )
401  {
402  categoryItem->setExpanded( ! categoryItem->isExpanded() );
403  }
404  }
405  }
406  else
407  {
408 
409  YQPkgObjList::pkgObjClicked( button, listViewItem, col, pos );
410  }
411 }
412 
413 
414 void
416 {
417 #if FIXME
418  QTreeWidgetItemIterator it( this );
419 
420  while ( *it )
421  {
422  QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (*it);
423  YQPkgPatternCategoryItem * categoryItem =
424  dynamic_cast<YQPkgPatternCategoryItem *> (*it);
425 
426  if ( item && item->isSelectable() && ! categoryItem )
427  {
428  setSelected( item, true ); // emits signal, too
429  return;
430  }
431 
432  ++it;
433  }
434 #endif
435 }
436 
437 
439  ZyppSel selectable,
440  ZyppPattern zyppPattern )
441  : YQPkgObjListItem( patternList, selectable, zyppPattern )
442  , _patternList( patternList )
443  , _zyppPattern( zyppPattern )
444  , _total(0), _installed(0)
445 {
446  init();
447 }
448 
449 
451  YQPkgPatternCategoryItem * parentCategory,
452  ZyppSel selectable,
453  ZyppPattern zyppPattern )
454  : YQPkgObjListItem( patternList, parentCategory, selectable, zyppPattern )
455  , _patternList( patternList )
456  , _zyppPattern( zyppPattern )
457  , _total(0), _installed(0)
458 {
459  init();
460  parentCategory->addPattern( _zyppPattern );
461 }
462 
463 
464 void
466 {
467  if ( ! _zyppPattern )
468  _zyppPattern = tryCastToZyppPattern( selectable()->theObj() );
469 
470  if (_zyppPattern)
471  {
472  string iconName = _zyppPattern->icon().basename();
473  if ( iconName.empty() )
474  iconName = "pattern-generic";
475 
476  setIcon( _patternList->iconCol(), YQUI::ui()->loadIcon( iconName ) );
477 
478  }
479 
480  setStatusIcon();
481  resetToolTip();
482  setFirstColumnSpanned ( false );
483 }
484 
485 
486 
488 {
489  // NOP
490 }
491 
492 
493 void
495 {
496  if ( ! _editable || ! _pkgObjList->editable() )
497  return;
498 
499  ZyppStatus oldStatus = status();
500  ZyppStatus newStatus = oldStatus;
501 
502  switch ( oldStatus )
503  {
504  case S_Install:
505  newStatus = S_NoInst;
506  break;
507 
508 // see: bnc 476965
509 // case S_KeepInstalled:
510 // newStatus = S_Install;
511 // break;
512 
513  case S_NoInst:
514  newStatus = S_Install;
515  break;
516 
517  case S_AutoInstall:
518  newStatus = S_NoInst;
519  break;
520 
521  default:
522  break;
523  }
524 
525  if ( oldStatus != newStatus )
526  {
527  setStatus( newStatus );
528 
529  if ( showLicenseAgreement() )
530  {
531  showNotifyTexts( newStatus );
532  }
533  else // License not confirmed?
534  {
535  // Status is now S_Taboo or S_Del - update status icon
536  setStatusIcon();
537  }
538 
539  _patternList->sendStatusChanged();
540  }
541 }
542 
543 
544 void
546 {
547  std::string infoToolTip;
548  infoToolTip += ("<p>" + zyppPattern()->description() + "</p>");
549 
550  if ( totalPackages() > 0 )
551  {
552  infoToolTip += ("<p>" + zypp::str::form("%d / %d", installedPackages(), totalPackages() ) + "</p>");
553  }
554 
555  setToolTip(_patternList->summaryCol(), fromUTF8(infoToolTip));
556 }
557 
558 
559 void
561 {
563 }
564 
565 
566 bool YQPkgPatternListItem::operator< ( const QTreeWidgetItem & otherListViewItem ) const
567 {
568  const YQPkgPatternListItem * otherPatternListitem = dynamic_cast<const YQPkgPatternListItem *>(&otherListViewItem);
569 
570  if ( _zyppPattern && otherPatternListitem && otherPatternListitem->zyppPattern() )
571  {
572  if ( _zyppPattern->order() != otherPatternListitem->zyppPattern()->order() )
573  return _zyppPattern->order() < otherPatternListitem->zyppPattern()->order();
574  else
575  return _zyppPattern->name() < otherPatternListitem->zyppPattern()->name();
576  }
577 
578  const YQPkgPatternCategoryItem * otherCategoryItem = dynamic_cast<const YQPkgPatternCategoryItem *>(&otherListViewItem);
579 
580  if ( otherCategoryItem ) // Patterns without category should always be sorted
581  return true; // before any category
582 
583  return QTreeWidgetItem::operator<( otherListViewItem );
584 }
585 
586 
588  const QString & category )
589  : QY2ListViewItem( patternList )
590  , _patternList( patternList )
591 {
592  setText( _patternList->summaryCol(), category );
593 
594  setExpanded( true );
595  setTreeIcon();
596 }
597 
598 
600 {
601  // NOP
602 }
603 
604 
605 void
607 {
608  if ( ! _firstPattern )
609  {
610  _firstPattern = pattern;
611  }
612  else
613  {
614  if ( _firstPattern->order().compare( pattern->order() ) < 0 )
615  _firstPattern = pattern;
616  }
617 }
618 
619 
620 void
621 YQPkgPatternCategoryItem::setExpanded( bool open )
622 {
623  QTreeWidgetItem::setExpanded( open );
624  setTreeIcon();
625 }
626 
627 
628 void
630 {
631  setIcon( 0,
632  isExpanded() ?
633  YQIconPool::arrowDown() :
634  YQIconPool::arrowRight() );
635 
636 }
637 
638 
639 bool YQPkgPatternCategoryItem::operator< ( const QTreeWidgetItem & otherListViewItem ) const
640 {
641  const YQPkgPatternCategoryItem * otherCategoryItem = dynamic_cast<const YQPkgPatternCategoryItem *>(&otherListViewItem);
642 
643  if ( _firstPattern && otherCategoryItem && otherCategoryItem->firstPattern() )
644  return _firstPattern->order() < otherCategoryItem->firstPattern()->order();
645 
646 
647  const YQPkgPatternListItem * otherPatternListitem = dynamic_cast<const YQPkgPatternListItem *>(&otherListViewItem);
648 
649  if ( otherPatternListitem ) // Patterns without category should always be sorted
650  return false; // before any category
651 
652  return QTreeWidgetItem::operator<( otherListViewItem );
653 }
654 
655 
656 
virtual void selectSomething()
Select the first selectable list entry that is not a pattern category.
void setTreeIcon(void)
Set a suitable tree open/close icon depending on this category&#39;s open/close status.
ZyppPattern firstPattern() const
Returns the first pattern.
void init()
Initialize things common to all constructors.
void filterFinished()
Emitted when filtering is finished.
Abstract base class to display a list of zypp::ResObjects.
Definition: YQPkgObjList.h:66
virtual void applyChanges()
Propagate status changes in this list to other lists: Have the solver transact all patterns...
virtual ~YQPkgPatternCategoryItem()
Destructor.
YQPkgPatternCategoryItem * category(const QString &categoryName)
Returns the category item with the specified name.
void fillList()
Fill the pattern list.
bool showLicenseAgreement()
Display this item&#39;s license agreement (if there is any) that corresponds to its current status (S_Ins...
YQPkgPatternListItem(YQPkgPatternList *patternList, ZyppSel selectable, ZyppPattern zyppPattern)
Constructor for root items.
virtual void clear()
Reimplemented from QY2ListView: Emit currentItemChanged() signal after clearing the list...
virtual void setStatus(ZyppStatus newStatus, bool sendSignals=true)
Set the (binary RPM) package status.
virtual ~YQPkgPatternListItem()
Destructor.
void filterMatch(ZyppSel selectable, ZyppPkg pkg)
Emitted during filtering for each pkg that matches the filter.
virtual void pkgObjClicked(int button, QTreeWidgetItem *item, int col, const QPoint &pos)
Dispatcher slot for mouse click: cycle status depending on column.
virtual ~YQPkgPatternList()
Destructor.
void filterIfVisible()
Same as filter(), but only if this widget is currently visible.
void sendStatusChanged()
Emit a statusChanged() signal for the specified zypp::ResObject.
Definition: YQPkgObjList.h:241
void filter()
Filter according to the view&#39;s rules and current selection.
virtual ZyppStatus status() const
Returns the (binary RPM) package status.
YQPkgPatternCategoryItem(YQPkgPatternList *patternList, const QString &category)
Constructor.
Display a list of zypp::Pattern objects.
bool editable() const
Return whether or not items in this list are generally editable, i.e.
Definition: YQPkgObjList.h:108
void filterStart()
Emitted when the filtering starts.
void applyExcludeRules()
Apply all exclude rules of this list to all items, including those that are currently excluded...
YQPkgPatternList(QWidget *parent, bool autoFill=true, bool autoFilter=true)
Constructor.
virtual bool operator<(const QTreeWidgetItem &other) const
sorting function
ZyppPattern zyppPattern() const
Returns the original object within the package manager backend.
ZyppSel selectable() const
Returns the original selectable within the package manager backend.
Definition: YQPkgObjList.h:452
void currentItemChanged(ZyppSel selectable)
Emitted when a zypp::ui::Selectable is selected.
virtual void cycleStatus()
Cycle the package status to the next valid value.
virtual bool operator<(const QTreeWidgetItem &other) const
sorting function
void solveResolvableCollections()
Do a "small" solver run for all "resolvable collections", i.e., for selections, patterns, languages, patches.
void showNotifyTexts(ZyppStatus status)
Display this item&#39;s notify text (if there is any) that corresponds to the specified status (S_Install...
void addPattern(ZyppPattern pattern)
Add a pattern to this category.
virtual void pkgObjClicked(int button, QTreeWidgetItem *item, int col, const QPoint &pos)
Dispatcher slot for mouse click: cycle status depending on column.
virtual void setStatusIcon()
Set a status icon according to the package&#39;s status.
void addPatternItem(ZyppSel selectable, ZyppPattern pattern)
Add a pattern to the list.
void resetToolTip()
resets the tooltip with the current available information
YQPkgPatternListItem * selection() const
Returns the currently selected item or 0 if there is none.