libyui-qt-pkg  2.47.5
YQPkgPatchList.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: YQPkgPatchList.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 
45 #include <QPainter>
46 #include <QItemDelegate>
47 #include <QMenu>
48 #include <QAction>
49 #include <QEvent>
50 #include <QHeaderView>
51 #include <zypp/base/Logger.h>
52 #include <set>
53 
54 #include "YQi18n.h"
55 #include "utf8.h"
56 
57 #include "YQPkgPatchList.h"
58 #include "YQPkgTextDialog.h"
59 #include "YQIconPool.h"
60 
61 using std::list;
62 using std::endl;
63 using std::set;
64 
65 class YQPkgPatchItemDelegate : public QItemDelegate
66 {
67  YQPkgPatchList *_view;
68 public:
69  YQPkgPatchItemDelegate( YQPkgPatchList *parent ) : QItemDelegate( parent ), _view( parent ) {
70  }
71 
72  virtual void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
73  {
74  painter->save();
75 
76  YQPkgPatchCategoryItem *citem = dynamic_cast<YQPkgPatchCategoryItem *>(_view->itemFromIndex(index));
77  // special painting for category items
78  if ( citem )
79  {
80  QFont f = painter->font();
81  f.setWeight(QFont::Bold);
82  QFontMetrics fm(f);
83  f.setPixelSize( (int) ( fm.height() * 1.05 ) );
84  citem->setFont(_view->summaryCol(), f);
85 
86  QItemDelegate::paint(painter, option, index);
87  painter->restore();
88  return;
89  }
90 
91  YQPkgPatchListItem *item = dynamic_cast<YQPkgPatchListItem *>(_view->itemFromIndex(index));
92  if ( item )
93  {
94  painter->restore();
95  QItemDelegate::paint(painter, option, index);
96  }
97  }
98 };
99 
100 
102  : YQPkgObjList( parent )
103 {
104  yuiDebug() << "Creating patch list" << endl;
105 
106  _filterCriteria = RelevantPatches;
107 
108  int numCol = 0;
109 
110  QStringList headers;
111 
112  headers << ""; _statusCol = numCol++;
113  //headers << _( "Patch" ); _nameCol = numCol++;
114  headers << _( "Summary" ); _summaryCol = numCol++;
115  //headers << _( "Category" ); _categoryCol = numCol++;
116  //headers << _( "Size" ); _sizeCol = numCol++;
117  //headers << _( "Version" ); _versionCol = numCol++;
118 
119  // Can use the same colum for "broken" and "satisfied":
120  // Both states are mutually exclusive
121 
122  _satisfiedIconCol = -42;
123  _brokenIconCol = -42;
124 
125  setHeaderLabels(headers);
126  setIndentation(0);
127 
128  header()->setSectionResizeMode(_statusCol, QHeaderView::ResizeToContents);
129  //header()->setSectionResizeMode(_versionCol, QHeaderView::ResizeToContents);
130  //header()->setSectionResizeMode(_categoryCol, QHeaderView::ResizeToContents);
131  header()->setSectionResizeMode(_summaryCol, QHeaderView::Stretch);
132 
133 
134  setItemDelegateForColumn( _summaryCol, new YQPkgPatchItemDelegate( this ) );
135  setItemDelegateForColumn( _statusCol, new YQPkgPatchItemDelegate( this ) );
136 
137  setAllColumnsShowFocus( true );
138  //FIXME setColumnAlignment( sizeCol(), Qt::AlignRight );
139 
140  connect( this, SIGNAL( currentItemChanged ( QTreeWidgetItem *, QTreeWidgetItem* ) ),
141  this, SLOT ( filter() ) );
142 
143  //sortItems( categoryCol(), Qt::AscendingOrder );
144  setSortingEnabled( true );
145 
146  fillList();
147 
148  yuiDebug() << "Creating patch list done" << endl;
149 }
150 
151 
153 {
154  // NOP
155 }
156 
157 
158 void
160 {
161  // Delayed initialization after widget is fully created etc.
162 
163  // Only now send currentItemChanged() signal so attached details views also
164  // display something if their showDetailsIfVisible() slot is connected to
165  // currentItemChanged() signals.
166  selectSomething();
167 }
168 
170 YQPkgPatchList::category( YQPkgPatchCategory category )
171 {
172  YQPkgPatchCategoryItem * cat = _categories[ category ];
173 
174  if ( ! cat )
175  {
176  yuiDebug() << "New patch category \""<< category << "\"" << endl;
177 
178  cat = new YQPkgPatchCategoryItem( category, this );
179  Q_CHECK_PTR( cat );
180  _categories.insert( category, cat );
181  }
182 
183  return cat;
184 }
185 
186 void
187 YQPkgPatchList::setFilterCriteria( FilterCriteria filterCriteria )
188 {
189  _filterCriteria = filterCriteria;
190 }
191 
192 void
194 {
195  // wee need to do a full solve in order
196  // to get the satisfied status correctly
197 
198  _categories.clear();
199 
200  clear();
201  yuiDebug() << "Filling patch list" << endl;
202 
203  for ( ZyppPoolIterator it = zyppPatchesBegin();
204  it != zyppPatchesEnd();
205  ++it )
206  {
207  ZyppSel selectable = *it;
208  ZyppPatch zyppPatch = tryCastToZyppPatch( selectable->theObj() );
209 
210  if ( zyppPatch )
211  {
212  bool displayPatch = false;
213 
214  switch ( _filterCriteria )
215  {
216  case RelevantPatches: // needed + broken + satisfied (but not installed)
217 
218  // only shows patches relevant to the system
219  if ( selectable->hasCandidateObj() &&
220  selectable->candidateObj().isRelevant() )
221  {
222  // and only those that are needed
223  if ( ! selectable->candidateObj().isSatisfied() ||
224  // may be it is satisfied because is preselected
225  selectable->candidateObj().status().isToBeInstalled() )
226  displayPatch = true;
227  else
228  yuiDebug() << "Patch " << zyppPatch->ident()
229  << " is already satisfied"
230  << endl;
231 
232  }
233  else
234  yuiDebug() << "Patch " << zyppPatch->ident()
235  << " is not relevant to the system"
236  << endl;
237  break;
238  case RelevantAndInstalledPatches: // patches we dont need
239 
240  // only shows patches relevant to the system
241  if ( ( selectable->hasCandidateObj() ) &&
242  ( ! selectable->candidateObj().isRelevant()
243  || ( selectable->candidateObj().isSatisfied() &&
244  ! selectable->candidateObj().status().isToBeInstalled() ) ) )
245  {
246  // now we show satisfied patches too
247  displayPatch = true;
248  }
249  break;
250  case AllPatches:
251  displayPatch = true;
252  break;
253 
254  // Intentionally omitting "default" so the compiler
255  // can catch unhandled enum values
256  default:
257  yuiDebug() << "unknown patch filter" << endl;
258 
259  }
260 
261  if ( displayPatch )
262  {
263  yuiDebug() << "Displaying patch " << zyppPatch->name()
264  << " - " << zyppPatch->summary()
265  << endl;
266  addPatchItem( *it, zyppPatch);
267  }
268  }
269  else
270  {
271  yuiError() << "Found non-patch selectable" << endl;
272  }
273  }
274 
275  yuiDebug() << "Patch list filled" << endl;
276  resizeColumnToContents(_statusCol);
277  //resizeColumnToContents(_nameCol);
278  //resizeColumnToContents(_categoryCol);
279 }
280 
281 
282 
283 void
284 YQPkgPatchList::message( const QString & text )
285 {
286  QY2ListViewItem * item = new QY2ListViewItem( this );
287  Q_CHECK_PTR( item );
288 
289  item->setText( 1, text );
290  item->setBackground( 0, QColor( 0xE0, 0xE0, 0xF8 ) );
291 }
292 
293 void
295 {
296  if ( isVisible() )
297  filter();
298 }
299 
300 
301 void
303 {
304  emit filterStart();
305 
306  if ( selection() )
307  {
308  ZyppPatch patch = selection()->zyppPatch();
309 
310  if ( patch )
311  {
312  zypp::Patch::Contents contents(patch->contents());
313  yuiMilestone() << contents << endl;
314 
315  for ( zypp::Patch::Contents::Selectable_iterator it = contents.selectableBegin();
316  it != contents.selectableEnd();
317  ++it )
318  {
319  ZyppPkg zyppPkg = tryCastToZyppPkg( (*it)->theObj() );
320  if ( zyppPkg )
321  {
322  emit filterMatch( *it, zyppPkg );
323  }
324  }
325  }
326  else
327  {
328  yuiMilestone() << "patch is bogus" << endl;
329  }
330 
331  }
332  else
333  yuiWarning() << "selection empty" << endl;
334 
335  emit filterFinished();
336 }
337 
338 
339 void
340 YQPkgPatchList::addPatchItem( ZyppSel selectable,
341  ZyppPatch zyppPatch )
342 {
343  if ( ! selectable || ! zyppPatch )
344  {
345  yuiError() << "NULL ZyppSel!" << endl;
346  return;
347  }
348 
349  YQPkgPatchCategory ncat = YQPkgPatchCategoryItem::patchCategory(zyppPatch->category());
350 
351  YQPkgPatchCategoryItem * cat = category(ncat);
352  YQPkgPatchListItem * item = 0;
353 
354  if ( cat )
355  {
356  item = new YQPkgPatchListItem( this, cat, selectable, zyppPatch );
357  }
358  else
359  {
360  item = new YQPkgPatchListItem( this, selectable, zyppPatch );
361  }
362 
363  if (item)
364  applyExcludeRules( item );
365 
366 }
367 
368 
371 {
372  QTreeWidgetItem * item = currentItem();
373 
374  if ( ! item )
375  return 0;
376 
377  return dynamic_cast<YQPkgPatchListItem *> (item);
378 }
379 
380 
381 
382 void
384 {
385  _notInstalledContextMenu = new QMenu( this );
386  Q_CHECK_PTR( _notInstalledContextMenu );
387 
388  _notInstalledContextMenu->addAction(actionSetCurrentInstall);
389  _notInstalledContextMenu->addAction(actionSetCurrentDontInstall);
390  _notInstalledContextMenu->addAction(actionSetCurrentTaboo);
391 
392  addAllInListSubMenu( _notInstalledContextMenu );
393 }
394 
395 
396 void
398 {
399  _installedContextMenu = new QMenu( this );
400  Q_CHECK_PTR( _installedContextMenu );
401 
402  _installedContextMenu->addAction(actionSetCurrentKeepInstalled);
403 
404 #if ENABLE_DELETING_PATCHES
405  _installedContextMenu->addAction(actionSetCurrentDelete);
406 #endif
407 
408  _installedContextMenu->addAction(actionSetCurrentUpdate);
409  _installedContextMenu->addAction(actionSetCurrentUpdateForce);
410  _installedContextMenu->addAction(actionSetCurrentProtected);
411 
412  addAllInListSubMenu( _installedContextMenu );
413 }
414 
415 
416 QMenu *
418 {
419  QMenu * submenu = new QMenu( menu );
420  Q_CHECK_PTR( submenu );
421 
422  submenu->addAction(actionSetListInstall);
423  submenu->addAction(actionSetListDontInstall);
424  submenu->addAction(actionSetListKeepInstalled);
425 
426 #if ENABLE_DELETING_PATCHES
427  submenu->addAction(actionSetListDelete);
428 #endif
429 
430  submenu->addAction(actionSetListUpdate);
431  submenu->addAction(actionSetListUpdateForce);
432  submenu->addAction(actionSetListTaboo);
433  submenu->addAction(actionSetListProtected);
434 
435  QAction *action = menu->addMenu(submenu);
436  action->setText(_( "&All in This List" ));
437 
438  return submenu;
439 }
440 
441 
442 void
443 YQPkgPatchList::keyPressEvent( QKeyEvent * event )
444 {
445  if ( event )
446  {
447 #if ! ENABLE_DELETING_PATCHES
448  if ( event->ascii() == '-' )
449  {
450  QTreeWidgetItem * selectedListViewItem = currentItem();
451 
452  if ( selectedListViewItem )
453  {
454  YQPkgPatchListItem * item = dynamic_cast<YQPkgPatchListItem *> (selectedListViewItem);
455 
456  if ( item && item->selectable()->hasInstalledObj() )
457  {
458  yuiWarning() << "Deleting patches is not supported" << endl;
459  return;
460  }
461  }
462  }
463 #endif
464  }
465 
467 }
468 
469 
471  YQPkgPatchCategoryItem * parentCategory,
472  ZyppSel selectable,
473  ZyppPatch zyppPatch )
474  : YQPkgObjListItem( patchList, parentCategory, selectable, zyppPatch )
475  , _patchList( patchList )
476  , _zyppPatch( zyppPatch )
477 {
478 
479  init();
480 }
481 
483  ZyppSel selectable,
484  ZyppPatch zyppPatch )
485  : YQPkgObjListItem( patchList, selectable, zyppPatch )
486  , _patchList( patchList )
487  , _zyppPatch( zyppPatch )
488 {
489  init();
490 
491 }
492 
493 void YQPkgPatchListItem::init()
494 {
495  setStatusIcon();
496 
497  if ( summaryCol() > -1 && _zyppPatch->summary().empty() )
498  setText( summaryCol(), _zyppPatch->name() ); // use name as fallback
499 }
500 
501 
503 {
504  // NOP
505 }
506 
507 void
509 {
511 
512  if ( status() == S_Del ) // Can't delete patches
513  setStatus( S_KeepInstalled );
514 }
515 
516 
517 QString
519 {
520  QString text;
521 
522  if ( col == statusCol() )
523  {
524  text = YQPkgObjListItem::toolTip( col );
525  }
526  else
527  {
528  if ( ( col == brokenIconCol() && isBroken() ) ||
529  ( col == satisfiedIconCol() && isSatisfied() ) )
530  {
531  text = YQPkgObjListItem::toolTip( col );
532  }
533  else
534  {
535  text = fromUTF8( zyppPatch()->category() );
536 
537  if ( ! text.isEmpty() )
538  text += "\n";
539 
540  text += fromUTF8( zyppPatch()->downloadSize().asString().c_str() );
541  }
542  }
543 
544  return text;
545 }
546 
547 
548 void
550 {
552 }
553 
554 
555 bool YQPkgPatchListItem::operator< ( const QTreeWidgetItem & otherListViewItem ) const
556 {
557  const YQPkgPatchListItem * other = dynamic_cast<const YQPkgPatchListItem *> (&otherListViewItem);
558  if ( other )
559  {
560  return ( this->text(_patchList->summaryCol()) < other->text( _patchList->summaryCol()) );
561  }
562  return YQPkgObjListItem::operator<( otherListViewItem );
563 }
564 
566  YQPkgPatchList * patchList )
567  : QY2ListViewItem( patchList )
568  , _patchList( patchList )
569 {
570 
571  _category = category;
572 
573 
574  if ( _patchList->categoryCol() > -1 )
575  setText( _patchList->summaryCol(), YQPkgPatchCategoryItem::asString( _category ) );
576 
577 
578  //setText( _patchList->summaryCol(), "Category" );
579 
580  setExpanded( true );
581  setTreeIcon();
582 }
583 
584 
585 YQPkgPatchCategory
586 YQPkgPatchCategoryItem::patchCategory( const string & category )
587 {
588  return patchCategory( fromUTF8( category ) );
589 }
590 
591 
592 YQPkgPatchCategory
594 {
595  category = category.toLower();
596 
597  if ( category == "yast" ) return YQPkgYaSTPatch;
598  if ( category == "security" ) return YQPkgSecurityPatch;
599  if ( category == "recommended" ) return YQPkgRecommendedPatch;
600  if ( category == "optional" ) return YQPkgOptionalPatch;
601  if ( category == "document" ) return YQPkgDocumentPatch;
602 
603  yuiWarning() << "Unknown patch category \"" << category << "\"" << endl;
604  return YQPkgUnknownPatchCategory;
605 }
606 
607 
608 QString
609 YQPkgPatchCategoryItem::asString( YQPkgPatchCategory category )
610 {
611  switch ( category )
612  {
613  // Translators: These are patch categories
614  case YQPkgYaSTPatch: return _( "YaST" );
615  case YQPkgSecurityPatch: return _( "security" );
616  case YQPkgRecommendedPatch: return _( "recommended" );
617  case YQPkgOptionalPatch: return _( "optional" );
618  case YQPkgDocumentPatch: return _( "document" );
619  case YQPkgUnknownPatchCategory: return "";
620  }
621 
622  return "";
623 }
624 
625 
627 {
628  // NOP
629 }
630 
631 void
633 {
634  if ( ! _firstPatch )
635  {
636  _firstPatch = patch;
637  }
638  else
639  {
640  //if ( _firstPatch->order().compare( pattern->order() ) < 0 )
641  // _firstPatch = pattern;
642  }
643 }
644 
645 
646 void
647 YQPkgPatchCategoryItem::setExpanded( bool open )
648 {
649  QTreeWidgetItem::setExpanded( open );
650  setTreeIcon();
651 }
652 
653 
654 void
656 {
657  setIcon( _patchList->iconCol(),
658  isExpanded() ?
659  YQIconPool::arrowDown() :
660  YQIconPool::arrowRight() );
661 
662 }
663 
664 
665 bool YQPkgPatchCategoryItem::operator< ( const QTreeWidgetItem & otherListViewItem ) const
666 {
667  const YQPkgPatchCategoryItem * otherCategoryItem = dynamic_cast<const YQPkgPatchCategoryItem *>(&otherListViewItem);
668 
669  return category() > otherCategoryItem->category();
670  return QTreeWidgetItem::operator<( otherListViewItem );
671 }
672 
673 
674 
Abstract base class to display a list of zypp::ResObjects.
Definition: YQPkgObjList.h:66
void setText(int column, const string text)
Set a column text via STL string.
Display a list of zypp::Patch objects.
FilterCriteria filterCriteria() const
Returns the current filter criteria.
virtual bool operator<(const QTreeWidgetItem &other) const
sorting function
virtual bool operator<(const QTreeWidgetItem &other) const
sorting function
void filterIfVisible()
Same as filter(), but only if this widget is currently visible.
virtual void polish()
Delayed initialization after the dialog is fully created.
virtual void applyChanges()
Propagate status changes in this list to other lists: Have the solver transact all patches...
ZyppPatch zyppPatch() const
Returns the original zyppPatch object.
void filter()
Filter according to the view&#39;s rules and current selection.
virtual ~YQPkgPatchCategoryItem()
Destructor.
virtual ~YQPkgPatchListItem()
Destructor.
virtual void clear()
Reimplemented from QY2ListView: Emit currentItemChanged() signal after clearing the list...
void fillList()
Fill the patch list according to filterCriteria().
virtual void keyPressEvent(QKeyEvent *ev)
Event handler for keyboard input.
virtual void cycleStatus()
Cycle the package status to the next valid value.
virtual void setStatus(ZyppStatus newStatus, bool sendSignals=true)
Set the (binary RPM) package status.
bool isBroken() const
Check if this item is "broken": If it is installed, but any of its dependencies are no longer satisfi...
void filterMatch(ZyppSel selectable, ZyppPkg pkg)
Emitted during filtering for each pkg that matches the filter.
YQPkgPatchList(QWidget *parent)
Constructor.
virtual ZyppStatus status() const
Returns the (binary RPM) package status.
virtual bool operator<(const QTreeWidgetItem &other) const
sorting function
YQPkgPatchCategoryItem(YQPkgPatchCategory category, YQPkgPatchList *patternList)
Constructor.
virtual void createInstalledContextMenu()
Create the context menu for installed items.
virtual void message(const QString &text)
Display a one-line message in the list.
static QString asString(YQPkgPatchCategory category)
Converts a patch category to a user-readable (translated) string.
void applyExcludeRules()
Apply all exclude rules of this list to all items, including those that are currently excluded...
virtual void createNotInstalledContextMenu()
Create the context menu for items that are not installed.
void setTreeIcon(void)
Set a suitable tree open/close icon depending on this category&#39;s open/close status.
virtual ~YQPkgPatchList()
Destructor.
ZyppSel selectable() const
Returns the original selectable within the package manager backend.
Definition: YQPkgObjList.h:452
bool isSatisfied() const
Check if this item is satisfied, even though it is not installed.
void currentItemChanged(ZyppSel selectable)
Emitted when a zypp::ui::Selectable is selected.
virtual QMenu * addAllInListSubMenu(QMenu *menu)
Add a submenu "All in this list..." to &#39;menu&#39;.
void filterFinished()
Emitted when filtering is finished.
void filterStart()
Emitted when the filtering starts.
YQPkgPatchCategory category() const
Category (and order ) for this item.
int categoryCol() const
Returns the column for the patch category.
static YQPkgPatchCategory patchCategory(QString category)
Maps a string patch category to the corresponding enum.
void addPatchItem(ZyppSel selectable, ZyppPatch zyppPatch)
Add a patch to the list.
void addPatch(ZyppPatch patch)
Add a pattern to this category.
virtual QString toolTip(int column)
Returns a tool tip text for a specific column of this item.
void solveResolvableCollections()
Do a "small" solver run for all "resolvable collections", i.e., for selections, patterns, languages, patches.
YQPkgPatchListItem * selection() const
Returns the currently selected item or 0 if there is none.
virtual QString toolTip(int column)
Returns a tool tip text for a specific column of this item.
virtual void keyPressEvent(QKeyEvent *ev)
Event handler for keyboard input.
void setFilterCriteria(FilterCriteria filterCriteria)
Set the filter criteria for fillList().
YQPkgPatchListItem(YQPkgPatchList *patchList, ZyppSel selectable, ZyppPatch zyppPatch)
Constructor.
YQPkgPatchCategoryItem * category(YQPkgPatchCategory category)
returns or creates a category item for a defined category
virtual void setStatusIcon()
Set a status icon according to the package&#39;s status.
virtual void cycleStatus()
Cycle the package status to the next valid value.