picking up branches/tmp/sh/qt4-port/, merging it with trunk
[duncan/yast2-qt4.git] / src / pkg / YQPackageSelectorBase.cc
1 /*---------------------------------------------------------------------\
2 |                                                                      |
3 |                      __   __    ____ _____ ____                      |
4 |                      \ \ / /_ _/ ___|_   _|___ \                     |
5 |                       \ V / _` \___ \ | |   __) |                    |
6 |                        | | (_| |___) || |  / __/                     |
7 |                        |_|\__,_|____/ |_| |_____|                    |
8 |                                                                      |
9 |                               core system                            |
10 |                                                        (C) SuSE GmbH |
11 \----------------------------------------------------------------------/
12
13   File:       YQPackageSelectorBase.cc
14
15   Author:     Stefan Hundhammer <sh@suse.de>
16
17   Textdomain "packages-qt"
18
19 /-*/
20
21 #include <qmessagebox.h>
22 //Added by qt3to4:
23 #include <qevent.h>
24
25 #define y2log_component "qt-pkg"
26 #include <ycp/y2log.h>
27
28 #include <q3action.h>
29 #include "QY2LayoutUtils.h"
30
31 #include "YQPackageSelectorBase.h"
32 #include "YQPkgChangesDialog.h"
33 #include "YQPkgConflictDialog.h"
34 #include "YQPkgDiskUsageList.h"
35 #include "YQPkgDiskUsageWarningDialog.h"
36 #include "YQPkgTextDialog.h"
37 #include "YQPkgObjList.h"
38
39 #include "YQDialog.h"
40 #include "utf8.h"
41 #include "YQApplication.h"
42 #include "YQUI.h"
43 #include "YEvent.h"
44 #include "YQi18n.h"
45
46
47 using std::max;
48 using std::string;
49
50
51 YQPackageSelectorBase::YQPackageSelectorBase( YWidget * parent,
52                                               long      modeFlags )
53     : Q3VBox( (QWidget *) parent->widgetRep() )
54     , YPackageSelector( parent, modeFlags )
55 {
56     setWidgetRep( this );
57
58     _showChangesDialog          = false;
59     _pkgConflictDialog          = 0;
60     _diskUsageList              = 0;
61     _pkgConflictDialog          = 0;
62
63     YQUI::setTextdomain( "packages-qt" );
64     setFont( YQUI::yqApp()->currentFont() );
65     YQUI::ui()->blockWmClose(); // Automatically undone after UI::RunPkgSelection()
66
67     _pkgConflictDialog = new YQPkgConflictDialog( this );
68     Q_CHECK_PTR( _pkgConflictDialog );
69
70     QString label = _( "Reset &Ignored Dependency Conflicts" );
71     _actionResetIgnoredDependencyProblems = new Q3Action( label,                        // text
72                                                          label,                 // menu text
73                                                          (QKeySequence) 0,      // accel
74                                                          this );                // parent
75     Q_CHECK_PTR( _actionResetIgnoredDependencyProblems );
76
77     connect( _actionResetIgnoredDependencyProblems, SIGNAL( activated() ),
78              this,                                  SLOT  ( resetIgnoredDependencyProblems() ) );
79
80     zyppPool().saveState<zypp::Package  >();
81     zyppPool().saveState<zypp::Pattern  >();
82     zyppPool().saveState<zypp::Selection>();
83     zyppPool().saveState<zypp::Language >();
84     zyppPool().saveState<zypp::Patch    >();
85
86
87     //
88     // Handle WM_CLOSE like "Cancel"
89     //
90
91     connect( YQUI::ui(),        SIGNAL( wmClose() ),
92              this,              SLOT  ( reject()   ) );
93
94     y2milestone( "PackageSelectorBase init done" );
95 }
96
97
98 YQPackageSelectorBase::~YQPackageSelectorBase()
99 {
100     y2milestone( "Destroying PackageSelector" );
101 }
102
103
104 int
105 YQPackageSelectorBase::resolveDependencies()
106 {
107     if ( ! _pkgConflictDialog )
108     {
109         y2error( "No package conflict dialog existing" );
110         return QDialog::Accepted;
111     }
112
113
114     YQUI::ui()->busyCursor();
115     emit resolvingStarted();
116
117     int result = _pkgConflictDialog->solveAndShowConflicts();
118
119     emit resolvingFinished();
120     YQUI::ui()->normalCursor();
121
122     return result;
123 }
124
125
126 int
127 YQPackageSelectorBase::verifySystem()
128 {
129     if ( ! _pkgConflictDialog )
130     {
131         y2error( "No package conflict dialog existing" );
132         return QDialog::Accepted;
133     }
134
135
136     YQUI::ui()->busyCursor();
137     int result = _pkgConflictDialog->verifySystem();
138     YQUI::ui()->normalCursor();
139
140     if ( result == QDialog::Accepted )
141     {
142         QMessageBox::information( this, "",
143                                   _( "System dependencies verify OK." ),
144                                   QMessageBox::Ok );
145     }
146
147     return result;
148 }
149
150
151 int
152 YQPackageSelectorBase::checkDiskUsage()
153 {
154     if ( ! _diskUsageList )
155     {
156         return QDialog::Accepted;
157     }
158
159     if ( ! _diskUsageList->overflowWarning.inRange() )
160         return QDialog::Accepted;
161
162     QString msg =
163         // Translators: RichText ( HTML-like ) format
164         "<p><b>" + _( "Error: Out of disk space!" ) + "</b></p>"
165         + _( "<p>"
166              "You can choose to install anyway if you know what you are doing, "
167              "but you risk getting a corrupted system that requires manual repairs. "
168              "If you are not absolutely sure how to handle such a case, "
169              "press <b>Cancel</b> now and deselect some packages."
170              "</p>" );
171
172     return YQPkgDiskUsageWarningDialog::diskUsageWarning( msg,
173                                                           100, _( "C&ontinue Anyway" ), _( "&Cancel" ) );
174
175 }
176
177
178
179 void
180 YQPackageSelectorBase::showAutoPkgList()
181 {
182     resolveDependencies();
183
184     // Show which packages are installed/deleted automatically
185     QString msg =
186         "<p><b>"
187         // Dialog header
188         + _( "Automatic Changes" )
189         + "</b></p>"
190         // Detailed explanation ( automatic word wrap! )
191         + "<p>"
192         + _( "In addition to your manual selections, the following packages"
193              " have been changed to resolve dependencies:" )
194         + "<p>";
195
196     YQPkgChangesDialog::showChangesDialog( msg,
197                                            _( "&OK" ),
198                                            QString::null,       // rejectButtonLabel
199                                            true );              // showIfEmpty
200 }
201
202
203
204 void
205 YQPackageSelectorBase::reject()
206 {
207     bool changes =
208         zyppPool().diffState<zypp::Package  >() ||
209         zyppPool().diffState<zypp::Pattern  >() ||
210         zyppPool().diffState<zypp::Selection>() ||
211         zyppPool().diffState<zypp::Language >() ||
212         zyppPool().diffState<zypp::Patch    >();
213
214     if ( changes )
215     {
216         if ( zyppPool().diffState<zypp::Package>() )
217             y2milestone( "diffState() reports changed packages" );
218
219         if ( zyppPool().diffState<zypp::Pattern>() )
220             y2milestone( "diffState() reports changed patterns" );
221
222         if ( zyppPool().diffState<zypp::Selection>() )
223             y2milestone( "diffState() reports changed selections" );
224
225         if ( zyppPool().diffState<zypp::Language>() )
226             y2milestone( "diffState() reports changed languages" );
227
228         if ( zyppPool().diffState<zypp::Patch>() )
229             y2milestone( "diffState() reports changed patches" );
230     }
231
232     if ( ! changes ||
233          ( QMessageBox::warning( this, "",
234                                  _( "Abandon all changes?" ),
235                                  _( "&OK" ), _( "&Cancel" ), "",
236                                  1, // defaultButtonNumber (from 0)
237                                  1 ) // escapeButtonNumber
238            == 0 )       // Proceed upon button #0 ( OK )
239          )
240     {
241         zyppPool().restoreState<zypp::Package  >();
242         zyppPool().restoreState<zypp::Pattern  >();
243         zyppPool().restoreState<zypp::Selection>();
244         zyppPool().restoreState<zypp::Language >();
245         zyppPool().restoreState<zypp::Patch    >();
246
247         y2milestone( "Closing PackageSelector with \"Cancel\"" );
248         YQUI::ui()->sendEvent( new YCancelEvent() );
249     }
250 }
251
252
253 void
254 YQPackageSelectorBase::accept()
255 {
256     bool confirmedAllLicenses;
257
258     do
259     {
260         // Force final dependency resolving
261         if ( resolveDependencies() == QDialog::Rejected )
262             return;
263
264         confirmedAllLicenses = showPendingLicenseAgreements();
265
266     } while ( ! confirmedAllLicenses ); // Some packages will be set to S_TABOO - need another solver run
267
268     if ( _showChangesDialog )
269     {
270         // Show which packages are installed/deleted automatically
271         QString msg =
272             "<p><b>"
273             // Dialog header
274             + _( "Automatic Changes" )
275             + "</b></p>"
276             // Detailed explanation ( automatic word wrap! )
277             + "<p>"
278             + _( "In addition to your manual selections, the following packages"
279                  " have been changed to resolve dependencies:" )
280             + "<p>";
281
282         if ( YQPkgChangesDialog::showChangesDialog( msg, _( "C&ontinue" ), _( "&Cancel" ) )
283              == QDialog::Rejected )
284             return;
285     }
286
287     // Check disk usage
288     if ( checkDiskUsage() == QDialog::Rejected )
289         return;
290
291     y2milestone( "Closing PackageSelector with \"Accept\"" );
292     YQUI::ui()->sendEvent( new YMenuEvent( YCPSymbol( "accept" ) ) );
293 }
294
295
296 bool
297 YQPackageSelectorBase::showPendingLicenseAgreements()
298 {
299     y2milestone( "Showing all pending license agreements" );
300
301     bool allConfirmed = true;
302
303     if ( onlineUpdateMode() )
304         allConfirmed = showPendingLicenseAgreements( zyppPatchesBegin(), zyppPatchesEnd() );
305
306     allConfirmed = showPendingLicenseAgreements( zyppPkgBegin(), zyppPkgEnd() ) && allConfirmed;
307
308     return allConfirmed;
309 }
310
311
312 bool
313 YQPackageSelectorBase::showPendingLicenseAgreements( ZyppPoolIterator begin, ZyppPoolIterator end )
314 {
315     bool allConfirmed = true;
316
317     for ( ZyppPoolIterator it = begin; it != end; ++it )
318     {
319         ZyppSel sel = (*it);
320
321         switch ( sel->status() )
322         {
323             case S_Install:
324             case S_AutoInstall:
325             case S_Update:
326             case S_AutoUpdate:
327
328                 if ( sel->candidateObj() )
329                 {
330                     string licenseText = sel->candidateObj()->licenseToConfirm();
331
332                     if ( ! licenseText.empty() )
333                     {
334                         y2milestone( "Resolvable %s has a license agreement", sel->name().c_str() );
335
336                         if( ! sel->hasLicenceConfirmed() )
337                         {
338                             y2debug( "Showing license agreement for resolvable %s", sel->name().c_str() );
339                             allConfirmed = YQPkgObjListItem::showLicenseAgreement( sel ) && allConfirmed;
340                         }
341                         else
342                         {
343                             y2milestone( "Resolvable %s's  license is already confirmed", sel->name().c_str() );
344                         }
345                     }
346                 }
347                 break;
348
349             default:
350                 break;
351         }
352     }
353
354     return allConfirmed;
355 }
356
357
358 void
359 YQPackageSelectorBase::notImplemented()
360 {
361     QMessageBox::information( this, "",
362                               _( "Not implemented yet. Sorry." ),
363                               QMessageBox::Ok );
364 }
365
366
367 void
368 YQPackageSelectorBase::resetIgnoredDependencyProblems()
369 {
370     YQPkgConflictDialog::resetIgnoredDependencyProblems();
371 }
372
373
374 void
375 YQPackageSelectorBase::keyPressEvent( QKeyEvent * event )
376 {
377     if ( event )
378     {
379         unsigned special_combo = ( Qt::ControlButton | Qt::ShiftButton | Qt::AltButton );
380
381         if ( ( event->state() & special_combo ) == special_combo )
382         {
383             if ( event->key() == Qt::Key_A )
384             {
385                 showAutoPkgList();
386                 event->accept();
387                 return;
388             }
389         }
390         else if ( event->key() == Qt::Key_F5 )  // No matter if Ctrl/Alt/Shift pressed
391         {
392             YQUI::ui()->easterEgg();
393             return;
394         }
395     }
396
397     QWidget::keyPressEvent( event );
398 }
399
400
401 int YQPackageSelectorBase::preferredWidth()
402 {
403     return max( 640, sizeHint().width() );
404 }
405
406
407 int YQPackageSelectorBase::preferredHeight()
408 {
409     return max( 480, sizeHint().height() );
410 }
411
412
413 void
414 YQPackageSelectorBase::setSize( int newWidth, int newHeight )
415 {
416     resize( newWidth, newHeight );
417 }
418
419
420 void
421 YQPackageSelectorBase::setEnabling( bool enabled )
422 {
423     QWidget::setEnabled( enabled );
424 }
425
426
427 bool
428 YQPackageSelectorBase::setKeyboardFocus()
429 {
430     setFocus();
431
432     return true;
433 }
434
435
436 #include "YQPackageSelectorBase.moc"