libyui-qt-pkg  2.45.15.2
YQPackageSelector.cc
1 /**************************************************************************
2 Copyright (C) 2000 - 2010 Novell, Inc.
3 All Rights Reserved.
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 
19 **************************************************************************/
20 
21 
22 /*---------------------------------------------------------------------\
23 | |
24 | __ __ ____ _____ ____ |
25 | \ \ / /_ _/ ___|_ _|___ \ |
26 | \ V / _` \___ \ | | __) | |
27 | | | (_| |___) || | / __/ |
28 | |_|\__,_|____/ |_| |_____| |
29 | |
30 | core system |
31 | (C) SuSE GmbH |
32 \----------------------------------------------------------------------/
33 
34  File: YQPackageSelector.cc
35  See also: YQPackageSelectorHelp.cc
36 
37  Author: Stefan Hundhammer <sh@suse.de>
38 
39  Textdomain "qt-pkg"
40 
41  /-*/
42 
43 #define CHECK_DEPENDENCIES_ON_STARTUP 1
44 #define DEPENDENCY_FEEDBACK_IF_OK 1
45 #define AUTO_CHECK_DEPENDENCIES_DEFAULT true
46 #define ALWAYS_SHOW_PATCHES_VIEW_IF_PATCHES_AVAILABLE 0
47 #define GLOBAL_UPDATE_CONFIRMATION_THRESHOLD 20
48 #define ENABLE_SOURCE_RPMS 0
49 #define BRAINDEAD_LIB_NAMING_SCHEME 1
50 #define MARGIN 6 // around the widget
51 #define SPACING_BELOW_MENU_BAR 4
52 #define SPLITTER_HALF_SPACING 4
53 
54 
55 #include <fstream>
56 #include <algorithm>
57 #include <boost/bind.hpp>
58 
59 #include <QHBoxLayout>
60 #include <QVBoxLayout>
61 #include <QAction>
62 #include <QShortcut>
63 #include <QApplication>
64 #include <QCheckBox>
65 #include <QDialog>
66 #include <QFileDialog>
67 #include <QLabel>
68 #include <QMap>
69 #include <QMenuBar>
70 #include <QMessageBox>
71 #include <QPushButton>
72 #include <QSplitter>
73 #include <QTabWidget>
74 #include <QTimer>
75 #include <QMenu>
76 #include <QSettings>
77 
78 #define YUILogComponent "qt-pkg"
79 #include "YUILog.h"
80 
81 #include "QY2LayoutUtils.h"
82 
83 #include "YQZypp.h"
84 #include "YQPackageSelector.h"
85 #include "YQPkgChangeLogView.h"
86 #include "YQPkgChangesDialog.h"
87 #include "YQPkgConflictDialog.h"
88 #include "YQPkgConflictList.h"
89 #include "YQPkgDependenciesView.h"
90 #include "YQPkgDescriptionView.h"
91 #include "YQPkgDiskUsageList.h"
92 #include "YQPkgDiskUsageWarningDialog.h"
93 #include "YQPkgFileListView.h"
94 #include "YQPkgFilterTab.h"
95 #include "YQPkgHistoryDialog.h"
96 #include "YQPkgLangList.h"
97 #include "YQPkgList.h"
98 #include "YQPkgPackageKitGroupsFilterView.h"
99 #include "YQPkgPatchFilterView.h"
100 #include "YQPkgPatchList.h"
101 #include "YQPkgPatternList.h"
102 #include "YQPkgProductDialog.h"
103 #include "YQPkgRepoFilterView.h"
104 #include "YQPkgRepoList.h"
105 #include "YQPkgRpmGroupTagsFilterView.h"
106 #include "YQPkgSearchFilterView.h"
107 #include "YQPkgServiceFilterView.h"
108 #include "YQPkgStatusFilterView.h"
109 #include "YQPkgTechnicalDetailsView.h"
110 #include "YQPkgTextDialog.h"
111 #include "YQPkgUpdateProblemFilterView.h"
112 #include "YQPkgVersionsView.h"
113 
114 #include "zypp/SysContent.h"
115 #include "zypp/base/String.h"
116 #include "zypp/base/Sysconfig.h"
117 
118 #include "QY2ComboTabWidget.h"
119 #include "YQDialog.h"
120 #include "YQApplication.h"
121 #include "utf8.h"
122 #include "YQUI.h"
123 #include "YEvent.h"
124 #include "YQi18n.h"
125 
126 
127 
128 using std::max;
129 using std::string;
130 using std::map;
131 using std::pair;
132 
133 #define DEFAULT_EXPORT_FILE_NAME "user-packages.xml"
134 #define FAST_SOLVER 1
135 
136 #define SETTINGS_DIR "YaST2"
137 #define PATH_TO_YAST_SYSCONFIG "/etc/sysconfig/yast2"
138 #define OPTION_VERIFY "PKGMGR_VERIFY_SYSTEM"
139 #define OPTION_AUTO_CHECK "PKGMGR_AUTO_CHECK"
140 #define OPTION_RECOMMENDED "PKGMGR_RECOMMENDED"
141 
142 YQPackageSelector::YQPackageSelector( YWidget * parent,
143  long modeFlags )
144  : YQPackageSelectorBase( parent, modeFlags )
145 {
146  _showChangesDialog = true;
147  _autoDependenciesAction = 0;
148  _detailsViews = 0;
149  _filters = 0;
150  _langList = 0;
151  _packageKitGroupsFilterView = 0;
152  _patchFilterView = 0;
153  _patchList = 0;
154  _patternList = 0;
155  _pkgChangeLogView = 0;
156  _pkgDependenciesView = 0;
157  _pkgDescriptionView = 0;
158  _pkgFileListView = 0;
159  _pkgList = 0;
160  _pkgTechnicalDetailsView = 0;
161  _pkgVersionsView = 0;
162  _repoFilterView = 0;
163  _serviceFilterView = 0;
164  _rpmGroupTagsFilterView = 0;
165  _searchFilterView = 0;
166  _statusFilterView = 0;
167  _updateProblemFilterView = 0;
168  _excludeDevelPkgs = 0;
169  _excludeDebugInfoPkgs = 0;
170 
171  yuiMilestone() << "This is libyui-qt-pkg " << VERSION << std::endl;
172 
173  if ( onlineUpdateMode() ) yuiMilestone() << "Online update mode" << std::endl;
174  if ( updateMode() ) yuiMilestone() << "Update mode" << std::endl;
175 
176  basicLayout();
177  addMenus(); // Only after all widgets are created!
178  loadSettings(); // Only after menus are created!
179  makeConnections();
180  emit loadData();
181 
182  _filters->loadSettings();
183  bool pagesRestored = _filters->tabCount() > 0;
184 
185  if ( _pkgList )
186  _pkgList->clear();
187 
188  if ( ! pagesRestored )
189  {
190  yuiDebug() << "No page configuration saved, using fallbacks" << std::endl;
191 
192  //
193  // Add a number of default tabs in the desired order
194  //
195 
196  if ( _searchFilterView ) _filters->showPage( _searchFilterView );
197 
198  if ( ! searchMode() && ! summaryMode()
199  && _patternList ) _filters->showPage( _patternList );
200  else if ( _rpmGroupTagsFilterView ) _filters->showPage( _rpmGroupTagsFilterView );
201 
202  if ( _statusFilterView ) _filters->showPage( _statusFilterView );
203  }
204 
205 
206  //
207  // Move the desired tab to the foreground
208  //
209 
210  if ( _patchFilterView && onlineUpdateMode() )
211  {
212  if ( _patchFilterView && _patchList )
213  {
214  _filters->showPage( _patchFilterView );
215  _patchList->filter();
216  }
217  }
218  else if ( _repoFilterView && repoMode() )
219  {
221  {
222  _filters->showPage( _repoFilterView );
223  _repoFilterView->filter();
224  }
225  }
226  else if ( _updateProblemFilterView )
227  {
228  _filters->showPage( _updateProblemFilterView );
229  _updateProblemFilterView->filter();
230  }
231  else if ( searchMode() && _searchFilterView )
232  {
233  _filters->showPage( _searchFilterView );
234  _searchFilterView->filter();
235  QTimer::singleShot( 0, _searchFilterView, SLOT( setFocus() ) );
236  }
237  else if ( summaryMode() && _statusFilterView )
238  {
239  _filters->showPage( _statusFilterView );
240  _statusFilterView->filter();
241  _pkgList->selectNextItem();
242  }
243  else if ( _patternList )
244  {
245  _filters->showPage( _patternList );
246  _patternList->filter();
247  }
248 
249 
250  if ( _filters->diskUsageList() )
251  _filters->diskUsageList()->updateDiskUsage();
252 
253  yuiMilestone() << "PackageSelector init done" << std::endl;
254 
255 
256 #if CHECK_DEPENDENCIES_ON_STARTUP
257 
258  if ( ! testMode() )
259  {
260  // Fire up the first dependency check in the main loop.
261  // Don't do this right away - wait until all initializations are finished.
262  QTimer::singleShot( 0, this, SLOT( resolveDependencies() ) );
263 
264  }
265 #endif
266 
267 }
268 
269 
270 std::string
271 YQPackageSelector::iconPath( const std::string &name, int size )
272 {
273  // FIXME
274  #define PREFIX "/usr/"
275  return zypp::str::form("%s/share/icons/hicolor/%dx%d/apps/%s.png",
276  PREFIX, size, size, name.c_str() );
277 }
278 
279 
280 void
281 YQPackageSelector::basicLayout()
282 {
283  QVBoxLayout *layout = new QVBoxLayout();
284  setLayout( layout );
285  layout->setContentsMargins( MARGIN, // left
286  0, // top
287  MARGIN, // right
288  MARGIN ); // bottom
289  layout->setSpacing( SPACING_BELOW_MENU_BAR );
290  layoutMenuBar( this );
291 
292  QString settingsName = "YQPackageSelector";
293 
294  if ( onlineUpdateMode() ) settingsName = "YQOnlineUpdate";
295  if ( updateMode() ) settingsName = "YQSystemUpdate";
296 
297  _filters = new YQPkgFilterTab( this, settingsName );
298  YUI_CHECK_NEW( _filters );
299 
300  layout->addWidget( _filters );
301  layoutFilters( this );
302  layoutRightPane( _filters->rightPane() );
303 }
304 
305 
306 void
307 YQPackageSelector::layoutFilters( QWidget *parent )
308 {
309  //
310  // Update problem view
311  //
312 
313  if ( updateMode() )
314  {
316  || testMode() )
317  {
318  _updateProblemFilterView = new YQPkgUpdateProblemFilterView( parent );
319  YUI_CHECK_NEW( _updateProblemFilterView );
320  _filters->addPage( _( "&Update Problems" ), _updateProblemFilterView, "update_problems" );
321  }
322  }
323 
324 
325  //
326  // Patches view
327  //
328 
329  if ( onlineUpdateMode()
330 #if ALWAYS_SHOW_PATCHES_VIEW_IF_PATCHES_AVAILABLE
331  || ! zyppPool().empty<zypp::Patch>()
332 #endif
333  )
334  {
336  }
337 
338 
339  //
340  // Patterns view
341  //
342 
343  if ( ! zyppPool().empty<zypp::Pattern>() || testMode() )
344  {
345  _patternList = new YQPkgPatternList( parent, true );
346  YUI_CHECK_NEW( _patternList );
347  _filters->addPage( _( "Patter&ns" ), _patternList, "patterns" );
348 
349  connect( _patternList, SIGNAL( statusChanged() ),
350  this, SLOT ( autoResolveDependencies() ) );
351 
352  connect( this, SIGNAL( refresh() ),
353  _patternList, SLOT ( updateItemStates() ) );
354 
355  if ( _pkgConflictDialog )
356  {
357  connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
358  _patternList, SLOT ( updateItemStates() ) );
359  }
360  }
361 
362 
363  //
364  // PackageKit group view
365  //
366 
367  _packageKitGroupsFilterView = new YQPkgPackageKitGroupsFilterView( parent );
368  YUI_CHECK_NEW( _packageKitGroupsFilterView );
369  _filters->addPage( _( "Package &Groups" ), _packageKitGroupsFilterView, "package_groups" );
370 
371  connect( this, SIGNAL( loadData() ),
372  _packageKitGroupsFilterView, SLOT ( filter() ) );
373 
374 
375  //
376  // RPM group tags view
377  //
378 
379  _rpmGroupTagsFilterView = new YQPkgRpmGroupTagsFilterView( parent );
380  YUI_CHECK_NEW( _rpmGroupTagsFilterView );
381  _filters->addPage( _( "&RPM Groups" ), _rpmGroupTagsFilterView, "rpm_groups" );
382 
383  connect( this, SIGNAL( loadData() ),
384  _rpmGroupTagsFilterView, SLOT ( filter() ) );
385 
386 
387  //
388  // Languages view
389  //
390 
391  _langList = new YQPkgLangList( parent );
392  YUI_CHECK_NEW( _langList );
393 
394  _filters->addPage( _( "&Languages" ), _langList, "languages" );
395  _langList->setSizePolicy( QSizePolicy( QSizePolicy::Ignored, QSizePolicy::Ignored ) ); // hor/vert
396 
397  connect( _langList, SIGNAL( statusChanged() ),
398  this, SLOT ( autoResolveDependencies() ) );
399 
400  connect( this, SIGNAL( refresh() ),
401  _langList, SLOT ( updateItemStates() ) );
402 
403 
404  //
405  // Repository view
406  //
407 
408  _repoFilterView = new YQPkgRepoFilterView( parent );
409  YUI_CHECK_NEW( _repoFilterView );
410  _filters->addPage( _( "&Repositories" ), _repoFilterView, "repos" );
411  // hide and show the upgrade label when tabs change, or when the user
412  // selects repositories
413  connect(_repoFilterView, SIGNAL(filterStart()), this, SLOT(updateRepositoryUpgradeLabel()));
414  connect(this, SIGNAL(refresh()), this, SLOT(updateRepositoryUpgradeLabel()));
415  connect(_filters, &YQPkgFilterTab::currentChanged,
417 
418  // Services view - only if a service is present
420  {
421  _serviceFilterView = new YQPkgServiceFilterView( parent );
422  YUI_CHECK_NEW( _serviceFilterView );
423 
424  // TRANSLATORS: Menu item
425  _filters->addPage( _( "&Services" ), _serviceFilterView, "services" );
426  }
427 
428  //
429  // Package search view
430  //
431 
432  _searchFilterView = new YQPkgSearchFilterView( parent );
433  YUI_CHECK_NEW( _searchFilterView );
434  _filters->addPage( _( "S&earch" ), _searchFilterView, "search" );
435 
436 
437 
438 #if 0
439  // DEBUG
440 
441  _filters->addPage( _( "&Keywords" ), new QLabel( "Keywords\nfilter\n\nfor future use", this ), "keywords" );
442 #endif
443 
444  //
445  // Status change view
446  //
447 
448  _statusFilterView = new YQPkgStatusFilterView( parent );
449  YUI_CHECK_NEW( _statusFilterView );
450  _filters->addPage( _( "&Installation Summary" ), _statusFilterView, "inst_summary" );
451 }
452 
453 
454 YQPackageSelector::~YQPackageSelector()
455 {
456  saveSettings();
457 }
458 
459 QWidget *
460 YQPackageSelector::layoutRightPane( QWidget *parent )
461 {
462  QVBoxLayout *layout = new QVBoxLayout( parent );
463  YUI_CHECK_NEW( layout );
464  layout->setContentsMargins( SPLITTER_HALF_SPACING, // left
465  0, // top
466  0, // right
467  0 ); // bottom
468 
469  QSplitter * splitter = new QSplitter( Qt::Vertical, parent );
470  YUI_CHECK_NEW( splitter );
471  layout->addWidget(splitter);
472 
473  layoutPkgList( splitter );
474  layoutDetailsViews( splitter );
475  layoutButtons( parent );
476 
477  return parent;
478 }
479 
480 
481 void
482 YQPackageSelector::layoutPkgList( QWidget *parent )
483 {
484  // this is made visible when activating the repository
485  // filter
486  QWidget *_notificationsContainer = new QWidget(parent);
487  QVBoxLayout *layout = new QVBoxLayout(_notificationsContainer);
488 
489  _repoUpgradingLabel = new QLabel(_notificationsContainer);
490  _repoUpgradingLabel->setTextFormat(Qt::RichText);
491  _repoUpgradingLabel->setWordWrap(true);
492  _repoUpgradingLabel->setVisible(false);
493 
494  _repoUpgradeLabel = new QLabel(_notificationsContainer);
495  _repoUpgradeLabel->setTextFormat(Qt::RichText);
496  _repoUpgradeLabel->setWordWrap(true);
497  _repoUpgradeLabel->setVisible(false);
498  _repoUpgradeLabel->setObjectName( "RepoUpgradeLabel");
499 
500  layout->addWidget(_repoUpgradingLabel);
501  layout->addWidget(_repoUpgradeLabel);
502 
503  // if the user clicks on a link on the label, we have to check
504  // which repository upgrade job to add or remove, for that
505  // we will encode the links as repoupgradeadd://alias and
506  // repoupgraderemove:://alias
507  connect( _repoUpgradeLabel, SIGNAL( linkActivated ( QString ) ),
508  this, SLOT( slotRepoUpgradeLabelLinkClicked( QString ) ) );
509 
510  connect(_repoUpgradingLabel, SIGNAL( linkActivated( QString ) ),
511  this, SLOT( slotRepoUpgradeLabelLinkClicked( QString ) ) );
512 
514 
515  _pkgList= new YQPkgList( parent );
516  YUI_CHECK_NEW( _pkgList );
517 
518  connect( _pkgList, SIGNAL( statusChanged() ),
519  this, SLOT ( autoResolveDependencies() ) );
520 }
521 
522 void
523 YQPackageSelector::layoutDetailsViews( QWidget *parent )
524 {
525  bool haveInstalledPkgs = YQPkgList::haveInstalledPkgs();
526 
527 
528  _detailsViews = new QTabWidget( parent );
529  YUI_CHECK_NEW( _detailsViews );
530 
531  //
532  // Description
533  //
534 
535  _pkgDescriptionView = new YQPkgDescriptionView( _detailsViews, confirmUnsupported() );
536  YUI_CHECK_NEW( _pkgDescriptionView );
537 
538  _detailsViews->addTab( _pkgDescriptionView, _( "D&escription" ) );
539  _detailsViews->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
540 
541  connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
542  _pkgDescriptionView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
543 
544  //
545  // Technical details
546  //
547 
548  _pkgTechnicalDetailsView = new YQPkgTechnicalDetailsView( _detailsViews );
549  YUI_CHECK_NEW( _pkgTechnicalDetailsView );
550 
551  _detailsViews->addTab( _pkgTechnicalDetailsView, _( "&Technical Data" ) );
552 
553  connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
554  _pkgTechnicalDetailsView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
555 
556 
557  //
558  // Dependencies
559  //
560 
561  _pkgDependenciesView = new YQPkgDependenciesView( _detailsViews );
562  YUI_CHECK_NEW( _pkgDependenciesView );
563 
564  _detailsViews->addTab( _pkgDependenciesView, _( "Dependencies" ) );
565  _detailsViews->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
566 
567  connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
568  _pkgDependenciesView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
569 
570 
571 
572  //
573  // Versions
574  //
575 
576  _pkgVersionsView = new YQPkgVersionsView( _detailsViews );
577  YUI_CHECK_NEW( _pkgVersionsView );
578 
579  _detailsViews->addTab( _pkgVersionsView, _( "&Versions" ) );
580 
581  connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
582  _pkgVersionsView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
583 
584  connect( _pkgList, SIGNAL( statusChanged() ),
585  _pkgVersionsView, SIGNAL( statusChanged() ) );
586 
587 
588  //
589  // File List
590  //
591 
592  if ( haveInstalledPkgs ) // file list information is only available for installed pkgs
593  {
594  _pkgFileListView = new YQPkgFileListView( _detailsViews );
595  YUI_CHECK_NEW( _pkgFileListView );
596 
597  _detailsViews->addTab( _pkgFileListView, _( "File List" ) );
598  _detailsViews->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
599 
600  connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
601  _pkgFileListView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
602  }
603 
604 
605  //
606  // Change Log
607  //
608 
609  if ( haveInstalledPkgs ) // change log information is only available for installed pkgs
610  {
611  _pkgChangeLogView = new YQPkgChangeLogView( _detailsViews );
612  YUI_CHECK_NEW( _pkgChangeLogView );
613 
614  _detailsViews->addTab( _pkgChangeLogView, _( "Change Log" ) );
615  _detailsViews->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
616 
617  connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
618  _pkgChangeLogView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
619  }
620 }
621 
622 
623 void
624 YQPackageSelector::layoutButtons( QWidget *parent )
625 {
626  QWidget * button_box = new QWidget( parent );
627  YUI_CHECK_NEW( button_box );
628  parent->layout()->addWidget( button_box );
629 
630  QHBoxLayout * layout = new QHBoxLayout( button_box );
631  YUI_CHECK_NEW( layout );
632 
633  button_box->setLayout( layout );
634  layout->setContentsMargins( 2, // left
635  2, // top
636  2, // right
637  2 ); // bottom
638 
639  layout->addStretch();
640 
641  QPushButton * cancel_button = new QPushButton( _( "&Cancel" ), button_box );
642  YUI_CHECK_NEW( cancel_button );
643  layout->addWidget(cancel_button);
644 
645  cancel_button->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); // hor/vert
646 
647  connect( cancel_button, SIGNAL( clicked() ),
648  this, SLOT ( reject() ) );
649 
650 
651  QPushButton * accept_button = new QPushButton( _( "&Accept" ), button_box );
652  YUI_CHECK_NEW( accept_button );
653  layout->addWidget(accept_button);
654  accept_button->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); // hor/vert
655 
656  connect( accept_button, SIGNAL( clicked() ),
657  this, SLOT ( accept() ) );
658 
659  button_box->setFixedHeight( button_box->sizeHint().height() );
660 }
661 
662 
663 void
664 YQPackageSelector::layoutMenuBar( QWidget *parent )
665 {
666  _menuBar = new QMenuBar( parent );
667  YUI_CHECK_NEW( _menuBar );
668  parent->layout()->addWidget(_menuBar);
669 
670  _fileMenu = 0;
671  _optionsMenu = 0;
672  _pkgMenu = 0;
673  _patchMenu = 0;
674  _extrasMenu = 0;
675  _configMenu = 0;
676  _dependencyMenu = 0;
677  _helpMenu = 0;
678 
679 }
680 
681 
682 void
684 {
685 
686 
687  //
688  // File menu
689  //
690 
691  _fileMenu = new QMenu( _menuBar );
692  YUI_CHECK_NEW( _fileMenu );
693  QAction * action = _menuBar->addMenu( _fileMenu );
694  action->setText( _( "&File" ));
695 
696  _fileMenu->addAction( _( "&Import..." ), this, SLOT( pkgImport() ) );
697  _fileMenu->addAction( _( "&Export..." ), this, SLOT( pkgExport() ) );
698 
699  _fileMenu->addSeparator();
700 
701  _fileMenu->addAction( _( "E&xit -- Discard Changes" ), this, SLOT( reject() ) );
702  _fileMenu->addAction( _( "&Quit -- Save Changes" ), this, SLOT( accept() ) );
703 
704 
705  if ( _pkgList )
706  {
707  //
708  // Package menu
709  //
710 
711  _pkgMenu = new QMenu( _menuBar );
712  YUI_CHECK_NEW( _pkgMenu );
713  action = _menuBar->addMenu( _pkgMenu );
714  action->setText(_( "&Package" ));
715 
716  _pkgMenu->addAction(_pkgList->actionSetCurrentInstall);
717  _pkgMenu->addAction(_pkgList->actionSetCurrentDontInstall);
718  _pkgMenu->addAction(_pkgList->actionSetCurrentKeepInstalled);
719  _pkgMenu->addAction(_pkgList->actionSetCurrentDelete);
720  _pkgMenu->addAction(_pkgList->actionSetCurrentUpdate);
721  _pkgMenu->addAction(_pkgList->actionSetCurrentUpdateForce);
722  _pkgMenu->addAction(_pkgList->actionSetCurrentTaboo);
723  _pkgMenu->addAction(_pkgList->actionShowCurrentSolverInfo);
724 
725 #if ENABLE_SOURCE_RPMS
726  _pkgMenu->addSeparator();
727 
728  _pkgMenu->addAction(_pkgList->actionInstallSourceRpm);
729  _pkgMenu->addAction(_pkgList->actionDontInstallSourceRpm);
730 #endif
731 
732  _pkgMenu->addSeparator();
733  QMenu * submenu = _pkgList->addAllInListSubMenu( _pkgMenu );
734  YUI_CHECK_NEW( submenu );
735 
736 #if ENABLE_SOURCE_RPMS
737  submenu->addSeparator();
738 
739  _pkgMenu->addAction(_pkgList->actionInstallListSourceRpms);
740  _pkgMenu->addAction(_pkgList->actionDontInstallListSourceRpms);
741 #endif
742 
743  //
744  // Submenu for all packages
745  //
746 
747  submenu = new QMenu( _pkgMenu );
748  YUI_CHECK_NEW( submenu );
749 
750  // Translators: Unlike the "all in this list" submenu, this submenu
751  // refers to all packages globally, not only to those that are
752  // currently visible in the packages list.
753  action = _pkgMenu->addMenu( submenu );
754  action->setText(_( "All Packages" ));
755 
756  submenu->addAction( _( "Update if newer version available" ),
757  this, SLOT( globalUpdatePkg() ) );
758 
759  submenu->addAction( _( "Update unconditionally" ),
760  this, SLOT( globalUpdatePkgForce() ) );
761  }
762 
763 
764  if ( _patchList )
765  {
766  //
767  // Patch menu
768  //
769 
770  _patchMenu = new QMenu( _menuBar );
771  YUI_CHECK_NEW( _patchMenu );
772  action = _menuBar->addMenu( _patchMenu );
773  action->setText(_( "&Patch" ));
774 
775  _patchMenu->addAction(_patchList->actionSetCurrentInstall);
776  _patchMenu->addAction(_patchList->actionSetCurrentDontInstall);
777  _patchMenu->addAction(_patchList->actionSetCurrentKeepInstalled);
778 
779 #if ENABLE_DELETING_PATCHES
780  _patchMenu->addAction(_patchList->actionSetCurrentDelete);
781 #endif
782  _patchMenu->addAction(_patchList->actionSetCurrentUpdate);
783  _patchMenu->addAction(_patchList->actionSetCurrentUpdateForce);
784  _patchMenu->addAction(_patchList->actionSetCurrentTaboo);
785 
786  _patchMenu->addSeparator();
787  _patchList->addAllInListSubMenu( _patchMenu );
788  }
789 
790 
791  //
792  // Configuration menu
793  //
794 
795  if ( repoMgrEnabled() )
796  {
797  _configMenu = new QMenu( _menuBar );
798  YUI_CHECK_NEW( _configMenu );
799  action = _menuBar->addMenu( _configMenu );
800  action->setText(_( "Confi&guration" ));
801  _configMenu->addAction( _( "&Repositories..." ), this, SLOT( repoManager() ), Qt::CTRL + Qt::Key_R );
802  _configMenu->addAction( _( "&Online Update..." ), this, SLOT( onlineUpdateConfiguration() ), Qt::CTRL + Qt::Key_O );
803  }
804 
805  //
806  // Dependency menu
807  //
808 
809  _dependencyMenu = new QMenu( _menuBar );
810  YUI_CHECK_NEW( _dependencyMenu );
811  action = _menuBar->addMenu( _dependencyMenu );
812  action->setText(_( "&Dependencies" ));
813 
814  _dependencyMenu->addAction( _( "&Check Now" ), this, SLOT( manualResolvePackageDependencies() ) );
815 
816  _autoDependenciesAction = new QAction( _( "&Autocheck" ), this );
817  _autoDependenciesAction->setCheckable( true );
818  _dependencyMenu->addAction( _autoDependenciesAction );
819 
820  _installRecommendedAction = _dependencyMenu->addAction(
821  _("Install &Recommended Packages"),
822  this, SLOT (pkgInstallRecommendedChanged(bool)));
823  _installRecommendedAction->setCheckable( true );
824 
825 
826  //
827  // View menu
828  //
829 
830  _optionsMenu = new QMenu( _menuBar );
831  YUI_CHECK_NEW( _optionsMenu );
832  action = _menuBar->addMenu( _optionsMenu );
833  // Translators: Menu for view options (Use a noun, not a verb!)
834  action->setText(_( "&Options" ));
835 
836  // Translators: This is about packages ending in "-devel", so don't translate that "-devel"!
837  _showDevelAction = _optionsMenu->addAction( _( "Show -de&vel Packages" ),
838  this, SLOT( pkgExcludeDevelChanged( bool ) ), Qt::Key_F7 );
839  _showDevelAction->setCheckable(true);
840 
841  _excludeDevelPkgs = new YQPkgObjList::ExcludeRule( _pkgList, QRegExp( ".*(\\d+bit)?-devel(-\\d+bit)?$" ), _pkgList->nameCol() );
842  YUI_CHECK_NEW( _excludeDevelPkgs );
843  _excludeDevelPkgs->enable( false );
844 
845  // Translators: This is about packages ending in "-debuginfo", so don't translate that "-debuginfo"!
846  _showDebugAction = _optionsMenu->addAction( _( "Show -&debuginfo/-debugsource Packages" ),
847  this, SLOT( pkgExcludeDebugChanged( bool ) ), Qt::Key_F8 );
848  _showDebugAction->setCheckable(true);
849  _excludeDebugInfoPkgs = new YQPkgObjList::ExcludeRule( _pkgList, QRegExp( ".*(-\\d+bit)?-(debuginfo|debugsource)(-32bit)?$" ), _pkgList->nameCol() );
850  YUI_CHECK_NEW( _excludeDebugInfoPkgs );
851  _excludeDebugInfoPkgs->enable( false );
852 
853 
854  _verifySystemModeAction = _optionsMenu->addAction( _( "&System Verification Mode" ),
855  this, SLOT( pkgVerifySytemModeChanged( bool ) ) );
856  _verifySystemModeAction->setCheckable(true);
857 
858 
859  _cleanDepsOnRemoveAction = _optionsMenu->addAction( _( "&Cleanup when deleting packages" ),
860  this, SLOT( pkgCleanDepsOnRemoveChanged( bool ) ) );
861  _cleanDepsOnRemoveAction->setCheckable(true);
862 
863  _allowVendorChangeAction = _optionsMenu->addAction( _( "&Allow vendor change" ),
864  this, SLOT( pkgAllowVendorChangeChanged( bool ) ) );
865  _allowVendorChangeAction->setCheckable(true);
866 
867 
868 
869  //
870  // Extras menu
871  //
872 
873  _extrasMenu = new QMenu( _menuBar );
874  YUI_CHECK_NEW( _extrasMenu );
875  action = _menuBar->addMenu( _extrasMenu );
876  action->setText(_( "E&xtras" ));
877 
878  _extrasMenu->addAction( _( "Show &Products" ), this, SLOT( showProducts() ) );
879  _extrasMenu->addAction( _( "Show P&ackage Changes" ), this, SLOT( showAutoPkgList() ), Qt::CTRL + Qt::Key_A );
880  _extrasMenu->addAction( _( "Show &History" ), this, SLOT( showHistory() ) );
881 
882  _extrasMenu->addSeparator();
883 
884 #if BRAINDEAD_LIB_NAMING_SCHEME
885  // See bug #434042: libcddb2 vs. libcddb-devel
886 #else
887  // Translators: This is about packages ending in "-devel", so don't translate that "-devel"!
888  _extrasMenu->addAction( _( "Install All Matching -&devel Packages" ), this, SLOT( installDevelPkgs() ) );
889 #endif
890 
891  // Translators: This is about packages ending in "-debuginfo", so don't translate that "-debuginfo"!
892  _extrasMenu->addAction( _( "Install All Matching -de&buginfo Packages" ), this, SLOT( installDebugInfoPkgs() ) );
893 
894  // Translators: This is about packages ending in "-debugsource", so don't translate that "-debugsource"!
895  _extrasMenu->addAction( _( "Install All Matching -debug&source Packages" ), this, SLOT( installDebugSourcePkgs() ) );
896 
897  _extrasMenu->addAction( _( "Install All Matching &Recommended Packages" ),
898  this, SLOT( installRecommendedPkgs() ) );
899 
900  _extrasMenu->addSeparator();
901 
902  if ( _pkgConflictDialog )
903  _extrasMenu->addAction( _( "Generate Dependency Resolver &Test Case" ),
904  _pkgConflictDialog, SLOT( askCreateSolverTestCase() ) );
905 
906  if ( _actionResetIgnoredDependencyProblems )
907  _extrasMenu->addAction(_actionResetIgnoredDependencyProblems);
908 
909 #ifdef FIXME
910  if ( _patchList )
911  _extrasMenu->addAction(_patchList->actionShowRawPatchInfo);
912 #endif
913 
914 
915  //
916  // Help menu
917  //
918 
919  _helpMenu = new QMenu( _menuBar );
920  YUI_CHECK_NEW( _helpMenu );
921  _menuBar->addSeparator();
922  action = _menuBar->addMenu( _helpMenu );
923  action->setText(_( "&Help" ));
924 
925  // Note: The help functions and their texts are moved out
926  // to a separate source file YQPackageSelectorHelp.cc
927 
928  // Menu entry for help overview
929  _helpMenu->addAction( _( "&Overview" ), this, SLOT( help() ), Qt::Key_F1 );
930 
931  // Menu entry for help about used symbols ( icons )
932  _helpMenu->addAction( _( "&Symbols" ), this, SLOT( symbolHelp() ), Qt::SHIFT + Qt::Key_F1 );
933 
934  // Menu entry for keyboard help
935  _helpMenu->addAction( _( "&Keys" ), this, SLOT( keyboardHelp() ) );
936 }
937 
938 
939 void
941  QWidget * pkgList,
942  bool hasUpdateSignal )
943 {
944  if ( ! filter ) return;
945  if ( ! pkgList ) return;
946 
947  if ( _filters )
948  {
949  connect( _filters, SIGNAL( currentChanged(QWidget *) ),
950  filter, SLOT ( filterIfVisible() ) );
951  }
952 
953  connect( this, SIGNAL( refresh() ),
954  filter, SLOT ( filterIfVisible() ) );
955 
956  connect( filter, SIGNAL( filterStart() ),
957  pkgList, SLOT ( clear() ) );
958 
959  connect( filter, SIGNAL( filterStart() ),
960  this, SLOT ( busyCursor() ) );
961 
962  connect( filter, SIGNAL( filterMatch( ZyppSel, ZyppPkg ) ),
963  pkgList, SLOT ( addPkgItem ( ZyppSel, ZyppPkg ) ) );
964 
965  connect( filter, SIGNAL( filterFinished() ),
966  pkgList, SLOT ( resort() ) );
967 
968  connect( filter, SIGNAL( filterFinished() ),
969  pkgList, SLOT ( selectSomething() ) );
970 
971  connect( filter, SIGNAL( filterFinished() ),
972  pkgList, SLOT ( logExcludeStatistics() ) );
973 
974  connect( filter, SIGNAL( filterFinished() ),
975  pkgList, SLOT ( setFocus() ) );
976 
977  connect( filter, SIGNAL( filterFinished() ),
978  this, SLOT ( normalCursor() ) );
979 
980 
981  if ( hasUpdateSignal && _filters->diskUsageList() )
982  {
983  connect( filter, SIGNAL( updatePackages() ),
984  pkgList, SLOT ( updateItemStates() ) );
985 
986  if ( _filters->diskUsageList() )
987  {
988  connect( filter, SIGNAL( updatePackages() ),
989  _filters->diskUsageList(), SLOT ( updateDiskUsage() ) );
990  }
991  }
992 }
993 
994 
995 void
997 {
998  connectFilter( _updateProblemFilterView, _pkgList, false );
999  connectFilter( _patternList, _pkgList );
1000  connectFilter( _langList, _pkgList );
1001  connectFilter( _repoFilterView, _pkgList, false );
1002  connectFilter( _serviceFilterView, _pkgList, false );
1003  connectFilter( _packageKitGroupsFilterView, _pkgList, false );
1004  connectFilter( _rpmGroupTagsFilterView, _pkgList, false );
1005  connectFilter( _statusFilterView, _pkgList, false );
1006  connectFilter( _searchFilterView, _pkgList, false );
1007 
1008  // FIXME
1009  // connectFilter( _langList, _pkgList );
1010 
1011  if ( _searchFilterView && _pkgList )
1012  {
1013  connect( _searchFilterView, SIGNAL( message( const QString & ) ),
1014  _pkgList, SLOT ( message( const QString & ) ) );
1015  }
1016 
1017  if ( _repoFilterView && _pkgList )
1018  {
1019  connect( _repoFilterView, SIGNAL( filterNearMatch ( ZyppSel, ZyppPkg ) ),
1020  _pkgList, SLOT ( addPkgItemDimmed ( ZyppSel, ZyppPkg ) ) );
1021  }
1022 
1023  if ( _serviceFilterView && _pkgList )
1024  {
1025  connect( _serviceFilterView, SIGNAL( filterNearMatch ( ZyppSel, ZyppPkg ) ),
1026  _pkgList, SLOT ( addPkgItemDimmed ( ZyppSel, ZyppPkg ) ) );
1027  }
1028 
1029  if ( _pkgList && _filters->diskUsageList() )
1030  {
1031 
1032  connect( _pkgList, SIGNAL( statusChanged() ),
1033  _filters->diskUsageList(), SLOT ( updateDiskUsage() ) );
1034  }
1035 
1036  connectPatchList();
1037 
1038 
1039 
1040  //
1041  // Connect package conflict dialog
1042  //
1043 
1044  if ( _pkgConflictDialog )
1045  {
1046  if (_pkgList )
1047  {
1048  connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
1049  _pkgList, SLOT ( updateItemStates() ) );
1050  }
1051 
1052  if ( _patternList )
1053  {
1054  connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
1055  _patternList, SLOT ( updateItemStates() ) );
1056  }
1057 
1058 
1059  if ( _filters->diskUsageList() )
1060  {
1061  connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
1062  _filters->diskUsageList(), SLOT ( updateDiskUsage() ) );
1063  }
1064  }
1065 
1066 
1067  //
1068  // Connect package versions view
1069  //
1070 
1071  if ( _pkgVersionsView && _pkgList )
1072  {
1073  connect( _pkgVersionsView, SIGNAL( candidateChanged( ZyppObj ) ),
1074  _pkgList, SLOT ( updateItemData() ) );
1075 
1076  connect( _pkgVersionsView, SIGNAL( statusChanged() ),
1077  _pkgList, SLOT ( updateItemData() ) );
1078  }
1079 
1080 
1081  //
1082  // Hotkey to enable "patches" filter view on the fly
1083  //
1084 
1085  QShortcut * accel = new QShortcut( Qt::Key_F2, this, SLOT( hotkeyInsertPatchFilterView() ) );
1086  YUI_CHECK_NEW( accel );
1087 
1088  //
1089  // Update actions just before opening menus
1090  //
1091 
1092  if ( _pkgMenu && _pkgList )
1093  {
1094  connect( _pkgMenu, SIGNAL( aboutToShow() ),
1095  _pkgList, SLOT ( updateActions() ) );
1096  }
1097 
1098  if ( _patchMenu && _patchList )
1099  {
1100  connect( _patchMenu, SIGNAL( aboutToShow() ),
1101  _patchList, SLOT ( updateActions() ) );
1102  }
1103 }
1104 
1105 
1106 void
1108 {
1109  if ( _autoDependenciesAction && ! _autoDependenciesAction->isChecked() )
1110  return;
1111 
1113 }
1114 
1115 
1116 int
1118 {
1119  if ( ! _pkgConflictDialog )
1120  {
1121  yuiError() << "No package conflict dialog existing" << std::endl;
1122  return QDialog::Accepted;
1123  }
1124 
1125  busyCursor();
1126  int result = _pkgConflictDialog->solveAndShowConflicts();
1127  normalCursor();
1128 
1129 #if DEPENDENCY_FEEDBACK_IF_OK
1130 
1131  if ( result == QDialog::Accepted )
1132  {
1133  QMessageBox::information( this, "",
1134  _( "All package dependencies are OK." ),
1135  QMessageBox::Ok );
1136  }
1137 #endif
1138 
1139  return result;
1140 }
1141 
1142 
1143 void
1145 {
1146  if ( ! _patchFilterView )
1147  {
1148  _patchFilterView = new YQPkgPatchFilterView( this );
1149  YUI_CHECK_NEW( _patchFilterView );
1150  _filters->addPage( _( "P&atches" ), _patchFilterView, "patches" );
1151 
1152  _patchList = _patchFilterView->patchList();
1153  YUI_CHECK_PTR( _patchList );
1154 
1155  connectPatchList();
1156  }
1157 }
1158 
1159 
1160 void
1162 {
1163  if ( ! _patchFilterView )
1164  {
1165  yuiMilestone() << "Activating patches filter view" << std::endl;
1166 
1168  connectPatchList();
1169 
1170  _filters->showPage( _patchFilterView );
1171  _pkgList->clear();
1172  _patchList->filter();
1173  }
1174  else
1175  {
1176  _filters->showPage( _patchFilterView );
1177  }
1178 }
1179 
1180 
1181 void
1183 {
1184  if ( _pkgList && _patchList )
1185  {
1186  connectFilter( _patchList, _pkgList );
1187 
1188  connect( _patchList, SIGNAL( filterMatch ( const QString &, const QString &, FSize ) ),
1189  _pkgList, SLOT ( addPassiveItem( const QString &, const QString &, FSize ) ) );
1190 
1191  connect( _patchList, SIGNAL( statusChanged() ),
1192  this, SLOT ( autoResolveDependencies() ) );
1193 
1194  if ( _pkgConflictDialog )
1195  {
1196  connect( _pkgConflictDialog,SIGNAL( updatePackages() ),
1197  _patchList, SLOT ( updateItemStates() ) );
1198  }
1199 
1200  connect( this, SIGNAL( refresh() ),
1201  _patchList, SLOT ( updateItemStates() ) );
1202 
1203  }
1204 }
1205 
1206 
1207 void
1209 {
1210  QString filename = YQApplication::askForSaveFileName( QString( DEFAULT_EXPORT_FILE_NAME ), // startsWith
1211  QString( "*.xml;;*" ), // filter
1212  _( "Save Package List" ) );
1213 
1214  if ( ! filename.isEmpty() )
1215  {
1216  zypp::syscontent::Writer writer;
1217  const zypp::ResPool & pool = zypp::getZYpp()->pool();
1218 
1219  // The ZYPP obfuscated C++ contest proudly presents:
1220 
1221  for_each( pool.begin(), pool.end(),
1222  boost::bind( &zypp::syscontent::Writer::addIf,
1223  boost::ref( writer ),
1224  _1 ) );
1225  // Yuck. What a mess.
1226  //
1227  // Does anybody seriously believe this kind of thing is easier to read,
1228  // let alone use? Get real. This is an argument in favour of all C++
1229  // haters. And it's one that is really hard to counter.
1230  //
1231  // -sh 2006-12-13
1232 
1233  try
1234  {
1235  std::ofstream exportFile( toUTF8( filename ).c_str() );
1236  exportFile.exceptions( std::ios_base::badbit | std::ios_base::failbit );
1237  exportFile << writer;
1238 
1239  yuiMilestone() << "Package list exported to " << filename << std::endl;
1240  }
1241  catch ( std::exception & exception )
1242  {
1243  yuiWarning() << "Error exporting package list to " << filename << std::endl;
1244 
1245  // The export might have left over a partially written file.
1246  // Try to delete it. Don't care if it doesn't exist and unlink() fails.
1247  QFile::remove(filename);
1248 
1249  // Post error popup
1250  QMessageBox::warning( this, // parent
1251  _( "Error" ), // caption
1252  _( "Error exporting package list to %1" ).arg( filename ),
1253  QMessageBox::Ok | QMessageBox::Default, // button0
1254  Qt::NoButton, // button1
1255  Qt::NoButton ); // button2
1256  }
1257  }
1258 }
1259 
1260 
1261 void
1263 {
1264  QString filename = QFileDialog::getOpenFileName( this, _( "Load Package List" ), DEFAULT_EXPORT_FILE_NAME,
1265  "*.xml+;;*"// filter
1266  );
1267 
1268  if ( ! filename.isEmpty() )
1269  {
1270  yuiMilestone() << "Importing package list from " << filename << std::endl;
1271 
1272  try
1273  {
1274  std::ifstream importFile( toUTF8( filename ).c_str() );
1275  zypp::syscontent::Reader reader( importFile );
1276 
1277  //
1278  // Put reader contents into maps
1279  //
1280 
1281  typedef zypp::syscontent::Reader::Entry ZyppReaderEntry;
1282  typedef std::pair<string, ZyppReaderEntry> ImportMapPair;
1283 
1284  map<string, ZyppReaderEntry> importPkg;
1285  map<string, ZyppReaderEntry> importPatterns;
1286 
1287  for ( zypp::syscontent::Reader::const_iterator it = reader.begin();
1288  it != reader.end();
1289  ++ it )
1290  {
1291  string kind = it->kind();
1292 
1293  if ( kind == "package" ) importPkg.insert ( ImportMapPair( it->name(), *it ) );
1294  else if ( kind == "pattern" ) importPatterns.insert( ImportMapPair( it->name(), *it ) );
1295  }
1296 
1297  yuiDebug() << "Found " << importPkg.size()
1298  <<" packages and " << importPatterns.size()
1299  << " patterns in " << filename
1300  << std::endl;
1301 
1302 
1303  //
1304  // Set status of all patterns and packages according to import map
1305  //
1306 
1307  for ( ZyppPoolIterator it = zyppPatternsBegin();
1308  it != zyppPatternsEnd();
1309  ++it )
1310  {
1311  ZyppSel selectable = *it;
1312  importSelectable( *it, importPatterns.find( selectable->name() ) != importPatterns.end(), "pattern" );
1313  }
1314 
1315  for ( ZyppPoolIterator it = zyppPkgBegin();
1316  it != zyppPkgEnd();
1317  ++it )
1318  {
1319  ZyppSel selectable = *it;
1320  importSelectable( *it, importPkg.find( selectable->name() ) != importPkg.end(), "package" );
1321  }
1322 
1323 
1324  //
1325  // Display result
1326  //
1327 
1328  emit refresh();
1329 
1330  if ( _statusFilterView )
1331  {
1332  // Switch to "Installation Summary" filter view
1333 
1334  _filters->showPage( _statusFilterView );
1335  _statusFilterView->filter();
1336  }
1337 
1338  }
1339  catch ( const zypp::Exception & exception )
1340  {
1341  yuiWarning() << "Error reading package list from " << filename << std::endl;
1342 
1343  // Post error popup
1344  QMessageBox::warning( this, // parent
1345  _( "Error" ), // caption
1346  _( "Error loading package list from %1" ).arg( filename ),
1347  QMessageBox::Ok | QMessageBox::Default, // button0
1348  QMessageBox::NoButton, // button1
1349  QMessageBox::NoButton ); // button2
1350  }
1351  }
1352 }
1353 
1354 
1355 void
1357  bool isWanted,
1358  const char * kind )
1359 {
1360  ZyppStatus oldStatus = selectable->status();
1361  ZyppStatus newStatus = oldStatus;
1362 
1363  if ( isWanted )
1364  {
1365  //
1366  // Make sure this selectable does not get installed
1367  //
1368 
1369  switch ( oldStatus )
1370  {
1371  case S_Install:
1372  case S_AutoInstall:
1373  case S_KeepInstalled:
1374  case S_Protected:
1375  case S_Update:
1376  case S_AutoUpdate:
1377  newStatus = oldStatus;
1378  break;
1379 
1380  case S_Del:
1381  case S_AutoDel:
1382  newStatus = S_KeepInstalled;
1383  yuiDebug() << "Keeping " << kind << " " << selectable->name() << std::endl;
1384  break;
1385 
1386  case S_NoInst:
1387  case S_Taboo:
1388 
1389  if ( selectable->hasCandidateObj() )
1390  {
1391  newStatus = S_Install;
1392  yuiDebug() << "Adding " << kind << " " << selectable->name() << std::endl;
1393  }
1394  else
1395  {
1396  yuiDebug() << "Can't add " << kind << " " << selectable->name()
1397  << ": No candidate" << std::endl;
1398  }
1399  break;
1400  }
1401  }
1402  else // ! isWanted
1403  {
1404  //
1405  // Make sure this selectable does not get installed
1406  //
1407 
1408  switch ( oldStatus )
1409  {
1410  case S_Install:
1411  case S_AutoInstall:
1412  case S_KeepInstalled:
1413  case S_Protected:
1414  case S_Update:
1415  case S_AutoUpdate:
1416  newStatus = S_Del;
1417  yuiDebug() << "Deleting " << kind << " " << selectable->name() << std::endl;
1418  break;
1419 
1420  case S_Del:
1421  case S_AutoDel:
1422  case S_NoInst:
1423  case S_Taboo:
1424  newStatus = oldStatus;
1425  break;
1426  }
1427  }
1428 
1429  if ( oldStatus != newStatus )
1430  selectable->setStatus( newStatus );
1431 }
1432 
1433 
1434 void
1436 {
1437  if ( ! _pkgList )
1438  return;
1439 
1440  int count = _pkgList->globalSetPkgStatus( S_Update, force,
1441  true ); // countOnly
1442  yuiMilestone() << count << " pkgs found for update" << std::endl;
1443 
1444  if ( count >= GLOBAL_UPDATE_CONFIRMATION_THRESHOLD )
1445  {
1446  if ( QMessageBox::question( this, "", // caption
1447  // Translators: %1 is the number of affected packages
1448  _( "%1 packages will be updated" ).arg( count ),
1449  _( "&Continue" ), _( "C&ancel" ),
1450  0, // defaultButtonNumber (from 0)
1451  1 ) // escapeButtonNumber
1452  == 1 ) // "Cancel"?
1453  {
1454  return;
1455  }
1456  }
1457 
1458  (void) _pkgList->globalSetPkgStatus( S_Update, force,
1459  false ); // countOnly
1460 
1461  if ( _statusFilterView )
1462  {
1463  _filters->showPage( _statusFilterView );
1464  _statusFilterView->clear();
1465  _statusFilterView->showTransactions();
1466  _statusFilterView->filter();
1467  }
1468 }
1469 
1470 void
1472 {
1473  zypp::ResPool::repository_iterator it;
1474  _repoUpgradeLabel->setText("");
1475  _repoUpgradingLabel->setText("");
1476 
1477  // we iterate twice to show first the repo upgrades that
1478  // can be cancelled, and then the repo that can be added
1479  for ( it = zypp::getZYpp()->pool().knownRepositoriesBegin();
1480  it != zypp::getZYpp()->pool().knownRepositoriesEnd();
1481  ++it )
1482  {
1483  zypp::Repository repo(*it);
1484  // add the option to cancel the upgrade job against this
1485  // repository if there is a job for it
1486  if ( zypp::getZYpp()->resolver()->upgradingRepo(repo) )
1487  {
1488  _repoUpgradingLabel->setText(_repoUpgradingLabel->text() + _("<p><small><a href=\"repoupgraderemove:///%1\">Cancel switching</a> system packages to versions in repository %2</small></p>")
1489  .arg(fromUTF8(repo.alias().c_str()))
1490  .arg(fromUTF8(repo.name().c_str()))
1491  );
1492  }
1493  }
1494 
1495  for ( it = zypp::getZYpp()->pool().knownRepositoriesBegin();
1496  it != zypp::getZYpp()->pool().knownRepositoriesEnd();
1497  ++it )
1498  {
1499  zypp::Repository repo(*it);
1500  // add the option to upgrade to this repo packages if it is not the system
1501  // repository and there is no upgrade job in the solver for it
1502  // and the repo is the one selected right now
1503  if ( ! zypp::getZYpp()->resolver()->upgradingRepo(repo) &&
1504  ! repo.isSystemRepo() &&
1505  _repoFilterView->selectedRepo() == repo )
1506  {
1507  _repoUpgradeLabel->setText(_repoUpgradeLabel->text() + _("<p><a href=\"repoupgradeadd:///%1\">Switch system packages</a> to the versions in this repository (%2)</p>")
1508  .arg(fromUTF8(repo.alias().c_str()))
1509  .arg(fromUTF8(repo.name().c_str()))
1510  );
1511  }
1512  }
1513  _repoUpgradeLabel->setVisible(!_repoUpgradeLabel->text().isEmpty() &&
1514  _repoFilterView->isVisible() );
1515  _repoUpgradingLabel->setVisible(!_repoUpgradingLabel->text().isEmpty());
1516 }
1517 
1518 void
1520 {
1521  yuiDebug() << "link " << link << " clicked on label" << std::endl;
1522 
1523  QUrl url(link);
1524  if (url.scheme() == "repoupgradeadd")
1525  {
1526  yuiDebug() << "looking for repo " << url.path() << std::endl;
1527  std::string alias(url.path().remove(0,1).toStdString());
1528  zypp::Repository repo(zypp::getZYpp()->pool().reposFind(alias));
1529  yuiDebug() << repo << std::endl;
1530 
1531  if ( repo != zypp::Repository::noRepository )
1532  zypp::getZYpp()->resolver()->addUpgradeRepo(repo);
1533  }
1534  else if (url.scheme() == "repoupgraderemove")
1535  {
1536  std::string alias(url.path().remove(0,1).toStdString());
1537  zypp::Repository repo(zypp::getZYpp()->pool().reposFind(alias));
1538 
1539  if ( repo != zypp::Repository::noRepository )
1540  zypp::getZYpp()->resolver()->removeUpgradeRepo(repo);
1541  }
1542  else
1543  yuiDebug() << "unknown link operation " << url.scheme() << std::endl;
1544 
1546  emit refresh();
1547 }
1548 
1549 void
1551 {
1553 }
1554 
1555 
1556 void
1558 {
1560 }
1561 
1562 void
1564 {
1565  installSubPkgs( "-devel" );
1566 }
1567 
1568 
1569 void
1571 {
1572  installSubPkgs( "-debuginfo" );
1573 }
1574 
1575 
1576 void
1578 {
1579  installSubPkgs( "-debugsource" );
1580 }
1581 
1582 
1583 void
1585 {
1586  zypp::getZYpp()->resolver()->setIgnoreAlreadyRecommended( false );
1588 
1589  if ( _filters && _statusFilterView )
1590  {
1591  _filters->showPage( _statusFilterView );
1592  _statusFilterView->filter();
1593  }
1594 
1596  _( "Added Subpackages:" ),
1597  _( "&OK" ),
1598  QString::null, // rejectButtonLabel
1599  YQPkgChangesDialog::FilterAutomatic,
1600  YQPkgChangesDialog::OptionNone ); // showIfEmpty
1601 }
1602 
1603 
1604 void
1606 {
1607  if ( _optionsMenu && _pkgList )
1608  {
1609  if ( _excludeDebugInfoPkgs )
1610  _excludeDebugInfoPkgs->enable( ! on );
1611 
1612  _pkgList->applyExcludeRules();
1613  }
1614 }
1615 
1616 
1617 void
1618 YQPackageSelector::pkgExcludeDevelChanged( bool on )
1619 {
1620  if ( _optionsMenu && _pkgList )
1621  {
1622  if ( _excludeDevelPkgs )
1623  _excludeDevelPkgs->enable( ! on );
1624 
1625  _pkgList->applyExcludeRules();
1626  }
1627 }
1628 
1629 
1630 void
1631 YQPackageSelector::pkgVerifySytemModeChanged( bool on )
1632 {
1633  zypp::getZYpp()->resolver()->setSystemVerification( on );
1634 }
1635 
1636 void
1637 YQPackageSelector::pkgInstallRecommendedChanged( bool on )
1638 {
1639  zypp::getZYpp()->resolver()->setOnlyRequires( !on );
1641 }
1642 
1643 void
1644 YQPackageSelector::pkgCleanDepsOnRemoveChanged( bool on )
1645 {
1646  zypp::getZYpp()->resolver()->setCleandepsOnRemove( on );
1648 }
1649 
1650 
1651 void
1652 YQPackageSelector::pkgAllowVendorChangeChanged( bool on )
1653 {
1654  zypp::getZYpp()->resolver()->setAllowVendorChange( on );
1656 }
1657 
1658 
1659 
1660 void
1661 YQPackageSelector::installSubPkgs( const QString & suffix )
1662 {
1663  // Find all matching packages and put them into a QMap
1664 
1665  QMap<QString, ZyppSel> subPkgs;
1666 
1667  for ( ZyppPoolIterator it = zyppPkgBegin();
1668  it != zyppPkgEnd();
1669  ++it )
1670  {
1671  QString name = (*it)->name().c_str();
1672 
1673  if ( name.endsWith( suffix ) || name.endsWith( suffix + "-32bit" ) )
1674  {
1675  subPkgs[ name ] = *it;
1676 
1677  yuiDebug() << "Found subpackage: " << name << std::endl;
1678  }
1679  }
1680 
1681 
1682  // Now go through all packages and look if there is a corresponding subpackage in the QMap
1683 
1684  for ( ZyppPoolIterator it = zyppPkgBegin();
1685  it != zyppPkgEnd();
1686  ++it )
1687  {
1688  QString name = (*it)->name().c_str();
1689 
1690  if ( subPkgs.contains( name + suffix ) )
1691  {
1692  QString subPkgName( name + suffix );
1693  ZyppSel subPkg = subPkgs[ subPkgName ];
1694 
1695  switch ( (*it)->status() )
1696  {
1697  case S_AutoDel:
1698  case S_NoInst:
1699  case S_Protected:
1700  case S_Taboo:
1701  case S_Del:
1702  // Don't install the subpackage
1703  yuiMilestone() << "Ignoring unwanted subpackage " << subPkgName << std::endl;
1704  break;
1705 
1706  case S_AutoInstall:
1707  case S_Install:
1708  case S_KeepInstalled:
1709 
1710  // Install the subpackage, but don't try to update it
1711 
1712  if ( ! subPkg->installedObj() )
1713  {
1714  subPkg->setStatus( S_Install );
1715  yuiMilestone() << "Installing subpackage " << subPkgName << std::endl;
1716  }
1717  break;
1718 
1719 
1720  case S_Update:
1721  case S_AutoUpdate:
1722 
1723  // Install or update the subpackage
1724 
1725  if ( ! subPkg->installedObj() )
1726  {
1727  subPkg->setStatus( S_Install );
1728  yuiMilestone() << "Installing subpackage " << subPkgName << std::endl;
1729  }
1730  else
1731  {
1732  subPkg->setStatus( S_Update );
1733  yuiMilestone() << "Updating subpackage " << subPkgName << std::endl;
1734  }
1735  break;
1736 
1737  // Intentionally omitting 'default' branch so the compiler can
1738  // catch unhandled enum states
1739  }
1740  }
1741  }
1742 
1743 
1744  if ( _filters && _statusFilterView )
1745  {
1746  _filters->showPage( _statusFilterView );
1747  _statusFilterView->filter();
1748  }
1749 
1751  _( "Added Subpackages:" ),
1752  QRegExp( ".*" + suffix + "$" ),
1753  _( "&OK" ),
1754  QString::null, // rejectButtonLabel
1755  YQPkgChangesDialog::FilterAutomatic,
1756  YQPkgChangesDialog::OptionNone ); // showIfEmpty
1757 }
1758 
1759 void
1761 {
1762  QString settingsName = "YQPackageSelector";
1763  if ( onlineUpdateMode() ) settingsName = "YQOnlineUpdate";
1764  if ( updateMode() ) settingsName = "YQSystemUpdate";
1765 
1766  QSettings settings( QSettings::UserScope, SETTINGS_DIR, settingsName );
1767 
1768  _showDevelAction->setChecked(settings.value("Options/showDevelPackages", true).toBool());
1769  pkgExcludeDevelChanged(_showDevelAction->isChecked());
1770 
1771  _showDebugAction->setChecked(settings.value("Options/showDebugPackages", true).toBool());
1772  pkgExcludeDebugChanged(_showDebugAction->isChecked());
1773 
1774  loadCommonSettings();
1775 }
1776 
1777 void
1778 YQPackageSelector::loadCommonSettings()
1779 {
1780  map<string, string> sysconfig = zypp::base::sysconfig::read(PATH_TO_YAST_SYSCONFIG);
1781 
1782  bool auto_check = AUTO_CHECK_DEPENDENCIES_DEFAULT;
1783  auto it = sysconfig.find(OPTION_AUTO_CHECK);
1784  if (it != sysconfig.end())
1785  {
1786  auto_check = it->second == "yes";
1787  }
1788  _autoDependenciesAction->setChecked(auto_check);
1789 
1790  bool verify_system = zypp::getZYpp()->resolver()->systemVerification();
1791  it = sysconfig.find(OPTION_VERIFY);
1792  if (it != sysconfig.end())
1793  {
1794  verify_system = it->second == "yes";
1795  }
1796  _verifySystemModeAction->setChecked(verify_system);
1797  pkgVerifySytemModeChanged(verify_system);
1798 
1799  bool install_recommended = ! zypp::getZYpp()->resolver()->onlyRequires();
1800  it = sysconfig.find(OPTION_RECOMMENDED);
1801  if (it != sysconfig.end())
1802  {
1803  install_recommended = it->second == "yes";
1804  }
1805  _installRecommendedAction->setChecked(install_recommended);
1806  pkgInstallRecommendedChanged(install_recommended);
1807 
1808  bool allow_vendor_change = zypp::getZYpp()->resolver()->allowVendorChange();
1809  _allowVendorChangeAction->setChecked(allow_vendor_change);
1810  pkgAllowVendorChangeChanged(allow_vendor_change);
1811 
1812  bool clean_deps_on_remove = zypp::getZYpp()->resolver()->cleandepsOnRemove();
1813  _cleanDepsOnRemoveAction->setChecked(clean_deps_on_remove);
1814  pkgCleanDepsOnRemoveChanged(clean_deps_on_remove);
1815 }
1816 
1817 void
1819 {
1820  QString settingsName = "YQPackageSelector";
1821  if ( onlineUpdateMode() ) settingsName = "YQOnlineUpdate";
1822  if ( updateMode() ) settingsName = "YQSystemUpdate";
1823 
1824  QSettings settings( QSettings::UserScope, SETTINGS_DIR, settingsName );
1825 
1826  settings.setValue("Options/showDevelPackages", _showDevelAction->isChecked() );
1827  settings.setValue("Options/showDebugPackages", _showDebugAction->isChecked() );
1828 
1829  saveCommonSettings();
1830 }
1831 
1832 void
1833 YQPackageSelector::saveCommonSettings()
1834 {
1835  try
1836  {
1837  zypp::base::sysconfig::writeStringVal(
1838  PATH_TO_YAST_SYSCONFIG,
1839  OPTION_AUTO_CHECK,
1840  ( _autoDependenciesAction->isChecked() ? "yes" : "no"),
1841  "Automatic dependency checking");
1842  zypp::base::sysconfig::writeStringVal(
1843  PATH_TO_YAST_SYSCONFIG,
1844  OPTION_VERIFY,
1845  (_verifySystemModeAction->isChecked() ? "yes" : "no"),
1846  "System verification mode");
1847  zypp::base::sysconfig::writeStringVal(
1848  PATH_TO_YAST_SYSCONFIG,
1849  OPTION_RECOMMENDED,
1850  (_installRecommendedAction->isChecked() ? "yes" : "no"),
1851  "Install recommended packages");
1852  }
1853  catch( const std::exception &e )
1854  {
1855  yuiError() << "Writing " << PATH_TO_YAST_SYSCONFIG << " failed" << std::endl;
1856  }
1857 }
1858 
1860 {
1861  YQUI::ui()->busyCursor();
1862 }
1863 
1865 {
1866  YQUI::ui()->normalCursor();
1867 }
1868 
1869 
1870 #include "YQPackageSelector.moc"
Display the description of a ZyppObj derived object along with its name and summary.
void onlineUpdateConfiguration()
Close processing and request start of the online update configuration.
void addPatchFilterView()
Add the "Patches" filter view, if it is not already there.
void showPage(QWidget *page)
Show a page.
int globalSetPkgStatus(ZyppStatus newStatus, bool force, bool countOnly)
Set the status of all packages in the pool to a new value.
Definition: YQPkgList.cc:678
void loadData()
Emitted once (!) when the dialog is about to be shown, when all widgets are created and all signal/sl...
RPM group tags filter view: Display the RPM group tags tree and emit signals if any group tag is sele...
void globalUpdatePkg()
Set the status of all installed packages (all in the pool, not only those currently displayed in the ...
void connectFilter(QWidget *filter, QWidget *pkgList, bool hasUpdateSignal=true)
Connect a filter view that provides the usual signals with a package list.
void addPage(const QString &pageLabel, QWidget *pageContent, const QString &internalName)
Add a page with a user-visible "pageLabel", a widget with the page content and an internal name (or I...
void normalCursor()
Show the standard cursor (arrow)
zypp::Repository selectedRepo() const
Current selected repository, or if nothing is selected.
Filter view for PackageKit groups.
static bool any_service()
Is any enabled libzypp service present?
static int countEnabledRepositories()
Returns the number of enabled repositories.
YQPkgPatchList * patchList() const
Returns this view&#39;s selections list.
void showProducts()
Show all products in a popup dialog.
void busyCursor()
Show the busy cursor (clock)
Filter view for packages that made problems during update.
void filter()
Filter according to the view&#39;s rules and current selection.
Widget for "tabbed browsing" in packages:
static bool haveInstalledPkgs()
Returns &#39;true&#39; if there are any installed packages.
Definition: YQPkgList.cc:178
void importSelectable(ZyppSel selectable, bool isWanted, const char *kind)
Import one selectable: Set its status according to &#39;isWanted&#39; based on its old status.
void updateRepositoryUpgradeLabel()
hides or shows the repository upgrade message
YQPkgDiskUsageList * diskUsageList() const
Return the disk usage list widget or 0 if there is none.
QWidget * rightPane() const
Return the right pane.
void currentChanged(QWidget *newPageContent)
Emitted when the current page changes.
void saveSettings()
saves settings of the checkboxes in the option menu
int manualResolvePackageDependencies()
Resolve package dependencies manually.
void keyboardHelp()
Display online help about magic keys.
void enable(bool enable=true)
Enable or disable this exclude rule.
void accept()
Close processing and accept changes.
Display a list of zypp::Patch objects and ( below ) details about the currently selected patch...
void slotRepoUpgradeLabelLinkClicked(const QString &link)
a link in the repo upgrade label was clicked
void repoManager()
Close processing and request start of the repository manager.
Display a pkg&#39;s file list.
static std::string iconPath(const std::string &name, int size)
returns the full path for an icon of a given size
Display a list of zypp::Package objects.
Definition: YQPkgList.h:54
Display a list of zypp::Pattern objects.
Filter view for searching within packages.
void symbolHelp()
Display online help about symbols (package status icons).
void installDebugInfoPkgs()
Install available -debuginfo packages for packages that are installed or marked for installation...
void connectPatchList()
Connect the patch list.
Display technical details (very much like &#39;rpm -qi&#39;) for a ZYPP object - the installed instance...
void clear()
Clears the tree-widgets content, resets the optimal column width values.
Definition: YQPkgList.cc:432
void pkgExport()
Export all current selection/package states.
void applyExcludeRules()
Apply all exclude rules of this list to all items, including those that are currently excluded...
Filter view for packages that made problems during update.
void help()
Display (generic) online help.
Package version selector: Display a list of available versions from all the different installation so...
void autoResolveDependencies()
Automatically resolve package dependencies if desired (if the "auto check" checkbox is on)...
static bool haveProblematicPackages()
Check if there are any problematic packages at all, i.e.
void addMenus()
Add pulldown menus to the menu bar.
Display a list of zypp::Selection objects.
Definition: YQPkgLangList.h:52
void clear()
Reset all check boxes (set them all to "off")
void installDevelPkgs()
Install any -devel package for packages that are installed or marked for installation.
void loadSettings()
loads settings for the checkboxes in the option menu
static void showHistoryDialog(QWidget *parent=0)
Static convenience method: Post a History dialog for pkg &#39;pkgName&#39;.
A widget to display a libzypp servic filter view.
static bool showChangesDialog(QWidget *parent, const QString &message, const QString &acceptButtonLabel, const QString &rejectButtonLabel=QString::null, Filters f=FilterAutomatic, Options o=OptionAutoAcceptIfEmpty)
Static convenience method: Post a changes dialog with text &#39;message&#39;, a list of changed packages and ...
void showTransactions()
Set up the check boxes so all pending transactions are displayed.
void refresh()
Emitted when the internal data base might have changed and a refresh of all displayed data might be n...
virtual QMenu * addAllInListSubMenu(QMenu *menu)
Add a submenu "All in this list..." to &#39;menu&#39;.
void installDebugSourcePkgs()
Install available -debugsource packages for packages that are installed or marked for installation...
virtual QMenu * addAllInListSubMenu(QMenu *menu)
Add a submenu "All in this list..." to &#39;menu&#39;.
Definition: YQPkgList.cc:501
Abstract base class for package selectors.
static void showProductDialog(QWidget *parent=0)
Static convenience method: Post a dialog with all products.
void filter()
Filter according to the view&#39;s rules and current selection.
void hotkeyInsertPatchFilterView()
Add the "Patches" filter view upon hotkey (F2).
void installSubPkgs(const QString &suffix)
Install any subpackage that ends with &#39;suffix&#39; for packages that are installed or marked for installa...
void installRecommendedPkgs()
Install recommended packages for packages that are installed.
void makeConnections()
Establish Qt signal / slot connections.
Display technical details ( very much like &#39;rpm -qi&#39; ) for a zypp::Package object - the installed ins...
void showHistory()
Show dialog for pkgmgr history.
void showAutoPkgList()
Display a list of automatically selected packages (excluding packages contained in any selections tha...
void pkgImport()
Import selection/package states.
bool reject()
Close processing and abandon changes.
int resolveDependencies()
Resolve dependencies (unconditionally) for all resolvables.
void pkgExcludeDebugChanged(bool on)
Enable or disable the package exclude rules (show or suppress -debuginfo or -devel packages) accordin...
int solveAndShowConflicts()
Run the package dependency solver for the current package set and open the conflict dialog if there a...
void globalUpdatePkgForce()
Set the status of all installed packages (all in the pool, not only those currently displayed in the ...
Display a pkg&#39;s file list.