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