/* BEGIN_COMMON_COPYRIGHT_HEADER
 * (c)LGPL2+
 *
 * Copyright: 2011 Razor team
 *            2014 LXQt team
 * Authors:
 *   Alexander Sokoloff <sokoloff.a@gmail.com>
 *   Maciej Płaza <plaza.maciej@gmail.com>
 *   Kuzma Shapran <kuzma.shapran@gmail.com>
 *
 * Copyright: 2019 Tianjin KYLIN Information Technology Co., Ltd. *
 *
 * This program or library is free software; you can redistribute it
 * and/or modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.

 * You should have received a copy of the GNU Lesser General
 * Public License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA
 *
 * END_COMMON_COPYRIGHT_HEADER */

#include <QApplication>
#include <QDebug>
#include <QSignalMapper>
#include <QToolButton>
#include <QSettings>
#include <QList>
#include <QMimeData>
#include <QWheelEvent>
#include <QFlag>
#include <QtX11Extras/QX11Info>
#include <QDebug>
#include <QTimer>
#include <XdgDesktopFile>
#include <XdgIcon>
#include <QMessageBox>
#include <QPainterPath>
#include <unistd.h>
#include "../panel/common/ukuigridlayout.h"

#include "ukuitaskbar.h"
#include "ukuitaskgroup.h"
#include "quicklaunchaction.h"
#define PANEL_SETTINGS     "org.ukui.panel.settings"
#define PANEL_LINES        "panellines"
#define PANEL_CONFIG_PATH  "/usr/share/ukui/ukui-panel/panel-commission.ini"
#define PANEL_POSITION_KEY  "panelposition"
using namespace UKUi;
/************************************************

************************************************/
UKUITaskBar::UKUITaskBar(IUKUIPanelPlugin *plugin, QWidget *parent) :
    QScrollArea(parent),
    m_signalMapper(new QSignalMapper(this)),
    m_buttonStyle(Qt::ToolButtonIconOnly),
    m_buttonWidth(400),
    m_buttonHeight(100),
    m_closeOnMiddleClick(true),
    m_raiseOnCurrentDesktop(true),
    m_showOnlyOneDesktopTasks(true),
    m_showDesktopNum(0),
    m_showOnlyCurrentScreenTasks(false),
    m_showOnlyMinimizedTasks(false),
    m_autoRotate(true),
    m_groupingEnabled(true),
    m_showGroupOnHover(true),
    m_iconByClass(false),
    m_cycleOnWheelScroll(true),
    m_plugin(plugin),
    m_ignoreWindow(),
    m_placeHolder(new QWidget(this)),
    m_style(new LeftAlignedTextStyle())
{
    m_allFrame=new QWidget(this);
    m_allFrame->setAttribute(Qt::WA_TranslucentBackground);

    this->setWidget(m_allFrame);
    this->horizontalScrollBar()->setVisible(false);
    this->verticalScrollBar()->setVisible(false);
    this->setFrameShape(QFrame::NoFrame);//去掉边框
    this->setWidgetResizable(true);
    //临时方案解决任务栏出现滚动时有滑动条区域遮挡图标,待滚动提示样式确认后再进行替换
    horizontalScrollBar()->setStyleSheet("QScrollBar {height:0px;}");
    verticalScrollBar()->setStyleSheet("QScrollBar {width:0px;}");

    QPalette pal = this->palette();
    pal.setBrush(QPalette::Window, QColor(Qt::transparent));
    this->setPalette(pal);

    m_taskStatus=NORMAL;

    m_layout = new UKUi::GridLayout(m_allFrame);
    m_allFrame->setLayout(m_layout);
    m_layout->setMargin(0);
    m_layout->setStretch(UKUi::GridLayout::StretchHorizontal | UKUi::GridLayout::StretchVertical);

    m_placeHolder->setMinimumSize(1,1);
    m_placeHolder->setMaximumSize(QWIDGETSIZE_MAX,QWIDGETSIZE_MAX);
    m_placeHolder->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));

    QString filename = QString::fromLocal8Bit(PANEL_CONFIG_PATH);
    QSettings settings(filename, QSettings::IniFormat);
    settings.setIniCodec("UTF-8");
    settings.beginGroup("IgnoreWindow");
    m_ignoreWindow = settings.value("ignoreWindow", "").toStringList();
    settings.endGroup();

    //往任务栏中加入快速启动按钮
    refreshQuickLaunch();
    realignSdk();

    settingsChanged();
    setAcceptDrops(true);

    const QByteArray id(PANEL_SETTINGS);
    if (QGSettings::isSchemaInstalled(id)) {
        m_settings=new QGSettings(id);
    }

    const QByteArray id_Theme("org.ukui.style");
    if (QGSettings::isSchemaInstalled(id_Theme)) {
        m_changeTheme = new QGSettings(id_Theme);
    }

    connect(m_changeTheme, &QGSettings::changed, this, [=] (const QString &key) {
                if (key=="iconThemeName") {
                    sleep(1);
                    for(auto it= m_knownSdkWindows.begin(); it != m_knownSdkWindows.end();it++) {
                        UKUITaskGroup *group = it.value();
                        group->updateSdkIcon();
                    }
                }
                if (key == PANEL_POSITION_KEY) {
                    realignSdk();
                }
            });

    connect(m_signalMapper, static_cast<void (QSignalMapper::*)(int)>(&QSignalMapper::mapped), this, &UKUITaskBar::activateSdkTask);

    connect(WindowManager::self(), &WindowManager::windowChanged, this, &UKUITaskBar::onWindowChanged);
    connect(WindowManager::self(), &WindowManager::windowAdded, this, &UKUITaskBar::onWindowAdded);
    connect(WindowManager::self(), &WindowManager::windowRemoved, this, &UKUITaskBar::onWindowRemoved);
    connect(WindowManager::self(), &WindowManager::currentDesktopChanged, this, &UKUITaskBar::onDesktopChanged);

    saveSdkSettings();

    /**/
    QDBusConnection::sessionBus().unregisterService("com.ukui.panel.plugins.service");
    QDBusConnection::sessionBus().registerService("com.ukui.panel.plugins.service");
    QDBusConnection::sessionBus().registerObject("/taskbar/click", this,QDBusConnection :: ExportAllSlots | QDBusConnection :: ExportAllSignals);

    QDBusConnection::sessionBus().connect(QString(), QString("/taskbar/quicklaunch"), "org.ukui.panel.taskbar", "AddToTaskbar", this, SLOT(addToTaskbar(QString)));
    QDBusConnection::sessionBus().connect(QString(), QString("/taskbar/quicklaunch"), "org.ukui.panel.taskbar", "RemoveFromTaskbar", this, SLOT(removeFromTaskbar(QString)));
}

/************************************************

 ************************************************/
UKUITaskBar::~UKUITaskBar()
{
    for (auto it = m_vBtn.begin(); it != m_vBtn.end();) {
        (*it)->deleteLater();
        m_vBtn.erase(it);
    }
    m_vBtn.clear();
}

QString UKUITaskBar::readFile(const QString &filename)
{
    QFile f(filename);
    if (!f.open(QFile::ReadOnly)) {
        return QString();
    } else {
        QTextStream in(&f);
        return in.readAll();
    }
}

void UKUITaskBar::onDesktopChanged()
{
    for (auto i = m_knownSdkWindows.begin(); m_knownSdkWindows.end() != i; ++i) {
        (*i)->onDesktopChanged();
        if ((*i)->m_existSameQckBtn) {
            UKUITaskGroup* btn = (*i)->getOwnQckBtn();
            if (m_vBtn.contains(btn))
                btn->setVisible((*i)->isHidden());
        }
    }
}

void UKUITaskBar::refreshQuickLaunch()
{
    for (auto it = m_vBtn.begin(); it != m_vBtn.end();) {
        (*it)->deleteLater();
        m_vBtn.erase(it);
    }

    QString desktop;
    QString file;

    //gsetting的方式读取写入 apps
    QList<QMap<QString, QVariant> > apps = m_plugin->settings()->readArray("apps");
    QString filename = QDir::homePath() + "/.config/ukui/panel.conf";
    QSettings user_qsettings(filename,QSettings::IniFormat);
    QStringList groupname = user_qsettings.childGroups();
    //为了兼容3.0版本和3.1版本，后续版本考虑删除
    if (apps.isEmpty() && groupname.contains("quicklaunch")) {
        apps = copyQuicklaunchConfig();
    } else if (groupname.contains("quicklaunch")) {
            user_qsettings.remove("quicklaunch");
    }

    for (const QMap<QString, QVariant> &app : apps) {
        desktop = app.value("desktop", "").toString();
        qDebug()<<"desktop  ******"<<desktop;

        file = app.value("file", "").toString();
        if (!desktop.isEmpty()) {
            XdgDesktopFile xdg;
            if (xdg.load(desktop)) {
                addSdkButton(new QuickLaunchAction(&xdg, this));
            }
        } else {
            qDebug()<<"error desktop file";
        }
    }
}

QList<QMap<QString, QVariant> > UKUITaskBar::copyQuicklaunchConfig()
{
    QString filename = QDir::homePath() + "/.config/ukui/panel.conf";
    //若taskbar中没有apps，则把quicklaunch中的内容复制到taskbar
    qDebug()<<"Taskbar is empty, read apps from quicklaunch";
    QSettings user_qsettings(filename,QSettings::IniFormat);
    user_qsettings.beginGroup("quicklaunch");
    QList<QMap<QString, QVariant> > array;
    int size = user_qsettings.beginReadArray("apps");
    for (int i = 0; i < size; ++i) {
        user_qsettings.setArrayIndex(i);
        QMap<QString, QVariant> map;
        map["desktop"] = user_qsettings.value("desktop");
        if (array.contains(map)) {
            continue;
        } else {
            array << map;
        }
    }
    user_qsettings.endArray();
    user_qsettings.endGroup();
    user_qsettings.remove("quicklaunch");
    user_qsettings.sync();
    return array;
}

//bool UKUITaskBar::acceptWindow(WId window) const
//{
//    QFlags<NET::WindowTypeMask> ignoreList;
//    ignoreList |= NET::DesktopMask;
//    ignoreList |= NET::DockMask;
//    ignoreList |= NET::SplashMask;
//    ignoreList |= NET::ToolbarMask;
//    ignoreList |= NET::MenuMask;
//    ignoreList |= NET::PopupMenuMask;
//    ignoreList |= NET::NotificationMask;

//    KWindowInfo info(window, NET::WMWindowType | NET::WMState, NET::WM2TransientFor);
//    if (!info.valid()) {
//        return false;
//    }

//    if (NET::typeMatchesMask(info.windowType(NET::AllTypesMask), ignoreList)) {
//        return false;
//    }

//    if (info.state() & NET::SkipTaskbar) {
//        return false;
//    }

//    // WM_TRANSIENT_FOR hint not set - normal window
//    WId transFor = info.transientFor();
//    if (transFor == 0 || transFor == window || transFor == (WId) QX11Info::appRootWindow()) {
//        return true;
//    }

//    info = KWindowInfo(transFor, NET::WMWindowType);

//    QFlags<NET::WindowTypeMask> normalFlag;
//    normalFlag |= NET::NormalMask;
//    normalFlag |= NET::DialogMask;
//    normalFlag |= NET::UtilityMask;

//    return !NET::typeMatchesMask(info.windowType(NET::AllTypesMask), normalFlag);
//}

bool UKUITaskBar::acceptWindow(const WindowId& window) const
{
    QString windowTitle = WindowManager::getWindowTitle(window);
    if (windowTitle == "UKUI Panel" || windowTitle == "桌面") {
        return false;
    }
    return true;
}

void UKUITaskBar::dragEnterEvent(QDragEnterEvent* event)
{
}

void UKUITaskBar::dragMoveEvent(QDragMoveEvent * event)
{
}

void UKUITaskBar::dropEvent(QDropEvent *e)
{
}

void UKUITaskBar::buttonMove(UKUITaskGroup * dst, UKUITaskGroup * src, QPoint const & pos)
{
    int src_index;
    if (!src || -1 == (src_index = m_layout->indexOf(src))) {
        return;
    }

    const int size = m_layout->count();
    Q_ASSERT(0 < size);
    //dst is nullptr in case the drop occured on empty space in taskbar
    int dst_index;
    if (nullptr == dst) {
        //moving based on taskbar (not signaled by button)
        QRect occupied = m_layout->occupiedGeometry();
        QRect last_empty_row{occupied};
        const QRect last_item_geometry = m_layout->itemAt(size - 1)->geometry();
        if (m_plugin->panel()->isHorizontal()) {
            if (isRightToLeft()) {
                last_empty_row.setTopRight(last_item_geometry.topLeft());
            } else {
                last_empty_row.setTopLeft(last_item_geometry.topRight());
            }
        } else {
            if (isRightToLeft()) {
                last_empty_row.setTopRight(last_item_geometry.topRight());
            } else {
                last_empty_row.setTopLeft(last_item_geometry.topLeft());
            }
        }
        if (occupied.contains(pos) && !last_empty_row.contains(pos)) {
            return;
        }

        dst_index = size;
    } else {
        //moving based on signal from child button
        dst_index = m_layout->indexOf(dst);
    }

    //moving lower index to higher one => consider as the QList::move => insert(to, takeAt(from))
    if (src_index < dst_index) {
        if (size == dst_index || src_index + 1 != dst_index) {
            --dst_index;
        } else {
            //switching positions of next standing
            const int tmp_index = src_index;
            src_index = dst_index;
            dst_index = tmp_index;
        }
    }

    if (dst_index == src_index || m_layout->animatedMoveInProgress()) {
        return;
    }

    m_layout->moveItem(src_index, dst_index, true);
}

void UKUITaskBar::groupSdkBecomeEmptySlot()
{
    //group now contains no buttons - clean up in hash and delete the group
    UKUITaskGroup * const group = qobject_cast<UKUITaskGroup*>(sender());
    Q_ASSERT(group);

    for (auto i = m_knownSdkWindows.begin(); m_knownSdkWindows.end() != i; ) {
        if (group == *i) {
            m_sdkSwid.removeOne(i.key());
            i = m_knownSdkWindows.erase(i);
            break;
        } else {
            ++i;
        }
    }
    for (auto it = m_vBtn.begin(); it!=m_vBtn.end(); ++it) {
        UKUITaskGroup *pQuickBtn = *it;
        if(pQuickBtn->m_fileName == group->m_fileName
           &&(m_layout->indexOf(pQuickBtn) >= 0 )) {
            pQuickBtn->setHidden(false);
            m_layout->moveItem(m_layout->indexOf(pQuickBtn), m_layout->indexOf(group));
            pQuickBtn->m_existSameQckBtn = false;
            break;
        }
    }
    m_layout->removeWidget(group);
    group->deleteLater();
}

void UKUITaskBar::addWindow(const WindowId& window)
{
    // If grouping disabled group behaves like regular button
    const QString group_id = m_groupingEnabled ? WindowManager::getWindowGroup(window) : QString("%1").arg(window.toInt());
    if (m_ignoreWindow.contains(group_id)) {
        return;
    }

    UKUITaskGroup *group = nullptr;
    bool isNeedAddNewWidget = true;
    auto i_group = m_knownSdkWindows.find(window.toInt());
    if (m_knownSdkWindows.end() != i_group) {
        if ((*i_group)->groupName() == group_id) {
            group = *i_group;
        } else {
            (*i_group)->onWindowRemoved(window);
        }
    }

    QStringList andriod_window_list;
    andriod_window_list<<"kydroid-display-window"<<"kylin-kmre-window"<<"";
    if (!group && m_groupingEnabled && !andriod_window_list.contains(group_id)) {
        for (auto i = m_knownSdkWindows.cbegin(), i_e = m_knownSdkWindows.cend(); i != i_e; ++i) {
            if ((*i)->groupName() == group_id) {
                group = *i;
                break;
            }
        }
    }

    if (!group) {
        group = new UKUITaskGroup(group_id, window, this);
        connect(group, SIGNAL(groupBecomeEmpty(QString)), this, SLOT(groupSdkBecomeEmptySlot()));
        connect(group, SIGNAL(t_saveSettings()), this, SLOT(saveSdkSettingsSlot()));
//        connect(group, SIGNAL(WindowAddtoTaskBar(QString)), this, SLOT(WindowSdkAddtoTaskBar(QString)));
//        connect(group, SIGNAL(WindowRemovefromTaskBar(QString)), this, SLOT(WindowRemovefromTaskBar(QString)));
        connect(group, SIGNAL(visibilityChanged(bool)), this, SLOT(refreshPlaceholderVisibility()));
        connect(group, &UKUITaskGroup::popupShown, this, &UKUITaskBar::popupShown);
        connect(group, &UKUITaskButton::dragging, this, [this] (QObject * dragSource, QPoint const & pos) {
                switchButtons(qobject_cast<UKUITaskGroup *>(sender()), qobject_cast<UKUITaskGroup *>(dragSource));//, pos);
                });
        for (auto it = m_vBtn.begin(); it!=m_vBtn.end(); ++it) {
            UKUITaskGroup *pQuickBtn = *it;
            if(pQuickBtn->m_fileName == group->m_fileName
               &&(m_layout->indexOf(pQuickBtn) >= 0 )) {
                m_layout->addWidget(group);
                m_layout->moveItem(m_layout->indexOf(group), m_layout->indexOf(pQuickBtn));
                pQuickBtn->setHidden(true);
                isNeedAddNewWidget = false;
                group->m_existSameQckBtn = true;
                pQuickBtn->m_existSameQckBtn = true;
                group->setQckLchBtn(pQuickBtn);
                break;
            }
        }
        if(isNeedAddNewWidget) {
            m_layout->addWidget(group);
        }
        group->setToolButtonsStyle(m_buttonStyle);
    }
    m_knownSdkWindows[window.toInt()] = group;
    m_sdkSwid.push_back(window.toInt());
    group->addWindow(window);
    group->groupName();
    group->updateSdkIcon();
}

auto UKUITaskBar::removeWindow(windowSdkMap_t::iterator pos) -> windowSdkMap_t::iterator
{
    qint32 const windowid = pos.key();
    UKUITaskGroup * const group = *pos;
    m_sdkSwid.removeOne(windowid);
    auto ret = m_knownSdkWindows.erase(pos);
    WindowId window = WindowId(windowid);
    group->onWindowRemoved(window);
    return ret;
}

void UKUITaskBar::refreshTaskList()
{
//    QList<WId> new_list;
    QList<qint32> new_list;
    // Just add new windows to groups, deleting is up to the groups
//    const auto wnds = KWindowSystem::stackingOrder();
    const auto wnds = WindowManager::windows();
    for (int i = 0; i < wnds.size(); i++) {
        if (acceptWindow(wnds.at(i))) {
            new_list << wnds.at(i).toInt();
            addWindow(wnds.at(i));
        }
    }
  //  m_layout->addWidget(m_tmpWidget);

    //emulate windowRemoved if known window not reported by KWindowSystem
    for (auto i = m_knownSdkWindows.begin(), i_e = m_knownSdkWindows.end(); i != i_e; ) {
        if (0 > new_list.indexOf(i.key())) {
            i = removeWindow(i);
        } else {
            ++i;
        }
    }

    refreshPlaceholderVisibility();
}


void UKUITaskBar::onWindowChanged(const WindowId& window)
{
    auto i = m_knownSdkWindows.find(window.toInt());
    if (m_knownSdkWindows.end() != i) {
        if (!(*i)->onWindowChanged(window) && acceptWindow(window)) {
            // window is removed from a group because of class change, so we should add it again
            addWindow(window);
        }
    }
}


void UKUITaskBar::onWindowAdded(const WindowId& window)
{
    auto const pos = m_knownSdkWindows.find(window.toInt());
    if (m_knownSdkWindows.end() == pos && acceptWindow(window)) {
        addWindow(window);
    }
}

void UKUITaskBar::onWindowRemoved(const WindowId& window)
{
    auto const pos = m_knownSdkWindows.find(window.toInt());
    if (m_knownSdkWindows.end() != pos) {
        removeWindow(pos);
    }
}

void UKUITaskBar::refreshButtonRotation()
{
    bool autoRotate = m_autoRotate && (m_buttonStyle != Qt::ToolButtonIconOnly);

    IUKUIPanel::Position panelPosition = m_plugin->panel()->position();
   // emit buttonRotationRefreshed(autoRotate, panelPosition);
}

/************************************************

 ************************************************/
void UKUITaskBar::refreshPlaceholderVisibility()
{
    bool haveVisibleWindow = false;
    for (auto i = m_knownSdkWindows.cbegin(), i_e = m_knownSdkWindows.cend(); i_e != i; ++i) {
        if ((*i)->isVisible()) {
            haveVisibleWindow = true;
            break;
        }
    }
    m_placeHolder->setVisible(!haveVisibleWindow);
    if (haveVisibleWindow || m_layout->count() != 0) {
        m_placeHolder->setFixedSize(0,0);
     } else {
        m_placeHolder->setMinimumSize(1,1);
        m_placeHolder->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
    }
}

/************************************************

 ************************************************/
void UKUITaskBar::setButtonStyle(Qt::ToolButtonStyle buttonStyle)
{
    emit buttonStyleRefreshed(m_buttonStyle);
}

void UKUITaskBar::settingsChanged()
{
    bool groupingEnabledOld = m_groupingEnabled;
    bool showOnlyOneDesktopTasksOld = m_showOnlyOneDesktopTasks;
    const int showDesktopNumOld = m_showDesktopNum;
    bool showOnlyCurrentScreenTasksOld = m_showOnlyCurrentScreenTasks;
    bool showOnlyMinimizedTasksOld = m_showOnlyMinimizedTasks;
    const bool iconByClassOld = m_iconByClass;

    m_buttonWidth = m_plugin->settings()->value("buttonWidth", 400).toInt();
    m_buttonHeight = m_plugin->settings()->value("buttonHeight", 100).toInt();
    QString s = m_plugin->settings()->value("buttonStyle").toString().toUpper();

    if (s == "ICON") {
        setButtonStyle(Qt::ToolButtonIconOnly);
    } else if (s == "TEXT") {
        setButtonStyle(Qt::ToolButtonTextOnly);
    } else {
        setButtonStyle(Qt::ToolButtonIconOnly);
    }

    m_showOnlyOneDesktopTasks = m_plugin->settings()->value("showOnlyOneDesktopTasks", m_showOnlyOneDesktopTasks).toBool();
    m_showDesktopNum = m_plugin->settings()->value("showDesktopNum", m_showDesktopNum).toInt();
    m_showOnlyCurrentScreenTasks = m_plugin->settings()->value("showOnlyCurrentScreenTasks", m_showOnlyCurrentScreenTasks).toBool();
    m_showOnlyMinimizedTasks = m_plugin->settings()->value("showOnlyMinimizedTasks", m_showOnlyMinimizedTasks).toBool();
    m_autoRotate = m_plugin->settings()->value("autoRotate", true).toBool();
    m_closeOnMiddleClick = m_plugin->settings()->value("closeOnMiddleClick", true).toBool();
    m_raiseOnCurrentDesktop = m_plugin->settings()->value("raiseOnCurrentDesktop", false).toBool();
    m_groupingEnabled = m_plugin->settings()->value("groupingEnabled",true).toBool();
    m_showGroupOnHover = m_plugin->settings()->value("showGroupOnHover",true).toBool();
    m_iconByClass = m_plugin->settings()->value("iconByClass", false).toBool();
    m_cycleOnWheelScroll = m_plugin->settings()->value("cycleOnWheelScroll", true).toBool();

    // Delete all groups if grouping feature toggled and start over
    if (groupingEnabledOld != m_groupingEnabled) {
        for (int i = m_knownSdkWindows.size() - 1; 0 <= i; --i) {
            UKUITaskGroup * group = m_knownSdkWindows.value(m_sdkSwid.value(i));
            if (nullptr != group) {
                m_layout->takeAt(i);
                group->deleteLater();
            }
        }
        m_knownSdkWindows.clear();
        m_sdkSwid.clear();
    }

    if (showOnlyOneDesktopTasksOld != m_showOnlyOneDesktopTasks
            || (m_showOnlyOneDesktopTasks && showDesktopNumOld != m_showDesktopNum)
            || showOnlyCurrentScreenTasksOld != m_showOnlyCurrentScreenTasks
            || showOnlyMinimizedTasksOld != m_showOnlyMinimizedTasks
            ) {
        emit showOnlySettingChanged();
    }
    if (iconByClassOld != m_iconByClass) {
        emit iconByClassChanged();
    }

    refreshTaskList();
}

void UKUITaskBar::setShowGroupOnHover(bool bFlag)
{
    m_showGroupOnHover = bFlag;
}

int i = 0;

void UKUITaskBar::realignSdk()
{
    m_layout->setEnabled(false);
    refreshButtonRotation();

    IUKUIPanel *panel = m_plugin->panel();
    QSize maxSize = QSize(m_plugin->panel()->panelSize(), m_plugin->panel()->panelSize());
    QSize minSize = QSize(m_plugin->panel()->iconSize()/2, m_plugin->panel()->iconSize()/2);
    int iconsize = panel->iconSize();

    bool rotated = false;
    if (panel->isHorizontal()) {
        this->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
        this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        m_allFrame->setMinimumSize(QSize((m_layout->count()+5)*panel->panelSize(),panel->panelSize()));
        if (m_allFrame->width() < this->width()) {
            m_allFrame->setFixedWidth(this->width());
        }

        m_layout->setRowCount(panel->lineCount());
        m_layout->setColumnCount(0);
    } else {
        this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
        this->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
        m_allFrame->setMinimumSize(QSize(panel->panelSize(),(m_layout->count()+3)*panel->panelSize()));
        if (m_allFrame->height() < this->height()) {
            m_allFrame->setFixedHeight(this->height());
        }

        m_layout->setRowCount(0);

        if (m_buttonStyle == Qt::ToolButtonIconOnly) {
            // Vertical + Icons
            m_layout->setColumnCount(panel->lineCount());
        } else {
            rotated = m_autoRotate && (panel->position() == IUKUIPanel::PositionLeft || panel->position() == IUKUIPanel::PositionRight);

            // Vertical + Text
            if (rotated) {
                maxSize.rwidth()  = m_buttonHeight;
                maxSize.rheight() = m_buttonWidth;

                m_layout->setColumnCount(panel->lineCount());
            } else {
                m_layout->setColumnCount(1);
            }
        }
    }

    for(auto it= m_knownSdkWindows.begin(); it != m_knownSdkWindows.end();it++) {
        UKUITaskGroup *group = it.value();
        group->setIconSize(QSize(iconsize,iconsize));
    }
    for (int i = 0; i < m_vBtn.size(); i++) {
        UKUITaskGroup * quicklaunch = m_vBtn.value(i);
        quicklaunch->setIconSize(QSize(iconsize, iconsize));
    }
    m_layout->setCellMinimumSize(minSize);
    m_layout->setCellMaximumSize(maxSize);
    m_layout->setDirection(rotated ? UKUi::GridLayout::TopToBottom : UKUi::GridLayout::LeftToRight);
    m_layout->setEnabled(true);
    //our placement on screen could have been changed
    emit showOnlySettingChanged();
    emit refreshIconGeometry();

    horizontalScrollBar()->setMaximum(m_allFrame->width() - this->width());
    verticalScrollBar()->setMaximum(m_allFrame->height() - this->height());
}

void UKUITaskBar::wheelEvent(QWheelEvent* event)
{
    if (this->verticalScrollBarPolicy()==Qt::ScrollBarAlwaysOff) {
        if (event->delta()>=0) {
            horizontalScrollBar()->setValue(horizontalScrollBar()->value()-40);
            qDebug()<<"-40-horizontalScrollBar()->value()"<<horizontalScrollBar()->value();
        } else {
            horizontalScrollBar()->setValue(horizontalScrollBar()->value()+40);
            if (horizontalScrollBar()->value()>m_allFrame->width()) {
                horizontalScrollBar()->setValue(m_allFrame->width());
            }
            qDebug()<<"+40+horizontalScrollBar()->value()"<<horizontalScrollBar()->value();
        }
    } else {
        if (event->delta()>=0) {
            verticalScrollBar()->setValue(verticalScrollBar()->value()-40);
        } else {
            verticalScrollBar()->setValue(verticalScrollBar()->value()+40);
        }
    }
}

void UKUITaskBar::resizeEvent(QResizeEvent* event)
{
    emit refreshIconGeometry();
    return QWidget::resizeEvent(event);
}

void UKUITaskBar::changeEvent(QEvent* event)
{
    // if current style is changed, reset the base style of the proxy style
    // so we can apply the new style correctly to task buttons.
    if(event->type() == QEvent::StyleChange)
        m_style->setBaseStyle(NULL);

    QFrame::changeEvent(event);
}

void UKUITaskBar::activateSdkTask(int pos)
{
    for (int i = 0; i < m_knownSdkWindows.size(); ++i) {
        UKUITaskGroup * g = m_knownSdkWindows.value(m_sdkSwid.value(i));
        if (g && g->isVisible()) {
            pos--;
            if (pos == 0) {
                g->raiseSdkApplication();
                break;
            }
        }
    }
}

void UKUITaskBar::enterEvent(QEvent *)
{
    m_taskStatus=HOVER;
    update();
}

void UKUITaskBar::leaveEvent(QEvent *)
{
    m_taskStatus=NORMAL;
    update();
}

void UKUITaskBar::paintEvent(QPaintEvent *)
{
        QStyleOption opt;
        opt.initFrom(this);
        QPainter p(this);

        p.setRenderHint(QPainter::Antialiasing);
        QPainterPath rectPath;
        rectPath.addRoundedRect(this->rect(),6,6);
        // 画一个黑底
        QPixmap pixmap(this->rect().size());
        pixmap.fill(Qt::transparent);
        QPainter pixmapPainter(&pixmap);
        pixmapPainter.setRenderHint(QPainter::Antialiasing);

        pixmapPainter.drawPath(rectPath);
        pixmapPainter.end();

        // 模糊这个黑底
        extern void qt_blurImage(QImage &blurImage, qreal radius, bool quality, int transposed);
        QImage img = pixmap.toImage();
        qt_blurImage(img, 10, false, false);

        switch(m_taskStatus) {
          case NORMAL:
              {
                  p.setPen(Qt::NoPen);
                  break;
              }
          case HOVER:
              {
                  p.setPen(Qt::NoPen);
                  break;
              }
          case PRESS:
              {
                  p.setPen(Qt::NoPen);
                  break;
              }
          }

        QPalette pal = this->palette();
        pal.setBrush(QPalette::Base, QColor(0,0,0,0));        //背景透明
        this->viewport()->setPalette(pal);
        this->setPalette(pal);
        m_allFrame->setPalette(pal);

        p.setRenderHint(QPainter::Antialiasing);
        p.drawRoundedRect(opt.rect,6,6);
        style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

void UKUITaskBar::mouseMoveEvent(QMouseEvent *e)
{
    QFrame::mouseMoveEvent(e);
}


void UKUITaskBar::mousePressEvent(QMouseEvent *)
{
    QDBusMessage message =QDBusMessage::createSignal("/taskbar/click", "com.ukui.panel.plugins.taskbar", "sendToUkuiDEApp");
    QDBusConnection::sessionBus().send(message);
}

///////////////////////////////////////////


////////////////////////////////////////////////////////////////////
/// About Quick Launch Functions
///

void UKUITaskBar::addSdkButton(QuickLaunchAction* action)
{
    bool isNeedAddNewWidget = true;
    m_layout->setEnabled(false);
    UKUITaskGroup *btn = new UKUITaskGroup(action, m_plugin, this);
    btn->setArrowType(Qt::NoArrow);
    /*＠bug
     * 快速启动栏右键菜单原本的样式有对于不可选项有置灰效果，
     * 后跟随主题框架之后置灰效果消失，可能与此属性相关
     */
    //        btn->setMenu(Qt::InstantPopup);
    for (auto it = m_knownSdkWindows.begin(); it!=m_knownSdkWindows.end(); ++it) {
        UKUITaskGroup *group = *it;
        if(btn->m_fileName == group->m_fileName
           &&(m_layout->indexOf(group) >= 0)) {
            m_layout->addWidget(btn);
            m_layout->moveItem(m_layout->indexOf(btn), m_layout->indexOf(group));
            isNeedAddNewWidget = false;
            group->m_existSameQckBtn = true;
            btn->m_existSameQckBtn = true;
            m_vBtn.push_back(btn);
            group->setQckLchBtn(btn);
            btn->setHidden(group->isVisible());
            break;
        }
    }
    if (isNeedAddNewWidget) {
        m_layout->addWidget(btn);
        btn->setIconSize(QSize(m_plugin->panel()->iconSize(),m_plugin->panel()->iconSize()));
        m_vBtn.push_back(btn);
        m_layout->moveItem(m_layout->indexOf(btn), countOfButtons() - 1);
    }
    connect(btn, &UKUITaskButton::dragging, this, [this] (QObject * dragSource, QPoint const & pos) {
            switchButtons(qobject_cast<UKUITaskGroup *>(sender()), qobject_cast<UKUITaskGroup *>(dragSource));//, pos);
            });
    connect(btn, SIGNAL(buttonDeleted()), this, SLOT(buttonSdkDeleted()));
    connect(btn, SIGNAL(t_saveSettings()), this, SLOT(saveSdkSettingsSlot()));
    m_layout->setEnabled(true);
}

void UKUITaskBar::switchButtons(UKUITaskGroup *dst_button, UKUITaskGroup *src_button)
{
    if (dst_button == src_button) {
        return;
    }
    if (!dst_button || !src_button) {
        return;
    }

    int dst = m_layout->indexOf(dst_button);
    int src = m_layout->indexOf(src_button);
    if (dst == src || m_layout->animatedMoveInProgress()) {
        return;
    }
    m_layout->moveItem(src, dst, true);
    saveSdkSettings();
}

bool UKUITaskBar::checkButton(QuickLaunchAction* action)
{
    bool checkresult;
    UKUITaskGroup* btn = new UKUITaskGroup(action, m_plugin, this);
    int i = 0;
    int counts = m_vBtn.size();
    if (m_vBtn.size()>0) {
        while (i != counts) {
            UKUITaskGroup *b = m_vBtn.value(i);
            qDebug()<<"m_layout->itemAt("<<i<<") ";
            if(b->m_fileName == btn->m_fileName) {
                checkresult=true;
                break;
            } else {
                checkresult=false;
                ++i;
            }
        }
        delete btn;
        return checkresult;
    } else {
        qDebug()<<"countOfButtons =  "<<countOfButtons();
        delete btn;
        return false;
    }
}

/* 以xdg的方式删除　button*/
void UKUITaskBar::removeButton(QuickLaunchAction* action)
{
    int i = 0;
    UKUITaskGroup* btn = new UKUITaskGroup(action, m_plugin, this);
    if (!btn) {
        return;
    }
    while (i < m_vBtn.size()) {
        UKUITaskGroup *tmp = m_vBtn.value(i);
        if (QString::compare(btn->m_fileName, tmp->m_fileName) == 0) {
            doInitGroupButton(tmp->m_fileName);
            tmp->deleteLater();
            m_layout->removeWidget(tmp);
            m_vBtn.remove(i);
            break;
        }
        ++i;
    }

    btn->deleteLater();
    saveSdkSettings();
}

void UKUITaskBar::removeButton(QString file)
{
    int i = 0;
    while (i < m_vBtn.size()) {
        UKUITaskGroup *tmp = m_vBtn.value(i);
        if (QString::compare(file, tmp->m_fileName) == 0) {
            doInitGroupButton(tmp->m_fileName);
            tmp->deleteLater();
            m_layout->removeWidget(tmp);
            m_vBtn.remove(i);
            break;
        }
        ++i;
    }
}

void UKUITaskBar::WindowSdkAddtoTaskBar(QString arg)
{
    for(auto it= m_knownSdkWindows.begin(); it != m_knownSdkWindows.end();it++) {
        UKUITaskGroup *group = it.value();
            if (arg.compare(group->groupName()) == 0) {
                addSdkToTaskbar(group->m_fileName);
                break;
        }
    }
}

void UKUITaskBar::WindowRemovefromTaskBar(QString arg)
{
    for (auto it = m_vBtn.begin(); it!=m_vBtn.end(); ++it) {
        UKUITaskGroup *pQuickBtn = *it;
        if(pQuickBtn->m_fileName == arg && (m_layout->indexOf(pQuickBtn) >= 0 )) {
            doInitGroupButton(pQuickBtn->m_fileName);
            m_vBtn.removeOne(pQuickBtn);
            pQuickBtn->deleteLater();
            m_layout->removeWidget(pQuickBtn);
            saveSdkSettings();
            break;
        }
    }
}

// 只要任何监控的目录更新（添加、删除、重命名），就会调用。
void UKUITaskBar::directoryUpdated(const QString &path)
{
    // 比较最新的内容和保存的内容找出区别(变化)
    QStringList currentrylist = m_currentContentsMap[path];
    const QDir dir(path);
    QStringList newentrylist = dir.entryList(QDir::NoDotAndDotDot  | QDir::AllDirs | QDir::Files, QDir::DirsFirst);
    QSet<QString> newdirset = QSet<QString>::fromList(newentrylist);
    QSet<QString> currentdirset = QSet<QString>::fromList(currentrylist);

    // 添加了文件
    QSet<QString> newfiles = newdirset - currentdirset;
    QStringList newfile = newfiles.toList();

    // 文件已被移除
    QSet<QString> deletedfiles = currentdirset - newdirset;
    QStringList deletefile = deletedfiles.toList();

    // 更新当前设置
    m_currentContentsMap[path] = newentrylist;

    if (!newfile.isEmpty() && !deletefile.isEmpty()) {
        // 文件/目录重命名
        if ((newfile.count() == 1) && (deletefile.count() == 1)) {
//            qDebug() << QString("File Renamed from %1 to %2").arg(deleteFile.first()).arg(newFile.first());
        }
    } else {
        // 从Dir中删除文件/目录
        if (!deletefile.isEmpty()) {
            foreach (QString file, deletefile) {
                removeButton(path+file);
            }
        }
    }
}

void UKUITaskBar::addToTaskbar(QString arg)
{
    const auto url=QUrl(arg);
    QString fileName(url.isLocalFile() ? url.toLocalFile() : url.url());
    QFileInfo fi(fileName);
    XdgDesktopFile xdg;
    if (xdg.load(fileName)) {
        if (!checkButton(new QuickLaunchAction(&xdg, this))) {
            addSdkButton(new QuickLaunchAction(&xdg, this));
            m_placeHolder->hide();
        }
    } else {
        qWarning() << "XdgDesktopFile" << fileName << "is not valid";
        QMessageBox::information(this, tr("Drop Error"),
                                 tr("File/URL '%1' cannot be embedded into QuickLaunch for now").arg(fileName)
                                 );
    }
    saveSdkSettings();
}

void UKUITaskBar::addSdkToTaskbar(QString arg)
{
    const auto url=QUrl(arg);
    QString fileName(url.isLocalFile() ? url.toLocalFile() : url.url());
    QFileInfo fi(fileName);
    XdgDesktopFile xdg;
    if (xdg.load(fileName)) {
        if (!checkButton(new QuickLaunchAction(&xdg, this))) {
            addSdkButton(new QuickLaunchAction(&xdg, this));
            m_placeHolder->hide();
        }
    } else {
        qWarning() << "XdgDesktopFile" << fileName << "is not valid";
        QMessageBox::information(this, tr("Drop Error"),
                                 tr("File/URL '%1' cannot be embedded into QuickLaunch for now").arg(fileName)
                                 );
    }
    saveSdkSettings();
}

void UKUITaskBar::removeFromTaskbar(QString arg)
{
    XdgDesktopFile xdg;
    xdg.load(arg);
    removeButton(new QuickLaunchAction(&xdg, this));
}

void UKUITaskBar::doInitGroupButton(QString sname)
{
    for(auto it= m_knownSdkWindows.begin(); it != m_knownSdkWindows.end();it++) {
        UKUITaskGroup *group = it.value();
        if (group->m_existSameQckBtn) {
            if (sname == group->m_fileName) {
                    group->m_existSameQckBtn = false;
                    group->setQckLchBtn(NULL);
                    break;
            }
        }
    }
}

void UKUITaskBar::buttonSdkDeleted()
{
    UKUITaskGroup *btn = qobject_cast<UKUITaskGroup*>(sender());
    if (!btn) {
        return;
    }
    for (auto it = m_vBtn.begin(); it != m_vBtn.end(); it++) {
        if (*it == btn) {
            for (auto it= m_knownSdkWindows.begin(); it != m_knownSdkWindows.end(); it++) {
                UKUITaskGroup *group = it.value();
                if (group->m_existSameQckBtn) {
                    if (btn->m_fileName == group->m_fileName) {
                            group->m_existSameQckBtn = false;
                            group->setQckLchBtn(NULL);
                    }
                }
            }
            m_vBtn.erase(it);
            break;
        }
    }
    m_layout->removeWidget(btn);
    btn->deleteLater();
    saveSdkSettings();
}


void UKUITaskBar::saveSdkSettingsSlot()
{
    saveSdkSettings();
}

void UKUITaskBar::saveSdkSettings()
{
    PluginSettings *settings = m_plugin->settings();
    settings->remove("apps");
    QList<QMap<QString, QVariant>> hashList;
    int size = m_layout->count();
    for (int j = 0; j < size; ++j) {
        UKUITaskGroup *b = qobject_cast<UKUITaskGroup*>(m_layout->itemAt(j)->widget());
        if (!(m_vBtn.contains(b) || m_knownSdkWindows.contains(m_knownSdkWindows.key(b)))) {
            continue;
        }
        if (!b->m_statFlag && b->m_existSameQckBtn) {
            continue;
        }
        if (!b) {
            continue;
        }
        if (b->m_statFlag && b->m_existSameQckBtn) {
            b = b->getQckLchBtn();
        }
        if (!b || b->m_statFlag) {
            continue;
        }
        // convert QHash<QString, QString> to QMap<QString, QVariant>
        QMap<QString, QVariant> map;
        QHashIterator<QString, QString> it(b->settingsMap());
        while (it.hasNext()) {
            it.next();
            map[it.key()] = it.value();
        }
        hashList << map;
    }
    settings->setArray("apps", hashList);
}

int UKUITaskBar::indexOfButton(UKUITaskGroup* button) const
{
    return m_layout->indexOf(button);
}

int UKUITaskBar::countOfButtons() const
{
    return m_layout->count();
}


QString UKUITaskBar::captionExchange(QString str)
{
    QString temp_group_id=str;
    QStringList strList = temp_group_id.split(" ");
    QString group_id = strList[0];
    QStringList video_list;
    if (m_androidIconHash.keys().contains(temp_group_id)) {
        group_id=m_androidIconHash.value(temp_group_id);
    } else {
        video_list<<"影音"<<"Video";
        if(video_list.contains(group_id)) group_id ="kylin-video";
        else group_id="application-x-desktop";
    }
    return group_id;
}

QHash<QString,QString> UKUITaskBar::matchAndroidIcon()
{
    QHash<QString,QString> hash;
    printf("*************\n");
    QFile file("/usr/share/ukui/ukui-panel/plugin-taskbar/name-icon.match");
    if (!file.open(QIODevice::ReadOnly)) {
        qDebug()<<"Read FIle failed";
    }
    while (!file.atEnd()) {
        QByteArray line= file.readLine();
        QString str=file.readLine();
        str.section('picture',1,1).trimmed().toStdString();
        str.simplified();
        QString str_name = str.section(QRegExp("[;]"),0,0);
        str_name = str_name.simplified();
        str_name = str_name.remove("name=");

        QString str_icon = str.section(QRegExp("[;]"),1,1);
        str_icon = str_icon.simplified();
        str_icon = str_icon.remove("icon=");

        hash.insert(str_name,str_icon);
    }

    return hash;
}
