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&#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: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, 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.