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

 Copyright 2019 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 "MvQFolderPanel.h"

#include <QtGlobal>
#include <QAction>
#include <QDebug>
#include <QDragEnterEvent>
#include <QDragMoveEvent>
#include <QMenu>
#include <QMessageBox>
#include <QPainter>
#include <QTabBar>
#include <QStackedWidget>
#include <QStyle>
#include <QStyleOption>
#include <QToolButton>
#include <QVBoxLayout>

#include "MvQ.h"
#include "MvQBookmarks.h"
#include "MvQContextMenu.h"
#include "MvQDropTarget.h"
#include "MvQFileBrowser.h"
#include "MvQFolderHistory.h"
#include "MvQFolderNavigation.h"
#include "MvQFolderViewBase.h"
#include "MvQFolderWidget.h"
#include "MvQIconProvider.h"
#include "MvQDesktopSettings.h"
#include "MvQMethods.h"

#include "Folder.h"
#include "FolderSettings.h"
#include "IconClass.h"
#include "IconObject.h"
#include "Path.h"
#include "PreviewPanel.h"
#include "MvRequest.h"


//=============================================
//
//  MvQTabWidget
//
//=============================================

MvQTabWidget::MvQTabWidget(QWidget* parent) :
    QWidget(parent)
{
    // Create layout
    auto* layout = new QVBoxLayout(this);
    layout->setSpacing(0);
    layout->setContentsMargins(0, 0, 0, 0);

    auto* hb = new QHBoxLayout();
    hb->setSpacing(0);
    hb->setContentsMargins(0, 0, 0, 0);
    layout->addLayout(hb);

    bar_ = new QTabBar(this);
    bar_->setProperty("desktop", "1");
    hb->addWidget(bar_, 1, Qt::AlignBottom);

    bar_->setMovable(true);
    bar_->setExpanding(true);

    // Add tab button
    addTb_ = new QToolButton(this);
    addTb_->setAutoRaise(true);
    addTb_->setIcon(QPixmap(":/desktop/add_tab.svg"));
    addTb_->setToolTip(tr("Open a new tab"));
    hb->addWidget(addTb_);

    prevAc_ = new QAction(this);
    prevAc_->setText("Go backward in tab history");
    prevAc_->setShortcut(tr("Ctrl+Shift+Left"));
    prevAc_->setIcon(QPixmap(":/desktop/triangle_left.svg"));

    nextAc_ = new QAction(this);
    nextAc_->setText("Go forward in tab history");
    nextAc_->setShortcut(QKeySequence(tr("Ctrl+Shift+Right")));
    nextAc_->setIcon(QPixmap(":/desktop/triangle_right.svg"));

    QList<QAction*> acLst;
    acLst << prevAc_ << nextAc_;
    MvQ::showShortcutInContextMenu(acLst);
    addActions(acLst);

    recentTb_ = new QToolButton(this);
    recentTb_->setAutoRaise(true);
    recentTb_->setIcon(QPixmap(":/desktop/history.svg"));
    recentTb_->setToolTip(tr("Most recent tabs"));
    hb->addWidget(recentTb_);

    prevTabTb_ = new QToolButton(this);
    prevTabTb_->setAutoRaise(true);
    prevTabTb_->setDefaultAction(prevAc_);
    hb->addWidget(prevTabTb_);

    nextTabTb_ = new QToolButton(this);
    nextTabTb_->setAutoRaise(true);
    nextTabTb_->setDefaultAction(nextAc_);
    hb->addWidget(nextTabTb_);

    // Tab list menu
    tabListTb_ = new QToolButton(this);
    tabListTb_->setAutoRaise(true);
    tabListTb_->setIcon(QPixmap(":/desktop/menu_arrow_down.svg"));
    tabListTb_->setToolTip(tr("List all tabs"));
    hb->addWidget(tabListTb_);

    stacked_ = new QStackedWidget(this);
    // stacked_->setMinimumHeight(1);
    // stacked_->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Minimum);
    layout->addWidget(stacked_);

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

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

    connect(bar_, SIGNAL(tabMoved(int, int)),
            this, SLOT(tabMoved(int, int)));

    connect(bar_, SIGNAL(currentChanged(int)),
            this, SLOT(currentTabChanged(int)));

    connect(bar_, SIGNAL(tabCloseRequested(int)),
            this, SLOT(removeTab(int)));

    connect(addTb_, SIGNAL(clicked(bool)),
            this, SIGNAL(newTabRequested(bool)));

    connect(prevAc_, SIGNAL(triggered(bool)),
            this, SIGNAL(prevTabRequested(bool)));

    connect(nextAc_, SIGNAL(triggered(bool)),
            this, SIGNAL(nextTabRequested(bool)));

    connect(recentTb_, SIGNAL(clicked()),
            this, SLOT(slotRecentTabs()));

    connect(tabListTb_, SIGNAL(clicked()),
            this, SLOT(slotTabList()));

    setAcceptDrops(true);
}

void MvQTabWidget::slotContextMenu(const QPoint& pos)
{
    if (pos.isNull())
        return;

    MvQContextItemSet* cms = cmSet();
    if (!cms)
        return;

    int index = bar_->tabAt(pos);

    QString selection = MvQContextMenu::instance()->exec(cms->icon(), mapToGlobal(pos), this,
                                                         // QString::number(bar_->count()));
                                                         "path=" + folderPath(index));
    if (!selection.isEmpty())
        tabBarCommand(selection, index);
}

int MvQTabWidget::count() const
{
    return bar_->count();
}

int MvQTabWidget::currentIndex() const
{
    return bar_->currentIndex();
}

void MvQTabWidget::setCurrentIndex(int index)
{
    bar_->setCurrentIndex(index);
}

QWidget* MvQTabWidget::widget(int index) const
{
    if (index >= 0 && index < bar_->count()) {
        return stacked_->widget(index);
    }

    return nullptr;
}

QWidget* MvQTabWidget::currentWidget() const
{
    return widget(bar_->currentIndex());
}

int MvQTabWidget::indexOfWidget(QWidget* w) const
{
    for (int i = 0; i < stacked_->count(); i++)
        if (w == stacked_->widget(i))
            return i;

    return -1;
}

void MvQTabWidget::clear()
{
    while (bar_->count() > 0) {
        removeTab(0);
    }
}

void MvQTabWidget::addTab(QWidget* w, QPixmap pix, QString name)
{
    stacked_->addWidget(w);
    bar_->addTab(pix, name);
    bar_->setCurrentIndex(count() - 1);
    checkTabStatus();
}

void MvQTabWidget::removeTab(int index)
{
    if (index >= 0 && index < bar_->count()) {
        QWidget* w = stacked_->widget(index);
        stacked_->removeWidget(w);
        bar_->removeTab(index);
        w->hide();
        w->deleteLater();
    }

    checkTabStatus();
}

void MvQTabWidget::removeOtherTabs(int index)
{
    QWidget* actW = stacked_->widget(index);

    while (bar_->count() > 0) {
        if (stacked_->widget(0) != actW) {
            removeTab(0);
        }
        else
            break;
    }

    while (bar_->count() > 1) {
        if (stacked_->widget(1) != actW) {
            removeTab(1);
        }
    }

    checkTabStatus();
}

void MvQTabWidget::currentTabChanged(int index)
{
    if (stacked_->count() == bar_->count()) {
        stacked_->setCurrentIndex(index);

        emit currentIndexChanged(index);

        checkTabStatus();
    }
}

void MvQTabWidget::tabMoved(int from, int to)
{
    QWidget* w = stacked_->widget(from);
    stacked_->removeWidget(w);
    stacked_->insertWidget(to, w);

    // Experience with Qt 4.6.3: Here from and to does not
    // incicate the dragged tabs's position!!!
    // But at least tab_->currentIndex() shows the dragged tab's new position.

    // qDebug() << "move" << from << to << bar_->currentIndex();

    // We do not emit  currentIndexChanged() signal here because
    // the "current widget" stayed the same!
    if (stacked_->count() == bar_->count()) {
        stacked_->setCurrentIndex(bar_->currentIndex());
        checkTabStatus();
    }
}

void MvQTabWidget::removeDuplicatedTabs()
{
    QList<QWidget*> removeLst;
    QStringList pathLst;
    for (int i = 0; i < bar_->count(); i++) {
        QString path = bar_->tabData(i).toString();
        if (pathLst.contains(path)) {
            removeLst << stacked_->widget(i);
        }
        else {
            pathLst << path;
        }
    }

    for (int i = 0; i < removeLst.count(); i++) {
        for (int j = 0; j < bar_->count(); j++) {
            if (stacked_->widget(j) == removeLst[i]) {
                removeTab(j);
                break;
            }
        }
    }
}

QVariant MvQTabWidget::tabData(int index) const
{
    if (index >= 0 && index < bar_->count()) {
        return bar_->tabData(index);
    }
    return {};
}


QIcon MvQTabWidget::tabIcon(int index) const
{
    if (index >= 0 && index < bar_->count()) {
        return bar_->tabIcon(index);
    }
    return {};
}

void MvQTabWidget::setTabText(int index, QString txt)
{
    if (index >= 0 && index < bar_->count()) {
        bar_->setTabText(index, txt);
    }
}

void MvQTabWidget::setTabIcon(int index, QPixmap pix)
{
    if (index >= 0 && index < bar_->count()) {
        bar_->setTabIcon(index, pix);
    }
}

void MvQTabWidget::setTabToolTip(int index, QString txt)
{
    if (index >= 0 && index < bar_->count()) {
        bar_->setTabToolTip(index, txt);
    }
}

void MvQTabWidget::setTabData(int index, QString txt)
{
    if (index >= 0 && index < bar_->count()) {
        bar_->setTabData(index, txt);
    }
}


void MvQTabWidget::checkTabStatus()
{
    bool multi = bar_->count() > 1;

    bar_->setVisible(multi);
    bar_->setTabsClosable(multi);
    addTb_->setVisible(multi);
    recentTb_->setVisible(multi);
    tabListTb_->setVisible(multi);

    for (int i = 0; i < bar_->count(); i++) {
        if (QWidget* w = bar_->tabButton(i, QTabBar::RightSide)) {
            if (i == bar_->currentIndex())
                w->show();
            else
                w->hide();
        }
    }
}

void MvQTabWidget::checkTabNavigationStatus(bool prev, bool next)
{
    prevAc_->setEnabled(prev);
    nextAc_->setEnabled(next);
}

void MvQTabWidget::checkDropTarget(QDropEvent* event)
{
    if (!event->mimeData()->hasFormat("metview/icon")) {
        removeDropTarget();
    }

    int index = bar_->tabAt(MvQ::eventPos(event));
    QString s = bar_->tabText(index);

    if (!s.isEmpty()) {
        // Folder *f=Folder::folder(s.toStdString(),false);
        // if(f && !f->locked())
        //{
        Qt::DropAction dropAction = event->proposedAction();
        MvQDropTarget::Instance()->reset(s, (dropAction == Qt::MoveAction));
        if (window()) {
            MvQDropTarget::Instance()->move(mapToGlobal(MvQ::eventPos(event)) + QPoint(20, 20));
        }
        return;
        //}
    }

    removeDropTarget();
}

void MvQTabWidget::removeDropTarget()
{
    MvQDropTarget::Instance()->hide();
}

void MvQTabWidget::dragEnterEvent(QDragEnterEvent* event)
{
    if (event->source() &&
        (event->proposedAction() == Qt::CopyAction ||
         event->proposedAction() == Qt::MoveAction)) {
        event->accept();
    }
    else
        event->ignore();
}

void MvQTabWidget::dragMoveEvent(QDragMoveEvent* event)
{
    if (event->source() &&
        (event->proposedAction() == Qt::CopyAction ||
         event->proposedAction() == Qt::MoveAction)) {
        checkDropTarget(event);
        event->accept();
    }
    else {
        removeDropTarget();
        event->ignore();
    }
}

void MvQTabWidget::dragLeaveEvent(QDragLeaveEvent* event)
{
    removeDropTarget();
    event->accept();
}

void MvQTabWidget::dropEvent(QDropEvent* event)
{
    removeDropTarget();

    if (!event->source()) {
        event->ignore();
        return;
    }

    if (event->proposedAction() != Qt::CopyAction &&
        event->proposedAction() != Qt::MoveAction) {
        event->ignore();
        return;
    }

    int index = bar_->tabAt(MvQ::eventPos(event));
    emit iconDropped(index, event);
}

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

//=============================================
//
//  MvQFolderPanel
//
//=============================================

MvQFolderPanel::MvQFolderPanel(QWidget* parent) :
    MvQTabWidget(parent),
    folderHistory_(nullptr),
    tabNavigation_(nullptr),
    inTabNavigation_(false),
    inInitialLoad_(false)
{
    mvHomePath_ = QString::fromStdString(Folder::top()->fullName());

    tabNavigation_ = new MvQFolderNavigation();

    connect(this, SIGNAL(currentIndexChanged(int)),
            this, SLOT(slotCurrentWidgetChanged(int)));

    connect(this, SIGNAL(newTabRequested(bool)),
            this, SLOT(slotNewTab(bool)));

    connect(this, SIGNAL(prevTabRequested(bool)),
            this, SLOT(slotPrevTab(bool)));

    connect(this, SIGNAL(nextTabRequested(bool)),
            this, SLOT(slotNextTab(bool)));

    connect(this, SIGNAL(iconDropped(int, QDropEvent*)),
            this, SLOT(slotIconDroppedToTab(int, QDropEvent*)));
}


MvQFolderPanel::~MvQFolderPanel()
{
    if (folderHistory_)
        delete folderHistory_;

    if (tabNavigation_)
        delete tabNavigation_;
}

QString MvQFolderPanel::currentFolderName()
{
    MvQFolderWidget* w = currentFolderWidget();
    return (w) ? (w->currentFolderName()) : QString();
}

QString MvQFolderPanel::currentFolderPath()
{
    MvQFolderWidget* w = currentFolderWidget();
    return (w) ? (w->currentFolderPath()) : QString();
}

Folder* MvQFolderPanel::currentFolder()
{
    MvQFolderWidget* w = currentFolderWidget();
    return (w) ? w->currentFolder() : nullptr;
}

QList<Folder*> MvQFolderPanel::currentFolders()
{
    QList<Folder*> lst;
    for (int i = 0; i < count(); i++) {
        MvQFolderWidget* w = folderWidget(i);
        if (w) {
            lst << w->currentFolder();
        }
    }
    return lst;
}

QString MvQFolderPanel::folderPath(int index)
{
    if (MvQFolderWidget* w = folderWidget(index)) {
        if (Folder* f = w->currentFolder())
            return QString::fromStdString(f->fullName());
    }
    return {};
}

void MvQFolderPanel::setHistoryMenu(QMenu* m)
{
    if (folderHistory_)
        return;

    folderHistory_ = new MvQFolderHistory(m);

    connect(folderHistory_, SIGNAL(itemSelected(QString)),
            this, SLOT(slotChFolderFromHistory(QString)));

    connect(folderHistory_, SIGNAL(commandRequested(QString, QString)),
            this, SLOT(slotPathCommand(QString, QString)));
}

//=============================================
//
//  Tab management desktopAction
//
//=============================================

MvQFolderWidget* MvQFolderPanel::addWidget(QString path)
{
    // if(path.isEmpty())
    //   	return 0;

    auto* fw = new MvQFolderWidget(path, folderHistory_, &iconActions_, &desktopActions_, this);

    QString name = fw->currentFolderName();
    QPixmap pix = MvQIconProvider::pixmap(fw->currentFolder(), 24);

    addTab(fw, pix, name);

    setTabToolTip(count() - 1, path);
    setTabData(count() - 1, path);

    connect(fw, SIGNAL(pathChanged()),
            this, SLOT(slotPathChanged()));

    connect(fw, SIGNAL(iconCommandRequested(QString, IconObjectH)),
            this, SLOT(slotIconCommand(QString, IconObjectH)));

    connect(fw, SIGNAL(desktopCommandRequested(QString, QPoint)),
            this, SLOT(slotDesktopCommand(QString, QPoint)));

    connect(fw, SIGNAL(itemInfoChanged(IconObject*)),
            this, SIGNAL(itemInfoChanged(IconObject*)));

    return fw;
}


void MvQFolderPanel::resetWidgets(QStringList lst)
{
    if (lst.count() == 0)
        return;

    clear();

    foreach (QString path, lst) {
        addWidget(path);
    }
}


MvQContextItemSet* MvQFolderPanel::cmSet()
{
    static MvQContextItemSet cmItems("FolderPanel");
    return &cmItems;
}

void MvQFolderPanel::tabBarCommand(QString name, int index)
{
    if (name == "reloadTab") {
        MvQFolderWidget* w = folderWidget(index);
        if (w)
            w->reload();
    }
    else if (name == "closeOtherTabs") {
        removeOtherTabs(index);
    }
    else if (name == "closeTab") {
        removeTab(index);
    }
    else if (name == "copy_path") {
        MvQFolderWidget* w = folderWidget(index);
        if (w) {
            MvQ::toClipboard(w->currentFolderFsPath());
        }
    }
    else if (name == "bookmark") {
        MvQFolderWidget* w = folderWidget(index);
        if (w)
            MvQBookmarks::addItem(w->currentFolder());
    }
    else if (name == "empty") {
        MvQ::emptyWasteBasket();
    }
}

MvQFolderWidget* MvQFolderPanel::folderWidget(int index)
{
    QWidget* w = widget(index);
    return (w) ? dynamic_cast<MvQFolderWidget*>(w) : nullptr;
}

MvQFolderWidget* MvQFolderPanel::currentFolderWidget()
{
    QWidget* w = currentWidget();
    return dynamic_cast<MvQFolderWidget*>(w);
}

void MvQFolderPanel::slotCurrentWidgetChanged(int /*index*/)
{
    emit currentWidgetChanged();

    folderHistory_->add(currentFolderPath());

    if (!inTabNavigation_ && !inInitialLoad_) {
        if (tabNavigation_->hasNext()) {
            tabNavigation_->removeAfterCurrent();
        }
        tabNavigation_->add(currentFolderPath());
        checkTabNavigationStatus(tabNavigation_->hasPrev(), tabNavigation_->hasNext());
    }

    if (previewPanel_) {
        previewPanel_->clear();
    }
}

void MvQFolderPanel::slotLookupOrOpenInTab(QString path)
{
    for (int i = 0; i < count(); i++) {
        if (path == tabData(i).toString()) {
            setCurrentIndex(i);
            return;
        }
    }

    addWidget(path);
}

void MvQFolderPanel::slotNewTab(bool)
{
    if (Folder* f = currentFolder()) {
        QString p = QString::fromStdString(f->fullName());
        addWidget(p);
    }
    else {
        addWidget(mvHomePath_);
    }
}

void MvQFolderPanel::slotNewWindow(bool)
{
    if (Folder* f = currentFolder()) {
        QString p = QString::fromStdString(f->fullName());
        MvQFileBrowser::openBrowser(p, this);
    }
}

void MvQFolderPanel::slotIconDroppedToTab(int index, QDropEvent* event)
{
    if (MvQFolderWidget* w = folderWidget(index)) {
        MvQFolderViewBase::dropToFolder(w->currentFolder(), event);
    }
}

void MvQFolderPanel::slotFindIcons(FolderSearchData* data)
{
    MvQFolderWidget* w = currentFolderWidget();
    if (w) {
        w->findIcons(data);
    }
}

//====================================================
//   Navigation
//===================================================

/*void MvQFolderPanel::updateFolderHistory(QString)
{
    folderNavigation_->removeAfterCurrent();
    folderNavigation_->add(path);
    updateNavigationActionState();
}*/

void MvQFolderPanel::slotChFolderBack()
{
    MvQFolderWidget* w = currentFolderWidget();
    if (w)
        w->chFolderBack();
}

void MvQFolderPanel::slotChFolderForward()
{
    MvQFolderWidget* w = currentFolderWidget();
    if (w)
        w->chFolderForward();
}

void MvQFolderPanel::slotChFolderParent()
{
    MvQFolderWidget* w = currentFolderWidget();
    if (w)
        w->chFolderParent();
}

void MvQFolderPanel::slotChFolderWastebasket()
{
    MvQFolderWidget* w = currentFolderWidget();
    if (w) {
        Folder* wbo = Folder::folder("wastebasket");
        if (wbo)
            w->chFolderFromBookmarks(QString::fromStdString(wbo->fullName()));
    }
}

void MvQFolderPanel::slotChFolderMvHome()
{
    MvQFolderWidget* w = currentFolderWidget();
    if (w) {
        w->chFolderFromBookmarks(mvHomePath_);
    }
    else {
        // If there is no widget at all we offer this way to create one!
        if (count() != 0)
            addWidget(mvHomePath_);
    }
}

void MvQFolderPanel::slotChFolderDefaults()
{
    QString defaultsPath =
        QString::fromStdString(Path(mvHomePath_.toStdString()).add("System").add("Defaults").str());
    MvQFolderWidget* w = currentFolderWidget();
    if (w) {
        w->chFolderFromBookmarks(defaultsPath);
    }
    else {
        // If there is no widget at all we offer this way to create one!
        if (count() != 0)
            addWidget(defaultsPath);
    }
}

/*void MvQFolderPanel::slotFolderChangedInView(QString path)
{
    folderNavigation_->removeAfterCurrent();
    folderNavigation_->add(path);
    updateNavigationActionState();
    folderHistory_->add(path);
    pathWidget_->setPath(path);
}*/

void MvQFolderPanel::slotChFolderFromHistory(QString path)
{
    MvQFolderWidget* w = currentFolderWidget();
    if (w)
        w->chFolderFromHistory(path);
}

void MvQFolderPanel::slotChFolderFromBookmarks(QString path)
{
    MvQFolderWidget* w = currentFolderWidget();
    if (w)
        w->chFolderFromBookmarks(path);
}

void MvQFolderPanel::slotChFolderFromBreadcrumbs(QString p)
{
    MvQFolderWidget* w = currentFolderWidget();
    if (w)
        w->chFolderFromBreadcrumbs(p);
}

void MvQFolderPanel::setViewMode(Desktop::FolderViewMode mode)
{
    MvQFolderWidget* w = currentFolderWidget();
    if (w)
        w->setViewMode(mode);
}

Desktop::FolderViewMode MvQFolderPanel::viewMode()
{
    MvQFolderWidget* w = currentFolderWidget();
    return (w) ? w->viewMode() : FolderSettings::defaultViewMode();
}

bool MvQFolderPanel::viewModeGrid()
{
    MvQFolderWidget* w = currentFolderWidget();
    return (w) ? w->viewModeGrid() : false;
}

void MvQFolderPanel::slotPathChanged()
{
    auto* fw = dynamic_cast<MvQFolderWidget*>(sender());

    if (count() > 0 && fw) {
        int index = indexOfWidget(fw);
        if (index >= 0) {
            setTabText(index, fw->currentFolderName());
            QPixmap pix = MvQIconProvider::pixmap(fw->currentFolder(), 24);
            setTabIcon(index, pix);
            setTabToolTip(index, fw->currentFolderPath());
            setTabData(index, fw->currentFolderPath());
        }
    }

    if (fw) {
        emit pathChanged();
    }
}


void MvQFolderPanel::slotIconCommand(QString name, IconObjectH obj)
{
    if (!obj)
        return;

    if (name == "open") {
        MvQFolderWidget* w = currentFolderWidget();
        if (w) {
            w->chFolder(QString::fromStdString(obj->fullName()));
        }
    }

    if (name == "openInTab") {
        addWidget(QString::fromStdString(obj->fullName()));
    }
    if (name == "bookmark") {
        if (obj->isFolder())
            MvQBookmarks::addItem(obj);
    }
}

void MvQFolderPanel::slotPathCommand(QString name, QString path)
{
    if (name == "openInTab") {
        addWidget(path);
    }
    else if (name == "openInWin") {
        MvQFileBrowser::openBrowser(path, this);
    }
    else if (name == "bookmark") {
        MvQBookmarks::addItem(path);
    }
    else if (name == "copy_path") {
        auto pathStr = path.toStdString();
        if (Folder* f = Folder::folder(pathStr, false)) {
            MvQ::toClipboard(QString::fromStdString(f->path().str()));
        }
    }
    else if (name == "locate") {
    }
}

void MvQFolderPanel::slotDesktopCommand(QString name, QPoint)
{
    desktopActions_.trigger(name);
}

void MvQFolderPanel::slotIconCommandFromMain(QAction* ac)
{
    if (ac && !ac->data().toString().isEmpty()) {
        MvQFolderWidget* w = currentFolderWidget();
        if (w) {
            w->iconCommandFromMain(ac->data().toString());
        }
    }
}

void MvQFolderPanel::addIconAction(QAction* ac)
{
    iconActions_.add(ac);
}

void MvQFolderPanel::addDesktopAction(QAction* ac)
{
    desktopActions_.add(ac);
}

//==========================================================
//
// Snap to grid
//
//==========================================================

void MvQFolderPanel::slotGridByName(bool)
{
    MvQFolderWidget* w = currentFolderWidget();
    if (w)
        w->toGrid(Desktop::GridSortByName);
}

void MvQFolderPanel::slotGridBySize(bool)
{
    MvQFolderWidget* w = currentFolderWidget();
    if (w)
        w->toGrid(Desktop::GridSortBySize);
}

void MvQFolderPanel::slotGridByType(bool)
{
    MvQFolderWidget* w = currentFolderWidget();
    if (w)
        w->toGrid(Desktop::GridSortByType);
}

void MvQFolderPanel::slotShowLastCreated(bool)
{
    MvQFolderWidget* w = currentFolderWidget();
    if (w)
        w->showLastCreated();
}

void MvQFolderPanel::saveFolderInfo()
{
    for (int i = 0; i < count(); i++) {
        if (MvQFolderWidget* w = folderWidget(i))
            w->saveFolderInfo();
    }
}

void MvQFolderPanel::setIconSize(int iconSize)
{
    MvQFolderWidget* w = currentFolderWidget();
    if (w)
        w->setIconSize(iconSize);
}

void MvQFolderPanel::forceIconSize(int iconSize)
{
    for (int i = 0; i < count(); i++) {
        if (MvQFolderWidget* w = folderWidget(i)) {
            w->setIconSize(iconSize);
        }
    }
}

int MvQFolderPanel::iconSize()
{
    MvQFolderWidget* w = currentFolderWidget();
    if (w)
        return w->iconSize();

    return 32;
}

MvQFolderNavigation* MvQFolderPanel::folderNavigation()
{
    MvQFolderWidget* w = currentFolderWidget();
    if (w)
        return w->folderNavigation();

    return nullptr;
}

//==========================================================
//
// Show an icon
//
//==========================================================

void MvQFolderPanel::slotShowIconInCurrent(IconObject* obj)
{
    MvQFolderWidget* w = currentFolderWidget();
    if (w)
        w->showIcon(obj);
}

bool MvQFolderPanel::showIcon(IconObject* obj, bool addFolder)
{
    if (!obj)
        return false;

    for (int i = 0; i < count(); i++) {
        MvQFolderWidget* w = folderWidget(i);
        if (w && w->currentFolder() == obj->parent()) {
            setCurrentIndex(i);
            w->showIcon(obj);
            return true;
        }
    }

    // If the icons's parent folder is not displayed
    if (addFolder) {
        if (MvQFolderWidget* fw = addWidget(QString::fromStdString(obj->parent()->fullName()))) {
            fw->showIcon(obj);
            return true;
        }
    }

    return false;
}


void MvQFolderPanel::slotPrevTab(bool)
{
    if (!tabNavigation_->hasPrev())
        return;

    QStringList pathLst;
    for (int i = 0; i < count(); i++) {
        pathLst << tabData(i).toString();
    }
#if 0
    qDebug() << "MvQFolderPanel::slotPrevTab -->";
    tabNavigation_->print();
    qDebug() << "----------------------";
#endif
    QString prevPath = tabNavigation_->prev();
    int idx = pathLst.indexOf(prevPath);
    if (idx != -1) {
        inTabNavigation_ = true;
        setCurrentIndex(idx);
        inTabNavigation_ = false;
    }

    tabNavigation_->print();
    checkTabNavigationStatus(tabNavigation_->hasPrev(), tabNavigation_->hasNext());
#if 0
    tabNavigation_->print();
    qDebug() << "<-- MvQFolderPanel::slotPrevTab";
#endif
}

void MvQFolderPanel::slotNextTab(bool)
{
    if (!tabNavigation_->hasNext())
        return;

    QStringList pathLst;
    for (int i = 0; i < count(); i++) {
        pathLst << tabData(i).toString();
    }

    QString nextPath = tabNavigation_->next();
    int idx = pathLst.indexOf(nextPath);
    if (idx != -1) {
        inTabNavigation_ = true;
        setCurrentIndex(idx);
        inTabNavigation_ = false;
    }

    checkTabNavigationStatus(tabNavigation_->hasPrev(), tabNavigation_->hasNext());
}

void MvQFolderPanel::slotRecentTabs()
{
    auto* menu = new QMenu(tabListTb_);

    menu->addAction(prevAc_);
    menu->addAction(nextAc_);

    // Recent tabs
    menu->addSeparator();

    QStringList pathLst;
    for (int i = 0; i < count(); i++) {
        pathLst << tabData(i).toString();
    }

    int cnt = 0;
    int maxCnt = 10;
    foreach (QString item, folderHistory_->items()) {
        int idx = pathLst.indexOf(item);
        if (idx != -1 && idx != currentIndex()) {
            auto* ac = new QAction(menu);
            ac->setText(tabData(idx).toString());
            ac->setIcon(tabIcon(idx));
            ac->setData(idx);

            menu->addAction(ac);
            cnt++;
        }
        if (cnt >= maxCnt)
            break;
    }

    // execute menu
    if (QAction* ac = menu->exec(QCursor::pos())) {
        if (!ac->isSeparator()) {
            if (ac == prevAc_) {
                slotPrevTab(true);
            }
            else if (ac == nextAc_) {
                slotNextTab(true);
            }
            else {
                int index = ac->data().toInt();
                if (index >= 0 && index < count()) {
                    setCurrentIndex(index);
                }
            }
        }
    }

    menu->clear();
    menu->deleteLater();
}

void MvQFolderPanel::slotTabList()
{
    auto* menu = new QMenu(tabListTb_);

    auto* removeDupAc = new QAction(menu);
    removeDupAc->setText(tr("Close duplicated tabs"));
    removeDupAc->setData(-1);
    menu->addAction(removeDupAc);

    // All the tabs
    menu->addSeparator();

    for (int i = 0; i < count(); i++) {
        auto* ac = new QAction(menu);
        ac->setText(tabData(i).toString());
        ac->setIcon(tabIcon(i));
        ac->setData(i);
        if (i == currentIndex()) {
            QFont font;
            font.setBold(true);
            ac->setFont(font);
        }
        menu->addAction(ac);
    }

    // execute menu
    if (QAction* ac = menu->exec(QCursor::pos())) {
        if (!ac->isSeparator()) {
            int index = ac->data().toInt();
            if (index >= 0 && index < count()) {
                setCurrentIndex(index);
            }
            else if (ac == removeDupAc) {
                removeDuplicatedTabs();
            }
        }
    }

    menu->clear();
    menu->deleteLater();
}

//==========================================================
//
// Rescan
//
//==========================================================

void MvQFolderPanel::slotReload(bool)
{
    MvQFolderWidget* w = currentFolderWidget();
    if (w)
        w->reload();
}

//==========================================================
//
// Save/restore settings
//
//==========================================================

void MvQFolderPanel::writeSettings(QSettings& settings)
{
    settings.setValue("folderCount", count());

    settings.setValue("current", (currentIndex() >= 0) ? currentIndex() : 0);

    for (int i = 0; i < count(); i++) {
        MvQFolderWidget* cw = folderWidget(i);

        settings.beginGroup("folder_" + QString::number(i));
        cw->writeSettings(settings);
        settings.endGroup();
    }
}

void MvQFolderPanel::readSettings(QSettings& settings)
{
    inInitialLoad_ = true;

    // Create folder tabs
    int cnt = settings.value("folderCount").toInt();
    int currentIndex = settings.value("current").toInt();

    if (cnt > 0) {
        for (int i = 0; i < cnt; i++) {
            settings.beginGroup("folder_" + QString::number(i));
            QString relPath = settings.value("path").toString();
            // Path mvPath(path.toStdString());
            // if(mvPath.exists())
            //{
            MvQFolderWidget* fw = addWidget(relPath);
            if (fw)
                fw->readSettings(settings);

            //}
            settings.endGroup();
        }

        // Set current tab
        if (currentIndex >= 0 && currentIndex < cnt) {
            setCurrentIndex(currentIndex);
        }
    }

    else if (!mvHomePath_.isEmpty()) {
        Path mvPath(mvHomePath_.toStdString());
        if (mvPath.exists())
            addWidget(mvHomePath_);
    }

    if (QWidget* w = currentFolderWidget())
        w->setFocus();

    inInitialLoad_ = false;

    tabNavigation_->add(currentFolderPath());
    checkTabNavigationStatus(tabNavigation_->hasPrev(), tabNavigation_->hasNext());
}
