]> icculus.org git repositories - duncan/yast2-qt4.git/blob - src/pkg/YQPkgList.cc
YQPkgChangesDialog QT3_SUPPORT
[duncan/yast2-qt4.git] / src / pkg / YQPkgList.cc
1 /*---------------------------------------------------------------------\
2 |                                                                      |
3 |                      __   __    ____ _____ ____                      |
4 |                      \ \ / /_ _/ ___|_   _|___ \                     |
5 |                       \ V / _` \___ \ | |   __) |                    |
6 |                        | | (_| |___) || |  / __/                     |
7 |                        |_|\__,_|____/ |_| |_____|                    |
8 |                                                                      |
9 |                               core system                            |
10 |                                                        (C) SuSE GmbH |
11 \----------------------------------------------------------------------/
12
13   File:       YQPkgList.cc
14
15   Author:     Stefan Hundhammer <sh@suse.de>
16
17   Textdomain "packages-qt"
18
19 /-*/
20
21 #define SOURCE_RPM_DISABLED 0
22
23 #define y2log_component "qt-pkg"
24 #include <ycp/y2log.h>
25 #include <QPixmap>
26 #include <QAction>
27 #include <QMenu>
28 #include <QMessageBox>
29 #include <QFile>
30
31 #include "utf8.h"
32
33 #include "YQPkgList.h"
34 #include "YQUI.h"
35 #include "YQi18n.h"
36 #include "YQIconPool.h"
37
38
39 YQPkgList::YQPkgList( QWidget * parent )
40     : YQPkgObjList( parent )
41 {
42     _srpmStatusCol      = -42;
43
44     int numCol = 0;
45     QStringList headers;
46
47     
48     headers <<  "";                     _statusCol      = numCol++;
49     // _statusCol = numCol;
50     headers <<  _( "Package"    );      _nameCol        = numCol++;
51
52     headers <<  _( "Summary"    );      _summaryCol     = numCol++;
53     headers <<  _( "Size"       );      _sizeCol        = numCol++;
54
55     if ( haveInstalledPkgs() )
56     {
57         headers << _( "Avail. Ver." ); _versionCol       = numCol++;
58         headers <<  _( "Inst. Ver."  ); _instVersionCol = numCol++;
59     }
60     else
61     {
62         headers <<   _( "Version"       );      _versionCol     = numCol++;
63         _instVersionCol = -1;
64     }
65
66 #if SOURCE_RPM_DISABLED
67 #warning Selecting source RPMs disabled!
68 #else
69     headers <<  _( "Source" );          _srpmStatusCol  = numCol++;
70 #endif
71     setHeaderLabels(headers);
72     saveColumnWidths();
73     //FIXME sort( nameCol() );
74     //FIXME setColumnAlignment( sizeCol(), Qt::AlignRight );
75     setAllColumnsShowFocus( true );
76
77     createActions();
78
79     createSourceRpmContextMenu();
80 }
81
82
83 YQPkgList::~YQPkgList()
84 {
85     // NOP
86 }
87
88
89 void YQPkgList::addPkgItem( ZyppSel selectable,
90                             ZyppPkg zyppPkg )
91 {
92     addPkgItem( selectable, zyppPkg, false );
93 }
94
95
96 void YQPkgList::addPkgItemDimmed( ZyppSel selectable,
97                                   ZyppPkg zyppPkg )
98 {
99     addPkgItem( selectable, zyppPkg, true );
100 }
101
102
103 void
104 YQPkgList::addPkgItem( ZyppSel  selectable,
105                        ZyppPkg  zyppPkg,
106                        bool     dimmed )
107 {
108     if ( ! selectable )
109     {
110         y2error( "NULL zypp::ui::Selectable!" );
111         return;
112     }
113
114     YQPkgListItem * item = new YQPkgListItem( this, selectable, zyppPkg );
115     Q_CHECK_PTR( item );
116
117     item->setDimmed( dimmed );
118     applyExcludeRules( item );
119 }
120
121
122 bool
123 YQPkgList::haveInstalledPkgs()
124 {
125     for ( ZyppPoolIterator it = zyppPkgBegin();
126           it != zyppPkgEnd();
127           ++it )
128     {
129         if ( (*it)->installedObj() )
130             return true;
131     }
132
133     return false;
134 }
135
136
137 void
138 YQPkgList::pkgObjClicked( int                   button,
139                           QTreeWidgetItem *     listViewItem,
140                           int                   col,
141                           const QPoint &        pos )
142 {
143     if ( col == srpmStatusCol() )
144     {
145         YQPkgListItem * item = dynamic_cast<YQPkgListItem *> (listViewItem);
146
147         if ( item )
148         {
149             if ( button == Qt::LeftButton )
150             {
151                 if ( editable() && item->editable() )
152                     item->toggleSourceRpmStatus();
153                 return;
154             }
155             else if ( button == Qt::RightButton )
156             {
157                 if ( editable() && item->editable() )
158                 {
159                     updateActions( item );
160
161                     if ( _sourceRpmContextMenu )
162                         _sourceRpmContextMenu->popup( pos );
163                 }
164
165                 return;
166             }
167         }
168     }
169
170     YQPkgObjList::pkgObjClicked( button, listViewItem, col, pos );
171 }
172
173
174 QSize
175 YQPkgList::sizeHint() const
176 {
177     return QSize( 600, 350 );
178 }
179
180
181 void
182 YQPkgList::createSourceRpmContextMenu()
183 {
184     _sourceRpmContextMenu = new QMenu( this );
185
186     _sourceRpmContextMenu->addAction(actionInstallSourceRpm);
187     _sourceRpmContextMenu->addAction(actionDontInstallSourceRpm);
188
189     QMenu * submenu = new QMenu( _sourceRpmContextMenu );
190     Q_CHECK_PTR( submenu );
191     QAction *action = _sourceRpmContextMenu->addMenu( submenu );
192     action->setText(_( "&All in This List" ));
193
194     submenu->addAction(actionInstallListSourceRpms);
195     submenu->addAction(actionDontInstallListSourceRpms);
196 }
197
198
199 void
200 YQPkgList::setInstallCurrentSourceRpm( bool installSourceRpm,
201                                        bool selectNextItem )
202 {
203 #if FIXME
204     QTreeWidgetItem * listViewItem = selectedItem();
205
206     if ( ! listViewItem )
207         return;
208
209     YQPkgListItem * item = dynamic_cast<YQPkgListItem *> (listViewItem);
210
211     if ( item )
212     {
213         item->setInstallSourceRpm( installSourceRpm );
214
215         if ( selectNextItem && item->nextSibling() )
216         {
217             item->setSelected( false );                 // doesn't emit signals
218             setSelected( item->nextSibling(), true );   // emits signals
219         }
220     }
221 #endif
222 }
223
224
225 void
226 YQPkgList::setInstallListSourceRpms( bool installSourceRpm )
227 {
228     if ( ! _editable )
229         return;
230
231 #if FIXME
232     QTreeWidgetItem * listViewItem = firstChild();
233
234     while ( listViewItem )
235     {
236         YQPkgListItem * item = dynamic_cast<YQPkgListItem *> (listViewItem);
237
238         if ( item && item->editable() )
239         {
240             item->setInstallSourceRpm( installSourceRpm );
241         }
242
243         listViewItem = listViewItem->nextSibling();
244     }
245 #endif
246 }
247
248
249
250 void
251 YQPkgList::createNotInstalledContextMenu()
252 {
253     _notInstalledContextMenu = new QMenu( this );
254     Q_CHECK_PTR( _notInstalledContextMenu );
255
256     _notInstalledContextMenu->addAction(actionSetCurrentInstall);
257     _notInstalledContextMenu->addAction(actionSetCurrentDontInstall);
258     _notInstalledContextMenu->addAction(actionSetCurrentTaboo);
259
260     addAllInListSubMenu( _notInstalledContextMenu );
261
262
263     _notInstalledContextMenu->addSeparator();
264     _notInstalledContextMenu->addAction( _( "Export This List to &Text File..." ),
265                                           this, SLOT( askExportList() ) );
266 }
267
268
269 void
270 YQPkgList::createInstalledContextMenu()
271 {
272     _installedContextMenu = new QMenu( this );
273     Q_CHECK_PTR( _installedContextMenu );
274
275     _installedContextMenu->addAction(actionSetCurrentKeepInstalled);
276     _installedContextMenu->addAction(actionSetCurrentDelete);
277     _installedContextMenu->addAction(actionSetCurrentUpdate);
278     _installedContextMenu->addAction(actionSetCurrentProtected);
279
280     addAllInListSubMenu( _installedContextMenu );
281
282     _installedContextMenu->addSeparator();
283     _installedContextMenu->addAction( _( "Export This List to &Text File..." ),
284                                        this, SLOT( askExportList() ) );
285 }
286
287
288 QMenu *
289 YQPkgList::addAllInListSubMenu( QMenu * menu )
290 {
291     QMenu * submenu = new QMenu( menu );
292     Q_CHECK_PTR( submenu );
293
294     submenu->addAction(actionSetListInstall);
295     submenu->addAction(actionSetListDontInstall);
296     submenu->addAction(actionSetListKeepInstalled);
297     submenu->addAction(actionSetListDelete);
298     submenu->addAction(actionSetListDelete);
299     submenu->addAction(actionSetListUpdate);
300     submenu->addAction(actionSetListUpdateForce);
301     submenu->addAction(actionSetListTaboo);
302     submenu->addAction(actionSetListProtected);
303
304     QAction *action = menu->addMenu( submenu );
305     action->setText(_( "&All in This List" ));
306
307     return submenu;
308 }
309
310
311 void
312 YQPkgList::createActions()
313 {
314     actionInstallSourceRpm              = createAction( _( "&Install Source" ),
315                                                         statusIcon( S_Install, true ),
316                                                         statusIcon( S_Install, false ) );
317
318     actionDontInstallSourceRpm          = createAction( _( "Do &Not Install Source" ),
319                                                         statusIcon( S_NoInst, true ),
320                                                         statusIcon( S_NoInst, false ) );
321
322     actionInstallListSourceRpms         = createAction( _( "&Install All Available Sources" ),
323                                                         statusIcon( S_Install, true ),
324                                                         statusIcon( S_Install, false ),
325                                                         QString::null,          // key
326                                                         true );                 // enabled
327
328     actionDontInstallListSourceRpms     = createAction( _( "Do &Not Install Any Sources" ),
329                                                         statusIcon( S_NoInst, true ),
330                                                         statusIcon( S_NoInst, false ),
331                                                         QString::null,          // key
332                                                         true );                 // enabled
333
334     connect( actionInstallSourceRpm,            SIGNAL( activated() ), this, SLOT( setInstallCurrentSourceRpm()     ) );
335     connect( actionDontInstallSourceRpm,        SIGNAL( activated() ), this, SLOT( setDontInstallCurrentSourceRpm() ) );
336
337     connect( actionInstallListSourceRpms,       SIGNAL( activated() ), this, SLOT( setInstallListSourceRpms()       ) );
338     connect( actionDontInstallListSourceRpms,   SIGNAL( activated() ), this, SLOT( setDontInstallListSourceRpms()   ) );
339 }
340
341
342 void
343 YQPkgList::updateActions( YQPkgObjListItem * pkgObjListItem )
344 {
345     YQPkgObjList::updateActions( pkgObjListItem );
346
347     YQPkgListItem * item = dynamic_cast<YQPkgListItem *> (pkgObjListItem);
348
349     if ( item )
350     {
351         actionInstallSourceRpm->setEnabled( item->hasSourceRpm() );
352         actionDontInstallSourceRpm->setEnabled( item->hasSourceRpm() );
353     }
354     else
355     {
356         actionInstallSourceRpm->setEnabled( false );
357         actionDontInstallSourceRpm->setEnabled( false );
358     }
359 }
360
361
362 void
363 YQPkgList::askExportList() const
364 {
365     QString filename = YQUI::ui()->askForSaveFileName( "pkglist.txt",   // startsWith
366                                                            "*.txt",             // filter
367                                                            _( "Export Package List" ) );
368     if ( ! filename.isEmpty() )
369         exportList( filename, true );
370 }
371
372
373 void
374 YQPkgList::exportList( const QString filename, bool interactive ) const
375 {
376     // Open file
377
378     QFile file(filename);
379     file.open(QIODevice::WriteOnly);
380
381     if ( file.error() != QFile::NoError )
382     {
383         y2error( "Can't open file %s", qPrintable(filename) );
384
385         if ( interactive )
386         {
387             // Post error popup.
388
389             QMessageBox::warning( 0,                                            // parent
390                                   _( "Error" ),                                 // caption
391                                   _( "Cannot open file %1" ).arg( filename ),
392                                   QMessageBox::Ok | QMessageBox::Default,       // button0
393                                   QMessageBox::NoButton,                        // button1
394                                   QMessageBox::NoButton );                      // button2
395         }
396         return;
397     }
398
399
400     //
401     // Write header
402     //
403
404     // Format the header line with QString::sprintf() because plain stdio
405     // fprintf() is not UTF-8 aware - it will count multi-byte characters
406     // wrong, so the formatting will be broken.
407
408     QString header;
409     header.sprintf( "# %-18s %-30s | %10s | %-16s | %-16s\n\n",
410                     (const char *) _( "Status"      ).toUtf8(),
411                     (const char *) _( "Package"     ).toUtf8(),
412                     (const char *) _( "Size"        ).toUtf8(),
413                     (const char *) _( "Avail. Ver." ).toUtf8(),
414                     (const char *) _( "Inst. Ver."  ).toUtf8()
415                     );
416     file.write(header.toUtf8());
417
418
419     //
420     // Write all items
421     //
422
423 #if FIXME
424     const QTreeWidgetItem * item = firstChild();
425
426     while ( item )
427     {
428         const YQPkgListItem * pkg = dynamic_cast<const YQPkgListItem *> (item);
429
430         if ( pkg )
431         {
432             QString candVersion = pkg->text( versionCol()     );
433             QString instVersion = pkg->text( instVersionCol() );
434
435             if ( candVersion.isEmpty() ) candVersion = "---";
436             if ( instVersion.isEmpty() ) instVersion = "---";
437
438             QString status = "[" + statusText( pkg->status() ) + "]";
439       QString format;
440             format.sprintf("%-20s %-30s | %10s | %-16s | %-16s\n",
441                      (const char *) status.toUtf8(),
442                      (const char *) pkg->text( nameCol()   ),
443                      (const char *) pkg->text( sizeCol()   ),
444                      (const char *) candVersion,
445                      (const char *) instVersion
446                      );
447       file.write(format.toUtf8());
448         }
449
450         item = item->nextSibling();
451     }
452
453 #endif
454     // Clean up
455
456     if ( file.isOpen() )
457       file.close();
458 }
459
460
461 int
462 YQPkgList::globalSetPkgStatus( ZyppStatus newStatus, bool force, bool countOnly )
463 {
464     YQUI::ui()->busyCursor();
465     int changedCount = 0;
466
467     for ( ZyppPoolIterator it = zyppPkgBegin();
468           it != zyppPkgEnd();
469           ++it )
470     {
471         ZyppSel    selectable = *it;
472         ZyppStatus oldStatus  = selectable->status();
473
474         if ( newStatus != oldStatus )
475         {
476             bool doChange = false;
477
478             switch ( newStatus )
479             {
480                 case S_KeepInstalled:
481                 case S_Del:
482                 case S_AutoDel:
483                 case S_Protected:
484                     doChange = selectable->hasInstalledObj();
485                     break;
486
487                 case S_Update:
488                 case S_AutoUpdate:
489
490                     if ( force )
491                     {
492                         doChange = selectable->hasInstalledObj();
493                     }
494                     else // don't force - update only if useful (if candidate is newer)
495                     {
496                         const ZyppObj candidate = selectable->candidateObj();
497                         const ZyppObj installed = selectable->installedObj();
498
499                         if ( candidate && installed )
500                         {
501                             doChange = ( installed->edition() < candidate->edition() );
502                         }
503                     }
504                     break;
505
506                 case S_Install:
507                 case S_AutoInstall:
508                 case S_NoInst:
509                 case S_Taboo:
510                     doChange = ! selectable->hasInstalledObj();
511                     break;
512             }
513
514             if ( doChange )
515             {
516                 if ( ! countOnly )
517                     selectable->set_status( newStatus );
518
519                 changedCount++;
520                 // y2milestone( "Updating %s", selectable->name().c_str() );
521             }
522         }
523     }
524
525     if ( changedCount > 0 && ! countOnly )
526     {
527         emit updateItemStates();
528         emit updatePackages();
529         emit statusChanged();
530     }
531
532     YQUI::ui()->normalCursor();
533
534     return changedCount;
535 }
536
537
538
539
540
541
542 YQPkgListItem::YQPkgListItem( YQPkgList *               pkgList,
543                               ZyppSel   selectable,
544                               ZyppPkg   zyppPkg )
545     : YQPkgObjListItem( pkgList, selectable, zyppPkg )
546     , _pkgList( pkgList )
547     , _zyppPkg( zyppPkg )
548     , _dimmed( false )
549 {
550     if ( ! _zyppPkg )
551         _zyppPkg = tryCastToZyppPkg( selectable->theObj() );
552
553     setSourceRpmIcon();
554 }
555
556
557 YQPkgListItem::~YQPkgListItem()
558 {
559     // NOP
560 }
561
562
563 void
564 YQPkgListItem::updateData()
565 {
566     YQPkgObjListItem::updateData();
567     setSourceRpmIcon();
568 }
569
570
571 bool
572 YQPkgListItem::hasSourceRpm() const
573 {
574     if ( ! selectable() )
575         return false;
576
577 #ifdef FIXME
578     return selectable()->providesSources();
579 #else
580     return false;
581 #endif
582 }
583
584
585 bool
586 YQPkgListItem::installSourceRpm() const
587 {
588     if ( ! selectable() )
589         return false;
590
591 #ifdef FIXME
592     if ( ! selectable()->providesSources() )
593         return false;
594
595     return selectable()->source_install();
596 #else
597     return false;
598 #endif
599 }
600
601
602 void
603 YQPkgListItem::setSourceRpmIcon()
604 {
605     if ( srpmStatusCol() < 0 )
606         return;
607
608     QPixmap icon;
609
610     if ( hasSourceRpm() )
611     {
612
613         if ( editable() && _pkgObjList->editable() )
614         {
615             icon = installSourceRpm() ?
616                 YQIconPool::pkgInstall() :
617                 YQIconPool::pkgNoInst();
618         }
619         else
620         {
621             icon = installSourceRpm() ?
622                 YQIconPool::disabledPkgInstall() :
623                 YQIconPool::disabledPkgNoInst();
624         }
625     }
626 #if FIXME
627     setPixmap( srpmStatusCol(), icon );
628 #endif
629 }
630
631
632 void
633 YQPkgListItem::setInstallSourceRpm( bool installSourceRpm )
634 {
635     if ( hasSourceRpm() )
636     {
637 #ifdef FIXME
638         if ( selectable() )
639             selectable()->set_source_install( installSourceRpm );
640 #endif
641     }
642
643     setSourceRpmIcon();
644 }
645
646
647 void
648 YQPkgListItem::toggleSourceRpmStatus()
649 {
650     setInstallSourceRpm( ! installSourceRpm() );
651 }
652
653
654 QString
655 YQPkgListItem::toolTip( int col )
656 {
657     QString text;
658     QString name = _zyppObj->name().c_str();
659
660     if ( col == statusCol() )
661     {
662         text = YQPkgObjListItem::toolTip( col );
663     }
664     else if ( col == srpmStatusCol() )
665     {
666         text = name + "\n\n";
667
668         if ( hasSourceRpm() )
669         {
670             text += installSourceRpm() ?
671                 _( "Install Sources" ) :
672                 _( "Do Not Install Sources" );
673         }
674         else
675         {
676             text += _( "No Sources Available" );
677         }
678     }
679     else
680     {
681         text = name + "\n\n";
682
683         QString installed;
684         QString candidate;
685
686         if ( selectable()->hasInstalledObj() )
687         {
688             installed  = selectable()->installedObj()->edition().asString().c_str();
689             installed += "-";
690             installed +=  selectable()->installedObj()->arch().asString().c_str();
691             installed  = _( "Installed Version: %1" ).arg( installed );
692         }
693
694         if (  selectable()->hasCandidateObj() )
695         {
696             candidate  = selectable()->candidateObj()->edition().asString().c_str();
697             candidate += "-";
698             candidate +=  selectable()->candidateObj()->arch().asString().c_str();
699         }
700
701         if ( selectable()->hasInstalledObj() )
702         {
703             text += installed + "\n";
704
705             if ( selectable()->hasCandidateObj() )
706             {
707                 // Translators: This is the relation between two versions of one package
708                 // if both versions are the same, e.g., both "1.2.3-42", "1.2.3-42"
709                 QString relation = _( "same" );
710
711                 if ( _candidateIsNewer )        relation = _( "newer" );
712                 if ( _installedIsNewer )        relation = _( "older" );
713
714                 // Translators: %1 is the version, %2 is one of "newer", "older", "same"
715                 text += _( "Available Version: %1 (%2)" ).arg( candidate ).arg( relation );
716             }
717             else
718             {
719                 text += _( "Not available for installation" );
720             }
721         }
722         else // not installed
723         {
724             text += candidate;
725         }
726     }
727
728     return text;
729 }
730
731
732
733 /**
734  * Comparison function used for sorting the list.
735  * Returns:
736  * -1 if this <  other
737  *  0 if this == other
738  * +1 if this >  other
739  **/
740 int
741 YQPkgListItem::compare( QTreeWidgetItem *               otherListViewItem,
742                         int                     col,
743                         bool                    ascending ) const
744 {
745     if ( col == srpmStatusCol() )
746     {
747         YQPkgListItem * other = dynamic_cast<YQPkgListItem *> (otherListViewItem);
748
749         if ( other )
750         {
751             int thisPoints  = ( this->hasSourceRpm()  ? 1 : 0 ) + ( this->installSourceRpm()  ? 1 : 0 );
752             int otherPoints = ( other->hasSourceRpm() ? 1 : 0 ) + ( other->installSourceRpm() ? 1 : 0 );
753
754             // Intentionally inverting order: Pkgs with source RPMs are more interesting than without.
755             if ( thisPoints > otherPoints ) return -1;
756             if ( thisPoints < otherPoints ) return  1;
757             return 0;
758         }
759     }
760
761     // Fallback: Use parent class method
762     return YQPkgObjListItem::compare( otherListViewItem, col, ascending );
763 }
764
765 #if 0
766 void
767 YQPkgListItem::paintCell( QPainter *            painter,
768                           const QColorGroup &   colorGroup,
769                           int                   column,
770                           int                   width,
771                           int                   alignment )
772 {
773 #if FIXME
774     if ( isDimmed() && ! YQUI::ui()->usingVisionImpairedPalette() )
775     {
776         QColorGroup cg = colorGroup;
777         cg.setColor( QColorGroup::Text, QColor( 0xA0, 0xA0, 0xA0 ) );
778
779         QTreeWidgetItem::paintCell( painter, cg, column, width, alignment );
780     }
781     else
782     {
783         if ( installedIsNewer() )
784         {
785             QColorGroup cg = colorGroup;
786
787             if ( ! YQUI::ui()->usingVisionImpairedPalette() )
788             {
789                 if ( column == instVersionCol() )
790                     cg.setColor( QColorGroup::Base, QColor( 0xFF, 0x30, 0x30 ) );       // Background
791                 else
792                     cg.setColor( QColorGroup::Text, QColor( 0xFF, 0, 0 ) );             // Foreground
793             }
794
795             QTreeWidgetItem::paintCell( painter, cg, column, width, alignment );
796         }
797         else if ( candidateIsNewer() )
798         {
799             QColorGroup cg = colorGroup;
800
801             if ( ! YQUI::ui()->usingVisionImpairedPalette() )
802             {
803                 cg.setColor( QColorGroup::Text, QColor( 0, 0, 0xC0 ) );                 // Foreground
804
805                 if ( column == versionCol() )
806                     cg.setColor( QColorGroup::Base, QColor( 0xF0, 0xF0, 0xF0 ) );       // Background
807             }
808
809             QTreeWidgetItem::paintCell( painter, cg, column, width, alignment );
810         }
811         else
812         {
813             QTreeWidgetItem::paintCell( painter, colorGroup, column, width, alignment );
814         }
815     }
816 #endif
817 }
818 #endif
819
820
821 #include "YQPkgList.moc"