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