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