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