libyui-qt-pkg  2.45.27
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;
128  percentageText.sprintf("%d/%d", item->installedPackages(), item->totalPackages());
129 
130  painter->setPen( _view->palette().color( QPalette::Base ) );
131  painter->drawText( QRect( x, y,
132  w, h ),
133  Qt::AlignHCenter, percentageText );
134  painter->restore();
135  }
136  painter->restore();
137  return;
138 
139  }
140  else
141  {
142  painter->restore();
143  QItemDelegate::paint(painter, option, index);
144  }
145  }
146  }
147 };
148 
149 
150 YQPkgPatternList::YQPkgPatternList( QWidget * parent, bool autoFill, bool autoFilter )
151  : YQPkgObjList( parent )
152  , _howmanyCol(0)
153 {
154  yuiDebug() << "Creating pattern list" << std::endl;
155 
156  int numCol = 0;
157  QStringList headers;
158  //headers << "";
159  headers << ""; _statusCol = numCol++;
160 
161  // Translators: "Pattern" refers to so-called "installation patterns",
162  // i.e., specific task-oriented groups of packages, like "everything that
163  // is needed to run a web server". The idea of patterns is that they also
164  // include the configuration workflow needed for that task, such of
165  // configuring the web server. For the scope of the package selector, this
166  // is only of little relevance, though.
167 
168  headers << ""; _iconCol = numCol++;
169  headers << _( "Pattern" ); _summaryCol = numCol++;
170 
171  //headers << ""; _howmanyCol = numCol++;
172 
173  setColumnCount( numCol );
174  setHeaderLabels(headers);
175 
176  setIndentation(0);
177 
178  setItemDelegateForColumn( _iconCol, new YQPkgPatternItemDelegate( this ) );
179  setItemDelegateForColumn( _statusCol, new YQPkgPatternItemDelegate( this ) );
180  setItemDelegateForColumn( _summaryCol, new YQPkgPatternItemDelegate( this ) );
181  //setItemDelegateForColumn( _howmanyCol, new YQPkgPatternItemDelegate(this) );
182 
183  // Can use the same colum for "broken" and "satisfied":
184  // Both states are mutually exclusive
185 
186  _satisfiedIconCol = -42;
187  _brokenIconCol = -42;
188 
189 // header()->setStretchEnabled( _statusCol , false );
190 // header()->setStretchEnabled( _summaryCol, true );
191 
192  setSortingEnabled( true );
193  sortByColumn( summaryCol(), Qt::AscendingOrder );
194 
195  setAllColumnsShowFocus( true );
196 
197  header()->setSectionResizeMode( statusCol(), QHeaderView::Fixed );
198  header()->setSectionResizeMode( summaryCol(), QHeaderView::Stretch );
199  header()->setSectionResizeMode( howmanyCol(), QHeaderView::Fixed );
200 
201  header()->resizeSection( statusCol(), 25 );
202  setColumnWidth( statusCol(), 25 );
203  setColumnWidth( summaryCol(), 100 );
204  setColumnWidth( howmanyCol(), 15 );
205 
206  //header()->resizeSection( 0, 0 );
207 
208  //header()->setMinimumSectionSize( 25 );
209 
210  if ( autoFilter )
211  {
212  connect( this, SIGNAL( currentItemChanged( QTreeWidgetItem *,
213  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 
227  yuiDebug() << "Creating pattern list done" << std::endl;
228 }
229 
230 
232 {
233  // NOP
234 }
235 
236 
237 void
239 {
240  _categories.clear();
241 
242  clear();
243  yuiDebug() << "Filling pattern list" << std::endl;
244 
245  for ( ZyppPoolIterator it = zyppPatternsBegin();
246  it != zyppPatternsEnd();
247  ++it )
248  {
249  ZyppPattern zyppPattern = tryCastToZyppPattern( (*it)->theObj() );
250 
251  if ( zyppPattern )
252  {
253  if ( zyppPattern->userVisible() )
254  {
255  addPatternItem( *it, zyppPattern );
256  }
257  else
258  yuiDebug() << "Pattern " << zyppPattern->name()
259  << " is not user-visible" << std::endl;
260  }
261  else
262  {
263  yuiError() << "Found non-Pattern selectable" << std::endl;
264  }
265  }
266 
267  yuiDebug() << "Pattern list filled" << std::endl;
268  resizeColumnToContents(_iconCol);
269  resizeColumnToContents(_statusCol);
270  resizeColumnToContents(_howmanyCol);
271 }
272 
273 
275 YQPkgPatternList::category( const QString & categoryName )
276 {
277  if ( categoryName.isEmpty() )
278  return 0;
279 
280  YQPkgPatternCategoryItem * cat = _categories[ categoryName ];
281 
282  if ( ! cat )
283  {
284  yuiDebug() << "New pattern category \""<< categoryName << "\"" << std::endl;
285 
286  cat = new YQPkgPatternCategoryItem( this, categoryName );
287  Q_CHECK_PTR( cat );
288  _categories.insert( categoryName, cat );
289  }
290 
291  return cat;
292 }
293 
294 
295 
296 void
298 {
299  if ( isVisible() )
300  filter();
301 }
302 
303 
304 void
306 {
307  emit filterStart();
308 
309  if ( selection() ) // The seleted QListViewItem
310  {
311  ZyppPattern zyppPattern = selection()->zyppPattern();
312 
313  if ( zyppPattern )
314  {
315  int total = 0;
316  int installed = 0;
317 
318  zypp::Pattern::Contents c(zyppPattern->contents());
319  for ( zypp::Pattern::Contents::Selectable_iterator it = c.selectableBegin();
320  it != c.selectableEnd();
321  ++it )
322  {
323  ZyppPkg zyppPkg = tryCastToZyppPkg( (*it)->theObj() );
324  if ( zyppPkg )
325  {
326  if ( (*it)->installedSize() > 0 )
327  ++installed;
328  ++total;
329 
330  emit filterMatch( *it, zyppPkg );
331  }
332  }
333  selection()->setInstalledPackages(installed);
334  selection()->setTotalPackages(total);
335  selection()->resetToolTip();
336  }
337  }
338 
339  emit filterFinished();
340  resizeColumnToContents(_howmanyCol);
341 }
342 
343 
344 void
346  ZyppPattern zyppPattern )
347 {
348  if ( ! selectable )
349  {
350  yuiError() << "NULL ZyppSelectable!" << std::endl;
351  return;
352  }
353 
354  YQPkgPatternCategoryItem * cat = category( fromUTF8( zyppPattern->category() ) );
355  YQPkgPatternListItem * item = 0;
356 
357  if ( cat )
358  {
359  item = new YQPkgPatternListItem( this, cat, selectable, zyppPattern );
360  }
361  else
362  {
363  item = new YQPkgPatternListItem( this, selectable, zyppPattern );
364  }
365 
366  resizeColumnToContents(_howmanyCol);
367  resizeColumnToContents(_summaryCol);
368 
369  addTopLevelItem(item);
370  applyExcludeRules( item );
371 }
372 
373 
376 {
377  QTreeWidgetItem * item = currentItem();
378 
379  if ( ! item )
380  return 0;
381 
382  return dynamic_cast<YQPkgPatternListItem *> (item);
383 }
384 
385 
386 void
388  QTreeWidgetItem * listViewItem,
389  int col,
390  const QPoint & pos )
391 {
392  YQPkgPatternCategoryItem * categoryItem
393  = dynamic_cast<YQPkgPatternCategoryItem *> (listViewItem);
394 
395  if ( categoryItem )
396  {
397  if ( button == Qt::LeftButton )
398  {
399  if ( col == 0 )
400  {
401  categoryItem->setExpanded( ! categoryItem->isExpanded() );
402  }
403  }
404  }
405  else
406  {
407 
408  YQPkgObjList::pkgObjClicked( button, listViewItem, col, pos );
409  }
410 }
411 
412 
413 void
415 {
416 #if FIXME
417  QTreeWidgetItemIterator it( this );
418 
419  while ( *it )
420  {
421  QY2ListViewItem * item = dynamic_cast<QY2ListViewItem *> (*it);
422  YQPkgPatternCategoryItem * categoryItem =
423  dynamic_cast<YQPkgPatternCategoryItem *> (*it);
424 
425  if ( item && item->isSelectable() && ! categoryItem )
426  {
427  setSelected( item, true ); // emits signal, too
428  return;
429  }
430 
431  ++it;
432  }
433 #endif
434 }
435 
436 
438  ZyppSel selectable,
439  ZyppPattern zyppPattern )
440  : YQPkgObjListItem( patternList, selectable, zyppPattern )
441  , _patternList( patternList )
442  , _zyppPattern( zyppPattern )
443  , _total(0), _installed(0)
444 {
445  init();
446 }
447 
448 
450  YQPkgPatternCategoryItem * parentCategory,
451  ZyppSel selectable,
452  ZyppPattern zyppPattern )
453  : YQPkgObjListItem( patternList, parentCategory, selectable, zyppPattern )
454  , _patternList( patternList )
455  , _zyppPattern( zyppPattern )
456  , _total(0), _installed(0)
457 {
458  init();
459  parentCategory->addPattern( _zyppPattern );
460 }
461 
462 
463 void
465 {
466  if ( ! _zyppPattern )
467  _zyppPattern = tryCastToZyppPattern( selectable()->theObj() );
468 
469  if (_zyppPattern)
470  {
471  string iconName = _zyppPattern->icon().basename();
472  if ( iconName.empty() )
473  iconName = "pattern-generic";
474 
475  setIcon( _patternList->iconCol(), YQUI::ui()->loadIcon( iconName ) );
476 
477  }
478 
479  setStatusIcon();
480  resetToolTip();
481  setFirstColumnSpanned ( false );
482 }
483 
484 
485 
487 {
488  // NOP
489 }
490 
491 
492 void
494 {
495  if ( ! _editable || ! _pkgObjList->editable() )
496  return;
497 
498  ZyppStatus oldStatus = status();
499  ZyppStatus newStatus = oldStatus;
500 
501  switch ( oldStatus )
502  {
503  case S_Install:
504  newStatus = S_NoInst;
505  break;
506 
507 // see: bnc 476965
508 // case S_KeepInstalled:
509 // newStatus = S_Install;
510 // break;
511 
512  case S_NoInst:
513  newStatus = S_Install;
514  break;
515 
516  case S_AutoInstall:
517  newStatus = S_NoInst;
518  break;
519 
520  default:
521  break;
522  }
523 
524  if ( oldStatus != newStatus )
525  {
526  setStatus( newStatus );
527 
528  if ( showLicenseAgreement() )
529  {
530  showNotifyTexts( newStatus );
531  }
532  else // License not confirmed?
533  {
534  // Status is now S_Taboo or S_Del - update status icon
535  setStatusIcon();
536  }
537 
538  _patternList->sendStatusChanged();
539  }
540 }
541 
542 
543 void
545 {
546  std::string infoToolTip;
547  infoToolTip += ("<p>" + zyppPattern()->description() + "</p>");
548 
549  if ( totalPackages() > 0 )
550  {
551  infoToolTip += ("<p>" + zypp::str::form("%d / %d", installedPackages(), totalPackages() ) + "</p>");
552  }
553 
554  setToolTip(_patternList->summaryCol(), fromUTF8(infoToolTip));
555 }
556 
557 
558 void
560 {
562 }
563 
564 
565 bool YQPkgPatternListItem::operator< ( const QTreeWidgetItem & otherListViewItem ) const
566 {
567  const YQPkgPatternListItem * otherPatternListitem = dynamic_cast<const YQPkgPatternListItem *>(&otherListViewItem);
568 
569  if ( _zyppPattern && otherPatternListitem && otherPatternListitem->zyppPattern() )
570  {
571  if ( _zyppPattern->order() != otherPatternListitem->zyppPattern()->order() )
572  return _zyppPattern->order() < otherPatternListitem->zyppPattern()->order();
573  else
574  return _zyppPattern->name() < otherPatternListitem->zyppPattern()->name();
575  }
576 
577  const YQPkgPatternCategoryItem * otherCategoryItem = dynamic_cast<const YQPkgPatternCategoryItem *>(&otherListViewItem);
578 
579  if ( otherCategoryItem ) // Patterns without category should always be sorted
580  return true; // before any category
581 
582  return QTreeWidgetItem::operator<( otherListViewItem );
583 }
584 
585 
587  const QString & category )
588  : QY2ListViewItem( patternList )
589  , _patternList( patternList )
590 {
591  setText( _patternList->summaryCol(), category );
592 
593  setExpanded( true );
594  setTreeIcon();
595 }
596 
597 
599 {
600  // NOP
601 }
602 
603 
604 void
606 {
607  if ( ! _firstPattern )
608  {
609  _firstPattern = pattern;
610  }
611  else
612  {
613  if ( _firstPattern->order().compare( pattern->order() ) < 0 )
614  _firstPattern = pattern;
615  }
616 }
617 
618 
619 void
620 YQPkgPatternCategoryItem::setExpanded( bool open )
621 {
622  QTreeWidgetItem::setExpanded( open );
623  setTreeIcon();
624 }
625 
626 
627 void
629 {
630  setIcon( 0,
631  isExpanded() ?
632  YQIconPool::arrowDown() :
633  YQIconPool::arrowRight() );
634 
635 }
636 
637 
638 bool YQPkgPatternCategoryItem::operator< ( const QTreeWidgetItem & otherListViewItem ) const
639 {
640  const YQPkgPatternCategoryItem * otherCategoryItem = dynamic_cast<const YQPkgPatternCategoryItem *>(&otherListViewItem);
641 
642  if ( _firstPattern && otherCategoryItem && otherCategoryItem->firstPattern() )
643  return _firstPattern->order() < otherCategoryItem->firstPattern()->order();
644 
645 
646  const YQPkgPatternListItem * otherPatternListitem = dynamic_cast<const YQPkgPatternListItem *>(&otherListViewItem);
647 
648  if ( otherPatternListitem ) // Patterns without category should always be sorted
649  return false; // before any category
650 
651  return QTreeWidgetItem::operator<( otherListViewItem );
652 }
653 
654 
655 
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'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'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'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:454
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,...
void showNotifyTexts(ZyppStatus status)
Display this item'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'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.