2f9c442ea9371ba9ab2d6ca12f20150af74eabf2
[duncan/yast2-qt4.git] / src / YQWizard.h
1 /*---------------------------------------------------------------------\
2 |                                                                      |
3 |                      __   __    ____ _____ ____                      |
4 |                      \ \ / /_ _/ ___|_   _|___ \                     |
5 |                       \ V / _` \___ \ | |   __) |                    |
6 |                        | | (_| |___) || |  / __/                     |
7 |                        |_|\__,_|____/ |_| |_____|                    |
8 |                                                                      |
9 |                               core system                            |
10 |                                                    (c) SuSE Linux AG |
11 \----------------------------------------------------------------------/
12
13   File:       YQWizard.h
14
15   Author:     Stefan Hundhammer <sh@suse.de>
16
17 /-*/
18
19
20 #ifndef YQWizard_h
21 #define YQWizard_h
22
23 #include "YWizard.h"
24 #include <q3vbox.h>
25 #include <qpixmap.h>
26 #include <q3ptrlist.h>
27 #include <qstringlist.h>
28 #include <q3dict.h>
29 #include "QY2ListView.h"
30 //Added by qt3to4:
31 #include <q3gridlayout.h>
32 #include <qlabel.h>
33 #include <q3popupmenu.h>
34 #include <qevent.h>
35
36 #include <string>
37 #include <vector>
38
39 class Q3GridLayout;
40 class QFrame;
41 class QLabel;
42 class QMenuBar;
43 class Q3PopupMenu;
44 class QPushButton;
45 class QSpacerItem;
46 class Q3TextBrowser;
47 class QToolButton;
48 class Q3WidgetStack;
49
50 class YQAlignment;
51 class YQReplacePoint;
52 class YQWizardButton;
53 class QY2ListView;
54
55
56 class YQWizard : public QFrame, public YWizard
57 {
58     Q_OBJECT
59
60 protected:
61     class Step;
62     class TreeItem;
63
64 public:
65     /**
66      * Constructor.
67      **/
68     YQWizard( YWidget *         parent,
69               YWidgetID *       backButtonId,   const string & backButtonLabel,
70               YWidgetID *       abortButtonId,  const string & abortButtonLabel,
71               YWidgetID *       nextButtonId,   const string & nextButtonLabel,
72               YWizardMode       wizardMode = YWizardMode_Standard );
73
74     /**
75      * Destructor.
76      **/
77     virtual ~YQWizard();
78
79
80     enum Direction { Forward, Backward };
81
82     /**
83      * Returns the current direction of wizard operations - going forward or
84      * going backward. This can be used to maintain a consistent direction when
85      * assigning default buttons to a dialog.
86      **/
87     Direction direction() const { return _direction; }
88
89     /**
90      * Generic direct access to implementation-specific functions.
91      * See YQWizard.cc for details.
92      *
93      * Returns 'true' on success, 'false' on failure.
94      * Reimplemented from YWizard.
95      **/
96     virtual YCPValue command( const YCPTerm & command );
97
98     /**
99      * Returns a descriptive label of this dialog instance for debugging.
100      *
101      * Reimplemented from YWidget.
102      **/
103     virtual string debugLabel();
104
105     /**
106      * Preferred width of the widget.
107      *
108      * Reimplemented from YWidget.
109      **/
110     virtual int preferredWidth();
111
112     /**
113      * Preferred height of the widget.
114      *
115      * Reimplemented from YWidget.
116      **/
117     virtual int preferredHeight();
118
119     /**
120      * Set the new size of the widget.
121      *
122      * Reimplemented from YWidget.
123      **/
124     virtual void setSize( int newWidth, int newHeight );
125
126     /**
127      * Event filter - inherited from QWidget.
128      **/
129     virtual bool eventFilter( QObject * obj, QEvent * ev );
130
131     /**
132      * Set a dialog icon. 0 is a valid value - it clears the current icon.
133      **/
134     void setDialogIcon( const char * iconName );
135
136     /**
137      * Set a dialog heading. 0 is a valid value - it clears the old text.
138      **/
139     void setDialogHeading( const QString & headingText );
140
141     /**
142      * Returns 'true' if this wizard was created with steps enabled, i.e. the
143      * side bar has a "steps" view.
144      **/
145     bool stepsEnabled() const { return _stepsEnabled; }
146
147     /**
148      * Add a step for the steps panel on the side bar.
149      * This only adds the step to the internal list of steps.
150      * The display is only updated upon calling updateSteps().
151      **/
152     void addStep( const QString & text, const QString & id );
153
154     /**
155      * Add a step heading for the steps panel on the side bar.
156      * This only adds the heading to the internal list of steps.
157      * The display is only updated upon calling updateSteps().
158      **/
159     void addStepHeading( const QString & text );
160
161     /**
162      * Delete all steps and step headings from the internal lists.
163      * The display is only updated upon calling updateSteps().
164      **/
165     void deleteSteps();
166
167     /**
168      * Set the current step. This also triggers updateSteps() if necessary.
169      **/
170     void setCurrentStep( const QString & id );
171
172     /**
173      * Update the steps display: Reflect the internal steps and heading lists
174      * in the layout.
175      **/
176     void updateSteps();
177
178     /**
179      * Returns 'true' if this wizard was created with a selection tree enabled,
180      * i.e. the side bar has a tree selection.
181      **/
182     bool treeEnabled() const { return _treeEnabled; }
183
184     /**
185      * Returns the wizard's "Next" (or "Accept") button.
186      **/
187     YQWizardButton * nextButton() const  { return _nextButton; }
188
189     /**
190      * Returns the wizard's "Back" button.
191      **/
192     YQWizardButton * backButton() const  { return _backButton; }
193
194     /**
195      * Returns the wizard's "Abort" button.
196      **/
197     YQWizardButton * abortButton() const { return _abortButton; }
198
199
200     /**
201      * Set wizard command verbosity
202      **/
203     void setVerboseCommands( bool verbose ) { _verboseCommands = verbose; }
204
205     /**
206      * Add a tree item. If "parentID" is an empty string, it will be a root
207      * item. 'text' is the text that will be displayed in the tree, 'id' the ID
208      * with which this newly created item can be referenced - and that will be
209      * returned when the user clicks on a tree item.
210      **/
211     void addTreeItem( const QString & parentID,
212                       const QString & text,
213                       const QString & id        );
214
215     /**
216      * Select the tree item with the specified ID, if such an item exists.
217      **/
218     void selectTreeItem( const QString & id );
219
220     /**
221      * Delete all tree items.
222      **/
223     void deleteTreeItems();
224
225
226     /**
227      * Add a menu to the menu bar. If the menu bar is not visible yet, it will
228      * be made visible. 'text' is the user-visible text for the menu bar
229      * (including keyboard shortcuts marked with '&'), 'id' is the menu ID for
230      * later addMenuEntry() etc. calls.
231      **/
232     void addMenu( const QString & text,
233                   const QString & id );
234
235     /**
236      * Add a submenu to the menu with ID 'parentMenuID'.
237      **/
238     void addSubMenu( const QString & parentMenuID,
239                      const QString & text,
240                      const QString & id );
241
242     /**
243      * Add a menu entry to the menu with ID 'parentMenuID'. 'id' is what will
244      * be returned by UI::UserInput() etc. when a user activates this menu entry.
245      **/
246     void addMenuEntry( const QString & parentMenuID,
247                        const QString & text,
248                        const QString & id );
249
250     /**
251      * Add a menu separator to a menu.
252      **/
253     void addMenuSeparator( const QString & parentMenuID );
254
255     /**
256      * Delete all menus and hide the menu bar.
257      **/
258     void deleteMenus();
259
260 signals:
261
262     /**
263      * Emitted when the "Back" or "Cancel" button is clicked.
264      **/
265     void backClicked();
266
267     /**
268      * Emitted when the "Abort" button is clicked.
269      **/
270     void abortClicked();
271
272     /**
273      * Emitted when the "Next" or "OK" button is clicked.
274      *
275      * Notice: As long as this signal is connected, the wizard will no longer
276      * send button events to the UI. Rather, the connected QObject has to take
277      * care to propagate those events.
278      * This is used in YQPatternSelector, for example. 
279      **/
280     void nextClicked();
281
282     
283 public slots:
284
285     /**
286      * Set the help text. 0 is a valid value - it clears the old text.
287      **/
288     void setHelpText( QString helpText );
289
290     /**
291      * Adapt the size of the client area (the ReplacePoint(`id(`contents)) to
292      * fit in its current space.
293      **/
294     void resizeClientArea();
295
296     /**
297      * Show the current help text.
298      *
299      * This is useful only if it is obscured by any wizard steps, but it can
300      * safely be called at any time.
301      **/
302     void showHelp();
303
304     /**
305      * Show the current wizard steps, if there are any. If there are none,
306      * nothing happens.
307      **/
308     void showSteps();
309
310     /**
311      * Show the current selection tree in the side panel, if there is any. If
312      * there is none, nothing happens.
313      **/
314     void showTree();
315
316     /**
317      * Set a widget's background pixmap to a gradient pixmap and set the
318      * widget's height (fixed) to that pixmap's height.
319      **/
320     static void setGradient( QWidget * widget, const QPixmap & pixmap );
321
322     /**
323      * Set a widget's background to the lower portion (the bottom
324      * 'croppedHeight' pixels) of a pixmap and set the widget's height (fixed)
325      * to that 'croppedHeight'.
326      **/
327     static void setBottomCroppedGradient( QWidget * widget,
328                                           const QPixmap & pixmap,
329                                           int croppedHeight );
330
331     /**
332      * Bottom-crop a pixmap: Return a pixmap with the bottom 'croppedHeight'
333      * pixels.
334      **/
335     static QPixmap bottomCropPixmap( const QPixmap & pixmap, int croppedHeight );
336
337     /**
338      * Return the color of pixel( x, y ) of a pixmap.
339      * If pixmap is null defaultColor is returned.
340      * This is a _very_ expensive operation!
341      **/
342     static QColor pixelColor( const QPixmap & pixmap, int x, int y, const QColor & defaultColor );
343
344
345 protected slots:
346
347     /**
348      * Internal notification that the "Back" button has been clicked.
349      **/
350     void slotBackClicked();
351
352     /**
353      * Internal notification that the "Abort" button has been clicked.
354      **/
355     void slotAbortClicked();
356
357     /**
358      * Internal notification that the "Next" button has been clicked.
359      **/
360     void slotNextClicked();
361
362     /**
363      * Propagate button clicked event of release notes button to the YCP
364      * application.
365      **/
366     void releaseNotesClicked();
367
368     /**
369      * Internal notification that [Space] or [Return] has been pressed on a
370      * tree item.
371      * If the item has an ID, that ID will be returned to UI::UserInput().
372      **/
373     void sendTreeEvent( Q3ListViewItem * item );
374
375     /**
376      * Internal notification that the tree selection has changed.
377      *
378      * If the currently selected item has an ID, that ID will be returned to
379      * UI::UserInput().
380      **/
381     void treeSelectionChanged();
382
383     /**
384      * Internal notification that a menu item with numeric ID 'numID' has been
385      * activated.
386      **/
387     void sendMenuEvent( int numID );
388
389
390     /**
391      * Retranslate internal buttons that are not accessible from the outside:
392      * - [Help]
393      * - [Steps]
394      * - [Tree]
395      **/
396     void retranslateInternalButtons();
397
398 protected:
399
400     // Layout functions
401
402     void layoutTitleBar         ( QWidget * parent );
403     void layoutSideBar          ( QWidget * parent );
404     void layoutSideBarButtonBox ( QWidget * parent, QPushButton * button );
405     void layoutStepsPanel();
406     void layoutHelpPanel();
407     void layoutTreePanel();
408     void layoutWorkArea ( QFrame * parentHBox );
409     void layoutClientArea( QWidget * parent );
410     void layoutButtonBox( QWidget * parent );
411
412
413     /**
414      * Load gradient pixmaps
415      **/
416     void loadGradientPixmaps();
417
418     /**
419      * Load step status icons
420      **/
421     void loadStepsIcons();
422
423     /**
424      * Destroy the button box's buttons
425      **/
426     void destroyButtons();
427
428     /**
429      * Update all step - use appropriate icons and colors
430      **/
431     void updateStepStates();
432
433     /**
434      * Add a (left or right) margin of the specified width to a widget,
435      * consisting of a fixed height top gradient , a flexible center part (in
436      * the gradient center color) and a fixed height bottom gradient.
437      *
438      * The bottom gradient widget is returned as a reference for other
439      * background pixmaps.
440      **/
441     void addGradientColumn( QWidget * parent, int width = 8 );
442
443     /**
444      * Send a wizard event with the specified ID.
445      **/
446     void sendEvent( YCPValue id );
447     void sendEvent( YWidgetID * id );
448
449     /**
450      * Returns 'true' if the application is running on a high-color display,
451      * i.e., on an X visual with more than 8 bit depth.
452      **/
453     bool highColorDisplay() const;
454
455     /**
456      * Notification that a signal is being connected.
457      *
458      * Reimplemented from QObject.
459      **/
460     void connectNotify ( const char * signal );
461
462     /**
463      * Notification that a signal is being disconnected.
464      *
465      * Reimplemented from QObject.
466      **/
467     void disconnectNotify ( const char * signal );
468
469     //
470     // Wizard command mini-parser
471     //
472
473     /**
474      * Check if 'term' matches wizard command 'declaration'.
475      * 'declaration' is a function prototype like this:
476      *
477      *          myFunction ( string, boolean, string )
478      *
479      * Void functions are declared without any parameters:
480      *
481      *          myFunction ()
482      *
483      * Function names must be unique. They cannot be overloaded.
484      **/
485     bool isCommand( QString declaration, const YCPTerm & term );
486
487     /**
488      * Return argument number 'argNo' from 'term' as QString.
489      **/
490     QString qStringArg( const YCPTerm & term, int argNo );
491
492     /**
493      * Return argument number 'argNo' from 'term' as std::string.
494      **/
495     std::string stringArg( const YCPTerm & term, int argNo );
496
497     /**
498      * Return argument number 'argNo' from 'term' as bool.
499      **/
500     bool boolArg( const YCPTerm & term, int argNo );
501
502     /**
503      * Return argument as type 'any' (plain YCPValue)
504      **/
505     YCPValue anyArg( const YCPTerm & term, int argNo );
506
507     /**
508      * Set a button's label.
509      **/
510     void setButtonLabel( YQWizardButton * button, const QString & newLabel );
511
512     /**
513      * Set a button's ID.
514      **/
515     void setButtonID( YQWizardButton * button, const YCPValue & id );
516
517     /**
518      * Enable or disable a button.
519      **/
520     void enableButton( YQWizardButton * button, bool enabled );
521
522     /**
523      * Set the keyboard focus to a button.
524      **/
525     void setButtonFocus( YQWizardButton * button );
526
527     /**
528      * Set text color and status icon for one wizard step
529      **/
530     void setStepStatus( YQWizard::Step * step, const QPixmap & icon, const QColor & color );
531
532     /**
533      * Find a step with the specified ID. Returns 0 if there is no such step.
534      **/
535     YQWizard::Step * findStep( const QString & id );
536
537     /**
538      * Find a tree item with the specified ID. Tree items without IDs cannot be
539      * found at all.
540      * Returns the item or 0 if no such item found.
541      **/
542     YQWizard::TreeItem * findTreeItem( const QString & id );
543
544     /**
545      * Returns the current tree selection or an empty string if nothing is
546      * selected or there is no tree.
547      *
548      * Reimplemented from YWizard.
549      **/
550     YCPString currentTreeSelection();
551
552     /**
553      * Show a "Release Notes" button above the "Help" button in the steps panel
554      * with the specified label that will return the specified id to
555      * UI::UserInput() when clicked.
556      **/
557     void showReleaseNotesButton( string label, const YCPValue & id );
558
559     /**
560      * Hide an existing "Release Notes" button.
561      **/
562     void hideReleaseNotesButton();
563
564     /**
565      * NOP command just to check if a YQWizard is running
566      **/
567     void ping();
568
569
570     //
571     // Data members
572     //
573
574     bool        _stepsEnabled;
575     bool        _treeEnabled;
576     bool        _verboseCommands;
577     bool        _protectNextButton;
578     bool        _stepsDirty;
579     bool        _sendButtonEvents;
580     Direction   _direction;
581
582     QPixmap     _titleBarGradientPixmap;
583     QPixmap     _topGradientPixmap;
584     QColor      _gradientCenterColor;
585     QColor      _gradientTopColor;
586     QPixmap     _bottomGradientPixmap;
587
588     QPixmap     _stepCurrentIcon;
589     QPixmap     _stepToDoIcon;
590     QPixmap     _stepDoneIcon;
591
592     QColor      _stepCurrentColor;
593     QColor      _stepToDoColor;
594     QColor      _stepDoneColor;
595
596     QString     _currentStepID;
597
598
599     Q3WidgetStack *     _sideBar;
600     Q3VBox *                _stepsPanel;
601     Q3VBox *                    _stepsBox;
602     Q3GridLayout *                  _stepsGrid;
603     QPushButton *               _releaseNotesButton;
604     YCPValue                    _releaseNotesButtonId;
605     QPushButton *               _helpButton;
606     Q3HBox *                _helpPanel;
607     Q3TextBrowser *             _helpBrowser;
608     QPushButton *               _stepsButton;
609     QPushButton *               _treeButton;
610     Q3HBox *                _treePanel;
611     QY2ListView *               _tree;
612
613     Q3VBox *            _clientArea;
614     QWidget *               _menuBarBox;
615     QMenuBar *                  _menuBar;
616     QLabel *                _dialogIcon;
617     QLabel *                _dialogHeading;
618     YQAlignment *           _contents;
619     YQWizardButton *        _backButton;
620     QSpacerItem *           _backButtonSpacer;
621     YQWizardButton *        _abortButton;
622     YQWizardButton *        _nextButton;
623
624     Q3PtrList<YQWizard::Step>   _stepsList;
625     Q3Dict<YQWizard::Step>      _stepsIDs;
626     Q3Dict<YQWizard::TreeItem>  _treeIDs;
627     Q3Dict<Q3PopupMenu>         _menuIDs;
628     vector<QString>             _menuEntryIDs;
629
630
631 protected:
632
633     /**
634      * Helper class to represent a wizard step internally
635      **/
636     class Step
637     {
638     public:
639
640         Step( const QString & name = "", const QString & id = "" )
641             : _name( name )
642             , _statusLabel( 0 )
643             , _nameLabel(0)
644             , _enabled( true )
645             , _idList( id )
646         {}
647
648         /**
649          * Destructor. Intentionally not deleting the widgets.
650          **/
651         virtual ~Step() {}
652
653         virtual bool isHeading() const { return false; }
654
655         QString  name()         const { return _name;           }
656         QLabel * statusLabel()  const { return _statusLabel;    }
657         QLabel * nameLabel()    const { return _nameLabel;      }
658         bool     isEnabled()    const { return _enabled;        }
659         const QStringList & id() const { return _idList;        }
660         void addID( const QString & id ) { _idList.append( id ); }
661         virtual bool hasID( const QString & id ) { return _idList.find( id ) != _idList.end(); }
662
663         void setStatusLabel( QLabel * label )   { _statusLabel = label; }
664         void setNameLabel  ( QLabel * label )   { _nameLabel   = label; }
665         void setEnabled( bool enabled )         { _enabled = enabled; }
666
667     protected:
668
669         QString         _name;
670         QLabel *        _statusLabel;
671         QLabel *        _nameLabel;
672         bool            _enabled;
673         QStringList     _idList;
674     };
675
676
677     /**
678      * Helper class to represent a wizard step heading internally
679      **/
680     class StepHeading: public Step
681     {
682     public:
683
684         StepHeading( const QString & name = "" )
685             : Step( name, "" )
686             {}
687
688         virtual ~StepHeading() {}
689         virtual bool isHeading() const { return true; }
690         virtual bool hasID( const QString & id ) { return false; }
691     };
692
693
694     /**
695      * Helper class for wizard tree item
696      **/
697     class TreeItem: public QY2ListViewItem
698     {
699     public:
700         TreeItem( QY2ListView *         parent,
701                   const QString &       text,
702                   const QString &       id )
703             : QY2ListViewItem( parent, text )
704             , _id( id )
705             {}
706
707         TreeItem( YQWizard::TreeItem *  parent,
708                   const QString &       text,
709                   const QString &       id )
710             : QY2ListViewItem( parent, text )
711             , _id( id )
712             {}
713
714         virtual QString text(int index) const { return Q3ListViewItem::text(index); } 
715         QString text() const { return Q3ListViewItem::text(0); }
716         QString id()   const { return _id; }
717
718     private:
719         QString _id;
720     };
721
722 }; // class YQWizard
723
724
725
726 #endif // YQWizard_h