/**********************************************************************
** Copyright (C) 2000 Trolltech AS.  All rights reserved.
**
** This file is part of TQt Designer.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://www.trolltech.com/gpl/ for GPL licensing information.
**
** Contact info@trolltech.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/

#ifndef COMMAND_H
#define COMMAND_H

#include "metadatabase.h"
#include "layout.h"

#include <tqstring.h>
#include <tqrect.h>
#include <tqvaluelist.h>
#include <tqvariant.h>
#include <tqobject.h>
#include <tqlistview.h>
#include <tqptrlist.h>
#include <tqmap.h>

class TQWizard;
class TQTabWidget;
class Command;
class TQWidget;
class FormWindow;
class PropertyEditor;
class TQListBox;
class TQIconView;
class TQMultiLineEdit;
class TQTable;
class TQAction;
class QDesignerToolBar;
class TQMainWindow;
class QDesignerPopupMenu;
class QDesignerMenuBar;
class TQToolBox;

class Command : public TQt
{
public:
    Command( const TQString &n, FormWindow *fw );
    virtual ~Command();

    enum Type {
	Resize,
	Insert,
	Move,
	Delete,
	SetProperty,
	LayoutHorizontal,
	LayoutVertical,
	LayoutHorizontalSplitter,
	LayoutVerticalSplitter,
	LayoutGrid,
	BreakLayout,
	Macro,
	AddTabPage,
	DeleteTabPage,
	MoveTabPage,
	AddWizardPage,
	DeleteWizardPage,
	SwapWizardPages,
	RenameWizardPage,
	AddConnection,
	RemoveConnection,
	AddSlot,
	RemoveSlot,
	Lower,
	Raise,
	Paste,
	TabOrder,
	PopulateListBox,
	PopulateIconView,
	PopulateListView,
	PopulateMultiLineEdit,
	PopulateTable,
	AddActionToToolBar,
	RemoveActionFromToolBar,
	AddActionToPopup,
	RemoveActionFromPopup,
	AddMenu,
	RemoveMenu,
	RenameMenu,
	MoveMenu,
	AddToolBar,
	RemoveToolBar,
    AddToolBoxPage,
    DeleteToolBoxPage
    };

    TQString name() const;

    virtual void execute() = 0;
    virtual void unexecute() = 0;
    virtual Type type() const = 0;
    virtual void merge( Command *c );
    virtual bool canMerge( Command *c );

    FormWindow *formWindow() const;

private:
    TQString cmdName;
    FormWindow *formWin;

};


class CommandHistory : public TQObject
{
    TQ_OBJECT
  

public:
    CommandHistory( int s );

    void addCommand( Command *cmd, bool tryCompress = FALSE );
    void undo();
    void redo();

    void emitUndoRedo();

    void setModified( bool m );
    bool isModified() const;

public slots:
    void checkCompressedCommand();

signals:
    void undoRedoChanged( bool undoAvailable, bool redoAvailable,
			  const TQString &undoCmd, const TQString &redoCmd );
    void modificationChanged( bool m );

private:
    TQPtrList<Command> history;
    int current, steps;
    bool modified;
    int savedAt;
    Command *compressedCommand;

};

class ResizeCommand : public Command
{
public:
    ResizeCommand( const TQString &n, FormWindow *fw,
		   TQWidget *w, const TQRect &oldr, const TQRect &nr );

    void execute();
    void unexecute();
    Type type() const { return Resize; }

private:
    TQWidget *widget;
    TQRect oldRect, newRect;

};

class InsertCommand : public Command
{
public:
    InsertCommand( const TQString &n, FormWindow *fw, TQWidget *w, const TQRect &g );

    void execute();
    void unexecute();
    Type type() const { return Insert; }

private:
    TQWidget *widget;
    TQRect geometry;

};

class MoveCommand : public Command
{
public:
    MoveCommand( const TQString &n, FormWindow *fw,
		 const TQWidgetList &w,
		 const TQValueList<TQPoint> op,
		 const TQValueList<TQPoint> np,
		 TQWidget *opr, TQWidget *npr );
    void execute();
    void unexecute();
    Type type() const { return Move; }
    void merge( Command *c );
    bool canMerge( Command *c );

private:
    TQWidgetList widgets;
    TQValueList<TQPoint> oldPos, newPos;
    TQWidget *oldParent, *newParent;

};

class DeleteCommand : public Command
{
public:
    DeleteCommand( const TQString &n, FormWindow *fw,
		   const TQWidgetList &w );
    void execute();
    void unexecute();
    Type type() const { return Delete; }

private:
    TQWidgetList widgets;
    TQMap< TQWidget*, TQValueList<MetaDataBase::Connection> > connections;

};

class SetPropertyCommand : public Command
{
public:
    SetPropertyCommand( const TQString &n, FormWindow *fw,
			TQObject *w, PropertyEditor *e,
			const TQString &pn, const TQVariant &ov,
			const TQVariant &nv, const TQString &ncut,
			const TQString &ocut,
			bool reset = FALSE );

    void execute();
    void unexecute();
    Type type() const { return SetProperty; }
    void merge( Command *c );
    bool canMerge( Command *c );
    bool checkProperty();

private:
    void setProperty( const TQVariant &v, const TQString &currentItemText, bool select = TRUE );

    TQObject *widget;
    PropertyEditor *editor;
    TQString propName;
    TQVariant oldValue, newValue;
    TQString oldCurrentItemText, newCurrentItemText;
    bool wasChanged;
    bool isResetCommand;

};

class LayoutHorizontalCommand : public Command
{
public:
    LayoutHorizontalCommand( const TQString &n, FormWindow *fw,
			     TQWidget *parent, TQWidget *layoutBase,
			     const TQWidgetList &wl );

    void execute();
    void unexecute();
    Type type() const { return LayoutHorizontal; }

private:
    HorizontalLayout layout;

};

class LayoutHorizontalSplitCommand : public Command
{
public:
    LayoutHorizontalSplitCommand( const TQString &n, FormWindow *fw,
				  TQWidget *parent, TQWidget *layoutBase,
				  const TQWidgetList &wl );

    void execute();
    void unexecute();
    Type type() const { return LayoutHorizontalSplitter; }

private:
    HorizontalLayout layout;

};

class LayoutVerticalCommand : public Command
{
public:
    LayoutVerticalCommand( const TQString &n, FormWindow *fw,
			   TQWidget *parent, TQWidget *layoutBase,
			   const TQWidgetList &wl );

    void execute();
    void unexecute();
    Type type() const { return LayoutVertical; }

private:
    VerticalLayout layout;

};

class LayoutVerticalSplitCommand : public Command
{
public:
    LayoutVerticalSplitCommand( const TQString &n, FormWindow *fw,
				TQWidget *parent, TQWidget *layoutBase,
				const TQWidgetList &wl );

    void execute();
    void unexecute();
    Type type() const { return LayoutVerticalSplitter; }

private:
    VerticalLayout layout;

};

class LayoutGridCommand : public Command
{
public:
    LayoutGridCommand( const TQString &n, FormWindow *fw,
		       TQWidget *parent, TQWidget *layoutBase,
		       const TQWidgetList &wl, int xres, int yres );

    void execute();
    void unexecute();
    Type type() const { return LayoutGrid; }

private:
    GridLayout layout;

};

class BreakLayoutCommand : public Command
{
public:
    BreakLayoutCommand( const TQString &n, FormWindow *fw,
			TQWidget *layoutBase, const TQWidgetList &wl );

    void execute();
    void unexecute();
    Type type() const { return BreakLayout; }

private:
    Layout *layout;
    int spacing;
    int margin;
    TQWidget *lb;
    TQWidgetList widgets;

};

class MacroCommand : public Command
{
public:
    MacroCommand( const TQString &n, FormWindow *fw,
		  const TQPtrList<Command> &cmds );

    void execute();
    void unexecute();
    Type type() const { return Macro; }

private:
    TQPtrList<Command> commands;

};

class AddTabPageCommand : public Command
{
public:
    AddTabPageCommand( const TQString &n, FormWindow *fw,
		       TQTabWidget *tw, const TQString &label );

    void execute();
    void unexecute();
    Type type() const { return AddTabPage; }

private:
    TQTabWidget *tabWidget;
    int index;
    TQWidget *tabPage;
    TQString tabLabel;

};

class DeleteTabPageCommand : public Command
{
public:
    DeleteTabPageCommand( const TQString &n, FormWindow *fw,
			  TQTabWidget *tw, TQWidget *page );

    void execute();
    void unexecute();
    Type type() const { return DeleteTabPage; }

private:
    TQTabWidget *tabWidget;
    int index;
    TQWidget *tabPage;
    TQString tabLabel;

};

class AddToolBoxPageCommand : public Command
{
public:
    AddToolBoxPageCommand( const TQString &n, FormWindow *fw,
               TQToolBox *tw, const TQString &label );

    void execute();
    void unexecute();
    Type type() const { return AddToolBoxPage; }

private:
    TQToolBox *toolBox;
    int index;
    TQWidget *page;
    TQString label;

};

class DeleteToolBoxPageCommand : public Command
{
public:
    DeleteToolBoxPageCommand( const TQString &n, FormWindow *fw,
              TQToolBox *tw, TQWidget *page );

    void execute();
    void unexecute();
    Type type() const { return DeleteToolBoxPage; }

private:
    TQToolBox *toolBox;
    int index;
    TQWidget *page;
    TQString label;

};
class MoveTabPageCommand : public Command
{
public:
    MoveTabPageCommand(const TQString &n, FormWindow *fw,
		       TQTabWidget *tw, TQWidget *page,  const TQString& label, int nIndex, int oIndex );

    void execute();
    void unexecute();
    Type type() const { return MoveTabPage; }

private:
    TQTabWidget *tabWidget;
    int newIndex, oldIndex;
    TQWidget *tabPage;
    TQString tabLabel;

};

class AddWizardPageCommand : public Command
{
public:
    AddWizardPageCommand( const TQString &n, FormWindow *fw,
			  TQWizard *w, const TQString &label, int index = -1, bool show = TRUE );

    void execute();
    void unexecute();
    Type type() const { return AddWizardPage; }

private:
    TQWizard *wizard;
    int index;
    bool show;
    TQWidget *page;
    TQString pageLabel;

};

class DeleteWizardPageCommand : public Command
{
public:
    DeleteWizardPageCommand( const TQString &n, FormWindow *fw,
			     TQWizard *w, int index, bool show = TRUE );

    void execute();
    void unexecute();
    Type type() const { return DeleteWizardPage; }

private:
    TQWizard *wizard;
    int index;
    bool show;
    TQWidget *page;
    TQString pageLabel;

};

class RenameWizardPageCommand : public Command
{
public:
    RenameWizardPageCommand( const TQString &n, FormWindow *fw,
			     TQWizard *w, int index, const TQString& name );

    void execute();
    void unexecute();
    Type type() const { return RenameWizardPage; }

private:
    TQWizard *wizard;
    int index;
    TQWidget *page;
    TQString label;

};

class SwapWizardPagesCommand : public Command
{
public:
    SwapWizardPagesCommand( const TQString &n, FormWindow *fw,
			      TQWizard *w, int index1, int index2 );

    void execute();
    void unexecute();
    Type type() const { return SwapWizardPages; }

private:
    TQWizard *wizard;
    int index1, index2;

};

class AddConnectionCommand : public Command
{
public:
    AddConnectionCommand( const TQString &name, FormWindow *fw,
			  MetaDataBase::Connection c );

    void execute();
    void unexecute();
    Type type() const { return AddConnection; }

private:
    MetaDataBase::Connection connection;

};

class RemoveConnectionCommand : public Command
{
public:
    RemoveConnectionCommand( const TQString &name, FormWindow *fw,
			     MetaDataBase::Connection c );

    void execute();
    void unexecute();
    Type type() const { return RemoveConnection; }

private:
    MetaDataBase::Connection connection;

};

class AddSlotCommand : public Command
{
public:
    AddSlotCommand( const TQString &name, FormWindow *fw, const TQCString &s, const TQString& spec, 
		    const TQString &a, const TQString &l, const TQString &rt );

    void execute();
    void unexecute();
    Type type() const { return AddSlot; }

private:
    TQCString slot;
    TQString specifier;
    TQString access;
    TQString language;
    TQString returnType;

};

class RemoveSlotCommand : public Command
{
public:
    RemoveSlotCommand( const TQString &name, FormWindow *fw, const TQCString &s, const TQString& spec,
		       const TQString &a, const TQString &l, const TQString &rt );

    void execute();
    void unexecute();
    Type type() const { return RemoveSlot; }

private:
    TQCString slot;
    TQString specifier;
    TQString access;
    TQString language;
    TQString returnType;

};

class LowerCommand : public Command
{
public:
    LowerCommand( const TQString &name, FormWindow *fw, const TQWidgetList &w );

    void execute();
    void unexecute();
    Type type() const { return Lower; }

private:
    TQWidgetList widgets;

};

class RaiseCommand : public Command
{
public:
    RaiseCommand( const TQString &name, FormWindow *fw, const TQWidgetList &w );

    void execute();
    void unexecute();
    Type type() const { return Raise; }

private:
    TQWidgetList widgets;

};

class PasteCommand : public Command
{
public:
    PasteCommand( const TQString &n, FormWindow *fw, const TQWidgetList &w );

    void execute();
    void unexecute();
    Type type() const { return Paste; }

private:
    TQWidgetList widgets;

};

class TabOrderCommand : public Command
{
public:
    TabOrderCommand( const TQString &n, FormWindow *fw, const TQWidgetList &ol, const TQWidgetList &nl );

    void execute();
    void unexecute();
    Type type() const { return TabOrder; }
    void merge( Command *c );
    bool canMerge( Command *c );

private:
    TQWidgetList oldOrder, newOrder;

};

class PopulateListBoxCommand : public Command
{
public:
    struct Item
    {
	TQString text;
	TQPixmap pix;
#if defined(TQ_FULL_TEMPLATE_INSTANTIATION)
	bool operator==( const Item & ) const { return FALSE; }
#endif
    };

    PopulateListBoxCommand( const TQString &n, FormWindow *fw,
			    TQListBox *lb, const TQValueList<Item> &items );
    void execute();
    void unexecute();
    Type type() const { return PopulateListBox; }

    bool operator==( const PopulateListBoxCommand & ) const;

private:
    TQValueList<Item> oldItems, newItems;
    TQListBox *listbox;

};

class PopulateIconViewCommand : public Command
{
public:
    struct Item
    {
	TQString text;
	TQPixmap pix;
#if defined(TQ_FULL_TEMPLATE_INSTANTIATION)
	bool operator==( const Item & ) const { return FALSE; }
#endif
    };

    PopulateIconViewCommand( const TQString &n, FormWindow *fw,
			    TQIconView *iv, const TQValueList<Item> &items );
    void execute();
    void unexecute();
    Type type() const { return PopulateIconView; }

    bool operator==( const PopulateIconViewCommand & ) const;

private:
    TQValueList<Item> oldItems, newItems;
    TQIconView *iconview;

};

class PopulateListViewCommand : public Command
{
public:
    PopulateListViewCommand( const TQString &n, FormWindow *fw,
			     TQListView *lv, TQListView *from );
    void execute();
    void unexecute();
    Type type() const { return PopulateListView; }
    static void transferItems( TQListView *from, TQListView *to );

    bool operator==( const PopulateListViewCommand & ) const;

private:
    TQListView *oldItems, *newItems;
    TQListView *listview;

};

class PopulateMultiLineEditCommand : public Command
{
public:
    PopulateMultiLineEditCommand( const TQString &n, FormWindow *fw,
				  TQMultiLineEdit *mle, const TQString &txt );
    void execute();
    void unexecute();
    Type type() const { return PopulateMultiLineEdit; }

private:
    TQString newText, oldText;
    TQMultiLineEdit *mlined;
    bool wasChanged;

};

class PopulateTableCommand : public Command
{
public:
    struct Row
    {
	TQString text;
	TQPixmap pix;
#if defined(TQ_FULL_TEMPLATE_INSTANTIATION)
	bool operator==( const Row& ) const { return FALSE; }
#endif
    };

    struct Column
    {
	TQString text;
	TQPixmap pix;
	TQString field;
#if defined(TQ_FULL_TEMPLATE_INSTANTIATION)
	bool operator==( const Column& ) const { return FALSE; }
#endif
    };

    PopulateTableCommand( const TQString &n, FormWindow *fw, TQTable *t,
			  const TQValueList<Row> &rows,
			  const TQValueList<Column> &columns );

    void execute();
    void unexecute();
    Type type() const { return PopulateTable; }

private:
    TQValueList<Row> oldRows, newRows;
    TQValueList<Column> oldColumns, newColumns;
    TQTable *table;

};

class AddActionToToolBarCommand : public Command
{
public:
    AddActionToToolBarCommand( const TQString &n, FormWindow *fw,
			       TQAction *a, QDesignerToolBar *tb, int idx );

    void execute();
    void unexecute();
    Type type() const { return AddActionToToolBar; }

private:
    TQAction *action;
    QDesignerToolBar *toolBar;
    int index;

};

class RemoveActionFromToolBarCommand : public AddActionToToolBarCommand
{
public:
    RemoveActionFromToolBarCommand( const TQString &n, FormWindow *fw,
				    TQAction *a, QDesignerToolBar *tb, int idx )
	: AddActionToToolBarCommand( n, fw, a, tb, idx ) {}

    void execute() { AddActionToToolBarCommand::unexecute(); }
    void unexecute() { AddActionToToolBarCommand::execute(); }
    Type type() const { return RemoveActionFromToolBar; }

};

class AddActionToPopupCommand : public Command
{
public:
    AddActionToPopupCommand( const TQString &n, FormWindow *fw,
			       TQAction *a, QDesignerPopupMenu *p, int idx );

    void execute();
    void unexecute();
    Type type() const { return AddActionToPopup; }

private:
    TQAction *action;
    QDesignerPopupMenu *popup;
    int index;

};

class RemoveActionFromPopupCommand : public AddActionToPopupCommand
{
public:
    RemoveActionFromPopupCommand( const TQString &n, FormWindow *fw,
				    TQAction *a, QDesignerPopupMenu *p, int idx )
	: AddActionToPopupCommand( n, fw, a, p, idx ) {}

    void execute() { AddActionToPopupCommand::unexecute(); }
    void unexecute() { AddActionToPopupCommand::execute(); }
    Type type() const { return RemoveActionFromPopup; }

};

class AddMenuCommand : public Command
{
public:
    AddMenuCommand( const TQString &n, FormWindow *fw, TQMainWindow *mw );

    void execute();
    void unexecute();
    Type type() const { return AddMenu; }

protected:
    QDesignerMenuBar *menuBar;
    QDesignerPopupMenu *popup;
    TQMainWindow *mainWindow;
    int id;
    int index;
    TQString name;

};

class RemoveMenuCommand : public AddMenuCommand
{
public:
    RemoveMenuCommand( const TQString &n, FormWindow *fw, TQMainWindow *mw,
		       QDesignerMenuBar *mb, QDesignerPopupMenu *p, int i, int idx, const TQString &mn )
	: AddMenuCommand( n, fw, mw ) { menuBar = mb; popup = p; id = i; index = idx, name = mn; }

    void execute() { AddMenuCommand::unexecute(); }
    void unexecute() { AddMenuCommand::execute(); }
    Type type() const { return RemoveMenu; }

};

class RenameMenuCommand : public Command
{
public:
    RenameMenuCommand( const TQString &n, FormWindow *fw, QDesignerMenuBar *mb,
		       int i, const TQString &on, const TQString &nn );

    void execute();
    void unexecute();
    Type type() const { return RenameMenu; }

private:
    QDesignerMenuBar *menuBar;
    int id;
    TQString oldName, newName;

};

class MoveMenuCommand : public Command
{
public:
    MoveMenuCommand( const TQString &n, FormWindow *fw, QDesignerMenuBar *mb,
		     QDesignerPopupMenu *p, int fidx, int tidx, const TQString &txt );

    void execute();
    void unexecute();
    Type type() const { return MoveMenu; }

private:
    QDesignerMenuBar *menuBar;
    QDesignerPopupMenu *popup;
    int fromIdx, toIdx;
    TQString text;

};

class AddToolBarCommand : public Command
{
public:
    AddToolBarCommand( const TQString &n, FormWindow *fw, TQMainWindow *mw );

    void execute();
    void unexecute();
    Type type() const { return AddToolBar; }

protected:
    QDesignerToolBar *toolBar;
    TQMainWindow *mainWindow;

};

class RemoveToolBarCommand : public AddToolBarCommand
{
public:
    RemoveToolBarCommand( const TQString &n, FormWindow *fw, TQMainWindow *mw, QDesignerToolBar *tb )
	: AddToolBarCommand( n, fw, mw ) { toolBar = tb; }

    void execute() { AddToolBarCommand::unexecute(); }
    void unexecute() { AddToolBarCommand::execute(); }
    Type type() const { return RemoveToolBar; }

};

#endif
