libyui-qt-pkg  2.47.5
YQPackageSelectorBase.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: YQPackageSelectorBase.cc
35 
36  Author: Stefan Hundhammer <sh@suse.de>
37 
38  Textdomain "qt-pkg"
39 
40 /-*/
41 
42 #include <QMessageBox>
43 #include <QKeyEvent>
44 
45 #define YUILogComponent "qt-pkg"
46 #include "YUILog.h"
47 
48 #include <QAction>
49 #include <QVBoxLayout>
50 #include <QHBoxLayout>
51 #include "QY2LayoutUtils.h"
52 
53 #include "YQPackageSelectorBase.h"
54 #include "YQPkgChangesDialog.h"
55 #include "YQPkgConflictDialog.h"
56 #include "YQPkgDiskUsageList.h"
57 #include "YQPkgDiskUsageWarningDialog.h"
58 #include "YQPkgTextDialog.h"
59 #include "YQPkgObjList.h"
60 
61 #include "YQDialog.h"
62 #include "utf8.h"
63 #include "YQApplication.h"
64 #include "YQUI.h"
65 #include "YEvent.h"
66 #include "YQi18n.h"
67 #include "QY2Styler.h"
68 
69 using std::max;
70 using std::string;
71 
72 
73 
75  long modeFlags )
76  : QFrame( (QWidget *) parent->widgetRep() )
77  , YPackageSelector( parent, modeFlags )
78 {
79  setWidgetRep( this );
80 
81  _wmCloseHandler = 0;
82  _showChangesDialog = false;
83  _pkgConflictDialog = 0;
84  _diskUsageList = 0;
85  _pkgConflictDialog = 0;
86 
87  YQUI::setTextdomain( "qt-pkg" );
88  setFont( YQUI::yqApp()->currentFont() );
89 
90  _pkgConflictDialog = new YQPkgConflictDialog( this );
91  Q_CHECK_PTR( _pkgConflictDialog );
92 
93  QString label = _( "Reset &Ignored Dependency Conflicts" );
94  _actionResetIgnoredDependencyProblems = new QAction( label, this);
95  _actionResetIgnoredDependencyProblems->setShortcut((QKeySequence) 0);
96  //_actionResetIgnoredDependencyProblems->setMenuRole(QAction::TextHeuristicRole);
97  Q_CHECK_PTR( _actionResetIgnoredDependencyProblems );
98 
99  connect( _actionResetIgnoredDependencyProblems, &QAction::triggered,
101 
102  zyppPool().saveState<zypp::Package >();
103  zyppPool().saveState<zypp::Pattern >();
104  zyppPool().saveState<zypp::Patch >();
105 
106  _wmCloseHandler = new YQPkgSelWmCloseHandler( this );
107 
108  QY2Styler::styler()->registerWidget( this );
109 
110  yuiMilestone() << "PackageSelectorBase init done" << std::endl;
111 }
112 
113 
115 {
116  yuiMilestone() << "Destroying PackageSelector" << std::endl;
117 
118  QY2Styler::styler()->unregisterWidget( this );
119 
120  if ( _wmCloseHandler )
121  delete _wmCloseHandler;
122 }
123 
124 
125 int
127 {
128  if ( ! _pkgConflictDialog )
129  {
130  yuiError() << "No package conflict dialog existing" << std::endl;
131  return QDialog::Accepted;
132  }
133 
134 
135  YQUI::ui()->busyCursor();
136  emit resolvingStarted();
137 
138  int result = _pkgConflictDialog->solveAndShowConflicts();
139 
140  emit resolvingFinished();
141  YQUI::ui()->normalCursor();
142 
143  return result;
144 }
145 
146 
147 int
149 {
150  if ( ! _pkgConflictDialog )
151  {
152  yuiError() << "No package conflict dialog existing" << std::endl;
153  return QDialog::Accepted;
154  }
155 
156 
157  YQUI::ui()->busyCursor();
158  int result = _pkgConflictDialog->verifySystem();
159  YQUI::ui()->normalCursor();
160 
161  if ( result == QDialog::Accepted )
162  {
163  QMessageBox::information( this, "",
164  _( "System dependencies verify OK." ),
165  QMessageBox::Ok );
166  }
167 
168  return result;
169 }
170 
171 
172 int
174 {
175  if ( ! _diskUsageList )
176  {
177  return QDialog::Accepted;
178  }
179 
180  if ( ! _diskUsageList->overflowWarning.inRange() )
181  return QDialog::Accepted;
182 
183  QString msg =
184  // Translators: RichText ( HTML-like ) format
185  "<p><b>" + _( "Error: Out of disk space!" ) + "</b></p>"
186  + _( "<p>"
187  "You can choose to install anyway if you know what you are doing, "
188  "but you risk getting a corrupted system that requires manual repairs. "
189  "If you are not absolutely sure how to handle such a case, "
190  "press <b>Cancel</b> now and deselect some packages."
191  "</p>" );
192 
194  100, _( "C&ontinue Anyway" ), _( "&Cancel" ) );
195 }
196 
197 
198 
199 void
201 {
203 
204  // Show which packages are installed/deleted
205  QString msg =
206  // Detailed explanation ( automatic word wrap! )
207  + "<p>"
208  + _( "The following items will be changed:"
209  " " )
210  + "<p>";
211 
213  msg,
214  _( "&OK" ),
215  QString(), // rejectButtonLabel
216  YQPkgChangesDialog::FilterAutomatic,
217  YQPkgChangesDialog::OptionNone ); // showIfEmpty
218 }
219 
220 
221 
222 bool
224 {
225  bool changes =
226  zyppPool().diffState<zypp::Package >() ||
227  zyppPool().diffState<zypp::Pattern >() ||
228  zyppPool().diffState<zypp::Patch >();
229 
230  if ( changes )
231  {
232  if ( zyppPool().diffState<zypp::Package>() )
233  yuiMilestone() << "diffState() reports changed packages" << std::endl;
234 
235  if ( zyppPool().diffState<zypp::Pattern>() )
236  yuiMilestone() << "diffState() reports changed patterns" << std::endl;
237 
238  if ( zyppPool().diffState<zypp::Patch>() )
239  yuiMilestone() << "diffState() reports changed patches" << std::endl;
240  }
241 
242  bool confirm = false;
243 
244  if ( changes )
245  {
246  int result =
247  QMessageBox::warning( this, "",
248  _( "Do you want to Abandon all changes and exit?" ),
249  _( "&Yes" ), _( "&No" ), "",
250  1, // defaultButtonNumber (from 0)
251  1 ); // escapeButtonNumber
252 
253  confirm = ( result == 0 );
254  }
255 
256  if ( ! changes || confirm )
257  {
258  zyppPool().restoreState<zypp::Package >();
259  zyppPool().restoreState<zypp::Pattern >();
260  zyppPool().restoreState<zypp::Patch >();
261 
262  yuiMilestone() << "Closing PackageSelector with \"Cancel\"" << std::endl;
263  YQUI::ui()->sendEvent( new YCancelEvent() );
264 
265  return true; // Really reject
266  }
267  else
268  {
269  yuiMilestone() << "Returning to package selector" << std::endl;
270 
271  return false; // User changed his mind - don't reject
272  }
273 }
274 
275 
276 void
278 {
279  bool confirmedAllLicenses;
280 
281  do
282  {
283  // Force final dependency resolving
284  if ( resolveDependencies() == QDialog::Rejected )
285  return;
286 
287  confirmedAllLicenses = showPendingLicenseAgreements();
288 
289  } while ( ! confirmedAllLicenses ); // Some packages will be set to S_TABOO - need another solver run
290 
291  if ( _showChangesDialog )
292  {
293  // Show which packages are installed/deleted automatically
294  QString msg =
295  "<p><b>"
296  // Dialog header
297  + _( "Automatic Changes" )
298  + "</b></p>"
299  // Detailed explanation ( automatic word wrap! )
300  + "<p>"
301  + _( "In addition to your manual selections, the following packages"
302  " have been changed to resolve dependencies:" )
303  + "<p>";
304 
305  if ( YQPkgChangesDialog::showChangesDialog( this, msg, _( "C&ontinue" ), _( "&Cancel" ), YQPkgChangesDialog::FilterAutomatic, YQPkgChangesDialog::OptionAutoAcceptIfEmpty )
306  == QDialog::Rejected )
307  return;
308  }
309 
310  if ( confirmUnsupported() )
311  {
312  yuiMilestone() << "Confirm unsupported packages enabled." << std::endl;
313  // Show which packages are unsupported
314 
315  QString msg =
316  "<p><b>"
317  // Dialog header
318  + _( "Unsupported Packages" )
319  + "</b></p>"
320  // Detailed explanation ( automatic word wrap! )
321  + "<p>"
322  + _( "Please realize that the following selected software is either unsupported or"
323  " requires an additional customer contract for support." )
324  + "<p>";
325 
326  if ( YQPkgUnsupportedPackagesDialog::showUnsupportedPackagesDialog( this, msg, _( "C&ontinue" ), _( "&Cancel" ), YQPkgChangesDialog::FilterUser, YQPkgChangesDialog::OptionAutoAcceptIfEmpty )
327  == QDialog::Rejected )
328  return;
329  }
330 
331 
332  // Check disk usage
333  if ( checkDiskUsage() == QDialog::Rejected )
334  return;
335 
336  yuiMilestone() << "Closing PackageSelector with \"Accept\"" << std::endl;
337  YQUI::ui()->sendEvent( new YMenuEvent( "accept" ) );
338 }
339 
340 void
342 {
343  yuiMilestone() << "Closing PackageSelector with \"RepoManager\"" << std::endl;
344  YQUI::ui()->sendEvent( new YMenuEvent( "repo_mgr" ) );
345 }
346 
347 void
349 {
350  yuiMilestone() << "Closing PackageSelector with \"OnlineUpdateConfiguration\"" << std::endl;
351  YQUI::ui()->sendEvent( new YMenuEvent( "online_update_configuration" ) );
352 }
353 
354 void
356 {
357  yuiMilestone() << "Closing PackageSelector with \"OnlineSearch\"" << std::endl;
358  YQUI::ui()->sendEvent( new YMenuEvent( "online_search" ) );
359 }
360 
361 bool
363 {
364  yuiMilestone() << "Showing all pending license agreements" << std::endl;
365 
366  bool allConfirmed = true;
367 
368  if ( onlineUpdateMode() )
369  allConfirmed = showPendingLicenseAgreements( zyppPatchesBegin(), zyppPatchesEnd() );
370 
371  allConfirmed = showPendingLicenseAgreements( zyppPkgBegin(), zyppPkgEnd() ) && allConfirmed;
372 
373  return allConfirmed;
374 }
375 
376 
377 bool
378 YQPackageSelectorBase::showPendingLicenseAgreements( ZyppPoolIterator begin, ZyppPoolIterator end )
379 {
380  bool allConfirmed = true;
381 
382  for ( ZyppPoolIterator it = begin; it != end; ++it )
383  {
384  ZyppSel sel = (*it);
385 
386  switch ( sel->status() )
387  {
388  case S_Install:
389  case S_AutoInstall:
390  case S_Update:
391  case S_AutoUpdate:
392 
393  if ( sel->candidateObj() )
394  {
395  string licenseText = sel->candidateObj()->licenseToConfirm();
396 
397  if ( ! licenseText.empty() )
398  {
399  yuiMilestone() << "Resolvable " << sel->name() << " has a license agreement" << std::endl;
400 
401  if( ! sel->hasLicenceConfirmed() )
402  {
403  yuiDebug() << "Showing license agreement for resolvable " << sel->name() << std::endl;
404  allConfirmed = YQPkgObjListItem::showLicenseAgreement( sel ) && allConfirmed;
405  }
406  else
407  {
408  yuiMilestone() << "Resolvable " << sel->name()
409  << "'s license is already confirmed" << std::endl;
410  }
411  }
412  }
413  break;
414 
415  default:
416  break;
417  }
418  }
419 
420  return allConfirmed;
421 }
422 
423 
424 void
426 {
427  QMessageBox::information( this, "",
428  _( "Not implemented yet. Sorry." ),
429  QMessageBox::Ok );
430 }
431 
432 
433 void
435 {
437 }
438 
439 
440 void
442 {
443  if ( event )
444  {
445  Qt::KeyboardModifiers special_combo = ( Qt::ControlModifier | Qt::ShiftModifier | Qt::AltModifier );
446 
447  if ( ( event->modifiers() & special_combo ) == special_combo )
448  {
449  if ( event->key() == Qt::Key_A )
450  {
451  showAutoPkgList();
452  event->accept();
453  return;
454  }
455  }
456  }
457 
458  QWidget::keyPressEvent( event );
459 }
460 
461 
463 {
464  return max( 640, sizeHint().width() );
465 }
466 
467 
469 {
470  return max( 480, sizeHint().height() );
471 }
472 
473 
474 void
475 YQPackageSelectorBase::setSize( int newWidth, int newHeight )
476 {
477  resize( newWidth, newHeight );
478 }
479 
480 
481 void
483 {
484  QWidget::setEnabled( enabled );
485 }
486 
487 
488 bool
490 {
491  setFocus();
492 
493  return true;
494 }
495 
496 
497 YEvent *
499 {
500  if ( event && event->eventType() == YEvent::CancelEvent // WM_CLOSE
501  && ! _inReject ) // prevent recursion
502  {
503  // Handle WM_CLOSE like "Cancel"
504  yuiMilestone() << "Caught WM_CLOSE from package selector dialog" << std::endl;
505 
506  YUI::app()->normalCursor();
507  YUI_CHECK_WIDGET( _pkgSel );
508 
509  _inReject = true; // reject() might send a CancelEvent, too
510  bool reallyReject = _pkgSel->reject();
511  _inReject = false;
512 
513  if ( ! reallyReject )
514  {
515  event = 0; // Stop processing this event
516  yuiMilestone() << "User changed his mind - discarding CancelEvent" << std::endl;
517  }
518  }
519 
520  return event; // Don't stop processing this event
521 }
522 
523 
int verifySystem()
Verifies dependencies of the currently installed system.
void onlineUpdateConfiguration()
Close processing and request start of the online update configuration.
YQPkgWarningRangeNotifier overflowWarning
Warning range notifier about disk space overflow warning.
void resetIgnoredDependencyProblems()
Reset all previously ignored dependency problems.
bool showPendingLicenseAgreements()
Show all license agreements the user has not confirmed yet (for all packages that will be installed...
static bool showUnsupportedPackagesDialog(QWidget *parent, const QString &message, const QString &acceptButtonLabel, const QString &rejectButtonLabel=QString(), Filters f=FilterAutomatic, Options o=OptionAutoAcceptIfEmpty)
Static convenience method: Post a changes dialog with text &#39;message&#39;, a list of changed packages and ...
static bool diskUsageWarning(const QString &message, int thresholdPercent, const QString &acceptButtonLabel, const QString &rejectButtonLabel=QString())
Static convenience method: Post a disk usage warning with text &#39;message&#39;, a list of partitions that a...
virtual void setEnabling(bool enabled)
Set enabled/disabled state.
int checkDiskUsage()
Check for disk overflow and post a warning dialog if necessary.
bool showLicenseAgreement()
Display this item&#39;s license agreement (if there is any) that corresponds to its current status (S_Ins...
virtual bool setKeyboardFocus()
Accept the keyboard focus.
bool inRange() const
Check if the value is in range, i.e.
void accept()
Close processing and accept changes.
static bool showChangesDialog(QWidget *parent, const QString &message, const QString &acceptButtonLabel, const QString &rejectButtonLabel=QString(), 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 repoManager()
Close processing and request start of the repository manager.
void notImplemented()
Inform user about a feature that is not implemented yet.
void onlineSearch()
Close processing and request start of the online search.
void resolvingStarted()
Emitted when package resolving is started.
void resolvingFinished()
Emitted when package resolving is finished.
virtual YEvent * filter(YEvent *event)
The filter method: This is what this class is all about.
int verifySystem()
Run the package dependency solver for the currently installed system plus the packages that are marke...
virtual ~YQPackageSelectorBase()
Destructor.
Helper class: Event filter for the WM_CLOSE event.
static void resetIgnoredDependencyProblems()
Reset all previously ignored dependency problems.
virtual void setSize(int newWidth, int newHeight)
Set the new size of the widget.
virtual void keyPressEvent(QKeyEvent *ev)
Event handler for keyboard input - for debugging and testing.
virtual int preferredWidth()
Preferred width of the widget.
YQPackageSelectorBase(YWidget *parent, long modeFlags=0)
Constructor.
Dialog that takes care of dependency checking and resolving conflicts.
void showAutoPkgList()
Display a list of automatically selected packages (excluding packages contained in any selections tha...
virtual int preferredHeight()
Preferred height of the widget.
bool reject()
Close processing and abandon changes.
int resolveDependencies()
Resolve dependencies (unconditionally) for all resolvables.
int solveAndShowConflicts()
Run the package dependency solver for the current package set and open the conflict dialog if there a...