]> icculus.org git repositories - duncan/yast2-qt4.git/blob - src/pkg/YQPkgObjList.h
restart qt4 porting
[duncan/yast2-qt4.git] / src / pkg / YQPkgObjList.h
1 /*---------------------------------------------------------------------\
2 |                                                                      |
3 |                      __   __    ____ _____ ____                      |
4 |                      \ \ / /_ _/ ___|_   _|___ \                     |
5 |                       \ V / _` \___ \ | |   __) |                    |
6 |                        | | (_| |___) || |  / __/                     |
7 |                        |_|\__,_|____/ |_| |_____|                    |
8 |                                                                      |
9 |                               core system                            |
10 |                                                        (C) SuSE GmbH |
11 \----------------------------------------------------------------------/
12
13   File:       YQPkgObjList.h
14
15   Author:     Stefan Hundhammer <sh@suse.de>
16
17 /-*/
18
19
20 #ifndef YQPkgObjList_h
21 #define YQPkgObjList_h
22
23 #include <qpixmap.h>
24 #include <qregexp.h>
25 #include <map>
26 #include <list>
27 #include <QY2ListView.h>
28 #include "YQZypp.h"
29 #include <zypp/Edition.h>
30 #include <FSize.h>
31
32 class YQPkgObjListItem;
33 class QAction;
34 class QPopupMenu;
35 using std::string;
36 using std::list;
37
38
39 /**
40  * @short Abstract base class to display a list of zypp::ResObjects.
41  * Handles most generic stuff like setting status etc.
42  **/
43 class YQPkgObjList : public QY2ListView
44 {
45     Q_OBJECT
46
47 protected:
48     /**
49      * Constructor. Does not add any QListView columns!
50      **/
51     YQPkgObjList( QWidget * parent );
52
53     /**
54      * Destructor
55      **/
56     virtual ~YQPkgObjList();
57
58
59 public:
60
61     // Column numbers
62
63     int statusCol()             const   { return _statusCol;            }
64     int nameCol()               const   { return _nameCol;              }
65     int summaryCol()            const   { return _summaryCol;           }
66     int sizeCol()               const   { return _sizeCol;              }
67     int versionCol()            const   { return _versionCol;           }
68     int instVersionCol()        const   { return _instVersionCol;       }
69     int brokenIconCol()         const   { return _brokenIconCol;        }
70     int satisfiedIconCol()      const   { return _satisfiedIconCol;     }
71
72     /**
73      * Return whether or not items in this list are generally editable,
74      * i.e. the user can change their status. Note that individual items can be
75      * set to non-editable even if the list is generally editable.
76      * Lists are editable by default.
77      **/
78     bool editable() const { return _editable; }
79
80     /**
81      * Set the list's editable status.
82      **/
83     void setEditable( bool editable = true ) { _editable = editable; }
84
85     /**
86      * Sets the currently selected item's status.
87      * Automatically selects the next item if 'selectNextItem' is 'true'.
88      **/
89     void setCurrentStatus( ZyppStatus   newStatus,
90                            bool                 selectNextItem = false );
91
92     /**
93      * Sets the status of all (toplevel) list items to 'newStatus', if possible.
94      * Only one single statusChanged() signal is emitted.
95      *
96      * 'force' overrides sensible defaults like setting only zypp::ResObjects to
97      * 'update' that really come with a newer version.
98      **/
99     void setAllItemStatus( ZyppStatus newStatus, bool force = false );
100
101     /**
102      * Add a submenu "All in this list..." to 'menu'.
103      * Returns the newly created submenu.
104      **/
105     virtual QPopupMenu * addAllInListSubMenu( QPopupMenu * menu );
106
107     /**
108      * Returns the suitable icon for a zypp::ResObject status - the regular
109      * icon if 'enabled' is 'true' or the insensitive icon if 'enabled' is
110      * 'false.  'bySelection' is relevant only for auto-states: This uses the
111      * icon for 'auto-by-selection" rather than the default auto-icon.
112      **/
113     virtual QPixmap statusIcon( ZyppStatus status,
114                                 bool            enabled     = true,
115                                 bool            bySelection = false );
116
117     /**
118      * Returns a short (one line) descriptive text for a zypp::ResObject status.
119      **/
120     virtual QString statusText( ZyppStatus status ) const;
121
122
123     class ExcludeRule;
124
125     /**
126      * Add an exclude rule to this list.
127      **/
128     void addExcludeRule( YQPkgObjList::ExcludeRule * rule );
129
130     /**
131      * Apply all exclude rules of this list to all items,
132      * including those that are currently excluded.
133      **/
134     void applyExcludeRules();
135
136     /**
137      * Apply all exclude rules of this list to one item.
138      **/
139     void applyExcludeRules( QListViewItem * );
140
141     /**
142      * Exclude or include an item, i.e. remove it from the visible items
143      * and add it to the internal exclude list or vice versa.
144      **/
145     void exclude( YQPkgObjListItem * item, bool exclude );
146
147
148 public slots:
149
150     /**
151      * Add a zypp::ResObject to the list. Connect a filter's filterMatch()
152      * signal to this slot. Remember to connect filterStart() to clear()
153      * (inherited from QListView).
154      *
155      * 'zyppObj' has to be one of the objects of 'selectable'. If it is 0,
156      * selectable->theObject() will be used.
157      *
158      * Intentionally NOT named addItem() so the calling class cannot confuse
159      * this method with overlaid methods of the same name that were simply
160      * forgotten to implement!
161      **/
162     void addPkgObjItem( ZyppSel selectable,
163                         ZyppObj zyppObj = 0 );
164
165     /**
166      * Add a purely passive list item that has a name and optional summary and
167      * size.
168      **/
169     void addPassiveItem( const QString & name,
170                          const QString & summary = QString::null,
171                          FSize           size    = -1 );
172
173     /**
174      * Dispatcher slot for mouse click: cycle status depending on column.
175      **/
176     virtual void pkgObjClicked( int             button,
177                                 QListViewItem * item,
178                                 int             col,
179                                 const QPoint &  pos );
180
181     /**
182      * Reimplemented from QY2ListView:
183      * Emit selectionChanged() signal after clearing the list.
184      **/
185     virtual void clear();
186
187     /**
188      * Update the internal actions: What actions are available for 'item'?
189      **/
190     virtual void updateActions( YQPkgObjListItem * item );
191
192     /**
193      * Update the internal actions for the currently selected item ( if any ).
194      * This only calls updateActions( YQPkgObjListItem * ) with the currently
195      * selected item as argument, so there is normally no need to reimplement
196      * this method, too, if the other one is reimplemented.
197      **/
198     virtual void updateActions();
199
200     /**
201      * Emit an updatePackages() signal.
202      **/
203     void sendUpdatePackages() { emit updatePackages(); }
204
205     /**
206      * Select the next item, i.e. move the selection one item further down the
207      * list.
208      **/
209     void selectNextItem();
210
211     /**
212      * Emit a statusChanged() signal for the specified zypp::ResObject.
213      **/
214     void sendStatusChanged() { emit statusChanged(); }
215
216     /**
217      * Display a one-line message in the list.
218      **/
219     virtual void message( const QString & text );
220
221     /**
222      * Write statistics about excluded items to the log, if there are any.
223      **/
224     void logExcludeStatistics();
225     
226
227     // Direct access to some states for menu actions
228
229     void setCurrentInstall()       { setCurrentStatus( S_Install        ); }
230     void setCurrentDontInstall()   { setCurrentStatus( S_NoInst         ); }
231     void setCurrentKeepInstalled() { setCurrentStatus( S_KeepInstalled  ); }
232     void setCurrentDelete()        { setCurrentStatus( S_Del            ); }
233     void setCurrentUpdate()        { setCurrentStatus( S_Update         ); }
234     void setCurrentTaboo()         { setCurrentStatus( S_Taboo          ); }
235     void setCurrentProtected()     { setCurrentStatus( S_Protected      ); }
236
237     void setListInstall()          { setAllItemStatus( S_Install        ); }
238     void setListDontInstall()      { setAllItemStatus( S_NoInst         ); }
239     void setListKeepInstalled()    { setAllItemStatus( S_KeepInstalled  ); }
240     void setListDelete()           { setAllItemStatus( S_Del            ); }
241     void setListUpdate()           { setAllItemStatus( S_Update         ); }
242     void setListUpdateForce()      { setAllItemStatus( S_Update, true   ); }
243     void setListTaboo()            { setAllItemStatus( S_Taboo          ); }
244     void setListProtected()        { setAllItemStatus( S_Protected      ); }
245
246
247 protected slots:
248
249     /**
250      * Dispatcher slot for selection change - internal only.
251      **/
252     virtual void selectionChangedInternal( QListViewItem * item );
253
254
255 signals:
256
257
258     /**
259      * Emitted when a zypp::ui::Selectable is selected.
260      * May be called with a null poiner if no zypp::ResObject is selected.
261      **/
262     void selectionChanged( ZyppSel selectable );
263
264     /**
265      * Emitted when the status of a zypp::ResObject is changed.
266      **/
267     void statusChanged();
268
269     /**
270      * Emitted when it's time to update displayed package information,
271      * e.g., package states.
272      **/
273     void updatePackages();
274
275
276 protected:
277
278     /**
279      * Event handler for keyboard input.
280      * Only very special keys are processed here.
281      *
282      * Reimplemented from QListView / QWidget.
283      **/
284     virtual void keyPressEvent( QKeyEvent * ev );
285
286     /**
287      * Returns the context menu for items that are not installed.
288      * Creates the menu upon the first call.
289      **/
290     virtual QPopupMenu * installedContextMenu();
291
292     /**
293      * Returns the context menu for items that are installed.
294      * Creates the menu upon the first call.
295      **/
296     virtual QPopupMenu * notInstalledContextMenu();
297
298     /**
299      * Create the context menu for items that are not installed.
300      **/
301     virtual void createNotInstalledContextMenu();
302
303     /**
304      * Create the context menu for installed items.
305      **/
306     virtual void createInstalledContextMenu();
307
308     /**
309      * Create the actions for the context menus.
310      * Note: This is intentionally not virtual!
311      **/
312     void createActions();
313
314     /**
315      * Create an action based on a zypp::ResObject status - automatically
316      * retrieve the corresponding status icons (both sensitive and insensitive)
317      * and text.  'key' is only a descriptive text, no true accelerator.
318      **/
319     QAction * createAction( ZyppStatus  status,
320                             const QString &     key     = QString::null,
321                             bool                enabled = false );
322
323     /**
324      * Low-level: Create an action.
325      * 'key' is only a descriptive text, no true accelerator.
326      **/
327     QAction * createAction( const QString &     text,
328                             const QPixmap &     icon            = QPixmap(),
329                             const QPixmap &     insensitiveIcon = QPixmap(),
330                             const QString &     key             = QString::null,
331                             bool                enabled         = false );
332
333     class ExcludedItems;
334
335     // Data members
336
337     int         _statusCol;
338     int         _nameCol;
339     int         _summaryCol;
340     int         _sizeCol;
341     int         _versionCol;
342     int         _instVersionCol;
343     int         _brokenIconCol;
344     int         _satisfiedIconCol;
345     bool        _editable;
346     bool        _debug;
347
348     typedef list<ExcludeRule *> ExcludeRuleList;
349     
350     ExcludeRuleList     _excludeRules;
351     ExcludedItems *     _excludedItems;
352
353     QPopupMenu *        _installedContextMenu;
354     QPopupMenu *        _notInstalledContextMenu;
355
356
357 public:
358
359     QAction *           actionSetCurrentInstall;
360     QAction *           actionSetCurrentDontInstall;
361     QAction *           actionSetCurrentKeepInstalled;
362     QAction *           actionSetCurrentDelete;
363     QAction *           actionSetCurrentUpdate;
364     QAction *           actionSetCurrentTaboo;
365     QAction *           actionSetCurrentProtected;
366
367     QAction *           actionSetListInstall;
368     QAction *           actionSetListDontInstall;
369     QAction *           actionSetListKeepInstalled;
370     QAction *           actionSetListDelete;
371     QAction *           actionSetListUpdate;
372     QAction *           actionSetListUpdateForce;
373     QAction *           actionSetListTaboo;
374     QAction *           actionSetListProtected;
375
376
377 public:
378
379 };
380
381
382
383 class YQPkgObjListItem: public QY2ListViewItem
384 {
385 public:
386
387     /**
388      * Constructor for root items: Creates a YQPkgObjList item that corresponds
389      * to the ZYPP selectable that 'selectable' refers to. 'zyppObj' has to be
390      * one object of 'selectable'.  If it is 0, selectable->theObject() will be
391      * used.
392      **/
393     YQPkgObjListItem( YQPkgObjList *    pkgObjList,
394                       ZyppSel           selectable,
395                       ZyppObj           zyppObj = 0 );
396
397 protected:
398     /**
399      * Constructor for non-root items.
400      **/
401     YQPkgObjListItem( YQPkgObjList *    pkgObjList,
402                       QY2ListViewItem * parent,
403                       ZyppSel           selectable,
404                       ZyppObj           zyppObj = 0 );
405
406 public:
407
408     /**
409      * Destructor
410      **/
411     virtual ~YQPkgObjListItem();
412
413     /**
414      * Returns the original selectable within the package manager backend.
415      **/
416     ZyppSel selectable() const { return _selectable; }
417
418     /**
419      * Returns the original object within the package manager backend.
420      **/
421     ZyppObj zyppObj() const { return _zyppObj; }
422
423     /**
424      * Return whether or not this items is editable, i.e. the user can change
425      * its status. This requires the corresponding list to be editable, too.
426      * Items are editable by default.
427      **/
428     bool editable() const { return _editable; }
429
430     /**
431      * Set this item's editable status.
432      **/
433     void setEditable( bool editable = true ) { _editable = editable; }
434
435     /**
436      * Returns the (binary RPM) package status
437      **/
438     ZyppStatus status() const;
439
440     /**
441      * Returns 'true' if this selectable's status is set by a selection
442      * (rather than by the user or by the dependency solver).
443      **/
444     bool bySelection() const;
445
446     /**
447      * Set the (binary RPM) package status.
448      *
449      * If 'sendSignals' is 'true' (default), the parent list will be requested
450      * to send update signals. List operations might want to use this for
451      * optimizations to send the signals only once after all changes are done.
452      **/
453     virtual void setStatus( ZyppStatus newStatus, bool sendSignals = true );
454
455     /**
456      * Set a status icon according to the package's status.
457      **/
458     virtual void setStatusIcon();
459
460     /**
461      * Update this item's status.
462      * Triggered by QY2ListView::updateAllItemStates().
463      * Overwritten from QY2ListViewItem.
464      **/
465     virtual void updateStatus();
466
467     /**
468      * Cycle the package status to the next valid value.
469      **/
470     virtual void cycleStatus();
471
472     /**
473      * Check if the candidate is newer than the installed version.
474      **/
475     bool candidateIsNewer() const { return _candidateIsNewer; }
476
477     /**
478      * Check if the installed version is newer than the candidate.
479      **/
480     bool installedIsNewer() const { return _installedIsNewer; }
481
482     /**
483      * Check if this item is satisfied, even though it is not installed.
484      * This is useful for package collections, e.g., patterns and patches:
485      * 'true' is returned if all requirements are fulfilled, but the object
486      * itself is not installed.
487      **/
488     bool isSatisfied() const;
489
490     /**
491      * Check if this item is "broken": If it is installed, but any of its
492      * dependencies are no longer satisfied.
493      * This is useful for package collections, e.g., patterns and patches.
494      **/
495     bool isBroken() const;
496
497     /**
498      * Display this item's notify text (if there is any) that corresponds to
499      * the specified status (S_Install, S_Del) in a pop-up window.
500      **/
501     void showNotifyTexts( ZyppStatus status );
502
503     /**
504      * Display a selectable's license agreement (if there is any) that
505      * corresponds to its current status (S_Install, S_Update) in a pop-up
506      * window.
507      *
508      * Returns 'true' if the user agreed to that license , 'false' otherwise.
509      * The item's status may have changed to S_Taboo, S_Proteced or S_Del if
510      * the user disagreed with the license.
511      **/
512     static bool showLicenseAgreement( ZyppSel sel );
513
514     /**
515      * Display this item's license agreement (if there is any) that corresponds
516      * to its current status (S_Install, S_Update) in a pop-up window.
517      **/
518     bool showLicenseAgreement();
519
520     /**
521      * Comparison function used for sorting the list.
522      * Returns:
523      * -1 if this <  other
524      *  0 if this == other
525      * +1 if this >  other
526      *
527      * Reimplemented from QListViewItem
528      **/
529     virtual int compare( QListViewItem *        other,
530                          int                    col,
531                          bool                   ascending ) const;
532
533     /**
534      * Calculate a numerical value to compare versions, based on version
535      * relations:
536      *
537      * - Installed newer than candidate (red)
538      * - Candidate newer than installed (blue) - worthwhile updating
539      * - Installed
540      * - Not installed, but candidate available
541      **/
542     int versionPoints() const;
543
544     /**
545      * Update this item's data completely.
546      * Triggered by QY2ListView::updateAllItemData().
547      *
548      * Reimplemented from QY2ListViewItem.
549      **/
550     virtual void updateData();
551
552     /**
553      * Returns a tool tip text for a specific column of this item.
554      * 'column' is -1 if the mouse pointer is in the tree indentation area.
555      *
556      * Reimplemented from QY2ListViewItem.
557      **/
558     virtual QString toolTip( int column );
559
560     /**
561      * Returns 'true' if this item is excluded.
562      **/
563     bool isExcluded() const { return _excluded; }
564
565     /**
566      * Set this item's exclude flag.
567      * Note that this is just a marker. It is the caller's responsibility
568      * to add or remove it from exclude lists etc.
569      **/
570     void setExcluded( bool exclude = true );
571
572
573     // Handle Debug isBroken and isSatisfied flags
574
575     bool debugIsBroken()    const               { return _debugIsBroken;                }
576     bool debugIsSatisfied() const               { return _debugIsSatisfied;             }
577     void setDebugIsBroken   ( bool val = true ) { _debugIsBroken = val;                 }
578     void setDebugIsSatisfied( bool val = true ) { _debugIsSatisfied = val;              }
579     void toggleDebugIsBroken()                  { _debugIsBroken = ! _debugIsBroken;    }
580     void toggleDebugIsSatisfied()               { _debugIsSatisfied = ! _debugIsSatisfied; }
581
582
583     // Columns
584
585     int statusCol()             const   { return _pkgObjList->statusCol();      }
586     int nameCol()               const   { return _pkgObjList->nameCol();        }
587     int summaryCol()            const   { return _pkgObjList->summaryCol();     }
588     int sizeCol()               const   { return _pkgObjList->sizeCol();        }
589     int versionCol()            const   { return _pkgObjList->versionCol();     }
590     int instVersionCol()        const   { return _pkgObjList->instVersionCol(); }
591     int brokenIconCol()         const   { return _pkgObjList->brokenIconCol();  }
592     int satisfiedIconCol()      const   { return _pkgObjList->satisfiedIconCol(); }
593
594
595 protected:
596
597     /**
598      * Initialize internal data and set fields accordingly.
599      **/
600     void init();
601
602     /**
603      * Apply changes hook. This is called each time the user changes the status
604      * of a list item manually (if the old status is different from the new
605      * one). Insert code to propagate changes to other objects here, for
606      * example to trigger a "small" solver run (Resolver::transactObjKind()
607      * etc.).
608      *
609      * This default implementation does nothing.
610      **/
611     virtual void applyChanges() {}
612
613     /**
614      * Do a "small" solver run for all "resolvable collections", i.e., for
615      * selections, patterns, languages, patches.
616      **/
617     void solveResolvableCollections();
618
619     /**
620      * Set a column text via STL string.
621      * ( QListViewItem::setText() expects a QString! )
622      **/
623     void setText( int column, const string text );
624
625     /**
626      * Re-declare ordinary setText() method so the compiler doesn't get
627      * confused which one to use.
628      **/
629     void setText( int column, const QString & text )
630         { QListViewItem::setText( column, text ); }
631
632     /**
633      * Set a column text via Edition.
634      **/
635     void setText( int column, const zypp::Edition & edition );
636
637
638     //
639     // Data members
640     //
641
642     YQPkgObjList *      _pkgObjList;
643     ZyppSel             _selectable;
644     ZyppObj             _zyppObj;
645     bool                _editable:1;
646     bool                _candidateIsNewer:1;
647     bool                _installedIsNewer:1;
648
649     bool                _debugIsBroken:1;
650     bool                _debugIsSatisfied:1;
651     bool                _excluded:1;
652 };
653
654
655
656 class YQPkgObjList::ExcludeRule
657 {
658 public:
659
660     /**
661      * Constructor: Creates a new exclude rule with a regular expression
662      * to check against the text of the specified column of each list
663      * entry.
664      *
665      * The parent YQPkgObjList will assume ownership of this exclude rule
666      * and destroy it when the parent is destroyed.
667      **/
668     ExcludeRule( YQPkgObjList *         parent,
669                  const QRegExp &        regexp,
670                  int                    column = 0 );
671
672     
673     // Intentionally omitting virtual destructor:
674     // No allocated objects, no other virtual methods,
675     // no need to have a vtable for each instance of this class.
676     //
677     // virtual ~ExcludeRule();
678
679     /**
680      * Enable or disable this exclude rule.
681      * New exclude rules are enabled by default.
682      **/
683     void enable( bool enable = true );
684
685     /**
686      * Returns 'true' if this exclude rule is enabled,
687      * 'false' otherwise.
688      **/
689     bool isEnabled() const { return _enabled; }
690
691     /**
692      * Change the regular expression after creation.
693      **/
694     void setRegexp( const QRegExp & regexp );
695
696     /**
697      * Returns the regexp.
698      **/
699     QRegExp regexp() const { return _regexp; };
700
701     /**
702      * Change the column number to check against after creation.
703      **/
704     void setColumn( int column = 0 );
705
706     /**
707      * Returns the column number.
708      **/
709     int column() const { return _column; }
710
711     /**
712      * Returns this exclude rule's parent YQPkgObjList.
713      **/
714     YQPkgObjList * parent() const { return _parent; }
715
716     /**
717      * Check a list item against this exclude rule. 
718      * Returns 'true' if the item matches this exclude rule,
719      * i.e. if it should be excluded.
720      **/
721     bool match( QListViewItem * item );
722
723 private:
724
725     YQPkgObjList *      _parent;
726     QRegExp             _regexp;
727     int                 _column;
728     bool                _enabled;
729 };
730
731
732 class YQPkgObjList::ExcludedItems
733 {
734 public:
735
736     typedef std::map <QListViewItem *, QListViewItem *> ItemMap;
737     typedef std::pair<QListViewItem *, QListViewItem *> ItemPair;
738     typedef ItemMap::iterator                           iterator;
739
740     /**
741      * Constructor
742      **/
743     ExcludedItems( YQPkgObjList * parent );
744
745     /**
746      * Destructor
747      **/
748     virtual ~ExcludedItems();
749
750     /**
751      * Add a list item to the excluded items and transfer ownership to this
752      * class.
753      *
754      * oldParent is the previous parent item of this item
755      * or 0 if it was a root item.
756      **/
757     void add( QListViewItem * item, QListViewItem * oldParent );
758
759     /**
760      * Remove a list item from the excluded items and transfer ownership back
761      * to the caller.
762      **/
763     void remove( QListViewItem * item );
764
765     /**
766      * Clear the excluded items. Delete all items still excluded.
767      **/
768     void clear();
769
770     /**
771      * Returns 'true' if the specified item is in the excluded items.
772      **/
773     bool contains( QListViewItem * item );
774
775     /**
776      * Returns the old parent of this item so it can be reparented
777      * or 0 if it was a root item.
778      **/
779     QListViewItem * oldParentItem( QListViewItem * item );
780
781     /**
782      * Returns the number of items
783      **/
784     int size() const { return (int) _excludeMap.size(); }
785
786     /**
787      * Returns an iterator that points to the first excluded item.
788      **/
789     iterator begin() { return _excludeMap.begin(); }
790
791     /**
792      * Returns an iterator that points after the last excluded item.
793      **/
794     iterator end()   { return _excludeMap.end(); }
795
796 private:
797
798     ItemMap             _excludeMap;
799     YQPkgObjList *      _pkgObjList;
800 };
801
802
803 #endif // ifndef YQPkgObjList_h