1 /*---------------------------------------------------------------------\
3 | __ __ ____ _____ ____ |
4 | \ \ / /_ _/ ___|_ _|___ \ |
5 | \ V / _` \___ \ | | __) | |
6 | | | (_| |___) || | / __/ |
7 | |_|\__,_|____/ |_| |_____| |
11 \----------------------------------------------------------------------/
13 File: YQPkgPatchList.cc
15 Author: Stefan Hundhammer <sh@suse.de>
17 Textdomain "packages-qt"
22 #define y2log_component "qt-pkg"
23 #include <ycp/y2log.h>
25 #include <qpopupmenu.h>
27 #include <zypp/ui/PatchContents.h>
33 #include "YQPkgPatchList.h"
34 #include "YQPkgTextDialog.h"
37 #define VERBOSE_PATCH_LIST 1
38 #define DEBUG_SHOW_ALL_UPDATE_STACK_PATCHES 0
41 typedef zypp::ui::PatchContents ZyppPatchContents;
42 typedef zypp::ui::PatchContents::const_iterator ZyppPatchContentsIterator;
48 YQPkgPatchList::YQPkgPatchList( QWidget * parent )
49 : YQPkgObjList( parent )
51 y2debug( "Creating patch list" );
53 _filterCriteria = RelevantPatches;
56 addColumn( "" ); _statusCol = numCol++;
57 addColumn( _( "Patch" ) ); _nameCol = numCol++;
58 addColumn( _( "Summary" ) ); _summaryCol = numCol++;
59 addColumn( _( "Category" ) ); _categoryCol = numCol++;
60 addColumn( _( "Size" ) ); _sizeCol = numCol++;
61 addColumn( _( "Version" ) ); _versionCol = numCol++;
63 // Can use the same colum for "broken" and "satisfied":
64 // Both states are mutually exclusive
66 _satisfiedIconCol = _summaryCol;
67 _brokenIconCol = _summaryCol;
69 setAllColumnsShowFocus( true );
70 setColumnAlignment( sizeCol(), Qt::AlignRight );
72 connect( this, SIGNAL( selectionChanged ( QListViewItem * ) ),
73 this, SLOT ( filter() ) );
75 setSorting( categoryCol() );
77 y2debug( "Creating patch list done" );
81 YQPkgPatchList::~YQPkgPatchList()
88 YQPkgPatchList::polish()
90 // Delayed initialization after widget is fully created etc.
92 // Only now send selectionChanged() signal so attached details views also
93 // display something if their showDetailsIfVisible() slot is connected to
94 // selectionChanged() signals.
100 YQPkgPatchList::setFilterCriteria( FilterCriteria filterCriteria )
102 _filterCriteria = filterCriteria;
107 YQPkgPatchList::fillList()
110 y2debug( "Filling patch list" );
112 for ( ZyppPoolIterator it = zyppPatchesBegin();
113 it != zyppPatchesEnd();
116 ZyppSel selectable = *it;
117 ZyppPatch zyppPatch = tryCastToZyppPatch( selectable->theObj() );
121 bool displayPatch = false;
123 switch ( _filterCriteria )
125 case UpdateStackPatches:
127 if ( zyppPatch->affects_pkg_manager() )
129 #if DEBUG_SHOW_ALL_UPDATE_STACK_PATCHES
132 if ( selectable->hasCandidateObj() &&
133 selectable->candidatePoolItem().status().isNeeded() )
137 y2milestone( "Found YaST patch that should be installed: %s - %s",
138 zyppPatch->name().c_str(),
139 zyppPatch->summary().c_str() );
142 if ( selectable->hasInstalledObj() &&
143 selectable->installedPoolItem().status().isIncomplete() ) // patch broken?
147 y2warning( "Installed YaST patch is broken: %s - %s",
148 zyppPatch->name().c_str(),
149 zyppPatch->summary().c_str() );
154 case RelevantPatches: // needed + broken + satisfied (but not installed)
156 if ( selectable->hasInstalledObj() ) // installed?
158 if ( selectable->installedPoolItem().status().isIncomplete() ) // patch broken?
160 // The patch is broken: It had been installed, but the user somehow
161 // downgraded individual packages belonging to the patch to older versions.
165 y2warning( "Installed patch is broken: %s - %s",
166 zyppPatch->name().c_str(),
167 zyppPatch->summary().c_str() );
170 else // not installed
172 if ( selectable->hasCandidateObj() &&
173 selectable->candidatePoolItem().status().isSatisfied() )
175 // This is a pretty exotic case, but still it might happen:
177 // The patch itelf is not installed, but it is satisfied because the
178 // user updated all the packages belonging to the patch to the versions
179 // the patch requires. All that is missing now is to get the patch meta
180 // data onto the system. So let's display the patch to give the user
181 // a chance to install it (if he so chooses).
185 y2milestone( "Patch satisfied, but not installed yet: %s - %s",
186 zyppPatch->name().c_str(),
187 zyppPatch->summary().c_str() );
191 if ( selectable->hasCandidateObj() ) // candidate available?
193 // The most common case: There is a candidate patch, i.e. one that could be
194 // installed, but either no version of that patch is installed or there is a
195 // newer one to which the patch could be updated.
197 if ( selectable->candidatePoolItem().status().isNeeded() ) // patch really needed?
199 // Patches are needed if any of the packages that belong to the patch
200 // are installed on the system.
206 // None of the packages that belong to the patch is installed on the system.
208 y2debug( "Patch not needed: %s - %s",
209 zyppPatch->name().c_str(),
210 zyppPatch->summary().c_str() );
216 case RelevantAndInstalledPatches: // needed + broken + installed
218 if ( selectable->hasInstalledObj() ) // installed?
222 else // not installed - display only if needed
224 zypp::ResStatus candidateStatus = selectable->candidatePoolItem().status();
226 if ( candidateStatus.isNeeded() ||
227 candidateStatus.isSatisfied() )
233 y2milestone( "Patch not needed: %s - %s",
234 zyppPatch->name().c_str(),
235 zyppPatch->summary().c_str() );
245 // Intentionally omitting "default" so the compiler
246 // can catch unhandled enum values
251 #if VERBOSE_PATCH_LIST
252 y2debug( "Displaying patch %s - %s", zyppPatch->name().c_str(), zyppPatch->summary().c_str() );
254 addPatchItem( *it, zyppPatch);
259 y2error( "Found non-patch selectable" );
264 if ( ! firstChild() )
265 message( _( "No patches available." ) );
267 y2debug( "patch list filled" );
273 YQPkgPatchList::message( const QString & text )
275 QY2ListViewItem * item = new QY2ListViewItem( this );
278 item->setText( 1, text );
279 item->setBackgroundColor( QColor( 0xE0, 0xE0, 0xF8 ) );
285 YQPkgPatchList::filterIfVisible()
293 YQPkgPatchList::filter()
296 std::set<ZyppSel> patchSelectables;
300 ZyppPatch patch = selection()->zyppPatch();
304 ZyppPatchContents patchContents( patch );
306 for ( ZyppPatchContentsIterator it = patchContents.begin();
307 it != patchContents.end();
310 ZyppPkg pkg = tryCastToZyppPkg( *it );
314 y2debug( "Found patch pkg: %s arch: %s", (*it)->name().c_str(), (*it)->arch().asString().c_str() );
316 ZyppSel sel = _selMapper.findZyppSel( pkg );
320 if ( contains( patchSelectables, sel ) )
322 y2milestone( "Suppressing duplicate selectable %s-%s arch: %s",
323 (*it)->name().c_str(),
324 (*it)->edition().asString().c_str(),
325 (*it)->arch().asString().c_str() );
329 patchSelectables.insert( sel );
330 emit filterMatch( sel, pkg );
334 y2error( "No selectable for pkg %s", (*it)->name().c_str() );
336 else // No ZyppPkg - some other kind of object (script, message)
338 if ( zypp::isKind<zypp::Script> ( *it ) )
340 y2debug( "Found patch script %s", (*it)->name().c_str() );
341 emit filterMatch( _( "Script" ), fromUTF8( (*it)->name() ), -1 );
343 else if ( zypp::isKind<zypp::Message> ( *it ) )
345 y2debug( "Found patch message %s (ignoring)", (*it)->name().c_str() );
349 y2error( "Found unknown object of kind %s in patch: %s-%s arch: %s",
350 (*it)->kind().asString().c_str(),
351 (*it)->name().c_str(),
352 (*it)->edition().asString().c_str(),
353 (*it)->arch().asString().c_str() );
360 emit filterFinished();
365 YQPkgPatchList::addPatchItem( ZyppSel selectable,
366 ZyppPatch zyppPatch )
370 y2error( "NULL ZyppSel!" );
374 YQPkgPatchListItem * item = new YQPkgPatchListItem( this, selectable, zyppPatch );
375 applyExcludeRules( item );
380 YQPkgPatchList::haveUpdateStackPatches()
382 for ( ZyppPoolIterator it = zyppPatchesBegin();
383 it != zyppPatchesEnd();
386 ZyppSel selectable = *it;
387 ZyppPatch zyppPatch = tryCastToZyppPatch( selectable->theObj() );
389 if ( zyppPatch && zyppPatch->affects_pkg_manager() )
391 #if DEBUG_SHOW_ALL_UPDATE_STACK_PATCHES
394 if ( selectable->hasCandidateObj() &&
395 selectable->candidatePoolItem().status().isNeeded() )
408 YQPkgPatchList::selection() const
410 QListViewItem * item = selectedItem();
415 return dynamic_cast<YQPkgPatchListItem *> (item);
420 YQPkgPatchList::createNotInstalledContextMenu()
422 _notInstalledContextMenu = new QPopupMenu( this );
423 CHECK_PTR( _notInstalledContextMenu );
425 actionSetCurrentInstall->addTo( _notInstalledContextMenu );
426 actionSetCurrentDontInstall->addTo( _notInstalledContextMenu );
427 actionSetCurrentTaboo->addTo( _notInstalledContextMenu );
429 addAllInListSubMenu( _notInstalledContextMenu );
434 YQPkgPatchList::createInstalledContextMenu()
436 _installedContextMenu = new QPopupMenu( this );
437 CHECK_PTR( _installedContextMenu );
439 actionSetCurrentKeepInstalled->addTo( _installedContextMenu );
441 #if ENABLE_DELETING_PATCHES
442 actionSetCurrentDelete->addTo( _installedContextMenu );
445 actionSetCurrentUpdate->addTo( _installedContextMenu );
446 actionSetCurrentProtected->addTo( _installedContextMenu );
448 addAllInListSubMenu( _installedContextMenu );
453 YQPkgPatchList::addAllInListSubMenu( QPopupMenu * menu )
455 QPopupMenu * submenu = new QPopupMenu( menu );
456 CHECK_PTR( submenu );
458 actionSetListInstall->addTo( submenu );
459 actionSetListDontInstall->addTo( submenu );
460 actionSetListKeepInstalled->addTo( submenu );
462 #if ENABLE_DELETING_PATCHES
463 actionSetListDelete->addTo( submenu );
466 actionSetListUpdate->addTo( submenu );
467 actionSetListUpdateForce->addTo( submenu );
468 actionSetListTaboo->addTo( submenu );
469 actionSetListProtected->addTo( submenu );
471 menu->insertItem( _( "&All in This List" ), submenu );
478 YQPkgPatchList::keyPressEvent( QKeyEvent * event )
482 #if ! ENABLE_DELETING_PATCHES
483 if ( event->ascii() == '-' )
485 QListViewItem * selectedListViewItem = selectedItem();
487 if ( selectedListViewItem )
489 YQPkgPatchListItem * item = dynamic_cast<YQPkgPatchListItem *> (selectedListViewItem);
491 if ( item && item->selectable()->hasInstalledObj() )
493 y2warning( "Deleting patches is not supported" );
501 YQPkgObjList::keyPressEvent( event );
507 YQPkgPatchListItem::YQPkgPatchListItem( YQPkgPatchList * patchList,
509 ZyppPatch zyppPatch )
510 : YQPkgObjListItem( patchList, selectable, zyppPatch )
511 , _patchList( patchList )
512 , _zyppPatch( zyppPatch )
515 _zyppPatch = tryCastToZyppPatch( selectable->theObj() );
521 _patchCategory = patchCategory( _zyppPatch->category() );
523 if ( categoryCol() > -1 )
524 setText( categoryCol(), asString( _patchCategory ) );
526 if ( summaryCol() > -1 && _zyppPatch->summary().empty() )
527 setText( summaryCol(), _zyppPatch->name() ); // use name as fallback
529 switch ( _patchCategory )
531 case YQPkgYaSTPatch: setTextColor( QColor( 0, 0, 0xC0 ) ); break; // medium blue
532 case YQPkgSecurityPatch: setTextColor( Qt::red ); break;
533 case YQPkgRecommendedPatch: setTextColor( QColor( 0, 0, 0xC0 ) ); break; // medium blue
534 case YQPkgOptionalPatch: break;
535 case YQPkgDocumentPatch: break;
536 case YQPkgUnknownPatchCategory: break;
541 YQPkgPatchListItem::~YQPkgPatchListItem()
548 YQPkgPatchListItem::patchCategory( QString category )
550 category = category.lower();
552 if ( category == "yast" ) return YQPkgYaSTPatch;
553 if ( category == "security" ) return YQPkgSecurityPatch;
554 if ( category == "recommended" ) return YQPkgRecommendedPatch;
555 if ( category == "optional" ) return YQPkgOptionalPatch;
556 if ( category == "document" ) return YQPkgDocumentPatch;
558 y2warning( "Unknown patch category \"%s\"", (const char *) category );
559 return YQPkgUnknownPatchCategory;
564 YQPkgPatchListItem::asString( YQPkgPatchCategory category )
568 // Translators: These are patch categories
569 case YQPkgYaSTPatch: return _( "YaST" );
570 case YQPkgSecurityPatch: return _( "security" );
571 case YQPkgRecommendedPatch: return _( "recommended" );
572 case YQPkgOptionalPatch: return _( "optional" );
573 case YQPkgDocumentPatch: return _( "document" );
574 case YQPkgUnknownPatchCategory: return "";
582 YQPkgPatchListItem::cycleStatus()
584 YQPkgObjListItem::cycleStatus();
586 #if ! ENABLE_DELETING_PATCHES
587 if ( status() == S_Del ) // Can't delete patches
588 setStatus( S_KeepInstalled );
594 YQPkgPatchListItem::toolTip( int col )
598 if ( col == statusCol() )
600 text = YQPkgObjListItem::toolTip( col );
604 if ( ( col == brokenIconCol() && isBroken() ) ||
605 ( col == satisfiedIconCol() && isSatisfied() ) )
607 text = YQPkgObjListItem::toolTip( col );
611 text = fromUTF8( zyppPatch()->category() );
613 if ( ! text.isEmpty() )
616 text += fromUTF8( zyppPatch()->size().asString().c_str() );
625 YQPkgPatchListItem::applyChanges()
627 solveResolvableCollections();
632 * Comparison function used for sorting the list.
639 YQPkgPatchListItem::compare( QListViewItem * otherListViewItem,
641 bool ascending ) const
643 YQPkgPatchListItem * other = dynamic_cast<YQPkgPatchListItem *> (otherListViewItem);
647 if ( col == categoryCol() )
649 if ( this->patchCategory() < other->patchCategory() ) return -1;
650 if ( this->patchCategory() > other->patchCategory() ) return 1;
654 return YQPkgObjListItem::compare( otherListViewItem, col, ascending );
659 #include "YQPkgPatchList.moc"