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

 Copyright 2014 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 "MvQAdvancedSearch.h"

#include <QtGlobal>
#include <QAction>
#include <QCheckBox>
#include <QCloseEvent>
#include <QComboBox>
#include <QDateEdit>
#include <QDateTime>
#include <QDebug>
#include <QDialogButtonBox>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QMenu>
#include <QProgressBar>
#include <QPushButton>
#include <QRadioButton>
#include <QSettings>
#include <QSpinBox>
#include <QStackedLayout>
#include <QTabWidget>
#include <QToolButton>
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QVBoxLayout>

#include "MvQFileBrowser.h"
#include "MvQFind.h"
#include "MvQIconProvider.h"
#include "MvQLineEdit.h"
#include "MvQMethods.h"
#include "Folder.h"

MvQAdvancedSearchDialog* MvQAdvancedSearchDialog::dialog_ = nullptr;
QList<const IconClass*> MvQAdvancedSearchDialog::iconClasses_;

void MvQAdvancedSearchDialog::open(QWidget* callerWidget, Folder* folder)
{
    if (!dialog_) {
        dialog_ = new MvQAdvancedSearchDialog(callerWidget, folder);
        dialog_->show();
    }
    else {
        dialog_->raise();
    }
}

MvQAdvancedSearchDialog::MvQAdvancedSearchDialog(QWidget* callerWidget, Folder* folder) :
    QDialog(nullptr),
    caller_(callerWidget),
    finder_(nullptr)
{
    QString currentRelPath("/");

    if (folder)
        currentRelPath = QString::fromStdString(folder->fullName());

    setWindowTitle(tr("Advanced search - Metview"));
    setWindowIcon(QPixmap(":/desktop/search.svg"));
    setAttribute(Qt::WA_DeleteOnClose, true);

    auto* hb = new QHBoxLayout();
    hb->setSpacing(2);
    hb->setContentsMargins(4, 4, 4, 4);
    setLayout(hb);

    auto* leftVb = new QVBoxLayout;
    hb->addLayout(leftVb, 1);

    // Tabs
    auto* tab = new QTabWidget(this);
    leftVb->addWidget(tab);

    tab->addTab(buildMainTab(), tr("&Basic"));
    tab->addTab(buildContentsTab(), tr("&Contents"));
    tab->addTab(buildPropTab(), tr("&Properties"));

    // Some init
    folderLe_->setText(currentRelPath);

    // Results view
    resTree_ = new QTreeWidget(this);
    resTree_->setRootIsDecorated(false);
    resTree_->setUniformRowHeights(true);
    resTree_->setColumnCount(7);
    resTree_->setSortingEnabled(true);
    resTree_->setAlternatingRowColors(true);
    QStringList headers;
    headers << tr("Name") << tr("Folder") << tr("Type") << tr("Size") << tr("Date") << tr("Owner") << tr("Permissions");
    resTree_->setHeaderLabels(headers);
    leftVb->addWidget(resTree_, 1);

    // Context menu
    resTree_->setContextMenuPolicy(Qt::CustomContextMenu);

    connect(resTree_, SIGNAL(customContextMenuRequested(const QPoint&)),
            this, SLOT(slotContextMenu(const QPoint&)));

    //------------------
    // Buttons
    //------------------

    auto* buttonVb = new QVBoxLayout();
    hb->addLayout(buttonVb);

    findPb_ = new QPushButton(tr("Find"), this);
    // findPb_->setIcon(QPixmap(":/desktop/search.svg"));
    buttonVb->addWidget(findPb_);

    connect(findPb_, SIGNAL(clicked()),
            this, SLOT(slotFind()));

    cancelPb_ = new QPushButton(tr("Stop"), this);
    // cancelPb_->setIcon(QPixmap(":/desktop/stop.svg"));
    buttonVb->addWidget(cancelPb_);

    connect(cancelPb_, SIGNAL(clicked()),
            this, SLOT(slotCancel()));

    buttonVb->addStretch(1);

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

    auto* buttonBox = new QDialogButtonBox(this);
    buttonVb->addWidget(buttonBox);

    buttonBox->addButton(QDialogButtonBox::Close);
    connect(buttonBox, SIGNAL(rejected()),
            this, SLOT(reject()));

    //-------------------
    // Status
    //-------------------

    auto* statusHb = new QHBoxLayout();
    leftVb->addLayout(statusHb);

    findProgress_ = new QProgressBar;
    statusHb->addWidget(findProgress_);
    findProgress_->hide();

    statusMessageLabel_ = new QLabel("");
    // statusMessageLabel_->setTextInteractionFlags(Qt::TextSelectableByMouse);
    statusMessageLabel_->setFrameShape(QFrame::NoFrame);
    // messageLabel_->setMinimumSize(messageLabel_->sizeHint());
    statusHb->addWidget(statusMessageLabel_, 1);

    // Init
    findPb_->setEnabled(true);
    cancelPb_->setEnabled(false);

    // Populate type combo
    loadTypeCb();

    readSettings();
}

MvQAdvancedSearchDialog::~MvQAdvancedSearchDialog()
{
    dialog_ = nullptr;
}

QWidget* MvQAdvancedSearchDialog::buildMainTab()
{
    auto* gridLayout = new QGridLayout();

    gridLayout->setColumnStretch(1, 1);
    gridLayout->setColumnStretch(2, 1);
    gridLayout->setAlignment(Qt::AlignTop);

    auto* w = new QWidget(this);
    w->setLayout(gridLayout);

    int row = 0;

    int colSpan = 2;

    // Folder
    auto* label = new QLabel(tr("&Folder:"));
    folderLe_ = new MvQLineEdit(this);
    label->setBuddy(folderLe_);
    gridLayout->addWidget(label, row, 0);
    gridLayout->addWidget(folderLe_, row, 1, 1, colSpan);
    row++;

    subFolderCheck_ = new QCheckBox(tr("Include sub&folders"));
    gridLayout->addWidget(subFolderCheck_, row, 1);

    connect(subFolderCheck_, SIGNAL(stateChanged(int)),
            this, SLOT(slotUpdateFolderBox(int)));

    linkCheck_ = new QCheckBox(tr("Follow folder &links"));
    linkCheck_->setEnabled(false);
    gridLayout->addWidget(linkCheck_, row, 2);
    row++;

    sysCheck_ = new QCheckBox(tr("Include &system folders"));
    sysCheck_->setEnabled(false);
    gridLayout->addWidget(sysCheck_, row, 1);

    caseCheck_ = new QCheckBox(tr("&Case sensitive"));
    gridLayout->addWidget(caseCheck_, row, 2);
    row++;

    // Name
    label = new QLabel(tr("&Name:"));
    nameLe_ = new MvQLineEdit(this);
    label->setBuddy(nameLe_);
    gridLayout->addWidget(label, row, 0);
    gridLayout->addWidget(nameLe_, row, 1, 1, colSpan);
    row++;

    // Type
    label = new QLabel(tr("&Type:"));
    typeTextRb_ = new QRadioButton("Define by &text");
    typeListRb_ = new QRadioButton("Select from &list");
    label->setBuddy(typeTextRb_);

    gridLayout->addWidget(label, row, 0);
    gridLayout->addWidget(typeTextRb_, row, 1);
    gridLayout->addWidget(typeListRb_, row, 2);
    row++;

    typeStacked_ = new QStackedLayout();
    typeLe_ = new MvQLineEdit(this);
    typeStacked_->addWidget(typeLe_);
    typeCb_ = new QComboBox(this);
    typeStacked_->addWidget(typeCb_);

    typeCb_->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLengthWithIcon);
    typeCb_->setMinimumContentsLength(18);

    gridLayout->addLayout(typeStacked_, row, 1, 1, colSpan);
    row++;

    connect(typeTextRb_, SIGNAL(toggled(bool)),
            this, SLOT(slotTypeRadio(bool)));

    connect(typeListRb_, SIGNAL(toggled(bool)),
            this, SLOT(slotTypeRadio(bool)));

    // Init
    typeTextRb_->toggle();
    return w;
}


QWidget* MvQAdvancedSearchDialog::buildContentsTab()
{
    auto* gridLayout = new QGridLayout();
    gridLayout->setAlignment(Qt::AlignTop);

    gridLayout->setColumnStretch(1, 1);
    gridLayout->setAlignment(Qt::AlignTop);

    auto* w = new QWidget(this);
    w->setLayout(gridLayout);

    int row = 0;

    // Contains
    auto* label = new QLabel(tr("&Containing text:"));
    contLe_ = new MvQLineEdit(this);
    label->setBuddy(contLe_);
    gridLayout->addWidget(label, row, 0);
    gridLayout->addWidget(contLe_, row, 1);
    row++;

    contentsCaseCheck_ = new QCheckBox(tr("&Case sensitive"));
    gridLayout->addWidget(contentsCaseCheck_, row, 1);
    row++;

    return w;
}

QWidget* MvQAdvancedSearchDialog::buildPropTab()
{
    auto* gridLayout = new QGridLayout();

    gridLayout->setColumnStretch(2, 1);
    gridLayout->setColumnStretch(3, 1);
    gridLayout->setColumnStretch(4, 1);
    // gridLayout->setSpacing();

    auto* w = new QWidget(this);
    w->setLayout(gridLayout);

    int row = 0;

    // Date
    dateCheck_ = new QCheckBox(tr("&Modified:"));
    gridLayout->addWidget(dateCheck_, row, 0, 1, 5);
    dateCheck_->setChecked(true);
    row++;

    connect(dateCheck_, SIGNAL(stateChanged(int)),
            this, SLOT(slotUpdateDateBox(int)));

    // Period
    periodRb_ = new QRadioButton("&from");
    auto* label = new QLabel(tr("to"));
    fromDateE_ = new QDateEdit(QDate::currentDate(), this);
    toDateE_ = new QDateEdit(QDate::currentDate(), this);

    dateBoxTop_ << periodRb_ << label << fromDateE_ << toDateE_;

    fromDateE_->setMaximumDate(QDate::currentDate());
    toDateE_->setMaximumDate(QDate::currentDate());

    gridLayout->addWidget(periodRb_, row, 1);
    gridLayout->addWidget(fromDateE_, row, 2);
    gridLayout->addWidget(label, row, 3, Qt::AlignCenter);
    gridLayout->addWidget(toDateE_, row, 4);
    row++;

    // Duration
    durationRb_ = new QRadioButton("&during the last");
    durationSp_ = new QSpinBox(this);
    durationCb_ = new QComboBox(this);

    dateBoxBottom_ << durationRb_ << durationSp_ << durationCb_;

    durationSp_->setRange(1, 1000);

    durationCb_->addItem(tr("minutes"), 60);
    durationCb_->addItem(tr("hours"), 3600);
    durationCb_->addItem(tr("days"), 86400);
    durationCb_->addItem(tr("weeks"), 86400 * 7);
    durationCb_->addItem(tr("months"), 86400 * 30);
    durationCb_->addItem(tr("years"), 86400 * 365);

    gridLayout->addWidget(durationRb_, row, 1);
    gridLayout->addWidget(durationSp_, row, 2, 1, 2);
    gridLayout->addWidget(durationCb_, row, 4);
    row++;

    connect(periodRb_, SIGNAL(toggled(bool)),
            this, SLOT(slotDateRadio(bool)));

    connect(durationRb_, SIGNAL(toggled(bool)),
            this, SLOT(slotDateRadio(bool)));

    // Size
    label = new QLabel(tr("&Size:"));
    sizeOperCb_ = new QComboBox(this);
    sizeValSp_ = new QSpinBox(this);
    sizeUnitsCb_ = new QComboBox(this);
    label->setBuddy(sizeOperCb_);

    gridLayout->addWidget(label, row, 0, 1, 2);
    gridLayout->addWidget(sizeOperCb_, row, 2);
    gridLayout->addWidget(sizeValSp_, row, 3);
    gridLayout->addWidget(sizeUnitsCb_, row, 4);
    row++;

    sizeOperCb_->addItem(tr("(none)"), 5);
    sizeOperCb_->addItem(tr("Less than"), -1);
    sizeOperCb_->addItem(tr("Equal to"), 0);
    sizeOperCb_->addItem(tr("Greater than"), 1);

    sizeValSp_->setRange(1, 100000);

    sizeUnitsCb_->addItem(tr("Kb"), 1024);
    sizeUnitsCb_->addItem(tr("Mb"), 1024 * 1024);
    sizeUnitsCb_->addItem(tr("Gb"), 1024 * 1024 * 1024);


    connect(sizeOperCb_, SIGNAL(currentIndexChanged(int)),
            this, SLOT(slotUpdateSizeBox(int)));

    // Owner
    label = new QLabel(tr("&Owner:"));
    ownerLe_ = new MvQLineEdit(this);
    label->setBuddy(ownerLe_);
    gridLayout->addWidget(label, row, 0, 1, 2);
    gridLayout->addWidget(ownerLe_, row, 2);

    // group
    label = new QLabel(tr("&Group:"));
    groupLe_ = new MvQLineEdit(this);
    label->setBuddy(groupLe_);
    gridLayout->addWidget(label, row, 3);
    gridLayout->addWidget(groupLe_, row, 4);

    row++;


    // Init
    periodRb_->toggle();
    dateCheck_->setChecked(false);
    sizeOperCb_->setCurrentIndex(-1);
    sizeOperCb_->setCurrentIndex(0);

    return w;
}

void MvQAdvancedSearchDialog::reject()
{
    writeSettings();
    QDialog::reject();
}

void MvQAdvancedSearchDialog::slotFind()
{
    if (!finder_) {
        finder_ = new MvQFind(Folder::top()->path().str(), this);

        connect(finder_, SIGNAL(found(QString, QString)),
                this, SLOT(itemArrived(QString, QString)));

        connect(finder_, SIGNAL(started()),
                this, SLOT(findStarted()));

        connect(finder_, SIGNAL(finished()),
                this, SLOT(findFinished()));
    }

    resTree_->clear();

    FindOptions options;

    options.name = nameLe_->text().toStdString();

    if (typeTextRb_->isChecked()) {
        options.type = typeLe_->text().toLower().toStdString();
    }
    else {
        int idxT = 0;
        if ((idxT = typeCb_->currentIndex()) > 0) {
            options.type = typeCb_->itemData(idxT).toString().toStdString();
            options.strictType = true;
        }
    }

    options.contentText = contLe_->text().toStdString();
    options.contentCaseSensitive = contentsCaseCheck_->isChecked();

    options.includeSub = subFolderCheck_->isChecked();
    options.followLinks = (linkCheck_->isEnabled()) ? linkCheck_->isChecked() : false;
    options.includeSys = (sysCheck_->isEnabled()) ? sysCheck_->isChecked() : false;
    options.caseSensitive = caseCheck_->isChecked();

    // Date
    if (dateCheck_->isChecked()) {
        options.useTime = true;
        if (periodRb_->isChecked()) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
            QDateTime dt = fromDateE_->date().startOfDay();
#else
            QDateTime dt(fromDateE_->date());
#endif

#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
            options.fromTime = dt.toSecsSinceEpoch();
#else
            options.fromTime = dt.toTime_t();
#endif

#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
            dt = toDateE_->date().endOfDay();
#else
            dt = QDateTime(toDateE_->date());
            dt = dt.addSecs(86399);
#endif
#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
            options.toTime = dt.toSecsSinceEpoch();
#else
            options.toTime = dt.toTime_t();
#endif
        }
        else {
            QDateTime dt = QDateTime::currentDateTime();
            int v = durationSp_->value();
            int idxD = 0;
            if ((idxD = durationCb_->currentIndex()) > -1) {
                int unitSec = durationCb_->itemData(idxD).toInt();
#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
                options.toTime = dt.toSecsSinceEpoch();
                options.fromTime = dt.toSecsSinceEpoch() - static_cast<time_t>(unitSec * v);
#else
                options.toTime = dt.toTime_t();
                options.fromTime = dt.toTime_t() - static_cast<time_t>(unitSec * v);
#endif
            }
        }
    }

    // Size
    int idx = sizeOperCb_->currentIndex();
    if (idx > 0) {
        options.sizeOper = sizeOperCb_->itemData(idx).toInt();

        int idxU = 0;
        if ((idxU = sizeUnitsCb_->currentIndex()) > -1) {
            options.size = sizeUnitsCb_->itemData(idxU).toLongLong();
            options.size *= sizeValSp_->value();
        }
        else
            options.size = 0;
    }

    options.owner = ownerLe_->text().simplified().toStdString();
    options.group = groupLe_->text().simplified().toStdString();

    finder_->find(fromRelPath(folderLe_->text()).toStdString(), options);
}

void MvQAdvancedSearchDialog::slotCancel()
{
    if (finder_)
        finder_->abortFind();
}

void MvQAdvancedSearchDialog::findStarted()
{
    findPb_->setEnabled(false);
    cancelPb_->setEnabled(true);

    findProgress_->setRange(0, 0);
    findProgress_->show();

    statusMessageLabel_->setText("Search in progress ...");
}

void MvQAdvancedSearchDialog::findFinished()
{
    findPb_->setEnabled(true);
    cancelPb_->setEnabled(false);

    findProgress_->hide();
    findProgress_->setRange(0, 1);
    findProgress_->setValue(1);

    statusMessageLabel_->setText(QString::number(resTree_->topLevelItemCount()) + " items found");
}

void MvQAdvancedSearchDialog::slotContextMenu(const QPoint& pos)
{
    if (QTreeWidgetItem* item = resTree_->itemAt(pos)) {
        auto* ac = new QAction(tr("Locate in folder view"), resTree_);
        QList<QAction*> lst;
        lst << ac;
        if (QMenu::exec(lst, resTree_->mapToGlobal(pos), ac, resTree_) == ac) {
            MvQFileBrowser::locate(caller_, item->text(1), item->text(0));
        }
        delete ac;
    }
}

void MvQAdvancedSearchDialog::slotUpdateFolderBox(int)
{
    if (subFolderCheck_->isChecked()) {
        linkCheck_->setEnabled(true);
        sysCheck_->setEnabled(true);
    }
    else {
        linkCheck_->setEnabled(false);
        sysCheck_->setEnabled(false);
    }
}

void MvQAdvancedSearchDialog::slotUpdateDateBox(int)
{
    bool st = dateCheck_->isChecked();

    foreach (QWidget* w, dateBoxTop_)
        w->setEnabled(st);
    foreach (QWidget* w, dateBoxBottom_)
        w->setEnabled(st);

    // Init radio button state
    slotDateRadio(true);
}

void MvQAdvancedSearchDialog::slotDateRadio(bool)
{
    if (!dateCheck_->isChecked()) {
        return;
    }
    else {
        bool top = true;
        bool bottom = true;
        if (periodRb_->isChecked()) {
            bottom = false;
        }
        else {
            top = false;
        }

        for (int i = 1; i < dateBoxTop_.count(); i++)
            dateBoxTop_.at(i)->setEnabled(top);

        for (int i = 1; i < dateBoxBottom_.count(); i++)
            dateBoxBottom_.at(i)->setEnabled(bottom);
    }
}

void MvQAdvancedSearchDialog::slotUpdateSizeBox(int)
{
    int idx = sizeOperCb_->currentIndex();

    if (idx != -1) {
        bool st = (sizeOperCb_->itemData(idx).toInt() == 5) ? false : true;
        sizeValSp_->setEnabled(st);
        sizeUnitsCb_->setEnabled(st);
    }
}

void MvQAdvancedSearchDialog::slotTypeRadio(bool)
{
    if (typeTextRb_->isChecked()) {
        typeStacked_->setCurrentIndex(0);
    }
    else {
        typeStacked_->setCurrentIndex(1);
    }
}


void MvQAdvancedSearchDialog::itemArrived(QString fileName, QString type)
{
    fileName.replace("//", "/");

    Path p(fileName.toStdString());

    QString relName = toRelPath(QString::fromStdString(p.directory().str()));

    QStringList lst;
    lst << QString::fromStdString(p.name());
    lst << relName;
    lst << type;
    lst << formatFileSize(p.sizeInBytes());
    lst << formatFileDate(p.lastModified());
    lst << QString::fromStdString(p.owner());
    lst << QString::fromStdString(p.permissions());

    auto* item = new QTreeWidgetItem(resTree_, lst);

    MvQIconProvider::pixmap(type.toStdString(), 16);

    item->setIcon(0, MvQIconProvider::pixmap(type.toStdString(), 16));
}


void MvQAdvancedSearchDialog::next(const IconClass& c)
{
    if (c.canBeCreated()) {
        iconClasses_ << &c;
    }
    else {
        QString type = QString::fromStdString(c.type());
        if (type.compare("file", Qt::CaseInsensitive) == 0) {
            iconClasses_ << &c;
        }
    }
}

void MvQAdvancedSearchDialog::loadTypeCb()
{
    // Scan for icon classes
    if (iconClasses_.count() == 0) {
        IconClass::scan(*this);

        // sort
        QMap<QString, const IconClass*> cmap;
        foreach (const IconClass* ic, iconClasses_) {
            cmap[QString::fromStdString(ic->defaultName())] = ic;
        }

        iconClasses_.clear();

        QMap<QString, const IconClass*>::const_iterator it = cmap.constBegin();
        while (it != cmap.constEnd()) {
            iconClasses_ << it.value();
            ++it;
        }
    }

    foreach (const IconClass* ic, iconClasses_) {
        typeCb_->addItem(MvQIconProvider::pixmap(*ic, 20),
                         QString::fromStdString(ic->defaultName()),
                         QString::fromStdString(ic->name()));
    }

    typeCb_->insertItem(0, tr("Any"), "__any__");
}

QString MvQAdvancedSearchDialog::toRelPath(QString path)
{
    static QString top = QString::fromStdString(Folder::top()->path().str());
    path.remove(top);
    if (path.isEmpty())
        path = "/";
    return path;
}

QString MvQAdvancedSearchDialog::fromRelPath(QString path)
{
    static QString top = QString::fromStdString(Folder::top()->path().str());
    return (path == "/") ? top : (top + path);
}

QString MvQAdvancedSearchDialog::formatFileSize(qint64 size) const
{
    if (size < 1024)
        return QString::number(size) + " B";
    else if (size < 1024 * 1024)
        return QString::number(size / 1024) + " KB";
    else if (size < 1024 * 1024 * 1024)
        return QString::number(size / (1024 * 1024)) + " MB";
    else
        return QString::number(size / (1024 * 1024 * 1024)) + " GB";

    return {};
}

QString MvQAdvancedSearchDialog::formatFileDate(time_t t) const
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0)
    QDateTime dt;
    dt.setSecsSinceEpoch(t);
#else
    QDateTime dt = QDateTime::fromTime_t(t);
#endif
    return dt.toString("yyyy-MM-dd hh:mm");
}

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

void MvQAdvancedSearchDialog::writeSettings()
{
    QSettings settings(MVQ_QSETTINGS_DEFAULT_ARGS, "MV4-Desktop-AdvancedSearchDialog");

    // 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();

    settings.beginGroup("options");
    settings.setValue("includeSub", subFolderCheck_->isChecked());
    settings.setValue("includeSys", sysCheck_->isChecked());
    settings.setValue("followLinks", linkCheck_->isChecked());
    settings.setValue("caseCheck", caseCheck_->isChecked());
    settings.setValue("name", nameLe_->text());

    // Type
    int typeMode = typeTextRb_->isChecked() ? 0 : 1;
    settings.setValue("typeMode", typeMode);
    settings.setValue("typeText", typeLe_->text());
    settings.setValue("typeCb", typeCb_->currentIndex());

    // Contents
    settings.setValue("containing", contLe_->text());
    settings.setValue("contentsCaseCheck", contentsCaseCheck_->isChecked());

    // Date
    settings.setValue("useDate", dateCheck_->isChecked());
    int dateMode = periodRb_->isChecked() ? 0 : 1;
    settings.setValue("dateMode", dateMode);
    settings.setValue("from", fromDateE_->date());
    settings.setValue("to", toDateE_->date());
    settings.setValue("duration", durationSp_->value());
    settings.setValue("durationUnits", durationCb_->currentIndex());

    // Size
    settings.setValue("sizeOper", sizeOperCb_->currentIndex());
    settings.setValue("sizeVal", sizeValSp_->value());
    settings.setValue("sizeUnits", sizeUnitsCb_->currentIndex());

    // Owner
    settings.setValue("owner", ownerLe_->text());
    settings.setValue("group", groupLe_->text());

    settings.endGroup();
}


void MvQAdvancedSearchDialog::readSettings()
{
    QSettings settings(MVQ_QSETTINGS_DEFAULT_ARGS, "MV4-Desktop-AdvancedSearchDialog");

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

    settings.endGroup();

    settings.beginGroup("options");

    if (settings.contains("includeSub"))
        subFolderCheck_->setChecked(settings.value("includeSub").toBool());

    if (settings.contains("includeSys"))
        sysCheck_->setChecked(settings.value("includeSys").toBool());

    if (settings.contains("followLinks"))
        linkCheck_->setChecked(settings.value("followLinks").toBool());

    if (settings.contains("caseCheck"))
        caseCheck_->setChecked(settings.value("caseCheck").toBool());

    if (settings.contains("name"))
        nameLe_->setText(settings.value("name").toString());


    // Type
    if (settings.contains("typeMode")) {
        int typeMode = settings.value("typeMode").toInt();
        if (typeMode == 0) {
            typeTextRb_->setChecked(true);
            typeListRb_->setChecked(false);
        }
        else {
            typeTextRb_->setChecked(false);
            typeListRb_->setChecked(true);
        }
    }

    if (settings.contains("typeText"))
        typeLe_->setText(settings.value("typeText").toString());

    if (settings.contains("typeCb")) {
        int idx = settings.value("typeCb").toInt();
        if (idx >= 0 && idx < typeCb_->count())
            typeCb_->setCurrentIndex(idx);
    }

    // Contents
    if (settings.contains("containing"))
        contLe_->setText(settings.value("containing").toString());

    if (settings.contains("contentsCaseCheck"))
        contentsCaseCheck_->setChecked(settings.value("contentsCaseCheck").toBool());

    // Date
    if (settings.contains("useDate"))
        dateCheck_->setChecked(settings.value("useDate").toBool());

    if (settings.contains("dateMode")) {
        int dateMode = settings.value("dateMode").toInt();
        if (dateMode == 0) {
            periodRb_->setChecked(true);
            durationRb_->setChecked(false);
        }
        else {
            periodRb_->setChecked(false);
            durationRb_->setChecked(true);
        }
    }

    if (settings.contains("from"))
        fromDateE_->setDate(settings.value("from").toDate());

    if (settings.contains("to"))
        toDateE_->setDate(settings.value("to").toDate());

    if (settings.contains("duration"))
        durationSp_->setValue(settings.value("duration").toInt());

    if (settings.contains("durationUnits")) {
        int idx = settings.value("durationUnits").toInt();
        if (idx >= 0 && idx < durationCb_->count())
            durationCb_->setCurrentIndex(idx);
    }

    // Size
    if (settings.contains("sizeOper")) {
        int idx = settings.value("sizeOper").toInt();
        if (idx >= 0 && idx < sizeOperCb_->count())
            sizeOperCb_->setCurrentIndex(idx);
    }

    if (settings.contains("sizeVal"))
        sizeValSp_->setValue(settings.value("sizeVal").toInt());

    if (settings.contains("sizeUnits")) {
        int idx = settings.value("sizeUnits").toInt();
        if (idx >= 0 && idx < sizeUnitsCb_->count())
            sizeUnitsCb_->setCurrentIndex(idx);
    }

    // Owner
    if (settings.contains("owner"))
        ownerLe_->setText(settings.value("owner").toString());

    if (settings.contains("group"))
        groupLe_->setText(settings.value("group").toString());

    settings.endGroup();
}
