libyui-qt-pkg  2.45.15
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 class YQPkgPatternItemDelegate : public QItemDelegate
65 {
66  YQPkgPatternList *_view;
67 public:
68  YQPkgPatternItemDelegate( YQPkgPatternList *parent ) : QItemDelegate( parent ), _view( parent ) {
69  }
70 
71  virtual void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
72  {
73  painter->save();
74 
75  YQPkgPatternCategoryItem *citem = dynamic_cast<YQPkgPatternCategoryItem *>(_view->itemFromIndex(index));
76  // special painting for category items
77  if ( citem )
78  {
79  //std::cout << "printing category: " << index.column() << std::endl;
80  QFont f = painter->font();
81  f.setWeight(QFont::Bold);
82  QFontMetrics fm(f);
83  f.setPixelSize( (int) ( fm.height() * 1.1 ) );
84  citem->setFont(_view->summaryCol(), f);
85 
86  QItemDelegate::paint(painter, option, index);
87  painter->restore();
88  return;
89  }
90 
91 
92  YQPkgPatternListItem *item = dynamic_cast<YQPkgPatternListItem *>(_view->itemFromIndex(index));
93  if ( item )
94  {
95  //if ( index.column() == _view->howmanyCol() )
96  if ( false )
97  {
98  //std::cout << "printing percentage: " << index.column() << std::endl;
99 
100  QColor background = option.palette.color(QPalette::Window);
101  painter->setBackground( background );
102 
103  float percent = (item->totalPackages() > 0)
104  ? (((float)item->installedPackages()*100) / (float)item->totalPackages())
105  : 0;
106 
107  QColor fillColor = option.palette.color(QPalette::Mid);
108 
109  if ( percent > 100.0 ) percent = 100.0;
110  if ( percent < 0.0 ) percent = 0.0;
111  int x = option.rect.left() + 1;
112  int y = option.rect.top() + 1;
113  int w = option.rect.width() - 2;
114  int h = (int) ( ( (float) option.rect.height() )/2 );
115  int fillWidth = 0;
116  if ( w > 0 )
117  {
118  fillWidth = (int) ( w * percent / 100.0 );
119  //std::cout << "percent: " << percent << " fillw: " << fillWidth << " x: " << x << " y: " << y << "w: " << w << " h: " << h << std::endl;
120 
121  // Fill the desired percentage.
122 
123  painter->fillRect( x, y, fillWidth, h,
124  fillColor );
125 
126  QString percentageText;
127  percentageText.sprintf("%d/%d", item->installedPackages(), item->totalPackages());
128 
129  painter->setPen( _view->palette().color( QPalette::Base ) );
130  painter->drawText( QRect( x, y,
131  w, h ),
132  Qt::AlignHCenter, percentageText );
133  painter->restore();
134  }
135  painter->restore();
136  return;
137 
138  }
139  else
140  {
141  //std::cout << "printing other: " << index.column() << std::endl;
142  painter->restore();
143  QItemDelegate::paint(painter, option, index);
144  }
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 *, QTreeWidgetItem * ) ),
214  this, SLOT ( filter() ) );
215  }
216 
217  setIconSize(QSize(32,32));
218  header()->resizeSection( iconCol(), 34 );
219  //header()->resizeSection( howmanyCol(), 15 );
220 
221  if ( autoFill )
222  {
223  fillList();
224  selectSomething();
225  }
226  yuiDebug() << "Creating pattern list done" << std::endl;
227 }
228 
229 
231 {
232  // NOP
233 }
234 
235 
236 void
238 {
239  _categories.clear();
240 
241  clear();
242  yuiDebug() << "Filling pattern list" << std::endl;
243 
244  for ( ZyppPoolIterator it = zyppPatternsBegin();
245  it != zyppPatternsEnd();
246  ++it )
247  {
248  ZyppPattern zyppPattern = tryCastToZyppPattern( (*it)->theObj() );
249 
250  if ( zyppPattern )
251  {
252  if ( zyppPattern->userVisible() )
253  {
254  addPatternItem( *it, zyppPattern );
255  }
256  else
257  yuiDebug() << "Pattern " << zyppPattern->name()
258  << " is not user-visible" << std::endl;
259  }
260  else
261  {
262  yuiError() << "Found non-Pattern selectable" << std::endl;
263  }
264  }
265 
266  yuiDebug() << "Pattern list filled" << std::endl;
267  resizeColumnToContents(_iconCol);
268  resizeColumnToContents(_statusCol);
269  resizeColumnToContents(_howmanyCol);
270 }
271 
272 
274 YQPkgPatternList::category( const QString & categoryName )
275 {
276  if ( categoryName.isEmpty() )
277  return 0;
278 
279  YQPkgPatternCategoryItem * cat = _categories[ categoryName ];
280 
281  if ( ! cat )
282  {
283  yuiDebug() << "New pattern category \""<< categoryName << "\"" << std::endl;
284 
285  cat = new YQPkgPatternCategoryItem( this, categoryName );
286  Q_CHECK_PTR( cat );
287  _categories.insert( categoryName, cat );
288  }
289 
290  return cat;
291 }
292 
293 
294 
295 void
297 {
298  if ( isVisible() )
299  filter();
300 }
301 
302 
303 void
305 {
306  emit filterStart();
307 
308  if ( selection() ) // The seleted QListViewItem
309  {
310  ZyppPattern zyppPattern = selection()->zyppPattern();
311 
312  if ( zyppPattern )
313  {
314  int total = 0;
315  int installed = 0;
316 
317  zypp::Pattern::Contents c(zyppPattern->contents());
318  for ( zypp::Pattern::Contents::Selectable_iterator it = c.selectableBegin();
319  it != c.selectableEnd();
320  ++it )
321  {
322  ZyppPkg zyppPkg = tryCastToZyppPkg( (*it)->theObj() );
323  if ( zyppPkg )
324  {
325  if ( (*it)->installedSize() > 0 )
326  ++installed;
327  ++total;
328 
329  emit filterMatch( *it, zyppPkg );
330  }
331  }
332  selection()->setInstalledPackages(installed);
333  selection()->setTotalPackages(total);
334  selection()->resetToolTip();
335  }
336  }
337 
338  emit filterFinished();
339  resizeColumnToContents(_howmanyCol);
340 }
341 
342 
343 void
345  ZyppPattern zyppPattern )
346 {
347  if ( ! selectable )
348  {
349  yuiError() << "NULL ZyppSelectable!" << std::endl;
350  return;
351  }
352 
353  YQPkgPatternCategoryItem * cat = category( fromUTF8( zyppPattern->category() ) );
354  YQPkgPatternListItem * item = 0;
355 
356  if ( cat )
357  {
358  item = new YQPkgPatternListItem( this, cat, selectable, zyppPattern );
359  }
360  else
361  {
362  item = new YQPkgPatternListItem( this, selectable, zyppPattern );
363  }
364 
365  resizeColumnToContents(_howmanyCol);
366  resizeColumnToContents(_summaryCol);
367 
368  addTopLevelItem(item);
369  applyExcludeRules( item );
370 }
371 
372 
375 {
376  QTreeWidgetItem * item = currentItem();
377 
378  if ( ! item )
379  return 0;
380 
381  return dynamic_cast<YQPkgPatternListItem *> (item);
382 }
383 
384 
385 void
387  QTreeWidgetItem * listViewItem,
388  int col,
389  const QPoint & pos )
390 {
391  YQPkgPatternCategoryItem * categoryItem
392  = dynamic_cast<YQPkgPatternCategoryItem *> (listViewItem);
393 
394  if ( categoryItem )
395  {
396  if ( button == Qt::LeftButton )
397  {
398  if ( col == 0 )
399  {
400  categoryItem->setExpanded( ! categoryItem->isExpanded() );
401  }
402  }
403  }
404  else
405  {
406 
407  YQPkgObjList::pkgObjClicked( button, listViewItem, col, pos );
408  }
409 }
410 
411 
412 void
414 {
415 #if FIXME
416  QTreeWidgetItemIterator it( this );
417 
418  while ( *it )
419  {
420  QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (*it);
421  YQPkgPatternCategoryItem * categoryItem =
422  dynamic_cast<YQPkgPatternCategoryItem *> (*it);
423 
424  if ( item && item->isSelectable() && ! categoryItem )
425  {
426  setSelected( item, true ); // emits signal, too
427  return;
428  }
429 
430  ++it;
431  }
432 #endif
433 }
434 
436  ZyppSel selectable,
437  ZyppPattern zyppPattern )
438  : YQPkgObjListItem( patternList, selectable, zyppPattern )
439  , _patternList( patternList )
440  , _zyppPattern( zyppPattern )
441  , _total(0), _installed(0)
442 {
443  init();
444 }
445 
446 
448  YQPkgPatternCategoryItem * parentCategory,
449  ZyppSel selectable,
450  ZyppPattern zyppPattern )
451  : YQPkgObjListItem( patternList, parentCategory, selectable, zyppPattern )
452  , _patternList( patternList )
453  , _zyppPattern( zyppPattern )
454  , _total(0), _installed(0)
455 {
456  init();
457  parentCategory->addPattern( _zyppPattern );
458 }
459 
460 
461 void
463 {
464  if ( ! _zyppPattern )
465  _zyppPattern = tryCastToZyppPattern( selectable()->theObj() );
466 
467  if (_zyppPattern)
468  {
469  string icon = _zyppPattern->icon().asString();
470  // HACK most patterns have wrong default icon
471  if ( (icon == zypp::Pathname("yast-system").asString()) ||
472  icon.empty() )
473  icon = "pattern-generic";
474 
475 
476  //std::cout << icon << " | "<< iconpath << std::endl;
477  QString iconName = QString::fromStdString(icon);
478  if ( QIcon::hasThemeIcon(iconName) )
479  {
480  setIcon( _patternList->iconCol(), QIcon::fromTheme(iconName) );
481  }
482  else
483  {
484  std::string iconpath = YQPackageSelector::iconPath(icon, 32);
485  setIcon(_patternList->iconCol(), QIcon(QString(iconpath.c_str())));
486  }
487 
488 
489  }
490 
491  setStatusIcon();
492  resetToolTip();
493  setFirstColumnSpanned ( false );
494 }
495 
496 
497 
499 {
500  // NOP
501 }
502 
503 
504 void
506 {
507  if ( ! _editable || ! _pkgObjList->editable() )
508  return;
509 
510  ZyppStatus oldStatus = status();
511  ZyppStatus newStatus = oldStatus;
512 
513  switch ( oldStatus )
514  {
515  case S_Install:
516  newStatus = S_NoInst;
517  break;
518 
519 // see: bnc 476965
520 // case S_KeepInstalled:
521 // newStatus = S_Install;
522 // break;
523 
524  case S_NoInst:
525  newStatus = S_Install;
526  break;
527 
528  case S_AutoInstall:
529  newStatus = S_NoInst;
530  break;
531 
532  default:
533  break;
534  }
535 
536  if ( oldStatus != newStatus )
537  {
538  setStatus( newStatus );
539 
540  if ( showLicenseAgreement() )
541  {
542  showNotifyTexts( newStatus );
543  }
544  else // License not confirmed?
545  {
546  // Status is now S_Taboo or S_Del - update status icon
547  setStatusIcon();
548  }
549 
550  _patternList->sendStatusChanged();
551  }
552 }
553 
554 
555 void
557 {
558  std::string infoToolTip;
559  infoToolTip += ("<p>" + zyppPattern()->description() + "</p>");
560 
561  if ( totalPackages() > 0 )
562  {
563  infoToolTip += ("<p>" + zypp::str::form("%d / %d", installedPackages(), totalPackages() ) + "</p>");
564  }
565 
566  setToolTip(_patternList->summaryCol(), fromUTF8(infoToolTip));
567 }
568 
569 void
571 {
573 }
574 
575 
576 bool YQPkgPatternListItem::operator< ( const QTreeWidgetItem & otherListViewItem ) const
577 {
578  const YQPkgPatternListItem * otherPatternListitem = dynamic_cast<const YQPkgPatternListItem *>(&otherListViewItem);
579 
580  //std::cout << _zyppPattern->order()<< " | " << otherPatternListitem->zyppPattern()->order() << std::endl;
581 
582 
583  if ( _zyppPattern && otherPatternListitem && otherPatternListitem->zyppPattern() )
584  {
585  if ( _zyppPattern->order() != otherPatternListitem->zyppPattern()->order() )
586  return _zyppPattern->order() < otherPatternListitem->zyppPattern()->order();
587  else
588  return _zyppPattern->name() < otherPatternListitem->zyppPattern()->name();
589  }
590 
591  const YQPkgPatternCategoryItem * otherCategoryItem = dynamic_cast<const YQPkgPatternCategoryItem *>(&otherListViewItem);
592 
593  if ( otherCategoryItem ) // Patterns without category should always be sorted
594  return true; // before any category
595 
596  return QTreeWidgetItem::operator<( otherListViewItem );
597 }
598 
600  const QString & category )
601  : QY2ListViewItem( patternList )
602  , _patternList( patternList )
603 {
604  setText( _patternList->summaryCol(), category );
605 
606  setExpanded( true );
607  setTreeIcon();
608 }
609 
610 
612 {
613  // NOP
614 }
615 
616 void
618 {
619  if ( ! _firstPattern )
620  {
621  _firstPattern = pattern;
622  }
623  else
624  {
625  if ( _firstPattern->order().compare( pattern->order() ) < 0 )
626  _firstPattern = pattern;
627  }
628 }
629 
630 
631 void
632 YQPkgPatternCategoryItem::setExpanded( bool open )
633 {
634  QTreeWidgetItem::setExpanded( open );
635  setTreeIcon();
636 }
637 
638 
639 void
641 {
642  setIcon( 0,
643  isExpanded() ?
644  YQIconPool::treeMinus() :
645  YQIconPool::treePlus() );
646 
647 }
648 
649 
650 bool YQPkgPatternCategoryItem::operator< ( const QTreeWidgetItem & otherListViewItem ) const
651 {
652  const YQPkgPatternCategoryItem * otherCategoryItem = dynamic_cast<const YQPkgPatternCategoryItem *>(&otherListViewItem);
653 
654  if ( _firstPattern && otherCategoryItem && otherCategoryItem->firstPattern() )
655  return _firstPattern->order() < otherCategoryItem->firstPattern()->order();
656 
657 
658  const YQPkgPatternListItem * otherPatternListitem = dynamic_cast<const YQPkgPatternListItem *>(&otherListViewItem);
659 
660  if ( otherPatternListitem ) // Patterns without category should always be sorted
661  return false; // before any category
662 
663  return QTreeWidgetItem::operator<( otherListViewItem );
664 }
665 
666 
667 
668 #include "YQPkgPatternList.moc"
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:68
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:248
void filter()
Filter according to the view&#39;s rules and current selection.
static std::string iconPath(const std::string &name, int size)
returns the full path for an icon of a given size
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:110
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:466
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.