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"
24 #define CHECK_DEPENDENCIES_ON_STARTUP 1
25 #define DEPENDENCY_FEEDBACK_IF_OK 1
26 #define AUTO_CHECK_DEPENDENCIES_DEFAULT true
27 #define ALWAYS_SHOW_PATCHES_VIEW_IF_PATCHES_AVAILABLE 0
28 #define GLOBAL_UPDATE_CONFIRMATION_THRESHOLD 20
31 #include <boost/bind.hpp>
33 #include <QHBoxLayout>
34 #include <QVBoxLayout>
37 #include <QApplication>
40 #include <QFileDialog>
44 #include <QMessageBox>
45 #include <QPushButton>
51 #define y2log_component "qt-pkg"
52 #include <ycp/y2log.h>
54 #include "QY2LayoutUtils.h"
56 #include "YQPackageSelector.h"
57 #include "YQPkgChangeLogView.h"
58 #include "YQPkgChangesDialog.h"
59 #include "YQPkgConflictDialog.h"
60 #include "YQPkgConflictList.h"
61 #include "YQPkgDependenciesView.h"
62 #include "YQPkgDescriptionView.h"
63 #include "YQPkgDiskUsageList.h"
64 #include "YQPkgDiskUsageWarningDialog.h"
65 #include "YQPkgFileListView.h"
66 #include "YQPkgRepoFilterView.h"
67 #include "YQPkgRepoList.h"
68 #include "YQPkgLangList.h"
69 #include "YQPkgList.h"
70 #include "YQPkgPatchFilterView.h"
71 #include "YQPkgPatchList.h"
72 #include "YQPkgPatternList.h"
73 #include "YQPkgProductDialog.h"
74 #include "YQPkgRpmGroupTagsFilterView.h"
75 #include "YQPkgSearchFilterView.h"
76 #include "YQPkgSelList.h"
77 #include "YQPkgStatusFilterView.h"
78 #include "YQPkgTechnicalDetailsView.h"
79 #include "YQPkgTextDialog.h"
80 #include "YQPkgUpdateProblemFilterView.h"
81 #include "YQPkgVersionsView.h"
82 #include "zypp/SysContent.h"
84 #include "QY2ComboTabWidget.h"
99 #define DEFAULT_EXPORT_FILE_NAME "user-packages.xml"
100 #define FAST_SOLVER 1
104 YQPackageSelector::YQPackageSelector( YWidget * parent,
106 : YQPackageSelectorBase( parent, modeFlags )
108 _showChangesDialog = true;
109 _autoDependenciesCheckBox = 0;
116 _pkgChangeLogView = 0;
117 _pkgDependenciesView = 0;
118 _pkgDescriptionView = 0;
119 _pkgFileListView = 0;
121 _pkgTechnicalDetailsView = 0;
122 _pkgVersionsView = 0;
123 _rpmGroupTagsFilterView = 0;
124 _searchFilterView = 0;
126 _statusFilterView = 0;
127 _updateProblemFilterView = 0;
128 _patchFilterView = 0;
130 _excludeDevelPkgs = 0;
131 _excludeDebugInfoPkgs = 0;
134 if ( onlineUpdateMode() ) y2milestone( "Online update mode" );
135 if ( updateMode() ) y2milestone( "Update mode" );
139 addMenus(); // Only after all widgets are created!
146 if ( _patchFilterView && onlineUpdateMode() )
148 if ( _filters && _patchFilterView && _patchList )
150 _filters->showPage( _patchFilterView );
151 _patchList->filter();
154 else if ( _repoFilterView && repoMode() )
156 if ( YQPkgRepoList::countEnabledRepositories() > 1 )
158 _filters->showPage( _repoFilterView );
159 _repoFilterView->filter();
161 else if ( _searchFilterView )
163 y2milestone( "No multiple repositories - falling back to search mode" );
164 _filters->showPage( _searchFilterView );
165 _searchFilterView->filter();
166 QTimer::singleShot( 0, _searchFilterView, SLOT( setFocus() ) );
169 else if ( _updateProblemFilterView )
171 _filters->showPage( _updateProblemFilterView );
172 _updateProblemFilterView->filter();
175 else if ( searchMode() && _searchFilterView )
177 _filters->showPage( _searchFilterView );
178 _searchFilterView->filter();
179 QTimer::singleShot( 0, _searchFilterView, SLOT( setFocus() ) );
181 else if ( summaryMode() && _statusFilterView )
183 _filters->showPage( _statusFilterView );
184 _statusFilterView->filter();
186 else if ( _patternList )
188 _filters->showPage( _patternList );
189 _patternList->filter();
193 _filters->showPage( _selList );
198 if ( _diskUsageList )
199 _diskUsageList->updateDiskUsage();
201 y2milestone( "PackageSelector init done" );
204 #if CHECK_DEPENDENCIES_ON_STARTUP
206 if ( ! testMode() && ! onlineUpdateMode() )
208 // Fire up the first dependency check in the main loop.
209 // Don't do this right away - wait until all initializations are finished.
210 QTimer::singleShot( 0, this, SLOT( resolveDependencies() ) );
218 YQPackageSelector::basicLayout()
220 QVBoxLayout *layout = new QVBoxLayout(this);
224 QSplitter * outer_splitter = new QSplitter( Qt::Horizontal, this );
225 Q_CHECK_PTR( outer_splitter );
227 layout->addWidget(outer_splitter);
229 QWidget * left_pane = layoutLeftPane ( outer_splitter );
231 QWidget * right_pane = layoutRightPane( outer_splitter );
233 outer_splitter->setResizeMode( left_pane, QSplitter::KeepSize );
234 outer_splitter->setResizeMode( right_pane, QSplitter::Stretch );
239 YQPackageSelector::layoutLeftPane( QWidget *parent )
241 QSplitter * splitter = new QSplitter( Qt::Vertical, parent );
242 Q_CHECK_PTR( splitter );
243 splitter->setMargin( MARGIN );
245 QWidget * upper_vbox = new QWidget( splitter );
246 QVBoxLayout *layout = new QVBoxLayout(upper_vbox);
247 upper_vbox->setLayout(layout);
249 Q_CHECK_PTR( upper_vbox );
250 layoutFilters( upper_vbox );
251 addVSpacing( upper_vbox, MARGIN );
253 QWidget * lower_vbox = new QWidget( splitter );
254 layout = new QVBoxLayout(lower_vbox);
255 lower_vbox->setLayout(layout);
257 addVSpacing( lower_vbox, MARGIN );
258 _diskUsageList = new YQPkgDiskUsageList( lower_vbox );
259 Q_CHECK_PTR( _diskUsageList );
260 layout->addWidget(_diskUsageList);
262 splitter->setResizeMode( upper_vbox, QSplitter::Stretch );
263 splitter->setResizeMode( lower_vbox, QSplitter::KeepSize );
270 YQPackageSelector::layoutFilters( QWidget *parent )
272 _filters = new QY2ComboTabWidget( _( "Fi<er:" ), parent );
273 Q_CHECK_PTR( _filters );
274 parent->layout()->addWidget(_filters);
277 // Update problem view
282 if ( YQPkgUpdateProblemFilterView::haveProblematicPackages()
285 _updateProblemFilterView = new YQPkgUpdateProblemFilterView( parent);
286 Q_CHECK_PTR( _updateProblemFilterView );
287 _filters->addPage( _( "Update Problems" ), _updateProblemFilterView );
296 if ( onlineUpdateMode()
297 #if ALWAYS_SHOW_PATCHES_VIEW_IF_PATCHES_AVAILABLE
298 || ! zyppPool().empty<zypp::Patch>()
301 addPatchFilterView();
308 if ( ! zyppPool().empty<zypp::Pattern>() || testMode() )
310 _patternList = new YQPkgPatternList( parent, true );
311 Q_CHECK_PTR( _patternList );
312 _filters->addPage( _( "Patterns" ), _patternList );
314 connect( _patternList, SIGNAL( statusChanged() ),
315 this, SLOT ( autoResolveDependencies() ) );
317 connect( this, SIGNAL( refresh() ),
318 _patternList, SLOT ( updateItemStates() ) );
320 if ( _pkgConflictDialog )
322 connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
323 _patternList, SLOT ( updateItemStates() ) );
332 if ( ! zyppPool().empty<zypp::Selection>() || testMode() )
335 _selList = new YQPkgSelList( parent, true );
336 Q_CHECK_PTR( _selList );
337 _filters->addPage( _( "Selections" ), _selList );
339 connect( _selList, SIGNAL( statusChanged() ),
340 this, SLOT ( autoResolveDependencies() ) );
342 connect( this, SIGNAL( refresh() ),
343 _selList, SLOT ( updateItemStates() ) );
345 if ( _pkgConflictDialog )
347 connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
348 _selList, SLOT ( updateItemStates() ) );
354 // RPM group tags view
357 _rpmGroupTagsFilterView = new YQPkgRpmGroupTagsFilterView( parent );
358 Q_CHECK_PTR( _rpmGroupTagsFilterView );
359 _filters->addPage( _( "Package Groups" ), _rpmGroupTagsFilterView );
361 connect( this, SIGNAL( loadData() ),
362 _rpmGroupTagsFilterView, SLOT ( filter() ) );
369 _langList = new YQPkgLangList( parent );
370 Q_CHECK_PTR( _langList );
372 _filters->addPage( _( "Languages" ), _langList );
373 _langList->setSizePolicy( QSizePolicy( QSizePolicy::Ignored, QSizePolicy::Ignored ) ); // hor/vert
375 connect( _langList, SIGNAL( statusChanged() ),
376 this, SLOT ( autoResolveDependencies() ) );
378 connect( this, SIGNAL( refresh() ),
379 _langList, SLOT ( updateItemStates() ) );
386 _repoFilterView = new YQPkgRepoFilterView( parent );
387 Q_CHECK_PTR( _repoFilterView );
388 _filters->addPage( _( "Repositories" ), _repoFilterView );
392 // Package search view
395 _searchFilterView = new YQPkgSearchFilterView( parent );
396 Q_CHECK_PTR( _searchFilterView );
397 _filters->addPage( _( "Search" ), _searchFilterView );
401 // Status change view
404 _statusFilterView = new YQPkgStatusFilterView( parent );
405 Q_CHECK_PTR( _statusFilterView );
406 _filters->addPage( _( "Installation Summary" ), _statusFilterView );
412 _filters->addPage( _( "Keywords" ), new QLabel( "Keywords\nfilter\n\nfor future use", 0 ) );
413 _filters->addPage( _( "MIME Types" ), new QLabel( "MIME Types\nfilter\n\nfor future use" , 0 ) );
420 YQPackageSelector::layoutRightPane( QWidget *parent )
422 QWidget * right_pane_vbox = new QWidget( parent );
424 QVBoxLayout *layout = new QVBoxLayout(right_pane_vbox);
425 right_pane_vbox->setLayout(layout);
427 Q_CHECK_PTR( right_pane_vbox );
429 layout->setMargin( MARGIN );
432 QSplitter * splitter = new QSplitter( Qt::Vertical, right_pane_vbox );
433 Q_CHECK_PTR( splitter );
434 layout->addWidget(splitter);
436 Q_CHECK_PTR( splitter );
437 layoutPkgList( splitter );
439 addVSpacing( splitter, MARGIN );
441 layoutDetailsViews( splitter );
443 layoutButtons( splitter );
445 return right_pane_vbox;
450 YQPackageSelector::layoutPkgList( QWidget *parent )
452 _pkgList= new YQPkgList( parent );
453 Q_CHECK_PTR( _pkgList );
455 connect( _pkgList, SIGNAL( statusChanged() ),
456 this, SLOT ( autoResolveDependencies() ) );
461 YQPackageSelector::layoutDetailsViews( QWidget *parent )
463 bool haveInstalledPkgs = YQPkgList::haveInstalledPkgs();
465 QWidget * details_vbox = new QWidget( parent );
466 Q_CHECK_PTR( details_vbox );
468 QVBoxLayout *layout = new QVBoxLayout(details_vbox);
469 details_vbox->setLayout(layout);
470 //details_vbox->setMinimumSize( 0, 0 );
472 addVSpacing( details_vbox, 8 );
474 _detailsViews = new QTabWidget( details_vbox );
475 layout->addWidget(_detailsViews);
477 Q_CHECK_PTR( _detailsViews );
478 _detailsViews->setMargin( MARGIN );
480 // _detailsViews->setTabPosition( QTabWidget::Bottom );
487 _pkgDescriptionView = new YQPkgDescriptionView( _detailsViews );
488 Q_CHECK_PTR( _pkgDescriptionView );
490 _detailsViews->addTab( _pkgDescriptionView, _( "D&escription" ) );
491 _detailsViews->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
493 connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
494 _pkgDescriptionView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
500 _pkgTechnicalDetailsView = new YQPkgTechnicalDetailsView( _detailsViews );
501 Q_CHECK_PTR( _pkgTechnicalDetailsView );
503 _detailsViews->addTab( _pkgTechnicalDetailsView, _( "&Technical Data" ) );
505 connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
506 _pkgTechnicalDetailsView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
513 _pkgDependenciesView = new YQPkgDependenciesView( _detailsViews );
514 Q_CHECK_PTR( _pkgDependenciesView );
516 _detailsViews->addTab( _pkgDependenciesView, _( "Dependencies" ) );
517 _detailsViews->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
519 connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
520 _pkgDependenciesView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
528 _pkgVersionsView = new YQPkgVersionsView( _detailsViews,
529 true ); // userCanSwitchVersions
530 Q_CHECK_PTR( _pkgVersionsView );
532 _detailsViews->addTab( _pkgVersionsView, _( "&Versions" ) );
534 connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
535 _pkgVersionsView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
542 if ( haveInstalledPkgs ) // file list information is only available for installed pkgs
544 _pkgFileListView = new YQPkgFileListView( _detailsViews );
545 Q_CHECK_PTR( _pkgFileListView );
547 _detailsViews->addTab( _pkgFileListView, _( "File List" ) );
548 _detailsViews->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
550 connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
551 _pkgFileListView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
559 if ( haveInstalledPkgs ) // change log information is only available for installed pkgs
561 _pkgChangeLogView = new YQPkgChangeLogView( _detailsViews );
562 Q_CHECK_PTR( _pkgChangeLogView );
564 _detailsViews->addTab( _pkgChangeLogView, _( "Change Log" ) );
565 _detailsViews->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
567 connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
568 _pkgChangeLogView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
574 YQPackageSelector::layoutButtons( QWidget *parent )
576 QWidget * button_box = new QWidget( parent );
577 Q_CHECK_PTR( button_box );
579 QHBoxLayout *layout = new QHBoxLayout(button_box);
580 button_box->setLayout(layout);
582 layout->setSpacing( SPACING );
584 // Button: Dependency check
585 // Translators: Please keep this short!
586 _checkDependenciesButton = new QPushButton( _( "Chec&k" ), button_box );
587 layout->addWidget(_checkDependenciesButton);
589 Q_CHECK_PTR( _checkDependenciesButton );
590 _checkDependenciesButton->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); // hor/vert
591 _normalButtonBackground = _checkDependenciesButton->paletteBackgroundColor();
593 connect( _checkDependenciesButton, SIGNAL( clicked() ),
594 this, SLOT ( manualResolvePackageDependencies() ) );
597 // Checkbox: Automatically check dependencies for every package status change?
598 // Translators: Please keep this short!
599 _autoDependenciesCheckBox = new QCheckBox( _( "A&utocheck" ), button_box );
600 Q_CHECK_PTR( _autoDependenciesCheckBox );
601 layout->addWidget(_autoDependenciesCheckBox);
603 _autoDependenciesCheckBox->setChecked( AUTO_CHECK_DEPENDENCIES_DEFAULT );
605 addHStretch( button_box );
607 QPushButton * cancel_button = new QPushButton( _( "&Cancel" ), button_box );
608 Q_CHECK_PTR( cancel_button );
609 layout->addWidget(cancel_button);
611 cancel_button->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); // hor/vert
613 connect( cancel_button, SIGNAL( clicked() ),
614 this, SLOT ( reject() ) );
617 QPushButton * accept_button = new QPushButton( _( "&Accept" ), button_box );
618 Q_CHECK_PTR( accept_button );
619 layout->addWidget(accept_button);
620 accept_button->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); // hor/vert
622 connect( accept_button, SIGNAL( clicked() ),
623 this, SLOT ( accept() ) );
625 button_box->setFixedHeight( button_box->sizeHint().height() );
630 YQPackageSelector::layoutMenuBar( QWidget *parent )
632 _menuBar = new QMenuBar( parent );
633 Q_CHECK_PTR( _menuBar );
635 parent->layout()->addWidget(_menuBar);
648 YQPackageSelector::addMenus()
654 _fileMenu = new QMenu( _menuBar );
655 Q_CHECK_PTR( _fileMenu );
656 _menuBar->insertItem( _( "&File" ), _fileMenu );
658 _fileMenu->insertItem( _( "&Import..." ), this, SLOT( pkgImport() ) );
659 _fileMenu->insertItem( _( "&Export..." ), this, SLOT( pkgExport() ) );
661 _fileMenu->insertSeparator();
663 _fileMenu->insertItem( _( "E&xit -- Discard Changes" ), this, SLOT( reject() ) );
664 _fileMenu->insertItem( _( "&Quit -- Save Changes" ), this, SLOT( accept() ) );
673 _viewMenu = new QMenu( _menuBar );
674 Q_CHECK_PTR( _viewMenu );
675 _menuBar->insertItem( _( "&View" ), _viewMenu );
677 // Translators: This is about packages ending in "-devel", so don't translate that "-devel"!
678 _viewShowDevelID = _viewMenu->insertItem( _( "Show -de&vel Packages" ),
679 this, SLOT( pkgExcludeRulesChanged( int ) ), Qt::Key_F7 );
680 _viewMenu->setItemChecked( _viewShowDevelID, true );
681 _excludeDevelPkgs = new YQPkgObjList::ExcludeRule( _pkgList, QRegExp( ".*-devel(-\\d+bit)?$" ), _pkgList->nameCol() );
682 Q_CHECK_PTR( _excludeDevelPkgs );
683 _excludeDevelPkgs->enable( false );
685 // Translators: This is about packages ending in "-debuginfo", so don't translate that "-debuginfo"!
686 _viewShowDebugInfoID = _viewMenu->insertItem( _( "Show -&debuginfo Packages" ),
687 this, SLOT( pkgExcludeRulesChanged( int ) ), Qt::Key_F8 );
688 _viewMenu->setItemChecked( _viewShowDebugInfoID, true );
689 _excludeDebugInfoPkgs = new YQPkgObjList::ExcludeRule( _pkgList, QRegExp( ".*-debuginfo$" ), _pkgList->nameCol() );
690 Q_CHECK_PTR( _excludeDebugInfoPkgs );
691 _excludeDebugInfoPkgs->enable( false );
698 _pkgMenu = new QMenu( _menuBar );
699 Q_CHECK_PTR( _pkgMenu );
700 _menuBar->insertItem( _( "&Package" ), _pkgMenu );
702 _pkgList->actionSetCurrentInstall->addTo( _pkgMenu );
703 _pkgList->actionSetCurrentDontInstall->addTo( _pkgMenu );
704 _pkgList->actionSetCurrentKeepInstalled->addTo( _pkgMenu );
705 _pkgList->actionSetCurrentDelete->addTo( _pkgMenu );
706 _pkgList->actionSetCurrentUpdate->addTo( _pkgMenu );
707 _pkgList->actionSetCurrentTaboo->addTo( _pkgMenu );
708 _pkgList->actionSetCurrentProtected->addTo( _pkgMenu );
710 _pkgMenu->insertSeparator();
712 _pkgList->actionInstallSourceRpm->addTo( _pkgMenu );
713 _pkgList->actionDontInstallSourceRpm->addTo( _pkgMenu );
715 _pkgMenu->insertSeparator();
716 QMenu * submenu = _pkgList->addAllInListSubMenu( _pkgMenu );
717 Q_CHECK_PTR( submenu );
719 submenu->insertSeparator();
720 _pkgList->actionInstallListSourceRpms->addTo( submenu );
721 _pkgList->actionDontInstallListSourceRpms->addTo( submenu );
725 // Submenu for all packages
728 submenu = new QMenu( _pkgMenu );
729 Q_CHECK_PTR( submenu );
731 // Translators: Unlike the "all in this list" submenu, this submenu
732 // refers to all packages globally, not only to those that are
733 // currently visible in the packages list.
734 _pkgMenu->insertItem( _( "All Packages" ), submenu );
736 submenu->insertItem( _( "Update if newer version available" ),
737 this, SLOT( globalUpdatePkg() ) );
739 submenu->insertItem( _( "Update unconditionally" ),
740 this, SLOT( globalUpdatePkgForce() ) );
750 _patchMenu = new QMenu( _menuBar );
751 Q_CHECK_PTR( _patchMenu );
752 _menuBar->insertItem( _( "&Patch" ), _patchMenu );
754 _patchList->actionSetCurrentInstall->addTo( _patchMenu );
755 _patchList->actionSetCurrentDontInstall->addTo( _patchMenu );
756 _patchList->actionSetCurrentKeepInstalled->addTo( _patchMenu );
757 #if ENABLE_DELETING_PATCHES
758 _patchList->actionSetCurrentDelete->addTo( _patchMenu );
760 _patchList->actionSetCurrentUpdate->addTo( _patchMenu );
761 _patchList->actionSetCurrentTaboo->addTo( _patchMenu );
763 _patchMenu->insertSeparator();
764 _patchList->addAllInListSubMenu( _patchMenu );
772 _extrasMenu = new QMenu( _menuBar );
773 Q_CHECK_PTR( _extrasMenu );
774 _menuBar->insertItem( _( "&Extras" ), _extrasMenu );
776 _extrasMenu->insertItem( _( "Show &Products" ), this, SLOT( showProducts() ) );
777 _extrasMenu->insertItem( _( "Show &Automatic Package Changes" ), this, SLOT( showAutoPkgList() ), Qt::CTRL + Qt::Key_A );
778 _extrasMenu->insertItem( _( "&Verify System" ), this, SLOT( verifySystem() ) );
780 _extrasMenu->insertSeparator();
782 // Translators: This is about packages ending in "-devel", so don't translate that "-devel"!
783 _extrasMenu->insertItem( _( "Install All Matching -&devel Packages" ), this, SLOT( installDevelPkgs() ) );
785 // Translators: This is about packages ending in "-debuginfo", so don't translate that "-debuginfo"!
786 _extrasMenu->insertItem( _( "Install All Matching -de&buginfo Packages" ), this, SLOT( installDebugInfoPkgs() ) );
788 _extrasMenu->insertSeparator();
790 if ( _pkgConflictDialog )
791 _extrasMenu->insertItem( _( "Generate Dependency Resolver &Test Case" ),
792 _pkgConflictDialog, SLOT( askCreateSolverTestCase() ) );
794 if ( _actionResetIgnoredDependencyProblems )
795 _actionResetIgnoredDependencyProblems->addTo( _extrasMenu );
800 _patchList->actionShowRawPatchInfo->addTo( _extrasMenu );
808 _helpMenu = new QMenu( _menuBar );
809 Q_CHECK_PTR( _helpMenu );
810 _menuBar->insertSeparator();
811 _menuBar->insertItem( _( "&Help" ), _helpMenu );
813 // Note: The help functions and their texts are moved out
814 // to a separate source file YQPackageSelectorHelp.cc
816 // Menu entry for help overview
817 _helpMenu->insertItem( _( "&Overview" ), this, SLOT( help() ), Qt::Key_F1 );
819 // Menu entry for help about used symbols ( icons )
820 _helpMenu->insertItem( _( "&Symbols" ), this, SLOT( symbolHelp() ), Qt::SHIFT + Qt::Key_F1 );
822 // Menu entry for keyboard help
823 _helpMenu->insertItem( _( "&Keys" ), this, SLOT( keyboardHelp() ) );
828 YQPackageSelector::connectFilter( QWidget * filter,
830 bool hasUpdateSignal )
832 if ( ! filter ) return;
833 if ( ! pkgList ) return;
837 connect( _filters, SIGNAL( currentChanged(QWidget *) ),
838 filter, SLOT ( filterIfVisible() ) );
841 connect( this, SIGNAL( refresh() ),
842 filter, SLOT ( filterIfVisible() ) );
844 connect( filter, SIGNAL( filterStart() ),
845 pkgList, SLOT ( clear() ) );
847 connect( filter, SIGNAL( filterMatch( ZyppSel, ZyppPkg ) ),
848 pkgList, SLOT ( addPkgItem ( ZyppSel, ZyppPkg ) ) );
850 connect( filter, SIGNAL( filterFinished() ),
851 pkgList, SLOT ( selectSomething() ) );
853 connect( filter, SIGNAL( filterFinished() ),
854 pkgList, SLOT ( logExcludeStatistics() ) );
857 if ( hasUpdateSignal )
859 connect( filter, SIGNAL( updatePackages() ),
860 pkgList, SLOT ( updateItemStates() ) );
862 if ( _diskUsageList )
864 connect( filter, SIGNAL( updatePackages() ),
865 _diskUsageList, SLOT ( updateDiskUsage() ) );
872 YQPackageSelector::makeConnections()
874 connect( this, SIGNAL( resolvingStarted() ),
875 this, SLOT ( animateCheckButton() ) );
877 connect( this, SIGNAL( resolvingFinished() ),
878 this, SLOT ( restoreCheckButton() ) );
880 connectFilter( _updateProblemFilterView, _pkgList, false );
881 connectFilter( _patternList, _pkgList );
882 connectFilter( _selList, _pkgList );
883 connectFilter( _repoFilterView, _pkgList, false );
884 connectFilter( _rpmGroupTagsFilterView, _pkgList, false );
885 connectFilter( _langList, _pkgList );
886 connectFilter( _statusFilterView, _pkgList, false );
887 connectFilter( _searchFilterView, _pkgList, false );
889 if ( _searchFilterView && _pkgList )
891 connect( _searchFilterView, SIGNAL( message( const QString & ) ),
892 _pkgList, SLOT ( message( const QString & ) ) );
895 if ( _repoFilterView && _pkgList )
897 connect( _repoFilterView, SIGNAL( filterNearMatch ( ZyppSel, ZyppPkg ) ),
898 _pkgList, SLOT ( addPkgItemDimmed ( ZyppSel, ZyppPkg ) ) );
901 if ( _pkgList && _diskUsageList )
904 connect( _pkgList, SIGNAL( statusChanged() ),
905 _diskUsageList, SLOT ( updateDiskUsage() ) );
913 // Connect package conflict dialog
916 if ( _pkgConflictDialog )
920 connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
921 _pkgList, SLOT ( updateItemStates() ) );
926 connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
927 _patternList, SLOT ( updateItemStates() ) );
932 connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
933 _selList, SLOT ( updateItemStates() ) );
936 if ( _diskUsageList )
938 connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
939 _diskUsageList, SLOT ( updateDiskUsage() ) );
945 // Connect package versions view
948 if ( _pkgVersionsView && _pkgList )
950 connect( _pkgVersionsView, SIGNAL( candidateChanged( ZyppObj ) ),
951 _pkgList, SLOT ( updateItemData() ) );
956 // Hotkey to enable "patches" filter view on the fly
959 QShortcut * accel = new QShortcut( Qt::Key_F2, this, SLOT( hotkeyInsertPatchFilterView() ) );
960 Q_CHECK_PTR( accel );
963 // Update actions just before opening menus
966 if ( _pkgMenu && _pkgList )
968 connect( _pkgMenu, SIGNAL( aboutToShow() ),
969 _pkgList, SLOT ( updateActions() ) );
972 if ( _patchMenu && _patchList )
974 connect( _patchMenu, SIGNAL( aboutToShow() ),
975 _patchList, SLOT ( updateActions() ) );
981 YQPackageSelector::animateCheckButton()
983 if ( _checkDependenciesButton )
985 _checkDependenciesButton->setPaletteBackgroundColor( QColor( 0xE0, 0xE0, 0xF8 ) );
986 _checkDependenciesButton->repaint();
992 YQPackageSelector::restoreCheckButton()
994 if ( _checkDependenciesButton )
995 _checkDependenciesButton->setPaletteBackgroundColor( _normalButtonBackground );
1000 YQPackageSelector::autoResolveDependencies()
1002 if ( _autoDependenciesCheckBox && ! _autoDependenciesCheckBox->isChecked() )
1005 resolveDependencies();
1010 YQPackageSelector::manualResolvePackageDependencies()
1012 if ( ! _pkgConflictDialog )
1014 y2error( "No package conflict dialog existing" );
1015 return QDialog::Accepted;
1018 YQUI::ui()->busyCursor();
1019 int result = _pkgConflictDialog->solveAndShowConflicts();
1020 YQUI::ui()->normalCursor();
1022 #if DEPENDENCY_FEEDBACK_IF_OK
1024 if ( result == QDialog::Accepted )
1026 QMessageBox::information( this, "",
1027 _( "All package dependencies are OK." ),
1037 YQPackageSelector::addPatchFilterView()
1039 if ( ! _patchFilterView )
1041 _patchFilterView = new YQPkgPatchFilterView( this );
1042 Q_CHECK_PTR( _patchFilterView );
1043 _filters->addPage( _( "Patches" ), _patchFilterView );
1045 _patchList = _patchFilterView->patchList();
1046 Q_CHECK_PTR( _patchList );
1054 YQPackageSelector::hotkeyInsertPatchFilterView()
1056 if ( ! _patchFilterView )
1058 y2milestone( "Activating patches filter view" );
1060 addPatchFilterView();
1063 _filters->showPage( _patchFilterView );
1065 _patchList->filter();
1071 YQPackageSelector::connectPatchList()
1073 if ( _pkgList && _patchList )
1075 connectFilter( _patchList, _pkgList );
1077 connect( _patchList, SIGNAL( filterMatch ( const QString &, const QString &, FSize ) ),
1078 _pkgList, SLOT ( addPassiveItem( const QString &, const QString &, FSize ) ) );
1080 connect( _patchList, SIGNAL( statusChanged() ),
1081 this, SLOT ( autoResolveDependencies() ) );
1083 if ( _pkgConflictDialog )
1085 connect( _pkgConflictDialog,SIGNAL( updatePackages() ),
1086 _patchList, SLOT ( updateItemStates() ) );
1089 connect( this, SIGNAL( refresh() ),
1090 _patchList, SLOT ( updateItemStates() ) );
1097 YQPackageSelector::pkgExport()
1099 QString filename = YQUI::ui()->askForSaveFileName( QString( DEFAULT_EXPORT_FILE_NAME ), // startsWith
1100 QString( "*.xml;;*" ), // filter
1101 _( "Save Package List" ) );
1103 if ( ! filename.isEmpty() )
1105 zypp::syscontent::Writer writer;
1106 const zypp::ResPool & pool = zypp::getZYpp()->pool();
1108 // The ZYPP obfuscated C++ contest proudly presents:
1110 for_each( pool.begin(), pool.end(),
1111 boost::bind( &zypp::syscontent::Writer::addIf,
1112 boost::ref( writer ),
1114 // Yuck. What a mess.
1116 // Does anybody seriously believe this kind of thing is easier to read,
1117 // let alone use? Get real. This is an argument in favour of all C++
1118 // haters. And it's one that is really hard to counter.
1124 std::ofstream exportFile( toUTF8( filename ).c_str() );
1125 exportFile.exceptions( std::ios_base::badbit | std::ios_base::failbit );
1126 exportFile << writer;
1128 y2milestone( "Package list exported to %s", (const char *) filename );
1130 catch ( std::exception & exception )
1132 y2warning( "Error exporting package list to %s", (const char *) filename );
1134 // The export might have left over a partially written file.
1135 // Try to delete it. Don't care if it doesn't exist and unlink() fails.
1136 QFile::remove(filename);
1139 QMessageBox::warning( this, // parent
1140 _( "Error" ), // caption
1141 _( "Error exporting package list to %1" ).arg( filename ),
1142 QMessageBox::Ok | QMessageBox::Default, // button0
1143 Qt::NoButton, // button1
1144 Qt::NoButton ); // button2
1151 YQPackageSelector::pkgImport()
1153 QString filename = QFileDialog::getOpenFileName( this, _( "Load Package List" ), DEFAULT_EXPORT_FILE_NAME, // startsWi
1154 "*.xml+;;*"// filter
1157 if ( ! filename.isEmpty() )
1159 y2milestone( "Importing package list from %s", qPrintable(filename) );
1163 std::ifstream importFile( toUTF8( filename ).c_str() );
1164 zypp::syscontent::Reader reader( importFile );
1167 // Put reader contents into maps
1170 typedef zypp::syscontent::Reader::Entry ZyppReaderEntry;
1171 typedef std::pair<string, ZyppReaderEntry> ImportMapPair;
1173 map<string, ZyppReaderEntry> importPkg;
1174 map<string, ZyppReaderEntry> importPatterns;
1176 for ( zypp::syscontent::Reader::const_iterator it = reader.begin();
1180 string kind = it->kind();
1182 if ( kind == "package" ) importPkg.insert ( ImportMapPair( it->name(), *it ) );
1183 else if ( kind == "pattern" ) importPatterns.insert( ImportMapPair( it->name(), *it ) );
1186 y2debug( "Found %zu packages and %zu patterns in %s",
1188 importPatterns.size(),
1189 qPrintable(filename) );
1193 // Set status of all patterns and packages according to import map
1196 for ( ZyppPoolIterator it = zyppPatternsBegin();
1197 it != zyppPatternsEnd();
1200 ZyppSel selectable = *it;
1201 importSelectable( *it, importPatterns.find( selectable->name() ) != importPatterns.end(), "pattern" );
1204 for ( ZyppPoolIterator it = zyppPkgBegin();
1208 ZyppSel selectable = *it;
1209 importSelectable( *it, importPkg.find( selectable->name() ) != importPkg.end(), "package" );
1219 if ( _statusFilterView )
1221 // Switch to "Installation Summary" filter view
1223 _filters->showPage( _statusFilterView );
1224 _statusFilterView->filter();
1228 catch ( const zypp::Exception & exception )
1230 y2warning( "Error reading package list from %s", qPrintable(filename) );
1233 QMessageBox::warning( this, // parent
1234 _( "Error" ), // caption
1235 _( "Error loading package list from %1" ).arg( filename ),
1236 QMessageBox::Ok | QMessageBox::Default, // button0
1237 QMessageBox::NoButton, // button1
1238 QMessageBox::NoButton ); // button2
1245 YQPackageSelector::importSelectable( ZyppSel selectable,
1249 ZyppStatus oldStatus = selectable->status();
1250 ZyppStatus newStatus = oldStatus;
1255 // Make sure this selectable does not get installed
1258 switch ( oldStatus )
1262 case S_KeepInstalled:
1266 newStatus = oldStatus;
1271 newStatus = S_KeepInstalled;
1272 y2debug( "Keeping %s %s", kind, selectable->name().c_str() );
1278 if ( selectable->hasCandidateObj() )
1280 newStatus = S_Install;
1281 y2debug( "Adding %s %s", kind, selectable->name().c_str() );
1285 y2debug( "Can't add %s %s: No candidate",
1286 kind, selectable->name().c_str() );
1294 // Make sure this selectable does not get installed
1297 switch ( oldStatus )
1301 case S_KeepInstalled:
1306 y2debug( "Deleting %s %s", kind, selectable->name().c_str() );
1313 newStatus = oldStatus;
1318 if ( oldStatus != newStatus )
1319 selectable->set_status( newStatus );
1324 YQPackageSelector::globalUpdatePkg( bool force )
1329 int count = _pkgList->globalSetPkgStatus( S_Update, force,
1330 true ); // countOnly
1331 y2milestone( "%d pkgs found for update", count );
1333 if ( count >= GLOBAL_UPDATE_CONFIRMATION_THRESHOLD )
1335 if ( QMessageBox::question( this, "", // caption
1336 // Translators: %1 is the number of affected packages
1337 _( "%1 packages will be updated" ).arg( count ),
1338 _( "&Continue" ), _( "C&ancel" ),
1339 0, // defaultButtonNumber (from 0)
1340 1 ) // escapeButtonNumber
1347 (void) _pkgList->globalSetPkgStatus( S_Update, force,
1348 false ); // countOnly
1350 if ( _statusFilterView )
1352 _filters->showPage( _statusFilterView );
1353 _statusFilterView->clear();
1354 _statusFilterView->showTransactions();
1355 _statusFilterView->filter();
1361 YQPackageSelector::showProducts()
1363 YQPkgProductDialog::showProductDialog();
1367 YQPackageSelector::installDevelPkgs()
1369 installSubPkgs( "-devel" );
1374 YQPackageSelector::installDebugInfoPkgs()
1376 installSubPkgs( "-debuginfo" );
1381 YQPackageSelector::pkgExcludeRulesChanged( int menuItemID )
1384 // if ( _viewMenu && _pkgList )
1386 // _viewMenu->setItemChecked( menuItemID, ! _viewMenu->isItemChecked( menuItemID ) );
1388 // if ( _excludeDevelPkgs )
1389 // _excludeDevelPkgs->enable( ! _viewMenu->isItemChecked( _viewShowDevelID ) );
1391 // if ( _excludeDebugInfoPkgs )
1392 // _excludeDebugInfoPkgs->enable( ! _viewMenu->isItemChecked( _viewShowDebugInfoID ) );
1394 // _pkgList->applyExcludeRules();
1400 YQPackageSelector::installSubPkgs( const QString suffix )
1402 // Find all matching packages and put them into a QMap
1404 QMap<QString, ZyppSel> subPkgs;
1406 for ( ZyppPoolIterator it = zyppPkgBegin();
1410 QString name = (*it)->name().c_str();
1412 if ( name.endsWith( suffix ) )
1414 subPkgs[ name ] = *it;
1416 y2debug( "Found subpackage: %s", qPrintable(name) );
1421 // Now go through all packages and look if there is a corresponding subpackage in the QMap
1423 for ( ZyppPoolIterator it = zyppPkgBegin();
1427 QString name = (*it)->name().c_str();
1429 if ( subPkgs.contains( name + suffix ) )
1431 QString subPkgName( name + suffix );
1432 ZyppSel subPkg = subPkgs[ subPkgName ];
1434 switch ( (*it)->status() )
1441 // Don't install the subpackage
1442 y2milestone( "Ignoring unwanted subpackage %s", qPrintable(subPkgName) );
1447 case S_KeepInstalled:
1449 // Install the subpackage, but don't try to update it
1451 if ( ! subPkg->installedObj() )
1453 subPkg->set_status( S_Install );
1454 y2milestone( "Installing subpackage %s", qPrintable(subPkgName) );
1462 // Install or update the subpackage
1464 if ( ! subPkg->installedObj() )
1466 subPkg->set_status( S_Install );
1467 y2milestone( "Installing subpackage %s", qPrintable(subPkgName) );
1471 subPkg->set_status( S_Update );
1472 y2milestone( "Updating subpackage %s", qPrintable(subPkgName) );
1476 // Intentionally omitting 'default' branch so the compiler can
1477 // catch unhandled enum states
1483 if ( _filters && _statusFilterView )
1485 _filters->showPage( _statusFilterView );
1486 _statusFilterView->filter();
1489 YQPkgChangesDialog::showChangesDialog( _( "Added Subpackages:" ),
1490 QRegExp( ".*" + suffix + "$" ),
1492 QString::null, // rejectButtonLabel
1493 true ); // showIfEmpty
1497 #include "YQPackageSelector.moc"