/*
 * Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd.
 *
 * This program 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, or (at your option)
 * any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/&gt;.
 *
 */

/********************************************************************
  Inspired by freedesktops tint2 ;)

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

/*
 * Some code in this file is commented but not deleted
 * because these commented codes are the old loading trayApp
 * I want to wait until the new version loading trayApp is stable before deleting
*/

#include <QApplication>
#include <QDebug>
#include <QTimer>
#include <QtX11Extras/QX11Info>
#include <QPainter>
#include <QtDBus/QtDBus>
#include "trayicon.h"
#include "../panel/iukuipanel.h"
#include "../panel/common/ukuigridlayout.h"
#include "ukuitray.h"
#include "xfitman.h"

#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/extensions/Xrender.h>
#include <X11/extensions/Xdamage.h>
#include <xcb/xcb.h>
#include <xcb/damage.h>
#include "ukuitrayplugin.h"
#undef Bool // defined as int in X11/Xlib.h

#include "../panel/iukuipanelplugin.h"

#include <QPushButton>
#include <QToolButton>
#include <QLabel>
#include <QMouseEvent>

#include "traydynamicgsetting.h"

#define _NET_SYSTEM_TRAY_ORIENTATION_HORZ 0
#define _NET_SYSTEM_TRAY_ORIENTATION_VERT 1

#define SYSTEM_TRAY_REQUEST_DOCK    0
#define SYSTEM_TRAY_BEGIN_MESSAGE   1
#define SYSTEM_TRAY_CANCEL_MESSAGE  2

#define XEMBED_EMBEDDED_NOTIFY  0
#define XEMBED_MAPPED          (1 << 0)

#define mWinWidth 46
#define mWinHeight 46

/* qt会将glib里的signals成员识别为宏，所以取消该宏
 * 后面如果用到signals时，使用Q_SIGNALS代替即可
 **/
#ifdef signals
#undef signals
#endif
extern "C" {
#include <glib.h>
#include <gio/gio.h>
#include <dconf/dconf.h>
}

#define KEYBINDINGS_CUSTOM_SCHEMA "org.ukui.panel.tray"
#define KEYBINDINGS_CUSTOM_DIR "/org/ukui/tray/keybindings/"

#define ACTION_KEY "action"
#define RECORD_KEY "record"
#define BINDING_KEY "binding"
#define NAME_KEY "name"

#define TRAY_APP_COUNT 16

#define PANEL_SETTINGS "org.ukui.panel.settings"
#define PANEL_LINES    "panellines"
#define TRAY_LINE      "traylines"
#define PANEL_SIZE     "panelsize"
#define ICON_SIZE      "iconsize"

bool flag=false;
extern storageBarStatus status;

UKUITray::UKUITray(UKUITrayPlugin *plugin, QWidget *parent):
    QFrame(parent),
    mValid(false),
    mTrayId(0),
    mDamageEvent(0),
    mDamageError(0),
    mIconSize(TRAY_ICON_SIZE_DEFAULT, TRAY_ICON_SIZE_DEFAULT),
    mPlugin(plugin),
    mDisplay(QX11Info::display())
{
    qDebug()<<"Plugin-Tray :: UKUITray start";
    m_pwidget = NULL;
    status=ST_HIDE;

    const QByteArray id(PANEL_SETTINGS);
    if(QGSettings::isSchemaInstalled(id))
    {
        settings=new QGSettings(id);
    }
    connect(settings, &QGSettings::changed, this, [=] (const QString &key){
        if(key==ICON_SIZE){
            trayIconSizeRefresh();
            handleStorageUi();
        }
    });

    mLayout = new UKUi::GridLayout(this);
    setLayout(mLayout);
    _NET_SYSTEM_TRAY_OPCODE = XfitMan::atom("_NET_SYSTEM_TRAY_OPCODE");
    // Init the selection later just to ensure that no signals are sent until
    // after construction is done and the creating object has a chance to connect.
    QTimer::singleShot(3, this, SLOT(startTray()));
    mBtn =new StorageArrow(this);
    mLayout->addWidget(mBtn);
    storageFrame=new UKUIStorageFrame;
    // fix 任务栏可隐藏时，鼠标放到traystorage时任务栏也会隐藏问题
    mPlugin->willShowWindow(storageFrame);
    mStorageLayout = new UKUi::GridLayout(storageFrame);
    storageFrame->setLayout(mStorageLayout);
    handleStorageUi();
    connect(mBtn,SIGNAL(clicked()),this,SLOT(storageBar()));
    mBtn->setVisible(true);
    realign();
    //进入桌面后可能存在的托盘区域未刷新问题
    QTimer::singleShot(100,[this] { realign(); trayIconSizeRefresh(); });
    //针对ukui桌面环境特殊应用的处理，保证稳定性
    //QTimer::singleShot(3000,[this] { panelStartupFcitx();});
    QTimer::singleShot(30000,[this] {
        //QProcess::execute("sh /usr/share/ukui/ukui-panel/plugin-tray/trayAppSetting.sh");
    });
    QDBusConnection::sessionBus().connect(QString(), QString("/taskbar/click"), "com.ukui.panel.plugins.taskbar", "sendToUkuiDEApp", this, SLOT(hideStorageWidget()));
    qDebug()<<"Plugin-Tray :: UKUITray end";
}

UKUITray::~UKUITray()
{
//    for(int i  = 0; i < mIcons.size(); i++)
//    {
//        if(mIcons[i])
//        {
//            mIcons[i]->deleteLater();
//            mIcons[i] = NULL;
//        }
//    }
//    mIcons.clear();
//    mStorageIcons.clear();
//    mTrayIcons.clear();
    freezeApp();
    stopTray();
}

void UKUITray::storageBar()
{
    if(mStorageIcons.size()<1) mBtn->setVisible(false);
    if(status==ST_HIDE)
    {
        status = ST_SHOW;
        showAndHideStorage(false);
    }
    else
    {
        status = ST_HIDE;
        showAndHideStorage(true);
    }
    realign();
}

void UKUITray::hideStorageWidget()
{
    status = ST_HIDE;
    showAndHideStorage(true);
}

void UKUITray::showAndHideStorage(bool storageStatus)
{
    if(storageStatus){
        storageFrame->hide();
    }else{
        storageFrame->show();
        handleStorageUi();
    }
}

bool UKUITray::nativeEventFilter(const QByteArray &eventType, void *message, long *)
{
    if (eventType != "xcb_generic_event_t")
        return false;

    xcb_generic_event_t* event = static_cast<xcb_generic_event_t *>(message);

    TrayIcon* icon;
    int event_type = event->response_type & ~0x80;

    switch (event_type)
    {
    /* 监听到托盘应用的启动事件
     */
    case ClientMessage:
        clientMessageEvent(event);
        repaint();
        break;

        //        case ConfigureNotify:
        //            icon = findIcon(event->xconfigure.window);
        //            if (icon)
        //                icon->configureEvent(&(event->xconfigure));
        //            break;


        /*
         * 监听到托盘应用的退出事件
         */
    case DestroyNotify: {
        /*
         * 在这里本应该刷新收纳栏 handleStorageUi()
         * 由于收纳栏不刷新可能会导致任务栏的崩溃
         * 在freeze信号接受的地方freezeTrayApp（）同样进行刷新收纳栏的操作
         * 但是如果在这里刷新收纳栏目会导致收纳栏的应用异常退出
         */

        unsigned long event_window;
        event_window = reinterpret_cast<xcb_destroy_notify_event_t*>(event)->window;
        icon = findIcon(event_window);
        if (icon)
        {
            icon->windowDestroyed(event_window);
            mTrayIcons.removeAll(icon);
            mStorageIcons.removeAll(icon);
            delete icon;
        }
        break;
    }
    default:
        if (event_type == mDamageEvent + XDamageNotify)
        {
            xcb_damage_notify_event_t* dmg = reinterpret_cast<xcb_damage_notify_event_t*>(event);
            icon = findIcon(dmg->drawable);
            if (icon)
                icon->update();
        }
        break;
    }

    return false;
}

void UKUITray::realign()
{
    mLayout->setEnabled(false);
    IUKUIPanel *panel = mPlugin->panel();

    /*　刷新托盘收纳栏界面
     * 不要在这里对收纳栏的图标执setFixedSize和setIconSize的操作
     * 这些应该在handleStorageUi()函数中执行
     * handleStorageUi();
    */
    if (panel->isHorizontal()){

        dynamic_cast<UKUi::GridLayout*>(mLayout)->setRowCount(panel->lineCount());
        dynamic_cast<UKUi::GridLayout*>(mLayout)->setColumnCount(0);
    }
    else{
        dynamic_cast<UKUi::GridLayout*>(mLayout)->setColumnCount(panel->lineCount());
        dynamic_cast<UKUi::GridLayout*>(mLayout)->setRowCount(0);
    }

    if(storageFrame){
        int storageFramePosition;
        if(mPlugin->panel()->isHorizontal()){
            storageFramePosition=(storageFrame->size().width()-mBtn->size().width())/2;
            storageFrame->setGeometry(mPlugin->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(-storageFramePosition,0)), storageFrame->size()));
        }
        else{
            storageFramePosition=(storageFrame->size().height()-mBtn->size().height())/2;
            storageFrame->setGeometry(mPlugin->panel()->calculatePopupWindowPos(mapToGlobal(QPoint(0,-storageFramePosition)), storageFrame->size()));
        }
    }

    if(mStorageIcons.size()<1) mBtn->setVisible(true);
    mLayout->setEnabled(true);
#if 0
    //设置任务栏
    for(int i=0;i<mTrayIcons.size();i++){
    TrayIcon *trayicon = mTrayIcons[i];
    connect(trayicon,&TrayIcon::iconIsMoving,[this](Window id){moveIconToStorage(id);});
    }
    for(int i=0;i<mStorageIcons.size();i++){
    TrayIcon *trayicon = mStorageIcons[i];
    connect(trayicon,&TrayIcon::iconIsMoving,[this](Window id){moveIconToTray(id);});
    }
#endif
}

void UKUITray::trayIconSizeRefresh()
{
    for(int i=0;i<mIcons.size();i++){
        if(mIcons.at(i)){
            if(mPlugin->panel()->isHorizontal()){
                mIcons.at(i)->setFixedSize(mPlugin->panel()->iconSize(),mPlugin->panel()->panelSize());
            }else{
                mIcons.at(i)->setFixedSize(mPlugin->panel()->panelSize(),mPlugin->panel()->iconSize());
            }
            mIcons.at(i)->setIconSize(QSize(mPlugin->panel()->iconSize()/2,mPlugin->panel()->iconSize()/2));
        }else{
            qDebug()<<"错误的托盘图标";
        }
    }
}

/*监听托盘事件*/
void UKUITray::clientMessageEvent(xcb_generic_event_t *e)
{
    unsigned long opcode;
    unsigned long message_type;
    Window id;
    xcb_client_message_event_t* event = reinterpret_cast<xcb_client_message_event_t*>(e);
    uint32_t* data32 = event->data.data32;
    message_type = event->type;
    opcode = data32[1];
    if(message_type != _NET_SYSTEM_TRAY_OPCODE)
        return;

    switch (opcode)
    {
    case SYSTEM_TRAY_REQUEST_DOCK:
        id = data32[2];
        if(id){
            regulateIcon(&id);
            trayIconSizeRefresh();
        }


    case SYSTEM_TRAY_BEGIN_MESSAGE:
    case SYSTEM_TRAY_CANCEL_MESSAGE:
//        qDebug() << "we don't show balloon messages.";
        break;

    default:
        //            if (opcode == xfitMan().atom("_NET_SYSTEM_TRAY_MESSAGE_DATA"))
        //                qDebug() << "message from dockapp:" << e->data.b;
        //            else
        //                qDebug() << "SYSTEM_TRAY : unknown message type" << opcode;
        break;
    }
}

/*遍历mIcons中的TrayIcon*/
TrayIcon* UKUITray::findIcon(Window id)
{
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
    for(int i=0;i<mIcons.size();i++){
        TrayIcon *icon=mIcons[i];
#endif
#if (QT_VERSION >= QT_VERSION_CHECK(5,7,0))
    for(TrayIcon* icon : qAsConst(mIcons) ){
#endif
        if (icon->iconId() == id || icon->windowId() == id)
            return icon;
    }
    return 0;
}

TrayIcon* UKUITray::findTrayIcon(Window id)
{
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
    for(int i=0;i<mTrayIcons.size();i++){
    TrayIcon *trayicon = mTrayIcons[i];
#endif
#if (QT_VERSION >= QT_VERSION_CHECK(5,7,0))
    for(TrayIcon* trayicon : qAsConst(mTrayIcons) ){
#endif
        if (trayicon->iconId() == id || trayicon->windowId() == id)
            return trayicon;
    }
    return 0;
}

TrayIcon* UKUITray::findStorageIcon(Window id)
{
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
    for(int i=0;i<mStorageIcons.size();i++){
    TrayIcon *storageicon=mStorageIcons[i];
#endif
#if (QT_VERSION >= QT_VERSION_CHECK(5,7,0))
    for(TrayIcon* storageicon :qAsConst(mStorageIcons)){
#endif
        if (storageicon->iconId() == id || storageicon->windowId() == id)
            return storageicon;
    }
    return 0;
}

void UKUITray::setIconSize()
{
    mIconSize=QSize(mPlugin->panel()->iconSize()/2,mPlugin->panel()->iconSize()/2);
    unsigned long size = qMin(mIconSize.width(), mIconSize.height());
    XChangeProperty(mDisplay,
                    mTrayId,
                    XfitMan::atom("_NET_SYSTEM_TRAY_ICON_SIZE"),
                    XA_CARDINAL,
                    32,
                    PropModeReplace,
                    (unsigned char*)&size,
                    1);
}

VisualID UKUITray::getVisual()
{
    VisualID visualId = 0;
    Display* dsp = mDisplay;

    XVisualInfo templ;
    templ.screen=QX11Info::appScreen();
    templ.depth=32;
    templ.c_class=TrueColor;

    int nvi;
    XVisualInfo* xvi = XGetVisualInfo(dsp, VisualScreenMask|VisualDepthMask|VisualClassMask, &templ, &nvi);

    if (xvi)
    {
        int i;
        XRenderPictFormat* format;
        for (i = 0; i < nvi; i++){
            format = XRenderFindVisualFormat(dsp, xvi[i].visual);
            if (format &&
                    format->type == PictTypeDirect &&
                    format->direct.alphaMask)
            {
                visualId = xvi[i].visualid;
                break;
            }
        }
        XFree(xvi);
    }

    return visualId;
}

/**
 * @brief UKUITray::startTray
 * freedesktop系统托盘规范
 */
void UKUITray::startTray()
{
    Display* dsp = mDisplay;
    Window root = QX11Info::appRootWindow();

    QString s = QString("_NET_SYSTEM_TRAY_S%1").arg(DefaultScreen(dsp));
    Atom _NET_SYSTEM_TRAY_S = XfitMan::atom(s.toLatin1());
    //this limit the tray apps  | will not run more Same apps
    if (XGetSelectionOwner(dsp, _NET_SYSTEM_TRAY_S) != None){
        qWarning() << "Another systray is running";
        mValid = false;
        return;
    }

    // init systray protocol
    mTrayId = XCreateSimpleWindow(dsp, root, -1, -1, 1, 1, 0, 0, 0);

    XSetSelectionOwner(dsp, _NET_SYSTEM_TRAY_S, mTrayId, CurrentTime);
    if (XGetSelectionOwner(dsp, _NET_SYSTEM_TRAY_S) != mTrayId){
        qWarning() << "Can't get systray manager";
        stopTray();
        mValid = false;
        return;
    }

    int orientation = _NET_SYSTEM_TRAY_ORIENTATION_HORZ;
    XChangeProperty(dsp,
                    mTrayId,
                    XfitMan::atom("_NET_SYSTEM_TRAY_ORIENTATION"),
                    XA_CARDINAL,
                    32,
                    PropModeReplace,
                    (unsigned char *) &orientation,
                    1);

    // ** Visual ********************************
    VisualID visualId = getVisual();
    if (visualId){
        XChangeProperty(mDisplay,
                        mTrayId,
                        XfitMan::atom("_NET_SYSTEM_TRAY_VISUAL"),
                        XA_VISUALID,
                        32,
                        PropModeReplace,
                        (unsigned char*)&visualId,
                        1);
    }
    setIconSize();

    XClientMessageEvent ev;
    ev.type = ClientMessage;
    ev.window = root;
    ev.message_type = XfitMan::atom("MANAGER");
    ev.format = 32;
    ev.data.l[0] = CurrentTime;
    ev.data.l[1] = _NET_SYSTEM_TRAY_S;
    ev.data.l[2] = mTrayId;
    ev.data.l[3] = 0;
    ev.data.l[4] = 0;
    XSendEvent(dsp, root, False, StructureNotifyMask, (XEvent*)&ev);

    XDamageQueryExtension(mDisplay, &mDamageEvent, &mDamageError);
    mValid = true;

    qApp->installNativeEventFilter(this);
}

void UKUITray::stopTray()
{
    for (auto & icon : mIcons)
        disconnect(icon, &QObject::destroyed, this, &UKUITray::onIconDestroyed);
    qDeleteAll(mIcons);
    if (mTrayId){
        XDestroyWindow(mDisplay, mTrayId);
        mTrayId = 0;
    }
    mValid = false;
}

//void UKUITray::stopStorageTray()
//{
//    for (auto & icon : mStorageIcons)
//        disconnect(icon, &QObject::destroyed, this, &UKUITray::onIconDestroyed);
//    qDeleteAll(mStorageIcons);
//    if (mTrayId){
//        XDestroyWindow(mDisplay, mTrayId);
//        mTrayId = 0;
//    }
//}

void UKUITray::onIconDestroyed(QObject * icon)
{
    //in the time QOjbect::destroyed is emitted, the child destructor
    //is already finished, so the qobject_cast to child will return nullptr in all cases
    mIcons.removeAll(static_cast<TrayIcon *>(icon));
    mStorageIcons.removeAll(static_cast<TrayIcon *>(icon));
}

void UKUITray::addTrayIcon(Window winId)
{
    // decline to add an icon for a window we already manage
    TrayIcon *icon = findTrayIcon(winId);
    if(icon)
        return;
    else{
        icon = new TrayIcon(winId, mIconSize, this);
        mIcons.append(icon);
        mTrayIcons.append(icon);
        mLayout->addWidget(icon);
        connect(icon, SIGNAL(switchButtons(TrayIcon*,TrayIcon*)), this, SLOT(switchButtons(TrayIcon*,TrayIcon*)));

        connect(icon,&QObject::destroyed,icon,&TrayIcon::notifyAppFreeze);
        connect(icon,&TrayIcon::notifyTray,[=](Window id){ freezeTrayApp(id);});
        connect(icon, &QObject::destroyed, this, &UKUITray::onIconDestroyed);
    }
}

void UKUITray::addStorageIcon(Window winId)
{
    TrayIcon *storageicon = findStorageIcon(winId);
    if(storageicon)
        return;
    else{
        storageicon = new TrayIcon(winId, mIconSize, this);
        mIcons.append(storageicon);
        mStorageIcons.append(storageicon);
        //storageLayout->addWidget(storageicon);

        connect(storageicon,&QObject::destroyed,storageicon,&TrayIcon::notifyAppFreeze);
        connect(storageicon,&TrayIcon::notifyTray,[=](Window id){freezeTrayApp(id);});
        connect(storageicon, &QObject::destroyed, this, &UKUITray::onIconDestroyed);
        if(mStorageIcons.size() > 0){
            if(!mBtn->isVisible()){
                mBtn->setVisible(true);
            }
        }
    }
}

/*与控制面板交互，移动应用到托盘栏或者收纳栏*/
void UKUITray::moveIconToTray(Window winId)
{
    TrayIcon *storageicon = findStorageIcon(winId);

    if(!storageicon)
        return;
    else{
        mStorageIcons.removeOne(storageicon);
        //storageLayout->removeWidget(storageicon);
        disconnect(storageicon, &QObject::destroyed, this, &UKUITray::onIconDestroyed);
        mTrayIcons.append(storageicon);
        mLayout->addWidget(storageicon);

        if(mStorageIcons.size() > 0){
            handleStorageUi();
        }
        else{
            mBtn->setVisible(false);
        }

        connect(storageicon,&QObject::destroyed,storageicon,&TrayIcon::notifyAppFreeze);
        connect(storageicon,&TrayIcon::notifyTray,[this](Window id){freezeTrayApp(id);});
        connect(storageicon, &QObject::destroyed, this, &UKUITray::onIconDestroyed);
    }
    trayIconSizeRefresh();
    handleStorageUi();
}

void UKUITray::moveIconToStorage(Window winId)
{
    TrayIcon *icon = findTrayIcon(winId);
    if(!icon)
        return;
    else{
        mLayout->removeWidget(icon);
        mTrayIcons.removeOne(icon);
        disconnect(icon, &QObject::destroyed, this, &UKUITray::onIconDestroyed);
        mStorageIcons.append(icon);

        if(mStorageIcons.size() > 0){
            if(!mBtn->isVisible()){
                mBtn->setVisible(true);
            }
            handleStorageUi();
        }
        else{
            mBtn->setVisible(false);
        }

        connect(icon,&QObject::destroyed,icon,&TrayIcon::notifyAppFreeze);
        connect(icon,&TrayIcon::notifyTray,[this](Window id){freezeTrayApp(id);});
        connect(icon, &QObject::destroyed, this, &UKUITray::onIconDestroyed);
    }
    handleStorageUi();
}

void UKUITray::regulateIcon(Window *mid)
{
    int wid=(int)*mid;
    int count=0;
    QList<char *> existsPath = listExistsPath();
    QString actionStr;
    int bingdingStr;
    QString nameStr;

    //匹配表中存在的name与该wid的name，若相等则用新的wid覆盖旧的wid，否则在表中添加新的路径，写上新的wid，name，以及状态。
    for (char * path : existsPath)
    {
        QString p =KEYBINDINGS_CUSTOM_DIR;
        std::string str = p.toStdString();
        const int len = str.length();
        char * prepath = new char[len+1];
        strcpy(prepath,str.c_str());
        char * allpath = strcat(prepath, path);
        const QByteArray bba(allpath);

        QGSettings *settings = NULL;
        const QByteArray id(KEYBINDINGS_CUSTOM_SCHEMA);
        if(QGSettings::isSchemaInstalled(id))
        {
            if(bba.isEmpty()){
                free(allpath);
                free(prepath);
                continue;
            }
            settings= new QGSettings(id, bba);
            if(settings){
                if(settings->keys().contains(RECORD_KEY)){
                    settings->set(ACTION_KEY,settings->get(RECORD_KEY).toString());
                }

                if(settings->keys().contains(ACTION_KEY)){
                    actionStr = settings->get(ACTION_KEY).toString();
                }

                if(settings->keys().contains(NAME_KEY)){
                    nameStr = settings->get(NAME_KEY).toString();
                }
                if(nameStr=="" || nameStr=="ErrorApplication"){
                    settings->reset(NAME_KEY);
                    settings->reset(BINDING_KEY);
                    settings->reset(ACTION_KEY);
                    settings->reset(RECORD_KEY);
                }
            }
            if(nameStr==xfitMan().getApplicationName(wid))
            {
                if(nameStr=="fcitx") {
                    fcitx_flag=true;
                }
                settings->set(BINDING_KEY, wid);
                bingdingStr=wid;
                if(QString::compare(actionStr,"tray")==0){
                    addTrayIcon(bingdingStr);
//                    TrayIcon *icon = findTrayIcon(bingdingStr);
//                    connect(icon,&TrayIcon::iconIsMoving,[this](Window id){moveIconToStorage(id);});
                }
                if(QString::compare(actionStr,"storage")==0){
                    addStorageIcon(bingdingStr);
//                    TrayIcon *icon = findStorageIcon(bingdingStr);
//                    connect(icon,&TrayIcon::iconIsMoving,[this](Window id){moveIconToTray(id);});
                }
                connect(settings, &QGSettings::changed, this, [=] (const QString &key){
                    if(key=="action"){
                        if(QString::compare(settings->get(ACTION_KEY).toString(),"tray")==0){
                            moveIconToTray(bingdingStr);
//                            TrayIcon *icon = findStorageIcon(bingdingStr);
//                            connect(icon,&TrayIcon::iconIsMoving,[this](Window id){moveIconToTray(id);});
                        }
                        else if(QString::compare(settings->get(ACTION_KEY).toString(),"storage")==0){
                            moveIconToStorage(bingdingStr);
//                            TrayIcon *icon = findTrayIcon(bingdingStr);
//                            connect(icon,&TrayIcon::iconIsMoving,[this](Window id){moveIconToStorage(id);});
                        }
                        else if(QString::compare(settings->get(ACTION_KEY).toString(),"freeze")==0){

                        }
                    }
                });
                delete allpath;
                break;
            }
        }
        settings->deleteLater();
        delete  prepath;
        count++;
        g_free(path);
    }

    if(count >= existsPath.count())
    {
        newAppDetect(wid);
        count++;
    }
}

QStringList UKUITray::getShowInTrayApp()
{
    QString filename = "/usr/share/ukui/ukui-panel/panel-commission.ini";
    QSettings m_settings(filename, QSettings::IniFormat);
    m_settings.setIniCodec("UTF-8");

    m_settings.beginGroup("ShowInTray");
    QStringList trayAppList = m_settings.value("trayname", "").toStringList();
    qDebug()<<"trayAppList  :"<<trayAppList;
    m_settings.endGroup();
    return trayAppList;
}

void UKUITray::newAppDetect(int wid)
{
    QString availablepath = findFreePath();

    const QByteArray id(KEYBINDINGS_CUSTOM_SCHEMA);
    const QByteArray idd(availablepath.toUtf8().data());
    QGSettings *newsetting;
    const QByteArray keyid(KEYBINDINGS_CUSTOM_SCHEMA);
    if(QGSettings::isSchemaInstalled(keyid))
    {
        newsetting=new QGSettings(id,idd);
        newsetting->set(BINDING_KEY,wid);
        newsetting->set(NAME_KEY,xfitMan().getApplicationName(wid));

        QStringList trayIconNameList = getShowInTrayApp();
        //trayIconNameList<<"ukui-volume-control-applet-qt"<<"kylin-nm"<<"ukui-sidebar"<<"indicator-china-weather"<<"ukui-flash-disk"<<"fcitx"<<"sogouimebs-qimpanel"<<"fcitx-qimpanel"<<"explorer.exe"<<"ukui-power-manager-tray"<<"baidu-qimpanel"<<"iflyime-qim";
        if(trayIconNameList.contains(xfitMan().getApplicationName(wid))){
            newsetting->set(ACTION_KEY,"tray");
            newsetting->set(RECORD_KEY,"tray");
            addTrayIcon(wid);
        }
        else{
            newsetting->set(ACTION_KEY,"storage");
            newsetting->set(RECORD_KEY,"storage");
            addStorageIcon(wid);
        }
    }
    delete newsetting;

    QGSettings* settings;
    const QByteArray keyId(KEYBINDINGS_CUSTOM_SCHEMA);
    if(QGSettings::isSchemaInstalled(keyId)){
        settings= new QGSettings(id, idd,this);
        connect(settings, &QGSettings::changed, this, [=] (const QString &key){
            if(key=="action"){
                if(QString::compare(settings->get(ACTION_KEY).toString(),"tray")==0){
                    moveIconToTray(wid);
                }
                else if(QString::compare(settings->get(ACTION_KEY).toString(),"storage")==0){
                    moveIconToStorage(wid);
                }
                else{
                    qDebug()<<"get error action";
                    qWarning()<<"get error action";
                }
            }
        });
    }
}

void UKUITray::handleStorageUi()
{

    if(m_pwidget)
    {
        if(mStorageLayout->count()){
            mStorageLayout->removeWidget(m_pwidget);
        }
        UKUi::GridLayout *vLayout = dynamic_cast<UKUi::GridLayout*>(m_pwidget->layout());
        if(vLayout)
        {
            vLayout->deleteLater();
        }
        m_pwidget->deleteLater();
        m_pwidget = NULL;
    }
    m_pwidget =  new UKUiStorageWidget;
    m_pwidget->setStorageWidgetButtonLayout(mStorageIcons.size());

    for(auto it = mStorageIcons.begin();it != mStorageIcons.end();++it)
    {
        m_pwidget->layout()->addWidget(*it);
        (*it)->setFixedSize(mWinWidth,mWinHeight);
    }
    storageFrame->layout()->addWidget(m_pwidget);
    storageFrame->setStorageFrameSize(mStorageIcons.size());
}

void UKUITray::contextMenuEvent(QContextMenuEvent *event)
{

}
void UKUITray::switchButtons(TrayIcon *button1, TrayIcon *button2)
{
    if (button1 == button2)
        return;
    int n1 = mLayout->indexOf(button1);
    int n2 = mLayout->indexOf(button2);
    int l = qMin(n1, n2);
    int m = qMax(n1, n2);
    mLayout->moveItem(l, m);
    mLayout->moveItem(m-1, l);
}

//特殊处理
//任务栏异常退出可能导致输入法异常，此时任务栏再次起来不会重新拉起输入法,此处特殊处理
void UKUITray::panelStartupFcitx()
{
    if(!fcitx_flag){
        qDebug()<<"fcitx未启动";
        QProcess *process =new QProcess(this);
        process->startDetached("fcitx");
        process->deleteLater();
    }
}
