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