libyui-qt-pkg  2.45.13.1
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::null, // 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 bool
356 {
357  yuiMilestone() << "Showing all pending license agreements" << std::endl;
358 
359  bool allConfirmed = true;
360 
361  if ( onlineUpdateMode() )
362  allConfirmed = showPendingLicenseAgreements( zyppPatchesBegin(), zyppPatchesEnd() );
363 
364  allConfirmed = showPendingLicenseAgreements( zyppPkgBegin(), zyppPkgEnd() ) && allConfirmed;
365 
366  return allConfirmed;
367 }
368 
369 
370 bool
371 YQPackageSelectorBase::showPendingLicenseAgreements( ZyppPoolIterator begin, ZyppPoolIterator end )
372 {
373  bool allConfirmed = true;
374 
375  for ( ZyppPoolIterator it = begin; it != end; ++it )
376  {
377  ZyppSel sel = (*it);
378 
379  switch ( sel->status() )
380  {
381  case S_Install:
382  case S_AutoInstall:
383  case S_Update:
384  case S_AutoUpdate:
385 
386  if ( sel->candidateObj() )
387  {
388  string licenseText = sel->candidateObj()->licenseToConfirm();
389 
390  if ( ! licenseText.empty() )
391  {
392  yuiMilestone() << "Resolvable " << sel->name() << " has a license agreement" << std::endl;
393 
394  if( ! sel->hasLicenceConfirmed() )
395  {
396  yuiDebug() << "Showing license agreement for resolvable " << sel->name() << std::endl;
397  allConfirmed = YQPkgObjListItem::showLicenseAgreement( sel ) && allConfirmed;
398  }
399  else
400  {
401  yuiMilestone() << "Resolvable " << sel->name()
402  << "'s license is already confirmed" << std::endl;
403  }
404  }
405  }
406  break;
407 
408  default:
409  break;
410  }
411  }
412 
413  return allConfirmed;
414 }
415 
416 
417 void
419 {
420  QMessageBox::information( this, "",
421  _( "Not implemented yet. Sorry." ),
422  QMessageBox::Ok );
423 }
424 
425 
426 void
428 {
430 }
431 
432 
433 void
435 {
436  if ( event )
437  {
438  Qt::KeyboardModifiers special_combo = ( Qt::ControlModifier | Qt::ShiftModifier | Qt::AltModifier );
439 
440  if ( ( event->modifiers() & special_combo ) == special_combo )
441  {
442  if ( event->key() == Qt::Key_A )
443  {
444  showAutoPkgList();
445  event->accept();
446  return;
447  }
448  }
449  }
450 
451  QWidget::keyPressEvent( event );
452 }
453 
454 
456 {
457  return max( 640, sizeHint().width() );
458 }
459 
460 
462 {
463  return max( 480, sizeHint().height() );
464 }
465 
466 
467 void
468 YQPackageSelectorBase::setSize( int newWidth, int newHeight )
469 {
470  resize( newWidth, newHeight );
471 }
472 
473 
474 void
476 {
477  QWidget::setEnabled( enabled );
478 }
479 
480 
481 bool
483 {
484  setFocus();
485 
486  return true;
487 }
488 
489 
490 YEvent *
492 {
493  if ( event && event->eventType() == YEvent::CancelEvent // WM_CLOSE
494  && ! _inReject ) // prevent recursion
495  {
496  // Handle WM_CLOSE like "Cancel"
497  yuiMilestone() << "Caught WM_CLOSE from package selector dialog" << std::endl;
498 
499  YUI::app()->normalCursor();
500  YUI_CHECK_WIDGET( _pkgSel );
501 
502  _inReject = true; // reject() might send a CancelEvent, too
503  bool reallyReject = _pkgSel->reject();
504  _inReject = false;
505 
506  if ( ! reallyReject )
507  {
508  event = 0; // Stop processing this event
509  yuiMilestone() << "User changed his mind - discarding CancelEvent" << std::endl;
510  }
511  }
512 
513  return event; // Don't stop processing this event
514 }
515 
516 
517 #include "YQPackageSelectorBase.moc"
int verifySystem()
Verifies dependencies of the currently installed system.
bool inRange() const
Check if the value is in range, i.e.
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...
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.
void accept()
Close processing and accept changes.
void repoManager()
Close processing and request start of the repository manager.
void notImplemented()
Inform user about a feature that is not implemented yet.
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.
static bool diskUsageWarning(const QString &message, int thresholdPercent, const QString &acceptButtonLabel, const QString &rejectButtonLabel=QString::null)
Static convenience method: Post a disk usage warning with text &#39;message&#39;, a list of partitions that a...
Helper class: Event filter for the WM_CLOSE event.
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 ...
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.
static bool showUnsupportedPackagesDialog(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 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...