libyui-qt-pkg  2.45.6
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  std::string iconpath = YQPackageSelector::iconPath(icon, 32);
476  //std::cout << icon << " | "<< iconpath << std::endl;
477 
478  setIcon(_patternList->iconCol(), QIcon(QString(iconpath.c_str())));
479 
480  }
481 
482  setStatusIcon();
483  resetToolTip();
484  setFirstColumnSpanned ( false );
485 }
486 
487 
488 
490 {
491  // NOP
492 }
493 
494 
495 void
497 {
498  if ( ! _editable || ! _pkgObjList->editable() )
499  return;
500 
501  ZyppStatus oldStatus = status();
502  ZyppStatus newStatus = oldStatus;
503 
504  switch ( oldStatus )
505  {
506  case S_Install:
507  newStatus = S_NoInst;
508  break;
509 
510 // see: bnc 476965
511 // case S_KeepInstalled:
512 // newStatus = S_Install;
513 // break;
514 
515  case S_NoInst:
516  newStatus = S_Install;
517  break;
518 
519  case S_AutoInstall:
520  newStatus = S_NoInst;
521  break;
522 
523  default:
524  break;
525  }
526 
527  if ( oldStatus != newStatus )
528  {
529  setStatus( newStatus );
530 
531  if ( showLicenseAgreement() )
532  {
533  showNotifyTexts( newStatus );
534  }
535  else // License not confirmed?
536  {
537  // Status is now S_Taboo or S_Del - update status icon
538  setStatusIcon();
539  }
540 
541  _patternList->sendStatusChanged();
542  }
543 }
544 
545 
546 void
548 {
549  std::string infoToolTip;
550  infoToolTip += ("<p>" + zyppPattern()->description() + "</p>");
551 
552  if ( totalPackages() > 0 )
553  {
554  infoToolTip += ("<p>" + zypp::str::form("%d / %d", installedPackages(), totalPackages() ) + "</p>");
555  }
556 
557  setToolTip(_patternList->summaryCol(), fromUTF8(infoToolTip));
558 }
559 
560 void
562 {
564 }
565 
566 
567 bool YQPkgPatternListItem::operator< ( const QTreeWidgetItem & otherListViewItem ) const
568 {
569  const YQPkgPatternListItem * otherPatternListitem = dynamic_cast<const YQPkgPatternListItem *>(&otherListViewItem);
570 
571  //std::cout << _zyppPattern->order()<< " | " << otherPatternListitem->zyppPattern()->order() << std::endl;
572 
573 
574  if ( _zyppPattern && otherPatternListitem && otherPatternListitem->zyppPattern() )
575  {
576  if ( _zyppPattern->order() != otherPatternListitem->zyppPattern()->order() )
577  return _zyppPattern->order() < otherPatternListitem->zyppPattern()->order();
578  else
579  return _zyppPattern->name() < otherPatternListitem->zyppPattern()->name();
580  }
581 
582  const YQPkgPatternCategoryItem * otherCategoryItem = dynamic_cast<const YQPkgPatternCategoryItem *>(&otherListViewItem);
583 
584  if ( otherCategoryItem ) // Patterns without category should always be sorted
585  return true; // before any category
586 
587  return QTreeWidgetItem::operator<( otherListViewItem );
588 }
589 
591  const QString & category )
592  : QY2ListViewItem( patternList )
593  , _patternList( patternList )
594 {
595  setText( _patternList->summaryCol(), category );
596 
597  setExpanded( true );
598  setTreeIcon();
599 }
600 
601 
603 {
604  // NOP
605 }
606 
607 void
609 {
610  if ( ! _firstPattern )
611  {
612  _firstPattern = pattern;
613  }
614  else
615  {
616  if ( _firstPattern->order().compare( pattern->order() ) < 0 )
617  _firstPattern = pattern;
618  }
619 }
620 
621 
622 void
623 YQPkgPatternCategoryItem::setExpanded( bool open )
624 {
625  QTreeWidgetItem::setExpanded( open );
626  setTreeIcon();
627 }
628 
629 
630 void
632 {
633  setIcon( 0,
634  isExpanded() ?
635  YQIconPool::treeMinus() :
636  YQIconPool::treePlus() );
637 
638 }
639 
640 
641 bool YQPkgPatternCategoryItem::operator< ( const QTreeWidgetItem & otherListViewItem ) const
642 {
643  const YQPkgPatternCategoryItem * otherCategoryItem = dynamic_cast<const YQPkgPatternCategoryItem *>(&otherListViewItem);
644 
645  if ( _firstPattern && otherCategoryItem && otherCategoryItem->firstPattern() )
646  return _firstPattern->order() < otherCategoryItem->firstPattern()->order();
647 
648 
649  const YQPkgPatternListItem * otherPatternListitem = dynamic_cast<const YQPkgPatternListItem *>(&otherListViewItem);
650 
651  if ( otherPatternListitem ) // Patterns without category should always be sorted
652  return false; // before any category
653 
654  return QTreeWidgetItem::operator<( otherListViewItem );
655 }
656 
657 
658 
659 #include "YQPkgPatternList.moc"
virtual void selectSomething()
Select the first selectable list entry that is not a pattern category.
ZyppSel selectable() const
Returns the original selectable within the package manager backend.
Definition: YQPkgObjList.h:466
void setTreeIcon(void)
Set a suitable tree open/close icon depending on this category&#39;s open/close status.
void init()
Initialize things common to all constructors.
void filterFinished()
Emitted when filtering is finished.
ZyppPattern firstPattern() const
Returns the first pattern.
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 bool operator<(const QTreeWidgetItem &other) const
sorting function
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 bool operator<(const QTreeWidgetItem &other) const
sorting function
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
bool editable() const
Return whether or not items in this list are generally editable, i.e.
Definition: YQPkgObjList.h:110
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
YQPkgPatternCategoryItem(YQPkgPatternList *patternList, const QString &category)
Constructor.
Display a list of zypp::Pattern objects.
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...
YQPkgPatternListItem * selection() const
Returns the currently selected item or 0 if there is none.
YQPkgPatternList(QWidget *parent, bool autoFill=true, bool autoFilter=true)
Constructor.
void currentItemChanged(ZyppSel selectable)
Emitted when a zypp::ui::Selectable is selected.
ZyppPattern zyppPattern() const
Returns the original object within the package manager backend.
virtual void cycleStatus()
Cycle the package status to the next valid value.
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 ZyppStatus status() const
Returns the (binary RPM) package status.
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