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