libyui-qt-pkg  2.44.7
 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, &YQPkgFilterTab::currentChanged,
412 
413  //
414  // Package search view
415  //
416 
417  _searchFilterView = new YQPkgSearchFilterView( parent );
418  YUI_CHECK_NEW( _searchFilterView );
419  _filters->addPage( _( "S&earch" ), _searchFilterView, "search" );
420 
421 
422 
423 #if 0
424  // DEBUG
425 
426  _filters->addPage( _( "&Keywords" ), new QLabel( "Keywords\nfilter\n\nfor future use", this ), "keywords" );
427 #endif
428 
429  //
430  // Status change view
431  //
432 
433  _statusFilterView = new YQPkgStatusFilterView( parent );
434  YUI_CHECK_NEW( _statusFilterView );
435  _filters->addPage( _( "&Installation Summary" ), _statusFilterView, "inst_summary" );
436 }
437 
438 
439 YQPackageSelector::~YQPackageSelector()
440 {
441  saveSettings();
442 }
443 
444 QWidget *
445 YQPackageSelector::layoutRightPane( QWidget *parent )
446 {
447  QVBoxLayout *layout = new QVBoxLayout( parent );
448  YUI_CHECK_NEW( layout );
449  layout->setContentsMargins( SPLITTER_HALF_SPACING, // left
450  0, // top
451  0, // right
452  0 ); // bottom
453 
454  QSplitter * splitter = new QSplitter( Qt::Vertical, parent );
455  YUI_CHECK_NEW( splitter );
456  layout->addWidget(splitter);
457 
458  layoutPkgList( splitter );
459  layoutDetailsViews( splitter );
460  layoutButtons( parent );
461 
462  return parent;
463 }
464 
465 
466 void
467 YQPackageSelector::layoutPkgList( QWidget *parent )
468 {
469  // this is made visible when activating the repository
470  // filter
471  QWidget *_notificationsContainer = new QWidget(parent);
472  QVBoxLayout *layout = new QVBoxLayout(_notificationsContainer);
473 
474  _repoUpgradingLabel = new QLabel(_notificationsContainer);
475  _repoUpgradingLabel->setTextFormat(Qt::RichText);
476  _repoUpgradingLabel->setWordWrap(true);
477  _repoUpgradingLabel->setVisible(false);
478 
479  _repoUpgradeLabel = new QLabel(_notificationsContainer);
480  _repoUpgradeLabel->setTextFormat(Qt::RichText);
481  _repoUpgradeLabel->setWordWrap(true);
482  _repoUpgradeLabel->setVisible(false);
483  _repoUpgradeLabel->setObjectName( "RepoUpgradeLabel");
484 
485  layout->addWidget(_repoUpgradingLabel);
486  layout->addWidget(_repoUpgradeLabel);
487 
488  // if the user clicks on a link on the label, we have to check
489  // which repository upgrade job to add or remove, for that
490  // we will encode the links as repoupgradeadd://alias and
491  // repoupgraderemove:://alias
492  connect(_repoUpgradeLabel, SIGNAL(linkActivated(const QString &)), this, SLOT(slotRepoUpgradeLabelLinkClicked(const QString &)));
493  connect(_repoUpgradingLabel, SIGNAL(linkActivated(const QString &)), this, SLOT(slotRepoUpgradeLabelLinkClicked(const QString &)));
494 
496 
497  _pkgList= new YQPkgList( parent );
498  YUI_CHECK_NEW( _pkgList );
499 
500  connect( _pkgList, SIGNAL( statusChanged() ),
501  this, SLOT ( autoResolveDependencies() ) );
502 }
503 
504 void
505 YQPackageSelector::layoutDetailsViews( QWidget *parent )
506 {
507  bool haveInstalledPkgs = YQPkgList::haveInstalledPkgs();
508 
509 
510  _detailsViews = new QTabWidget( parent );
511  YUI_CHECK_NEW( _detailsViews );
512 
513  //
514  // Description
515  //
516 
517  _pkgDescriptionView = new YQPkgDescriptionView( _detailsViews, confirmUnsupported() );
518  YUI_CHECK_NEW( _pkgDescriptionView );
519 
520  _detailsViews->addTab( _pkgDescriptionView, _( "D&escription" ) );
521  _detailsViews->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
522 
523  connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
524  _pkgDescriptionView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
525 
526  //
527  // Technical details
528  //
529 
530  _pkgTechnicalDetailsView = new YQPkgTechnicalDetailsView( _detailsViews );
531  YUI_CHECK_NEW( _pkgTechnicalDetailsView );
532 
533  _detailsViews->addTab( _pkgTechnicalDetailsView, _( "&Technical Data" ) );
534 
535  connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
536  _pkgTechnicalDetailsView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
537 
538 
539  //
540  // Dependencies
541  //
542 
543  _pkgDependenciesView = new YQPkgDependenciesView( _detailsViews );
544  YUI_CHECK_NEW( _pkgDependenciesView );
545 
546  _detailsViews->addTab( _pkgDependenciesView, _( "Dependencies" ) );
547  _detailsViews->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
548 
549  connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
550  _pkgDependenciesView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
551 
552 
553 
554  //
555  // Versions
556  //
557 
558  _pkgVersionsView = new YQPkgVersionsView( _detailsViews,
559  true ); // userCanSwitchVersions
560  YUI_CHECK_NEW( _pkgVersionsView );
561 
562  _detailsViews->addTab( _pkgVersionsView, _( "&Versions" ) );
563 
564  connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
565  _pkgVersionsView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
566 
567  connect( _pkgList, SIGNAL( statusChanged() ),
568  _pkgVersionsView, SLOT ( slotRefreshDetails() ) );
569 
570 
571  //
572  // File List
573  //
574 
575  if ( haveInstalledPkgs ) // file list information is only available for installed pkgs
576  {
577  _pkgFileListView = new YQPkgFileListView( _detailsViews );
578  YUI_CHECK_NEW( _pkgFileListView );
579 
580  _detailsViews->addTab( _pkgFileListView, _( "File List" ) );
581  _detailsViews->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
582 
583  connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
584  _pkgFileListView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
585  }
586 
587 
588  //
589  // Change Log
590  //
591 
592  if ( haveInstalledPkgs ) // change log information is only available for installed pkgs
593  {
594  _pkgChangeLogView = new YQPkgChangeLogView( _detailsViews );
595  YUI_CHECK_NEW( _pkgChangeLogView );
596 
597  _detailsViews->addTab( _pkgChangeLogView, _( "Change Log" ) );
598  _detailsViews->setSizePolicy( QSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ) ); // hor/vert
599 
600  connect( _pkgList, SIGNAL( currentItemChanged ( ZyppSel ) ),
601  _pkgChangeLogView, SLOT ( showDetailsIfVisible( ZyppSel ) ) );
602  }
603 }
604 
605 
606 void
607 YQPackageSelector::layoutButtons( QWidget *parent )
608 {
609  QWidget * button_box = new QWidget( parent );
610  YUI_CHECK_NEW( button_box );
611  parent->layout()->addWidget( button_box );
612 
613  QHBoxLayout * layout = new QHBoxLayout( button_box );
614  YUI_CHECK_NEW( layout );
615 
616  button_box->setLayout( layout );
617  layout->setContentsMargins( 2, // left
618  2, // top
619  2, // right
620  2 ); // bottom
621 
622  layout->addStretch();
623 
624  QPushButton * cancel_button = new QPushButton( _( "&Cancel" ), button_box );
625  YUI_CHECK_NEW( cancel_button );
626  layout->addWidget(cancel_button);
627 
628  cancel_button->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); // hor/vert
629 
630  connect( cancel_button, SIGNAL( clicked() ),
631  this, SLOT ( reject() ) );
632 
633 
634  QPushButton * accept_button = new QPushButton( _( "&Accept" ), button_box );
635  YUI_CHECK_NEW( accept_button );
636  layout->addWidget(accept_button);
637  accept_button->setSizePolicy( QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed ) ); // hor/vert
638 
639  connect( accept_button, SIGNAL( clicked() ),
640  this, SLOT ( accept() ) );
641 
642  button_box->setFixedHeight( button_box->sizeHint().height() );
643 }
644 
645 
646 void
647 YQPackageSelector::layoutMenuBar( QWidget *parent )
648 {
649  _menuBar = new QMenuBar( parent );
650  YUI_CHECK_NEW( _menuBar );
651  parent->layout()->addWidget(_menuBar);
652 
653  _fileMenu = 0;
654  _optionsMenu = 0;
655  _pkgMenu = 0;
656  _patchMenu = 0;
657  _extrasMenu = 0;
658  _configMenu = 0;
659  _dependencyMenu = 0;
660  _helpMenu = 0;
661 
662 }
663 
664 
665 void
667 {
668 
669 
670  //
671  // File menu
672  //
673 
674  _fileMenu = new QMenu( _menuBar );
675  YUI_CHECK_NEW( _fileMenu );
676  QAction * action = _menuBar->addMenu( _fileMenu );
677  action->setText( _( "&File" ));
678 
679  _fileMenu->addAction( _( "&Import..." ), this, SLOT( pkgImport() ) );
680  _fileMenu->addAction( _( "&Export..." ), this, SLOT( pkgExport() ) );
681 
682  _fileMenu->addSeparator();
683 
684  _fileMenu->addAction( _( "E&xit -- Discard Changes" ), this, SLOT( reject() ) );
685  _fileMenu->addAction( _( "&Quit -- Save Changes" ), this, SLOT( accept() ) );
686 
687 
688  if ( _pkgList )
689  {
690  //
691  // Package menu
692  //
693 
694  _pkgMenu = new QMenu( _menuBar );
695  YUI_CHECK_NEW( _pkgMenu );
696  action = _menuBar->addMenu( _pkgMenu );
697  action->setText(_( "&Package" ));
698 
699  _pkgMenu->addAction(_pkgList->actionSetCurrentInstall);
700  _pkgMenu->addAction(_pkgList->actionSetCurrentDontInstall);
701  _pkgMenu->addAction(_pkgList->actionSetCurrentKeepInstalled);
702  _pkgMenu->addAction(_pkgList->actionSetCurrentDelete);
703  _pkgMenu->addAction(_pkgList->actionSetCurrentUpdate);
704  _pkgMenu->addAction(_pkgList->actionSetCurrentUpdateForce);
705  _pkgMenu->addAction(_pkgList->actionSetCurrentTaboo);
706  _pkgMenu->addAction(_pkgList->actionShowCurrentSolverInfo);
707 
708 #if ENABLE_SOURCE_RPMS
709  _pkgMenu->addSeparator();
710 
711  _pkgMenu->addAction(_pkgList->actionInstallSourceRpm);
712  _pkgMenu->addAction(_pkgList->actionDontInstallSourceRpm);
713 #endif
714 
715  _pkgMenu->addSeparator();
716  QMenu * submenu = _pkgList->addAllInListSubMenu( _pkgMenu );
717  YUI_CHECK_NEW( submenu );
718 
719 #if ENABLE_SOURCE_RPMS
720  submenu->addSeparator();
721 
722  _pkgMenu->addAction(_pkgList->actionInstallListSourceRpms);
723  _pkgMenu->addAction(_pkgList->actionDontInstallListSourceRpms);
724 #endif
725 
726  //
727  // Submenu for all packages
728  //
729 
730  submenu = new QMenu( _pkgMenu );
731  YUI_CHECK_NEW( submenu );
732 
733  // Translators: Unlike the "all in this list" submenu, this submenu
734  // refers to all packages globally, not only to those that are
735  // currently visible in the packages list.
736  action = _pkgMenu->addMenu( submenu );
737  action->setText(_( "All Packages" ));
738 
739  submenu->addAction( _( "Update if newer version available" ),
740  this, SLOT( globalUpdatePkg() ) );
741 
742  submenu->addAction( _( "Update unconditionally" ),
743  this, SLOT( globalUpdatePkgForce() ) );
744  }
745 
746 
747  if ( _patchList )
748  {
749  //
750  // Patch menu
751  //
752 
753  _patchMenu = new QMenu( _menuBar );
754  YUI_CHECK_NEW( _patchMenu );
755  action = _menuBar->addMenu( _patchMenu );
756  action->setText(_( "&Patch" ));
757 
758  _patchMenu->addAction(_patchList->actionSetCurrentInstall);
759  _patchMenu->addAction(_patchList->actionSetCurrentDontInstall);
760  _patchMenu->addAction(_patchList->actionSetCurrentKeepInstalled);
761 
762 #if ENABLE_DELETING_PATCHES
763  _patchMenu->addAction(_patchList->actionSetCurrentDelete);
764 #endif
765  _patchMenu->addAction(_patchList->actionSetCurrentUpdate);
766  _patchMenu->addAction(_patchList->actionSetCurrentUpdateForce);
767  _patchMenu->addAction(_patchList->actionSetCurrentTaboo);
768 
769  _patchMenu->addSeparator();
770  _patchList->addAllInListSubMenu( _patchMenu );
771  }
772 
773 
774  //
775  // Configuration menu
776  //
777 
778  if ( repoMgrEnabled() )
779  {
780  _configMenu = new QMenu( _menuBar );
781  YUI_CHECK_NEW( _configMenu );
782  action = _menuBar->addMenu( _configMenu );
783  action->setText(_( "Confi&guration" ));
784  _configMenu->addAction( _( "&Repositories..." ), this, SLOT( repoManager() ), Qt::CTRL + Qt::Key_R );
785  _configMenu->addAction( _( "&Online Update..." ), this, SLOT( onlineUpdateConfiguration() ), Qt::CTRL + Qt::Key_O );
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  zypp::getZYpp()->resolver()->ignoreAlreadyRecommended() ).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"
Display the description of a ZyppObj derived object along with its name and summary.
void onlineUpdateConfiguration()
Close processing and request start of the online update configuration.
void addPatchFilterView()
Add the "Patches" filter view, if it is not already there.
void showPage(QWidget *page)
Show a page.
QWidget * rightPane() const
Return the right pane.
int globalSetPkgStatus(ZyppStatus newStatus, bool force, bool countOnly)
Set the status of all packages in the pool to a new value.
Definition: YQPkgList.cc:678
void loadData()
Emitted once (!) when the dialog is about to be shown, when all widgets are created and all signal/sl...
RPM group tags filter view: Display the RPM group tags tree and emit signals if any group tag is sele...
void globalUpdatePkg()
Set the status of all installed packages (all in the pool, not only those currently displayed in the ...
void connectFilter(QWidget *filter, QWidget *pkgList, bool hasUpdateSignal=true)
Connect a filter view that provides the usual signals with a package list.
void addPage(const QString &pageLabel, QWidget *pageContent, const QString &internalName)
Add a page with a user-visible "pageLabel", a widget with the page content and an internal name (or I...
Filter view for PackageKit groups.
static int countEnabledRepositories()
Returns the number of enabled repositories.
YQPkgDiskUsageList * diskUsageList() const
Return the disk usage list widget or 0 if there is none.
void showProducts()
Show all products in a popup dialog.
Filter view for packages that made problems during update.
void filter()
Filter according to the view's rules and current selection.
Widget for "tabbed browsing" in packages:
static bool haveInstalledPkgs()
Returns 'true' 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 'isWanted' 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.
void keyboardHelp()
Display online help about magic keys.
void enable(bool enable=true)
Enable or disable this exclude rule.
void accept()
Close processing and accept changes.
Display a list of zypp::Patch objects and ( below ) details about the currently selected patch...
void slotRepoUpgradeLabelLinkClicked(const QString &link)
a link in the repo upgrade label was clicked
void repoManager()
Close processing and request start of the repository manager.
Display a pkg's file list.
static std::string iconPath(const std::string &name, int size)
returns the full path for an icon of a given size
Display a list of zypp::Package objects.
Definition: YQPkgList.h:54
Display a list of zypp::Pattern objects.
Filter view for searching within packages.
void symbolHelp()
Display online help about symbols (package status icons).
void installDebugInfoPkgs()
Install available -debuginfo packages for packages that are installed or marked for installation...
void connectPatchList()
Connect the patch list.
Display technical details (very much like 'rpm -qi') for a ZYPP object - the installed instance...
void clear()
Clears the tree-widgets content, resets the optimal column width values.
Definition: YQPkgList.cc:432
void pkgExport()
Export all current selection/package states.
void applyExcludeRules()
Apply all exclude rules of this list to all items, including those that are currently excluded...
Filter view for packages that made problems during update.
void help()
Display (generic) online help.
Package version selector: Display a list of available versions from all the different installation so...
void autoResolveDependencies()
Automatically resolve package dependencies if desired (if the "auto check" checkbox is on)...
static bool haveProblematicPackages()
Check if there are any problematic packages at all, i.e.
void addMenus()
Add pulldown menus to the menu bar.
Display a list of zypp::Selection objects.
Definition: YQPkgLangList.h:52
void clear()
Reset all check boxes (set them all to "off")
void installDevelPkgs()
Install any -devel package for packages that are installed or marked for installation.
void loadSettings()
loads settings for the checkboxes in the option menu
static void showHistoryDialog(QWidget *parent=0)
Static convenience method: Post a History dialog for pkg 'pkgName'.
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 'message', a list of changed packages and ...
void showTransactions()
Set up the check boxes so all pending transactions are displayed.
void refresh()
Emitted when the internal data base might have changed and a refresh of all displayed data might be n...
virtual QMenu * addAllInListSubMenu(QMenu *menu)
Add a submenu "All in this list..." to 'menu'.
void installDebugSourcePkgs()
Install available -debugsource packages for packages that are installed or marked for installation...
virtual QMenu * addAllInListSubMenu(QMenu *menu)
Add a submenu "All in this list..." to 'menu'.
Definition: YQPkgList.cc:501
YQPkgPatchList * patchList() const
Returns this view's selections list.
Abstract base class for package selectors.
static void showProductDialog(QWidget *parent=0)
Static convenience method: Post a dialog with all products.
void filter()
Filter according to the view's rules and current selection.
void hotkeyInsertPatchFilterView()
Add the "Patches" filter view upon hotkey (F2).
void installSubPkgs(const QString &suffix)
Install any subpackage that ends with 'suffix' for packages that are installed or marked for installa...
void makeConnections()
Establish Qt signal / slot connections.
Display technical details ( very much like 'rpm -qi' ) for a zypp::Package object - the installed ins...
void showHistory()
Show dialog for pkgmgr history.
void showAutoPkgList()
Display a list of automatically selected packages (excluding packages contained in any selections tha...
void pkgImport()
Import selection/package states.
bool reject()
Close processing and abandon changes.
int resolveDependencies()
Resolve dependencies (unconditionally) for all resolvables.
void pkgExcludeDebugChanged(bool on)
Enable or disable the package exclude rules (show or suppress -debuginfo or -devel packages) accordin...
int solveAndShowConflicts()
Run the package dependency solver for the current package set and open the conflict dialog if there a...
void globalUpdatePkgForce()
Set the status of all installed packages (all in the pool, not only those currently displayed in the ...
Display a pkg's file list.
zypp::Repository selectedRepo() const
Current selected repository, or if nothing is selected.