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