#include <QButtonGroup>
#include <QApplication>
#include <QGroupBox>
#include <QHeaderView>
#include <QFileDialog>

#include "imred.h"
#include "QFitsMainWindow.h"
#include "QFitsMainView.h"
#include "QFitsWidget2D.h"
#include "QFitsView2D.h"
#include "QFitsSingleBuffer.h"
#include "QFitsGlobal.h"
#include "fits.h"
#include "dpuser.h"
#include "qtdpuser.h"
#include "dpuser_utils.h"
#include "dpstringlist.h"
#include "fitting.h"
#include "astrolib.h"

extern "C" {
#include "resources/fileopen.xpm"
}

_userDialogs userDialogs;
extern Fits *markposBuffer;

/* XPM */
static const char * const imredicon[]={
"32 32 2 1",
"# c #000000",
". c #ffffff",
"................................",
"................................",
"..............####..............",
"...............####.............",
"................####............",
".................####...........",
"..................####..........",
"...................####.........",
"....................####........",
".....................####.......",
"......................####......",
".......................####.....",
"........................####....",
".........................####...",
".##..##..#.#..##.###.##...####..",
".#.#.#.#.#.#.#...#...#.#...####.",
".#.#.##..#.#.###.##..##.....####",
".#.#.#...#.#...#.#...#.#...####.",
".##..#...###.##..###.#.#..####..",
".........................####...",
"........................####....",
".......................####.....",
"......................####......",
".....................####.......",
"....................####........",
"...................####.........",
"..................####..........",
".................####...........",
"................####............",
"...............####.............",
"..............####..............",
"................................"};

imRedGeneric::imRedGeneric(QFitsMainWindow *parent) : QDialog(parent, Qt::WindowTitleHint |
                                                                      Qt::WindowSystemMenuHint)
{
    if (fitsMainWindow != NULL) {
        currentBufferLabel = new QLabel("<b>Current buffer is:</b>  " +
                                    QString(fitsMainWindow->getCurrentBufferIndex().c_str()));
    } else {
        currentBufferLabel = new QLabel("<b>Current buffer is:</b>");
    }
    mainLayout = new QVBoxLayout;
    mainLayout->addWidget(currentBufferLabel);
    mainLayout->addSpacing(10);
    setLayout(mainLayout);

    setWindowIcon(QPixmap((const char **)imredicon));
}

void imRedGeneric::show() {
    setWindowTitle("QFitsView: " + action);
    QDialog::show();
}

void imRedGeneric::help() {
    dpuserthread.sendHelp(QString("function_") + action + ".html");
}

void imRedGeneric::addButtons(QWidget *lastWidget, bool help, bool displayNewBuffer) {
    mainLayout->addSpacing(10);

    if (displayNewBuffer) {
        newBufferButton = new QRadioButton("Store result in new buffer");
        newBufferButton->setAutoExclusive(false);
        mainLayout->addWidget(newBufferButton);
    }

    QPushButton *buttonOk = new QPushButton("Ok");
    buttonOk->setDefault(true);
    QPushButton *buttonCancel = new QPushButton("Cancel");
    QPushButton *buttonHelp = new QPushButton("Help");

    QGridLayout *buttonLayout = new QGridLayout();
    buttonLayout->addWidget(buttonHelp, 0, 0);
    buttonLayout->addWidget(buttonCancel, 0, 2);
    buttonLayout->addWidget(buttonOk, 0, 3);
    mainLayout->addLayout(buttonLayout);

    if (displayNewBuffer) {
        setTabOrder(lastWidget, newBufferButton);
        lastWidget = newBufferButton;
    }
    if (help) {
        setTabOrder(lastWidget, buttonHelp);
        lastWidget = buttonHelp;
    } else {
        buttonHelp->setVisible(false);
    }
    setTabOrder(lastWidget, buttonCancel);
    setTabOrder(buttonCancel, buttonOk);

    connect(buttonOk, SIGNAL(clicked()),
            this, SLOT(accepted()));
    connect(buttonCancel, SIGNAL(clicked()),
            this, SLOT(reject()));
    connect(buttonHelp, SIGNAL(clicked()),
            this, SLOT(help()));

    setMinimumWidth(275);
    adjustSize();
    setFixedSize(size());
}

QString imRedGeneric::saveConvert(const QString &source) {
    if (source.toDouble() == 0.0) {
        return QString("0");
    } else {
        return source;
    }
}

imRedUser::imRedUser(QFitsMainWindow *parent) : imRedGeneric(parent) {
}

void imRedUser::getFileName() {
    QString ppp = settings.lastOpenPath;
    QString pathname = QFileDialog::getOpenFileName(this, "QFitsView", ppp);
    if (!pathname.isEmpty()) emit fileSelected(pathname);
}

void imRedUser::show(QString which) {
    if (userDialogs.count(which)) {
        fields.clear();
        labels.clear();
        action = which;
        setWindowTitle(action);

        QStringList buffList;
        int comboCurrent = 0,
            j = 0;
        for (auto var:dpuser_vars) {
            if (var.second.type == typeFits) {
                buffList += QString(var.first.c_str());
                if (var.first == fitsMainWindow->getCurrentBufferIndex()) {
                    comboCurrent = j;
                }
                j++;
            }
        }

        QGridLayout *gridLayout = new QGridLayout();
        for (int i = 0; i < userDialogs[action].labels.size(); i++) {
            QLabel *label = new QLabel(userDialogs[action].labels[i]);
            labels.push_back(label);
            gridLayout->addWidget(label, i, 0, Qt::AlignRight);

            if (userDialogs[action].types[i][0] == '/') {
                QCheckBox *checker = new QCheckBox(userDialogs[action].types[i]);
                if (userDialogs[action].defaultValues[i] != "") {
                    checker->setChecked(userDialogs[action].defaultValues[i].toInt() == 1);
                }
                fields[i] = checker;
                gridLayout->addWidget(checker, i, 1, 1, 2);
            } else if (userDialogs[action].types[i] == "int") {
                QSpinBox *integer = new QSpinBox();
                integer->setRange(INT_MIN, INT_MAX);
                if (userDialogs[action].defaultValues[i] != "") {
                    integer->setValue(userDialogs[action].defaultValues[i].toInt());
                }
                fields[i] = integer;
                gridLayout->addWidget(integer, i, 1, 1, 2);
            } else if (userDialogs[action].types[i] == "fits") {
                QComboBox *buffers = new QComboBox();
                buffers->insertItems(0, buffList);
                buffers->setCurrentIndex(comboCurrent);
                fields[i] = buffers;
                gridLayout->addWidget(buffers, i, 1, 1, 2);
            } else if (userDialogs[action].types[i] == "file") {
                QLineEdit *lineedit = new QLineEdit();
                if (userDialogs[action].defaultValues[i] != "") {
                    lineedit->setText(userDialogs[action].defaultValues[i]);
                }
                fields[i] = lineedit;
                QPushButton *fileButton = new QPushButton(QPixmap(fileopen), "");
                gridLayout->addWidget(lineedit, i, 1);
                gridLayout->addWidget(fileButton, i, 2);
                connect(fileButton, SIGNAL(clicked()), this, SLOT(getFileName()));
                connect(this, SIGNAL(fileSelected(QString)), lineedit, SLOT(setText(QString)));
            } else if (userDialogs[action].types[i] == "real") {
                QLineEdit *lineedit = new QLineEdit();
                lineedit->setValidator(new QDoubleValidator(lineedit));
                if (userDialogs[action].defaultValues[i] != "") {
                    lineedit->setText(userDialogs[action].defaultValues[i]);
                }
                fields[i] = lineedit;
                gridLayout->addWidget(lineedit, i, 1, 1, 2);
            } else {
                QLineEdit *lineedit = new QLineEdit();
                if (userDialogs[action].defaultValues[i] != "") {
                    lineedit->setText(userDialogs[action].defaultValues[i]);
                }
                fields[i] = lineedit;
                gridLayout->addWidget(lineedit, i, 1, 1, 2);
            }
        }
        mainLayout->addLayout(gridLayout);

        addButtons(NULL, false, true);
        newBufferButton->setChecked(true);
        fields[0]->setFocus();

        QDialog::show();
    }
}

void imRedUser::showDialog(QFitsMainWindow *parent, QString which) {
    imRedUser *dialog = new imRedUser(parent);
    dialog->show(which);
}

void imRedUser::accepted() {
    QString cmd;
    if (newBufferButton->isChecked()) {
        cmd = freeBufferName().c_str();
    } else {
        cmd = fitsMainWindow->getCurrentBufferIndex().c_str();
    }
    cmd += " = " + action + "(";
    for (int i = 0; i < userDialogs[action].labels.size(); i++) {
        if (userDialogs[action].types[i] == "int") {
            if (i > 0) cmd += ", ";
            cmd += ((QSpinBox *)(fields[i]))->text();
            userDialogs[action].defaultValues[i] = ((QSpinBox *)(fields[i]))->text();
        } else if (userDialogs[action].types[i][0] == '/') {
            if (((QCheckBox *)(fields[i]))->isChecked()) {
                if (i > 0) cmd += ", ";
                cmd += userDialogs[action].types[i];
                userDialogs[action].defaultValues[i] = "1";
            } else {
                userDialogs[action].defaultValues[i] = "0";
            }
        } else if (userDialogs[action].types[i] == "fits"){
            if (i > 0) cmd += ", ";
            cmd += ((QComboBox *)(fields[i]))->currentText();
            userDialogs[action].defaultValues[i] = ((QComboBox *)(fields[i]))->currentText();;
        } else if (userDialogs[action].types[i] == "file" || userDialogs[action].types[i] == "string" ) {
            if (i > 0) cmd += ", ";
            cmd += "\"" + ((QLineEdit *)(fields[i]))->text() + "\"";
            userDialogs[action].defaultValues[i] = ((QLineEdit *)(fields[i]))->text();
        } else {
            if (i > 0) cmd += ", ";
            cmd += ((QLineEdit *)(fields[i]))->text();
            userDialogs[action].defaultValues[i] = ((QLineEdit *)(fields[i]))->text();
        }
    }
    cmd += ")";

    dpuser_widget->executeCommand(cmd);

    delete this;
}

imFilterGeneric::imFilterGeneric(QFitsMainWindow *parent) : imRedGeneric(parent) {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if ((sb != NULL) && (sb->getDpData()->type == typeFits)) {
        Fits *f = sb->getDpData()->fvalue;
        QLabel *labelSize = new QLabel("Size of array:");

        xsize = new QSpinBox();
        xsize->setMinimum(1);
        xsize->setMaximum(50000);
        xsize->setValue(f->Naxis(1));

        ysize = new QSpinBox();
        ysize->setMinimum(1);
        ysize->setMaximum(50000);
        ysize->setValue(f->Naxis(2));

        QLabel *labelCenter = new QLabel("Center:");
        buffersLock.lockForRead();
        centerX = new QLineEdit();
        centerX->setText(QString::number(f->Naxis(1) / 2 + 1));
        centerX->setValidator(new QDoubleValidator(centerX));

        centerY = new QLineEdit();
        centerY->setText(QString::number(f->Naxis(2) / 2 + 1));
        centerY->setValidator(new QDoubleValidator(centerY));
        buffersLock.unlock();

        gridLayout = new QGridLayout();
        gridLayout->addWidget(labelSize, 0, 0);
        QHBoxLayout *sizeHBoxLayout = new QHBoxLayout();
        sizeHBoxLayout->addWidget(xsize);
        sizeHBoxLayout->addWidget(ysize);
        gridLayout->addLayout(sizeHBoxLayout, 0, 1);
        QHBoxLayout *centerHBoxLayout = new QHBoxLayout();
        centerHBoxLayout->addWidget(centerX);
        centerHBoxLayout->addWidget(centerY);
        gridLayout->addWidget(labelCenter, 1, 0);
        gridLayout->addLayout(centerHBoxLayout, 1, 1);
        mainLayout->addLayout(gridLayout);

        setTabOrder(xsize, ysize);
        setTabOrder(ysize, centerX);
        setTabOrder(centerX, centerY);
    }
}

imFilterGauss::imFilterGauss(QFitsMainWindow *parent) : imFilterGeneric(parent) {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if (sb != NULL) {
        action = "gauss";

        QLabel *labelFwhm1  = new QLabel("FWHM 1 (Pixels):");
        QLabel *labelFwhm2  = new QLabel("FWHM 2 (-1 for circular):");
        QLabel *labelRot    = new QLabel("Rotation (degrees):");

        fwhm1 = new QLineEdit();
        fwhm1->setText("5.0");
        fwhm1->setValidator(new QDoubleValidator(fwhm1));
        fwhm1->selectAll();
        fwhm1->setFocus();

        fwhm2 = new QLineEdit();
        fwhm2->setText("-1.0");
        fwhm2->setValidator(new QDoubleValidator(fwhm2));

        angle = new QLineEdit();
        angle->setText("0.0");
        angle->setValidator(new QDoubleValidator(angle));

        gridLayout->addWidget(labelFwhm1, 2, 0);
        gridLayout->addWidget(fwhm1, 2, 1);
        gridLayout->addWidget(labelFwhm2, 3, 0);
        gridLayout->addWidget(fwhm2, 3, 1);
        gridLayout->addWidget(labelRot, 4, 0);
        gridLayout->addWidget(angle, 4, 1);

        setTabOrder(centerY, fwhm1);
        setTabOrder(fwhm1, fwhm2);
        setTabOrder(fwhm2, angle);

        addButtons(angle);
    }
}

void imFilterGauss::showDialog(QFitsMainWindow *parent) {
    imFilterGauss *dialog = new imFilterGauss(parent);
    dialog->show();
}

void imFilterGauss::accepted() {
    QString cmd, val;
    if (newBufferButton->isChecked()) {
        cmd = freeBufferName().c_str();
    } else {
        cmd = fitsMainWindow->getCurrentBufferIndex().c_str();
    }
    cmd += " = gauss(";
    val = centerX->text();
    if (val == "") {
        val = "0";
    }
    cmd += val + ", ";
    val = centerY->text();
    if (val == "") {
        val = "0";
    }
    cmd += val + ", ";
    val = fwhm1->text();
    if (val == "") {
        val = "0";
    }
    cmd += val + ", ";
    if (fwhm2->text().toDouble() > 0.0) {
        cmd += fwhm2->text() + ", ";
        if (angle->text().toDouble() != 0.0) {
            cmd += angle->text() + ", ";
        }
    }
    cmd += "naxis1 = " + xsize->text() + ", naxis2 = " + ysize->text() + ")";
    dpuser_widget->executeCommand(cmd);

    delete this;
}

imFilterEllipse::imFilterEllipse(QFitsMainWindow *parent) : imFilterGeneric(parent) {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if (sb != NULL) {
        action = "ellipse";

        QLabel *labelMajor = new QLabel("Major Axis (Pixels):");
        QLabel *labelMinor = new QLabel("Minor (0 for circle):");
        QLabel *labelRot = new QLabel("Rotation angle (degrees):");

        major = new QSpinBox();
        major->setMinimum(0);
        major->setMaximum(4096);
        major->setValue(5);
        major->setFocus();

        minor = new QSpinBox();
        minor->setMinimum(0);
        minor->setMaximum(4096);
        minor->setValue(0);

        angle = new QLineEdit();
        angle->setText("0.0");
        angle->setValidator(new QDoubleValidator(angle));

        gridLayout->addWidget(labelMajor, 2, 0);
        gridLayout->addWidget(major, 2, 1);
        gridLayout->addWidget(labelMinor, 3, 0);
        gridLayout->addWidget(minor, 3, 1);
        gridLayout->addWidget(labelRot, 4, 0);
        gridLayout->addWidget(angle, 4, 1);

        setTabOrder(centerY, major);
        setTabOrder(major, minor);
        setTabOrder(minor, angle);

        addButtons(angle);
    }
}

void imFilterEllipse::showDialog(QFitsMainWindow *parent) {
    imFilterEllipse *dialog = new imFilterEllipse(parent);
    dialog->show();
}

void imFilterEllipse::accepted() {
    QString cmd, val;
    if (newBufferButton->isChecked()) {
        cmd = freeBufferName().c_str();
    } else {
        cmd = fitsMainWindow->getCurrentBufferIndex().c_str();
    }
    cmd += " = ellipse(";
    val = centerX->text();
    if (val == "") {
        val = "0";
    }
    cmd += val + ", ";
    val = centerY->text();
    if (val == "") {
        val = "0";
    }
    cmd += val + ", ";
    val = major->text();
    if (val == "") {
        val = "0";
    }
    cmd += val + ", ";
    if (minor->text().toDouble() > 0.0) {
        cmd += minor->text() + ", ";
        if (angle->text().toDouble() != 0.0) {
            cmd += angle->text() + ", ";
        }
    }
    cmd += "naxis1 = " + xsize->text() + ", naxis2 = " + ysize->text() + ")";
    dpuser_widget->executeCommand(cmd);

    delete this;
}

imFilterMoffat::imFilterMoffat(QFitsMainWindow *parent) : imFilterGeneric(parent) {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if (sb != NULL) {
        action = "moffat";

        QLabel *labelPower = new QLabel("Power index:");
        QLabel *labelFwhm1  = new QLabel("FWHM 1 (Pixels):");
        QLabel *labelFwhm2  = new QLabel("FWHM 2 (-1 for circular):");
        QLabel *labelRot    = new QLabel("Rotation (degrees):");

        power = new QLineEdit();
        power->setText("1.0");
        power->setValidator(new QDoubleValidator(power));
        power->selectAll();
        power->setFocus();

        fwhm1 = new QLineEdit();
        fwhm1->setText("5.0");
        fwhm1->setValidator(new QDoubleValidator(fwhm1));

        fwhm2 = new QLineEdit();
        fwhm2->setText("-1.0");
        fwhm2->setValidator(new QDoubleValidator(fwhm2));

        angle = new QLineEdit();
        angle->setText("0.0");
        angle->setValidator(new QDoubleValidator(angle));

        gridLayout->addWidget(labelPower, 2, 0);
        gridLayout->addWidget(power, 2, 1);
        gridLayout->addWidget(labelFwhm1, 3, 0);
        gridLayout->addWidget(fwhm1, 3, 1);
        gridLayout->addWidget(labelFwhm2, 4, 0);
        gridLayout->addWidget(fwhm2, 4, 1);
        gridLayout->addWidget(labelRot, 5, 0);
        gridLayout->addWidget(angle, 5, 1);

        setTabOrder(centerY, power);
        setTabOrder(power, fwhm1);
        setTabOrder(fwhm1, fwhm2);
        setTabOrder(fwhm2, angle);

        addButtons(angle);
    }
}

void imFilterMoffat::showDialog(QFitsMainWindow *parent) {
    imFilterMoffat *dialog = new imFilterMoffat(parent);
    dialog->show();
}

void imFilterMoffat::accepted() {
    QString cmd, val;
    if (newBufferButton->isChecked()) {
        cmd = freeBufferName().c_str();
    } else {
        cmd = fitsMainWindow->getCurrentBufferIndex().c_str();
    }
    cmd += " = moffat(";
    val = centerX->text();
    if (val == "") {
        val = "0";
    }
    cmd += val + ", ";
    val = centerY->text();
    if (val == "") {
        val = "0";
    }
    cmd += val + ", ";
    val = power->text();
    if (val == "") {
        val = "0";
    }
    cmd += val + ", ";
    val = fwhm1->text();
    if (val == "") {
        val = "0";
    }
    cmd += val + ", ";
    if (fwhm2->text().toDouble() > 0.0) {
        cmd += fwhm2->text() + ", ";
        if (angle->text().toDouble() != 0.0) {
            cmd += angle->text() + ", ";
        }
    }
    cmd += "naxis1 = " + xsize->text() + ", naxis2 = " + ysize->text() + ")";
    dpuser_widget->executeCommand(cmd);

    delete this;
}

imFilterAiry::imFilterAiry(QFitsMainWindow *parent) : imRedGeneric(parent) {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if (sb != NULL) {
        Fits *f = sb->getDpData()->fvalue;
        QLabel *labelSize = new QLabel("Size of array:");

        xsize = new QSpinBox();
        xsize->setMinimum(1);
        xsize->setMaximum(50000);
        xsize->setValue(f->Naxis(1));

        ysize = new QSpinBox();
        ysize->setMinimum(1);
        ysize->setMaximum(50000);
        ysize->setValue(f->Naxis(2));

        gridLayout = new QGridLayout();
        gridLayout->addWidget(labelSize, 0, 0);
        QHBoxLayout *sizeHBoxLayout = new QHBoxLayout();
        sizeHBoxLayout->addWidget(xsize);
        sizeHBoxLayout->addWidget(ysize);
        gridLayout->addLayout(sizeHBoxLayout, 0, 1);
        mainLayout->addLayout(gridLayout);

        setTabOrder(xsize, ysize);

        action = "airy";

        QLabel *labelDiameter = new QLabel("Diameter (meters):");
        QLabel *labelPixelscale  = new QLabel("Pixel scale (arcseconds):");
        QLabel *labelWavelength  = new QLabel("Wavelength (microns):");

        diameter = new QDoubleSpinBox();
        diameter->setDecimals(3);
        diameter->setValue(8.2);
        diameter->setRange(0.001, 99999.);
        diameter->setSingleStep(0.2);
        diameter->selectAll();
        diameter->setFocus();

        pixelscale = new QDoubleSpinBox();
        pixelscale->setDecimals(5);
        pixelscale->setValue(0.013);
        pixelscale->setSingleStep(0.001);
        pixelscale->setRange(1e-10, 99999.);

        wavelength = new QDoubleSpinBox();
        wavelength->setDecimals(5);
        wavelength->setValue(2.2);
        wavelength->setSingleStep(0.1);
        wavelength->setDecimals(5);
        wavelength->setRange(1e-10, 99999.);

        gridLayout->addWidget(labelDiameter, 1, 0);
        gridLayout->addWidget(diameter, 1, 1);
        gridLayout->addWidget(labelPixelscale, 2, 0);
        gridLayout->addWidget(pixelscale, 2, 1);
        gridLayout->addWidget(labelWavelength, 3, 0);
        gridLayout->addWidget(wavelength, 3, 1);

        setTabOrder(ysize, diameter);
        setTabOrder(diameter, pixelscale);
        setTabOrder(pixelscale, wavelength);

        addButtons(wavelength);
    }
}

void imFilterAiry::showDialog(QFitsMainWindow *parent) {
    imFilterAiry *dialog = new imFilterAiry(parent);
    dialog->show();
}

void imFilterAiry::accepted() {
    QString cmd, val;
    if (newBufferButton->isChecked()) {
        cmd = freeBufferName().c_str();
    } else {
        cmd = fitsMainWindow->getCurrentBufferIndex().c_str();
    }
    cmd += " = airy(";

    val = diameter->text();
    if (val == "") {
        val = "1";
    }
    cmd += val + ", ";
    val = pixelscale->text();
    if (val == "") {
        val = "1";
    }
    cmd += val + ", ";
    val = wavelength->text();
    if (val == "") {
        val = "1";
    }
    cmd += val + ", ";
    cmd += "naxis1 = " + xsize->text() + ", naxis2 = " + ysize->text() + ")";
    dpuser_widget->executeCommand(cmd);

    delete this;
}

imRedRotate::imRedRotate(QFitsMainWindow *parent) : imRedGeneric(parent) {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if ((sb != NULL) && (sb->getDpData()->type == typeFits)) {
        Fits *f = sb->getDpData()->fvalue;
        action = "rotate";

        QLabel *labelAngle = new QLabel("Rotation angle (degrees):");
        QLabel *labelCenter = new QLabel("Center of rotation:");

        angle = new QLineEdit();
        angle->setText("0.0");
        angle->setValidator(new QDoubleValidator(angle));
        angle->selectAll();
        angle->setFocus();

        centerX = new QLineEdit();
        centerX->setText(QString::number(f->Naxis(1) / 2 + 1));
        centerX->setValidator(new QIntValidator(centerX));

        centerY = new QLineEdit();
        centerY->setText(QString::number(f->Naxis(2) / 2 + 1));
        centerY->setValidator(new QIntValidator(centerY));

        QGridLayout *gridLayout = new QGridLayout();
        gridLayout->addWidget(labelAngle, 0, 0);
        gridLayout->addWidget(angle, 0, 1);
        gridLayout->addWidget(labelCenter, 1, 0);
        QHBoxLayout *centerHBoxLayout = new QHBoxLayout();
        centerHBoxLayout->addWidget(centerX);
        centerHBoxLayout->addWidget(centerY);
        gridLayout->addLayout(centerHBoxLayout, 1, 1);
        mainLayout->addLayout(gridLayout);

        setTabOrder(angle, centerX);
        setTabOrder(centerX, centerY);

        addButtons(centerY);
    }
}

void imRedRotate::showDialog(QFitsMainWindow *parent) {
    imRedRotate *dialog = new imRedRotate(parent);
    dialog->show();
}

void imRedRotate::accepted() {
    QString cmd;
    if (newBufferButton->isChecked()) {
        cmd = QString(freeBufferName().c_str()) + " = rotate(";
    } else {
        cmd = "rotate ";
    }
    cmd += QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + ", ";
    cmd += angle->text();

    if (centerX->isModified() || centerY->isModified()) {
        cmd += ", " + centerX->text() + ", " + centerY->text();
    }
    if (newBufferButton->isChecked()) {
        cmd += ")";
    }

    dpuser_widget->executeCommand(cmd);

    delete this;
}

imRedShift::imRedShift(QFitsMainWindow *parent) : imRedGeneric(parent) {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if ((sb != NULL) && (sb->getDpData()->type == typeFits)) {
        action = "shift";
        is3D = (sb->getDpData()->fvalue->Naxis(3) > 1);

        QLabel *labelX = new QLabel("X shift (pixels):");
        QLabel *labelY = new QLabel("Y shift (pixels):");
        QLabel *labelZ = new QLabel("Z shift (pixels):");

        xshift = new QLineEdit();
        xshift->setText("0");
        if (is3D) {
            xshift->setValidator(new QIntValidator(xshift));
        } else {
            xshift->setValidator(new QDoubleValidator(xshift));
        }
        xshift->selectAll();
        xshift->setFocus();

        yshift = new QLineEdit();
        yshift->setText("0");
        if (is3D) {
            yshift->setValidator(new QIntValidator(yshift));
        } else {
            yshift->setValidator(new QDoubleValidator(yshift));
        }

        zshift = new QLineEdit();
        zshift->setText("0");
        zshift->setValidator(new QIntValidator(zshift));
        if (!is3D) {
            zshift->setEnabled(false);
            labelZ->setEnabled(false);
        }

        wrap = new QRadioButton("Wrap image");
        wrap->setAutoExclusive(false);

        QGridLayout *gridLayout = new QGridLayout();
        gridLayout->addWidget(labelX, 0, 0);
        gridLayout->addWidget(xshift, 0, 1);
        gridLayout->addWidget(labelY, 1, 0);
        gridLayout->addWidget(yshift, 1, 1);
        gridLayout->addWidget(labelZ, 2, 0);
        gridLayout->addWidget(zshift, 2, 1);
        gridLayout->addWidget(wrap, 3, 1);
        mainLayout->addLayout(gridLayout);

        setTabOrder(xshift, yshift);
        if (!is3D) {
            setTabOrder(yshift, zshift);
            setTabOrder(zshift, wrap);
        } else {
            setTabOrder(yshift, wrap);
        }

        addButtons(wrap);
    }
}

void imRedShift::showDialog(QFitsMainWindow *parent) {
    imRedShift *dialog = new imRedShift(parent);
    dialog->show();
}

void imRedShift::accepted() {
    QString cmd;
    if (newBufferButton->isChecked()) {
        cmd = QString(freeBufferName().c_str()) + " = shift(";
    } else {
        cmd = "shift ";
    }
    cmd += QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + ", ";
    cmd += saveConvert(xshift->text()) + ", ";
    cmd += saveConvert(yshift->text());
    if (is3D) {
        cmd += ", " + saveConvert(zshift->text());
    }
    if (wrap->isChecked()) {
        cmd += ", /wrap";
    }
    if (newBufferButton->isChecked()) {
        cmd += ")";
    }

    dpuser_widget->executeCommand(cmd);

    delete this;
}

imRedCrop::imRedCrop(QFitsMainWindow *parent) : imRedGeneric(parent) {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if ((sb != NULL) && (sb->getDpData()->type == typeFits)) {
        Fits *f = sb->getDpData()->fvalue;
        action = "crop";

        QLabel *labelX = new QLabel("X axis:");
        QLabel *labelY = new QLabel("Y axis:");
        QLabel *labelZ = new QLabel("Z axis:");

        x1 = new QSpinBox();
        x1->setMinimum(1);
        x1->setMaximum(f->Naxis(1));
        x1->setValue(1);
        x1->selectAll();
        x1->setFocus();

        x2 = new QSpinBox();
        x2->setMinimum(1);
        x2->setMaximum(f->Naxis(1));
        x2->setValue(f->Naxis(1));

        y1 = new QSpinBox();
        y1->setMinimum(1);
        y1->setMaximum(f->Naxis(2));
        y1->setValue(1);

        y2 = new QSpinBox();
        y2->setMinimum(1);
        y2->setMaximum(f->Naxis(2));
        y2->setValue(f->Naxis(2));

        z1 = new QSpinBox();
        z1->setMinimum(1);
        z1->setMaximum(f->Naxis(3));
        z1->setValue(1);

        z2 = new QSpinBox();
        z2->setMinimum(1);
        z2->setMaximum(f->Naxis(3));
        z2->setValue(f->Naxis(3));

        if (f->Naxis(3) < 2) {
            labelZ->setEnabled(false);
            z1->setEnabled(false);
            z2->setEnabled(false);
        }
        if (f->Naxis(2) < 2) {
            labelY->setEnabled(false);
            y1->setEnabled(false);
            y2->setEnabled(false);
        }

        QGridLayout *gridLayout = new QGridLayout();
        gridLayout->addWidget(labelX, 0, 0);
        gridLayout->addWidget(x1, 0, 1);
        gridLayout->addWidget(x2, 0, 2);
        gridLayout->addWidget(labelY, 1, 0);
        gridLayout->addWidget(y1, 1, 1);
        gridLayout->addWidget(y2, 1, 2);
        gridLayout->addWidget(labelZ, 2, 0);
        gridLayout->addWidget(z1, 2, 1);
        gridLayout->addWidget(z2, 2, 2);
        mainLayout->addLayout(gridLayout);

        setTabOrder(x1, x2);
        setTabOrder(x2, y1);
        setTabOrder(y1, y2);
        setTabOrder(y2, z1);
        setTabOrder(z1, z2);

        addButtons(z2, false);
    }
}

void imRedCrop::showDialog(QFitsMainWindow *parent) {
    imRedCrop *dialog = new imRedCrop(parent);
    dialog->show();
}

void imRedCrop::accepted() {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if ((sb != NULL) && (sb->getDpData()->type == typeFits)) {
        Fits *f = sb->getDpData()->fvalue;
        QString cmd;
        if (newBufferButton->isChecked()) {
            cmd = freeBufferName().c_str();
        } else {
            cmd = fitsMainWindow->getCurrentBufferIndex().c_str();
        }
        cmd += " = " + QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + "[";
        if ((x1->value() == 1) &&
            (x2->value() == f->Naxis(1)))
        {
            cmd += "*";
        } else if (x1->value() == x2->value()) {
            cmd += x1->text();
        } else {
            cmd += x1->text() + ":" + x2->text();
        }
        if (f->Naxis(2) > 1) {
            cmd += ",";
            if ((y1->value() == 1) &&
                (y2->value() == f->Naxis(2)))
            {
                cmd += "*";
            } else if (y1->value() == y2->value()) {
                cmd += y1->text();
            } else {
                cmd += y1->text() + ":" + y2->text();
            }
            if (f->Naxis(3) > 1) {
                cmd += ",";
                if ((z1->value() == 1) &&
                    (z2->value() == f->Naxis(3)))
                {
                        cmd += "*";
                } else if (z1->value() == z2->value()) {
                        cmd += z1->text();
                } else {
                        cmd += z1->text() + ":" + z2->text();
                }
            }
        }
        cmd += "]";

        dpuser_widget->executeCommand(cmd);
    }
    delete this;
}

imRedCblank::imRedCblank(QFitsMainWindow *parent) : imRedGeneric(parent) {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if ((sb != NULL) && (sb->getDpData()->type == typeFits)) {
        Fits *f = sb->getDpData()->fvalue;
        action = "cblank";

        QLabel *label = new QLabel("Replacement value:");

        value = new QLineEdit();
        value->setText("0");
        value->setValidator(new QDoubleValidator(value));
        value->selectAll();
        value->setFocus();

        QGridLayout *gridLayout = new QGridLayout();
        gridLayout->addWidget(label, 0, 0);
        gridLayout->addWidget(value, 0, 1);
        mainLayout->addLayout(gridLayout);

        addButtons(value, true, true);
    }
}

void imRedCblank::showDialog(QFitsMainWindow *parent) {
    imRedCblank *dialog = new imRedCblank(parent);
    dialog->show();
}

void imRedCblank::accepted() {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if ((sb != NULL) && (sb->getDpData()->type == typeFits)) {
        QString cmd, val;
        if (newBufferButton->isChecked()) {
            cmd = freeBufferName().c_str();
            cmd += " = cblank(";
        } else {
            cmd = "cblank ";
        }
        cmd += fitsMainWindow->getCurrentBufferIndex().c_str();
        val = value->text();
        if (val == "") {
            val = "0";
        }
        if (val != "0") {
          cmd += ", " + val;
        }
        if (newBufferButton->isChecked()) {
            cmd += ")";
        }

        dpuser_widget->executeCommand(cmd);
    }
    delete this;
}

imRedResize::imRedResize(QFitsMainWindow *parent) : imRedGeneric(parent) {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if ((sb != NULL) && (sb->getDpData()->type == typeFits)) {
        Fits *f = sb->getDpData()->fvalue;
        action = "resize";

        QLabel *labelX = new QLabel("X axis:");
        QLabel *labelY = new QLabel("Y axis:");
        QLabel *labelZ = new QLabel("Z axis:");

        resizeX = new QSpinBox();
        resizeX->setMinimum(1);
        resizeX->setMaximum(32000);
        resizeX->setValue(f->Naxis(1));
        resizeX->selectAll();
        resizeX->setFocus();

        resizeY = new QSpinBox();
        resizeY->setMinimum(1);
        resizeY->setMaximum(32000);
        resizeY->setValue(f->Naxis(2));

        resizeZ = new QSpinBox();
        resizeZ->setMinimum(1);
        resizeZ->setMaximum(32000);
        resizeZ->setValue(f->Naxis(3));

        QGridLayout *gridLayout = new QGridLayout();
        gridLayout->addWidget(labelX, 0, 0);
        gridLayout->addWidget(resizeX, 0, 1);
        gridLayout->addWidget(labelY, 1, 0);
        gridLayout->addWidget(resizeY, 1, 1);
        gridLayout->addWidget(labelZ, 2, 0);
        gridLayout->addWidget(resizeZ, 2, 1);
        mainLayout->addLayout(gridLayout);

        if (f->Naxis(3) < 2) {
            labelZ->setEnabled(false);
            resizeZ->setEnabled(false);
        }

        setTabOrder(resizeX, resizeY);
        setTabOrder(resizeY, resizeZ);

        addButtons(resizeZ);
    }
}

void imRedResize::showDialog(QFitsMainWindow *parent) {
    imRedResize *dialog = new imRedResize(parent);
    dialog->show();
}

void imRedResize::accepted() {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if ((sb != NULL) && (sb->getDpData()->type == typeFits)) {
        Fits *f = sb->getDpData()->fvalue;
        QString cmd;
        if (newBufferButton->isChecked()) {
            cmd = QString(freeBufferName().c_str()) + " = resize(";
        } else {
            cmd = "resize ";
        }
        cmd += QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + ", ";
        cmd += resizeX->text() + ", ";
        cmd += resizeY->text();
        if (sb->getDpData()->fvalue->Naxis(3) > 1) {
            cmd += ", " + resizeZ->text();
        }
        if (newBufferButton->isChecked()) {
            cmd += ")";
        }

        dpuser_widget->executeCommand(cmd);
    }
    delete this;
}

imRedRebin::imRedRebin(QFitsMainWindow *parent) : imRedGeneric(parent) {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if ((sb != NULL) && (sb->getDpData()->type == typeFits)) {
        Fits *f = sb->getDpData()->fvalue;
        action = "rebin";

        QLabel *labelX = new QLabel("X axis:");
        QLabel *labelY = new QLabel("Y axis:");
        QLabel *labelZ = new QLabel("Z axis:");

        rebinX = new QSpinBox();
        rebinX->setMinimum(1);
        rebinX->setMaximum(32000);
        rebinX->setValue(f->Naxis(1));
        rebinX->selectAll();

        rebinY = new QSpinBox();
        rebinY->setMinimum(1);
        rebinY->setMaximum(32000);
        rebinY->setValue(f->Naxis(2));

        rebinZ = new QSpinBox();
        rebinZ->setMinimum(1);
        rebinZ->setMaximum(320000);
        rebinZ->setValue(f->Naxis(3));

        QGridLayout *gridLayout = new QGridLayout();
        gridLayout->addWidget(labelX, 0, 0);
        gridLayout->addWidget(rebinX, 0, 1);
        gridLayout->addWidget(labelY, 1, 0);
        gridLayout->addWidget(rebinY, 1, 1);
        gridLayout->addWidget(labelZ, 2, 0);
        gridLayout->addWidget(rebinZ, 2, 1);
        mainLayout->addLayout(gridLayout);

        setTabOrder(rebinX, rebinY);
        setTabOrder(rebinY, rebinZ);

        addButtons(rebinZ);
        rebinX->setFocus();

        if (f->Naxis(3) < 2) {
            rebinZ->setEnabled(FALSE);
        }
    }
}

void imRedRebin::showDialog(QFitsMainWindow *parent) {
    imRedRebin *dialog = new imRedRebin(parent);
    dialog->show();
}

void imRedRebin::accepted() {
    QString cmd;
    if (newBufferButton->isChecked()) {
        cmd = QString(freeBufferName().c_str()) + " = rebin(";
    } else {
        cmd = "rebin ";
    }
    cmd += QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + ", ";
    cmd += rebinX->text() + ", ";
    cmd += rebinY->text();
    if (rebinZ->isEnabled()) {
        cmd += ", ";
        cmd += rebinZ->text();
    }
    if (newBufferButton->isChecked()) {
        cmd += ")";
    }

    dpuser_widget->executeCommand(cmd);

    delete this;
}

imRedCreatePSF::imRedCreatePSF(QFitsMainWindow *parent) : imRedGeneric(parent) {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if (sb != NULL) {
        action = "psf";

        QLabel *label2 = new QLabel("find parameters:");
        QLabel *label3 = new QLabel("Low threshold:");
        QLabel *label4 = new QLabel("FWHM [pixels]:");
        QLabel *label5 = new QLabel("Number of stars:");
        QLabel *label6 = new QLabel("Size of cosine bell:");

        low = new QLineEdit();
        low->setText("5");
        low->setValidator(new QDoubleValidator(low));
        low->selectAll();
        low->setFocus();

        fwhm = new QLineEdit();
        fwhm->setText("5");
        fwhm->setValidator(new QDoubleValidator(fwhm));

        nstars = new QSpinBox();
        nstars->setMinimum(1);
        nstars->setMaximum(1000);
        nstars->setValue(10);

        cbell1 = new QSpinBox();
        cbell1->setMinimum(1);
        cbell1->setMaximum(32000);
        cbell1->setValue(10);

        cbell2 = new QSpinBox();
        cbell2->setMinimum(1);
        cbell2->setMaximum(32000);
        cbell2->setValue(15);

        QGridLayout *gridLayout = new QGridLayout();
        gridLayout->addWidget(label2, 0, 0);
        gridLayout->addWidget(label3, 1, 0);
        gridLayout->addWidget(low, 1, 1);
        gridLayout->addWidget(label4, 2, 0);
        gridLayout->addWidget(fwhm, 2, 1);
        gridLayout->addWidget(label5, 3, 0);
        gridLayout->addWidget(nstars, 3, 1);
        gridLayout->addWidget(label6, 4, 0);
        QHBoxLayout *bellHBoxLayout = new QHBoxLayout();
        bellHBoxLayout->addWidget(cbell1);
        bellHBoxLayout->addWidget(cbell2);
        gridLayout->addLayout(bellHBoxLayout, 4, 1);
        mainLayout->addLayout(gridLayout);

        setTabOrder(low, fwhm);
        setTabOrder(fwhm, nstars);
        setTabOrder(nstars, cbell1);
        setTabOrder(cbell1, cbell2);

        addButtons(cbell2);
    }
}

void imRedCreatePSF::showDialog(QFitsMainWindow *parent) {
    imRedCreatePSF *dialog = new imRedCreatePSF(parent);
    dialog->show();
}

void imRedCreatePSF::accepted() {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if ((sb != NULL) && (sb->getDpData()->type == typeFits)) {
        Fits *f = sb->getDpData()->fvalue;
        QString cmd;
        if (newBufferButton->isChecked()) {
            cmd = QString(freeBufferName().c_str()) + " = psf(";
        } else {
            cmd = QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " = psf(";
        }
        cmd += QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + ", ";
        cmd += "resize(find(";
        cmd += QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + ", ";
        cmd += low->text() + ", " + fwhm->text() + "), 2, ";
        cmd += nstars->text() + "), /median)";
        cmd += " * cosbell(";
        cmd += QString::number((int)(f->Naxis(1) / 2 + 1));
        cmd += ", ";
        cmd += QString::number((int)(f->Naxis(2) / 2 + 1));
        cmd += ", " + cbell1->text() + ", " + cbell2->text();
        cmd += ", naxis1 = " + QString::number(f->Naxis(1));
        cmd += ", naxis2 = " + QString::number(f->Naxis(2));
        cmd += ")";

        dpuser_widget->executeCommand(cmd);
    }
    delete this;
}

imRedSmooth::imRedSmooth(QFitsMainWindow *parent) : imRedGeneric(parent) {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if ((sb != NULL) && (sb->getDpData()->type == typeFits)) {
        Fits *f = sb->getDpData()->fvalue;
        is3D = (sb->getDpData()->fvalue->Naxis(3) > 1);
        action = "smooth";

        //
        // widget/layout for Smoothing
        //
        QLabel *label = new QLabel("Smoothing width (pixels):");
        fwhm = new QLineEdit();
        fwhm->setText("3");
        fwhm->setValidator(new QDoubleValidator(fwhm));
        fwhm->selectAll();
        fwhm->setFocus();

        QHBoxLayout *fwhmLayout = new QHBoxLayout;
        fwhmLayout->addWidget(label);
        fwhmLayout->addWidget(fwhm);
        mainLayout->addLayout(fwhmLayout);

        //
        // Create QHBoxLayout for method & axes
        //
        QHBoxLayout *hboxMainMethodAxes = new QHBoxLayout;
        mainLayout->addLayout(hboxMainMethodAxes);

        //
        // widget/layout for Method
        //
        method1Button = new QRadioButton("Gauss");
        method1Button->setChecked(true);
        method2Button = new QRadioButton("Boxcar average");
        method3Button = new QRadioButton("Boxcar median");

        methodButtonGroup = new QButtonGroup();
        methodButtonGroup->addButton(method1Button, 1);
        methodButtonGroup->addButton(method2Button, 2);
        methodButtonGroup->addButton(method3Button, 3);

        QGroupBox *groupMethod = new QGroupBox();
        groupMethod->setTitle("Method");
        QVBoxLayout *vboxMethod = new QVBoxLayout(groupMethod);
        vboxMethod->addWidget(method1Button);
        vboxMethod->addWidget(method2Button);
        vboxMethod->addWidget(method3Button);
        hboxMainMethodAxes->addWidget(groupMethod);

        //
        // widget/layout for Axes
        //
        xyButton = new QRadioButton("XY");
        xButton = new QRadioButton("X");
        yButton = new QRadioButton("Y");
        zButton = new QRadioButton("Z");
        xyButton->setChecked(true);

        axesButtonGroup = new QButtonGroup();
        axesButtonGroup->addButton(xyButton, 1);
        axesButtonGroup->addButton(xButton, 2);
        axesButtonGroup->addButton(yButton, 3);
        axesButtonGroup->addButton(zButton, 4);

        QGroupBox *groupAxes = new QGroupBox();
        groupAxes->setTitle("Smoothing axes");
        QVBoxLayout *vboxAxes = new QVBoxLayout(groupAxes);
        vboxAxes->addWidget(xyButton);
        QHBoxLayout *hboxAxes = new QHBoxLayout;
        hboxAxes->addWidget(xButton);
        hboxAxes->addWidget(yButton);
        hboxAxes->addWidget(zButton);
        vboxAxes->addLayout(hboxAxes);
        vboxAxes->addStretch(1);
        hboxMainMethodAxes->addWidget(groupAxes);

        //
        // Add standard widgets/layouts (NewBuffer, Help, Cancel, Ok)
        //
        addButtons(groupAxes);
    }
}

void imRedSmooth::showDialog(QFitsMainWindow *parent) {
    imRedSmooth *dialog = new imRedSmooth(parent);
    dialog->show();
}

void imRedSmooth::accepted() {
    QString cmd;
    int methodid = methodButtonGroup->checkedId();
    if (methodid == 1)  {
        if (newBufferButton->isChecked()) {
            cmd = QString(freeBufferName().c_str()) + " = smooth(";
        } else {
            cmd = "smooth ";
        }
    } else {
        if (newBufferButton->isChecked()) {
            cmd = QString(freeBufferName().c_str()) + " = boxcar(";
        } else {
            cmd = "boxcar ";
        }
    }
    cmd += QString(fitsMainWindow->getCurrentBufferIndex().c_str());
    cmd += ", ";
    if (methodid == 1) {
        cmd += fwhm->text();
    } else {
        cmd += QString::number(fwhm->text().toInt());
    }
    if (methodid == 3) {
        cmd += ", /median";
    }
    if (xButton->isChecked()) {
        cmd += ", /x";
    }
    if (yButton->isChecked()) {
        cmd += ", /y";
    }
    if (is3D && zButton->isChecked()) {
        cmd += ", /z";
    }
    if (newBufferButton->isChecked()) {
        cmd += ")";
    }

    dpuser_widget->executeCommand(cmd);

    delete this;
}

imRedSmoothSubtract::imRedSmoothSubtract(QFitsMainWindow *parent) : imRedGeneric(parent) {
    action = "smooth";

    QLabel *label = new QLabel("Smoothing width (pixels):");

    fwhm = new QLineEdit();
    fwhm->setText("3");
    fwhm->setValidator(new QDoubleValidator(fwhm));
    fwhm->selectAll();
    fwhm->setFocus();

    QHBoxLayout *smoothLayout = new QHBoxLayout;
    smoothLayout->addWidget(label);
    smoothLayout->addWidget(fwhm);
    mainLayout->addLayout(smoothLayout);

    method1Button = new QRadioButton("Gauss");
    method1Button->setChecked(true);
    method2Button = new QRadioButton("Boxcar average");
    method3Button = new QRadioButton("Boxcar median");

    methodButtonGroup = new QButtonGroup();
    methodButtonGroup->addButton(method1Button, 1);
    methodButtonGroup->addButton(method2Button, 2);
    methodButtonGroup->addButton(method3Button, 3);
    QGroupBox *groupMethod = new QGroupBox();
    groupMethod->setTitle("Method");
    QVBoxLayout *vboxMethod = new QVBoxLayout(groupMethod);
    vboxMethod->addWidget(method1Button);
    vboxMethod->addWidget(method2Button);
    vboxMethod->addWidget(method3Button);
    mainLayout->addWidget(groupMethod);

    setTabOrder(fwhm, groupMethod);

    addButtons(groupMethod);
}

void imRedSmoothSubtract::showDialog(QFitsMainWindow *parent) {
    imRedSmoothSubtract *dialog = new imRedSmoothSubtract(parent);
    dialog->show();
}

void imRedSmoothSubtract::accepted() {
    QString cmd;
    int methodid = methodButtonGroup->checkedId();
    if (newBufferButton->isChecked()) {
        cmd = QString(freeBufferName().c_str()) + " = " +
              QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " - ";
    } else {
        cmd = QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " -= ";
    }
    if (methodid == 1) {
        cmd += "smooth(";
    } else {
        cmd += "boxcar(";
    }
    cmd += QString(fitsMainWindow->getCurrentBufferIndex().c_str());
    cmd += ", ";
    if (methodid == 1) {
        cmd += fwhm->text();
    } else {
        cmd += QString::number(fwhm->text().toInt());
    }
    if (methodid == 3) {
        cmd += ", /median";
    }
    cmd += ")";

    dpuser_widget->executeCommand(cmd);

    delete this;
}

imRedWien::imRedWien(QFitsMainWindow *parent) : imRedGeneric(parent) {
    action = "wien";

    QStringList buffList;
    for (auto var:dpuser_vars) {
        if (var.second.type == typeFits) {
            buffList += QString(var.first.c_str());
        }
    }

    QLabel *labelPsf = new QLabel("Point Spread Function:");
    QLabel *labelHeight = new QLabel("Height:");

    psf = new QComboBox();
    psf->insertItems(0, buffList);
    psf->setCurrentIndex(0);
    psf->setFocus();

    factor = new QLineEdit();
    factor->setText("1.0");
    factor->setValidator(new QDoubleValidator(factor));

    QGridLayout *gridLayout = new QGridLayout();
    gridLayout->addWidget(labelPsf, 0, 0);
    gridLayout->addWidget(psf, 0, 1);
    gridLayout->addWidget(labelHeight, 1, 0);
    gridLayout->addWidget(factor, 1, 1);
    mainLayout->addLayout(gridLayout);

    setTabOrder(psf, factor);

    addButtons(factor);    
}

void imRedWien::showDialog(QFitsMainWindow *parent) {
    imRedWien *dialog = new imRedWien(parent);
    dialog->show();
}

void imRedWien::accepted() {
    QString cmd;
    if (newBufferButton->isChecked()) {
        cmd = freeBufferName().c_str();
    } else  {
        cmd = fitsMainWindow->getCurrentBufferIndex().c_str();
    }
    cmd += " = wien(" + QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + ", ";
    cmd += psf->currentText() + ", ";
    cmd += saveConvert(factor->text());
    cmd += ")";

    dpuser_widget->executeCommand(cmd);

    delete this;
}

imRedLucy::imRedLucy(QFitsMainWindow *parent) : imRedGeneric(parent) {
    action = "lucy";

    QStringList buffList;
    for (auto var:dpuser_vars) {
        if (var.second.type == typeFits) {
            buffList += QString(var.first.c_str());
        }
    }

    QLabel *labelPsf = new QLabel("Point Spread Function:");
    QLabel *labelIter = new QLabel("Number of iterations:");
    QLabel *labelThresh = new QLabel("Threshold:");

    psf = new QComboBox();
    psf->insertItems(0, buffList);
    psf->setCurrentIndex(0);
    psf->setFocus();

    niter = new QSpinBox();
    niter->setMinimum(1);
    niter->setMaximum(10000000);
    niter->setValue(100);

    thresh = new QLineEdit();
    thresh->setText("0.000003");
    thresh->setValidator(new QDoubleValidator(thresh));

    QGridLayout *gridLayout = new QGridLayout();
    gridLayout->addWidget(labelPsf, 0, 0);
    gridLayout->addWidget(psf, 0, 1);
    gridLayout->addWidget(labelIter, 1, 0);
    gridLayout->addWidget(niter, 1, 1);
    gridLayout->addWidget(labelThresh, 2, 0);
    gridLayout->addWidget(thresh, 2, 1);
    mainLayout->addLayout(gridLayout);

    setTabOrder(psf, niter);
    setTabOrder(niter, thresh);

    addButtons(thresh);    
}

void imRedLucy::showDialog(QFitsMainWindow *parent) {
    imRedLucy *dialog = new imRedLucy(parent);
    dialog->show();
}

void imRedLucy::accepted() {
    QString cmd;
    if (newBufferButton->isChecked()) {
        cmd = freeBufferName().c_str();
    } else {
        cmd = fitsMainWindow->getCurrentBufferIndex().c_str();
    }
    cmd += " = lucy(" + QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + ", ";
    cmd += psf->currentText() + ", ";
    cmd += niter->text();
    if (thresh->isModified()) {
        cmd += ", " + saveConvert(thresh->text());
    }
    cmd += ")";

    dpuser_widget->executeCommand(cmd);

    delete this;
}

imRedVelmap::imRedVelmap(QFitsMainWindow *parent) : imRedGeneric(parent) {
    action = "velmap";

    QLabel *labelCentral = new QLabel("Central Wavelength:");
    QLabel *labelFwhm = new QLabel("FWHM:");
    QLabel *labelFlux = new QLabel("Flux threshold (in % of max):");

    center = new QLineEdit();
    center->setText("2.1661");
    center->setValidator(new QDoubleValidator(center));
    center->setFocus();

    fwhm = new QLineEdit();
    fwhm->setText("0.001");
    fwhm->setValidator(new QDoubleValidator(fwhm));

    thresh = new QLineEdit();
    thresh->setText("1.0");
    thresh->setValidator(new QDoubleValidator(thresh));

    QGridLayout *gridLayout = new QGridLayout();
    gridLayout->addWidget(labelCentral, 0, 0);
    gridLayout->addWidget(center, 0, 1);
    gridLayout->addWidget(labelFwhm, 1, 0);
    gridLayout->addWidget(fwhm, 1, 1);
    gridLayout->addWidget(labelFlux, 2, 0);
    gridLayout->addWidget(thresh, 2, 1);
    mainLayout->addLayout(gridLayout);

    method1Button = new QRadioButton("Gaussfit");
    method1Button->setChecked(true);
    method2Button = new QRadioButton("Centroid");

    methodButtonGroup = new QButtonGroup();
    methodButtonGroup->addButton(method1Button, 1);
    methodButtonGroup->addButton(method2Button, 2);
    QGroupBox *groupMethod = new QGroupBox();
    groupMethod->setTitle("Method");
    QVBoxLayout *vboxMethod = new QVBoxLayout(groupMethod);
    vboxMethod->addWidget(method1Button);
    vboxMethod->addWidget(method2Button);
    mainLayout->addWidget(groupMethod);

    setTabOrder(center, fwhm);
    setTabOrder(fwhm, thresh);
    setTabOrder(thresh, groupMethod);

    addButtons(groupMethod);
    newBufferButton->setChecked(true);
}

void imRedVelmap::showDialog(QFitsMainWindow *parent) {
    imRedVelmap *dialog = new imRedVelmap(parent);
    dialog->show();
}

void imRedVelmap::accepted() {
    QString cmd;
    int methodid = methodButtonGroup->checkedId();
    if (newBufferButton->isChecked()){
        cmd = freeBufferName().c_str();
    } else {
        cmd = fitsMainWindow->getCurrentBufferIndex().c_str();
    }
    cmd += " = velmap(" + QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + ", ";
    cmd += saveConvert(center->text()) + ", ";
    cmd += saveConvert(fwhm->text()) + ",";
    cmd += saveConvert(thresh->text());
    if (methodid == 2) {
        cmd += ", /centroid";
    }
    cmd += ")";
    dpuser_widget->executeCommand(cmd);

    delete this;
}

imRedEvalVelmap::imRedEvalVelmap(QFitsMainWindow *parent) : imRedGeneric(parent) {
    action = "evalvelmap";

    QStringList buffList;
    for (auto var:dpuser_vars) {
        if (var.second.type == typeFits) {
            buffList += QString(var.first.c_str());
        }
    }

    QLabel *labelData = new QLabel("Original data:");
    QLabel *labelVel = new QLabel("velocity map:");

    data = new QComboBox();
    data->insertItems(0, buffList);
    data->setCurrentIndex(0);
    data->setFocus();

    velmap = new QComboBox();
    velmap->insertItems(0, buffList);
    velmap->setCurrentIndex(0);

    QGridLayout *gridLayout = new QGridLayout();
    gridLayout->addWidget(labelData, 0, 0);
    gridLayout->addWidget(data, 0, 1);
    gridLayout->addWidget(labelVel, 1, 0);
    gridLayout->addWidget(velmap, 1, 1);
    mainLayout->addLayout(gridLayout);

    setTabOrder(data, velmap);

    addButtons(velmap);
    newBufferButton->setChecked(true);
}

void imRedEvalVelmap::showDialog(QFitsMainWindow *parent) {
    imRedEvalVelmap *dialog = new imRedEvalVelmap(parent);
    dialog->show();
}

void imRedEvalVelmap::accepted() {
    QString cmd;
    if (newBufferButton->isChecked()) {
        cmd = freeBufferName().c_str();
    } else {
        cmd = fitsMainWindow->getCurrentBufferIndex().c_str();
    }
    cmd += " = evalvelmap(" + velmap->currentText() + ", ";
    cmd += data->currentText() + ")";

    dpuser_widget->executeCommand(cmd);

    delete this;
}

imRedCorrmap::imRedCorrmap(QFitsMainWindow *parent) : imRedGeneric(parent) {
    action = "correlmap";

    QStringList buffList;
    for (auto var:dpuser_vars) {
        if (var.second.type == typeFits) {
            buffList += QString(var.first.c_str());
        }
    }

    QLabel *labelSpec = new QLabel("Template spectrum:");

    templateSpec = new QComboBox();
    templateSpec->insertItems(0, buffList);
    templateSpec->setCurrentIndex(0);
    templateSpec->setFocus();

    QHBoxLayout *layout = new QHBoxLayout();
    layout->addWidget(labelSpec);
    layout->addWidget(templateSpec);
    mainLayout->addLayout(layout);

    addButtons(templateSpec);
    newBufferButton->setChecked(true);
}

void imRedCorrmap::showDialog(QFitsMainWindow *parent) {
    imRedCorrmap *dialog = new imRedCorrmap(parent);
    dialog->show();
}

void imRedCorrmap::accepted() {
    QString cmd;
    if (newBufferButton->isChecked()) {
        cmd = freeBufferName().c_str();
    } else {
        cmd = fitsMainWindow->getCurrentBufferIndex().c_str();
    }
    cmd += " = correlmap(" + QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + ", ";
    cmd += templateSpec->currentText() + ")";

    dpuser_widget->executeCommand(cmd);

    delete this;
}

imRedLongslit::imRedLongslit(QFitsMainWindow *parent) : imRedGeneric(parent) {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if ((sb != NULL) &&
        (sb->getDpData()->type == typeFits) &&
        (sb->getDpData()->fvalue != NULL))
    {
        Fits *f = sb->getDpData()->fvalue;
        is3D = (f->Naxis(3) > 1);
        if (is3D) {
            action = "longslit";
        } else {
            action = "twodcut";
        }

        QLabel *labelCenter = new QLabel("Center:");
        QLabel *labelAngle = new QLabel("Angle:");
        QLabel *labelWidth = new QLabel("Width:");
        QLabel *labelOpening = new QLabel("Opening Angle:");

        xcenter = new QSpinBox();
        xcenter->setMinimum(1);
        xcenter->setMaximum(f->Naxis(1));
        xcenter->setValue(f->Naxis(1) / 2);
        xcenter->selectAll();
        xcenter->setFocus();
        ycenter = new QSpinBox();
        ycenter->setMinimum(1);
        ycenter->setMaximum(f->Naxis(2));
        ycenter->setValue(f->Naxis(2) / 2);
        angle = new QLineEdit();
        angle->setText("0.0");
        angle->setValidator(new QDoubleValidator(angle));
        zeroDeg = new QPushButton("0.0");
        ninetyDeg = new QPushButton("90.0");
        slitwidth = new QSpinBox();
        slitwidth->setMinimum(1);
        slitwidth->setMaximum(f->Naxis(1));
        slitwidth->setValue(1);
        opening_angle = new QDoubleSpinBox();
        opening_angle->setMinimum(0.0);
        opening_angle->setMaximum(90.0);

        QGridLayout *gridLayout = new QGridLayout();
        gridLayout->addWidget(labelCenter, 0, 0);
        gridLayout->addWidget(xcenter, 0, 1);
        gridLayout->addWidget(ycenter, 0, 2);
        gridLayout->addItem(new QSpacerItem(100, 10, QSizePolicy::Expanding, QSizePolicy::Expanding), 0, 3);
        gridLayout->setColumnStretch(3, 999);
        gridLayout->addWidget(labelAngle, 1, 0);
        gridLayout->addWidget(angle, 1, 1);
        QHBoxLayout *layout = new QHBoxLayout();
        layout->addWidget(zeroDeg);
        layout->addWidget(ninetyDeg);
        gridLayout->addLayout(layout, 1, 2);
        gridLayout->addWidget(labelWidth, 2, 0);
        gridLayout->addWidget(slitwidth, 2, 1);
        gridLayout->addWidget(labelOpening, 3, 0);
        gridLayout->addWidget(opening_angle, 3, 1);
        mainLayout->addLayout(gridLayout);

        connect(zeroDeg, SIGNAL(pressed()),
                this, SLOT(zeroDegPressed()));
        connect(ninetyDeg, SIGNAL(pressed()),
                this, SLOT(ninetyDegPressed()));

        setTabOrder(xcenter, ycenter);
        setTabOrder(ycenter, angle);
        setTabOrder(angle, slitwidth);
        setTabOrder(slitwidth, opening_angle);

        if (is3D) {
            addButtons(opening_angle);
            plotarea = NULL;
        } else {
            plotarea = new QCustomPlot(this);
            plotarea->addGraph();
            plotarea->graph(0)->setAntialiased(false);
            plotarea->graph(0)->setLineStyle(QCPGraph::lsLine);
            plotarea->setInteraction(QCP::iRangeDrag);
            plotarea->setInteraction(QCP::iRangeZoom);
            QPen pen;
            pen.setWidth(1);
            pen.setColor(QColor(0, 0, 0));
            plotarea->graph(0)->setPen(pen);
            mainLayout->addWidget(plotarea, 4);
            addButtons(plotarea);
            setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
        }
        newBufferButton->setChecked(true);

        if (!is3D) {
            opening_angle->hide();
            labelOpening->hide();
        }
    }
}

void imRedLongslit::angleChanged(double value) {
    angle->setText(QString::number(value));
}

void imRedLongslit::centerChanged(int x, int y) {
    xcenter->setValue(x);
    ycenter->setValue(y);
}

void imRedLongslit::zeroDegPressed() {
    angleChanged(0.0);
}

void imRedLongslit::ninetyDegPressed() {
    angleChanged(90.0);
}

void imRedLongslit::opening_angleChanged(double value) {
    opening_angle->setValue(value);
}

void imRedLongslit::showDialog(QFitsMainWindow *parent) {
    imRedLongslit *dialog = new imRedLongslit(parent);
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
    connect(dialog->xcenter, SIGNAL(valueChanged(const QString &)),
            dialog, SLOT(someValueChanged(const QString &)));
    connect(dialog->ycenter, SIGNAL(valueChanged(const QString &)),
            dialog, SLOT(someValueChanged(const QString &)));
    connect(dialog->slitwidth, SIGNAL(valueChanged(const QString &)),
            dialog, SLOT(someValueChanged(const QString &)));
    connect(dialog->opening_angle, SIGNAL(valueChanged(const QString &)),
            dialog, SLOT(someValueChanged(const QString &)));
#else
    connect(dialog->xcenter, SIGNAL(textChanged(const QString &)),
            dialog, SLOT(someValueChanged(const QString &)));
    connect(dialog->ycenter, SIGNAL(textChanged(const QString &)),
            dialog, SLOT(someValueChanged(const QString &)));
    connect(dialog->slitwidth, SIGNAL(textChanged(const QString &)),
            dialog, SLOT(someValueChanged(const QString &)));
    connect(dialog->opening_angle, SIGNAL(textChanged(const QString &)),
            dialog, SLOT(someValueChanged(const QString &)));
#endif
    connect(dialog->angle, SIGNAL(textChanged(const QString &)),
            dialog, SLOT(someValueChanged(const QString &)));
    connect(dialog, SIGNAL(longslitChangedValues(int, int, double, int, double)),
            parent, SLOT(longslitChangedValues(int, int, double, int, double)));
    connect(parent, SIGNAL(longslitCenterChanged(int, int)),
            dialog, SLOT(centerChanged(int, int)));
    connect(parent, SIGNAL(longslitAngleChanged(double)),
            dialog, SLOT(angleChanged(double)));
    dialog->someValueChanged("");
    dialog->show();
}

void imRedLongslit::accepted() {
    emit longslitChangedValues(0, 0, 0.0, -1, 0.0);

    QString cmd;
    if (newBufferButton->isChecked()) {
        cmd = freeBufferName().c_str();
    } else {
        cmd = fitsMainWindow->getCurrentBufferIndex().c_str();
    }
    if (is3D) {
        cmd += " = longslit(" + QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + ", ";
    } else {
        cmd += " = twodcut(" + QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + ", ";
    }
    cmd += xcenter->text() + ", ";
    cmd += ycenter->text() + ", ";
    cmd += saveConvert(angle->text()) + ", ";
    cmd += slitwidth->text();
    if (opening_angle->value() != 0.0) cmd += ", " + opening_angle->text();
    cmd += + ")";

    dpuser_widget->executeCommand(cmd);

    delete this;
}

void imRedLongslit::reject() {
    emit longslitChangedValues(0, 0, 0.0, -1, 0.0);

    delete this;
}

void imRedLongslit::someValueChanged(const QString &v) {
    emit longslitChangedValues(xcenter->value(),
                               ycenter->value(),
                               angle->text().toDouble(),
                               slitwidth->value(),
                               opening_angle->value());

    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if ((sb != NULL) &&
        (sb->getDpData()->type == typeFits) &&
        (sb->getDpData()->fvalue != NULL) &&
        (sb->getDpData()->fvalue->Naxis(0) == 2)) {
        Fits *f = sb->getDpData()->fvalue;
        double c_angle = cos(angle->text().toDouble() * M_PI / 180.);
        double s_angle = sin(angle->text().toDouble() * M_PI / 180.);
        double xr, yr;
        int maxsize = (int)sqrt(f->Naxis(1)*f->Naxis(1)+f->Naxis(2)*f->Naxis(2))+1;
        QVector<double>xx(maxsize), data(maxsize);

/*
        Fits mask;
        mask.create(maxsize, maxsize, I1);
*/
        int i = 0;
        for (int y = 2*maxsize; y > -maxsize; y--) {
            xr = /*-xcenter->value() * c_angle*/ - (y - ycenter->value()) * s_angle + xcenter->value() - 0.5;
            yr = /*-1. * s_angle*/ - (y - ycenter->value()) * c_angle + ycenter->value() - 0.5;
            if (xr >= 0 && xr < f->Naxis(1) && yr >= 0 && yr < f->Naxis(2)) {
                xx[i] = i;
                data[i] = f->ValueAt(f->C_I(xr, yr));
                if (slitwidth->value() > 1) {
                    for (int j = 1; j <= (slitwidth->value() - 1) / 2; j++) {
                        data[i] += f->ValueAt(f->C_I(xr+j*c_angle, yr+j*s_angle));
                        data[i] += f->ValueAt(f->C_I(xr-j*c_angle, yr-j*s_angle));
                    }
                    if (slitwidth->value() % 2 == 0) {
                        data[i] += f->ValueAt(f->C_I(xr+(slitwidth->value() / 2)*c_angle, yr+(slitwidth->value() / 2)*s_angle)) / 2.;
                        data[i] += f->ValueAt(f->C_I(xr-(slitwidth->value() / 2)*c_angle, yr-(slitwidth->value() / 2)*s_angle)) / 2.;
                    }
                }
                i++;
            }
//            if (xr >= 0 && xr < maxsize && yr >= 0 && yr < maxsize) mask.i1data[mask.C_I(xr, yr)] = 1;
        }
/*
        mask.WriteFITS("/tmp/mask.fits");
*/
        plotarea->graph(0)->setData(xx, data);
        plotarea->xAxis->rescale();
        plotarea->yAxis->rescale();
        plotarea->replot();
    }
}

imRedEllipticalProfile::imRedEllipticalProfile(QFitsMainWindow *parent) : imRedGeneric(parent) {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if ((sb != NULL) &&
        (sb->getDpData()->type == typeFits) &&
        (sb->getDpData()->fvalue != NULL))
    {
        Fits *f = sb->getDpData()->fvalue;
        action = "ellipticalprofile";

        QLabel *label1 = new QLabel("Center:");
        QLabel *label2 = new QLabel("Angle:");
        QLabel *label3 = new QLabel("Aspect Ratio:");
        QLabel *label4 = new QLabel("Width:");

        xcenter = new QSpinBox();
        xcenter->setMinimum(1);
        xcenter->setMaximum(f->Naxis(1));
        xcenter->setValue(f->Naxis(1) / 2);
        xcenter->selectAll();
        xcenter->setFocus();

        ycenter = new QSpinBox();
        ycenter->setMinimum(1);
        ycenter->setMaximum(f->Naxis(2));
        ycenter->setValue(f->Naxis(2) / 2);

        angle = new QDoubleSpinBox();
        angle->setValue(0.0);
        angle->setMaximum(360);
        angle->setMinimum(-360);

        ratio = new QLineEdit();
        ratio->setText("0.5");
        ratio->setValidator(new QDoubleValidator(ratio));

        slitwidth = new QSpinBox();
        slitwidth->setMinimum(1);
        slitwidth->setMaximum(f->Naxis(1));
        slitwidth->setValue(1);

        QGridLayout *gridLayout = new QGridLayout();
        gridLayout->addWidget(label1, 0, 0);
        QHBoxLayout *layout = new QHBoxLayout();
        layout->addWidget(xcenter);
        layout->addWidget(ycenter);
        gridLayout->addLayout(layout, 0, 1);
        gridLayout->addWidget(label2, 1, 0);
        gridLayout->addWidget(angle, 1, 1);
        gridLayout->addWidget(label3, 2, 0);
        gridLayout->addWidget(ratio, 2, 1);
        gridLayout->addWidget(label4, 3, 0);
        gridLayout->addWidget(slitwidth, 3, 1);
        mainLayout->addLayout(gridLayout);

        setTabOrder(xcenter, ycenter);
        setTabOrder(ycenter, angle);
        setTabOrder(angle, ratio);
        setTabOrder(ratio, slitwidth);

        addButtons(slitwidth);
        newBufferButton->setChecked(true);
    }
}

void imRedEllipticalProfile::angleChanged(double value) {
    angle->setValue(-value+360);
}

void imRedEllipticalProfile::ratioChanged(double value) {
    ratio->setText(QString::number(value));
}

void imRedEllipticalProfile::centerChanged(int x, int y) {
    xcenter->setValue(x);
    ycenter->setValue(y);
}

void imRedEllipticalProfile::showDialog(QFitsMainWindow *parent) {
    imRedEllipticalProfile *dialog = new imRedEllipticalProfile(parent);
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
    connect(dialog->xcenter, SIGNAL(valueChanged(const QString &)),
            dialog, SLOT(someValueChanged(const QString &)));
    connect(dialog->ycenter, SIGNAL(valueChanged(const QString &)),
            dialog, SLOT(someValueChanged(const QString &)));
    connect(dialog->slitwidth, SIGNAL(valueChanged(const QString &)),
            dialog, SLOT(someValueChanged(const QString &)));
    connect(dialog->angle, SIGNAL(valueChanged(const QString &)),
            dialog, SLOT(someValueChanged(const QString &)));
#else
    connect(dialog->xcenter, SIGNAL(textChanged(const QString &)),
            dialog, SLOT(someValueChanged(const QString &)));
    connect(dialog->ycenter, SIGNAL(textChanged(const QString &)),
            dialog, SLOT(someValueChanged(const QString &)));
    connect(dialog->slitwidth, SIGNAL(textChanged(const QString &)),
            dialog, SLOT(someValueChanged(const QString &)));
    connect(dialog->angle, SIGNAL(textChanged(const QString &)),
            dialog, SLOT(someValueChanged(const QString &)));
#endif
    connect(dialog->ratio, SIGNAL(textChanged(const QString &)),
            dialog, SLOT(someValueChanged(const QString &)));
    connect(dialog, SIGNAL(ellipticalProfileChangedValues(int, int, double, double, int)),
            parent, SLOT(ellipticalProfileChangedValues(int, int, double, double, int)));
    connect(parent, SIGNAL(longslitCenterChanged(int, int)),
            dialog, SLOT(centerChanged(int, int)));
    connect(parent, SIGNAL(longslitAngleChanged(double)),
            dialog, SLOT(angleChanged(double)));
    dialog->someValueChanged("");
    dialog->show();
}

void imRedEllipticalProfile::accepted() {
    emit ellipticalProfileChangedValues(0, 0, 0.0, 0.0, -1);

    QString cmd;
    if (newBufferButton->isChecked()) {
        cmd = freeBufferName().c_str();
    } else {
        cmd = fitsMainWindow->getCurrentBufferIndex().c_str();
    }
    cmd += " = ellipticalprofile(" +
           QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + ", ";
    cmd += xcenter->text() + ", ";
    cmd += ycenter->text() + ", ";
    cmd += saveConvert(angle->text()) + ", ";
    cmd += saveConvert(ratio->text()) + ", ";
    cmd += slitwidth->text() + ")";

    dpuser_widget->executeCommand(cmd);

    delete this;
}

void imRedEllipticalProfile::reject() {
    emit ellipticalProfileChangedValues(0, 0, 0.0, 0.0, -1);

    delete this;
}

void imRedEllipticalProfile::someValueChanged(const QString &v) {
    emit ellipticalProfileChangedValues(xcenter->value(), ycenter->value(),
                                        angle->value(), ratio->text().toDouble(),
                                        slitwidth->value());
}

imRedMarkpos::imRedMarkpos(QFitsMainWindow *parent) : QWidget(dynamic_cast<QWidget*>(parent)) {
    QLabel *label1 = new QLabel("Radius:");

    radius = new QSpinBox();
    radius->setMinimum(0);
    radius->setMaximum(9999);
    radius->setValue(5);
    radius->selectAll();
    radius->setFocus();

    QGridLayout *gridLayout = new QGridLayout();
    gridLayout->addWidget(label1, 0, 0);
    gridLayout->addWidget(radius, 0, 1);

    method0Button = new QRadioButton("Pixel");
    method1Button = new QRadioButton("Center");
    method1Button->setChecked(true);
    method2Button = new QRadioButton("Centroid");
    method3Button = new QRadioButton("Gaussfit");

    methodButtonGroup = new QButtonGroup();
    methodButtonGroup->addButton(method0Button, 1);
    methodButtonGroup->addButton(method1Button, 2);
    methodButtonGroup->addButton(method2Button, 3);
    methodButtonGroup->addButton(method3Button, 4);
    QGroupBox *groupMethod = new QGroupBox();
    groupMethod->setTitle("Method");
    QVBoxLayout *vboxMethod = new QVBoxLayout(groupMethod);
    vboxMethod->addWidget(method0Button);
    vboxMethod->addWidget(method1Button);
    vboxMethod->addWidget(method2Button);
    vboxMethod->addWidget(method3Button);
    gridLayout->addWidget(groupMethod, 1, 0, 1, 2);

    positionsTable = new QTableWidget(0, 2, this);
    QStringList titles;
    titles.append("x");
    titles.append("y");
    positionsTable->setHorizontalHeaderLabels(titles);
    positionsTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);

    gridLayout->addWidget(positionsTable, 2, 0, 1, 2);

//    setTabOrder(radius, method0Button);

    createButton = new QPushButton("new buffer from values", this);
    gridLayout->addWidget(createButton, 3, 0, 1, 2);

    setLayout(gridLayout);

//    addButtons(method3Button);
//    newBufferButton->setChecked(true);
    connect(parent, SIGNAL(markPosition(int, int)),
            this, SLOT(newPosition(int, int)));
    connect(this, SIGNAL(markposChangedValues(QVector<int>)),
            parent, SLOT(markposChangedValues(QVector<int>)));
    connect(methodButtonGroup, SIGNAL(buttonClicked(QAbstractButton *)), this, SLOT(updateMethod()));
    connect(radius, SIGNAL(valueChanged(int)), this, SLOT(updateMethod()));
    connect(createButton, SIGNAL(clicked()),
            this, SLOT(createBufferFromValues()));

    Qt::WindowFlags flags = windowFlags();
    flags |= Qt::WindowStaysOnTopHint;
    setWindowFlags(flags);
}

void imRedMarkpos::show() {
//    currentBufferLabel->setText("<b>Current buffer is:</b>  " +
//                                QString(fitsMainWindow->getCurrentBufferIndex().c_str()));
    positions[fitsMainWindow->getCurrentBufferIndex()].clear();
    positionsTable->clear();
    positionsTable->setRowCount(0);
    emit markposChangedValues(positions[fitsMainWindow->getCurrentBufferIndex()]);
    move(0, 0);
    if (dpusermutex->tryLock()) {         // Standalone
        dpusermutex->unlock();
        method0Button->setEnabled(true);
        method1Button->setEnabled(true);
        method2Button->setEnabled(true);
        method3Button->setEnabled(true);
    } else {                              // called from dpuser function markpos
        method0Button->setEnabled(false);
        method1Button->setEnabled(false);
        method2Button->setEnabled(false);
        method3Button->setEnabled(false);
    }
    QWidget::show();

    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if (sb != NULL)
        sb->getQFitsWidget2D()->viewer->setMarkposDrawMode(true);
}

void imRedMarkpos::newPosition(int x, int y) {
    positions[fitsMainWindow->getCurrentBufferIndex()].append(x);
    positions[fitsMainWindow->getCurrentBufferIndex()].append(y);

    positionsTable->setRowCount(positionsTable->rowCount() + 1);

    QTableWidgetItem *xItem, *yItem;
    if (method0Button->isChecked()) {
        xItem = new QTableWidgetItem(QString::number(x));
        yItem = new QTableWidgetItem(QString::number(y));
    } else {
        QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
        if ((sb != NULL) &&
            (sb->getDpData()->type == typeFits) &&
            (sb->getDpData()->fvalue != NULL)) {
                Fits *f = sb->getDpData()->fvalue;
                Fits clickedpos, result;
                clickedpos.create(2, 1, I4);
                clickedpos.i4data[0] = x;
                clickedpos.i4data[1] = y;

                if (method1Button->isChecked()) {
                    f->maxima(clickedpos, radius->value());
                    xItem = new QTableWidgetItem(QString::number((int)clickedpos.ValueAt(0)));
                    yItem = new QTableWidgetItem(QString::number((int)clickedpos.ValueAt(1)));
                } else if (method2Button->isChecked()) {
                    f->centroids(result, clickedpos, radius->value());
                    xItem = new QTableWidgetItem(QString::number(result.ValueAt(0)));
                    yItem = new QTableWidgetItem(QString::number(result.ValueAt(1)));
                } else if (method3Button->isChecked()) {
                    if (gauss2dsimplefit(result, *f, x, y, radius->value()) > 0.0) {
                        xItem = new QTableWidgetItem(QString::number(result.ValueAt(2)));
                        yItem = new QTableWidgetItem(QString::number(result.ValueAt(3)));
                    } else {
                        xItem = new QTableWidgetItem(QString::number(x));
                        yItem = new QTableWidgetItem(QString::number(y));
                    }
                }
        }
    }
    xItem->setFlags(Qt::NoItemFlags);
    positionsTable->setItem(positionsTable->rowCount() - 1, 0, xItem);
    yItem->setFlags(Qt::NoItemFlags);
    positionsTable->setItem(positionsTable->rowCount() - 1, 1, yItem);

    positionsTable->scrollToBottom();

    QWidget::show();

    emit markposChangedValues(positions[fitsMainWindow->getCurrentBufferIndex()]);
}

void imRedMarkpos::clearValues() {
    positionsTable->clear();
    positionsTable->setRowCount(0);
    positions[fitsMainWindow->getCurrentBufferIndex()].clear();
}

void imRedMarkpos::setMethod(int method) {
    if (method == 0) method0Button->setChecked(true);
    if (method & 1) method1Button->setChecked(true);
    if (method & 2) method2Button->setChecked(true);
    if (method & 4) method3Button->setChecked(true);
}

void imRedMarkpos::updateMethod() {
    positionsTable->clear();

    positionsTable->setRowCount(positions[fitsMainWindow->getCurrentBufferIndex()].size() / 2);

    int method = methodButtonGroup->checkedId();
    for (int i = 0; i < positions[fitsMainWindow->getCurrentBufferIndex()].size(); i += 2) {
        int x = positions[fitsMainWindow->getCurrentBufferIndex()].at(i);
        int y = positions[fitsMainWindow->getCurrentBufferIndex()].at(i+1);
        QTableWidgetItem *xItem, *yItem;
        if (method == 1) {
            xItem = new QTableWidgetItem(QString::number(x));
            yItem = new QTableWidgetItem(QString::number(y));
        } else {
            QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
            if ((sb != NULL) &&
                (sb->getDpData()->type == typeFits) &&
                (sb->getDpData()->fvalue != NULL)) {
                    Fits *f = sb->getDpData()->fvalue;
                    Fits clickedpos, result;
                    clickedpos.create(2, 1, I4);
                    clickedpos.i4data[0] = x;
                    clickedpos.i4data[1] = y;

                    if (method == 2) {
                        f->maxima(clickedpos, radius->value());
                        xItem = new QTableWidgetItem(QString::number((int)clickedpos.ValueAt(0)));
                        yItem = new QTableWidgetItem(QString::number((int)clickedpos.ValueAt(1)));
                    } else if (method == 3) {
                        f->centroids(result, clickedpos, radius->value());
                        xItem = new QTableWidgetItem(QString::number(result.ValueAt(0)));
                        yItem = new QTableWidgetItem(QString::number(result.ValueAt(1)));
                    } else if (method == 4) {
                        if (gauss2dsimplefit(result, *f, x, y, radius->value()) > 0.0) {
                            xItem = new QTableWidgetItem(QString::number(result.ValueAt(2)));
                            yItem = new QTableWidgetItem(QString::number(result.ValueAt(3)));
                        } else {
                            xItem = new QTableWidgetItem(QString::number(x));
                            yItem = new QTableWidgetItem(QString::number(y));
                        }
                    }
            }
        }
        xItem->setFlags(Qt::NoItemFlags);
        positionsTable->setItem(i / 2, 0, xItem);
        yItem->setFlags(Qt::NoItemFlags);
        positionsTable->setItem(i / 2, 1, yItem);
    }

    positionsTable->scrollToBottom();
}

void imRedMarkpos::createBufferFromValues() {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if (sb != NULL)
        sb->getQFitsWidget2D()->viewer->setMarkposDrawMode(false);
    if (dpusermutex->tryLock()) {
        QString cmd, bufName;
//        if (newBufferButton->isChecked()) {
            bufName = freeBufferName().c_str();
//        } else {
//            bufName = fitsMainWindow->getCurrentBufferIndex().c_str();
//        }
        cmd = bufName;
        cmd += " = ";
        if (method1Button->isChecked()) {
            cmd += "maxima(";
            cmd += fitsMainWindow->getCurrentBufferIndex().c_str();
            cmd += ",";
        } else if (method2Button->isChecked()) {
                cmd += "centroids(";
                cmd += fitsMainWindow->getCurrentBufferIndex().c_str();
                cmd += ",";
        } else if (method3Button->isChecked()) {
            cmd += "gausspos(";
            cmd += fitsMainWindow->getCurrentBufferIndex().c_str();
            cmd += ",";
        }
        if (positions[fitsMainWindow->getCurrentBufferIndex()].size() > 2) cmd += "[";
        for (int i = 0; i < positions[fitsMainWindow->getCurrentBufferIndex()].size(); i += 2) {
            cmd += "[";
            cmd += QString::number(positions[fitsMainWindow->getCurrentBufferIndex()].at(i));
            cmd += ",";
            cmd += QString::number(positions[fitsMainWindow->getCurrentBufferIndex()].at(i+1));
            cmd += "]";
            if (i < positions[fitsMainWindow->getCurrentBufferIndex()].size() - 2) cmd += ",";
        }
        if (positions[fitsMainWindow->getCurrentBufferIndex()].size() > 2) cmd += "]";
        if (method1Button->isChecked() || method2Button->isChecked() || method3Button->isChecked()) {
            cmd += ",";
            cmd += radius->text();
            cmd += ")";
        }
        cmd += "; setfitstype " + bufName + ", /bintable";

        dpuser_widget->executeCommand(cmd);
    } else {
        markposBuffer->create(2, positions[fitsMainWindow->getCurrentBufferIndex()].size() / 2, I4);
        for (int i = 0; i < positions[fitsMainWindow->getCurrentBufferIndex()].size(); i++) markposBuffer->i4data[i] = positions[fitsMainWindow->getCurrentBufferIndex()].at(i);
        QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
        if ((sb != NULL) &&
            (sb->getDpData()->type == typeFits) &&
            (sb->getDpData()->fvalue != NULL)) {
                Fits *f = sb->getDpData()->fvalue;
                if (method1Button->isChecked()) {
                    f->maxima(*markposBuffer, radius->value());
                } else if (method2Button->isChecked()) {
                    Fits centroids;
                    f->centroids(centroids, *markposBuffer, radius->value());
                    markposBuffer->copy(centroids);

                } else if (method3Button->isChecked()) {
                    Fits gaussians;
                    f->gausspos(gaussians, *markposBuffer, radius->value());
                    markposBuffer->copy(gaussians);
                }
        }
        markposBuffer->extensionType = BINTABLE;
    }

    dpusermutex->unlock();
    positionsTable->clear();
    positionsTable->setRowCount(0);
    positions[fitsMainWindow->getCurrentBufferIndex()].clear();
    emit markposChangedValues(positions[fitsMainWindow->getCurrentBufferIndex()]);

    hide();
}

//void imRedMarkpos::reject() {
////    emit ellipticalProfileChangedValues(0, 0, 0.0, 0.0, -1);
//    dpusermutex->tryLock();
//    dpusermutex->unlock();
//    positions[svariables[fitsMainWindow->getCurrentBufferIndex()]].clear();
//    emit markposChangedValues(positions[svariables[fitsMainWindow->getCurrentBufferIndex()]]);

//    hide();
//}

imRedVoronoi::imRedVoronoi(QFitsMainWindow *parent) : imRedGeneric(parent) {
    action = "voronoi";

    QStringList buffList;
    for (auto var:dpuser_vars) {
        if (var.second.type == typeFits) {
            buffList += QString(var.first.c_str());
        }
    }

    QLabel *label1 = new QLabel("Signal map:");
    QLabel *label2 = new QLabel("Noise map:");
    QLabel *label3 = new QLabel("Target S/N:");
    QLabel *label4 = new QLabel("Apply to:");

    signal = new QComboBox();
    signal->insertItems(0, buffList);
    signal->adjustSize();
    signal->setCurrentIndex(0);
    signal->setFocus();

    noise = new QComboBox();
    noise->insertItems(0, buffList);
    noise->adjustSize();
    noise->setCurrentIndex(0);

    targetSN = new QLineEdit();
    targetSN->setText("20");
    targetSN->setValidator(new QDoubleValidator(targetSN));

    target = new QComboBox();
    target->insertItems(0, buffList);
    target->adjustSize();
    target->setCurrentIndex(0);

    QGridLayout *gridLayout = new QGridLayout();
    gridLayout->addWidget(label1, 0, 0);
    gridLayout->addWidget(signal, 0, 1);
    gridLayout->addWidget(label2, 1, 0);
    gridLayout->addWidget(noise, 1, 1);
    gridLayout->addWidget(label3, 2, 0);
    gridLayout->addWidget(targetSN, 2, 1);
    gridLayout->addWidget(label4, 3, 0);
    gridLayout->addWidget(target, 3, 1);
    mainLayout->addLayout(gridLayout);

    setTabOrder(signal, noise);
    setTabOrder(noise, targetSN);
    setTabOrder(targetSN, target);

    addButtons(target);    
}

void imRedVoronoi::showDialog(QFitsMainWindow *parent) {
    imRedVoronoi *dialog = new imRedVoronoi(parent);
    dialog->show();
}

void imRedVoronoi::accepted() {
    QString cmd;
    if (newBufferButton->isChecked()) {
        cmd = freeBufferName().c_str();
    } else {
        cmd = fitsMainWindow->getCurrentBufferIndex().c_str();
    }
    cmd += " = voronoi(";
    cmd += signal->currentText() + ", ";
    cmd += noise->currentText() + ", ";
    cmd += target->currentText() + ", ";
    cmd += saveConvert(targetSN->text()) + ")";

    dpuser_widget->executeCommand(cmd);

    delete this;
}

imRedSetWCS::imRedSetWCS(QFitsMainWindow *parent) : imRedGeneric(parent) {
    QFitsSingleBuffer *sb = fitsMainWindow->getActualSB();
    if ((sb != NULL) &&
        (sb->getDpData()->type == typeFits) &&
        (sb->getDpData()->fvalue !=NULL))
    {
        Fits *f = sb->getDpData()->fvalue;
        action = "setwcs";

        QLabel *label1a = new QLabel("CRPIX1");
        QLabel *label1b = new QLabel("CRVAL1");
        QLabel *label1c = new QLabel("CDELT1");
        QLabel *label2a = new QLabel("CRPIX2");
        QLabel *label2b = new QLabel("CRVAL2");
        QLabel *label2c = new QLabel("CDELT2");
        QLabel *label3a = new QLabel("CRPIX3");
        QLabel *label3b = new QLabel("CRVAL3");
        QLabel *label3c = new QLabel("CDELT3");

        crpix1 = new QLineEdit();
        crpix1->setText(QString::number(f->getCRPIX(1)));
        crpix1->setValidator(new QDoubleValidator(crpix1));
        crpix1->selectAll();
        crpix1->setFocus();
        crval1 = new QLineEdit();
        crval1->setText(QString::number(f->getCRVAL(1)));
        crval1->setValidator(new QDoubleValidator(crval1));
        cdelt1 = new QLineEdit();
        cdelt1->setText(QString::number(f->getCDELT(1)));
        cdelt1->setValidator(new QDoubleValidator(cdelt1));

        crpix2 = new QLineEdit();
        crpix2->setText(QString::number(f->getCRPIX(2)));
        crpix2->setValidator(new QDoubleValidator(crpix2));
        crval2 = new QLineEdit();
        crval2->setText(QString::number(f->getCRVAL(2)));
        crval2->setValidator(new QDoubleValidator(crval2));
        cdelt2 = new QLineEdit();
        cdelt2->setText(QString::number(f->getCDELT(2)));
        cdelt2->setValidator(new QDoubleValidator(cdelt2));

        crpix3 = new QLineEdit();
        crpix3->setText(QString::number(f->getCRPIX(3)));
        crpix3->setValidator(new QDoubleValidator(crpix3));
        crval3 = new QLineEdit();
        crval3->setText(QString::number(f->getCRVAL(3)));
        crval3->setValidator(new QDoubleValidator(crval3));
        cdelt3 = new QLineEdit();
        cdelt3->setText(QString::number(f->getCDELT(3)));
        cdelt3->setValidator(new QDoubleValidator(cdelt3));

        QGridLayout *gridLayout = new QGridLayout();
        gridLayout->addWidget(label1a, 0, 0);
        gridLayout->addWidget(crpix1, 0, 1);
        gridLayout->addWidget(label1b, 0, 2);
        gridLayout->addWidget(crval1, 0, 3);
        gridLayout->addWidget(label1c, 0, 4);
        gridLayout->addWidget(cdelt1, 0, 5);

        gridLayout->addWidget(label2a, 1, 0);
        gridLayout->addWidget(crpix2, 1, 1);
        gridLayout->addWidget(label2b, 1, 2);
        gridLayout->addWidget(crval2, 1, 3);
        gridLayout->addWidget(label2c, 1, 4);
        gridLayout->addWidget(cdelt2, 1, 5);

        gridLayout->addWidget(label3a, 2, 0);
        gridLayout->addWidget(crpix3, 2, 1);
        gridLayout->addWidget(label3b, 2, 2);
        gridLayout->addWidget(crval3, 2, 3);
        gridLayout->addWidget(label3c, 2, 4);
        gridLayout->addWidget(cdelt3, 2, 5);
        mainLayout->addLayout(gridLayout);

        is3D = (f->Naxis(3) > 1);
        is2D = (f->Naxis(2) > 1);
        if (!is3D) {
            crpix3->setEnabled(false);
            crval3->setEnabled(false);
            cdelt3->setEnabled(false);
            label3a->setEnabled(false);
            label3b->setEnabled(false);
            label3c->setEnabled(false);
        }
        if (!is2D) {
            crpix2->setEnabled(false);
            crval2->setEnabled(false);
            cdelt2->setEnabled(false);
            label2a->setEnabled(false);
            label2b->setEnabled(false);
            label2c->setEnabled(false);
        }

        setTabOrder(crpix1, crval1);
        setTabOrder(crval1, cdelt1);
        setTabOrder(cdelt1, crpix2);
        setTabOrder(crpix2, crval2);
        setTabOrder(crval2, cdelt2);
        setTabOrder(cdelt2, crpix3);
        setTabOrder(crpix3, crval3);
        setTabOrder(crval3, cdelt3);

        addButtons(cdelt3, false, false);
    }
}

void imRedSetWCS::showDialog(QFitsMainWindow *parent) {
    imRedSetWCS *dialog = new imRedSetWCS(parent);
    dialog->setModal(true);
    dialog->show();
}

void imRedSetWCS::accepted() {
    QString cmd;
    if (crpix1->isModified() || crval1->isModified() || cdelt1->isModified() ||
        crpix2->isModified() || crval2->isModified() || cdelt2->isModified())
        dpuser_widget->executeCommand("setwcs " +
                                      QString(fitsMainWindow->getCurrentBufferIndex().c_str()) +
                                      ", " + crpix1->text() + ", " + crpix2->text() +
                                      ", " + crval1->text() + ", " + crval2->text() +
                                      ", " + cdelt1->text() + ", " + cdelt2->text());

    if (crpix3->isModified()) {
        dpuser_widget->executeCommand("setfitskey " +
                                      QString(fitsMainWindow->getCurrentBufferIndex().c_str()) +
                                      ", \"CRPIX3\", " + crpix3->text());
    }
    if (crval3->isModified()) {
        dpuser_widget->executeCommand("setfitskey " +
                                      QString(fitsMainWindow->getCurrentBufferIndex().c_str()) +
                                      ", \"CRVAL3\", " + crval3->text());
    }
    if (cdelt3->isModified()) {
        dpuser_widget->executeCommand("setfitskey " +
                                      QString(fitsMainWindow->getCurrentBufferIndex().c_str()) +
                                      ", \"CD3_3\", " + cdelt3->text());
    }

    delete this;
}

imRedArithImage::imRedArithImage(QFitsMainWindow *parent) : imRedGeneric(parent) {
    action = "arithmetics";

    QStringList buffList;
    for (auto var:dpuser_vars) {
        if (var.second.type == typeFits) {
            buffList += QString(var.first.c_str());
        }
    }

    QLabel *label1 = new QLabel("Operation:");
    QLabel *label2 = new QLabel("Operand:");

    oper = new QComboBox();
    oper->insertItem(0, "add");
    oper->insertItem(1, "subtract");
    oper->insertItem(2, "multiply");
    oper->insertItem(3, "divide");
    oper->insertItem(4, "power");
    oper->insertItem(5, "convolve");
    oper->insertItem(6, "matrix multiply");
    oper->setFocus();

    operand = new QComboBox();
    operand->insertItems(0, buffList);
    operand->setCurrentIndex(0);

    QGridLayout *gridLayout = new QGridLayout();
    gridLayout->addWidget(label1, 0, 0);
    gridLayout->addWidget(oper, 0, 1);
    gridLayout->addWidget(label2, 1, 0);
    gridLayout->addWidget(operand, 1, 1);
    mainLayout->addLayout(gridLayout);

    setTabOrder(oper, operand);

    addButtons(operand, false);
}

void imRedArithImage::showDialog(QFitsMainWindow *parent) {
    imRedArithImage *dialog = new imRedArithImage(parent);
    dialog->show();
}

void imRedArithImage::accepted() {
    QString cmd = fitsMainWindow->getCurrentBufferIndex().c_str();
    switch (oper->currentIndex()) {
        case 0:
            if (newBufferButton->isChecked()) {
                cmd = QString(freeBufferName().c_str()) + " = " +
                      QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " + " +
                      operand->currentText();
            } else {
                cmd = QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " += " +
                      operand->currentText();
            }
            break;
        case 1:
            if (newBufferButton->isChecked()) {
                cmd = QString(freeBufferName().c_str()) + " = " +
                      QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " - " +
                      operand->currentText();
            } else {
                cmd = QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " -= " +
                      operand->currentText();
            }
            break;
        case 2:
            if (newBufferButton->isChecked()) {
                cmd = QString(freeBufferName().c_str()) + " = " +
                      QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " * " +
                      operand->currentText();
            } else {
                cmd = QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " *= " +
                      operand->currentText();
            }
            break;
        case 3:
            if (newBufferButton->isChecked()) {
                cmd = QString(freeBufferName().c_str()) + " = " +
                      QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " / " +
                      operand->currentText();
            } else {
                cmd = QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " /= " +
                      operand->currentText();
            }
            break;
        case 4:
            if (newBufferButton->isChecked()) {
                cmd = freeBufferName().c_str();
            } else {
                cmd = fitsMainWindow->getCurrentBufferIndex().c_str();

            }
            cmd += " = " + QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " ^ " +
                   operand->currentText();
            break;
        case 5:
            if (newBufferButton->isChecked()) {
                cmd = freeBufferName().c_str();
            } else {
                cmd = fitsMainWindow->getCurrentBufferIndex().c_str();
            }
            cmd += " = convolve(" + QString(fitsMainWindow->getCurrentBufferIndex().c_str()) +
                   ", " + operand->currentText() + ")";
            break;
        case 6:
            if (newBufferButton->isChecked()) {
                cmd = freeBufferName().c_str();
            } else {
                cmd = fitsMainWindow->getCurrentBufferIndex().c_str();
            }
            cmd += " = " + QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " # " +
                   operand->currentText();
            break;
        default:
            cmd = "";
            break;
    }

    dpuser_widget->executeCommand(cmd);

    delete this;
}

imRedArithNumber::imRedArithNumber(QFitsMainWindow *parent) : imRedGeneric(parent) {
    action = "arithmetics";

    QLabel *label1 = new QLabel("Operation:");
    QLabel *label2 = new QLabel("Operand:");

    oper = new QComboBox();
    oper->insertItem(0, "add");
    oper->insertItem(1, "subtract");
    oper->insertItem(2, "multiply");
    oper->insertItem(3, "divide");
    oper->insertItem(4, "power");
    oper->setFocus();

    operand = new QLineEdit();
    operand->setText("0.0");
    operand->setValidator(new QDoubleValidator(operand));

    QGridLayout *gridLayout = new QGridLayout();
    gridLayout->addWidget(label1, 0, 0);
    gridLayout->addWidget(oper, 0, 1);
    gridLayout->addWidget(label2, 1, 0);
    gridLayout->addWidget(operand, 1, 1);
    mainLayout->addLayout(gridLayout);

    setTabOrder(oper, operand);

    addButtons(operand, false);
}

void imRedArithNumber::showDialog(QFitsMainWindow *parent) {
    imRedArithNumber *dialog = new imRedArithNumber(parent);
    dialog->show();
}

void imRedArithNumber::accepted() {
    QString cmd, value;
	
    if (newBufferButton->isChecked()) {
       cmd = QString(freeBufferName().c_str()) + " = " +
             QString(fitsMainWindow->getCurrentBufferIndex().c_str());
   } else {
        cmd = fitsMainWindow->getCurrentBufferIndex().c_str();
    }
    value = saveConvert(operand->text());
    switch (oper->currentIndex()) {
        case 0:
            if (newBufferButton->isChecked()) {
                cmd = QString(freeBufferName().c_str()) + " = " +
                      QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " + " + value;
            } else {
                cmd = QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " += " + value;
            }
            break;
        case 1:
            if (newBufferButton->isChecked()) {
                cmd = QString(freeBufferName().c_str()) + " = " +
                      QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " - " + value;
            } else {
                cmd = QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " -= " + value;
            }
            break;
        case 2:
            if (newBufferButton->isChecked()) {
                cmd = QString(freeBufferName().c_str()) + " = " +
                      QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " * " + value;
            } else {
                cmd = QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " *= " + value;
            }
            break;
        case 3:
            if (newBufferButton->isChecked()) {
                cmd = QString(freeBufferName().c_str()) + " = " +
                      QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " / " + value;
            } else {
                cmd = QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " /= " + value;
            }
            break;
        case 4:
            if (newBufferButton->isChecked()) {
                cmd = QString(freeBufferName().c_str()) + " = " +
                      QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " ^ " + value;
            } else {
                cmd = QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " = " +
                      QString(fitsMainWindow->getCurrentBufferIndex().c_str()) + " ^ " + value;
            }
            break;
        default:
            cmd = "";
            break;
    }

    dpuser_widget->executeCommand(cmd);

    delete this;
}
