/***************************** LICENSE START ***********************************

 Copyright 2013 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#include "MvQEditor.h"

#include <QtGlobal>
#include <QAction>
#include <QActionGroup>
#include <QApplication>
#include <QCloseEvent>
#include <QDateTime>
#include <QDebug>
#include <QDialogButtonBox>
#include <QDrag>
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QPainter>
#include <QPlainTextEdit>
#include <QPushButton>
#include <QSettings>
#include <QStyle>
#include <QStyleOption>
#include <QStackedLayout>
#include <QStackedWidget>
#include <QToolBar>
#include <QToolButton>
#include <QVBoxLayout>

#include "EditorDrawerFactory.h"
#include "Folder.h"
#include "IconClass.h"
#include "MvRequest.h"
#include "Path.h"
#include "Request.h"

#include "MvQEditorDrawerPanel.h"
#include "MvQFolderModel.h"
#include "MvQTemplateDrawer.h"
#include "MvQIconProvider.h"
#include "MvQTheme.h"
#include "MvQMethods.h"
#include "MvQIconMimeData.h"
#include "MessageLabel.h"

//#define DEBUG_MV_MVQEDITOR__

//===========================
//
// MvQEditorDragLabel
//
//===========================

MvQEditorDragLabel::MvQEditorDragLabel(QPixmap pix, int maxHeight, QWidget* parent) :
    QLabel(parent),
    oriPix_(pix)
{
    setPixmap(oriPix_);
    setFrameShape(QFrame::Box);
    setFrameShape(QFrame::StyledPanel);
    setObjectName(QString::fromUtf8("editorHeaderIcon"));
    setMaximumHeight(maxHeight);
    setMouseTracking(true);

    highlightPix_ = pix;
    QPainter painter(&highlightPix_);
    QPen pen = MvQTheme::pen("iconeditor", "drag_label_border");
    pen.setWidth(2);
    painter.setPen(pen);
    painter.drawRect(QRect(0, 0,
                           highlightPix_.width(), highlightPix_.height())
                         .adjusted(1, 1, -1, -1));
}

void MvQEditorDragLabel::setIconObject(IconObject* obj)
{
    obj_ = obj;
}

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void MvQEditorDragLabel::enterEvent(QEnterEvent* event)
#else
void MvQEditorDragLabel::enterEvent(QEvent* event)
#endif
{
    setPixmap(highlightPix_);
    QLabel::enterEvent(event);
}

void MvQEditorDragLabel::leaveEvent(QEvent* event)
{
    setPixmap(oriPix_);
    QLabel::leaveEvent(event);
}

void MvQEditorDragLabel::mousePressEvent(QMouseEvent* event)
{
    if (!obj_) {
        QLabel::mousePressEvent(event);
        return;
    }

    canDrag_ = false;
    if (event->button() == Qt::LeftButton) {
        startPos_ = event->pos();
        canDrag_  = true;
    }

    QLabel::mousePressEvent(event);
}

void MvQEditorDragLabel::mouseMoveEvent(QMouseEvent* event)
{
    if (obj_ && canDrag_ && event->buttons() & Qt::LeftButton) {
        int distance = (event->pos() - startPos_).manhattanLength();
        if (distance >= QApplication::startDragDistance()) {
            canDrag_ = false;
            performDrag(Qt::CopyAction, event->pos());
        }
        return;
    }

    QLabel::mouseMoveEvent(event);
}

void MvQEditorDragLabel::performDrag(Qt::DropAction dropAction, QPoint scenePos)
{
    if (obj_) {
        QDrag* drag = buildDrag(obj_, scenePos);
        if (drag) {
            emit dragStarted();
            //We always initiate a copy action
            drag->exec(Qt::CopyAction, dropAction);
        }
        else {
            qDebug() << "MvQEditorDragLabel::performDrag -> Could not build drag object!!!";
        }
    }

    canDrag_ = false;
}

QDrag* MvQEditorDragLabel::buildDrag(IconObject* dragObj, QPoint /*dragPos*/)
{
    if (dragObj) {
        auto* drag = new QDrag(this);

        //Hotspot is the bottom right corner of the dragged object's pixmap
        //we overwrite it if dragPos is null!! We use normalised coordinates
        QPointF hotSpotInPix(1, 1);

        //It has to have as many elements as there are in objLst
        QList<QPoint> pixDistanceLst;
        //QPointF hotSpotInPix=0.;

        drag->setPixmap(oriPix_);

        QList<IconObject*> objLst;
        objLst << dragObj;

        //Create and set drag mime data
        auto* mimeData = new MvQIconMimeData(nullptr,
                                             dragObj, hotSpotInPix,
                                             objLst, pixDistanceLst);

        mimeData->setFromEditor(true);
        mimeData->setFromHelper(false);
        drag->setMimeData(mimeData);

        return drag;
    }

    return nullptr;
}

//================================================
//
// MvQEditorHeader
//
//================================================

MvQEditorHeader::MvQEditorHeader(MvQEditor* owner, QPixmap pix) :
    QWidget(owner),
    owner_(owner)
{
    auto* hb = new QHBoxLayout(this);
    hb->setSpacing(0);
    hb->setContentsMargins(0, 0, 0, 0);

    QFont font;
    font.setBold(true);
    QFontMetrics fm(font);
    int txth = 3 * fm.height() + 2 * fm.leading() + 8;
    txth     = (txth > 32) ? txth : 32;

    //Pixmap label - can be dragged into a plot window
    pixLabel_ = new MvQEditorDragLabel(pix, txth, this);
    hb->addWidget(pixLabel_);

    connect(pixLabel_, SIGNAL(dragStarted()),
            owner_, SLOT(save()));

    stackLayout_ = new QStackedLayout();
    hb->addLayout(stackLayout_);

    //Info panel
    auto* w       = new QWidget;
    auto* labelHb = new QHBoxLayout(w);
    labelHb->setSpacing(0);
    labelHb->setContentsMargins(2, 1, 2, 1);
    stackLayout_->addWidget(w);

    label_ = new QLabel("", this);
    // label_->setObjectName(QString::fromUtf8("editorHeaderLabel"));
    label_->setProperty("type", "info");
    label_->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    label_->setAutoFillBackground(true);
    label_->setTextInteractionFlags(Qt::LinksAccessibleByMouse | Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse);
    label_->setFrameShape(QFrame::Box);
    label_->setFrameShape(QFrame::StyledPanel);
    label_->setMargin(2);
    label_->setMaximumHeight(txth);
    labelHb->addWidget(label_);

    renameTb_ = new QToolButton(this);
    renameTb_->setAutoRaise(true);
    //renameTb_->setText(tr("Rename"));
    renameTb_->setToolTip(tr("Click to rename icon"));
    renameTb_->setIcon(QPixmap(QString::fromUtf8(":/desktop/edit.svg")));
    labelHb->addWidget(renameTb_);

    connect(renameTb_, SIGNAL(clicked(bool)),
            this, SLOT(slotStartEdit(bool)));

    //Editor
    w            = new QWidget;
    auto* editHb = new QHBoxLayout(w);
    editHb->setSpacing(0);
    editHb->setContentsMargins(2, 1, 2, 1);
    stackLayout_->addWidget(w);

    edit_ = new QLineEdit(this);
    editHb->addWidget(edit_);

    //Rename buttonBox_

    auto* acceptTb = new QToolButton(this);
    acceptTb->setAutoRaise(true);
    acceptTb->setIcon(QPixmap(QString::fromUtf8(":/desktop/accept.svg")));
    editHb->addWidget(acceptTb);

    auto* cancelTb = new QToolButton(this);
    cancelTb->setAutoRaise(true);
    cancelTb->setIcon(QPixmap(QString::fromUtf8(":/desktop/cancel.svg")));
    editHb->addWidget(cancelTb);

    connect(acceptTb, SIGNAL(clicked(bool)),
            this, SLOT(slotAcceptEdit(bool)));

    connect(cancelTb, SIGNAL(clicked(bool)),
            this, SLOT(slotCancelEdit(bool)));

    setProperty("editor", "true");
}

void MvQEditorHeader::slotStartEdit(bool)
{
    if (stackLayout_->currentIndex() == 0) {
        stackLayout_->setCurrentIndex(1);
        if (owner_->current())
            edit_->setText(QString::fromStdString(owner_->current()->name()));
        else
            edit_->clear();
    }
}

void MvQEditorHeader::slotAcceptEdit(bool)
{
    if (stackLayout_->currentIndex() == 1) {
        owner_->rename(edit_->text());
        stackLayout_->setCurrentIndex(0);
    }
}

void MvQEditorHeader::slotCancelEdit(bool)
{
    if (stackLayout_->currentIndex() == 1) {
        stackLayout_->setCurrentIndex(0);
        edit_->clear();
    }
}

void MvQEditorHeader::updateLabel(IconObject* obj)
{
    if (!obj)
        return;

    auto subCol = MvQTheme::subText();
    QString str = MvQ::formatText("Icon name: ", subCol) + QString::fromStdString(obj->name()) + "<br>";
    str += MvQ::formatText("Folder: ", subCol);
    str += QString::fromStdString(obj->parent()->fullName()) + "<br>";
    str += MvQ::formatText("Type: ", subCol);
    str += QString::fromStdString(obj->className());

#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
    QDateTime dt;
    dt.setSecsSinceEpoch(obj->path().lastModified());
#else
    QDateTime dt = QDateTime::fromTime_t(obj->path().lastModified());
#endif
    str += MvQ::formatText(" Modified: ", subCol);
    str += dt.toString("yyyy-MM-dd hh:mm");

    if (obj->locked())
        str += MvQ::formatText(" Status: ", subCol) +
               MvQ::formatText("Read only", Qt::red);

    label_->setText(str);
    pixLabel_->setIconObject(obj);

    lock(obj->locked());
}

void MvQEditorHeader::lock(bool b)
{
    renameTb_->setEnabled(!b);
}

void MvQEditorHeader::paintEvent(QPaintEvent*)
{
    QStyleOption opt;
    opt.initFrom(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

//================================================
//
// MvQEditorTextPanel
//
//================================================

MvQEditorTextPanel::MvQEditorTextPanel(const IconClass& c, Editor* owner, QWidget* parent) :
    QWidget(parent),
    class_(c),
    owner_(owner)
{
    auto* vb = new QVBoxLayout;
    setLayout(vb);

    vb->setSpacing(0);
    vb->setContentsMargins(0, 0, 0, 0);

    //Warning label
    auto* warnLayout = new QHBoxLayout();
    vb->addLayout(warnLayout);

    warnLabel_ = new MessageLabel(this);
    warnLabel_->showWarning("This is the contents of the file storing your icon settings. Please only edit it at <b> your own <b>risk</b>!");
    warnLayout->addWidget(warnLabel_, 1);

    //Message label
    auto* msgLayout = new QHBoxLayout();
    vb->addLayout(msgLayout);

    msgLabel_ = new MessageLabel(this);
    msgLayout->addWidget(msgLabel_, 1);

    //Text editor
    te_ = new QPlainTextEdit(this);
    vb->addWidget(te_, 1);

    connect(te_, SIGNAL(textChanged()),
            this, SLOT(slotTextChanged()));
}

void MvQEditorTextPanel::setObject(IconObject* obj)
{
    current_ = obj;

    QString str = tr("This is the contents of the file storing your icon settings. ");

    if (obj->locked() || !obj->storedAsRequestFile()) {
        te_->setReadOnly(true);
    }
    else {
        te_->setReadOnly(false);
        str += tr("Please only edit it at <b> your own <b>risk</b>!");
    }

    te_->update();
    warnLabel_->showWarning(str);
}


void MvQEditorTextPanel::loadRequestFile()
{
    beingLoaded_ = true;
    QFile f(QString::fromStdString(current_->path().str()));
    if (f.open(QFile::ReadOnly | QFile::Text)) {
        QTextStream rs(&f);
        te_->setPlainText(rs.readAll());
    } else {
        te_->clear();
    }
    beingLoaded_ = false;
}

bool MvQEditorTextPanel::check(bool fromSave)
{
    if (!current_ || !current_->storedAsRequestFile()) {
        correct_ = true;
        return correct_;
    }

    QString s = te_->toPlainText();
    Request r = Request::fromText(s.toStdString());
    QString verb;

#ifdef DEBUG_MV_MVQEDITOR__
    qDebug() << "TEXT --->";
    r.print();
    qDebug() << "<--- TEXT";
#endif

    if (r)
        verb = QString(r.getVerb());

    QString ic = QString::fromStdString(current_->editorClass().name());
    //QString ic=QString::fromStdString(current_->iconClass().name());

    QString msg;
    bool failed = false;
    if (verb.compare(ic, Qt::CaseInsensitive) != 0) {
        msg = "Request type <b>" + verb + "</b> in text does not match icon type <b>" + ic + "</b>! ";
        msg += "Please change the request type to <b>" + ic + "</b> or revert the icon back to system defaults.";
        failed = true;
    }

    if (failed) {
        QString s;
        if (fromSave)
            s += "<u>Cannot save file!</u>";
        else
            s += "<u>Broken request!</u>";

        s += "<br>" + msg + "</td></tr></table>";
        msgLabel_->showError(s);
    }
    else {
        msgLabel_->clear();
        msgLabel_->hide();
    }

    correct_ = (!failed);

    return correct_;
}


void MvQEditorTextPanel::slotTextChanged()
{
    if (!beingLoaded_) {
        owner_->changed();
        msgLabel_->hide();
    }
}


void MvQEditorTextPanel::save()
{
    FILE* f = fopen(current_->path().str().c_str(), "w");
    if (f == nullptr) {
        //marslog(LOG_EROR|LOG_PERR,"%s",tmp);
        return;
    }
#ifdef DEBUG_MV_MVQEDITOR__
    qDebug() << te_->toPlainText() << current_->path().str().c_str();
#endif
    fprintf(f, "%s\n", te_->toPlainText().toStdString().c_str());
    fclose(f);
}

void MvQEditorTextPanel::load()
{
    loadRequestFile();
    check(false);
}

//================================================
//
// MvQEditor
//
//================================================

MvQEditor::MvQEditor(const IconClass& name, const std::string& kind, QWidget* parent) :
    QDialog(parent),
    Editor(name, kind)
{
    //Set Window icon
    setWindowIcon(MvQIconProvider::pixmap(name, 24));

    auto* vb = new QVBoxLayout;
    vb->setSpacing(0);
    vb->setContentsMargins(0, 0, 0, 0);
    setLayout(vb);

    //Header
    headerPanel_ = new MvQEditorHeader(this, MvQIconProvider::pixmap(name, 32));
    vb->addWidget(headerPanel_);


    //-------------------
    // Toolbar
    //-------------------

    toolBarLayout_ = new QHBoxLayout();
    toolBarLayout_->setSpacing(0);
    toolBarLayout_->setContentsMargins(0, 0, 0, 0);

    //Widget to provide bg for the toolbars
    auto* w = new QWidget(this);
    w->setProperty("editor", "true");
    w->setLayout(toolBarLayout_);
    vb->addWidget(w);

    toolbarLeft_ = new QToolBar(this);
    toolBarLayout_->addWidget(toolbarLeft_);

    toolbarRight_ = new QToolBar(w);
    toolBarLayout_->addWidget(toolbarRight_);

    auto* spacer = new QWidget(this);
    spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    sepAc_ = toolbarRight_->addWidget(spacer);

    toolBarLayout_->addWidget(toolbarRight_);
    toolBarLayout_->addWidget(toolbarRight_);

    //Gui edit
    guiAc_ = new QAction(this);
    guiAc_->setIcon(QPixmap(":/desktop/gui_edit.svg"));
    guiAc_->setCheckable(true);
    guiAc_->setToolTip(tr("<b>GUI</b> mode.<br> To switch between view modes changes have to be <u>saved<u>!"));
    toolbarRight_->addAction(guiAc_);

    //Text edit
    textAc_ = new QAction(this);
    textAc_->setIcon(QPixmap(":/desktop/text_edit.svg"));
    textAc_->setCheckable(true);
    textAc_->setToolTip(tr("<b>Text</b> mode.<br> To switch between view modes changes have to be <u>saved</u>!"));
    toolbarRight_->addAction(textAc_);

    viewAg_ = new QActionGroup(this);
    viewAg_->setExclusive(true);
    viewAg_->addAction(guiAc_);
    viewAg_->addAction(textAc_);

    guiAc_->setChecked(true);

    connect(viewAg_, SIGNAL(triggered(QAction*)),
            this, SLOT(slotChangeView(QAction*)));

    //Search
    //QSearchLine
    //QLabel
    //searchLine_=new QLineEdit(this);

    //toolBarLayout_->addStretch(1);

    //---------------------
    // Central part
    //---------------------

    viewSw_ = new QStackedWidget(this);
    vb->addWidget(viewSw_, 1);

    //Panel layout
    w              = new QWidget(this);
    centralLayout_ = new QVBoxLayout;
    centralLayout_->setSpacing(0);
    centralLayout_->setContentsMargins(1, 1, 1, 1);
    w->setLayout(centralLayout_);
    viewSw_->addWidget(w);

    //Text widget
    textPanel_ = new MvQEditorTextPanel(name, this, this);
    viewSw_->addWidget(textPanel_);
    viewSw_->addWidget(textPanel_);

    viewSw_->setCurrentIndex(0);

    //--------------------
    // Drawer
    //--------------------

    drawerPanel_ = new MvQEditorDrawerPanel(this);

    /*map<std::string, EditorDrawer*> drawers=EditorDrawerFactory::create(this);
	for(map<std::string, EditorDrawer*>::iterator j = drawers.begin();j != drawers.end(); ++j) 
	{
	  	drawerPanel_->addDrawer((*j).second->widget(),
						(*j).second->name());
	}*/

    vb->addWidget(drawerPanel_);

    drawerPanel_->shrink();

    //--------------------
    // Buttonbox
    //--------------------

    buttonBox_ = new QDialogButtonBox(this);

    savePb_   = buttonBox_->addButton(QDialogButtonBox::Save);
    okPb_     = buttonBox_->addButton(QDialogButtonBox::Ok);
    cancelPb_ = buttonBox_->addButton(QDialogButtonBox::Cancel);
    resetPb_  = buttonBox_->addButton(QDialogButtonBox::Reset);

    savePb_->setDefault(true);
    savePb_->setEnabled(false);
    resetPb_->setEnabled(false);

    /*QCheckBox* stayOpenCb= new QCheckBox(tr("Stay open"),this);
	stayOpenCb->setChecked(false);
	buttonBox_->addButton(stayOpenCb,QDialogButtonBox::YesRole);*/

    //buttonBox_->addButton(QDialogButtonBox::Close);

    connect(buttonBox_, SIGNAL(clicked(QAbstractButton*)),
            this, SLOT(slotButtonClicked(QAbstractButton*)));

    vb->addWidget(buttonBox_);

    // to ignore ESC key
    installEventFilter(this);
}


MvQEditor::~MvQEditor() = default;


bool MvQEditor::eventFilter(QObject* obj, QEvent* event)
{
    if (static_cast<MvQEditor*>(obj) == this &&
        event->type() == QEvent::KeyPress && ((QKeyEvent*)event)->key() == Qt::Key_Escape) {
        return true;
    }
    return false;
}


void MvQEditor::setupLineFilter()
{
    auto label = new QLabel(this);
    label->setPixmap(QPixmap(":/desktop/filter_decor.svg"));
    toolbarLeft_->insertWidget(nullptr, label);

    filterLe_ = new QLineEdit(this);
    filterLe_->setPlaceholderText("Filter ...");
#if QT_VERSION >= QT_VERSION_CHECK(5, 2, 0)
    filterLe_->setClearButtonEnabled(true);
#endif

    toolbarLeft_->insertWidget(nullptr, filterLe_);

    filterCountLabel_ = new QLabel(this);
    filterCountLabel_->setProperty("filterCount", "1");
    toolbarLeft_->insertWidget(nullptr, filterCountLabel_);

    connect(filterLe_, SIGNAL(textChanged(QString)),
            this, SLOT(slotFilterItems(QString)));
}

void MvQEditor::updateFilterCountLabel()
{
    if (filterLe_) {
        if (filterLe_->text().isEmpty()) {
            filterCountLabel_->clear();
        }
        else {
            int cnt = filterNonMatchCount();
            if (cnt == 0) {
                filterCountLabel_->clear();
            }
            else {
                filterCountLabel_->setText("(" + QString::number(cnt) + " hidden)");
            }
        }
    }
}

void MvQEditor::setupShowDisabledActions()
{
    showDisabledAc_ = new QAction(this);
    showDisabledAc_->setText(tr("Show disabled parameters"));
    showDisabledAc_->setCheckable(true);
    showDisabledAc_->setChecked(false);
    showDisabledAc_->setIcon(QPixmap(":/desktop/show_disabled.svg"));
    toolbarRight_->addAction(showDisabledAc_);

    MvRequest r = MvApplication::getExpandedPreferences();
    if (const char* c = r("SHOW_DISABLED_PARAMETERS_IN_ICON_EDITORS")) {
        if (strcmp(c, "ON") == 0)
            showDisabledAc_->setChecked(true);
    }

    connect(showDisabledAc_, SIGNAL(triggered(bool)),
            this, SLOT(slotShowDisabled(bool)));
}

bool MvQEditor::showDisabled() const
{
    return (showDisabledAc_) ? showDisabledAc_->isChecked() : false;
}

void MvQEditor::showIt()
{
    show();

    //Mimimize the drawer
    drawerPanel_->shrink();
}

void MvQEditor::addToToolBar(QList<QAction*> lst)
{
    toolbarRight_->insertActions(sepAc_, lst);
}

//Iconobserver method
void MvQEditor::iconChanged(IconObject* obj)
{
    if (obj == current_) {
        headerPanel_->updateLabel(current_);
        updateWindowTitle();
    }
}


void MvQEditor::changed()
{
    if (!temporary_ && !ignoreChange_) {
        savePb_->setEnabled(true);
        resetPb_->setEnabled(true);
        viewAg_->setEnabled(false);
        updateFilterCountLabel();
    }

    //resetPb_->setEnabled(true);
}

void MvQEditor::edit()
{
    if (!current_)
        return;

    //Set default button status
    savePb_->setEnabled(false);
    resetPb_->setEnabled(false);

    //Populate drawers if needed
    if (!drawerFilled_) {
        std::map<std::string, EditorDrawer*> drawers = EditorDrawerFactory::create(this);
        for (auto& drawer : drawers) {
            drawerPanel_->addDrawer(drawer.second->widget(),
                                    drawer.second->name());
        }
        drawerFilled_ = true;
    }

    //Read the previous size
    readSettings();

    //Header
    headerPanel_->updateLabel(current_);

    //Title
    updateWindowTitle();

    //Text
    textPanel_->setObject(current_);

    //If request is broken we switch to text mode
    if (!current_->checkRequest()) {
        textPanel_->load();
        viewAg_->setEnabled(false);
        textAc_->setChecked(true);
        slotChangeView(textAc_);
        //textAc_->toggled();
    }
    //otherwise we start with gui mode
    else {
        viewAg_->setEnabled(true);
        guiAc_->setChecked(true);
        slotChangeView(guiAc_);  // this will call reset
        viewAg_->setEnabled(true);
    }

    savePb_->setEnabled(false);
    resetPb_->setEnabled(false);

    okPb_->setEnabled(!current_->locked());
}

bool MvQEditor::isTextMode() const
{
    return (viewSw_->currentIndex() == TextViewMode);
}

void MvQEditor::slotTextChanged()
{
    changed();
}

void MvQEditor::save()
{
    slotButtonClicked(savePb_);
}

void MvQEditor::raiseIt()
{
    if (isMinimized())
        showNormal();

    raise();
}

void MvQEditor::closeIt()
{
    close();
    reject();
}

void MvQEditor::rename(QString text)
{
    if (!current_)
        return;

    if (!text.isEmpty()) {
        auto n = text.toStdString();
        if (n != current_->name()) {
            current_->editor(0);
            current_->rename(n);
            current_->editor(this);
        }
        headerPanel_->updateLabel(current_);
        updateWindowTitle();
    }
}

void MvQEditor::slotChangeView(QAction* ac)
{
    if (savePb_->isEnabled()) {
        viewAg_->setEnabled(false);
        return;
    }

    //From gui to text mode
    if (ac == textAc_) {
        viewSw_->setCurrentIndex(TextViewMode);
        ignoreChange_ = true;
        textPanel_->load();
        ignoreChange_ = false;
    }
    //From text to gui mode
    else {
        viewSw_->setCurrentIndex(LineViewMode);
        ignoreChange_ = true;
        reset();
        ignoreChange_ = false;
    }
}

void MvQEditor::slotButtonClicked(QAbstractButton* button)
{
    if (!button)
        return;

    if (buttonBox_->standardButton(button) == QDialogButtonBox::Cancel) {
        writeSettings();

        savePb_->setEnabled(false);
        resetPb_->setEnabled(false);

        close();
        reject();
    }
    else if (buttonBox_->standardButton(button) == QDialogButtonBox::Ok) {
        writeSettings();

        //Text mode
        if (isTextMode()) {
            if (textPanel_->check())
                textPanel_->save();
            else {
                viewAg_->setEnabled(false);
                return;
            }
        }
        //GUI mode
        else {
            ignoreChange_ = true;
            apply();
            ignoreChange_ = false;
        }

        current_->modified();
        notifyObserverApply();

        savePb_->setEnabled(false);
        resetPb_->setEnabled(false);

        close();
        accept();
    }
    else if (buttonBox_->standardButton(button) == QDialogButtonBox::Save) {
        ignoreChange_ = true;

        //Text mode
        if (isTextMode()) {
            if (textPanel_->check())
                textPanel_->save();
            else {
                viewAg_->setEnabled(false);
                return;
            }
        }
        //GUI mode
        else {
            ignoreChange_ = true;
            apply();
            ignoreChange_ = false;
        }

        current_->modified();
        notifyObserverApply();

        savePb_->setEnabled(false);
        resetPb_->setEnabled(false);
        viewAg_->setEnabled(true);
    }
    else if (buttonBox_->standardButton(button) == QDialogButtonBox::Reset) {
        //Text mode
        if (isTextMode())
            textPanel_->load();
        else {
            ignoreChange_ = true;
            reset();
            ignoreChange_ = false;
        }

        savePb_->setEnabled(false);
        resetPb_->setEnabled(false);
        viewAg_->setEnabled(true);
    }
}

void MvQEditor::accept()
{
    editDone();
    QDialog::accept();
}

void MvQEditor::reject()
{
    notifyObserverClose();
    editDone();
    QDialog::reject();
}

void MvQEditor::temporary()
{
    Editor::temporary();
    savePb_->setEnabled(false);
    viewAg_->setEnabled(false);
    headerPanel_->lock(true);
}

void MvQEditor::closeEvent(QCloseEvent* event)
{
    writeSettings();
    close();
    accept();
    event->accept();
}

void MvQEditor::updateWindowTitle()
{
    QString txt = QString::fromStdString(current_->name());
    if (current_->parent())
        txt += " - " + QString::fromStdString(current_->parent()->fullName());

    txt += " - Metview";
    setWindowTitle(txt);
}

void MvQEditor::writeSettings()
{
    QSettings settings(MVQ_QSETTINGS_DEFAULT_ARGS, "MV4-Desktop-Editor-" + QString::fromStdString(class_.name()));

    //We have to clear it so that should not remember all the previous values
    settings.clear();

    settings.beginGroup("main");
    settings.setValue("size", size());
    settings.endGroup();

    writeSettings(settings);
}

void MvQEditor::readSettings()
{
    QSettings settings(MVQ_QSETTINGS_DEFAULT_ARGS, "MV4-Desktop-Editor-" + QString::fromStdString(class_.name()));

    settings.beginGroup("main");
    if (settings.contains("size")) {
        resize(settings.value("size").toSize());
    }
    else {
        resize(QSize(520, 500));
    }

    settings.endGroup();

    readSettings(settings);
}
