//  qgu.h
//
//  Qsas - drop slot Header File
//
//  Tony Allen
//  Jan 2002
//
/// \file qgu.h
///  Declaration file for the main GUI classes that are used within QSAS which are: \n
///  \arg \c QguWLinput  \n
///  \arg \c QguWindow   \n \n
///  Those classes specialise respectively the QT3 built-in classes as listed below\n
///  \arg \c QLineEdit     \n
///  \arg \c QMainWindow   \n\n
///  \author A J Allen    \n
///  \date    2005/2007

#ifndef QSAS_SL_H_
#define QSAS_SL_H_

#define QSLOT_VERSION  "QSL V_2.1 [ Aug 2007]"

#include <string>
#include <vector>

#include <qlineedit.h>
#include <qtoolbutton.h>
#include <qlabel.h>
#include <qcombobox.h>
#include <qslider.h>
#include <qmenubar.h>
#include <qpushbutton.h>

#include "qt_version.h"

#include "qsas_version.h"
#include "Qdos.h"
#if QT_VERSION < 0x040000
#include <qhgroupbox.h>
#include <qvgroupbox.h>
#include <qpopupmenu.h>
#include "qsw_helpwindow.h"
#include "qgu.h"
#else
#include <QGroupBox>
#include <QMenu>
#include "qsw_helpwindow_qt4.h"
#include "qgu_qt4.h"
#endif
#include "qdutil.h"


class QguWLinput;
class RecordSlider;
class timeSlider ;

/// \class QguLineEdit qgu.h
/// \brief This is the QguLineEdit class
///
/// This class specialises the QLineEdit widget itself inside QguWLinput to allow us to overload drop and paste
///
/// A line edit allows the user to enter and edit a single line of plain text with a useful collection of editing functions, 
/// including undo and redo, cut and paste, and drag and drop
///
/// It inherits QLineEdit which is a built-in QT3 class
///
/// \remarks { 
/// This class includes Q_OBJECT which is a QT3 macro that is used in all sub-classes of QObject in order to
/// benefit from the QT's Meta object system which are signals and slots mechanisms for inter-object communication,
/// runtime type information and the dynamic property system }

class QguLineEdit : public QLineEdit
{
   Q_OBJECT
   
public:
   QguLineEdit(QWidget *parent, const char *name);
   ~QguLineEdit();
   QguWLinput *WLinput;
      
signals:
   /// \fn void hadDropEvent()
   /// \brief signal emitted drop received
   /// \param    None
   /// \exception None
   /// \return   None
   ///          
   void hadDropEvent();
   
   
public slots:
   void paste();
   
protected:
   virtual void dropEvent(QDropEvent *e);

};

class QguWLinput;

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

/// \class QguWLinput qgu.h
/// \brief This is the QguWLinput class
///
/// This class specialises the QLineEdit widget which is a one-line text editor. Does so inside a box with optional 
/// drop down menu for sub-dimensions
///
/// A line edit allows the user to enter and edit a single line of plain text with a useful collection of editing functions, 
/// including undo and redo, cut and paste, and drag and drop
///
/// It inherits Q_H_GROUP_BOX which is a built-in QT3 class
///
/// \remarks {
/// This class includes Q_OBJECT which is a QT3 macro that is used in all sub-classes of QObject in order to
/// benefit from the QT's Meta object system which are signals and slots mechanisms for inter-object communication,
/// runtime type information and the dynamic property system }

class QguWLinput : public Q3_H_GROUP_BOX
{
   Q_OBJECT
  friend Vostream& operator<<(Vostream&,QguWLinput&);
  friend Vistream& operator>>(Vistream&,QguWLinput&);
   
public:
   QguWLinput(QWidget *parent, const char *name);
   ~QguWLinput();
   QdObject_var getSlotObject();
   void setColour(const QString& validity);
   void setText(QString txt);
   void setTextKeepComp(const QString& txt);
   bool compatibleComp(QdObject_var dobj, const QString &comp, bool &nowVector);
   void setAliasKeepComp(const QString &txt);
   QString text();
   QString textObject();
   double value();
   void setDouble(double value);
   void setCursorPosition(int posn);
#if QT_VERSION < 0x040000
   void setAlignment(int flag);
#else
   void setAlignment(Qt::AlignmentFlag flag);
#endif
   void setMaxLength(int len);
   bool edited();
   void setEdited(bool hasBeenEdited);
   bool setDropdownActive(QdObject_var dobj, const bool toScalar, bool isVect, bool useTimeSlicer);
   void setReadOnly(bool readOnly);
   void clear();
   bool hasFocus();
   void clearFocus();
   void setEnabled(bool enabled);
   dimTripleStack parseArrayReduce();
   dimTriple parseTimeSlice();
   QguComp_e getComponent();
   Dim_var getSlotArrDim();
   void emitCmpSelected(const char * cmpTxt, const char * cmpType);
   bool isTimeSelection();
   
   Q_POPUP_MENU *getDefaultPopup();
   Q_POPUP_MENU *getDefaultPopupSlice();
   Q_POPUP_MENU *getTrangePopup();
   Q_POPUP_MENU *getTivlPopup();
   Q_POPUP_MENU *getTivlPopupPlus();
   Q_POPUP_MENU *getTivlFromEvtTablePopup();
   Q_POPUP_MENU *getTivlSeqSlicePopup();
   Q_POPUP_MENU *getVectorPopup();
   Q_POPUP_MENU *getVectorPopupPlus();
   Q_POPUP_MENU *getVectorPopupSlice();
   Q_POPUP_MENU *getVectorPopupPlusSlice();
   Q_POPUP_MENU *getArrayPopup();
   Q_POPUP_MENU *getArrayPopupPlus();
      
   QToolButton * dropDownArray;
   QguLineEdit *lineBox;
   QguListView * aliasList;
   Q_POPUP_MENU * defaultPopup;
   Q_POPUP_MENU * defaultPopupSlice;
   Q_POPUP_MENU * TivlPopup;
   Q_POPUP_MENU * TivlPopupPlus;
   Q_POPUP_MENU * TivlFromEvtTablePopup;
   Q_POPUP_MENU * TivlSlicePopup;
   Q_POPUP_MENU * TrangePopup;
   Q_POPUP_MENU * vectorPopup;
   Q_POPUP_MENU * vectorPopupPlus;
   Q_POPUP_MENU * vectorPopupSlice;
   Q_POPUP_MENU * vectorPopupPlusSlice;
   Q_POPUP_MENU * arrayPopup;
   Q_POPUP_MENU * arrayPopupPlus;
   bool reduce3Dto1;
   bool reduce3DtoScalar;

   
   bool active;   ///< Public flag set to signify that this QguWLinput is active (accepts input)
   bool acceptNumber;   ///< Public flag, true implies QguWLinput accepts numerical input (using atof() from text input)
   bool acceptInteger;   ///< Public flag, true implies QguWLinput accepts integer input (using atoi() from text input)
   bool acceptObject;   ///< Public flag, true implies QguWLinput accepts QdObject_var input
   bool acceptObjectPlus;   ///< Public flag, true implies QguWLinput accepts QdObject_var input permitting dimension reduction 
   bool acceptObjectMinus;   ///< Public flag, true implies QguWLinput accepts QdObject_var input only for dimension reduction 
   bool acceptScalarObject;   ///< Public flag, true implies QguWLinput accepts QdRScalar_var and QdRScalarSeq_var input 
   bool acceptVectorObject;   ///< Public flag, true implies QguWLinput accepts QdRMatrix_var and QdRMatrixSeq_var input that satisfies QuIsThreeVector
   bool acceptArrayObject;    ///< Public flag, true implies QguWLinput accepts QdRMatrix_var and QdRMatrixSeq_var input 
   bool acceptObjectPlus_TSonly;   ///< Public flag, true implies QguWLinput accepts any input if it has TIME_TAGS xref   
   bool acceptScalarObject_TSonly;   ///< Public flag, true implies QguWLinput accepts QdRScalar_var and QdRScalarSeq_var input if it has TIME_TAGS xref
   bool acceptVectorObject_TSonly;   ///< Public flag, true implies QguWLinput accepts QdRMatrix_var input if it has TIME_TAGS xref, that satisfies QuIsThreeVector, 
   bool acceptArrayObject_TSonly;    ///< Public flag, true implies QguWLinput accepts QdRMatrix_var input if it has TIME_TAGS xref
   bool acceptTTagObject;    ///< Public flag, true implies QguWLinput accepts QdTimeSequenace_var or QdObject_var input with a TIME_TAGS xref
   bool acceptTIvlObject;    ///< Public flag, true implies QguWLinput accepts QdTimeInterval_var input
   bool acceptTIvlSeqObject; ///< Public flag, true implies QguWLinput accepts QdTimeIntervalSeq_var input
   bool acceptDuration;    ///< Public flag, true implies QguWLinput accepts number input to be used as time duration
   bool acceptTimeObject;    ///< Public flag, true implies QguWLinput accepts QdTime_var input 
   bool acceptText;    ///< Public flag, true implies QguWLinput accepts any keyboard text input
   bool acceptTime;   ///< Public flag, true implies QguWLinput accepts any valid ISO time text string input
   bool acceptAliasToScalar;   ///< Public flag, true if slot accepts a name on the specified QguListView * aliasList. Restricted to Scalar
   bool acceptAliasToVector;   ///< Public flag, true if slot accepts a name on the specified QguListView * aliasList. Restricted to Vector
   bool acceptAlias;   ///< Public flag, true if slot accepts a name on the specified QguListView * aliasList
   bool acceptTimeSlice; ///<Public flag, true if slot accepts slice or average down to single time
   bool acceptTimeSubset; ///<Public flag, true if slot accepts slice, average down or subset on time
   bool refresh;      ///< local flag to trap re-validation following a refresh of the input during validation. No infinite loop.

   int with;    ///< Public member defining how the list view is being saved (saved with/without data)
   bool beenEdited;  ///< flag to show a manual edit has taken place
   QString ObjectName; ///< The WL context for the valid object or the alias name
   QString ObjectName_nil; ///< nil string used when input did not validate OK
   QString objType; ///< the type of object resloved to, "text", "object", "number", "timeString"
   QdObject_var nilObject; ///< nil object for use when invalid slot input text so that a .is)nil() object is returned
   bool slotObjVector; ///<  flag for current item is vector
   bool slotObjArray; ///<  flag for current item is array
   bool userChoice; ///<  flag to let initialisation of Time object without validation to time string
   bool canEmitCmpSel;
   QPalette *WLI_palette;
   
signals:
   /// \fn void hadDropEvent()
   /// \brief signal emitted drop received
   /// \param    None
   /// \exception None
   /// \return   None
   ///          
   void hadDropEvent();

   /// \fn void validated_alias()
   /// \brief Function signal that is emitted when entered text is alias on calculator list
   /// \param     text validated
   /// \exception None
   /// \return    None
   ///  
   void validated_alias(const QString &);
   
   /// \fn void validated_WL_OBJ()
   /// \brief Function signal that is emitted when entered text is WLcontext for item on WL
   /// \param     text validated
   /// \exception None
   /// \return    None
   ///  
   void validated_WL_OBJ(const QString &);
   
   /// \fn void validated_number()
   /// \brief Function signal that is emitted when entered text is a number
   /// \param     text validated
   /// \exception None
   /// \return    None
   ///  
   void validated_number(const QString &);
   
   /// \fn void validated_TEXT()
   /// \brief Function signal that is emitted when text data being entered has been validated
   /// \param     None
   /// \exception None
   /// \return    None
   ///  
   void validated_TEXT(const QString &);
   
   /// \fn void validated_OK()
   /// \brief Function signal that is emitted when any data being entered has been validated with success
   /// \param     None
   /// \exception None
   /// \return    None
   ///  
   void validated_OK();
   
   /// \fn void validated_WARN()
   /// \brief Function signal that is emitted when text entered is incomplete, but valid so far
   /// \param     None
   /// \exception None
   /// \return    None
   /// 
  void validated_WARN();
  
   /// \fn void validated_NOT_OK()
   /// \brief Function signal that is emitted when text entered is not compatible with slot requirements 
   /// \param     None
   /// \exception None
   /// \return    None
   /// 
   void validated_NOT_OK();
   
   /// \fn void validated_EMPTY()
   /// \brief Function signal that is emitted when line input object does not contain any text
   /// \param     None
   /// \exception None
   /// \return   None
   /// 
   void validated_EMPTY();
   
   /// \fn void validated_INACTIVE()
   /// \brief Function signal that is emitted when the line input object is set inactive
   /// \param     None
   /// \exception None
   /// \return   None
   /// 
   void validated_INACTIVE();
      
   /// \fn void textChanged(const QString&)
   /// \brief signal emitted when input text changes
   /// \param     txt of type QString
   /// \exception None
   /// \return   None
   /// 
   void textChanged(const QString &);
   
   /// \fn void componentSelected(const char *, const char *)
   /// \brief signal emitted when dropdown component menu activated for time or vector
   /// \param     component of type const char *, flag of type const char * = "VECTOR" or "TIME"
   /// \exception None
   /// \return   None
   ///    
   void componentSelected(const char *, const char *);
  
   /// \fn void TimeChosen()
   /// \brief signal emitted when dropdown component menu selected a time
   /// \param     None
   /// \exception None
   /// \return   None
   ///   
   void TimeChosen();

   /// \fn void dropDetected()
   /// \brief signal emitted when data obj dropped or pasted in slot
   /// \param     object name of type const char *
   /// \exception None
   /// \return   None
   ///   
   void dropDetected(const char *);


public slots:
   void validateInput(const QString &);   
   void sendTextChanged(const QString &);
   void reValidate();
   void paste();
   void setDropdownText_r();
   void setDropdownText_x();
   void setDropdownText_y();
   void setDropdownText_z();
   void setDropdownText_ld();
   void setDropdownText_td();
   void setDropdownText_pd();
   void setDropdownText_lr();
   void setDropdownText_tr();
   void setDropdownText_pr();
   void setDropdownText_dobj();
   void openArrayReduce();
   void openSliceT();
   void openSliceS();
   void openSliceV();
   void openSliceVP();
   void openSelectMetadata();
   void setDropdownTstart();
   void setDropdownTcentre();
   void setDropdownTend();
   void resetColour();
   void selectTivlSeqSubset();
   void selectTivlEvent();
   
protected:
 //  virtual void mouseDoubleClickEvent(QMouseEvent *e);
 
};



//class indexSlider : public Q_H_GROUP_BOX {
class indexSlider : public QWidget {
  
Q_OBJECT

public:
  indexSlider( int atNum, QString title, int maxN, QWidget *parent=0, char * name=0 );
  ~indexSlider();
  
  QguWLinput *numField;
  QLabel * echoLabel;
  int num;
  int maxNum;
  
  void setLabel(const QString& label){echoLabel->setText(label);}
  
public slots:
  void decRec();
  void incRec();
  void adjustRec();
  
signals:
   void indexChanged();
   
protected:
 //  QGroupBox *index_slider_groupbox;
};


class rangeSlider : public Q_H_GROUP_BOX {
  
Q_OBJECT

public:
  rangeSlider(int idx, int MaxN, QdObject_var depend_i, QWidget *parent=0, char * name=0 );
  ~rangeSlider();
  
  indexSlider * fromSlide;
  indexSlider * toSlide;
  QLabel *fromLabel;
  QLabel *toLabel;
  QdStringSeq_var binTextSeq;
  QComboBox *actionChoice;
  
public slots:
  void updateOnIdx();
  void updateRangeWidget(int);
  
signals:
  
   
protected:
  
};


class ArrayReduceWindow : public QDialog {

Q_OBJECT

  QMenuBar *_menu_bar;
  QswHelpWindow *arrHelp_window;
  QPushButton *dismissBtn;
  
public slots:
  void launchVersion();
  void launchManArrayReduce();
  void launchManual();
  void setDefaults();
  void setToLastChoice();
  void dismiss();
  void acceptSelection();
  void updateFeedback();
    
signals:

public:
    
  ArrayReduceWindow(QString WLcontext, Dim &arrayDim, QWidget *parent=0, const char *name=0,
		  bool acceptTSubset=false, bool acceptTSlice=false, bool modal=false ); 

  ~ArrayReduceWindow(){;};
  QguWLinput *parentSlot; 
  vector <rangeSlider *> sliderStack;
  bool isSequence;
#if QT_VERSION < 0x040000
  QHGroupBox *buttons_layout;
#else
  QGroupBox * buttons_groupbox;
#endif
  timeSlider *slicer;
  
protected:
  
};


class TimeSliceWindow : public QDialog {

Q_OBJECT

  QMenuBar *_menu_bar;
  
public slots:
  void setDefaults();
  void setToLastChoice();
  void dismiss();
  void acceptSelection();
  void updateFeedback();
    
signals:

public:
    
  TimeSliceWindow(QString WLcontext, const char * source,QWidget *parent=0, 
		  const char *name=0,bool acceptTSubset=false, bool acceptTSlice=false, 
		  bool modal=false ); 

  ~TimeSliceWindow(){;};
  QguWLinput *parentSlot;   
#if QT_VERSION < 0x040000 
  QHGroupBox *buttons_layout;
#else
  QGroupBox *buttons_groupbox;
#endif
  QComboBox  *vectorChoice;
  timeSlider *slicer;
  
protected:
  
};

class TimeIntervalSlider : public Q_H_GROUP_BOX {

    Q_OBJECT

    public:
        TimeIntervalSlider(const QString & title, QWidget * parent=0, const char * name =0);
        void updateTitle();
  
        QSlider *recBar;
        QguWLinput *recField;
        int record;
        int maxRecord;
        QdTimeIntervalSeq_var obj;
        QString titleBase;
  
    public slots:
        void incRec();
        void decRec();
        void lastRec();
        void firstRec();
        void adjustRec(int);
        void setFromTyping();
  
    signals:
        void sliderChanged();
};

class SelectTivlWindow : public QDialog {

    Q_OBJECT

  
    public slots:
        void validated();
        void cancelled();
    
    signals:

    public:
    
        SelectTivlWindow(QString WLcontext, const char * source,QWidget *parent=0, 
                        const char *name=0,
                        bool modal=false ); 

        ~SelectTivlWindow(){;};
        QguWLinput *parentSlot;
        QPushButton * validateBtn;
        QPushButton * cancelBtn;
        TimeIntervalSlider * slider;
        QdTimeIntervalSeq_var obj;
        int record;
        int max_rec;
  
    protected:
  
};

class SelectTivlSubsetWindow : public QDialog {

    Q_OBJECT

//             QMenuBar *_menu_bar;
  
    public slots:
        void validated();
        void cancelled();
        
    public:
        int record_start, record_end;
        int max_rec;
    
    signals:

    public:
    
        SelectTivlSubsetWindow(QString WLcontext, const char * source,QWidget *parent=0, 
                         const char *name=0,
                         bool modal=false ); 

        ~SelectTivlSubsetWindow(){;};
        QguWLinput *parentSlot;
        TimeIntervalSlider * slider1;
        TimeIntervalSlider * slider2;
        QPushButton * validateBtn;
        QPushButton * cancelBtn;
        QdTimeIntervalSeq_var obj;

  
    protected:
  
};


class selectMetadataWindow : public QMainWindow{

Q_OBJECT

  QswHelpWindow *metaHelp_window;
  QPushButton *dismissBtn;
  
public slots:
  void selectAndClose();
  void dismiss();
  void launchManual();
    
signals:

public:
    
  selectMetadataWindow(QdObject_var dobj,  QWidget *parent=0, const char *name=0); 

  ~selectMetadataWindow();
  Q_LIST_VIEW * xrefList;
  QguWLinput *parentSlot; 
    
protected:
  
};


/// \class DataSliceWindow qdutil.h
/// \brief This is the DataSliceWindow class
///
/// This class specialises the QMainWindow class which provies a main application window.
///
/// Main windows are most often used to provide menus, toolbars and a status bar around a large central widget.
///
/// It inherits QMainWindow which is a built-in QT3 class
///
/// \remarks {
/// This class includes Q_OBJECT which is a QT3 macro that is used in all sub-classes of QObject in order to
/// benefit from the QT's Meta object system which are signals and slots mechanisms for inter-object communication,
/// runtime type information and the dynamic property system }

class DataSliceWindow: public QMainWindow
{
  Q_OBJECT

protected:
  QMenuBar *_menu_bar;      ///<  Menu bar of the current main window object
  
public:
  DataSliceWindow( QWidget *parent=0, const char *name=0 );
  /// \fn ~DataSliceWindow()
  /// \brief Destructor of the DataSliceWindow class
  /// \param     None
  /// \exception None
  /// \return    None
  ///
  virtual ~DataSliceWindow(){};
  void setObject(const char * WLctxt);

  QStatusBar* msgBar;       ///<  Message bar of the current main window object (also qsas window)

  QMenuBar* menu_bar(){ return _menu_bar;};

  /// \fn QStatusBar* status_bar()
  /// \brief Function that returns the status bar pointer of the current main window object
  /// \param     None
  /// \exception None
  /// \return    None
  ///
  QStatusBar* status_bar(){return msgBar;};
  QguWLinput *objField;
  QguWLinput *name_field;
  bool userSet;

public slots:
  void acceptSlice();
  void setUserInput(const QString &);
  void setNewName();

protected:
  void keyPressEvent(QKeyEvent * e );
  QPushButton *saveBtn;
  QPushButton *dismissBtn;
};


class RecordSlider : public Q_H_GROUP_BOX {

Q_OBJECT

public:
  RecordSlider(const QString & title, QWidget * parent=0, const char * name =0);
  void updateTitle();
  
  QSlider *recBar;
  QguWLinput *recField;
  int record;
  int maxRecord;
  QdTimeSeq_var ttags;
  QString titleBase;
  
public slots:
  void incRec();
  void decRec();
  void lastRec();
  void firstRec();
  void adjustRec(int);
  void setFromTyping();
  
signals:
  void recordSliderChanged();
};

class timeSlider : public Q_V_GROUP_BOX {

Q_OBJECT

public:
  timeSlider(QdObject_var dobj, bool acceptTSlice, bool acceptTSubset, QWidget *parent=0, char * name=0);
  virtual ~timeSlider(){;};
  bool isDefault();

  QComboBox *sliceChoice;
  RecordSlider *fromSlider;
  RecordSlider *toSlider;
  RecordSlider *atSlider;
  QVBoxLayout * mainLayout;
  int Inothing;
  int Isubset;
  int Iaverage;
  int Islice;
  
public slots:
  void updateTimeSlider(int opChoice);
  void resetEnd();
  void resetStart();
  
};

/// \class MakeVectorWindow qdutil.h
/// \brief This is the DataSliceWindow class
///
/// This class specialises the QMainWindow class which provies a main application window.
///
/// Main windows are most often used to provide menus, toolbars and a status bar around a large central widget.
///
/// It inherits QMainWindow which is a built-in QT3 class
///
/// \remarks {
/// This class includes Q_OBJECT which is a QT3 macro that is used in all sub-classes of QObject in order to
/// benefit from the QT's Meta object system which are signals and slots mechanisms for inter-object communication,
/// runtime type information and the dynamic property system }

class MakeVectorWindow: public QMainWindow
{
  Q_OBJECT

protected:
  QMenuBar *_menu_bar;      ///<  Menu bar of the current main window object
  
public:
  MakeVectorWindow( QWidget *parent=0, const char *name=0 );
  /// \fn ~MakeVectorWindow()
  /// \brief Destructor of the DataSliceWindow class
  /// \param     None
  /// \exception None
  /// \return    None
  ///
  virtual ~MakeVectorWindow(){};
  void setObject(const char * WLctxt);

  QStatusBar* msgBar;       ///<  Message bar of the current main window object (also qsas window)

  QMenuBar* menu_bar(){ return _menu_bar;};

  /// \fn QStatusBar* status_bar()
  /// \brief Function that returns the status bar pointer of the current main window object
  /// \param     None
  /// \exception None
  /// \return    None
  ///
  QStatusBar* status_bar(){return msgBar;};
  QguWLinput *objField;
  QguWLinput *frame_field;
  QComboBox *rep_field;
  bool userSet;

public slots:
  void makeVector();
  void testArray();
  
protected:
  void keyPressEvent(QKeyEvent * e );
  QPushButton *doBtn;
  QPushButton *dismissBtn;
};



# endif // QSAS_SL_H_
