You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kmymoney/kmymoney2/widgets/kmymoneywizard.h

543 lines
17 KiB

/***************************************************************************
kmymoneywizard.h
-------------------
copyright : (C) 2006 by Thomas Baumagrt
email : ipwizard@users.sourceforge.net
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef KMYMONEYWIZARD_H
#define KMYMONEYWIZARD_H
// ----------------------------------------------------------------------------
// QT Includes
#include <tqdialog.h>
#include <tqvaluelist.h>
#include <tqpalette.h>
class TQVBoxLayout;
class TQHBoxLayout;
class TQLabel;
class TQFrame;
// ----------------------------------------------------------------------------
// KDE Includes
class KPushButton;
// ----------------------------------------------------------------------------
// Project Includes
class KMyMoneyTitleLabel;
class KMyMoneyWizard;
class KMyMoneyWizardPagePrivate;
class kMandatoryFieldGroup;
/**
* @author Thomas Baumgart (C) 2006
*
* @note: the following documentation is somewhat outdated
* as of May 2007. Wizards should use a namespace
* for the pages and can use the WizardPage<T> template class.
* See the NewUserWizard class and NewUserWizardPages namespace
* as an example of this setup.
*
* This class represents the base class for wizard pages for the
* KMyMoneyWizard. One cannot create a wizard page directly, but
* must derive from it. The KMyMoneyWizardPage class provides the
* necessary functionality to work in concert with KMyMoneyWizard.
*
* Therefore, few steps are necessary to use this class. They seem to
* be awkward at some stage, but I wanted to be able to use TQt designer
* to actually design the widget for the page. That's why some things
* aren't implemented in a more straight fashion than one would
* normally do this.
*
* The first step is to derive a specific base page for the specific wizard.
* In this example we use the name NewUser as template for the specific wizard.
* This class provides a 'back'-pointer to the actual wizard object
* for all pages.
*
* @code
* class KNewUserPage : public KMyMoneyWizardPage
* {
* public:
* KNewUserPage(unsigned int step, TQWidget* widget, KNewUserWizard* parent, const char* name);
*
* protected:
* KNewUserWizard* m_wizard;
* }
* @endcode
*
* The implementation of this class is rather straight-forward:
*
* @code
* KNewUserPage::KNewUserPage(unsigned int step, TQWidget* widget, KNewUserWizard* parent, const char* name) :
* KMyMoneyWizardPage(step, widget, name),
* m_wizard(parent)
* {
* }
* @endcode
*
* For each page of the wizard, you will have to create a @p ui file with
* TQt designer.
* Let's assume we call the first page of the wizard 'General' and go
* from there.
* We also assume, that the wizard has more than one page.
* The ui designer generated class should have the name KNewUserGeneralDecl
* as all other dialogs. The class definition of KNewUserGeneral will
* look like this:
*
* @code
* class KNewUserGeneral : public KNewUserGeneralDecl, public KNewUserPage
* {
* Q_OBJECT
* public:
* KNewUserGeneral(KNewUserWizard* parent, const char* name = 0);
* KMyMoneyWizardPage* nextPage(void);
* bool isLastPage(void) { return false; }
*
* protected:
* KNewUserWizard* m_wizard;
* }
* @endcode
*
* The implementation depends heavily on the logic of your code. If you only
* fill some widgets, it could be as simple as:
*
* @code
* KNewUserGeneral::KNewUserGeneral(KNewUserWizard* parent, const char* name) :
* KNewUserGeneralDecl(parent),
* KNewUserPage(1, this, parent, name)
* {
* kMandatoryFieldGroup* mandatoryGroup = new kMandatoryFieldGroup(this);
* mandatoryGroup->add(m_userName);
* connect(m_mandatoryGroup, TQT_SIGNAL(stateChanged()), object(), TQT_SIGNAL(completeStateChanged()));
* }
*
* KMyMoneyWizardPage* KNewUserGeneral::nextPage(void)
* {
* return m_wizard->m_personalPage;
* }
* @endcode
*
* A note on the first parameter to KNewUserPage in the above example: it ties
* this page to be part of step 1 (see KMyMoneyWizard::addStep() for details).
*
* Depending on the actual logic of the page, you would want to override the
* following methods: resetPage, nextPage, isLastPage and isComplete.
*
* @note The implementation of this class is heavily based on ideas found at
* http://doc.trolltech.com/4.1/dialogs-complexwizard.html
*/
class KMyMoneyWizardPage
{
public:
/**
* This method is called by the wizard when the page is entered from
* the previous page. The default implementation does nothing.
*/
virtual void enterPage(void);
/**
* This method is called by the wizard when the page is left to return to
* the previous page. The default implementation does nothing.
*/
virtual void leavePage(void);
/**
* This method is called by the wizard whenever a page is entered
* (either in forward or backward direction). The default
* implementation does nothing.
*/
virtual void resetPage(void);
/**
* This method returns a pointer to the next page that should be
* shown when the user presses the 'Next' button.
*
* @return pointer to next wizard page
*/
virtual KMyMoneyWizardPage* nextPage(void) const;
/**
* This returns, if the current page is the last page of the wizard.
* The default implementation returns @p false if nextPage() returns 0,
* @p true otherwise.
*
* @retval false more pages follow
* @retval true this is the last page of the wizard
*/
virtual bool isLastPage(void) const;
/**
* This returns, if all necessary data for this page has been
* filled. It is used to enabled the 'Next' or 'Finish' button.
* The button is only enabled, if this method returns @p true,
* which is the default implementation.
*
* @retval false more data required from the user before we can proceed
* @retval true all data available, we allow to switch to the next page
*/
virtual bool isComplete(void) const;
/**
* This method returns the step to which this page belongs.
* It is required by the KMyMoneyWizard and is not intended
* to be used by application code.
*
* @return step of wizard this page belongs to
*/
unsigned int step(void) const { return m_step; }
/**
* This method returns a pointer to the widget of the page.
* It is required by the KMyMoneyWizard and is not intended
* to be used by application code.
*
* @return pointer to widget of page
*/
TQWidget* widget(void) const { return m_widget; }
/**
* This method returns a pointer to the TQObject used for
* the signal/slot mechanism.
* It is required by the KMyMoneyWizard and can be used
* by application code for signal/slot connections as well.
* Other use is not foreseen.
*/
TQObject* object(void) const;
/**
* This method returns a pointer to the widget which should
* receive the focus when the page is opened.
*
* @return pointer to widget or 0 if none is to be selected
* The default implementation returns 0
*/
virtual TQWidget* initialFocusWidget(void) const { return 0; }
virtual KMyMoneyWizard* wizard(void) const = 0;
/**
* This method returns a specific help context for the page shown
* The default returns an empty string.
*/
virtual const TQString& helpContext(void) const;
virtual ~KMyMoneyWizardPage() {}
protected:
/**
* Constructor (kept protected, so that one cannot create such an object directly)
*/
KMyMoneyWizardPage(unsigned int step, TQWidget* widget, const char* name = 0);
/**
* This method must be called by the implementation when the
* data in the fields of the wizard change and the state of
* completeness changed.
*
* @note If you do not override isComplete() then there is no need
* to call this method.
*/
void completeStateChanged(void) const;
protected:
kMandatoryFieldGroup* m_mandatoryGroup;
private:
unsigned int m_step;
TQWidget* m_widget;
KMyMoneyWizardPagePrivate* const d;
};
/**
* The general base class for wizard pages
*
* @author Thomas Baumgart
*/
template <class T>
class WizardPage : public KMyMoneyWizardPage
{
public:
WizardPage(unsigned int step, TQWidget* widget, T* parent, const char* name) :
KMyMoneyWizardPage(step, widget, name),
m_wizard(parent),
m_wizardBase(parent)
{
}
virtual ~WizardPage() {}
virtual KMyMoneyWizard* wizard(void) const { return m_wizardBase; }
protected:
T* m_wizard;
KMyMoneyWizard* m_wizardBase;
};
/**
* @author Thomas Baumgart (C) 2006
*
* This is a base class for implementation of the KMyMoneyWizard. It provides
* the following layout of a wizard:
*
* @code
* +-wizardLayout-----------------------------------------------+
* | |
* +------------------------------------------------------------+
* |+-stepLayout--++-------------------------------------------+|
* || ||+-pageLayout------------------------------+||
* || ||| |||
* || ||| |||
* || ||| |||
* || ||| |||
* || ||| |||
* || ||| |||
* || ||+-----------------------------------------+||
* || |||+-buttonLayout--------------------------+|||
* || |||| ||||
* || |||+---------------------------------------+|||
* || ||+-----------------------------------------+||
* |+-------------++-------------------------------------------+|
* +------------------------------------------------------------+
* @endcode
*
* The top bar is filled with a KMyMoneyTitleLabel as known from
* KMyMoney's views. To the left there is an area in the same color
* as the title bar showing the steps for this wizard. Each such step
* can consist of one or more wizard pages. At the bottom of this area
* the text "Step x of y" is shown and updated. To the right of this
* part, the actual wizard page is shown. At the bottom of the page
* the class inserts a standard button widget consisting of a Help,
* Back, Next/Finish and Cancel button.
*
* The wizard serves as container for the wizard pages. In order to access
* the data filled into the pages, one would have to provide getter methods.
*
* Here is an example how this object could be used. Please also see the
* example described with the KMyMoneyWizardPage class.
*
* @code
*
* class KNewUserGeneral;
* class KNewUserPersonal;
*
* class KNewUserWizard : public KMyMoneyWizard
* {
* Q_OBJECT
* public:
* KNewUserWizard(TQWidget* parent = 0, const char* name = 0, bool modal = false, WFlags flags = 0);
*
* private:
* KNewUserGeneral* m_generalPage;
* KNewUserPersonal* m_personalPage;
* KNewUserFinal* m_finalPage;
* // add more pages here
*
* friend class KNewUserGeneral;
* friend class KNewUserPersonal;
* friend class KNewUserFinal;
* // add more pages here
* };
* @endcode
*
* The implementation is also easy and looks like this:
*
* @code
* KNewUserWizard::KNewUserWizard(TQWidget* parent, const char* name, bool modal, WFlags flags) :
* KMyMoneyWizard(parent, name, modal, flags)
* {
* setTitle("KMyMoney New User Setup");
* addStep("General Data");
* addStep("Personal Data");
* addStep("Finish");
*
* m_generalPage = new KNewUserGeneral(this);
* m_personalPage = new KNewUserPersonal(this);
* m_finalPage = new KNewUserFinal(this);
*
* setFirstPage(m_testPage1);
* }
* @endcode
*
* Don't forget to call setFirstPage() to get things started.
*
* The code to use this whole structure would then look something like this:
*
* @code
* KNewUserWizard* wizard = new KNewUserWizard(this, "NewUserWizard");
* int rc = wizard->exec();
* @endcode
*
* The return code of exec() is either @p TQDialog::Accepted or
* @p TQDialog::Rejected.
*
* @note The implementation of this class is heavily based on ideas found at
* http://doc.trolltech.com/4.1/dialogs-complexwizard.html
*/
class KMyMoneyWizard : public TQDialog
{
friend class KMyMoneyWizardPage;
Q_OBJECT
public:
/**
* Modify the title of the wizard to be @p txt.
*
* @param txt The text that should be used as title
*/
void setTitle(const TQString& txt);
/**
* Add step @p text to the wizard
*
* @param text Text to be shown for this step
*/
void addStep(const TQString& text);
TQValueList<KMyMoneyWizardPage*> historyPages(void) const { return m_history; }
/**
* This method repeats selection of the current step in the
* step frame.
* This is used to allow changes made to showing and hiding
* pages to immediately to be reflected in the step frame
*/
void reselectStep(void);
/**
* Setup a global help context for the wizard. It will be used whenever
* there is no specific help context available for the current page.
*
* @sa KMyMoneyWizardPage::helpContext()
*/
void setHelpContext(const TQString& ctx) { m_helpContext = ctx; }
virtual ~KMyMoneyWizard(){}
signals:
/**
* This signal is sent out, when a new payee needs to be created
* @sa KMyMoneyCombo::createItem()
*
* @param txt The name of the payee to be created
* @param id A connected slot should store the id of the created object in this variable
*/
void createPayee(const TQString& txt, TQString& id);
/**
* This signal is sent out, when a new category needs to be created
* @sa KMyMoneyCombo::createItem()
*
* @param txt The name of the category to be created
* @param id A connected slot should store the id of the created object in this variable
*/
void createCategory(const TQString& txt, TQString& id);
protected:
/**
* Constructor (kept protected, so that one cannot create such an object directly)
*/
KMyMoneyWizard(TQWidget *parent = 0, const char *name = 0, bool modal = false, WFlags f = 0);
/**
* This method sets up the first page after creation of the object
*
* @param page pointer to first page of wizard
*/
void setFirstPage(KMyMoneyWizardPage* page);
/**
* This method allows to hide or show a @p step.
*
* @param step step to be shown/hidden
* @param hidden hide step if true (the default) or show it if false
*/
void setStepHidden(unsigned int step, bool hidden = true);
protected slots:
virtual void accept(void);
void completeStateChanged(void);
private:
void updateStepCount(void);
private slots:
void backButtonClicked(void);
void nextButtonClicked(void);
void helpButtonClicked(void);
protected:
/*
* The buttons
*/
KPushButton* m_cancelButton;
KPushButton* m_backButton;
KPushButton* m_nextButton;
KPushButton* m_finishButton;
KPushButton* m_helpButton;
private:
/**
* Switch to page which is currently the top of the history stack.
* @p oldPage is a pointer to the current page or 0 if no page
* is shown.
*
* @param oldPage pointer to currently displayed page
*/
void switchPage(KMyMoneyWizardPage* oldPage);
/**
* This method selects the step given by @p step.
*
* @param step step to be selected
*/
void selectStep(unsigned int step);
/*
* The layouts
*/
TQVBoxLayout* m_wizardLayout;
TQVBoxLayout* m_stepLayout;
TQVBoxLayout* m_pageLayout;
TQHBoxLayout* m_buttonLayout;
/*
* Some misc. widgets required
*/
TQFrame* m_stepFrame;
TQLabel* m_stepLabel;
TQPalette m_stepPalette;
TQValueList<TQLabel*> m_steps; // the list of step labels
int m_step; // the currently selected step
/*
* The title bar
*/
KMyMoneyTitleLabel* m_titleLabel;
/*
* The history stack
*/
TQValueList<KMyMoneyWizardPage*> m_history;
TQString m_helpContext;
};
#endif