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>
31 #include <QHBoxLayout>
32 #include <QVBoxLayout>
35 #include <QApplication>
38 #include <QFileDialog>
42 #include <QMessageBox>
43 #include <QPushButton>
49 #define y2log_component "qt-pkg"
50 #include <ycp/y2log.h>
52 #include "QY2LayoutUtils.h"
54 #include "YQPackageSelector.h"
55 #include "YQPkgChangeLogView.h"
56 #include "YQPkgChangesDialog.h"
57 #include "YQPkgConflictDialog.h"
58 #include "YQPkgConflictList.h"
59 #include "YQPkgDependenciesView.h"
60 #include "YQPkgDescriptionView.h"
61 #include "YQPkgDiskUsageList.h"
62 #include "YQPkgDiskUsageWarningDialog.h"
63 #include "YQPkgFileListView.h"
64 #include "YQPkgRepoFilterView.h"
65 #include "YQPkgRepoList.h"
66 #include "YQPkgLangList.h"
67 #include "YQPkgList.h"
68 #include "YQPkgPatchFilterView.h"
69 #include "YQPkgPatchList.h"
70 #include "YQPkgPatternList.h"
71 #include "YQPkgProductDialog.h"
72 #include "YQPkgRpmGroupTagsFilterView.h"
73 #include "YQPkgSearchFilterView.h"
74 #include "YQPkgSelList.h"
75 #include "YQPkgStatusFilterView.h"
76 #include "YQPkgTechnicalDetailsView.h"
77 #include "YQPkgTextDialog.h"
78 #include "YQPkgUpdateProblemFilterView.h"
79 #include "YQPkgVersionsView.h"
80 #include "zypp/SysContent.h"
82 #include "QY2ComboTabWidget.h"
84 #include "YQApplication.h"
98 #define DEFAULT_EXPORT_FILE_NAME "user-packages.xml"
103 YQPackageSelector::YQPackageSelector( YWidget * parent,
105 : YQPackageSelectorBase( parent, modeFlags )
107 _showChangesDialog = true;
108 _autoDependenciesCheckBox = 0;
115 _pkgChangeLogView = 0;
116 _pkgDependenciesView = 0;
117 _pkgDescriptionView = 0;
118 _pkgFileListView = 0;
120 _pkgTechnicalDetailsView = 0;
121 _pkgVersionsView = 0;
122 _rpmGroupTagsFilterView = 0;
123 _searchFilterView = 0;
125 _statusFilterView = 0;
126 _updateProblemFilterView = 0;
127 _patchFilterView = 0;
129 _excludeDevelPkgs = 0;
130 _excludeDebugInfoPkgs = 0;
133 if ( onlineUpdateMode() ) y2milestone( "Online update mode" );
134 if ( updateMode() ) y2milestone( "Update mode" );
138 addMenus(); // Only after all widgets are created!
145 if ( _patchFilterView && onlineUpdateMode() )
147 if ( _filters && _patchFilterView && _patchList )
149 _filters->showPage( _patchFilterView );
150 _patchList->filter();
153 else if ( _repoFilterView && repoMode() )
155 if ( YQPkgRepoList::countEnabledRepositories() > 1 )
157 _filters->showPage( _repoFilterView );
158 _repoFilterView->filter();
160 else if ( _searchFilterView )
162 y2milestone( "No multiple repositories - falling back to search mode" );
163 _filters->showPage( _searchFilterView );
164 _searchFilterView->filter();
165 QTimer::singleShot( 0, _searchFilterView, SLOT( setFocus() ) );
168 else if ( _updateProblemFilterView )
170 _filters->showPage( _updateProblemFilterView );
171 _updateProblemFilterView->filter();
174 else if ( searchMode() && _searchFilterView )
176 _filters->showPage( _searchFilterView );
177 _searchFilterView->filter();
178 QTimer::singleShot( 0, _searchFilterView, SLOT( setFocus() ) );
180 else if ( summaryMode() && _statusFilterView )
182 _filters->showPage( _statusFilterView );
183 _statusFilterView->filter();
185 else if ( _patternList )
187 _filters->showPage( _patternList );
188 _patternList->filter();
192 _filters->showPage( _selList );
197 if ( _diskUsageList )
198 _diskUsageList->updateDiskUsage();
200 y2milestone( "PackageSelector init done" );
203 #if CHECK_DEPENDENCIES_ON_STARTUP
205 if ( ! testMode() && ! onlineUpdateMode() )
207 // Fire up the first dependency check in the main loop.
208 // Don't do this right away - wait until all initializations are finished.
209 QTimer::singleShot( 0, this, SLOT( resolveDependencies() ) );
217 YQPackageSelector::basicLayout()
219 QVBoxLayout *layout = new QVBoxLayout();
223 QSplitter * outer_splitter = new QSplitter( Qt::Horizontal, this );
224 Q_CHECK_PTR( outer_splitter );
226 layout->addWidget(outer_splitter);
228 QWidget * left_pane = layoutLeftPane ( outer_splitter );
230 QWidget * right_pane = layoutRightPane( outer_splitter );
232 outer_splitter->setStretchFactor(outer_splitter->indexOf(left_pane), 0);
233 outer_splitter->setStretchFactor(outer_splitter->indexOf(right_pane), 1);
238 YQPackageSelector::layoutLeftPane( QWidget *parent )
240 QSplitter * splitter = new QSplitter( Qt::Vertical, parent );
241 Q_CHECK_PTR( splitter );
243 QWidget * upper_vbox = new QWidget( splitter );
244 QVBoxLayout *layout = new QVBoxLayout(upper_vbox);
245 upper_vbox->setLayout(layout);
247 Q_CHECK_PTR( upper_vbox );
248 layoutFilters( upper_vbox );
249 addVSpacing( upper_vbox, MARGIN );
251 QWidget * lower_vbox = new QWidget( splitter );
252 layout = new QVBoxLayout(lower_vbox);
253 lower_vbox->setLayout(layout);
255 addVSpacing( lower_vbox, MARGIN );
256 _diskUsageList = new YQPkgDiskUsageList( lower_vbox );
257 Q_CHECK_PTR( _diskUsageList );
258 layout->addWidget(_diskUsageList);
260 splitter->setStretchFactor(splitter->indexOf(upper_vbox), 0);
261 splitter->setStretchFactor(splitter->indexOf(lower_vbox), 1);
268 YQPackageSelector::layoutFilters( QWidget *parent )
270 _filters = new QY2ComboTabWidget( _( "Fi<er:" ), parent );
271 Q_CHECK_PTR( _filters );
272 parent->layout()->addWidget(_filters);
275 // Update problem view
280 if ( YQPkgUpdateProblemFilterView::haveProblematicPackages()
283 _updateProblemFilterView = new YQPkgUpdateProblemFilterView( parent);
284 Q_CHECK_PTR( _updateProblemFilterView );
285 _filters->addPage( _( "Update Problems" ), _updateProblemFilterView );
294 if ( onlineUpdateMode()
295 #if ALWAYS_SHOW_PATCHES_VIEW_IF_PATCHES_AVAILABLE
296 || ! zyppPool().empty<zypp::Patch>()
299 addPatchFilterView();
306 if ( ! zyppPool().empty<zypp::Pattern>() || testMode() )
308 _patternList = new YQPkgPatternList( parent, true );
309 Q_CHECK_PTR( _patternList );
310 _filters->addPage( _( "Patterns" ), _patternList );
312 connect( _patternList, SIGNAL( statusChanged() ),
313 this, SLOT ( autoResolveDependencies() ) );
315 connect( this, SIGNAL( refresh() ),
316 _patternList, SLOT ( updateItemStates() ) );
318 if ( _pkgConflictDialog )
320 connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
321 _patternList, SLOT ( updateItemStates() ) );
330 if ( ! zyppPool().empty<zypp::Selection>() || testMode() )
333 _selList = new YQPkgSelList( parent, true );
334 Q_CHECK_PTR( _selList );
335 _filters->addPage( _( "Selections" ), _selList );
337 connect( _selList, SIGNAL( statusChanged() ),
338 this, SLOT ( autoResolveDependencies() ) );
340 connect( this, SIGNAL( refresh() ),
341 _selList, SLOT ( updateItemStates() ) );
343 if ( _pkgConflictDialog )
345 connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
346 _selList, SLOT ( updateItemStates() ) );
352 // RPM group tags view
355 _rpmGroupTagsFilterView = new YQPkgRpmGroupTagsFilterView( parent );
356 Q_CHECK_PTR( _rpmGroupTagsFilterView );
357 _filters->addPage( _( "Package Groups" ), _rpmGroupTagsFilterView );
359 connect( this, SIGNAL( loadData() ),
360 _rpmGroupTagsFilterView, SLOT ( filter() ) );
367 _langList = new YQPkgLangList( parent );
368 Q_CHECK_PTR( _langList );
370 _filters->addPage( _( "Languages" ), _langList );
371 _langList->setSizePolicy( QSizePolicy( QSizePolicy::Ignored, QSizePolicy::Ignored ) ); // hor/vert
373 connect( _langList, SIGNAL( statusChanged() ),
374 this, SLOT ( autoResolveDependencies() ) );
376 connect( this, SIGNAL( refresh() ),
377 _langList, SLOT ( updateItemStates() ) );
384 _repoFilterView = new YQPkgRepoFilterView( parent );
385 Q_CHECK_PTR( _repoFilterView );
386 _filters->addPage( _( "Repositories" ), _repoFilterView );
390 // Package search view
393 _searchFilterView = new YQPkgSearchFilterView( parent );
394 Q_CHECK_PTR( _searchFilterView );
395 _filters->addPage( _( "Search" ), _searchFilterView );
399 // Status change view
402 _statusFilterView = new YQPkgStatusFilterView( parent );
403 Q_CHECK_PTR( _statusFilterView );
404 _filters->addPage( _( "Installation Summary" ), _statusFilterView );
410 _filters->addPage( _( "Keywords" ), new QLabel( "Keywords\nfilter\n\nfor future use", 0 ) );
411 _filters->addPage( _( "MIME Types" ), new QLabel( "MIME Types\nfilter\n\nfor future use" , 0 ) );
418 YQPackageSelector::layoutRightPane( QWidget *parent )
420 QWidget * right_pane_vbox = new QWidget( parent );
422 QVBoxLayout *layout = new QVBoxLayout(right_pane_vbox);
423 right_pane_vbox->setLayout(layout);
425 Q_CHECK_PTR( right_pane_vbox );
427 layout->setMargin( MARGIN );
430 QSplitter * splitter = new QSplitter( Qt::Vertical, right_pane_vbox );
431 Q_CHECK_PTR( splitter );
432 layout->addWidget(splitter);
434 Q_CHECK_PTR( splitter );
435 layoutPkgList( splitter );
437 addVSpacing( splitter, MARGIN );
439 layoutDetailsViews( splitter );
441 layoutButtons( splitter );
443 return right_pane_vbox;
448 YQPackageSelector::layoutPkgList( QWidget *parent )
450 _pkgList= new YQPkgList( parent );
451 Q_CHECK_PTR( _pkgList );
453 connect( _pkgList, SIGNAL( statusChanged() ),
454 this, SLOT ( autoResolveDependencies() ) );
459 YQPackageSelector::layoutDetailsViews( QWidget *parent )
461 bool haveInstalledPkgs = YQPkgList::haveInstalledPkgs();
463 QWidget * details_vbox = new QWidget( parent );
464 Q_CHECK_PTR( details_vbox );
466 QVBoxLayout *layout = new QVBoxLayout(details_vbox);
467 details_vbox->setLayout(layout);
468 //details_vbox->setMinimumSize( 0, 0 );
470 addVSpacing( details_vbox, 8 );
472 _detailsViews = new QTabWidget( details_vbox );
473 layout->addWidget(_detailsViews);
475 Q_CHECK_PTR( _detailsViews );
476 //FIXME _detailsViews->setMargin( MARGIN );
478 // _detailsViews->setTabPosition( QTabWidget::Bottom );
485 _pkgDescriptionView = new YQPkgDescriptionView( _detailsViews );
486 Q_CHECK_PTR( _pkgDescriptionView );
488 _detailsViews->addTab( _pkgDescriptionView, _( "D&escription" ) );
489 _detailsViews->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
491 connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
492 _pkgDescriptionView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
498 _pkgTechnicalDetailsView = new YQPkgTechnicalDetailsView( _detailsViews );
499 Q_CHECK_PTR( _pkgTechnicalDetailsView );
501 _detailsViews->addTab( _pkgTechnicalDetailsView, _( "&Technical Data" ) );
503 connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
504 _pkgTechnicalDetailsView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
511 _pkgDependenciesView = new YQPkgDependenciesView( _detailsViews );
512 Q_CHECK_PTR( _pkgDependenciesView );
514 _detailsViews->addTab( _pkgDependenciesView, _( "Dependencies" ) );
515 _detailsViews->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
517 connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
518 _pkgDependenciesView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
526 _pkgVersionsView = new YQPkgVersionsView( _detailsViews,
527 true ); // userCanSwitchVersions
528 Q_CHECK_PTR( _pkgVersionsView );
530 _detailsViews->addTab( _pkgVersionsView, _( "&Versions" ) );
532 connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
533 _pkgVersionsView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
540 if ( haveInstalledPkgs ) // file list information is only available for installed pkgs
542 _pkgFileListView = new YQPkgFileListView( _detailsViews );
543 Q_CHECK_PTR( _pkgFileListView );
545 _detailsViews->addTab( _pkgFileListView, _( "File List" ) );
546 _detailsViews->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
548 connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
549 _pkgFileListView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
557 if ( haveInstalledPkgs ) // change log information is only available for installed pkgs
559 _pkgChangeLogView = new YQPkgChangeLogView( _detailsViews );
560 Q_CHECK_PTR( _pkgChangeLogView );
562 _detailsViews->addTab( _pkgChangeLogView, _( "Change Log" ) );
563 _detailsViews->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
565 connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
566 _pkgChangeLogView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
572 YQPackageSelector::layoutButtons( QWidget *parent )
574 QWidget * button_box = new QWidget( parent );
575 Q_CHECK_PTR( button_box );
577 QHBoxLayout *layout = new QHBoxLayout(button_box);
578 button_box->setLayout(layout);
580 layout->setSpacing( SPACING );
582 // Button: Dependency check
583 // Translators: Please keep this short!
584 _checkDependenciesButton = new QPushButton( _( "Chec&k" ), button_box );
585 layout->addWidget(_checkDependenciesButton);
587 Q_CHECK_PTR( _checkDependenciesButton );
588 _checkDependenciesButton->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); // hor/vert
589 _normalButtonBackground = _checkDependenciesButton->palette().color(QPalette::Background);;
591 connect( _checkDependenciesButton, SIGNAL( clicked() ),
592 this, SLOT ( manualResolvePackageDependencies() ) );
595 // Checkbox: Automatically check dependencies for every package status change?
596 // Translators: Please keep this short!
597 _autoDependenciesCheckBox = new QCheckBox( _( "A&utocheck" ), button_box );
598 Q_CHECK_PTR( _autoDependenciesCheckBox );
599 layout->addWidget(_autoDependenciesCheckBox);
601 _autoDependenciesCheckBox->setChecked( AUTO_CHECK_DEPENDENCIES_DEFAULT );
603 addHStretch( button_box );
605 QPushButton * cancel_button = new QPushButton( _( "&Cancel" ), button_box );
606 Q_CHECK_PTR( cancel_button );
607 layout->addWidget(cancel_button);
609 cancel_button->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); // hor/vert
611 connect( cancel_button, SIGNAL( clicked() ),
612 this, SLOT ( reject() ) );
615 QPushButton * accept_button = new QPushButton( _( "&Accept" ), button_box );
616 Q_CHECK_PTR( accept_button );
617 layout->addWidget(accept_button);
618 accept_button->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); // hor/vert
620 connect( accept_button, SIGNAL( clicked() ),
621 this, SLOT ( accept() ) );
623 button_box->setFixedHeight( button_box->sizeHint().height() );
628 YQPackageSelector::layoutMenuBar( QWidget *parent )
630 _menuBar = new QMenuBar( parent );
631 Q_CHECK_PTR( _menuBar );
633 parent->layout()->addWidget(_menuBar);
646 YQPackageSelector::addMenus()
652 _fileMenu = new QMenu( _menuBar );
653 Q_CHECK_PTR( _fileMenu );
654 QAction *action = _menuBar->addMenu( _fileMenu );
655 action->setText(( "&File" ));
657 _fileMenu->addAction( _( "&Import..." ), this, SLOT( pkgImport() ) );
658 _fileMenu->addAction( _( "&Export..." ), this, SLOT( pkgExport() ) );
660 _fileMenu->addSeparator();
662 _fileMenu->addAction( _( "E&xit -- Discard Changes" ), this, SLOT( reject() ) );
663 _fileMenu->addAction( _( "&Quit -- Save Changes" ), this, SLOT( accept() ) );
672 _viewMenu = new QMenu( _menuBar );
673 Q_CHECK_PTR( _viewMenu );
674 QAction *action = _menuBar->addMenu( _viewMenu );
675 action->setText(_( "&View" ));
677 // Translators: This is about packages ending in "-devel", so don't translate that "-devel"!
678 _showDevelAction = _viewMenu->addAction( _( "Show -de&vel Packages" ),
679 this, SLOT( pkgExcludeRulesChanged() ), Qt::Key_F7 );
680 _showDevelAction->setChecked(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 _showDebugAction = _viewMenu->addAction( _( "Show -&debuginfo Packages" ),
687 this, SLOT( pkgExcludeRulesChanged() ), Qt::Key_F8 );
688 _showDebugAction->setChecked(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 action = _menuBar->addMenu( _pkgMenu );
701 action->setText(_( "&Package" ));
703 _pkgMenu->addAction(_pkgList->actionSetCurrentInstall);
704 _pkgMenu->addAction(_pkgList->actionSetCurrentDontInstall);
705 _pkgMenu->addAction(_pkgList->actionSetCurrentKeepInstalled);
706 _pkgMenu->addAction(_pkgList->actionSetCurrentDelete);
707 _pkgMenu->addAction(_pkgList->actionSetCurrentUpdate);
708 _pkgMenu->addAction(_pkgList->actionSetCurrentTaboo);
710 _pkgMenu->addSeparator();
712 _pkgMenu->addAction(_pkgList->actionInstallSourceRpm);
713 _pkgMenu->addAction(_pkgList->actionDontInstallSourceRpm);
715 _pkgMenu->addSeparator();
716 QMenu * submenu = _pkgList->addAllInListSubMenu( _pkgMenu );
717 Q_CHECK_PTR( submenu );
719 submenu->addSeparator();
721 _pkgMenu->addAction(_pkgList->actionInstallListSourceRpms);
722 _pkgMenu->addAction(_pkgList->actionDontInstallListSourceRpms);
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 action = _pkgMenu->addMenu( submenu );
735 action->setText(_( "All Packages" ));
737 submenu->addAction( _( "Update if newer version available" ),
738 this, SLOT( globalUpdatePkg() ) );
740 submenu->addAction( _( "Update unconditionally" ),
741 this, SLOT( globalUpdatePkgForce() ) );
751 _patchMenu = new QMenu( _menuBar );
752 Q_CHECK_PTR( _patchMenu );
753 action = _menuBar->addMenu( _patchMenu );
754 action->setText(_( "&Patch" ));
756 _patchMenu->addAction(_patchList->actionSetCurrentInstall);
757 _patchMenu->addAction(_patchList->actionSetCurrentDontInstall);
758 _patchMenu->addAction(_patchList->actionSetCurrentKeepInstalled);
760 #if ENABLE_DELETING_PATCHES
761 _patchMenu->addAction(_patchList->actionSetCurrentDelete);
763 _patchMenu->addAction(_patchList->actionSetCurrentUpdate);
764 _patchMenu->addAction(_patchList->actionSetCurrentTaboo);
766 _patchMenu->addSeparator();
767 _patchList->addAllInListSubMenu( _patchMenu );
775 _extrasMenu = new QMenu( _menuBar );
776 Q_CHECK_PTR( _extrasMenu );
777 action = _menuBar->addMenu( _extrasMenu );
778 action->setText(_( "&Extras" ));
780 _extrasMenu->addAction( _( "Show &Products" ), this, SLOT( showProducts() ) );
781 _extrasMenu->addAction( _( "Show &Automatic Package Changes" ), this, SLOT( showAutoPkgList() ), Qt::CTRL + Qt::Key_A );
782 _extrasMenu->addAction( _( "&Verify System" ), this, SLOT( verifySystem() ) );
784 _extrasMenu->addSeparator();
786 // Translators: This is about packages ending in "-devel", so don't translate that "-devel"!
787 _extrasMenu->addAction( _( "Install All Matching -&devel Packages" ), this, SLOT( installDevelPkgs() ) );
789 // Translators: This is about packages ending in "-debuginfo", so don't translate that "-debuginfo"!
790 _extrasMenu->addAction( _( "Install All Matching -de&buginfo Packages" ), this, SLOT( installDebugInfoPkgs() ) );
792 _extrasMenu->addSeparator();
794 if ( _pkgConflictDialog )
795 _extrasMenu->addAction( _( "Generate Dependency Resolver &Test Case" ),
796 _pkgConflictDialog, SLOT( askCreateSolverTestCase() ) );
798 if ( _actionResetIgnoredDependencyProblems )
799 _extrasMenu->addAction(_actionResetIgnoredDependencyProblems);
804 _extrasMenu->addAction(_patchList->actionShowRawPatchInfo);
812 _helpMenu = new QMenu( _menuBar );
813 Q_CHECK_PTR( _helpMenu );
814 _menuBar->addSeparator();
815 action = _menuBar->addMenu( _helpMenu );
816 action->setText(_( "&Help" ));
818 // Note: The help functions and their texts are moved out
819 // to a separate source file YQPackageSelectorHelp.cc
821 // Menu entry for help overview
822 _helpMenu->addAction( _( "&Overview" ), this, SLOT( help() ), Qt::Key_F1 );
824 // Menu entry for help about used symbols ( icons )
825 _helpMenu->addAction( _( "&Symbols" ), this, SLOT( symbolHelp() ), Qt::SHIFT + Qt::Key_F1 );
827 // Menu entry for keyboard help
828 _helpMenu->addAction( _( "&Keys" ), this, SLOT( keyboardHelp() ) );
833 YQPackageSelector::connectFilter( QWidget * filter,
835 bool hasUpdateSignal )
837 if ( ! filter ) return;
838 if ( ! pkgList ) return;
842 connect( _filters, SIGNAL( currentChanged(QWidget *) ),
843 filter, SLOT ( filterIfVisible() ) );
846 connect( this, SIGNAL( refresh() ),
847 filter, SLOT ( filterIfVisible() ) );
849 connect( filter, SIGNAL( filterStart() ),
850 pkgList, SLOT ( clear() ) );
852 connect( filter, SIGNAL( filterMatch( ZyppSel, ZyppPkg ) ),
853 pkgList, SLOT ( addPkgItem ( ZyppSel, ZyppPkg ) ) );
855 connect( filter, SIGNAL( filterFinished() ),
856 pkgList, SLOT ( selectSomething() ) );
858 connect( filter, SIGNAL( filterFinished() ),
859 pkgList, SLOT ( logExcludeStatistics() ) );
862 if ( hasUpdateSignal )
864 connect( filter, SIGNAL( updatePackages() ),
865 pkgList, SLOT ( updateItemStates() ) );
867 if ( _diskUsageList )
869 connect( filter, SIGNAL( updatePackages() ),
870 _diskUsageList, SLOT ( updateDiskUsage() ) );
877 YQPackageSelector::makeConnections()
879 connect( this, SIGNAL( resolvingStarted() ),
880 this, SLOT ( animateCheckButton() ) );
882 connect( this, SIGNAL( resolvingFinished() ),
883 this, SLOT ( restoreCheckButton() ) );
885 connectFilter( _updateProblemFilterView, _pkgList, false );
886 connectFilter( _patternList, _pkgList );
887 connectFilter( _selList, _pkgList );
888 connectFilter( _repoFilterView, _pkgList, false );
889 connectFilter( _rpmGroupTagsFilterView, _pkgList, false );
890 connectFilter( _langList, _pkgList );
891 connectFilter( _statusFilterView, _pkgList, false );
892 connectFilter( _searchFilterView, _pkgList, false );
894 if ( _searchFilterView && _pkgList )
896 connect( _searchFilterView, SIGNAL( message( const QString & ) ),
897 _pkgList, SLOT ( message( const QString & ) ) );
900 if ( _repoFilterView && _pkgList )
902 connect( _repoFilterView, SIGNAL( filterNearMatch ( ZyppSel, ZyppPkg ) ),
903 _pkgList, SLOT ( addPkgItemDimmed ( ZyppSel, ZyppPkg ) ) );
906 if ( _pkgList && _diskUsageList )
909 connect( _pkgList, SIGNAL( statusChanged() ),
910 _diskUsageList, SLOT ( updateDiskUsage() ) );
918 // Connect package conflict dialog
921 if ( _pkgConflictDialog )
925 connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
926 _pkgList, SLOT ( updateItemStates() ) );
931 connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
932 _patternList, SLOT ( updateItemStates() ) );
937 connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
938 _selList, SLOT ( updateItemStates() ) );
941 if ( _diskUsageList )
943 connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
944 _diskUsageList, SLOT ( updateDiskUsage() ) );
950 // Connect package versions view
953 if ( _pkgVersionsView && _pkgList )
955 connect( _pkgVersionsView, SIGNAL( candidateChanged( ZyppObj ) ),
956 _pkgList, SLOT ( updateItemData() ) );
961 // Hotkey to enable "patches" filter view on the fly
964 QShortcut * accel = new QShortcut( Qt::Key_F2, this, SLOT( hotkeyInsertPatchFilterView() ) );
965 Q_CHECK_PTR( accel );
968 // Update actions just before opening menus
971 if ( _pkgMenu && _pkgList )
973 connect( _pkgMenu, SIGNAL( aboutToShow() ),
974 _pkgList, SLOT ( updateActions() ) );
977 if ( _patchMenu && _patchList )
979 connect( _patchMenu, SIGNAL( aboutToShow() ),
980 _patchList, SLOT ( updateActions() ) );
986 YQPackageSelector::animateCheckButton()
988 if ( _checkDependenciesButton )
990 QPalette p = _checkDependenciesButton->palette();
991 p.setColor(QPalette::Background, QColor( 0xE0, 0xE0, 0xF8 ));
992 _checkDependenciesButton->setPalette(p);
993 _checkDependenciesButton->repaint();
999 YQPackageSelector::restoreCheckButton()
1001 if ( _checkDependenciesButton )
1003 QPalette p = _checkDependenciesButton->palette();
1004 p.setColor(QPalette::Background, _normalButtonBackground);
1005 _checkDependenciesButton->setPalette(p);
1011 YQPackageSelector::autoResolveDependencies()
1013 if ( _autoDependenciesCheckBox && ! _autoDependenciesCheckBox->isChecked() )
1016 resolveDependencies();
1021 YQPackageSelector::manualResolvePackageDependencies()
1023 if ( ! _pkgConflictDialog )
1025 y2error( "No package conflict dialog existing" );
1026 return QDialog::Accepted;
1029 YQUI::ui()->busyCursor();
1030 int result = _pkgConflictDialog->solveAndShowConflicts();
1031 YQUI::ui()->normalCursor();
1033 #if DEPENDENCY_FEEDBACK_IF_OK
1035 if ( result == QDialog::Accepted )
1037 QMessageBox::information( this, "",
1038 _( "All package dependencies are OK." ),
1048 YQPackageSelector::addPatchFilterView()
1050 if ( ! _patchFilterView )
1052 _patchFilterView = new YQPkgPatchFilterView( this );
1053 Q_CHECK_PTR( _patchFilterView );
1054 _filters->addPage( _( "Patches" ), _patchFilterView );
1056 _patchList = _patchFilterView->patchList();
1057 Q_CHECK_PTR( _patchList );
1065 YQPackageSelector::hotkeyInsertPatchFilterView()
1067 if ( ! _patchFilterView )
1069 y2milestone( "Activating patches filter view" );
1071 addPatchFilterView();
1074 _filters->showPage( _patchFilterView );
1076 _patchList->filter();
1082 YQPackageSelector::connectPatchList()
1084 if ( _pkgList && _patchList )
1086 connectFilter( _patchList, _pkgList );
1088 connect( _patchList, SIGNAL( filterMatch ( const QString &, const QString &, FSize ) ),
1089 _pkgList, SLOT ( addPassiveItem( const QString &, const QString &, FSize ) ) );
1091 connect( _patchList, SIGNAL( statusChanged() ),
1092 this, SLOT ( autoResolveDependencies() ) );
1094 if ( _pkgConflictDialog )
1096 connect( _pkgConflictDialog,SIGNAL( updatePackages() ),
1097 _patchList, SLOT ( updateItemStates() ) );
1100 connect( this, SIGNAL( refresh() ),
1101 _patchList, SLOT ( updateItemStates() ) );
1108 YQPackageSelector::pkgExport()
1110 QString filename = YQApplication::askForSaveFileName( QString( DEFAULT_EXPORT_FILE_NAME ), // startsWith
1111 QString( "*.xml;;*" ), // filter
1112 _( "Save Package List" ) );
1114 if ( ! filename.isEmpty() )
1116 zypp::syscontent::Writer writer;
1117 const zypp::ResPool & pool = zypp::getZYpp()->pool();
1119 // The ZYPP obfuscated C++ contest proudly presents:
1121 for_each( pool.begin(), pool.end(),
1122 boost::bind( &zypp::syscontent::Writer::addIf,
1123 boost::ref( writer ),
1125 // Yuck. What a mess.
1127 // Does anybody seriously believe this kind of thing is easier to read,
1128 // let alone use? Get real. This is an argument in favour of all C++
1129 // haters. And it's one that is really hard to counter.
1135 std::ofstream exportFile( toUTF8( filename ).c_str() );
1136 exportFile.exceptions( std::ios_base::badbit | std::ios_base::failbit );
1137 exportFile << writer;
1139 y2milestone( "Package list exported to %s", qPrintable(filename) );
1141 catch ( std::exception & exception )
1143 y2warning( "Error exporting package list to %s", qPrintable(filename) );
1145 // The export might have left over a partially written file.
1146 // Try to delete it. Don't care if it doesn't exist and unlink() fails.
1147 QFile::remove(filename);
1150 QMessageBox::warning( this, // parent
1151 _( "Error" ), // caption
1152 _( "Error exporting package list to %1" ).arg( filename ),
1153 QMessageBox::Ok | QMessageBox::Default, // button0
1154 Qt::NoButton, // button1
1155 Qt::NoButton ); // button2
1162 YQPackageSelector::pkgImport()
1164 QString filename = QFileDialog::getOpenFileName( this, _( "Load Package List" ), DEFAULT_EXPORT_FILE_NAME, // startsWi
1165 "*.xml+;;*"// filter
1168 if ( ! filename.isEmpty() )
1170 y2milestone( "Importing package list from %s", qPrintable(filename) );
1174 std::ifstream importFile( toUTF8( filename ).c_str() );
1175 zypp::syscontent::Reader reader( importFile );
1178 // Put reader contents into maps
1181 typedef zypp::syscontent::Reader::Entry ZyppReaderEntry;
1182 typedef std::pair<string, ZyppReaderEntry> ImportMapPair;
1184 map<string, ZyppReaderEntry> importPkg;
1185 map<string, ZyppReaderEntry> importPatterns;
1187 for ( zypp::syscontent::Reader::const_iterator it = reader.begin();
1191 string kind = it->kind();
1193 if ( kind == "package" ) importPkg.insert ( ImportMapPair( it->name(), *it ) );
1194 else if ( kind == "pattern" ) importPatterns.insert( ImportMapPair( it->name(), *it ) );
1197 y2debug( "Found %zu packages and %zu patterns in %s",
1199 importPatterns.size(),
1200 qPrintable(filename) );
1204 // Set status of all patterns and packages according to import map
1207 for ( ZyppPoolIterator it = zyppPatternsBegin();
1208 it != zyppPatternsEnd();
1211 ZyppSel selectable = *it;
1212 importSelectable( *it, importPatterns.find( selectable->name() ) != importPatterns.end(), "pattern" );
1215 for ( ZyppPoolIterator it = zyppPkgBegin();
1219 ZyppSel selectable = *it;
1220 importSelectable( *it, importPkg.find( selectable->name() ) != importPkg.end(), "package" );
1230 if ( _statusFilterView )
1232 // Switch to "Installation Summary" filter view
1234 _filters->showPage( _statusFilterView );
1235 _statusFilterView->filter();
1239 catch ( const zypp::Exception & exception )
1241 y2warning( "Error reading package list from %s", qPrintable(filename) );
1244 QMessageBox::warning( this, // parent
1245 _( "Error" ), // caption
1246 _( "Error loading package list from %1" ).arg( filename ),
1247 QMessageBox::Ok | QMessageBox::Default, // button0
1248 QMessageBox::NoButton, // button1
1249 QMessageBox::NoButton ); // button2
1256 YQPackageSelector::importSelectable( ZyppSel selectable,
1260 ZyppStatus oldStatus = selectable->status();
1261 ZyppStatus newStatus = oldStatus;
1266 // Make sure this selectable does not get installed
1269 switch ( oldStatus )
1273 case S_KeepInstalled:
1277 newStatus = oldStatus;
1282 newStatus = S_KeepInstalled;
1283 y2debug( "Keeping %s %s", kind, selectable->name().c_str() );
1289 if ( selectable->hasCandidateObj() )
1291 newStatus = S_Install;
1292 y2debug( "Adding %s %s", kind, selectable->name().c_str() );
1296 y2debug( "Can't add %s %s: No candidate",
1297 kind, selectable->name().c_str() );
1305 // Make sure this selectable does not get installed
1308 switch ( oldStatus )
1312 case S_KeepInstalled:
1317 y2debug( "Deleting %s %s", kind, selectable->name().c_str() );
1324 newStatus = oldStatus;
1329 if ( oldStatus != newStatus )
1330 selectable->set_status( newStatus );
1335 YQPackageSelector::globalUpdatePkg( bool force )
1340 int count = _pkgList->globalSetPkgStatus( S_Update, force,
1341 true ); // countOnly
1342 y2milestone( "%d pkgs found for update", count );
1344 if ( count >= GLOBAL_UPDATE_CONFIRMATION_THRESHOLD )
1346 if ( QMessageBox::question( this, "", // caption
1347 // Translators: %1 is the number of affected packages
1348 _( "%1 packages will be updated" ).arg( count ),
1349 _( "&Continue" ), _( "C&ancel" ),
1350 0, // defaultButtonNumber (from 0)
1351 1 ) // escapeButtonNumber
1358 (void) _pkgList->globalSetPkgStatus( S_Update, force,
1359 false ); // countOnly
1361 if ( _statusFilterView )
1363 _filters->showPage( _statusFilterView );
1364 _statusFilterView->clear();
1365 _statusFilterView->showTransactions();
1366 _statusFilterView->filter();
1372 YQPackageSelector::showProducts()
1374 YQPkgProductDialog::showProductDialog();
1378 YQPackageSelector::installDevelPkgs()
1380 installSubPkgs( "-devel" );
1385 YQPackageSelector::installDebugInfoPkgs()
1387 installSubPkgs( "-debuginfo" );
1392 YQPackageSelector::pkgExcludeRulesChanged()
1394 QAction *action = dynamic_cast<QAction *>(QObject::sender());
1396 if ( _viewMenu && _pkgList )
1398 //action->setChecked();
1399 //_viewMenu->setItemChecked( menuItemID, ! _viewMenu->isItemChecked( menuItemID ) );
1401 if ( _excludeDevelPkgs )
1402 _excludeDevelPkgs->enable( ! _showDevelAction->isChecked() );
1404 if ( _excludeDebugInfoPkgs )
1405 _excludeDebugInfoPkgs->enable( ! _showDebugAction->isChecked() );
1407 _pkgList->applyExcludeRules();
1413 YQPackageSelector::installSubPkgs( const QString suffix )
1415 // Find all matching packages and put them into a QMap
1417 QMap<QString, ZyppSel> subPkgs;
1419 for ( ZyppPoolIterator it = zyppPkgBegin();
1423 QString name = (*it)->name().c_str();
1425 if ( name.endsWith( suffix ) )
1427 subPkgs[ name ] = *it;
1429 y2debug( "Found subpackage: %s", qPrintable(name) );
1434 // Now go through all packages and look if there is a corresponding subpackage in the QMap
1436 for ( ZyppPoolIterator it = zyppPkgBegin();
1440 QString name = (*it)->name().c_str();
1442 if ( subPkgs.contains( name + suffix ) )
1444 QString subPkgName( name + suffix );
1445 ZyppSel subPkg = subPkgs[ subPkgName ];
1447 switch ( (*it)->status() )
1454 // Don't install the subpackage
1455 y2milestone( "Ignoring unwanted subpackage %s", qPrintable(subPkgName) );
1460 case S_KeepInstalled:
1462 // Install the subpackage, but don't try to update it
1464 if ( ! subPkg->installedObj() )
1466 subPkg->set_status( S_Install );
1467 y2milestone( "Installing subpackage %s", qPrintable(subPkgName) );
1475 // Install or update the subpackage
1477 if ( ! subPkg->installedObj() )
1479 subPkg->set_status( S_Install );
1480 y2milestone( "Installing subpackage %s", qPrintable(subPkgName) );
1484 subPkg->set_status( S_Update );
1485 y2milestone( "Updating subpackage %s", qPrintable(subPkgName) );
1489 // Intentionally omitting 'default' branch so the compiler can
1490 // catch unhandled enum states
1496 if ( _filters && _statusFilterView )
1498 _filters->showPage( _statusFilterView );
1499 _statusFilterView->filter();
1502 YQPkgChangesDialog::showChangesDialog( _( "Added Subpackages:" ),
1503 QRegExp( ".*" + suffix + "$" ),
1505 QString::null, // rejectButtonLabel
1506 true ); // showIfEmpty
1510 #include "YQPackageSelector.moc"