]> icculus.org git repositories - duncan/yast2-qt4.git/blob - src/pkg/YQPkgConflictList.cc
e948880223461ca3dd1c7f9304a61184119c8731
[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 #include <QPainter>
22 #include <QPixmap>
23 #include <QDateTime>
24 #include <QMessageBox>
25 #include <QList>
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
62     setHeaderLabel( _( "Dependency Conflict" ) );
63     setRootIsDecorated( true );
64     setSortByInsertionSequence( true );
65 }
66
67
68 YQPkgConflictList::~YQPkgConflictList()
69 {
70     // NOP
71 }
72
73
74 void
75 YQPkgConflictList::fill( zypp::ResolverProblemList problemList )
76 {
77     clear();
78     string text;
79
80
81     zypp::ResolverProblemList::iterator it = problemList.begin();
82
83     while ( it != problemList.end() )
84     {
85         YQPkgConflict * conflict = new YQPkgConflict( this, *it );
86         Q_CHECK_PTR( conflict );
87
88         ++it;
89     }
90 }
91
92
93 void
94 YQPkgConflictList::applyResolutions()
95 {
96     zypp::ProblemSolutionList userChoices;
97
98     int count=0;
99     QTreeWidgetItem * child;
100
101     while ( (child = topLevelItem(count)) )
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         count++;
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 = YQApplication::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     QFile file(filename);
138   
139     if ( ! file.open(QIODevice::WriteOnly) )
140     {
141         y2error( "Can't open file %s", qPrintable(filename) );
142
143         if ( interactive )
144         {
145             // Post error popup.
146
147             QMessageBox::warning( 0,                                            // parent
148                                   _( "Error" ),                                 // caption
149                                   _( "Cannot open file %1" ).arg( filename ),
150                                   QMessageBox::Ok | QMessageBox::Default,       // button0
151                                   QMessageBox::NoButton,                        // button1
152                                   QMessageBox::NoButton );                      // button2
153         }
154         return;
155     }
156
157
158     // Write header
159
160     QString header = "#### YaST2 conflicts list - generated ";
161     header += QDateTime::currentDateTime().toString( "yyyy-MM-dd hh:mm:ss" );
162     header += " ####\n\n";
163
164    file.write(header.toUtf8());
165
166
167     // Recursively write all items
168     int count=0;
169     const QTreeWidgetItem * item;
170
171     while ( (item = topLevelItem(count)) )
172     {
173         saveItemToFile( file, item );
174         count++;
175     }
176
177
178     // Write footer
179
180     file.write("\n#### YaST2 conflicts list END ###\n" );
181
182
183     // Clean up
184
185     if ( file.isOpen() )
186         file.close();
187 }
188
189
190 void
191 YQPkgConflictList::saveItemToFile( QFile                        &file,
192                                    const QTreeWidgetItem *      item ) const
193 {
194 #if FIXME
195     if ( ! item || ! file.isOpen() )
196         return;
197
198     // Write indentation
199     for ( int level = 0; level < item->depth(); level++ )
200         file.write( "    " );
201
202     // Write item
203
204     const QTreeWidgetItem * checkListItem = dynamic_cast<const QTreeWidgetItem *> (item);
205
206     if ( checkListItem )
207     {
208         switch ( checkListItem->type() )
209         {
210     QString buffer;
211             case Q3CheckListItem::CheckBox:
212                 buffer.sprintf( "[%c] ", checkListItem->( checkState(0) == Qt::Checked ) ? 'x' : ' ' );
213                 break;
214             case Q3CheckListItem::RadioButton:
215                 sbuffer.sprintf( "(%c) ", checkListItem->( checkState(0) == Qt::Checked ) ? 'x' : ' ' );
216                 break;
217             default:
218                 break;
219         }
220     file.write(buffer.toUtf8());
221     }
222
223     buffer.sprintf("%s\n", qPrintable(item->text(0)) );
224     file.write(buffer.toUtf8());
225
226     if ( item->isExpanded() )
227     {
228         // Recursively write children
229
230         const QTreeWidgetItem * child = item->firstChild();
231
232         while ( child )
233         {
234             saveItemToFile( file, child );
235             child = child->nextSibling();
236         }
237     }
238 #endif
239 }
240
241
242 void
243 YQPkgConflictList::dumpList( QTreeWidgetItem *  parent,
244                              const QString &    longText,
245                              const QString &    header,
246                              int                splitThreshold )
247 {
248     if ( ! parent )
249     {
250         y2error( "Null parent" );
251         return;
252     }
253
254     if ( longText.isEmpty() )
255         return;
256
257 #if FIXME
258     if ( ! header.isEmpty() )
259     {
260         parent = new QY2ListViewItem( parent, header );
261         Q_CHECK_PTR( parent );
262         parent->setExpanded( true );
263     }
264
265     QStringList lines = QStringList::split( '\n', longText,
266                                             true );             // allowEmptyEntries
267     QList<QString>::const_iterator it = lines.begin();
268
269     bool doSplit        = splitThreshold > 1 && lines.size() > splitThreshold + 3;
270     bool didSplit       = false;
271     int  count          = 0;
272
273
274     while ( it != lines.end() )
275     {
276         if ( doSplit && ! didSplit && ++count > splitThreshold )
277         {
278             // Split list
279
280             int more = lines.size() - count + 1;
281             QString text = ( _( "%1 more..." ) ).arg( more );
282             QY2ListViewItem * sublist = new QY2ListViewItem( parent, text );
283             didSplit = true;
284
285             if ( sublist )
286             {
287                 sublist->setBackgroundColor( LIGHT_ORANGE );
288                 parent = sublist;
289             }
290         }
291
292         new QY2ListViewItem( parent, *it );
293         ++it;
294     }
295 #endif
296 }
297
298
299
300
301
302
303
304 YQPkgConflict::YQPkgConflict( YQPkgConflictList *               parentList,
305                               zypp::ResolverProblem_Ptr         problem )
306     : QY2ListViewItem( parentList )
307     , _problem( problem )
308     , _resolutionsHeader( 0 )
309 {
310     setBackgroundColor( LIGHT_BLUE );
311 #if FIXME
312     setExpanded( true );
313 #endif
314
315     formatHeading();
316     YQPkgConflictList::dumpList( this, fromUTF8( _problem->details() ) );
317
318     addSolutions();
319 }
320
321
322 void
323 YQPkgConflict::formatHeading()
324 {
325     QString text;
326     QPixmap icon = YQIconPool::normalPkgConflict();
327     setTextColor( BRIGHT_RED );
328
329 #if FIXME
330     setText( 0, Qt::DisplayRole, fromUTF8( problem()->description() ) );
331 #endif
332     setData( 0, Qt::DecorationRole, icon );
333 }
334
335
336 void
337 YQPkgConflict::addSolutions()
338 {
339     _resolutionsHeader = new QY2CheckListItem( this,
340                                                // Heading for the choices
341                                                // how to resolve this conflict
342                                                _( "Conflict Resolution:" ) );
343     Q_CHECK_PTR( _resolutionsHeader );
344
345     _resolutionsHeader->setExpanded( true );
346     _resolutionsHeader->setBackgroundColor( LIGHT_GREY );
347
348     zypp::ProblemSolutionList solutions = problem()->solutions();
349     zypp::ProblemSolutionList::iterator it = solutions.begin();
350
351     while ( it != solutions.end() )
352     {
353         YQPkgConflictResolution * solution = new YQPkgConflictResolution( _resolutionsHeader, *it );
354         Q_CHECK_PTR( solution );
355         //FIXME solution->setExpanded(true);
356
357         ++it;
358     }
359 }
360
361
362 // void
363 // YQPkgConflict::paintCell( QPainter *         painter,
364 //                        const QColorGroup &   colorGroup,
365 //                        int                   column,
366 //                        int                   width,
367 //                        int                   alignment )
368 // {
369 //     painter->setFont( YQUI::yqApp()->headingFont() );
370 // #if FIXME
371 //     QY2ListViewItem::paintCell( painter, colorGroup, column, width, alignment );
372 // #endif
373 // }
374
375
376 zypp::ProblemSolution_Ptr
377 YQPkgConflict::userSelectedResolution()
378 {
379     QTreeWidgetItem * item;
380     QTreeWidgetItemIterator it(_resolutionsHeader);
381
382     while ( (item = *it) )
383     {
384         YQPkgConflictResolution * res = dynamic_cast<YQPkgConflictResolution *> (item);
385
386         if ( res && ( res->checkState(0) == Qt::Checked ) )
387         {
388             zypp::ProblemSolution_Ptr solution = res->solution();
389
390             y2milestone( "User selected resolution \"%s\" for problem \"%s\"",
391                          solution->description().c_str(),
392                          solution->problem()->description().c_str() );
393             return solution;
394         }
395
396         ++it;
397     }
398
399     return zypp::ProblemSolution_Ptr();         // Null pointer
400 }
401
402
403
404
405
406
407 YQPkgConflictResolution::YQPkgConflictResolution( QY2CheckListItem *            parent,
408                                                   zypp::ProblemSolution_Ptr     solution )
409     : QY2CheckListItem( parent,
410                         fromUTF8( solution->description() ) )
411                         /*, Q3CheckListItem::RadioButton) */
412 {
413     _solution = solution;
414     YQPkgConflictList::dumpList( this, fromUTF8( solution->details() ) );
415 }
416
417
418
419 #include "YQPkgConflictList.moc"