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