]> icculus.org git repositories - duncan/yast2-qt4.git/blob - src/pkg/YQPkgConflictList.cc
clicking packages work! so the package selector is now
[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     setExpanded( true );
312
313     formatHeading();
314     YQPkgConflictList::dumpList( this, fromUTF8( _problem->details() ) );
315
316     addSolutions();
317 }
318
319
320 void
321 YQPkgConflict::formatHeading()
322 {
323     QString text;
324     QPixmap icon = YQIconPool::normalPkgConflict();
325     setTextColor( BRIGHT_RED );
326
327     setData( 0, Qt::DisplayRole, fromUTF8( problem()->description() ) );
328     setData( 0, Qt::DecorationRole, icon );
329 }
330
331
332 void
333 YQPkgConflict::addSolutions()
334 {
335     _resolutionsHeader = new QY2CheckListItem( this,
336                                                // Heading for the choices
337                                                // how to resolve this conflict
338                                                _( "Conflict Resolution:" ) );
339     Q_CHECK_PTR( _resolutionsHeader );
340
341     _resolutionsHeader->setExpanded( true );
342     _resolutionsHeader->setBackgroundColor( LIGHT_GREY );
343
344     zypp::ProblemSolutionList solutions = problem()->solutions();
345     zypp::ProblemSolutionList::iterator it = solutions.begin();
346
347     while ( it != solutions.end() )
348     {
349         YQPkgConflictResolution * solution = new YQPkgConflictResolution( _resolutionsHeader, *it );
350         Q_CHECK_PTR( solution );
351         //FIXME solution->setExpanded(true);
352
353         ++it;
354     }
355 }
356
357
358 // void
359 // YQPkgConflict::paintCell( QPainter *         painter,
360 //                        const QColorGroup &   colorGroup,
361 //                        int                   column,
362 //                        int                   width,
363 //                        int                   alignment )
364 // {
365 //     painter->setFont( YQUI::yqApp()->headingFont() );
366 // #if FIXME
367 //     QY2ListViewItem::paintCell( painter, colorGroup, column, width, alignment );
368 // #endif
369 // }
370
371
372 zypp::ProblemSolution_Ptr
373 YQPkgConflict::userSelectedResolution()
374 {
375     QTreeWidgetItem * item;
376     QTreeWidgetItemIterator it(_resolutionsHeader);
377
378     while ( (item = *it) )
379     {
380         YQPkgConflictResolution * res = dynamic_cast<YQPkgConflictResolution *> (item);
381
382         if ( res && ( res->checkState(0) == Qt::Checked ) )
383         {
384             zypp::ProblemSolution_Ptr solution = res->solution();
385
386             y2milestone( "User selected resolution \"%s\" for problem \"%s\"",
387                          solution->description().c_str(),
388                          solution->problem()->description().c_str() );
389             return solution;
390         }
391
392         ++it;
393     }
394
395     return zypp::ProblemSolution_Ptr();         // Null pointer
396 }
397
398
399
400
401
402
403 YQPkgConflictResolution::YQPkgConflictResolution( QY2CheckListItem *            parent,
404                                                   zypp::ProblemSolution_Ptr     solution )
405     : QY2CheckListItem( parent,
406                         fromUTF8( solution->description() ) )
407                         /*, Q3CheckListItem::RadioButton) */
408 {
409     _solution = solution;
410     YQPkgConflictList::dumpList( this, fromUTF8( solution->details() ) );
411 }
412
413
414
415 #include "YQPkgConflictList.moc"