]> icculus.org git repositories - duncan/yast2-qt4.git/blob - src/pkg/YQPkgConflictList.cc
picking up branches/tmp/sh/qt4-port/, merging it with trunk
[duncan/yast2-qt4.git] / src / pkg / YQPkgConflictList.cc
1 /*---------------------------------------------------------------------\
2 |                                                                      |
3 |                      __   __    ____ _____ ____                      |
4 |                      \ \ / /_ _/ ___|_   _|___ \                     |
5 |                       \ V / _` \___ \ | |   __) |                    |
6 |                        | | (_| |___) || |  / __/                     |
7 |                        |_|\__,_|____/ |_| |_____|                    |
8 |                                                                      |
9 |                               core system                            |
10 |                                                        (C) SuSE GmbH |
11 \----------------------------------------------------------------------/
12
13   File:       YQPkgConflictList.cc
14
15   Author:     Stefan Hundhammer <sh@suse.de>
16
17   Textdomain "packages-qt"
18
19 /-*/
20
21
22 #include <qpainter.h>
23 #include <qpixmap.h>
24 #include <qdatetime.h>
25 #include <qmessagebox.h>
26 //Added by qt3to4:
27 #include <q3valuelist.h>
28
29 #include <errno.h>
30
31 #define y2log_component "qt-pkg"
32 #include <ycp/y2log.h>
33
34 #include <zypp/ZYppFactory.h>
35 #include "YQPkgConflictList.h"
36 #include "YQPkgConflictDialog.h"
37 #include "YQIconPool.h"
38
39 #include "YQApplication.h"
40 #include "YQUI.h"
41 #include "YQi18n.h"
42 #include "utf8.h"
43
44 using std::list;
45 using std::string;
46
47
48 #define LIST_SPLIT_THRESHOLD    8
49
50 #define RED                     QColor( 0xC0, 0, 0 )
51 #define BRIGHT_RED              QColor( 0xFF, 0, 0 )
52 #define BLUE                    QColor( 0, 0, 0xC0 )
53 #define LIGHT_BLUE              QColor( 0xE0, 0xE0, 0xF8 )
54 #define LIGHT_GREY              QColor( 0xE0, 0xE0, 0xE0 )
55 #define MAGENTA                 Qt::magenta
56 #define DEEP_ORANGE             QColor( 0xFF, 0x80, 0x20 )
57 #define LIGHT_ORANGE            QColor( 0xFF, 0xC0, 0x50 )
58
59
60 YQPkgConflictList::YQPkgConflictList( QWidget * parent )
61     : QY2ListView( parent )
62 {
63     addColumn( _( "Dependency Conflict" ) );
64     setRootIsDecorated( true );
65     setSortByInsertionSequence( true );
66 }
67
68
69 YQPkgConflictList::~YQPkgConflictList()
70 {
71     // NOP
72 }
73
74
75 void
76 YQPkgConflictList::fill( zypp::ResolverProblemList problemList )
77 {
78     clear();
79     string text;
80
81
82     zypp::ResolverProblemList::iterator it = problemList.begin();
83
84     while ( it != problemList.end() )
85     {
86         YQPkgConflict * conflict = new YQPkgConflict( this, *it );
87         Q_CHECK_PTR( conflict );
88
89         ++it;
90     }
91 }
92
93
94 void
95 YQPkgConflictList::applyResolutions()
96 {
97     zypp::ProblemSolutionList userChoices;
98
99     Q3ListViewItem * child = firstChild();
100
101     while ( child )
102     {
103         YQPkgConflict * conflict = dynamic_cast<YQPkgConflict *> (child);
104
105         if ( conflict )
106         {
107             zypp::ProblemSolution_Ptr userChoice = conflict->userSelectedResolution();
108
109             if ( userChoice )
110                 userChoices.push_back( userChoice );
111         }
112
113         child = child->nextSibling();
114     }
115
116     zypp::getZYpp()->resolver()->applySolutions( userChoices );
117
118     emit updatePackages();
119 }
120
121
122 void
123 YQPkgConflictList::askSaveToFile() const
124 {
125     QString filename = YQUI::ui()->askForSaveFileName( "conflicts.txt", // startsWith
126                                                        "*.txt",         // filter
127                                                        _( "Save Conflicts List" ) );
128     if ( ! filename.isEmpty() )
129         saveToFile( filename, true );
130 }
131
132
133 void
134 YQPkgConflictList::saveToFile( const QString filename, bool interactive ) const
135 {
136     // Open file
137
138     FILE * file = fopen( (const char *) filename, "w" );
139
140     if ( ! file )
141     {
142         y2error( "Can't open file %s", (const char *) filename );
143
144         if ( interactive )
145         {
146             // Post error popup.
147
148             QMessageBox::warning( 0,                                            // parent
149                                   _( "Error" ),                                 // caption
150                                   _( "Cannot open file %1" ).arg( filename ),
151                                   QMessageBox::Ok | QMessageBox::Default,       // button0
152                                   QMessageBox::NoButton,                        // button1
153                                   QMessageBox::NoButton );                      // button2
154         }
155         return;
156     }
157
158
159     // Write header
160
161     QString header = "#### YaST2 conflicts list - generated ";
162     header += QDateTime::currentDateTime().toString( "yyyy-MM-dd hh:mm:ss" );
163     header += " ####\n\n";
164
165     fputs( (const char *) header, file );
166
167
168     // Recursively write all items
169
170     const Q3ListViewItem * item = firstChild();
171
172     while ( item )
173     {
174         saveItemToFile( file, item );
175         item = item->nextSibling();
176     }
177
178
179     // Write footer
180
181     fprintf( file, "\n#### YaST2 conflicts list END ###\n" );
182
183
184     // Clean up
185
186     if ( file )
187         fclose( file );
188 }
189
190
191 void
192 YQPkgConflictList::saveItemToFile( FILE *                       file,
193                                    const Q3ListViewItem *       item ) const
194 {
195     if ( ! item || ! file )
196         return;
197
198     // Write indentation
199
200     for ( int level = 0; level < item->depth(); level++ )
201         fprintf( file, "    " );
202
203
204     // Write item
205
206     const Q3CheckListItem * checkListItem = dynamic_cast<const Q3CheckListItem *> (item);
207
208     if ( checkListItem )
209     {
210         switch ( checkListItem->type() )
211         {
212             case Q3CheckListItem::CheckBox:
213                 fprintf( file, "[%c] ", checkListItem->isOn() ? 'x' : ' ' );
214                 break;
215             case Q3CheckListItem::RadioButton:
216                 fprintf( file, "(%c) ", checkListItem->isOn() ? 'x' : ' ' );
217                 break;
218             default:
219                 break;
220         }
221     }
222
223     fprintf( file, "%s\n", (const char *) item->text(0) );
224
225
226     if ( item->isOpen() )
227     {
228         // Recursively write children
229
230         const Q3ListViewItem * child = item->firstChild();
231
232         while ( child )
233         {
234             saveItemToFile( file, child );
235             child = child->nextSibling();
236         }
237     }
238 }
239
240
241 void
242 YQPkgConflictList::dumpList( Q3ListViewItem *   parent,
243                              const QString &    longText,
244                              const QString &    header,
245                              int                splitThreshold )
246 {
247     if ( ! parent )
248     {
249         y2error( "Null parent" );
250         return;
251     }
252
253     if ( longText.isEmpty() )
254         return;
255
256     if ( ! header.isEmpty() )
257     {
258         parent = new QY2ListViewItem( parent, header );
259         Q_CHECK_PTR( parent );
260         parent->setOpen( true );
261     }
262
263     QStringList lines = QStringList::split( '\n', longText,
264                                             true );             // allowEmptyEntries
265     QList<QString>::const_iterator it = lines.begin();
266
267     bool doSplit        = splitThreshold > 1 && lines.size() > splitThreshold + 3;
268     bool didSplit       = false;
269     int  count          = 0;
270
271
272     while ( it != lines.end() )
273     {
274         if ( doSplit && ! didSplit && ++count > splitThreshold )
275         {
276             // Split list
277
278             int more = lines.size() - count + 1;
279             QString text = ( _( "%1 more..." ) ).arg( more );
280             QY2ListViewItem * sublist = new QY2ListViewItem( parent, text );
281             didSplit = true;
282
283             if ( sublist )
284             {
285                 sublist->setBackgroundColor( LIGHT_ORANGE );
286                 parent = sublist;
287             }
288         }
289
290         new QY2ListViewItem( parent, *it );
291         ++it;
292     }
293 }
294
295
296
297
298
299
300
301 YQPkgConflict::YQPkgConflict( YQPkgConflictList *               parentList,
302                               zypp::ResolverProblem_Ptr         problem )
303     : QY2ListViewItem( parentList )
304     , _problem( problem )
305     , _resolutionsHeader( 0 )
306 {
307     setBackgroundColor( LIGHT_BLUE );
308     setOpen( true );
309
310     formatHeading();
311     YQPkgConflictList::dumpList( this, fromUTF8( _problem->details() ) );
312
313     addSolutions();
314 }
315
316
317 void
318 YQPkgConflict::formatHeading()
319 {
320     QString text;
321     QPixmap icon = YQIconPool::normalPkgConflict();
322     setTextColor( BRIGHT_RED );
323
324     setText( 0, fromUTF8( problem()->description() ) );
325     setPixmap( 0, icon );
326 }
327
328
329 void
330 YQPkgConflict::addSolutions()
331 {
332     _resolutionsHeader = new QY2CheckListItem( this,
333                                                // Heading for the choices
334                                                // how to resolve this conflict
335                                                _( "Conflict Resolution:" ),
336                                                Q3CheckListItem::Controller );
337     Q_CHECK_PTR( _resolutionsHeader );
338     _resolutionsHeader->setOpen( true );
339     _resolutionsHeader->setBackgroundColor( LIGHT_GREY );
340
341     zypp::ProblemSolutionList solutions = problem()->solutions();
342     zypp::ProblemSolutionList::iterator it = solutions.begin();
343
344     while ( it != solutions.end() )
345     {
346         new YQPkgConflictResolution( _resolutionsHeader, *it );
347         ++it;
348     }
349 }
350
351
352 void
353 YQPkgConflict::paintCell( QPainter *            painter,
354                           const QColorGroup &   colorGroup,
355                           int                   column,
356                           int                   width,
357                           int                   alignment )
358 {
359     painter->setFont( YQUI::yqApp()->headingFont() );
360     QY2ListViewItem::paintCell( painter, colorGroup, column, width, alignment );
361 }
362
363
364 zypp::ProblemSolution_Ptr
365 YQPkgConflict::userSelectedResolution()
366 {
367     Q3ListViewItem * item = _resolutionsHeader->firstChild();
368
369     while ( item )
370     {
371         YQPkgConflictResolution * res = dynamic_cast<YQPkgConflictResolution *> (item);
372
373         if ( res && res->isOn() )
374         {
375             zypp::ProblemSolution_Ptr solution = res->solution();
376
377             y2milestone( "User selected resolution \"%s\" for problem \"%s\"",
378                          solution->description().c_str(),
379                          solution->problem()->description().c_str() );
380             return solution;
381         }
382
383         item = item->nextSibling();
384     }
385
386     return zypp::ProblemSolution_Ptr();         // Null pointer
387 }
388
389
390
391
392
393
394 YQPkgConflictResolution::YQPkgConflictResolution( QY2CheckListItem *            parent,
395                                                   zypp::ProblemSolution_Ptr     solution )
396     : QY2CheckListItem( parent,
397                         fromUTF8( solution->description() ),
398                         Q3CheckListItem::RadioButton )
399     , _solution( solution )
400 {
401     YQPkgConflictList::dumpList( this, fromUTF8( solution->details() ) );
402 }
403
404
405
406 #include "YQPkgConflictList.moc"