libyui-qt-pkg  2.44.7
 All Classes Functions Variables Enumerations
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'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'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'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'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's status.
void addPatternItem(ZyppSel selectable, ZyppPattern pattern)
Add a pattern to the list.
void resetToolTip()
resets the tooltip with the current available information