1 /*---------------------------------------------------------------------\
3 | __ __ ____ _____ ____ |
4 | \ \ / /_ _/ ___|_ _|___ \ |
5 | \ V / _` \___ \ | | __) | |
6 | | | (_| |___) || | / __/ |
7 | |_|\__,_|____/ |_| |_____| |
11 \----------------------------------------------------------------------/
13 File: YQPackageSelector.cc
14 See also: YQPackageSelectorHelp.cc
16 Author: Stefan Hundhammer <sh@suse.de>
18 Textdomain "packages-qt"
22 #define CHECK_DEPENDENCIES_ON_STARTUP 1
23 #define DEPENDENCY_FEEDBACK_IF_OK 1
24 #define AUTO_CHECK_DEPENDENCIES_DEFAULT true
25 #define ALWAYS_SHOW_PATCHES_VIEW_IF_PATCHES_AVAILABLE 0
26 #define GLOBAL_UPDATE_CONFIRMATION_THRESHOLD 20
29 #include <boost/bind.hpp>
33 #include <QApplication>
36 #include <QFileDialog>
40 #include <QMessageBox>
41 #include <QPushButton>
47 #define y2log_component "qt-pkg"
48 #include <ycp/y2log.h>
50 #include "QY2LayoutUtils.h"
52 #include "YQPackageSelector.h"
53 #include "YQPkgChangeLogView.h"
54 #include "YQPkgChangesDialog.h"
55 #include "YQPkgConflictDialog.h"
56 #include "YQPkgConflictList.h"
57 #include "YQPkgDependenciesView.h"
58 #include "YQPkgDescriptionView.h"
59 #include "YQPkgDiskUsageList.h"
60 #include "YQPkgDiskUsageWarningDialog.h"
61 #include "YQPkgFileListView.h"
62 #include "YQPkgRepoFilterView.h"
63 #include "YQPkgRepoList.h"
64 #include "YQPkgLangList.h"
65 #include "YQPkgList.h"
66 #include "YQPkgPatchFilterView.h"
67 #include "YQPkgPatchList.h"
68 #include "YQPkgPatternList.h"
69 #include "YQPkgProductDialog.h"
70 #include "YQPkgRpmGroupTagsFilterView.h"
71 #include "YQPkgSearchFilterView.h"
72 #include "YQPkgSelList.h"
73 #include "YQPkgStatusFilterView.h"
74 #include "YQPkgTechnicalDetailsView.h"
75 #include "YQPkgTextDialog.h"
76 #include "YQPkgUpdateProblemFilterView.h"
77 #include "YQPkgVersionsView.h"
78 #include "zypp/SysContent.h"
80 #include "QY2ComboTabWidget.h"
95 #define DEFAULT_EXPORT_FILE_NAME "user-packages.xml"
100 YQPackageSelector::YQPackageSelector( YWidget * parent,
102 : YQPackageSelectorBase( parent, modeFlags )
104 _showChangesDialog = true;
105 _autoDependenciesCheckBox = 0;
112 _pkgChangeLogView = 0;
113 _pkgDependenciesView = 0;
114 _pkgDescriptionView = 0;
115 _pkgFileListView = 0;
117 _pkgTechnicalDetailsView = 0;
118 _pkgVersionsView = 0;
119 _rpmGroupTagsFilterView = 0;
120 _searchFilterView = 0;
122 _statusFilterView = 0;
123 _updateProblemFilterView = 0;
124 _patchFilterView = 0;
126 _excludeDevelPkgs = 0;
127 _excludeDebugInfoPkgs = 0;
130 if ( onlineUpdateMode() ) y2milestone( "Online update mode" );
131 if ( updateMode() ) y2milestone( "Update mode" );
135 addMenus(); // Only after all widgets are created!
142 if ( _patchFilterView && onlineUpdateMode() )
144 if ( _filters && _patchFilterView && _patchList )
146 _filters->showPage( _patchFilterView );
147 _patchList->filter();
150 else if ( _repoFilterView && repoMode() )
152 if ( YQPkgRepoList::countEnabledRepositories() > 1 )
154 _filters->showPage( _repoFilterView );
155 _repoFilterView->filter();
157 else if ( _searchFilterView )
159 y2milestone( "No multiple repositories - falling back to search mode" );
160 _filters->showPage( _searchFilterView );
161 _searchFilterView->filter();
162 QTimer::singleShot( 0, _searchFilterView, SLOT( setFocus() ) );
165 else if ( _updateProblemFilterView )
167 _filters->showPage( _updateProblemFilterView );
168 _updateProblemFilterView->filter();
171 else if ( searchMode() && _searchFilterView )
173 _filters->showPage( _searchFilterView );
174 _searchFilterView->filter();
175 QTimer::singleShot( 0, _searchFilterView, SLOT( setFocus() ) );
177 else if ( summaryMode() && _statusFilterView )
179 _filters->showPage( _statusFilterView );
180 _statusFilterView->filter();
182 else if ( _patternList )
184 _filters->showPage( _patternList );
185 _patternList->filter();
189 _filters->showPage( _selList );
194 if ( _diskUsageList )
195 _diskUsageList->updateDiskUsage();
197 y2milestone( "PackageSelector init done" );
200 #if CHECK_DEPENDENCIES_ON_STARTUP
202 if ( ! testMode() && ! onlineUpdateMode() )
204 // Fire up the first dependency check in the main loop.
205 // Don't do this right away - wait until all initializations are finished.
206 QTimer::singleShot( 0, this, SLOT( resolveDependencies() ) );
214 YQPackageSelector::basicLayout()
216 layoutMenuBar( this );
218 QSplitter * outer_splitter = new QSplitter( Qt::Horizontal, this );
219 Q_CHECK_PTR( outer_splitter );
221 QWidget * left_pane = layoutLeftPane ( outer_splitter );
222 QWidget * right_pane = layoutRightPane( outer_splitter );
224 outer_splitter->setResizeMode( left_pane, QSplitter::KeepSize );
225 outer_splitter->setResizeMode( right_pane, QSplitter::Stretch );
230 YQPackageSelector::layoutLeftPane( QWidget * parent )
232 QSplitter * splitter = new QSplitter( Qt::Vertical, parent );
233 Q_CHECK_PTR( splitter );
234 splitter->setMargin( MARGIN );
236 Q3VBox * upper_vbox = new Q3VBox( splitter );
237 Q_CHECK_PTR( upper_vbox );
238 layoutFilters( upper_vbox );
239 addVSpacing( upper_vbox, MARGIN );
241 Q3VBox * lower_vbox = new Q3VBox( splitter );
242 addVSpacing( lower_vbox, MARGIN );
243 _diskUsageList = new YQPkgDiskUsageList( lower_vbox );
244 Q_CHECK_PTR( _diskUsageList );
246 splitter->setResizeMode( upper_vbox, QSplitter::Stretch );
247 splitter->setResizeMode( lower_vbox, QSplitter::KeepSize );
254 YQPackageSelector::layoutFilters( QWidget * parent )
256 _filters = new QY2ComboTabWidget( _( "Fi<er:" ), parent );
257 Q_CHECK_PTR( _filters );
261 // Update problem view
266 if ( YQPkgUpdateProblemFilterView::haveProblematicPackages()
269 _updateProblemFilterView = new YQPkgUpdateProblemFilterView( parent );
270 Q_CHECK_PTR( _updateProblemFilterView );
271 _filters->addPage( _( "Update Problems" ), _updateProblemFilterView );
280 if ( onlineUpdateMode()
281 #if ALWAYS_SHOW_PATCHES_VIEW_IF_PATCHES_AVAILABLE
282 || ! zyppPool().empty<zypp::Patch>()
285 addPatchFilterView();
292 if ( ! zyppPool().empty<zypp::Pattern>() || testMode() )
294 _patternList = new YQPkgPatternList( parent, true );
295 Q_CHECK_PTR( _patternList );
296 _filters->addPage( _( "Patterns" ), _patternList );
298 connect( _patternList, SIGNAL( statusChanged() ),
299 this, SLOT ( autoResolveDependencies() ) );
301 connect( this, SIGNAL( refresh() ),
302 _patternList, SLOT ( updateItemStates() ) );
304 if ( _pkgConflictDialog )
306 connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
307 _patternList, SLOT ( updateItemStates() ) );
316 if ( ! zyppPool().empty<zypp::Selection>() || testMode() )
319 _selList = new YQPkgSelList( parent, true );
320 Q_CHECK_PTR( _selList );
321 _filters->addPage( _( "Selections" ), _selList );
323 connect( _selList, SIGNAL( statusChanged() ),
324 this, SLOT ( autoResolveDependencies() ) );
326 connect( this, SIGNAL( refresh() ),
327 _selList, SLOT ( updateItemStates() ) );
329 if ( _pkgConflictDialog )
331 connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
332 _selList, SLOT ( updateItemStates() ) );
338 // RPM group tags view
341 _rpmGroupTagsFilterView = new YQPkgRpmGroupTagsFilterView( parent );
342 Q_CHECK_PTR( _rpmGroupTagsFilterView );
343 _filters->addPage( _( "Package Groups" ), _rpmGroupTagsFilterView );
345 connect( this, SIGNAL( loadData() ),
346 _rpmGroupTagsFilterView, SLOT ( filter() ) );
353 _langList = new YQPkgLangList( parent );
354 Q_CHECK_PTR( _langList );
356 _filters->addPage( _( "Languages" ), _langList );
357 _langList->setSizePolicy( QSizePolicy( QSizePolicy::Ignored, QSizePolicy::Ignored ) ); // hor/vert
359 connect( _langList, SIGNAL( statusChanged() ),
360 this, SLOT ( autoResolveDependencies() ) );
362 connect( this, SIGNAL( refresh() ),
363 _langList, SLOT ( updateItemStates() ) );
370 _repoFilterView = new YQPkgRepoFilterView( parent );
371 Q_CHECK_PTR( _repoFilterView );
372 _filters->addPage( _( "Repositories" ), _repoFilterView );
376 // Package search view
379 _searchFilterView = new YQPkgSearchFilterView( parent );
380 Q_CHECK_PTR( _searchFilterView );
381 _filters->addPage( _( "Search" ), _searchFilterView );
385 // Status change view
388 _statusFilterView = new YQPkgStatusFilterView( parent );
389 Q_CHECK_PTR( _statusFilterView );
390 _filters->addPage( _( "Installation Summary" ), _statusFilterView );
396 _filters->addPage( _( "Keywords" ), new QLabel( "Keywords\nfilter\n\nfor future use", 0 ) );
397 _filters->addPage( _( "MIME Types" ), new QLabel( "MIME Types\nfilter\n\nfor future use" , 0 ) );
404 YQPackageSelector::layoutRightPane( QWidget * parent )
406 Q3VBox * right_pane_vbox = new Q3VBox( parent );
407 Q_CHECK_PTR( right_pane_vbox );
408 right_pane_vbox->setMargin( MARGIN );
410 QSplitter * splitter = new QSplitter( Qt::Vertical, right_pane_vbox );
411 Q_CHECK_PTR( splitter );
413 Q3VBox * splitter_vbox = new Q3VBox( splitter );
414 Q_CHECK_PTR( splitter_vbox );
415 layoutPkgList( splitter_vbox );
416 addVSpacing( splitter_vbox, MARGIN );
418 layoutDetailsViews( splitter );
420 layoutButtons( right_pane_vbox );
422 return right_pane_vbox;
427 YQPackageSelector::layoutPkgList( QWidget * parent )
429 _pkgList= new YQPkgList( parent );
430 Q_CHECK_PTR( _pkgList );
432 connect( _pkgList, SIGNAL( statusChanged() ),
433 this, SLOT ( autoResolveDependencies() ) );
438 YQPackageSelector::layoutDetailsViews( QWidget * parent )
440 bool haveInstalledPkgs = YQPkgList::haveInstalledPkgs();
442 Q3VBox * details_vbox = new Q3VBox( parent );
443 Q_CHECK_PTR( details_vbox );
444 details_vbox->setMinimumSize( 0, 0 );
446 addVSpacing( details_vbox, 8 );
448 _detailsViews = new QTabWidget( details_vbox );
449 Q_CHECK_PTR( _detailsViews );
450 _detailsViews->setMargin( MARGIN );
452 // _detailsViews->setTabPosition( QTabWidget::Bottom );
459 _pkgDescriptionView = new YQPkgDescriptionView( _detailsViews );
460 Q_CHECK_PTR( _pkgDescriptionView );
462 _detailsViews->addTab( _pkgDescriptionView, _( "D&escription" ) );
463 _detailsViews->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
465 connect( _pkgList, SIGNAL( selectionChanged ( ZyppSel ) ),
466 _pkgDescriptionView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
472 _pkgTechnicalDetailsView = new YQPkgTechnicalDetailsView( _detailsViews );
473 Q_CHECK_PTR( _pkgTechnicalDetailsView );
475 _detailsViews->addTab( _pkgTechnicalDetailsView, _( "&Technical Data" ) );
477 connect( _pkgList, SIGNAL( selectionChanged ( ZyppSel ) ),
478 _pkgTechnicalDetailsView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
485 _pkgDependenciesView = new YQPkgDependenciesView( _detailsViews );
486 Q_CHECK_PTR( _pkgDependenciesView );
488 _detailsViews->addTab( _pkgDependenciesView, _( "Dependencies" ) );
489 _detailsViews->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
491 connect( _pkgList, SIGNAL( selectionChanged ( ZyppSel ) ),
492 _pkgDependenciesView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
500 _pkgVersionsView = new YQPkgVersionsView( _detailsViews,
501 true ); // userCanSwitchVersions
502 Q_CHECK_PTR( _pkgVersionsView );
504 _detailsViews->addTab( _pkgVersionsView, _( "&Versions" ) );
506 connect( _pkgList, SIGNAL( selectionChanged ( ZyppSel ) ),
507 _pkgVersionsView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
514 if ( haveInstalledPkgs ) // file list information is only available for installed pkgs
516 _pkgFileListView = new YQPkgFileListView( _detailsViews );
517 Q_CHECK_PTR( _pkgFileListView );
519 _detailsViews->addTab( _pkgFileListView, _( "File List" ) );
520 _detailsViews->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
522 connect( _pkgList, SIGNAL( selectionChanged ( ZyppSel ) ),
523 _pkgFileListView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
531 if ( haveInstalledPkgs ) // change log information is only available for installed pkgs
533 _pkgChangeLogView = new YQPkgChangeLogView( _detailsViews );
534 Q_CHECK_PTR( _pkgChangeLogView );
536 _detailsViews->addTab( _pkgChangeLogView, _( "Change Log" ) );
537 _detailsViews->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
539 connect( _pkgList, SIGNAL( selectionChanged ( ZyppSel ) ),
540 _pkgChangeLogView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
546 YQPackageSelector::layoutButtons( QWidget * parent )
548 Q3HBox * button_box = new Q3HBox( parent );
549 Q_CHECK_PTR( button_box );
550 button_box->setSpacing( SPACING );
552 // Button: Dependency check
553 // Translators: Please keep this short!
554 _checkDependenciesButton = new QPushButton( _( "Chec&k" ), button_box );
555 Q_CHECK_PTR( _checkDependenciesButton );
556 _checkDependenciesButton->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); // hor/vert
557 _normalButtonBackground = _checkDependenciesButton->paletteBackgroundColor();
559 connect( _checkDependenciesButton, SIGNAL( clicked() ),
560 this, SLOT ( manualResolvePackageDependencies() ) );
563 // Checkbox: Automatically check dependencies for every package status change?
564 // Translators: Please keep this short!
565 _autoDependenciesCheckBox = new QCheckBox( _( "A&utocheck" ), button_box );
566 Q_CHECK_PTR( _autoDependenciesCheckBox );
567 _autoDependenciesCheckBox->setChecked( AUTO_CHECK_DEPENDENCIES_DEFAULT );
569 addHStretch( button_box );
571 QPushButton * cancel_button = new QPushButton( _( "&Cancel" ), button_box );
572 Q_CHECK_PTR( cancel_button );
573 cancel_button->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); // hor/vert
575 connect( cancel_button, SIGNAL( clicked() ),
576 this, SLOT ( reject() ) );
579 QPushButton * accept_button = new QPushButton( _( "&Accept" ), button_box );
580 Q_CHECK_PTR( accept_button );
581 accept_button->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); // hor/vert
583 connect( accept_button, SIGNAL( clicked() ),
584 this, SLOT ( accept() ) );
586 button_box->setFixedHeight( button_box->sizeHint().height() );
591 YQPackageSelector::layoutMenuBar( QWidget * parent )
593 _menuBar = new QMenuBar( parent );
594 Q_CHECK_PTR( _menuBar );
607 YQPackageSelector::addMenus()
613 _fileMenu = new QMenu( _menuBar );
614 Q_CHECK_PTR( _fileMenu );
615 _menuBar->insertItem( _( "&File" ), _fileMenu );
617 _fileMenu->insertItem( _( "&Import..." ), this, SLOT( pkgImport() ) );
618 _fileMenu->insertItem( _( "&Export..." ), this, SLOT( pkgExport() ) );
620 _fileMenu->insertSeparator();
622 _fileMenu->insertItem( _( "E&xit -- Discard Changes" ), this, SLOT( reject() ) );
623 _fileMenu->insertItem( _( "&Quit -- Save Changes" ), this, SLOT( accept() ) );
632 _viewMenu = new QMenu( _menuBar );
633 Q_CHECK_PTR( _viewMenu );
634 _menuBar->insertItem( _( "&View" ), _viewMenu );
636 // Translators: This is about packages ending in "-devel", so don't translate that "-devel"!
637 _viewShowDevelID = _viewMenu->insertItem( _( "Show -de&vel Packages" ),
638 this, SLOT( pkgExcludeRulesChanged( int ) ), Qt::Key_F7 );
639 _viewMenu->setItemChecked( _viewShowDevelID, true );
640 _excludeDevelPkgs = new YQPkgObjList::ExcludeRule( _pkgList, QRegExp( ".*-devel(-\\d+bit)?$" ), _pkgList->nameCol() );
641 Q_CHECK_PTR( _excludeDevelPkgs );
642 _excludeDevelPkgs->enable( false );
644 // Translators: This is about packages ending in "-debuginfo", so don't translate that "-debuginfo"!
645 _viewShowDebugInfoID = _viewMenu->insertItem( _( "Show -&debuginfo Packages" ),
646 this, SLOT( pkgExcludeRulesChanged( int ) ), Qt::Key_F8 );
647 _viewMenu->setItemChecked( _viewShowDebugInfoID, true );
648 _excludeDebugInfoPkgs = new YQPkgObjList::ExcludeRule( _pkgList, QRegExp( ".*-debuginfo$" ), _pkgList->nameCol() );
649 Q_CHECK_PTR( _excludeDebugInfoPkgs );
650 _excludeDebugInfoPkgs->enable( false );
657 _pkgMenu = new QMenu( _menuBar );
658 Q_CHECK_PTR( _pkgMenu );
659 _menuBar->insertItem( _( "&Package" ), _pkgMenu );
661 _pkgList->actionSetCurrentInstall->addTo( _pkgMenu );
662 _pkgList->actionSetCurrentDontInstall->addTo( _pkgMenu );
663 _pkgList->actionSetCurrentKeepInstalled->addTo( _pkgMenu );
664 _pkgList->actionSetCurrentDelete->addTo( _pkgMenu );
665 _pkgList->actionSetCurrentUpdate->addTo( _pkgMenu );
666 _pkgList->actionSetCurrentTaboo->addTo( _pkgMenu );
667 _pkgList->actionSetCurrentProtected->addTo( _pkgMenu );
669 _pkgMenu->insertSeparator();
671 _pkgList->actionInstallSourceRpm->addTo( _pkgMenu );
672 _pkgList->actionDontInstallSourceRpm->addTo( _pkgMenu );
674 _pkgMenu->insertSeparator();
675 QMenu * submenu = _pkgList->addAllInListSubMenu( _pkgMenu );
676 Q_CHECK_PTR( submenu );
678 submenu->insertSeparator();
679 _pkgList->actionInstallListSourceRpms->addTo( submenu );
680 _pkgList->actionDontInstallListSourceRpms->addTo( submenu );
684 // Submenu for all packages
687 submenu = new QMenu( _pkgMenu );
688 Q_CHECK_PTR( submenu );
690 // Translators: Unlike the "all in this list" submenu, this submenu
691 // refers to all packages globally, not only to those that are
692 // currently visible in the packages list.
693 _pkgMenu->insertItem( _( "All Packages" ), submenu );
695 submenu->insertItem( _( "Update if newer version available" ),
696 this, SLOT( globalUpdatePkg() ) );
698 submenu->insertItem( _( "Update unconditionally" ),
699 this, SLOT( globalUpdatePkgForce() ) );
709 _patchMenu = new QMenu( _menuBar );
710 Q_CHECK_PTR( _patchMenu );
711 _menuBar->insertItem( _( "&Patch" ), _patchMenu );
713 _patchList->actionSetCurrentInstall->addTo( _patchMenu );
714 _patchList->actionSetCurrentDontInstall->addTo( _patchMenu );
715 _patchList->actionSetCurrentKeepInstalled->addTo( _patchMenu );
716 #if ENABLE_DELETING_PATCHES
717 _patchList->actionSetCurrentDelete->addTo( _patchMenu );
719 _patchList->actionSetCurrentUpdate->addTo( _patchMenu );
720 _patchList->actionSetCurrentTaboo->addTo( _patchMenu );
722 _patchMenu->insertSeparator();
723 _patchList->addAllInListSubMenu( _patchMenu );
731 _extrasMenu = new QMenu( _menuBar );
732 Q_CHECK_PTR( _extrasMenu );
733 _menuBar->insertItem( _( "&Extras" ), _extrasMenu );
735 _extrasMenu->insertItem( _( "Show &Products" ), this, SLOT( showProducts() ) );
736 _extrasMenu->insertItem( _( "Show &Automatic Package Changes" ), this, SLOT( showAutoPkgList() ), Qt::CTRL + Qt::Key_A );
737 _extrasMenu->insertItem( _( "&Verify System" ), this, SLOT( verifySystem() ) );
739 _extrasMenu->insertSeparator();
741 // Translators: This is about packages ending in "-devel", so don't translate that "-devel"!
742 _extrasMenu->insertItem( _( "Install All Matching -&devel Packages" ), this, SLOT( installDevelPkgs() ) );
744 // Translators: This is about packages ending in "-debuginfo", so don't translate that "-debuginfo"!
745 _extrasMenu->insertItem( _( "Install All Matching -de&buginfo Packages" ), this, SLOT( installDebugInfoPkgs() ) );
747 _extrasMenu->insertSeparator();
749 if ( _pkgConflictDialog )
750 _extrasMenu->insertItem( _( "Generate Dependency Resolver &Test Case" ),
751 _pkgConflictDialog, SLOT( askCreateSolverTestCase() ) );
753 if ( _actionResetIgnoredDependencyProblems )
754 _actionResetIgnoredDependencyProblems->addTo( _extrasMenu );
759 _patchList->actionShowRawPatchInfo->addTo( _extrasMenu );
767 _helpMenu = new QMenu( _menuBar );
768 Q_CHECK_PTR( _helpMenu );
769 _menuBar->insertSeparator();
770 _menuBar->insertItem( _( "&Help" ), _helpMenu );
772 // Note: The help functions and their texts are moved out
773 // to a separate source file YQPackageSelectorHelp.cc
775 // Menu entry for help overview
776 _helpMenu->insertItem( _( "&Overview" ), this, SLOT( help() ), Qt::Key_F1 );
778 // Menu entry for help about used symbols ( icons )
779 _helpMenu->insertItem( _( "&Symbols" ), this, SLOT( symbolHelp() ), Qt::SHIFT + Qt::Key_F1 );
781 // Menu entry for keyboard help
782 _helpMenu->insertItem( _( "&Keys" ), this, SLOT( keyboardHelp() ) );
787 YQPackageSelector::connectFilter( QWidget * filter,
789 bool hasUpdateSignal )
791 if ( ! filter ) return;
792 if ( ! pkgList ) return;
796 connect( _filters, SIGNAL( currentChanged(QWidget *) ),
797 filter, SLOT ( filterIfVisible() ) );
800 connect( this, SIGNAL( refresh() ),
801 filter, SLOT ( filterIfVisible() ) );
803 connect( filter, SIGNAL( filterStart() ),
804 pkgList, SLOT ( clear() ) );
806 connect( filter, SIGNAL( filterMatch( ZyppSel, ZyppPkg ) ),
807 pkgList, SLOT ( addPkgItem ( ZyppSel, ZyppPkg ) ) );
809 connect( filter, SIGNAL( filterFinished() ),
810 pkgList, SLOT ( selectSomething() ) );
812 connect( filter, SIGNAL( filterFinished() ),
813 pkgList, SLOT ( logExcludeStatistics() ) );
816 if ( hasUpdateSignal )
818 connect( filter, SIGNAL( updatePackages() ),
819 pkgList, SLOT ( updateItemStates() ) );
821 if ( _diskUsageList )
823 connect( filter, SIGNAL( updatePackages() ),
824 _diskUsageList, SLOT ( updateDiskUsage() ) );
831 YQPackageSelector::makeConnections()
833 connect( this, SIGNAL( resolvingStarted() ),
834 this, SLOT ( animateCheckButton() ) );
836 connect( this, SIGNAL( resolvingFinished() ),
837 this, SLOT ( restoreCheckButton() ) );
839 connectFilter( _updateProblemFilterView, _pkgList, false );
840 connectFilter( _patternList, _pkgList );
841 connectFilter( _selList, _pkgList );
842 connectFilter( _repoFilterView, _pkgList, false );
843 connectFilter( _rpmGroupTagsFilterView, _pkgList, false );
844 connectFilter( _langList, _pkgList );
845 connectFilter( _statusFilterView, _pkgList, false );
846 connectFilter( _searchFilterView, _pkgList, false );
848 if ( _searchFilterView && _pkgList )
850 connect( _searchFilterView, SIGNAL( message( const QString & ) ),
851 _pkgList, SLOT ( message( const QString & ) ) );
854 if ( _repoFilterView && _pkgList )
856 connect( _repoFilterView, SIGNAL( filterNearMatch ( ZyppSel, ZyppPkg ) ),
857 _pkgList, SLOT ( addPkgItemDimmed ( ZyppSel, ZyppPkg ) ) );
860 if ( _pkgList && _diskUsageList )
863 connect( _pkgList, SIGNAL( statusChanged() ),
864 _diskUsageList, SLOT ( updateDiskUsage() ) );
872 // Connect package conflict dialog
875 if ( _pkgConflictDialog )
879 connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
880 _pkgList, SLOT ( updateItemStates() ) );
885 connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
886 _patternList, SLOT ( updateItemStates() ) );
891 connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
892 _selList, SLOT ( updateItemStates() ) );
895 if ( _diskUsageList )
897 connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
898 _diskUsageList, SLOT ( updateDiskUsage() ) );
904 // Connect package versions view
907 if ( _pkgVersionsView && _pkgList )
909 connect( _pkgVersionsView, SIGNAL( candidateChanged( ZyppObj ) ),
910 _pkgList, SLOT ( updateItemData() ) );
915 // Hotkey to enable "patches" filter view on the fly
918 QShortcut * accel = new QShortcut( Qt::Key_F2, this, SLOT( hotkeyInsertPatchFilterView() ) );
919 Q_CHECK_PTR( accel );
922 // Update actions just before opening menus
925 if ( _pkgMenu && _pkgList )
927 connect( _pkgMenu, SIGNAL( aboutToShow() ),
928 _pkgList, SLOT ( updateActions() ) );
931 if ( _patchMenu && _patchList )
933 connect( _patchMenu, SIGNAL( aboutToShow() ),
934 _patchList, SLOT ( updateActions() ) );
940 YQPackageSelector::animateCheckButton()
942 if ( _checkDependenciesButton )
944 _checkDependenciesButton->setPaletteBackgroundColor( QColor( 0xE0, 0xE0, 0xF8 ) );
945 _checkDependenciesButton->repaint();
951 YQPackageSelector::restoreCheckButton()
953 if ( _checkDependenciesButton )
954 _checkDependenciesButton->setPaletteBackgroundColor( _normalButtonBackground );
959 YQPackageSelector::autoResolveDependencies()
961 if ( _autoDependenciesCheckBox && ! _autoDependenciesCheckBox->isChecked() )
964 resolveDependencies();
969 YQPackageSelector::manualResolvePackageDependencies()
971 if ( ! _pkgConflictDialog )
973 y2error( "No package conflict dialog existing" );
974 return QDialog::Accepted;
977 YQUI::ui()->busyCursor();
978 int result = _pkgConflictDialog->solveAndShowConflicts();
979 YQUI::ui()->normalCursor();
981 #if DEPENDENCY_FEEDBACK_IF_OK
983 if ( result == QDialog::Accepted )
985 QMessageBox::information( this, "",
986 _( "All package dependencies are OK." ),
996 YQPackageSelector::addPatchFilterView()
998 if ( ! _patchFilterView )
1000 _patchFilterView = new YQPkgPatchFilterView( this );
1001 Q_CHECK_PTR( _patchFilterView );
1002 _filters->addPage( _( "Patches" ), _patchFilterView );
1004 _patchList = _patchFilterView->patchList();
1005 Q_CHECK_PTR( _patchList );
1013 YQPackageSelector::hotkeyInsertPatchFilterView()
1015 if ( ! _patchFilterView )
1017 y2milestone( "Activating patches filter view" );
1019 addPatchFilterView();
1022 _filters->showPage( _patchFilterView );
1024 _patchList->filter();
1030 YQPackageSelector::connectPatchList()
1032 if ( _pkgList && _patchList )
1034 connectFilter( _patchList, _pkgList );
1036 connect( _patchList, SIGNAL( filterMatch ( const QString &, const QString &, FSize ) ),
1037 _pkgList, SLOT ( addPassiveItem( const QString &, const QString &, FSize ) ) );
1039 connect( _patchList, SIGNAL( statusChanged() ),
1040 this, SLOT ( autoResolveDependencies() ) );
1042 if ( _pkgConflictDialog )
1044 connect( _pkgConflictDialog,SIGNAL( updatePackages() ),
1045 _patchList, SLOT ( updateItemStates() ) );
1048 connect( this, SIGNAL( refresh() ),
1049 _patchList, SLOT ( updateItemStates() ) );
1056 YQPackageSelector::pkgExport()
1058 QString filename = YQUI::ui()->askForSaveFileName( QString( DEFAULT_EXPORT_FILE_NAME ), // startsWith
1059 QString( "*.xml;;*" ), // filter
1060 _( "Save Package List" ) );
1062 if ( ! filename.isEmpty() )
1064 zypp::syscontent::Writer writer;
1065 const zypp::ResPool & pool = zypp::getZYpp()->pool();
1067 // The ZYPP obfuscated C++ contest proudly presents:
1069 for_each( pool.begin(), pool.end(),
1070 boost::bind( &zypp::syscontent::Writer::addIf,
1071 boost::ref( writer ),
1073 // Yuck. What a mess.
1075 // Does anybody seriously believe this kind of thing is easier to read,
1076 // let alone use? Get real. This is an argument in favour of all C++
1077 // haters. And it's one that is really hard to counter.
1083 std::ofstream exportFile( toUTF8( filename ).c_str() );
1084 exportFile.exceptions( std::ios_base::badbit | std::ios_base::failbit );
1085 exportFile << writer;
1087 y2milestone( "Package list exported to %s", (const char *) filename );
1089 catch ( std::exception & exception )
1091 y2warning( "Error exporting package list to %s", (const char *) filename );
1093 // The export might have left over a partially written file.
1094 // Try to delete it. Don't care if it doesn't exist and unlink() fails.
1095 (void) unlink( (const char *) filename );
1098 QMessageBox::warning( this, // parent
1099 _( "Error" ), // caption
1100 _( "Error exporting package list to %1" ).arg( filename ),
1101 QMessageBox::Ok | QMessageBox::Default, // button0
1102 Qt::NoButton, // button1
1103 Qt::NoButton ); // button2
1110 YQPackageSelector::pkgImport()
1112 QString filename = QFileDialog::getOpenFileName( this, _( "Load Package List" ), DEFAULT_EXPORT_FILE_NAME, // startsWi
1113 "*.xml+;;*"// filter
1116 if ( ! filename.isEmpty() )
1118 y2milestone( "Importing package list from %s", (const char *) filename );
1122 std::ifstream importFile( toUTF8( filename ).c_str() );
1123 zypp::syscontent::Reader reader( importFile );
1126 // Put reader contents into maps
1129 typedef zypp::syscontent::Reader::Entry ZyppReaderEntry;
1130 typedef std::pair<string, ZyppReaderEntry> ImportMapPair;
1132 map<string, ZyppReaderEntry> importPkg;
1133 map<string, ZyppReaderEntry> importPatterns;
1135 for ( zypp::syscontent::Reader::const_iterator it = reader.begin();
1139 string kind = it->kind();
1141 if ( kind == "package" ) importPkg.insert ( ImportMapPair( it->name(), *it ) );
1142 else if ( kind == "pattern" ) importPatterns.insert( ImportMapPair( it->name(), *it ) );
1145 y2debug( "Found %zu packages and %zu patterns in %s",
1147 importPatterns.size(),
1148 (const char *) filename );
1152 // Set status of all patterns and packages according to import map
1155 for ( ZyppPoolIterator it = zyppPatternsBegin();
1156 it != zyppPatternsEnd();
1159 ZyppSel selectable = *it;
1160 importSelectable( *it, importPatterns.find( selectable->name() ) != importPatterns.end(), "pattern" );
1163 for ( ZyppPoolIterator it = zyppPkgBegin();
1167 ZyppSel selectable = *it;
1168 importSelectable( *it, importPkg.find( selectable->name() ) != importPkg.end(), "package" );
1178 if ( _statusFilterView )
1180 // Switch to "Installation Summary" filter view
1182 _filters->showPage( _statusFilterView );
1183 _statusFilterView->filter();
1187 catch ( const zypp::Exception & exception )
1189 y2warning( "Error reading package list from %s", (const char *) filename );
1192 QMessageBox::warning( this, // parent
1193 _( "Error" ), // caption
1194 _( "Error loading package list from %1" ).arg( filename ),
1195 QMessageBox::Ok | QMessageBox::Default, // button0
1196 QMessageBox::NoButton, // button1
1197 QMessageBox::NoButton ); // button2
1204 YQPackageSelector::importSelectable( ZyppSel selectable,
1208 ZyppStatus oldStatus = selectable->status();
1209 ZyppStatus newStatus = oldStatus;
1214 // Make sure this selectable does not get installed
1217 switch ( oldStatus )
1221 case S_KeepInstalled:
1225 newStatus = oldStatus;
1230 newStatus = S_KeepInstalled;
1231 y2debug( "Keeping %s %s", kind, selectable->name().c_str() );
1237 if ( selectable->hasCandidateObj() )
1239 newStatus = S_Install;
1240 y2debug( "Adding %s %s", kind, selectable->name().c_str() );
1244 y2debug( "Can't add %s %s: No candidate",
1245 kind, selectable->name().c_str() );
1253 // Make sure this selectable does not get installed
1256 switch ( oldStatus )
1260 case S_KeepInstalled:
1265 y2debug( "Deleting %s %s", kind, selectable->name().c_str() );
1272 newStatus = oldStatus;
1277 if ( oldStatus != newStatus )
1278 selectable->set_status( newStatus );
1283 YQPackageSelector::globalUpdatePkg( bool force )
1288 int count = _pkgList->globalSetPkgStatus( S_Update, force,
1289 true ); // countOnly
1290 y2milestone( "%d pkgs found for update", count );
1292 if ( count >= GLOBAL_UPDATE_CONFIRMATION_THRESHOLD )
1294 if ( QMessageBox::question( this, "", // caption
1295 // Translators: %1 is the number of affected packages
1296 _( "%1 packages will be updated" ).arg( count ),
1297 _( "&Continue" ), _( "C&ancel" ),
1298 0, // defaultButtonNumber (from 0)
1299 1 ) // escapeButtonNumber
1306 (void) _pkgList->globalSetPkgStatus( S_Update, force,
1307 false ); // countOnly
1309 if ( _statusFilterView )
1311 _filters->showPage( _statusFilterView );
1312 _statusFilterView->clear();
1313 _statusFilterView->showTransactions();
1314 _statusFilterView->filter();
1320 YQPackageSelector::showProducts()
1322 YQPkgProductDialog::showProductDialog();
1326 YQPackageSelector::installDevelPkgs()
1328 installSubPkgs( "-devel" );
1333 YQPackageSelector::installDebugInfoPkgs()
1335 installSubPkgs( "-debuginfo" );
1340 YQPackageSelector::pkgExcludeRulesChanged( int menuItemID )
1342 if ( _viewMenu && _pkgList )
1344 _viewMenu->setItemChecked( menuItemID, ! _viewMenu->isItemChecked( menuItemID ) );
1346 if ( _excludeDevelPkgs )
1347 _excludeDevelPkgs->enable( ! _viewMenu->isItemChecked( _viewShowDevelID ) );
1349 if ( _excludeDebugInfoPkgs )
1350 _excludeDebugInfoPkgs->enable( ! _viewMenu->isItemChecked( _viewShowDebugInfoID ) );
1352 _pkgList->applyExcludeRules();
1358 YQPackageSelector::installSubPkgs( const QString suffix )
1360 // Find all matching packages and put them into a QMap
1362 QMap<QString, ZyppSel> subPkgs;
1364 for ( ZyppPoolIterator it = zyppPkgBegin();
1368 QString name = (*it)->name().c_str();
1370 if ( name.endsWith( suffix ) )
1372 subPkgs[ name ] = *it;
1374 y2debug( "Found subpackage: %s", (const char *) name );
1379 // Now go through all packages and look if there is a corresponding subpackage in the QMap
1381 for ( ZyppPoolIterator it = zyppPkgBegin();
1385 QString name = (*it)->name().c_str();
1387 if ( subPkgs.contains( name + suffix ) )
1389 QString subPkgName( name + suffix );
1390 ZyppSel subPkg = subPkgs[ subPkgName ];
1392 switch ( (*it)->status() )
1399 // Don't install the subpackage
1400 y2milestone( "Ignoring unwanted subpackage %s", (const char *) subPkgName );
1405 case S_KeepInstalled:
1407 // Install the subpackage, but don't try to update it
1409 if ( ! subPkg->installedObj() )
1411 subPkg->set_status( S_Install );
1412 y2milestone( "Installing subpackage %s", (const char *) subPkgName );
1420 // Install or update the subpackage
1422 if ( ! subPkg->installedObj() )
1424 subPkg->set_status( S_Install );
1425 y2milestone( "Installing subpackage %s", (const char *) subPkgName );
1429 subPkg->set_status( S_Update );
1430 y2milestone( "Updating subpackage %s", (const char *) subPkgName );
1434 // Intentionally omitting 'default' branch so the compiler can
1435 // catch unhandled enum states
1441 if ( _filters && _statusFilterView )
1443 _filters->showPage( _statusFilterView );
1444 _statusFilterView->filter();
1447 YQPkgChangesDialog::showChangesDialog( _( "Added Subpackages:" ),
1448 QRegExp( ".*" + suffix + "$" ),
1450 QString::null, // rejectButtonLabel
1451 true ); // showIfEmpty
1455 #include "YQPackageSelector.moc"