//  Qcalc.h
//
//  Qsas - Calculator Header File
//
//  Nora Bounaira
//  Dec 2003
//

#ifndef QSAS_QCALC_H_
#define QSAS_QCALC_H_

#include "qt_version.h"
#include <qobject.h>
#include <qsplitter.h>
#include <qtabwidget.h>
#include <qstatusbar.h>
#include <qlayout.h>
#include <qtooltip.h>
#include <qdatetime.h>
#ifdef QT_VERSION
#if QT_VERSION<0x030000
#include <qmultilineedit.h>
#else
#include <qtextedit.h>
#endif
#endif

#if QT_VERSION < 0x040000
#include <qhbox.h>
#include "qgu.h"
#else
#include "qgu_qt4.h"
#endif
#include "qslot.h"
#include "qOperators.h"

#define Qcalc_VERSION  " V_2.10 [ Nov 2005 ]"


#define JOIN_MENU_ITEM_ID           0
#define ARITHMETIC_MENU_ITEM_ID     1
#define FILTER_MENU_ITEM_ID         2
#define TRIG_MENU_ITEM_ID           3
#define VECTOR_OPS_MENU_ITEM_ID     5
#define MODIFY_MENU_ITEM_ID         5

#define RENAME_ALIAS_RB_MENU_ITEM        7
#define RENAME_ALIAS_EDITMENU_MENU_ITEM  8

#define MAX_N_OPERANDS  2

#define NUMBER_OPERAND  "NUMBER"

enum ItemTypeEnum   { WORKING_LIST_OBJECT = 0,  VIRTUAL_OBJECT, NONE_OBJECT  };

class QcalcWindow;
class QcalcListVirtualItem;
class QcalcTab;
class QcalcInput;

Vostream& operator<<(   Vostream&,    QcalcListVirtualItem& );
Vostream& WriteCalcItem( Vostream&,   QcalcListVirtualItem& );

Vistream& operator>>(   Vistream&,    QcalcListVirtualItem& );
Vistream& ReadCalcItem( Vistream&,    QcalcListVirtualItem& );

#define  DELETE_POINTER( PTR ) \
      if ( PTR )               \
	  {                        \
	       delete PTR;         \
		   PTR = NULL;         \
	  }



class QcalcListVirtualItem : public QguListItem
{

public:
    QcalcListVirtualItem( QguListView *parent= 0,
                          QString      txt   = "",
		                QString      WL    = "",
	                     QguListType  type  = ListTypeEntry,
	                     QguListItem *after = 0 );

    QcalcListVirtualItem( QguListItem *parent= 0,
                          QString      txt   = "",
	                     QString      WL    = "",
	                     QguListType  type  = ListTypeEntry,
	                     QguListItem *after = 0 );

    ~QcalcListVirtualItem();
    void setChoices( ); 

    void QcalcInitItem( QString txt, QString WL, QguListType  type );
    QString GetNextAliaseName();
    bool    AliasAlreadyUsed( QString name );
    QdObject_var getDataObject();
    Dim_var getVirtualArrDim();
    
    virtual bool validateLink( bool valid );

   ItemTypeEnum    m_eObjType;
   QdObject_var    m_qdObjJoinedFirst;
    QString        m_alias_cpy;  // used ONLY to hold alias while writing modified one to save file
    QString        m_qstrOperator;
    int            m_nOp;
    QdObject_var   m_qdObjResult;
    bool           m_bCalcDone;
    bool           m_bFilled;
    QcalcTab*      m_pcalcTab;
    QString        m_NameForSave;
    int            isIvlObj;
    int            isTagObj;
    bool           ObjIsVec;    // only used by WL objects


    bool setArrayFlags();
    void SetItemVirtualName( bool bEmitChange = true );

    QdObject_var getResultObject();
    
    void DoMathOperation();
    void DoOperation();
    bool CheckOperatorSelfLink( QString& rqstrAliase );

    void reNameAlias( const QString& NewVal );
    bool getIsVector( );
    bool getIsArray( );
    
};




class QcalcListView;

Vostream& operator<<( Vostream&, QcalcListView& );
Vistream& operator>>( Vistream&, QcalcListView& );

class QcalcListView : public QguListView
{

  typedef void ( QCheckBox::*CheckBoxFnPtr )( bool bOn );

  Q_OBJECT
  friend Vostream& operator<<(Vostream&,QcalcListView&);
  friend Vistream& operator>>(Vistream&,QcalcListView&);

public:
   QcalcWindow* owner;
   QString      m_qstrWidgetText;
   QdTimeSeq_var    qdtargetTT;
   
   QcalcListView( QWidget *parent, QcalcWindow* QjW, const char *name=0 );
   ~QcalcListView();
   void insertEntries(QguListItem *dropAt, QguListItem *item);
   virtual void dropEvent(QDropEvent *event);
   bool reNameItemAlias(  QcalcListVirtualItem * item );

   void setSelectedList( QguListItem *item );
   virtual void getAliasArrDim(QString,Dim_var &);
   virtual QguAliasObjType getAliasObjectType(QString);
   virtual QguAliasType getAliasObject(QString,QdObject_var);
   virtual QdObject_var getAliasResultObject(QString);

protected:
   void keyPressEvent(QKeyEvent * e );

signals:
  void pasteDetected();
  void SelectionUpdated();
  void listItemDeleted();


public slots:
  void makeGroup();
  void paste();
  void renameSelectedItemAlias();
  void deleteListItems();
  void deleteAllItems();

  void insertVirtualItem();
  void tabChanged( QWidget* qwdgt );
  void validateWLitems();
  void propagateSelection(const char *, const char *);
  void propagateDrop(const char *);

protected:
   virtual void contentsMouseReleaseEvent(  QMouseEvent*    event );
   virtual void contentsMousePressEvent(    QMouseEvent*    event );
   virtual void contentsMouseMoveEvent(     QMouseEvent*    event );
   virtual void dragMoveEvent(              QDragMoveEvent* event );
   virtual void contentsMouseDoubleClickEvent( QMouseEvent *event );

private:

   QString       m_strAliseName;
   char          m_chChar;


};


class QcalcTab : public QWidget
{
Q_OBJECT

public:
   QcalcTab();
   ~QcalcTab();

   QGroupBox*       details_groupbox;  ///< Object name group box
#if QT_VERSION < 0x040000
   QWidget*			details_widget;
#endif
   QGridLayout*		details_layout;
   QLabel*			objAlias_label;
   QGroupBox*		operation_groupbox;
#if QT_VERSION < 0x040000
   QWidget*			operation_widget;
#endif
   QGridLayout*		operation_layout;
#if QT_VERSION < 0x040000
   QWidget*			operand_widget;
#endif
   QGridLayout*		operand_layout;
#if QT_VERSION < 0x040000
   QWidget*			extras_widget;
#endif
   QGridLayout*		extras_layout;
   QLabel*			operator_label;
   QGroupBox*		join_groupbox;
#if QT_VERSION < 0x040000
   QWidget  *		qwJoinSetting;
#endif
   QGridLayout*		join_layout;
   QLabel*			algorithm_label;
   QLabel*			width_label;
   QLabel*			blank_label;
   QLabel*			blank2_label;
   QLabel*			gap_label;
   QLabel*			gapSize_label;
   QguWLinput*      objAliase_field;///< Alias widget. This can be changed directly from its parent tab
   Q_POPUP_MENU*      arithmetic;
   Q_POPUP_MENU*      trig;
   Q_POPUP_MENU*      vectorOps;
   Q_POPUP_MENU*      filter;
   Q_POPUP_MENU*      modify;
   QcalcInput*      AngleUnits;
   QCheckBox*       saveWL_check;
   QguWLinput*      _nameWL_field;
   QcalcListView*   calcListview;
   QPushButton*     tb4;
   Q_POPUP_MENU*      menu;
   vector <QcalcInput*>  operandStack;
   int              nSlots;
   QcalcListVirtualItem *virtualItem;
   QguWLinput* _width_field;
   QComboBox*  _gap;
   QguWLinput* _gap_field;
   QComboBox*  _algorithm;
   bool WLnameUnset;
   bool opWasJoin;
 
   void createCalcTabWidgets(QcalcListVirtualItem *VirtItem);
   void SetOperator( const QString&  strOperator );
   void SetSlotsForOperator( const QString&  strOperator );
   bool isOpAllowed();
   bool AddValid();
   bool DivideValid();
   bool VectorProdValid();
   bool FilterValid();
   bool MultiplyValid();
   bool PowerValid();

private:
	void DisplayOperatorDesc( int nOperator, Q_POPUP_MENU* qMenu );

protected:

signals:

public slots:
  void reNameAliasTab(const QString&);
  void ValidateAlgorithm( int nIndex );  // If algorithm is set to LINEAR then the average edit box is disabled
  void setGap(int nIndex);
  void setWidthField();
  void setGapField();
  void SetTab();
  void SetTabFeedback( );
  void confirmAliasSlot();
  void SetOperand( const QString & opStr );
  void SetLink( const QString & opStr );  
  void toggleWLName();  
  void setNameForSave(const QString& ); // sets m_NameForSave which is used ONLY to keep name while save toggle is off

  void SetOperatorArithemtic( int nOperator );
  void SetOperatorTrig(       int nOperator );
  void SetOperatorVectorOps(  int nOperator );
  void SetOperatorFilter(     int nOperator );
  void SetOperatorModify(     int nOperator );
  void SetOperatorJoin(       int nOperator );

  
  void DisplayOpArithemticDesc( int nOperator );
  void DisplayOpTrigDesc(       int nOperator );
  void DisplayOpVectorOpsDesc(  int nOperator );
  void DisplayOpFilterDesc(     int nOperator );
  void DisplayOpModifyDesc(     int nOperator );
  
  void setThisSelected();
  void updateFlags( );
};


class QcalcWindow : public QguWindow {

Q_OBJECT

  QGridLayout*   _top_gl;
  QSplitter *    _top_splitter;
  Q_POPUP_MENU*    options_menu;
  int            toggleID;

public slots:
  void save();
  void saveAs();
  void saveSession(QString);
  void defaultAll();
  void verboseToggle();
  bool joinObjects( QdObjectSeq_var JoinedList, vector<KVDataBase_var> &OptionList, bool skipVirtual);
  bool joinSlotObjects(QcalcTab *qTab, vector <QdObject_var>   &returnList );
  void writeFile();
  void keepChoices();
  void applyChoices();
  void setTTsource(int);
  void setTTivl(int);
  void setTimeFeedback();
  void messageHandler( QString txt, bool bError = false );

  void launchManExport();
  void launchManJoin();
  void launchManual();
  void launchVersion();

   // Slot called when do button is pressed
  void DoCalculation();

	// Display end message
	void DisplayEndMessage();

signals:
  void ClearComboBox();
  void ProcessListView();

public:
  QcalcWindow( QWidget *parent=0, const char *name=0 );
  virtual ~QcalcWindow();
  void setDefaults();
  QcalcListView* _join_listview;
  
  QString SAVE_ALIAS_EXT;
   
  QdTimeInterval_var QcalcGetIntervalFromData();
  QdTimeSeq_var      getTimeTags( );
  QdTimeInterval_var QcalcGetInterval(  );

  virtual void save( Vostream& );
  virtual void restore( Vistream& v_is, bool replace=true );

#if QT_VERSION < 0x040000
  QHGroupBox  *buttons_layout;
#else
  QGroupBox  *buttons_groupbox;
#endif
  QPushButton *dismissBtn;
  QPushButton *WriteBtn;
  QPushButton *JoinBtn;
  QWidget*    _top_widget;
  QPushButton *newCalcBtn;

  QComboBox*  _TimeIvlSelect;
  QguWLinput* _DataSource;
  QguWLinput* _IvlSource;
  QComboBox*  _TimeTagSelect;
  QguWLinput* _TagSource;

  QLabel*     IvlSource_label;
  QLabel*     TagSource_label;
  QLabel*     Start_field;
  QLabel*     End_field;
  QLabel*     Ntags_field;
  QLabel*     spacing_field;


  //Q_POPUP_MENU* menu;

  QCheckBox*  multiJn_check1;
  QCheckBox*  multiJn_check2;

  // Tab widget
  QTabWidget* tabWidget;

  Q_POPUP_MENU* edit_menu;


#ifdef QT_VERSION
#if QT_VERSION <0x030000
  QMultiLineEdit* logArea;
#else
  QTextEdit*      logArea;
#endif // end of #if
#endif // end of #ifdef

  QString  _width_field_Def;
  int      _gap_Def;
  QString  _gap_field_Def;
  int      _algorithm_Def;
  QString  _IvlSource_Def;
  int      _TimeIvlSelect_Def;
  QString  _TagSource_Def;
  int      _TimeTagSelect_Def;

  QString  _width_field_cpy;
  int      _gap_cpy;
  QString  _gap_field_cpy;
  int      _algorithm_cpy;
  QString  _IvlSource_cpy;
  int      _TimeIvlSelect_cpy;
  QString  _TagSource_cpy;
  int      _TimeTagSelect_cpy;

  double   qcalc_version;
  bool     verbose;

  MapCalculator m_mapOps;

protected:
  void dragEnterEvent( QDragEnterEvent *event);
  void keyPressEvent(QKeyEvent * e );
 
private:
  void CreateObjectLisView();
  void CreateJoinTabWindow();
  void CreateFeedBackGroupBox();
  void CreatePopUpMenus();

  KVDataBase_var GetJoinOptionObject( QcalcListVirtualItem* next,
                                      QdObject_var          obj  );

  bool CheckSelfLinkedVirtualObjs();
  bool JoinFirst();
  bool JoinLast();
  bool disjointSeries( QdObject_var obj );

};


class QcalcInput : public Q_H_BOX{

Q_OBJECT


public:
    QcalcInput( QWidget *parent= 0, QString name="", QString label="", QcalcTab *qTab=0 );

    void setText(QString);
    void setAnglePulldown();
    void SetConstant( const QString& strConstant );
    
    QLabel *inputLabel;
    QguWLinput *slot;
    QComboBox *pulldown;
};



QcalcWindow * QCALCmakeWindow( QWidget *parent, const char * Title );
void QCEXPmakeWindow( QWidget *parent, const char * Title );
void QcalcShowCalc();
void QcalcShowExport();
void QcalcAppendTextDisplay ( const char*  text );
QString getOpName(int OpNum);
QString getOpChar(int OpNum);

extern QcalcWindow *QCALC_widget;
extern QcalcWindow *QCEX_widget;



#endif // QSAS_QCALC_H_

