1 /*---------------------------------------------------------------------\
3 | __ __ ____ _____ ____ |
4 | \ \ / /_ _/ ___|_ _|___ \ |
5 | \ V / _` \___ \ | | __) | |
6 | | | (_| |___) || | / __/ |
7 | |_|\__,_|____/ |_| |_____| |
11 \----------------------------------------------------------------------/
15 Author: Stefan Hundhammer <sh@suse.de>
17 Textdomain "packages-qt"
21 #define SOURCE_RPM_DISABLED 0
23 #define y2log_component "qt-pkg"
24 #include <ycp/y2log.h>
28 #include <QMessageBox>
33 #include "YQPkgList.h"
36 #include "YQIconPool.h"
37 #include "YQApplication.h"
40 YQPkgList::YQPkgList( QWidget * parent )
41 : YQPkgObjList( parent )
49 headers << ""; _statusCol = numCol++;
50 // _statusCol = numCol;
51 headers << _( "Package" ); _nameCol = numCol++;
53 headers << _( "Summary" ); _summaryCol = numCol++;
54 headers << _( "Size" ); _sizeCol = numCol++;
56 if ( haveInstalledPkgs() )
58 headers << _( "Avail. Ver." ); _versionCol = numCol++;
59 headers << _( "Inst. Ver." ); _instVersionCol = numCol++;
63 headers << _( "Version" ); _versionCol = numCol++;
67 #if SOURCE_RPM_DISABLED
68 #warning Selecting source RPMs disabled!
70 headers << _( "Source" ); _srpmStatusCol = numCol++;
72 setHeaderLabels(headers);
74 //FIXME sort( nameCol() );
75 //FIXME setColumnAlignment( sizeCol(), Qt::AlignRight );
76 setAllColumnsShowFocus( true );
80 createSourceRpmContextMenu();
84 YQPkgList::~YQPkgList()
90 void YQPkgList::addPkgItem( ZyppSel selectable,
93 addPkgItem( selectable, zyppPkg, false );
97 void YQPkgList::addPkgItemDimmed( ZyppSel selectable,
100 addPkgItem( selectable, zyppPkg, true );
105 YQPkgList::addPkgItem( ZyppSel selectable,
111 y2error( "NULL zypp::ui::Selectable!" );
115 YQPkgListItem * item = new YQPkgListItem( this, selectable, zyppPkg );
118 item->setDimmed( dimmed );
119 applyExcludeRules( item );
124 YQPkgList::haveInstalledPkgs()
126 for ( ZyppPoolIterator it = zyppPkgBegin();
130 if ( (*it)->installedObj() )
139 YQPkgList::pkgObjClicked( int button,
140 QTreeWidgetItem * listViewItem,
144 if ( col == srpmStatusCol() )
146 YQPkgListItem * item = dynamic_cast<YQPkgListItem *> (listViewItem);
150 if ( button == Qt::LeftButton )
152 if ( editable() && item->editable() )
153 item->toggleSourceRpmStatus();
156 else if ( button == Qt::RightButton )
158 if ( editable() && item->editable() )
160 updateActions( item );
162 if ( _sourceRpmContextMenu )
163 _sourceRpmContextMenu->popup( pos );
171 YQPkgObjList::pkgObjClicked( button, listViewItem, col, pos );
176 YQPkgList::sizeHint() const
178 return QSize( 600, 350 );
183 YQPkgList::createSourceRpmContextMenu()
185 _sourceRpmContextMenu = new QMenu( this );
187 _sourceRpmContextMenu->addAction(actionInstallSourceRpm);
188 _sourceRpmContextMenu->addAction(actionDontInstallSourceRpm);
190 QMenu * submenu = new QMenu( _sourceRpmContextMenu );
191 Q_CHECK_PTR( submenu );
192 QAction *action = _sourceRpmContextMenu->addMenu( submenu );
193 action->setText(_( "&All in This List" ));
195 submenu->addAction(actionInstallListSourceRpms);
196 submenu->addAction(actionDontInstallListSourceRpms);
201 YQPkgList::setInstallCurrentSourceRpm( bool installSourceRpm,
202 bool selectNextItem )
205 QTreeWidgetItem * listViewItem = selectedItem();
207 if ( ! listViewItem )
210 YQPkgListItem * item = dynamic_cast<YQPkgListItem *> (listViewItem);
214 item->setInstallSourceRpm( installSourceRpm );
216 if ( selectNextItem && item->nextSibling() )
218 item->setSelected( false ); // doesn't emit signals
219 setSelected( item->nextSibling(), true ); // emits signals
227 YQPkgList::setInstallListSourceRpms( bool installSourceRpm )
233 QTreeWidgetItem * listViewItem = firstChild();
235 while ( listViewItem )
237 YQPkgListItem * item = dynamic_cast<YQPkgListItem *> (listViewItem);
239 if ( item && item->editable() )
241 item->setInstallSourceRpm( installSourceRpm );
244 listViewItem = listViewItem->nextSibling();
252 YQPkgList::createNotInstalledContextMenu()
254 _notInstalledContextMenu = new QMenu( this );
255 Q_CHECK_PTR( _notInstalledContextMenu );
257 _notInstalledContextMenu->addAction(actionSetCurrentInstall);
258 _notInstalledContextMenu->addAction(actionSetCurrentDontInstall);
259 _notInstalledContextMenu->addAction(actionSetCurrentTaboo);
261 addAllInListSubMenu( _notInstalledContextMenu );
264 _notInstalledContextMenu->addSeparator();
265 _notInstalledContextMenu->addAction( _( "Export This List to &Text File..." ),
266 this, SLOT( askExportList() ) );
271 YQPkgList::createInstalledContextMenu()
273 _installedContextMenu = new QMenu( this );
274 Q_CHECK_PTR( _installedContextMenu );
276 _installedContextMenu->addAction(actionSetCurrentKeepInstalled);
277 _installedContextMenu->addAction(actionSetCurrentDelete);
278 _installedContextMenu->addAction(actionSetCurrentUpdate);
279 _installedContextMenu->addAction(actionSetCurrentProtected);
281 addAllInListSubMenu( _installedContextMenu );
283 _installedContextMenu->addSeparator();
284 _installedContextMenu->addAction( _( "Export This List to &Text File..." ),
285 this, SLOT( askExportList() ) );
290 YQPkgList::addAllInListSubMenu( QMenu * menu )
292 QMenu * submenu = new QMenu( menu );
293 Q_CHECK_PTR( submenu );
295 submenu->addAction(actionSetListInstall);
296 submenu->addAction(actionSetListDontInstall);
297 submenu->addAction(actionSetListKeepInstalled);
298 submenu->addAction(actionSetListDelete);
299 submenu->addAction(actionSetListDelete);
300 submenu->addAction(actionSetListUpdate);
301 submenu->addAction(actionSetListUpdateForce);
302 submenu->addAction(actionSetListTaboo);
303 submenu->addAction(actionSetListProtected);
305 QAction *action = menu->addMenu( submenu );
306 action->setText(_( "&All in This List" ));
313 YQPkgList::createActions()
315 actionInstallSourceRpm = createAction( _( "&Install Source" ),
316 statusIcon( S_Install, true ),
317 statusIcon( S_Install, false ) );
319 actionDontInstallSourceRpm = createAction( _( "Do &Not Install Source" ),
320 statusIcon( S_NoInst, true ),
321 statusIcon( S_NoInst, false ) );
323 actionInstallListSourceRpms = createAction( _( "&Install All Available Sources" ),
324 statusIcon( S_Install, true ),
325 statusIcon( S_Install, false ),
326 QString::null, // key
329 actionDontInstallListSourceRpms = createAction( _( "Do &Not Install Any Sources" ),
330 statusIcon( S_NoInst, true ),
331 statusIcon( S_NoInst, false ),
332 QString::null, // key
335 connect( actionInstallSourceRpm, SIGNAL( activated() ), this, SLOT( setInstallCurrentSourceRpm() ) );
336 connect( actionDontInstallSourceRpm, SIGNAL( activated() ), this, SLOT( setDontInstallCurrentSourceRpm() ) );
338 connect( actionInstallListSourceRpms, SIGNAL( activated() ), this, SLOT( setInstallListSourceRpms() ) );
339 connect( actionDontInstallListSourceRpms, SIGNAL( activated() ), this, SLOT( setDontInstallListSourceRpms() ) );
344 YQPkgList::updateActions( YQPkgObjListItem * pkgObjListItem )
346 YQPkgObjList::updateActions( pkgObjListItem );
348 YQPkgListItem * item = dynamic_cast<YQPkgListItem *> (pkgObjListItem);
352 actionInstallSourceRpm->setEnabled( item->hasSourceRpm() );
353 actionDontInstallSourceRpm->setEnabled( item->hasSourceRpm() );
357 actionInstallSourceRpm->setEnabled( false );
358 actionDontInstallSourceRpm->setEnabled( false );
364 YQPkgList::askExportList() const
366 QString filename = YQApplication::askForSaveFileName( "pkglist.txt", // startsWith
368 _( "Export Package List" ) );
369 if ( ! filename.isEmpty() )
370 exportList( filename, true );
375 YQPkgList::exportList( const QString filename, bool interactive ) const
379 QFile file(filename);
380 file.open(QIODevice::WriteOnly);
382 if ( file.error() != QFile::NoError )
384 y2error( "Can't open file %s", qPrintable(filename) );
390 QMessageBox::warning( 0, // parent
391 _( "Error" ), // caption
392 _( "Cannot open file %1" ).arg( filename ),
393 QMessageBox::Ok | QMessageBox::Default, // button0
394 QMessageBox::NoButton, // button1
395 QMessageBox::NoButton ); // button2
405 // Format the header line with QString::sprintf() because plain stdio
406 // fprintf() is not UTF-8 aware - it will count multi-byte characters
407 // wrong, so the formatting will be broken.
410 header.sprintf( "# %-18s %-30s | %10s | %-16s | %-16s\n\n",
411 (const char *) _( "Status" ).toUtf8(),
412 (const char *) _( "Package" ).toUtf8(),
413 (const char *) _( "Size" ).toUtf8(),
414 (const char *) _( "Avail. Ver." ).toUtf8(),
415 (const char *) _( "Inst. Ver." ).toUtf8()
417 file.write(header.toUtf8());
425 const QTreeWidgetItem * item = firstChild();
429 const YQPkgListItem * pkg = dynamic_cast<const YQPkgListItem *> (item);
433 QString candVersion = pkg->text( versionCol() );
434 QString instVersion = pkg->text( instVersionCol() );
436 if ( candVersion.isEmpty() ) candVersion = "---";
437 if ( instVersion.isEmpty() ) instVersion = "---";
439 QString status = "[" + statusText( pkg->status() ) + "]";
441 format.sprintf("%-20s %-30s | %10s | %-16s | %-16s\n",
442 (const char *) status.toUtf8(),
443 (const char *) pkg->text( nameCol() ),
444 (const char *) pkg->text( sizeCol() ),
445 (const char *) candVersion,
446 (const char *) instVersion
448 file.write(format.toUtf8());
451 item = item->nextSibling();
463 YQPkgList::globalSetPkgStatus( ZyppStatus newStatus, bool force, bool countOnly )
465 YQUI::ui()->busyCursor();
466 int changedCount = 0;
468 for ( ZyppPoolIterator it = zyppPkgBegin();
472 ZyppSel selectable = *it;
473 ZyppStatus oldStatus = selectable->status();
475 if ( newStatus != oldStatus )
477 bool doChange = false;
481 case S_KeepInstalled:
485 doChange = selectable->hasInstalledObj();
493 doChange = selectable->hasInstalledObj();
495 else // don't force - update only if useful (if candidate is newer)
497 const ZyppObj candidate = selectable->candidateObj();
498 const ZyppObj installed = selectable->installedObj();
500 if ( candidate && installed )
502 doChange = ( installed->edition() < candidate->edition() );
511 doChange = ! selectable->hasInstalledObj();
518 selectable->set_status( newStatus );
521 // y2milestone( "Updating %s", selectable->name().c_str() );
526 if ( changedCount > 0 && ! countOnly )
528 emit updateItemStates();
529 emit updatePackages();
530 emit statusChanged();
533 YQUI::ui()->normalCursor();
543 YQPkgListItem::YQPkgListItem( YQPkgList * pkgList,
546 : YQPkgObjListItem( pkgList, selectable, zyppPkg )
547 , _pkgList( pkgList )
548 , _zyppPkg( zyppPkg )
552 _zyppPkg = tryCastToZyppPkg( selectable->theObj() );
558 YQPkgListItem::~YQPkgListItem()
565 YQPkgListItem::updateData()
567 YQPkgObjListItem::updateData();
573 YQPkgListItem::hasSourceRpm() const
575 if ( ! selectable() )
579 return selectable()->providesSources();
587 YQPkgListItem::installSourceRpm() const
589 if ( ! selectable() )
593 if ( ! selectable()->providesSources() )
596 return selectable()->source_install();
604 YQPkgListItem::setSourceRpmIcon()
606 if ( srpmStatusCol() < 0 )
611 if ( hasSourceRpm() )
614 if ( editable() && _pkgObjList->editable() )
616 icon = installSourceRpm() ?
617 YQIconPool::pkgInstall() :
618 YQIconPool::pkgNoInst();
622 icon = installSourceRpm() ?
623 YQIconPool::disabledPkgInstall() :
624 YQIconPool::disabledPkgNoInst();
627 setData( srpmStatusCol(), Qt::DecorationRole, icon );
632 YQPkgListItem::setInstallSourceRpm( bool installSourceRpm )
634 if ( hasSourceRpm() )
638 selectable()->set_source_install( installSourceRpm );
647 YQPkgListItem::toggleSourceRpmStatus()
649 setInstallSourceRpm( ! installSourceRpm() );
654 YQPkgListItem::toolTip( int col )
657 QString name = _zyppObj->name().c_str();
659 if ( col == statusCol() )
661 text = YQPkgObjListItem::toolTip( col );
663 else if ( col == srpmStatusCol() )
665 text = name + "\n\n";
667 if ( hasSourceRpm() )
669 text += installSourceRpm() ?
670 _( "Install Sources" ) :
671 _( "Do Not Install Sources" );
675 text += _( "No Sources Available" );
680 text = name + "\n\n";
685 if ( selectable()->hasInstalledObj() )
687 installed = selectable()->installedObj()->edition().asString().c_str();
689 installed += selectable()->installedObj()->arch().asString().c_str();
690 installed = _( "Installed Version: %1" ).arg( installed );
693 if ( selectable()->hasCandidateObj() )
695 candidate = selectable()->candidateObj()->edition().asString().c_str();
697 candidate += selectable()->candidateObj()->arch().asString().c_str();
700 if ( selectable()->hasInstalledObj() )
702 text += installed + "\n";
704 if ( selectable()->hasCandidateObj() )
706 // Translators: This is the relation between two versions of one package
707 // if both versions are the same, e.g., both "1.2.3-42", "1.2.3-42"
708 QString relation = _( "same" );
710 if ( _candidateIsNewer ) relation = _( "newer" );
711 if ( _installedIsNewer ) relation = _( "older" );
713 // Translators: %1 is the version, %2 is one of "newer", "older", "same"
714 text += _( "Available Version: %1 (%2)" ).arg( candidate ).arg( relation );
718 text += _( "Not available for installation" );
721 else // not installed
732 bool YQPkgListItem::operator< ( const QTreeWidgetItem & otherListViewItem ) const
734 int col = treeWidget()->sortColumn();
735 if ( col == srpmStatusCol() )
737 const YQPkgListItem * other = dynamic_cast<const YQPkgListItem *> (&otherListViewItem);
741 int thisPoints = ( this->hasSourceRpm() ? 1 : 0 ) + ( this->installSourceRpm() ? 1 : 0 );
742 int otherPoints = ( other->hasSourceRpm() ? 1 : 0 ) + ( other->installSourceRpm() ? 1 : 0 );
744 // Intentionally inverting order: Pkgs with source RPMs are more interesting than without.
745 return ( thisPoints < otherPoints );
749 // Fallback: Use parent class method
750 return YQPkgObjListItem::operator<( otherListViewItem );
755 YQPkgListItem::paintCell( QPainter * painter,
756 const QColorGroup & colorGroup,
762 if ( isDimmed() && ! YQUI::ui()->usingVisionImpairedPalette() )
764 QColorGroup cg = colorGroup;
765 cg.setColor( QColorGroup::Text, QColor( 0xA0, 0xA0, 0xA0 ) );
767 QTreeWidgetItem::paintCell( painter, cg, column, width, alignment );
771 if ( installedIsNewer() )
773 QColorGroup cg = colorGroup;
775 if ( ! YQUI::ui()->usingVisionImpairedPalette() )
777 if ( column == instVersionCol() )
778 cg.setColor( QColorGroup::Base, QColor( 0xFF, 0x30, 0x30 ) ); // Background
780 cg.setColor( QColorGroup::Text, QColor( 0xFF, 0, 0 ) ); // Foreground
783 QTreeWidgetItem::paintCell( painter, cg, column, width, alignment );
785 else if ( candidateIsNewer() )
787 QColorGroup cg = colorGroup;
789 if ( ! YQUI::ui()->usingVisionImpairedPalette() )
791 cg.setColor( QColorGroup::Text, QColor( 0, 0, 0xC0 ) ); // Foreground
793 if ( column == versionCol() )
794 cg.setColor( QColorGroup::Base, QColor( 0xF0, 0xF0, 0xF0 ) ); // Background
797 QTreeWidgetItem::paintCell( painter, cg, column, width, alignment );
801 QTreeWidgetItem::paintCell( painter, colorGroup, column, width, alignment );
809 #include "YQPkgList.moc"