libyui-qt-pkg  2.45.19
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  {
335  addPatchFilterView();
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 
513  updateRepositoryUpgradeLabel();
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 
724 #if ENABLE_SOURCE_RPMS
725  _pkgMenu->addSeparator();
726 
727  _pkgMenu->addAction(_pkgList->actionInstallSourceRpm);
728  _pkgMenu->addAction(_pkgList->actionDontInstallSourceRpm);
729 #endif
730 
731  _pkgMenu->addSeparator();
732  QMenu * submenu = _pkgList->addAllInListSubMenu( _pkgMenu );
733  YUI_CHECK_NEW( submenu );
734 
735 #if ENABLE_SOURCE_RPMS
736  submenu->addSeparator();
737 
738  _pkgMenu->addAction(_pkgList->actionInstallListSourceRpms);
739  _pkgMenu->addAction(_pkgList->actionDontInstallListSourceRpms);
740 #endif
741 
742  //
743  // Submenu for all packages
744  //
745 
746  submenu = new QMenu( _pkgMenu );
747  YUI_CHECK_NEW( submenu );
748 
749  // Translators: Unlike the "all in this list" submenu, this submenu
750  // refers to all packages globally, not only to those that are
751  // currently visible in the packages list.
752  action = _pkgMenu->addMenu( submenu );
753  action->setText(_( "All Packages" ));
754 
755  submenu->addAction( _( "Update if newer version available" ),
756  this, SLOT( globalUpdatePkg() ) );
757 
758  submenu->addAction( _( "Update unconditionally" ),
759  this, SLOT( globalUpdatePkgForce() ) );
760  }
761 
762 
763  if ( _patchList )
764  {
765  //
766  // Patch menu
767  //
768 
769  _patchMenu = new QMenu( _menuBar );
770  YUI_CHECK_NEW( _patchMenu );
771  action = _menuBar->addMenu( _patchMenu );
772  action->setText(_( "&Patch" ));
773 
774  _patchMenu->addAction(_patchList->actionSetCurrentInstall);
775  _patchMenu->addAction(_patchList->actionSetCurrentDontInstall);
776  _patchMenu->addAction(_patchList->actionSetCurrentKeepInstalled);
777 
778 #if ENABLE_DELETING_PATCHES
779  _patchMenu->addAction(_patchList->actionSetCurrentDelete);
780 #endif
781  _patchMenu->addAction(_patchList->actionSetCurrentUpdate);
782  _patchMenu->addAction(_patchList->actionSetCurrentUpdateForce);
783  _patchMenu->addAction(_patchList->actionSetCurrentTaboo);
784 
785  _patchMenu->addSeparator();
786  _patchList->addAllInListSubMenu( _patchMenu );
787  }
788 
789 
790  //
791  // Configuration menu
792  //
793 
794  if ( repoMgrEnabled() )
795  {
796  _configMenu = new QMenu( _menuBar );
797  YUI_CHECK_NEW( _configMenu );
798  action = _menuBar->addMenu( _configMenu );
799  action->setText(_( "Confi&guration" ));
800  _configMenu->addAction( _( "&Repositories..." ), this, SLOT( repoManager() ), Qt::CTRL + Qt::Key_R );
801  _configMenu->addAction( _( "&Online Update..." ), this, SLOT( onlineUpdateConfiguration() ), Qt::CTRL + Qt::Key_O );
802  }
803 
804  //
805  // Dependency menu
806  //
807 
808  _dependencyMenu = new QMenu( _menuBar );
809  YUI_CHECK_NEW( _dependencyMenu );
810  action = _menuBar->addMenu( _dependencyMenu );
811  action->setText(_( "&Dependencies" ));
812 
813  _dependencyMenu->addAction( _( "&Check Now" ), this, SLOT( manualResolvePackageDependencies() ) );
814 
815  _autoDependenciesAction = new QAction( _( "&Autocheck" ), this );
816  _autoDependenciesAction->setCheckable( true );
817  _dependencyMenu->addAction( _autoDependenciesAction );
818 
819  _installRecommendedAction = _dependencyMenu->addAction(
820  _("Install &Recommended Packages"),
821  this, SLOT (pkgInstallRecommendedChanged(bool)));
822  _installRecommendedAction->setCheckable( true );
823 
824 
825  //
826  // View menu
827  //
828 
829  _optionsMenu = new QMenu( _menuBar );
830  YUI_CHECK_NEW( _optionsMenu );
831  action = _menuBar->addMenu( _optionsMenu );
832  // Translators: Menu for view options (Use a noun, not a verb!)
833  action->setText(_( "&Options" ));
834 
835  // Translators: This is about packages ending in "-devel", so don't translate that "-devel"!
836  _showDevelAction = _optionsMenu->addAction( _( "Show -de&vel Packages" ),
837  this, SLOT( pkgExcludeDevelChanged( bool ) ), Qt::Key_F7 );
838  _showDevelAction->setCheckable(true);
839 
840  _excludeDevelPkgs = new YQPkgObjList::ExcludeRule( _pkgList, QRegExp( ".*(\\d+bit)?-devel(-\\d+bit)?$" ), _pkgList->nameCol() );
841  YUI_CHECK_NEW( _excludeDevelPkgs );
842  _excludeDevelPkgs->enable( false );
843 
844  // Translators: This is about packages ending in "-debuginfo", so don't translate that "-debuginfo"!
845  _showDebugAction = _optionsMenu->addAction( _( "Show -&debuginfo/-debugsource Packages" ),
846  this, SLOT( pkgExcludeDebugChanged( bool ) ), Qt::Key_F8 );
847  _showDebugAction->setCheckable(true);
848  _excludeDebugInfoPkgs = new YQPkgObjList::ExcludeRule( _pkgList, QRegExp( ".*(-\\d+bit)?-(debuginfo|debugsource)(-32bit)?$" ), _pkgList->nameCol() );
849  YUI_CHECK_NEW( _excludeDebugInfoPkgs );
850  _excludeDebugInfoPkgs->enable( false );
851 
852 
853  _verifySystemModeAction = _optionsMenu->addAction( _( "&System Verification Mode" ),
854  this, SLOT( pkgVerifySytemModeChanged( bool ) ) );
855  _verifySystemModeAction->setCheckable(true);
856 
857 
858  _cleanDepsOnRemoveAction = _optionsMenu->addAction( _( "&Cleanup when deleting packages" ),
859  this, SLOT( pkgCleanDepsOnRemoveChanged( bool ) ) );
860  _cleanDepsOnRemoveAction->setCheckable(true);
861 
862  _allowVendorChangeAction = _optionsMenu->addAction( _( "&Allow vendor change" ),
863  this, SLOT( pkgAllowVendorChangeChanged( bool ) ) );
864  _allowVendorChangeAction->setCheckable(true);
865 
866 
867 
868  //
869  // Extras menu
870  //
871 
872  _extrasMenu = new QMenu( _menuBar );
873  YUI_CHECK_NEW( _extrasMenu );
874  action = _menuBar->addMenu( _extrasMenu );
875  action->setText(_( "E&xtras" ));
876 
877  _extrasMenu->addAction( _( "Show &Products" ), this, SLOT( showProducts() ) );
878  _extrasMenu->addAction( _( "Show P&ackage Changes" ), this, SLOT( showAutoPkgList() ), Qt::CTRL + Qt::Key_A );
879  _extrasMenu->addAction( _( "Show &History" ), this, SLOT( showHistory() ) );
880 
881  _extrasMenu->addSeparator();
882 
883 #if BRAINDEAD_LIB_NAMING_SCHEME
884  // See bug #434042: libcddb2 vs. libcddb-devel
885 #else
886  // Translators: This is about packages ending in "-devel", so don't translate that "-devel"!
887  _extrasMenu->addAction( _( "Install All Matching -&devel Packages" ), this, SLOT( installDevelPkgs() ) );
888 #endif
889 
890  // Translators: This is about packages ending in "-debuginfo", so don't translate that "-debuginfo"!
891  _extrasMenu->addAction( _( "Install All Matching -de&buginfo Packages" ), this, SLOT( installDebugInfoPkgs() ) );
892 
893  // Translators: This is about packages ending in "-debugsource", so don't translate that "-debugsource"!
894  _extrasMenu->addAction( _( "Install All Matching -debug&source Packages" ), this, SLOT( installDebugSourcePkgs() ) );
895 
896  _extrasMenu->addAction( _( "Install All Matching &Recommended Packages" ),
897  this, SLOT( installRecommendedPkgs() ) );
898 
899  _extrasMenu->addSeparator();
900 
901  if ( _pkgConflictDialog )
902  _extrasMenu->addAction( _( "Generate Dependency Resolver &Test Case" ),
903  _pkgConflictDialog, SLOT( askCreateSolverTestCase() ) );
904 
905  if ( _actionResetIgnoredDependencyProblems )
906  _extrasMenu->addAction(_actionResetIgnoredDependencyProblems);
907 
908 #ifdef FIXME
909  if ( _patchList )
910  _extrasMenu->addAction(_patchList->actionShowRawPatchInfo);
911 #endif
912 
913 
914  //
915  // Help menu
916  //
917 
918  _helpMenu = new QMenu( _menuBar );
919  YUI_CHECK_NEW( _helpMenu );
920  _menuBar->addSeparator();
921  action = _menuBar->addMenu( _helpMenu );
922  action->setText(_( "&Help" ));
923 
924  // Note: The help functions and their texts are moved out
925  // to a separate source file YQPackageSelectorHelp.cc
926 
927  // Menu entry for help overview
928  _helpMenu->addAction( _( "&Overview" ), this, SLOT( help() ), Qt::Key_F1 );
929 
930  // Menu entry for help about used symbols ( icons )
931  _helpMenu->addAction( _( "&Symbols" ), this, SLOT( symbolHelp() ), Qt::SHIFT + Qt::Key_F1 );
932 
933  // Menu entry for keyboard help
934  _helpMenu->addAction( _( "&Keys" ), this, SLOT( keyboardHelp() ) );
935 }
936 
937 
938 void
940  QWidget * pkgList,
941  bool hasUpdateSignal )
942 {
943  if ( ! filter ) return;
944  if ( ! pkgList ) return;
945 
946  if ( _filters )
947  {
948  connect( _filters, SIGNAL( currentChanged(QWidget *) ),
949  filter, SLOT ( filterIfVisible() ) );
950  }
951 
952  connect( this, SIGNAL( refresh() ),
953  filter, SLOT ( filterIfVisible() ) );
954 
955  connect( filter, SIGNAL( filterStart() ),
956  pkgList, SLOT ( clear() ) );
957 
958  connect( filter, SIGNAL( filterStart() ),
959  this, SLOT ( busyCursor() ) );
960 
961  connect( filter, SIGNAL( filterMatch( ZyppSel, ZyppPkg ) ),
962  pkgList, SLOT ( addPkgItem ( ZyppSel, ZyppPkg ) ) );
963 
964  connect( filter, SIGNAL( filterFinished() ),
965  pkgList, SLOT ( resort() ) );
966 
967  connect( filter, SIGNAL( filterFinished() ),
968  pkgList, SLOT ( selectSomething() ) );
969 
970  connect( filter, SIGNAL( filterFinished() ),
971  pkgList, SLOT ( logExcludeStatistics() ) );
972 
973  connect( filter, SIGNAL( filterFinished() ),
974  pkgList, SLOT ( setFocus() ) );
975 
976  connect( filter, SIGNAL( filterFinished() ),
977  this, SLOT ( normalCursor() ) );
978 
979 
980  if ( hasUpdateSignal && _filters->diskUsageList() )
981  {
982  connect( filter, SIGNAL( updatePackages() ),
983  pkgList, SLOT ( updateItemStates() ) );
984 
985  if ( _filters->diskUsageList() )
986  {
987  connect( filter, SIGNAL( updatePackages() ),
988  _filters->diskUsageList(), SLOT ( updateDiskUsage() ) );
989  }
990  }
991 }
992 
993 
994 void
996 {
997  connectFilter( _updateProblemFilterView, _pkgList, false );
998  connectFilter( _patternList, _pkgList );
999  connectFilter( _langList, _pkgList );
1000  connectFilter( _repoFilterView, _pkgList, false );
1001  connectFilter( _serviceFilterView, _pkgList, false );
1002  connectFilter( _packageKitGroupsFilterView, _pkgList, false );
1003  connectFilter( _rpmGroupTagsFilterView, _pkgList, false );
1004  connectFilter( _statusFilterView, _pkgList, false );
1005  connectFilter( _searchFilterView, _pkgList, false );
1006 
1007  // FIXME
1008  // connectFilter( _langList, _pkgList );
1009 
1010  if ( _searchFilterView && _pkgList )
1011  {
1012  connect( _searchFilterView, SIGNAL( message( const QString & ) ),
1013  _pkgList, SLOT ( message( const QString & ) ) );
1014  }
1015 
1016  if ( _repoFilterView && _pkgList )
1017  {
1018  connect( _repoFilterView, SIGNAL( filterNearMatch ( ZyppSel, ZyppPkg ) ),
1019  _pkgList, SLOT ( addPkgItemDimmed ( ZyppSel, ZyppPkg ) ) );
1020  }
1021 
1022  if ( _serviceFilterView && _pkgList )
1023  {
1024  connect( _serviceFilterView, SIGNAL( filterNearMatch ( ZyppSel, ZyppPkg ) ),
1025  _pkgList, SLOT ( addPkgItemDimmed ( ZyppSel, ZyppPkg ) ) );
1026  }
1027 
1028  if ( _pkgList && _filters->diskUsageList() )
1029  {
1030 
1031  connect( _pkgList, SIGNAL( statusChanged() ),
1032  _filters->diskUsageList(), SLOT ( updateDiskUsage() ) );
1033  }
1034 
1035  connectPatchList();
1036 
1037 
1038 
1039  //
1040  // Connect package conflict dialog
1041  //
1042 
1043  if ( _pkgConflictDialog )
1044  {
1045  if (_pkgList )
1046  {
1047  connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
1048  _pkgList, SLOT ( updateItemStates() ) );
1049  }
1050 
1051  if ( _patternList )
1052  {
1053  connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
1054  _patternList, SLOT ( updateItemStates() ) );
1055  }
1056 
1057 
1058  if ( _filters->diskUsageList() )
1059  {
1060  connect( _pkgConflictDialog, SIGNAL( updatePackages() ),
1061  _filters->diskUsageList(), SLOT ( updateDiskUsage() ) );
1062  }
1063  }
1064 
1065 
1066  //
1067  // Connect package versions view
1068  //
1069 
1070  if ( _pkgVersionsView && _pkgList )
1071  {
1072  connect( _pkgVersionsView, SIGNAL( candidateChanged( ZyppObj ) ),
1073  _pkgList, SLOT ( updateItemData() ) );
1074 
1075  connect( _pkgVersionsView, SIGNAL( statusChanged() ),
1076  _pkgList, SLOT ( updateItemData() ) );
1077  }
1078 
1079 
1080  //
1081  // Hotkey to enable "patches" filter view on the fly
1082  //
1083 
1084  QShortcut * accel = new QShortcut( Qt::Key_F2, this, SLOT( hotkeyInsertPatchFilterView() ) );
1085  YUI_CHECK_NEW( accel );
1086 
1087  //
1088  // Update actions just before opening menus
1089  //
1090 
1091  if ( _pkgMenu && _pkgList )
1092  {
1093  connect( _pkgMenu, SIGNAL( aboutToShow() ),
1094  _pkgList, SLOT ( updateActions() ) );
1095  }
1096 
1097  if ( _patchMenu && _patchList )
1098  {
1099  connect( _patchMenu, SIGNAL( aboutToShow() ),
1100  _patchList, SLOT ( updateActions() ) );
1101  }
1102 }
1103 
1104 
1105 void
1107 {
1108  if ( _autoDependenciesAction && ! _autoDependenciesAction->isChecked() )
1109  return;
1110 
1111  resolveDependencies();
1112 }
1113 
1114 
1115 int
1117 {
1118  if ( ! _pkgConflictDialog )
1119  {
1120  yuiError() << "No package conflict dialog existing" << std::endl;
1121  return QDialog::Accepted;
1122  }
1123 
1124  busyCursor();
1125  int result = _pkgConflictDialog->solveAndShowConflicts();
1126  normalCursor();
1127 
1128 #if DEPENDENCY_FEEDBACK_IF_OK
1129 
1130  if ( result == QDialog::Accepted )
1131  {
1132  QMessageBox::information( this, "",
1133  _( "All package dependencies are OK." ),
1134  QMessageBox::Ok );
1135  }
1136 #endif
1137 
1138  return result;
1139 }
1140 
1141 
1142 void
1144 {
1145  if ( ! _patchFilterView )
1146  {
1147  _patchFilterView = new YQPkgPatchFilterView( this );
1148  YUI_CHECK_NEW( _patchFilterView );
1149  _filters->addPage( _( "P&atches" ), _patchFilterView, "patches" );
1150 
1151  _patchList = _patchFilterView->patchList();
1152  YUI_CHECK_PTR( _patchList );
1153 
1154  connectPatchList();
1155  }
1156 }
1157 
1158 
1159 void
1161 {
1162  if ( ! _patchFilterView )
1163  {
1164  yuiMilestone() << "Activating patches filter view" << std::endl;
1165 
1166  addPatchFilterView();
1167  connectPatchList();
1168 
1169  _filters->showPage( _patchFilterView );
1170  _pkgList->clear();
1171  _patchList->filter();
1172  }
1173  else
1174  {
1175  _filters->showPage( _patchFilterView );
1176  }
1177 }
1178 
1179 
1180 void
1182 {
1183  if ( _pkgList && _patchList )
1184  {
1185  connectFilter( _patchList, _pkgList );
1186 
1187  connect( _patchList, SIGNAL( filterMatch ( const QString &, const QString &, FSize ) ),
1188  _pkgList, SLOT ( addPassiveItem( const QString &, const QString &, FSize ) ) );
1189 
1190  connect( _patchList, SIGNAL( statusChanged() ),
1191  this, SLOT ( autoResolveDependencies() ) );
1192 
1193  if ( _pkgConflictDialog )
1194  {
1195  connect( _pkgConflictDialog,SIGNAL( updatePackages() ),
1196  _patchList, SLOT ( updateItemStates() ) );
1197  }
1198 
1199  connect( this, SIGNAL( refresh() ),
1200  _patchList, SLOT ( updateItemStates() ) );
1201 
1202  }
1203 }
1204 
1205 
1206 void
1208 {
1209  QString filename = YQApplication::askForSaveFileName( QString( DEFAULT_EXPORT_FILE_NAME ), // startsWith
1210  QString( "*.xml;;*" ), // filter
1211  _( "Save Package List" ) );
1212 
1213  if ( ! filename.isEmpty() )
1214  {
1215  zypp::syscontent::Writer writer;
1216  const zypp::ResPool & pool = zypp::getZYpp()->pool();
1217 
1218  // The ZYPP obfuscated C++ contest proudly presents:
1219 
1220  for_each( pool.begin(), pool.end(),
1221  boost::bind( &zypp::syscontent::Writer::addIf,
1222  boost::ref( writer ),
1223  _1 ) );
1224  // Yuck. What a mess.
1225  //
1226  // Does anybody seriously believe this kind of thing is easier to read,
1227  // let alone use? Get real. This is an argument in favour of all C++
1228  // haters. And it's one that is really hard to counter.
1229  //
1230  // -sh 2006-12-13
1231 
1232  try
1233  {
1234  std::ofstream exportFile( toUTF8( filename ).c_str() );
1235  exportFile.exceptions( std::ios_base::badbit | std::ios_base::failbit );
1236  exportFile << writer;
1237 
1238  yuiMilestone() << "Package list exported to " << filename << std::endl;
1239  }
1240  catch ( std::exception & exception )
1241  {
1242  yuiWarning() << "Error exporting package list to " << filename << std::endl;
1243 
1244  // The export might have left over a partially written file.
1245  // Try to delete it. Don't care if it doesn't exist and unlink() fails.
1246  QFile::remove(filename);
1247 
1248  // Post error popup
1249  QMessageBox::warning( this, // parent
1250  _( "Error" ), // caption
1251  _( "Error exporting package list to %1" ).arg( filename ),
1252  QMessageBox::Ok | QMessageBox::Default, // button0
1253  Qt::NoButton, // button1
1254  Qt::NoButton ); // button2
1255  }
1256  }
1257 }
1258 
1259 
1260 void
1262 {
1263  QString filename = QFileDialog::getOpenFileName( this, _( "Load Package List" ), DEFAULT_EXPORT_FILE_NAME,
1264  "*.xml+;;*"// filter
1265  );
1266 
1267  if ( ! filename.isEmpty() )
1268  {
1269  yuiMilestone() << "Importing package list from " << filename << std::endl;
1270 
1271  try
1272  {
1273  std::ifstream importFile( toUTF8( filename ).c_str() );
1274  zypp::syscontent::Reader reader( importFile );
1275 
1276  //
1277  // Put reader contents into maps
1278  //
1279 
1280  typedef zypp::syscontent::Reader::Entry ZyppReaderEntry;
1281  typedef std::pair<string, ZyppReaderEntry> ImportMapPair;
1282 
1283  map<string, ZyppReaderEntry> importPkg;
1284  map<string, ZyppReaderEntry> importPatterns;
1285 
1286  for ( zypp::syscontent::Reader::const_iterator it = reader.begin();
1287  it != reader.end();
1288  ++ it )
1289  {
1290  string kind = it->kind();
1291 
1292  if ( kind == "package" ) importPkg.insert ( ImportMapPair( it->name(), *it ) );
1293  else if ( kind == "pattern" ) importPatterns.insert( ImportMapPair( it->name(), *it ) );
1294  }
1295 
1296  yuiDebug() << "Found " << importPkg.size()
1297  <<" packages and " << importPatterns.size()
1298  << " patterns in " << filename
1299  << std::endl;
1300 
1301 
1302  //
1303  // Set status of all patterns and packages according to import map
1304  //
1305 
1306  for ( ZyppPoolIterator it = zyppPatternsBegin();
1307  it != zyppPatternsEnd();
1308  ++it )
1309  {
1310  ZyppSel selectable = *it;
1311  importSelectable( *it, importPatterns.find( selectable->name() ) != importPatterns.end(), "pattern" );
1312  }
1313 
1314  for ( ZyppPoolIterator it = zyppPkgBegin();
1315  it != zyppPkgEnd();
1316  ++it )
1317  {
1318  ZyppSel selectable = *it;
1319  importSelectable( *it, importPkg.find( selectable->name() ) != importPkg.end(), "package" );
1320  }
1321 
1322 
1323  //
1324  // Display result
1325  //
1326 
1327  emit refresh();
1328 
1329  if ( _statusFilterView )
1330  {
1331  // Switch to "Installation Summary" filter view
1332 
1333  _filters->showPage( _statusFilterView );
1334  _statusFilterView->filter();
1335  }
1336 
1337  }
1338  catch ( const zypp::Exception & exception )
1339  {
1340  yuiWarning() << "Error reading package list from " << filename << std::endl;
1341 
1342  // Post error popup
1343  QMessageBox::warning( this, // parent
1344  _( "Error" ), // caption
1345  _( "Error loading package list from %1" ).arg( filename ),
1346  QMessageBox::Ok | QMessageBox::Default, // button0
1347  QMessageBox::NoButton, // button1
1348  QMessageBox::NoButton ); // button2
1349  }
1350  }
1351 }
1352 
1353 
1354 void
1356  bool isWanted,
1357  const char * kind )
1358 {
1359  ZyppStatus oldStatus = selectable->status();
1360  ZyppStatus newStatus = oldStatus;
1361 
1362  if ( isWanted )
1363  {
1364  //
1365  // Make sure this selectable does not get installed
1366  //
1367 
1368  switch ( oldStatus )
1369  {
1370  case S_Install:
1371  case S_AutoInstall:
1372  case S_KeepInstalled:
1373  case S_Protected:
1374  case S_Update:
1375  case S_AutoUpdate:
1376  newStatus = oldStatus;
1377  break;
1378 
1379  case S_Del:
1380  case S_AutoDel:
1381  newStatus = S_KeepInstalled;
1382  yuiDebug() << "Keeping " << kind << " " << selectable->name() << std::endl;
1383  break;
1384 
1385  case S_NoInst:
1386  case S_Taboo:
1387 
1388  if ( selectable->hasCandidateObj() )
1389  {
1390  newStatus = S_Install;
1391  yuiDebug() << "Adding " << kind << " " << selectable->name() << std::endl;
1392  }
1393  else
1394  {
1395  yuiDebug() << "Can't add " << kind << " " << selectable->name()
1396  << ": No candidate" << std::endl;
1397  }
1398  break;
1399  }
1400  }
1401  else // ! isWanted
1402  {
1403  //
1404  // Make sure this selectable does not get installed
1405  //
1406 
1407  switch ( oldStatus )
1408  {
1409  case S_Install:
1410  case S_AutoInstall:
1411  case S_KeepInstalled:
1412  case S_Protected:
1413  case S_Update:
1414  case S_AutoUpdate:
1415  newStatus = S_Del;
1416  yuiDebug() << "Deleting " << kind << " " << selectable->name() << std::endl;
1417  break;
1418 
1419  case S_Del:
1420  case S_AutoDel:
1421  case S_NoInst:
1422  case S_Taboo:
1423  newStatus = oldStatus;
1424  break;
1425  }
1426  }
1427 
1428  if ( oldStatus != newStatus )
1429  selectable->setStatus( newStatus );
1430 }
1431 
1432 
1433 void
1435 {
1436  if ( ! _pkgList )
1437  return;
1438 
1439  int count = _pkgList->globalSetPkgStatus( S_Update, force,
1440  true ); // countOnly
1441  yuiMilestone() << count << " pkgs found for update" << std::endl;
1442 
1443  if ( count >= GLOBAL_UPDATE_CONFIRMATION_THRESHOLD )
1444  {
1445  if ( QMessageBox::question( this, "", // caption
1446  // Translators: %1 is the number of affected packages
1447  _( "%1 packages will be updated" ).arg( count ),
1448  _( "&Continue" ), _( "C&ancel" ),
1449  0, // defaultButtonNumber (from 0)
1450  1 ) // escapeButtonNumber
1451  == 1 ) // "Cancel"?
1452  {
1453  return;
1454  }
1455  }
1456 
1457  (void) _pkgList->globalSetPkgStatus( S_Update, force,
1458  false ); // countOnly
1459 
1460  if ( _statusFilterView )
1461  {
1462  _filters->showPage( _statusFilterView );
1463  _statusFilterView->clear();
1464  _statusFilterView->showTransactions();
1465  _statusFilterView->filter();
1466  }
1467 }
1468 
1469 void
1471 {
1472  zypp::ResPool::repository_iterator it;
1473  _repoUpgradeLabel->setText("");
1474  _repoUpgradingLabel->setText("");
1475 
1476  // we iterate twice to show first the repo upgrades that
1477  // can be cancelled, and then the repo that can be added
1478  for ( it = zypp::getZYpp()->pool().knownRepositoriesBegin();
1479  it != zypp::getZYpp()->pool().knownRepositoriesEnd();
1480  ++it )
1481  {
1482  zypp::Repository repo(*it);
1483  // add the option to cancel the upgrade job against this
1484  // repository if there is a job for it
1485  if ( zypp::getZYpp()->resolver()->upgradingRepo(repo) )
1486  {
1487  _repoUpgradingLabel->setText(_repoUpgradingLabel->text() + _("<p><small><a href=\"repoupgraderemove:///%1\">Cancel switching</a> system packages to versions in repository %2</small></p>")
1488  .arg(fromUTF8(repo.alias().c_str()))
1489  .arg(fromUTF8(repo.name().c_str()))
1490  );
1491  }
1492  }
1493 
1494  for ( it = zypp::getZYpp()->pool().knownRepositoriesBegin();
1495  it != zypp::getZYpp()->pool().knownRepositoriesEnd();
1496  ++it )
1497  {
1498  zypp::Repository repo(*it);
1499  // add the option to upgrade to this repo packages if it is not the system
1500  // repository and there is no upgrade job in the solver for it
1501  // and the repo is the one selected right now
1502  if ( ! zypp::getZYpp()->resolver()->upgradingRepo(repo) &&
1503  ! repo.isSystemRepo() &&
1504  _repoFilterView->selectedRepo() == repo )
1505  {
1506  _repoUpgradeLabel->setText(_repoUpgradeLabel->text() + _("<p><a href=\"repoupgradeadd:///%1\">Switch system packages</a> to the versions in this repository (%2)</p>")
1507  .arg(fromUTF8(repo.alias().c_str()))
1508  .arg(fromUTF8(repo.name().c_str()))
1509  );
1510  }
1511  }
1512  _repoUpgradeLabel->setVisible(!_repoUpgradeLabel->text().isEmpty() &&
1513  _repoFilterView->isVisible() );
1514  _repoUpgradingLabel->setVisible(!_repoUpgradingLabel->text().isEmpty());
1515 }
1516 
1517 void
1519 {
1520  yuiDebug() << "link " << link << " clicked on label" << std::endl;
1521 
1522  QUrl url(link);
1523  if (url.scheme() == "repoupgradeadd")
1524  {
1525  yuiDebug() << "looking for repo " << url.path() << std::endl;
1526  std::string alias(url.path().remove(0,1).toStdString());
1527  zypp::Repository repo(zypp::getZYpp()->pool().reposFind(alias));
1528  yuiDebug() << repo << std::endl;
1529 
1530  if ( repo != zypp::Repository::noRepository )
1531  zypp::getZYpp()->resolver()->addUpgradeRepo(repo);
1532  }
1533  else if (url.scheme() == "repoupgraderemove")
1534  {
1535  std::string alias(url.path().remove(0,1).toStdString());
1536  zypp::Repository repo(zypp::getZYpp()->pool().reposFind(alias));
1537 
1538  if ( repo != zypp::Repository::noRepository )
1539  zypp::getZYpp()->resolver()->removeUpgradeRepo(repo);
1540  }
1541  else
1542  yuiDebug() << "unknown link operation " << url.scheme() << std::endl;
1543 
1544  resolveDependencies();
1545  emit refresh();
1546 }
1547 
1548 void
1550 {
1552 }
1553 
1554 
1555 void
1557 {
1559 }
1560 
1561 void
1563 {
1564  installSubPkgs( "-devel" );
1565 }
1566 
1567 
1568 void
1570 {
1571  installSubPkgs( "-debuginfo" );
1572 }
1573 
1574 
1575 void
1577 {
1578  installSubPkgs( "-debugsource" );
1579 }
1580 
1581 
1582 void
1584 {
1585  zypp::getZYpp()->resolver()->setIgnoreAlreadyRecommended( false );
1586  resolveDependencies();
1587 
1588  if ( _filters && _statusFilterView )
1589  {
1590  _filters->showPage( _statusFilterView );
1591  _statusFilterView->filter();
1592  }
1593 
1595  _( "Added Subpackages:" ),
1596  _( "&OK" ),
1597  QString::null, // rejectButtonLabel
1598  YQPkgChangesDialog::FilterAutomatic,
1599  YQPkgChangesDialog::OptionNone ); // showIfEmpty
1600 }
1601 
1602 
1603 void
1605 {
1606  if ( _optionsMenu && _pkgList )
1607  {
1608  if ( _excludeDebugInfoPkgs )
1609  _excludeDebugInfoPkgs->enable( ! on );
1610 
1611  _pkgList->applyExcludeRules();
1612  }
1613 }
1614 
1615 
1616 void
1617 YQPackageSelector::pkgExcludeDevelChanged( bool on )
1618 {
1619  if ( _optionsMenu && _pkgList )
1620  {
1621  if ( _excludeDevelPkgs )
1622  _excludeDevelPkgs->enable( ! on );
1623 
1624  _pkgList->applyExcludeRules();
1625  }
1626 }
1627 
1628 
1629 void
1630 YQPackageSelector::pkgVerifySytemModeChanged( bool on )
1631 {
1632  zypp::getZYpp()->resolver()->setSystemVerification( on );
1633 }
1634 
1635 void
1636 YQPackageSelector::pkgInstallRecommendedChanged( bool on )
1637 {
1638  zypp::getZYpp()->resolver()->setOnlyRequires( !on );
1639  resolveDependencies();
1640 }
1641 
1642 void
1643 YQPackageSelector::pkgCleanDepsOnRemoveChanged( bool on )
1644 {
1645  zypp::getZYpp()->resolver()->setCleandepsOnRemove( on );
1646  resolveDependencies();
1647 }
1648 
1649 
1650 void
1651 YQPackageSelector::pkgAllowVendorChangeChanged( bool on )
1652 {
1653  zypp::getZYpp()->resolver()->setAllowVendorChange( on );
1654  resolveDependencies();
1655 }
1656 
1657 
1658 
1659 void
1660 YQPackageSelector::installSubPkgs( const QString & suffix )
1661 {
1662  // Find all matching packages and put them into a QMap
1663 
1664  QMap<QString, ZyppSel> subPkgs;
1665 
1666  for ( ZyppPoolIterator it = zyppPkgBegin();
1667  it != zyppPkgEnd();
1668  ++it )
1669  {
1670  QString name = (*it)->name().c_str();
1671 
1672  if ( name.endsWith( suffix ) || name.endsWith( suffix + "-32bit" ) )
1673  {
1674  subPkgs[ name ] = *it;
1675 
1676  yuiDebug() << "Found subpackage: " << name << std::endl;
1677  }
1678  }
1679 
1680 
1681  // Now go through all packages and look if there is a corresponding subpackage in the QMap
1682 
1683  for ( ZyppPoolIterator it = zyppPkgBegin();
1684  it != zyppPkgEnd();
1685  ++it )
1686  {
1687  QString name = (*it)->name().c_str();
1688 
1689  if ( subPkgs.contains( name + suffix ) )
1690  {
1691  QString subPkgName( name + suffix );
1692  ZyppSel subPkg = subPkgs[ subPkgName ];
1693 
1694  switch ( (*it)->status() )
1695  {
1696  case S_AutoDel:
1697  case S_NoInst:
1698  case S_Protected:
1699  case S_Taboo:
1700  case S_Del:
1701  // Don't install the subpackage
1702  yuiMilestone() << "Ignoring unwanted subpackage " << subPkgName << std::endl;
1703  break;
1704 
1705  case S_AutoInstall:
1706  case S_Install:
1707  case S_KeepInstalled:
1708 
1709  // Install the subpackage, but don't try to update it
1710 
1711  if ( ! subPkg->installedObj() )
1712  {
1713  subPkg->setStatus( S_Install );
1714  yuiMilestone() << "Installing subpackage " << subPkgName << std::endl;
1715  }
1716  break;
1717 
1718 
1719  case S_Update:
1720  case S_AutoUpdate:
1721 
1722  // Install or update the subpackage
1723 
1724  if ( ! subPkg->installedObj() )
1725  {
1726  subPkg->setStatus( S_Install );
1727  yuiMilestone() << "Installing subpackage " << subPkgName << std::endl;
1728  }
1729  else
1730  {
1731  subPkg->setStatus( S_Update );
1732  yuiMilestone() << "Updating subpackage " << subPkgName << std::endl;
1733  }
1734  break;
1735 
1736  // Intentionally omitting 'default' branch so the compiler can
1737  // catch unhandled enum states
1738  }
1739  }
1740  }
1741 
1742 
1743  if ( _filters && _statusFilterView )
1744  {
1745  _filters->showPage( _statusFilterView );
1746  _statusFilterView->filter();
1747  }
1748 
1750  _( "Added Subpackages:" ),
1751  QRegExp( ".*" + suffix + "$" ),
1752  _( "&OK" ),
1753  QString::null, // rejectButtonLabel
1754  YQPkgChangesDialog::FilterAutomatic,
1755  YQPkgChangesDialog::OptionNone ); // showIfEmpty
1756 }
1757 
1758 void
1760 {
1761  QString settingsName = "YQPackageSelector";
1762  if ( onlineUpdateMode() ) settingsName = "YQOnlineUpdate";
1763  if ( updateMode() ) settingsName = "YQSystemUpdate";
1764 
1765  QSettings settings( QSettings::UserScope, SETTINGS_DIR, settingsName );
1766 
1767  _showDevelAction->setChecked(settings.value("Options/showDevelPackages", true).toBool());
1768  pkgExcludeDevelChanged(_showDevelAction->isChecked());
1769 
1770  _showDebugAction->setChecked(settings.value("Options/showDebugPackages", true).toBool());
1771  pkgExcludeDebugChanged(_showDebugAction->isChecked());
1772 
1773  loadCommonSettings();
1774 }
1775 
1776 void
1777 YQPackageSelector::loadCommonSettings()
1778 {
1779  map<string, string> sysconfig = zypp::base::sysconfig::read(PATH_TO_YAST_SYSCONFIG);
1780 
1781  bool auto_check = AUTO_CHECK_DEPENDENCIES_DEFAULT;
1782  auto it = sysconfig.find(OPTION_AUTO_CHECK);
1783  if (it != sysconfig.end())
1784  {
1785  auto_check = it->second == "yes";
1786  }
1787  _autoDependenciesAction->setChecked(auto_check);
1788 
1789  bool verify_system = zypp::getZYpp()->resolver()->systemVerification();
1790  it = sysconfig.find(OPTION_VERIFY);
1791  if (it != sysconfig.end())
1792  {
1793  verify_system = it->second == "yes";
1794  }
1795  _verifySystemModeAction->setChecked(verify_system);
1796  pkgVerifySytemModeChanged(verify_system);
1797 
1798  bool install_recommended = ! zypp::getZYpp()->resolver()->onlyRequires();
1799  it = sysconfig.find(OPTION_RECOMMENDED);
1800  if (it != sysconfig.end())
1801  {
1802  install_recommended = it->second == "yes";
1803  }
1804  _installRecommendedAction->setChecked(install_recommended);
1805  pkgInstallRecommendedChanged(install_recommended);
1806 
1807  bool allow_vendor_change = zypp::getZYpp()->resolver()->allowVendorChange();
1808  _allowVendorChangeAction->setChecked(allow_vendor_change);
1809  pkgAllowVendorChangeChanged(allow_vendor_change);
1810 
1811  bool clean_deps_on_remove = zypp::getZYpp()->resolver()->cleandepsOnRemove();
1812  _cleanDepsOnRemoveAction->setChecked(clean_deps_on_remove);
1813  pkgCleanDepsOnRemoveChanged(clean_deps_on_remove);
1814 }
1815 
1816 void
1818 {
1819  QString settingsName = "YQPackageSelector";
1820  if ( onlineUpdateMode() ) settingsName = "YQOnlineUpdate";
1821  if ( updateMode() ) settingsName = "YQSystemUpdate";
1822 
1823  QSettings settings( QSettings::UserScope, SETTINGS_DIR, settingsName );
1824 
1825  settings.setValue("Options/showDevelPackages", _showDevelAction->isChecked() );
1826  settings.setValue("Options/showDebugPackages", _showDebugAction->isChecked() );
1827 
1828  saveCommonSettings();
1829 }
1830 
1831 void
1832 YQPackageSelector::saveCommonSettings()
1833 {
1834  try
1835  {
1836  zypp::base::sysconfig::writeStringVal(
1837  PATH_TO_YAST_SYSCONFIG,
1838  OPTION_AUTO_CHECK,
1839  ( _autoDependenciesAction->isChecked() ? "yes" : "no"),
1840  "Automatic dependency checking");
1841  zypp::base::sysconfig::writeStringVal(
1842  PATH_TO_YAST_SYSCONFIG,
1843  OPTION_VERIFY,
1844  (_verifySystemModeAction->isChecked() ? "yes" : "no"),
1845  "System verification mode");
1846  zypp::base::sysconfig::writeStringVal(
1847  PATH_TO_YAST_SYSCONFIG,
1848  OPTION_RECOMMENDED,
1849  (_installRecommendedAction->isChecked() ? "yes" : "no"),
1850  "Install recommended packages");
1851  }
1852  catch( const std::exception &e )
1853  {
1854  yuiError() << "Writing " << PATH_TO_YAST_SYSCONFIG << " failed" << std::endl;
1855  }
1856 }
1857 
1859 {
1860  YQUI::ui()->busyCursor();
1861 }
1862 
1864 {
1865  YQUI::ui()->normalCursor();
1866 }
1867 
1868 
1869 #include "YQPackageSelector.moc"
Display the description of a ZyppObj derived object along with its name and summary.
void addPatchFilterView()
Add the "Patches" filter view, if it is not already there.
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 normalCursor()
Show the standard cursor (arrow)
Filter view for PackageKit groups.
static bool any_service()
Is any enabled libzypp service present?
static int countEnabledRepositories()
Returns the number of enabled repositories.
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.
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
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.
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
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 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 pkgExport()
Export all current selection/package states.
Filter view for packages that made problems during update.
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 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 installDebugSourcePkgs()
Install available -debugsource packages for packages that are installed or marked for installation...
Abstract base class for package selectors.
static void showProductDialog(QWidget *parent=0)
Static convenience method: Post a dialog with all products.
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 pkgImport()
Import selection/package states.
void pkgExcludeDebugChanged(bool on)
Enable or disable the package exclude rules (show or suppress -debuginfo or -devel packages) accordin...
Display a pkg&#39;s file list.