/* Note: some of the icons are copied and modified the internet, namely open, save, print, copy:
 * The Breeze Icon Theme
 */


#include <QToolTip>
#include <QImage>
#include <QPixmap>
#include <QValidator>
#include <QSlider>
#include <QInputDialog>
#include <QSizePolicy>
#include <QFileDialog>
#include <QString>

#include "QFitsMainWindow.h"
#include "QFitsMainView.h"

#include "fits.h"
#include "qtdpuser.h"
#include "dpuser.h"
#include "dpstringlist.h"
#include "QFitsBaseWidget.h"
#include "QFitsCubeSpectrum.h"
#include "QFitsToolBar.h"
#include "QFitsSingleBuffer.h"
#include "QFitsMultiBuffer.h"

#ifdef HAS_VTK
#include "QFitsWidget3D.h"
#endif
#include "QFitsWidgetWiregrid.h"

QFitsToolBar::QFitsToolBar(QFitsMainWindow *parent) :
                                       QWidget(dynamic_cast<QWidget*>(parent)) {
    setFocusPolicy(Qt::StrongFocus);

//    setMinimumSize(QSize(950, 60));
//    setFixedSize(890, 60);
    updateAll = true;

    buttonOpen = new QToolButton(this);
    buttonOpen->setIcon(QIcon(":/open.svg"));
//    buttonOpen->setIcon(buttonOpen->style()->standardIcon(QStyle::SP_DialogOpenButton));
    buttonOpen->setGeometry(QRect(0, 0, 30, 30));
    buttonOpen->setToolTip("Open File");
    connect(buttonOpen, SIGNAL(clicked()),
            parent, SLOT(LoadClicked()));

    buttonReload = new QToolButton(this);
//    buttonReload->setIcon(QPixmap(reload));
    buttonReload->setIcon(QIcon(":/reload.svg"));
    buttonReload->setGeometry(QRect(30, 0, 30, 30));
    buttonReload->setToolTip("Reload current buffer from file");
    connect(buttonReload, SIGNAL(clicked()),
            parent, SLOT(reloadImage()));

    buttonSave = new QToolButton(this);
    buttonSave->setIcon(QIcon(":/save.svg"));
    buttonSave->setGeometry(QRect(60, 0, 30, 30));
    buttonSave->setToolTip("Save file");
    connect(buttonSave, SIGNAL(clicked()),
            parent->main_view, SLOT(saveImage()));

    buttonCopy = new QToolButton(this);
    buttonCopy->setIcon(QIcon(":/copy.svg"));
    buttonCopy->setGeometry(QRect(0, 30, 30, 30));
    buttonCopy->setToolTip("Copy current buffer to clipboard");
    connect(buttonCopy, SIGNAL(clicked()),
            parent, SLOT(copyImage()));

    buttonPrint = new QToolButton(this);
    buttonPrint->setIcon(QIcon(":/print.svg"));
    buttonPrint->setGeometry(QRect(30, 30, 30, 30));
    buttonPrint->setToolTip("Print current buffer");
    connect(buttonPrint, SIGNAL(clicked()),
            parent->main_view, SLOT(printImage()));

    buttonFlip = new QToolButton(this);
//    buttonFlip->setIcon(QPixmap(flip_icon));
    buttonFlip->setIcon(QIcon(":/flip.svg"));
    buttonFlip->setGeometry(QRect(100, 0, 30, 30));
    buttonFlip->setCheckable(true);
    buttonFlip->setToolTip("Flip x-axis");
    connect(buttonFlip, SIGNAL(toggled(bool)),
            this, SLOT(flipped(bool)));

    buttonFlop = new QToolButton(this);
//    buttonFlop->setIcon(QPixmap(flop_icon));
    buttonFlop->setIcon(QIcon(":/flop.svg"));
    buttonFlop->setGeometry(QRect(270, 0, 30, 30));
    buttonFlop->setCheckable(true);
    buttonFlop->setToolTip("Flip y-axis");
    connect(buttonFlop, SIGNAL(toggled(bool)),
            this, SLOT(flopped(bool)));

    buttonRotateCW = new QToolButton(this);
//    buttonRotateCW->setIcon(QPixmap(rotate2_icon));
    buttonRotateCW->setIcon(QIcon(":/rotateCW.svg"));
    buttonRotateCW->setGeometry(QRect(240, 0, 30, 30));
    buttonRotateCW->setToolTip("Rotate clockwise");
    connect(buttonRotateCW, SIGNAL(clicked()),
            this, SLOT(decRotation()));

    buttonRotateCCW = new QToolButton(this);
//    buttonRotateCCW->setIcon(QPixmap(rotate_icon));
    buttonRotateCCW->setIcon(QIcon(":/rotateCCW.svg"));
    buttonRotateCCW->setGeometry(QRect(130, 0, 30, 30));
    buttonRotateCCW->setToolTip("Rotate counter-clockwise");
    connect(buttonRotateCCW, SIGNAL(clicked()),
            this, SLOT(incRotation()));

    comboRotate = new QComboBox(this);
    comboRotate->setEditable(false);
    comboRotate->setGeometry(QRect(160, 0, 80, 30));
    comboRotate->insertItem(0, tr("\x30\xc2\xb0"));
    comboRotate->insertItem(1, tr("\x39\x30\xc2\xb0"));
    comboRotate->insertItem(2, tr("\x31\x38\x30\xc2\xb0"));
    comboRotate->insertItem(3, tr("\x32\x37\x30\xc2\xb0"));
    comboRotate->setToolTip("Select rotation");
    connect(comboRotate, SIGNAL(activated(int)),
            this, SLOT(setRotation(int)));

    buttonZoomIn = new QToolButton(this);
//    buttonZoomIn->setIcon(QPixmap(zoomin_icon));
    buttonZoomIn->setIcon(QIcon(":/zoomin.svg"));
    buttonZoomIn->setGeometry(QRect(255, 30, 30, 30));
    buttonZoomIn->setToolTip("Zoom in");
    buttonZoomIn->setAutoRepeat(true);
    buttonZoomIn->setShortcut(QKeySequence::ZoomIn);
    connect(buttonZoomIn, SIGNAL(clicked()),
            this, SLOT(incZoom()));

    buttonZoomOut = new QToolButton(this);
//    buttonZoomOut->setIcon(QPixmap(zoomout_icon));
    buttonZoomOut->setIcon(QIcon(":/zoomout.svg"));
    buttonZoomOut->setGeometry(QRect(115, 30, 30, 30));
    buttonZoomOut->setToolTip("Zoom out");
    buttonZoomOut->setAutoRepeat(true);
    buttonZoomOut->setShortcut(QKeySequence::ZoomOut);
    connect(buttonZoomOut, SIGNAL(clicked()),
            this, SLOT(decZoom()));

    comboZoom = new QComboBox(this);
    comboZoom->setEditable(false);
    comboZoom->setGeometry(QRect(145, 30, 110, 30));
    comboZoom->setEditable(true);
    comboZoom->insertItem(0,  "Fit window");
    comboZoom->insertItem(1,  "Fit width");
    comboZoom->insertItem(2,  "Fit height");
    comboZoom->insertSeparator(3);
    comboZoom->insertItem(4,  "3.125%");
    comboZoom->insertItem(5,  "6.25%");
    comboZoom->insertItem(6,  "12.5%");
    comboZoom->insertItem(7,  "25%");
    comboZoom->insertItem(8,  "50%");
    comboZoom->insertItem(9,  "100%");
    comboZoom->insertItem(10,  "200%");
    comboZoom->insertItem(11,  "400%");
    comboZoom->insertItem(12,  "800%");
    comboZoom->insertItem(13, "1600%");
    comboZoom->insertItem(14, "3200%");
    comboZoom->setCurrentIndex(9);
    comboZoom->setMaxVisibleItems(20);
    comboZoom->setToolTip("Select zoom factor");
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    connect(comboZoom, SIGNAL(activated(const QString &)),
            this, SLOT(comboZoomTriggered(const QString &)));
#else
    connect(comboZoom, SIGNAL(textActivated(const QString &)),
            this, SLOT(comboZoomTriggered(const QString &)));
#endif /* QT_VERSION */

//#ifdef HAS_VTK
    buttonZoomIn_3Dwire = new QToolButton(this);
    buttonZoomIn_3Dwire->setIcon(QIcon(":/zoomin.svg"));
    buttonZoomIn_3Dwire->setGeometry(QRect(255, 30, 30, 30));
    buttonZoomIn_3Dwire->setToolTip("Zoom in");
    connect(buttonZoomIn_3Dwire, SIGNAL(clicked()),
            this, SLOT(incZoom_3Dwire()));

    buttonZoomOut_3Dwire = new QToolButton(this);
    buttonZoomOut_3Dwire->setIcon(QIcon(":/zoomout.svg"));
    buttonZoomOut_3Dwire->setGeometry(QRect(115, 30, 30, 30));
    buttonZoomOut_3Dwire->setToolTip("Zoom out");
    connect(buttonZoomOut_3Dwire, SIGNAL(clicked()),
            this, SLOT(decZoom_3Dwire()));

    comboZoom_3Dwire = new QComboBox(this);
    comboZoom_3Dwire->setEditable(false);
    comboZoom_3Dwire->setGeometry(QRect(145, 30, 110, 30));
    comboZoom_3Dwire->setEditable(true);
    comboZoom_3Dwire->insertItem(0,  "100%");
    comboZoom_3Dwire->insertItem(1,  "200%");
    comboZoom_3Dwire->insertItem(2,  "400%");
    comboZoom_3Dwire->insertItem(3,  "800%");
    comboZoom_3Dwire->insertItem(4,  "1600%");
    comboZoom_3Dwire->insertItem(5,  "3200%");
    comboZoom_3Dwire->setCurrentIndex(1);
    comboZoom_3Dwire->setMaxVisibleItems(20);
    comboZoom_3Dwire->setToolTip("Select zoom factor");
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    connect(comboZoom_3Dwire, SIGNAL(activated(const QString &)),
            this, SLOT(comboZoomTriggered(const QString &)));
#else
    connect(comboZoom_3Dwire, SIGNAL(textActivated(const QString &)),
            this, SLOT(comboZoomTriggered(const QString &)));
#endif /* QT_VERSION */

//#endif

    cubeMode = new QComboBox(this);
    cubeMode->setEditable(false);
    cubeMode->setGeometry(QRect(610, 0, 100, 30));
    cubeMode->clear();
    cubeMode->insertItem(0, "Single");
    cubeMode->insertItem(1, "Average");
    cubeMode->insertItem(2, "Median");
    cubeMode->insertItem(3, "Linemap");
    cubeMode->setToolTip("Cube display mode");
    connect(cubeMode, SIGNAL(activated(int)),
            parent, SLOT(updateCubeMode(int)));

    movieButton = new QToolButton(this);
//    movieButton->setIcon(QPixmap(movieplay));
    movieButton->setIcon(QIcon(":/play.svg"));
    movieButton->setGeometry(QRect(680, 30, 30, 30));
    movieButton->setCheckable(true);
    movieButton->setToolTip("Play / Stop movie");
    connect(movieButton, SIGNAL(toggled(bool)),
            this, SLOT(movieButtonToggled(bool)));
    connect(movieButton, SIGNAL(toggled(bool)),
            parent->main_view, SLOT(enableMovie(bool)));

    movieSlider = new QSlider(this);
    movieSlider->setGeometry(QRect(520, 30, 160, 30));
    movieSlider->setMinimum(1);
    movieSlider->setOrientation(Qt::Horizontal);
//    movieSlider->setTickPosition(QSlider::TicksBelow);
//    movieSlider->setTickInterval(10);

    cubeImageSlice = new QSpinBox(this);
    cubeImageSlice->setGeometry(QRect(520, 0, 90, 30));
    cubeImageSlice->setMinimum(1);
    cubeImageSlice->setWrapping(true);
    cubeImageSlice->setMaximum(99999);
    cubeImageSlice->setValue(1);
    cubeImageSlice->setToolTip("Cube center");
    connect(cubeImageSlice, SIGNAL( valueChanged(int) ),
            movieSlider, SLOT( setValue(int) ) );
    connect(movieSlider, SIGNAL( sliderMoved(int) ),
            cubeImageSlice, SLOT( setValue(int) ) );
    connect(parent->spectrum, SIGNAL(sliceSelected(int)),
            cubeImageSlice, SLOT(setValue(int)));

    imageScaleRange = new QComboBox(this);
    imageScaleRange->setEditable(false);
    imageScaleRange->setGeometry(QRect(310, 30, 100, 30));
    imageScaleRange->setCurrentIndex(settings.defaultLimits);
    imageScaleRange->insertItem(0, "minmax");
    imageScaleRange->insertItem(1, "99.9%");
    imageScaleRange->insertItem(2, "99.5%");
    imageScaleRange->insertItem(3, "99%");
    imageScaleRange->insertItem(4, "98%");
    imageScaleRange->insertItem(5, "95%");
    imageScaleRange->insertItem(6, "manual");
    imageScaleRange->setToolTip("Select scale range");
    connect(imageScaleRange, SIGNAL(activated(int)),
            this, SLOT(setImageLimitsScaleRange(int)));

    imageScaleMethod = new ActionComboBox(this);
    imageScaleMethod->setGeometry(QRect(410, 30, 100, 30));
    imageScaleMethod->setToolTip("Select scale method");
    imageScaleMethod->setActions(parent->scalingMethods);

    imageMinValue = new QLineEdit(this);
    imageMinValue->setGeometry(QRect(310, 0, 100, 30));
    imageMinValue->setToolTip("Image scale min value");
    connect(imageMinValue, SIGNAL(returnPressed()),
            this, SLOT(setImageLimitsManual()));

    imageMaxValue = new QLineEdit(this);
    imageMaxValue->setGeometry(QRect(410, 0, 100, 30));
    imageMaxValue->setToolTip("Image scale max value");
    connect(imageMaxValue, SIGNAL(returnPressed()),
            this, SLOT(setImageLimitsManual()));

    specPhysMinYValue = new QLineEdit(this);
    specPhysMinYValue->setGeometry(QRect(310, 0, 100, 30));
    specPhysMinYValue->setToolTip("Spectrum min value");
    connect(specPhysMinYValue, SIGNAL(returnPressed()),
            this, SLOT(setSpecYLimitsManual()));

    specPhysMaxYValue = new QLineEdit(this);
    specPhysMaxYValue->setGeometry(QRect(410, 0, 100, 30));
    specPhysMaxYValue->setToolTip("Spectrum max value");
    connect(specPhysMaxYValue, SIGNAL(returnPressed()),
            this, SLOT(setSpecYLimitsManual()));

    setTabOrder(specPhysMinYValue, specPhysMaxYValue);
//    setTabOrder(specPhysMaxYValue, specPhysMinXValue);

    imredPlus = new QToolButton(this);
//    imredPlus->setIcon(QPixmap(plus_xpm));
    imredPlus->setIcon(QIcon(":/plus.svg"));
    imredPlus->setGeometry(QRect(710, 0, 30, 30));
    imredPlus->setToolTip("Add buffer");
    imredPlus->setPopupMode(QToolButton::InstantPopup);
    plusPopupMenu = new QMenu(imredPlus);
    imredPlus->setMenu(plusPopupMenu);
    connect(plusPopupMenu, SIGNAL(aboutToShow()), this, SLOT(createPlusPopupMenu()));
    connect(plusPopupMenu, SIGNAL(triggered(QAction*)), this, SLOT(doArithmetics(QAction*)));

    imredMinus = new QToolButton(this);
//    imredMinus->setIcon(QPixmap(minus_xpm));
    imredMinus->setIcon(QIcon(":/minus.svg"));
    imredMinus->setGeometry(QRect(740, 0, 30, 30));
    imredMinus->setToolTip("Subtract buffer");
    imredMinus->setPopupMode(QToolButton::InstantPopup);
    minusPopupMenu = new QMenu(imredMinus);
    imredMinus->setMenu(minusPopupMenu);
    connect(minusPopupMenu, SIGNAL(aboutToShow()), this, SLOT(createMinusPopupMenu()));
    connect(minusPopupMenu, SIGNAL(triggered(QAction*)), this, SLOT(doArithmetics(QAction*)));

    imredMul = new QToolButton(this);
//    imredMul->setIcon(QPixmap(multiply));
    imredMul->setIcon(QIcon(":/multiply.svg"));
    imredMul->setGeometry(QRect(770, 0, 30, 30));
    imredMul->setToolTip("Multiply buffer");
    imredMul->setPopupMode(QToolButton::InstantPopup);
    mulPopupMenu = new QMenu(imredMul);
    imredMul->setMenu(mulPopupMenu);
    connect(mulPopupMenu, SIGNAL(aboutToShow()), this, SLOT(createMulPopupMenu()));
    connect(mulPopupMenu, SIGNAL(triggered(QAction*)), this, SLOT(doArithmetics(QAction*)));

    imredDiv = new QToolButton(this);
//    imredDiv->setIcon(QPixmap(divide));
    imredDiv->setIcon(QIcon(":/divide.svg"));
    imredDiv->setGeometry(QRect(800, 0, 30, 30));
    imredDiv->setToolTip("Divide buffer");
    imredDiv->setPopupMode(QToolButton::InstantPopup);
    divPopupMenu = new QMenu(imredDiv);
    imredDiv->setMenu(divPopupMenu);
    connect(divPopupMenu, SIGNAL(aboutToShow()), this, SLOT(createDivPopupMenu()));
    connect(divPopupMenu, SIGNAL(triggered(QAction*)), this, SLOT(doArithmetics(QAction*)));

    imredPow = new QToolButton(this);
//    imredPow->setIcon(QPixmap(power));
    imredPow->setIcon(QIcon(":/power.svg"));
    imredPow->setGeometry(QRect(830, 0, 30, 30));
    imredPow->setToolTip("Raise buffer to power");
    imredPow->setPopupMode(QToolButton::InstantPopup);
    powPopupMenu = new QMenu(imredPow);
    imredPow->setMenu(powPopupMenu);
    connect(powPopupMenu, SIGNAL(aboutToShow()), this, SLOT(createPowPopupMenu()));
    connect(powPopupMenu, SIGNAL(triggered(QAction*)), this, SLOT(doArithmetics(QAction*)));

    imredConv = new QToolButton(this);
//    imredConv->setIcon(QPixmap(convolve));
    imredConv->setIcon(QIcon(":/convolve.svg"));
    imredConv->setGeometry(QRect(860, 0, 30, 30));
    imredConv->setToolTip("Convolve buffer");
    imredConv->setPopupMode(QToolButton::InstantPopup);
    convPopupMenu = new QMenu(imredConv);
    imredConv->setMenu(convPopupMenu);
    connect(convPopupMenu, SIGNAL(aboutToShow()), this, SLOT(createConvPopupMenu()));
    connect(convPopupMenu, SIGNAL(triggered(QAction*)), this, SLOT(doArithmetics(QAction*)));

    limitZCheckBox = new QCheckBox(this);
    limitZCheckBox->setText(QStringLiteral("Limit Z:"));
    limitZCheckBox->adjustSize();
    limitZCheckBox->setGeometry(520, 0, limitZCheckBox->width(), 30);
    limitZCheckBox->setChecked(false);
    limitSpinboxZ = new QSpinBox(this);
    limitSpinboxZ->setSuffix("px");
    limitSpinboxZ->setGeometry(520 + limitZCheckBox->width(), 0, 160-limitZCheckBox->width(), 30);
    limitSpinboxZ->setValue(50);
    limitSpinboxZ->setSingleStep(2);
    limitSpinboxZ->setEnabled(false);
    limitSliderZ = new QSlider(Qt::Horizontal, this);
    limitSliderZ->setGeometry(520,30, 160, 30);
    limitSliderZ->setMinimum(1);
    limitSliderZ->setMaximum(1024);
    limitSliderZ->setValue(512);
    limitSliderZ->setEnabled(false);
    connect(limitZCheckBox, SIGNAL(toggled(bool)), limitSpinboxZ, SLOT(setEnabled(bool)));
    connect(limitZCheckBox, SIGNAL(toggled(bool)), limitSliderZ, SLOT(setEnabled(bool)));

    alphaMultiplierLabel = new QLabel(QStringLiteral("Alpha:"), this);
    alphaMultiplierLabel->adjustSize();
    alphaMultiplierLabel->setGeometry(QRect(690, 0, alphaMultiplierLabel->width(), 30));
    alphaMultiplierSlider = new QSlider(Qt::Horizontal, this);
    alphaMultiplierSlider->setGeometry(QRect(690 + alphaMultiplierLabel->width(), 0, 190-alphaMultiplierLabel->width(), 30));
    alphaMultiplierSlider->setToolTip("Alpha multiplier");
    alphaMultiplierSlider->setMinimum(0);
    alphaMultiplierSlider->setMaximum(139);
    alphaMultiplierSlider->setValue(50);
    alphaMultiplierSlider->setEnabled(true);
    drawSliceFramesCheckBox = new QCheckBox(this);
    drawSliceFramesCheckBox->setText(QStringLiteral("Draw slice frames"));
    drawSliceFramesCheckBox->setChecked(false);
    drawSliceFramesCheckBox->setGeometry(QRect(690, 30, 190, 30));

    showControls();
}

void QFitsToolBar::keyPressEvent( QKeyEvent *e ) {
    fitsMainWindow->main_view->keyPressEvent(e);
}

void QFitsToolBar::resizeEvent(QResizeEvent *e) {
    int h = e->size().height() / 2;
    int x = 0;

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
		int cw = imageScaleMethod->fontMetrics().boundingRect("square root").width() * 1.7;
#else
    int cw = imageScaleMethod->fontMetrics().horizontalAdvance("square root") * 1.7;
#endif /* QT_VERSION */

    // upper row
    buttonOpen->setGeometry(QRect(x, 0, h, h)); x += h;
    buttonReload->setGeometry(QRect(x, 0, h, h)); x += h;
    buttonSave->setGeometry(QRect(x, 0, h, h)); x += h + h/2;

    buttonFlip->setGeometry(QRect(x, 0, h, h)); x += h;
    buttonRotateCCW->setGeometry(QRect(x, 0, h, h)); x += h;
    comboRotate->setGeometry(QRect(x, 0, 3*h, h)); x += 3*h;
    buttonRotateCW->setGeometry(QRect(x, 0, h, h)); x += h;
    buttonFlop->setGeometry(QRect(x, 0, h, h)); x += h + h/2;

    imageMinValue->setGeometry(QRect(x, 0, cw, h));
    specPhysMinYValue->setGeometry(QRect(x, 0, cw, h)); x += cw;
    imageMaxValue->setGeometry(QRect(x, 0, cw, h));
    specPhysMaxYValue->setGeometry(QRect(x, 0, cw, h)); x += cw + h/2;

    cubeImageSlice->setGeometry(QRect(x, 0, 3*h, h));
    limitZCheckBox->setGeometry(x, 0, limitZCheckBox->width(), h);
    limitSpinboxZ->setGeometry(x + limitZCheckBox->width(), 0, 6*h-limitZCheckBox->width(), h); x += 3*h;
    cubeMode->setGeometry(QRect(x, 0, 3*h, h)); x += 3*h + h/2;
    alphaMultiplierLabel->setGeometry(QRect(x, 0, alphaMultiplierLabel->width(), h));
    alphaMultiplierSlider->setGeometry(QRect(x + alphaMultiplierLabel->width(), 0, 6*h-alphaMultiplierLabel->width(), h));

    imredPlus->setGeometry(QRect(x, 0, h, h)); x += h;
    imredMinus->setGeometry(QRect(x, 0, h, h)); x += h;
    imredMul->setGeometry(QRect(x, 0, h, h)); x += h;
    imredDiv->setGeometry(QRect(x, 0, h, h)); x += h;
    imredPow->setGeometry(QRect(x, 0, h, h)); x += h;
    imredConv->setGeometry(QRect(x, 0, h, h));

    buttonZoomIn->setGeometry(QRect(255, 30, 30, 30));

    // lower row
    x = 0;
    buttonCopy->setGeometry(QRect(x, h, h, h)); x += h;
    buttonPrint->setGeometry(QRect(h, h, h, h)); x += h;

    x += 2*h;
    buttonZoomOut->setGeometry(QRect(x, h, h, h));
    buttonZoomOut_3Dwire->setGeometry(QRect(x, h, h, h)); x += h;
    comboZoom->setGeometry(QRect(x, h, 4*h, h));
    comboZoom_3Dwire->setGeometry(QRect(x, h, 4*h, h)); x += 4*h;
    buttonZoomIn->setGeometry(QRect(x, h, h, h));
    buttonZoomIn_3Dwire->setGeometry(QRect(x, h, h, h)); x += h + h;

    imageScaleRange->setGeometry(QRect(x, h, cw, h)); x += cw;
    imageScaleMethod->setGeometry(QRect(x, h, cw, h)); x += cw + h/2;

    movieSlider->setGeometry(QRect(x, h, 5*h, h)); x += 5*h;
    movieButton->setGeometry(QRect(x, h, h, h)); x += h/2;
    drawSliceFramesCheckBox->setGeometry(QRect(x, h, 6*h, h));

// set Icon Size of all ToolButtons
    QSize iconSize = QSize(h/1.8, h/1.8);
//    QFont theFont = imageMinValue->createStandardContextMenu()->font();
//    theFont.setPixelSize(iconSize.height()/2);
    QObjectList buttons = children();
    for (int i = 0; i < buttons.count(); i++) {
        QToolButton *button = dynamic_cast<QToolButton*>(buttons.at(i));
        if (button != NULL) {
            button->setIconSize(iconSize);
        } else {
//            QWidget *widget = dynamic_cast<QWidget*>(buttons.at(i));
//            if (widget != NULL) {
//                widget->setFont(theFont);
//                widget->update();
//            }
        }
    }
}

QFitsSingleBuffer* QFitsToolBar::getMyBuffer() {
    if (fitsMainWindow != NULL) {
        QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
        QFitsBaseBuffer   *bb = fitsMainWindow->getCurrentBuffer();
        QFitsMultiBuffer  *mb = dynamic_cast<QFitsMultiBuffer*>(bb);
        if ((sb == NULL) &&
            (mb != NULL) &&
             mb->hasCubeSpecHomogenSB())
        {
            sb = mb->getFirstImageBuffer();
        }
        return sb;
    }
    return NULL;
}

void QFitsToolBar::comboZoomTriggered(const QString&) {
    fitsMainWindow->zoomCorr_ComboZoomTriggered = true;

    QFitsBaseBuffer *bb = fitsMainWindow->getCurrentBuffer();
    if (bb != NULL) {
        FitZoom fz;
        double zoomValue = getZoomTextCombo(&fz);
        setZoomTextCombo(zoomValue);
        bb->zoomTextChanged(zoomValue, fz);
    }
}

QComboBox* QFitsToolBar::getActualZoomCombo() {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    bool show3dzoom = FALSE;
    if (sb != NULL) {
#ifdef HAS_VTK
        if (dynamic_cast<QFitsWidget3D*>(sb->getState()) != NULL) {
            show3dzoom = TRUE;
        }
#endif
        if (dynamic_cast<QFitsWidgetWiregrid*>(sb->getState()) != NULL) {
            show3dzoom = TRUE;
        }
    }
    if (show3dzoom) {
        return comboZoom_3Dwire;
    }
    return comboZoom;
}

double QFitsToolBar::getZoomTextCombo(FitZoom *fitZoom) {
    double ret = 0.;
    *fitZoom = FitZoomNone;
    QString zoomLevelString = getActualZoomCombo()->currentText();
    if (zoomLevelString == "Fit window") {
        *fitZoom = FitZoomWindow;
    } else if (zoomLevelString == "Fit width") {
        *fitZoom = FitZoomWidth;
    } else if (zoomLevelString == "Fit height") {
        *fitZoom = FitZoomHeight;
    } else {
        QString tmpStr = zoomLevelString;
        if (tmpStr.right(1) == "%") {
            tmpStr.truncate(tmpStr.length() - 1);
        }
        ret = tmpStr.toDouble() / 100.;
    }
    return ret;
}

void QFitsToolBar::setZoomValue(double zoomValue) {
    QFitsBaseBuffer *bb = fitsMainWindow->getCurrentBuffer();
    if ((bb != NULL)/* &&
        (zoomValue != bb->getZoom())*/)
    {
        setZoomTextCombo(zoomValue);
        FitZoom fz = FitZoomNone;
        bb->zoomTextChanged(zoomValue, fz);
    }
}

void QFitsToolBar::setZoomTextCombo(double zoomFactor) {
    zoomFactor *= 100.;
    if (zoomFactor > 40.) {
        getActualZoomCombo()->setEditText(QString::number(zoomFactor) + "%");
    } else {
        getActualZoomCombo()->setEditText(QString::number(zoomFactor, 'g', 3) + "%");
    }
}

void QFitsToolBar::showControls() {
    if (fitsMainWindow != NULL) {
//        QFitsSingleBuffer *sb = getMyBuffer();
        QFitsBaseBuffer *bb = fitsMainWindow->getCurrentBuffer();
        if (bb != NULL) {
            BufferAppearance bufAppearance = bb->getAppearance();
            showControlsZoom(bb->getViewMode());
            showControlsOrientation(bufAppearance.showToolbarOrientation);
            showControlsScaling(bufAppearance.showToolbarScaling);
            showControlsMovie(bufAppearance.showToolbarMovie);
            showControlsArithmetics(bufAppearance.showToolbarArithmetics);
            showControlsCube(bufAppearance.showToolbarCube);
        }
    }
    updateValues();
}

void QFitsToolBar::enableControlsView1D(bool enable) {
    specPhysMinYValue->setEnabled(enable);
    specPhysMaxYValue->setEnabled(enable);

    if (!enable) {
        updateAll = false;
        specPhysMinYValue->setText("");
        specPhysMaxYValue->setText("");
        updateAll = true;
    }
}

void QFitsToolBar::enableControlsView2D(bool enable) {
    imageMinValue->setEnabled(enable);
    imageMinValue->setEnabled(enable);
    imageScaleRange->setEnabled(enable);
    imageScaleMethod->setEnabled(enable);

    if (!enable) {
        updateAll = false;
        imageMinValue->setText("");
        imageMaxValue->setText("");
        updateAll = true;
    }
}

void QFitsToolBar::enableControlsArithmetic(bool enable) {
    imredPlus->setEnabled(enable);
    imredMinus->setEnabled(enable);
    imredMul->setEnabled(enable);
    imredDiv->setEnabled(enable);
    imredPow->setEnabled(enable);
    imredConv->setEnabled(enable);
}

void QFitsToolBar::setPaletteControls(QPalette &pal) {
    specPhysMinYValue->setPalette(pal);
    specPhysMaxYValue->setPalette(pal);
    imageMinValue->setPalette(pal);
    imageMaxValue->setPalette(pal);
}

void QFitsToolBar::updateImageMinMax(QFitsBaseBuffer *bb) {
    QString min,
            max;

    if (bb != NULL) {
        min = QString::number(bb->getImageMinValue(), 'g', 4);
        max = QString::number(bb->getImageMaxValue(), 'g', 4);
    }

    updateAll = false;
    imageMinValue->setText(min);
    imageMaxValue->setText(max);
    updateAll = true;
}

void QFitsToolBar::updateSpecMinMaxY(QFitsBaseBuffer *bb) {
    QString min,
            max;

    if (bb != NULL) {
        min = QString::number(bb->getSpecPhysMinY(), 'g', 4);
        max = QString::number(bb->getSpecPhysMaxY(), 'g', 4);
    }

    updateAll = false;
    specPhysMinYValue->setText(min);
    specPhysMaxYValue->setText(max);
    updateAll = true;
}


void QFitsToolBar::showControlsZoom(dpViewMode viewmode) {
    int actcounter;
    switch (viewmode) {
        case ViewImage:
        case ViewContour:
            buttonZoomIn_3Dwire->hide();
            buttonZoomOut_3Dwire->hide();
            comboZoom_3Dwire->hide();
            if (fitsMainWindow->getActualSB() != NULL) {
                if (fitsMainWindow->getActualSB()->getHasSpectrum()) {
                    buttonZoomIn->hide();
                    buttonZoomOut->hide();
                    comboZoom->hide();
                    fitsMainWindow->zoom->setEnabled(false);
                    for (actcounter = 0; actcounter <= 8; actcounter++) {
                        fitsMainWindow->zoom->actions().at(actcounter)->setVisible(false);
                    }
                } else {
                    buttonZoomIn->show();
                    buttonZoomOut->show();
                    comboZoom->show();
                    fitsMainWindow->zoom->setEnabled(true);
                    for (actcounter = 0; actcounter <= 8; actcounter++) {
                        fitsMainWindow->zoom->actions().at(actcounter)->setVisible(true);
                    }
                }
            }
        break;
        case ViewTable:
            buttonZoomIn_3Dwire->hide();
            buttonZoomOut_3Dwire->hide();
            comboZoom_3Dwire->hide();
            buttonZoomIn->hide();
            buttonZoomOut->hide();
            comboZoom->hide();
            fitsMainWindow->zoom->setEnabled(FALSE);
        break;
//#ifdef HAS_VTK
        case View3D:
//#endif
        case ViewWiregrid:
            buttonZoomIn_3Dwire->show();
            buttonZoomOut_3Dwire->show();
            comboZoom_3Dwire->show();
            buttonZoomIn->hide();
            buttonZoomOut->hide();
            comboZoom->hide();
            fitsMainWindow->zoom->setEnabled(TRUE);
            for (actcounter = 0; actcounter <= 8; actcounter++) {
                fitsMainWindow->zoom->actions().at(actcounter)->setVisible(FALSE);
            }
        break;
        default:
        break;
    }
}

void QFitsToolBar::showControlsOrientation(bool show) {
    if (show) {
        buttonFlip->show();
        buttonFlop->show();
        buttonRotateCW->show();
        buttonRotateCCW->show();
        comboRotate->show();
    } else {
        buttonFlip->hide();
        buttonFlop->hide();
        buttonRotateCW->hide();
        buttonRotateCCW->hide();
        comboRotate->hide();
    }
}

void QFitsToolBar::showControlsScaling(bool show) {
    if (show) {
        QFitsSingleBuffer *sb = getMyBuffer();
        if ((sb != NULL) && (sb->Naxis(0) == 1)) {
            // 1D
            imageMinValue->hide();
            imageMaxValue->hide();
            imageScaleRange->hide();
            imageScaleMethod->hide();

            specPhysMinYValue->show();
            specPhysMaxYValue->show();
        } else {
            // 2D
            imageMinValue->show();
            imageMaxValue->show();
            imageScaleRange->show();
            imageScaleMethod->show();

            specPhysMinYValue->hide();
            specPhysMaxYValue->hide();
        }
    } else {
        imageMinValue->hide();
        imageMaxValue->hide();
        imageScaleRange->hide();
        imageScaleMethod->hide();

        specPhysMinYValue->hide();
        specPhysMaxYValue->hide();
    }
}

void QFitsToolBar::showControlsMovie(bool show) {
    if (show) {
        movieButton->show();
        movieSlider->show();
        cubeImageSlice->show();
        cubeMode->show();
    } else {
        movieButton->hide();
        movieSlider->hide();
        cubeImageSlice->hide();
        cubeMode->hide();
    }
}

void QFitsToolBar::showControlsArithmetics(bool show) {
    if (show) {
        imredPlus->show();
        imredMinus->show();
        imredMul->show();
        imredDiv->show();
        imredPow->show();
        imredConv->show();
    } else {
        imredPlus->hide();
        imredMinus->hide();
        imredMul->hide();
        imredDiv->hide();
        imredPow->hide();
        imredConv->hide();
    }
}

void QFitsToolBar::showControlsCube(bool show) {
    if (show) {
        alphaMultiplierSlider->show();
        alphaMultiplierLabel->show();
        drawSliceFramesCheckBox->show();
        limitZCheckBox->show();
        limitSpinboxZ->show();
        limitSliderZ->show();
    } else {
        alphaMultiplierSlider->hide();
        alphaMultiplierLabel->hide();
        drawSliceFramesCheckBox->hide();
        limitZCheckBox->hide();
        limitSpinboxZ->hide();
        limitSliderZ->hide();
    }
//        QFitsSingleBuffer *sb = getMyBuffer();
//        if ((sb != NULL) && (
//#ifdef HAS_VTK
//             (sb->getViewMode() == View3D) ||
//#endif
//             (sb->getViewMode() == ViewWiregrid)))
//        {
//            cubeMode->hide();
//#ifdef HAS_VTK
//#endif
//        } else {
//            cubeMode->show();
//#ifdef HAS_VTK
//#endif
//        }
//    } else {
//        cubeMode->hide();
//#ifdef HAS_VTK
//#endif
//    }
}

void QFitsToolBar::incZoom() {
    QFitsBaseBuffer *bb = fitsMainWindow->getCurrentBuffer();
    if (bb != NULL) {
        bb->incZoom();
        setZoomValue(bb->getZoomFactor());
    }
}

void QFitsToolBar::decZoom() {
    QFitsBaseBuffer *bb = fitsMainWindow->getCurrentBuffer();
    if (bb != NULL) {
        bb->decZoom();
        setZoomValue(bb->getZoomFactor());
    }
}

//#ifdef HAS_VTK
void QFitsToolBar::incZoom_3Dwire() {
    QFitsBaseBuffer *bb = fitsMainWindow->getCurrentBuffer();
    if (bb != NULL) {
        bb->incZoom_3Dwire();
        setZoomValue(bb->getZoomFactor_3Dwire());
    }
}

void QFitsToolBar::decZoom_3Dwire() {
    QFitsBaseBuffer *bb = fitsMainWindow->getCurrentBuffer();
    if ((bb != NULL) &&
        (bb->getZoomFactor_3Dwire() > 1.))
    {
        bb->decZoom_3Dwire();
        setZoomValue(bb->getZoomFactor_3Dwire());
    }
}
//#endif

void QFitsToolBar::incRotation() {
    int newRot = comboRotate->currentIndex() + 1;
    if (newRot > 3) {
        newRot -= 4;
    }
    setRotation(newRot);
}

void QFitsToolBar::decRotation() {
    int newRot = comboRotate->currentIndex() - 1;
    if (newRot < 0) {
        newRot += 4;
    }
    setRotation(newRot);
}

void QFitsToolBar::setRotation(int newvalue) {
    QFitsBaseBuffer *bb = fitsMainWindow->getCurrentBuffer();
    if ((bb != NULL) &&
        (bb->getRotation() == newvalue * 90))
    {
        return;
    }
    bool fy = bb->getFlipX(),
         fx = bb->getFlipY();
    bb->setOrientation(newvalue * 90, fx, fy);

    comboRotate->setCurrentIndex(newvalue);
    buttonFlip->setChecked(fx);
    buttonFlop->setChecked(fy);

    emit orientationChanged();
}

void QFitsToolBar::flipped(bool checked) {
    QFitsBaseBuffer *bb = fitsMainWindow->getCurrentBuffer();
    if (bb != NULL) {
        if (checked == bb->getFlipX()) return;
    }
    bb->setOrientation(bb->getRotation(), checked, bb->getFlipY());

    emit orientationChanged();
}

void QFitsToolBar::flopped(bool checked) {
    QFitsBaseBuffer *bb = fitsMainWindow->getCurrentBuffer();
    if (bb != NULL) {
        if (checked == bb->getFlipY()) return;
    }
    bb->setOrientation(bb->getRotation(), bb->getFlipX(), checked);

    emit orientationChanged();
}

void QFitsToolBar::setOrientation() {
    emit orientationChanged();
}

void QFitsToolBar::updateValues() {
    QFitsSingleBuffer *sb = getMyBuffer();
    if (sb != NULL) {
        QReadLocker locker(&buffersLock);
        if (sb->Naxis(0) == 1) {
        } else if (sb->Naxis(0) == 2) {
        } else if (sb->Naxis(0) == 3) {
//#ifdef HAS_VTK
            if (sb->getViewMode() == View3D) {
//@                updateZminmax();
            } else
//#endif
            {
                int c = (int)(sb->getCubeCenter(QFV::Wavelength) + 0.5);
                if (cubeImageSlice->minimum() != 1) {
                    cubeImageSlice->setMinimum(1);
                }
                if (cubeImageSlice->maximum() != sb->Naxis(3)) {
                    cubeImageSlice->setMaximum(sb->Naxis(3));
                }
                if (movieSlider->maximum() != sb->Naxis(3)) {
                    movieSlider->setMaximum(sb->Naxis(3));
                }
                cubeMode->setCurrentIndex(sb->getCubeMode());
                if ((sb->getCubeMode() == DisplayCubeSingle) ||
                    (sb->getCubeMode() == DisplayCubeLinemap))
                {
                    cubeImageSlice->setEnabled(true);
                    movieSlider->setEnabled(true);
                    movieButton->setEnabled(true);
                } else {
                    cubeImageSlice->setEnabled(false);
                    movieSlider->setEnabled(false);
                    movieButton->setEnabled(false);
                }
                if (c > 0)
                    if (cubeImageSlice->value() != c) {
                        cubeImageSlice->setValue(c);
                    }
                    if (movieSlider->value() != c) {
                        movieSlider->setValue(c);
                    }
                }
        }
        comboRotate->setCurrentIndex(sb->getRotation() / 90);
        buttonFlip->setChecked(sb->getFlipX());
        buttonFlop->setChecked(sb->getFlipY());
        imageScaleRange->setCurrentIndex(sb->getImageScaleRange());
        imageScaleMethod->setCurrentIndex(sb->getImageScalingMethod());
        if (fitsMainWindow != NULL) {
            fitsMainWindow->updateMenuScaling(sb->getImageScalingMethod());
        }
    }
}

void QFitsToolBar::movieButtonToggled(bool toggled) {
    if (toggled) {
//        movieButton->setIcon(QPixmap(moviepause));
        movieButton->setIcon(QIcon(":/pause.svg"));
    } else {
//        movieButton->setIcon(QPixmap(movieplay));
        movieButton->setIcon(QIcon(":/play.svg"));
    }
}

void QFitsToolBar::setImageLimitsManual() {
    if (updateAll) {
        QFitsBaseBuffer *sb = getMyBuffer();
        if (sb != NULL) {
            sb->setImageMinValue(imageMinValue->text().toDouble());
            sb->setImageMaxValue(imageMaxValue->text().toDouble());
            sb->setImageScaleRange(ScaleManual);
            fitsMainWindow->updateScaling();
        }
    }
}

void QFitsToolBar::setSpecYLimitsManual() {
    if (updateAll) {
        QFitsBaseBuffer *sb = getMyBuffer();
        if (sb != NULL) {
            sb->setSpecPhysRangeY(specPhysMinYValue->text().toDouble(),
                                  specPhysMaxYValue->text().toDouble());
            ((QFitsView1D*)(sb->getState()->getView()))->setAutoScale(false);
            sb->setYRange();
        }
    }
}

void QFitsToolBar::setImageLimitsScaleRange(int selected) {
    if (updateAll) {
        QFitsBaseBuffer *bb = fitsMainWindow->getCurrentBuffer();
        if (bb != NULL) {
            bb->setImageScaleRange((dpScaleMode)selected);
            fitsMainWindow->updateScaling();
        }
    }
}

void QFitsToolBar::createArithPopupMenu(int arithmetics, QMenu *arithPopupMenu) {
    requestedArithmetics = arithmetics;
    QAction *action = NULL;

    arithPopupMenu->clear();

    QFitsMainWindow *p = static_cast<QFitsMainWindow*>(parent());
    for (auto var:p->main_view->bufferMap) {
        if (var.second->getDpData()->type == typeFits) {
            action = new QAction(QString(var.first.c_str()), this);
            action->setData(QString(var.first.c_str()));
            arithPopupMenu->addAction(action);
        }
    }

    arithPopupMenu->addSeparator();

    if (requestedArithmetics < 6) {
        action = new QAction("Number...", this);
        action->setData("");
        arithPopupMenu->addAction(action);
    }

    action = new QAction("File...", this);
    action->setData(" ");
    arithPopupMenu->addAction(action);
}

void QFitsToolBar::createPlusPopupMenu() {
    createArithPopupMenu(1, plusPopupMenu);
}

void QFitsToolBar::createMinusPopupMenu() {
    createArithPopupMenu(2, minusPopupMenu);
}

void QFitsToolBar::createMulPopupMenu() {
    createArithPopupMenu(3, mulPopupMenu);
}

void QFitsToolBar::createDivPopupMenu() {
    createArithPopupMenu(4, divPopupMenu);
}

void QFitsToolBar::createPowPopupMenu() {
    createArithPopupMenu(5, powPopupMenu);
}

void QFitsToolBar::createConvPopupMenu() {
    createArithPopupMenu(6, convPopupMenu);
}

void QFitsToolBar::doArithmetics(QAction *action) {
    QString id = action->data().toString();
    static double value = 0.0;
    bool ok = true;
    QString cmd, operand;

    cmd = fitsMainWindow->getCurrentBufferIndex().c_str();

    if (id == "") {
        // get user input as a number
        value = QInputDialog::getDouble(this, "QFitsView Arithmetics",
                                        "Enter a number:", value,
                                        7-1e30, 1e30, 20, &ok);
        if (ok) operand = QString::number(value);
    } else if (id == " ") {
        // get user input as filename
        operand = QFileDialog::getOpenFileName(this, "QFitsView - Open File", settings.lastOpenPath,
                               "Fits files (*.fits *.fts *.fits.gz *.fts.gz);;"
                               "All files (*)");
        if (!operand.isNull()) {
            QDir dir;
            settings.lastOpenPath = dir.filePath(operand);
            operand = "'" + operand + "'";
        }
    } else {
        operand = id;
    }

    if (!operand.isNull()) {
        switch (requestedArithmetics) {
            case 1:
                cmd += " += ";
                break;
            case 2:
                cmd += " -= ";
                break;
            case 3:
                cmd += " *= ";
                break;
            case 4:
                cmd += " /= ";
                break;
            case 5:
                cmd += " = " + QString(fitsMainWindow->getCurrentBufferIndex().c_str()) +
                       " ^ ";
                break;
            case 6:
                 cmd += " = convolve(" +
                        QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + ", ";
            default:
                break;
        }
        if (id != "") {
            QFitsMainWindow *p = static_cast<QFitsMainWindow*>(parent());
            cmd += "resize(" + operand + ", "
                +  QString::number(p->main_view->bufferMap[fitsMainWindow->getCurrentBufferIndex()]->getDpData()->fvalue->Naxis(1))
                    +  ", "
                +  QString::number(p->main_view->bufferMap[fitsMainWindow->getCurrentBufferIndex()]->getDpData()->fvalue->Naxis(2))
                    + ")";
        } else {
            cmd += operand;
        }
        if (requestedArithmetics == 6) {
            cmd += ")";
        }

        dpuser_widget->executeCommand(cmd);
    }
}

ActionComboBox::ActionComboBox(QWidget *parent): QComboBox(parent) {
}

void ActionComboBox::setActions(QActionGroup *actions) {
    comboActions = actions;
    clear();
    for (int i = 0; i < comboActions->actions().size(); i++) {
        insertItem(i, comboActions->actions().at(i)->iconText());
    }
    connect(comboActions, SIGNAL(triggered(QAction *)),
            this, SLOT(actionActivated(QAction *)));
    connect(this, SIGNAL(activated(int)),
            this, SLOT(itemTriggered(int)));
}

void ActionComboBox::actionActivated(QAction *action) {
    for (int i = 0; i < comboActions->actions().size(); i++) {
        if (comboActions->actions().at(i) == action) {
            setCurrentIndex(i);
        }
    }
}

void ActionComboBox::itemTriggered(int item) {
    comboActions->actions().at(item)->trigger();
}
