/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 *
 * Copyright (C) 2019 KylinSoft  Co., Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, 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, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 */
#include "shortcutui.h"

#define UKCC_SETTING "org.ukui.control-center"

ShortcutUi::ShortcutUi()
{
    setAttribute(Qt::WA_DeleteOnClose);
    uiLayout     = new QVBoxLayout(this);
    systemLayout = new QVBoxLayout(this);
    m_windowLayout = new QVBoxLayout(this);
    customLayout = new QVBoxLayout(this);
    m_defaultLayout = new QHBoxLayout(this);;
    uiLayout->addLayout(systemLayout);
    uiLayout->addLayout(m_windowLayout);
    uiLayout->addLayout(m_defaultLayout);
    uiLayout->addLayout(customLayout);
    uiLayout->addStretch();
    uiLayout->setContentsMargins(0, 0, 0, 0);
    initUi();

    m_ukccSetting = new QGSettings(UKCC_SETTING);
    m_shortcutInterface = new QDBusInterface("org.ukui.ukcc.session",
                                            "/Shortcut",
                                            "org.ukui.ukcc.session.Shortcut",
                                            QDBusConnection::sessionBus(), this);
}

ShortcutUi::~ShortcutUi()
{
    if (m_ukccSetting) {
        delete m_ukccSetting;
        m_ukccSetting = nullptr;
    }
    for (auto* frame : m_customFrameList) {
        if (frame) {
            frame->deleteLater();
        }
    }
    if (addButton) {
        addButton->deleteLater();
    }
    m_customFrameList.clear();
}

void ShortcutUi::updateDefaultButtonStatus(bool status) {
    if (m_ukccSetting && m_ukccSetting->keys().contains("shortcutDefaultEnabled")) {
          m_ukccSetting->set("shortcutDefaultEnabled", status);
          m_defaultButton->setEnabled(status);
          qDebug() << Q_FUNC_INFO << "set shortcut default button enabled to false" << status;
    } else {
        qDebug() << Q_FUNC_INFO << "has not key shortcutDefaultEnabled";
    }
}

void ShortcutUi::initUi()
{
    initSystem();
    initWindow();
    initCustom();
}

void ShortcutUi::initSystem()
{
    systemTitle         = new KLabel(this);
    systemTitle->setContentsMargins(16, 0, 0, 0);
    systemShortcutGroup = new SettingGroup(this);
    //~ contents_path /Shortcut/System Shortcut
    systemTitle->setText(tr("System Shortcut"));
    systemLayout->addWidget(systemTitle);
    systemLayout->setSpacing(8);
    systemLayout->addWidget(systemShortcutGroup);
}

void ShortcutUi::initWindow()
{
    m_windowTitle         = new KLabel(this);
    m_windowTitle->setContentsMargins(16, 0, 0, 0);
    m_windowShortcutGroup = new SettingGroup(this);
    //~ contents_path /Shortcut/Window Shortcut
    m_windowTitle->setText(tr("Window Shortcut"));
    m_windowLayout->addWidget(m_windowTitle);
    m_windowLayout->setSpacing(8);
    m_windowLayout->addWidget(m_windowShortcutGroup);
}

AddButton* ShortcutUi::getAddButton() {
    return addButton;
}

KLabel* ShortcutUi::getCustomTitle() {
    return customTitle;
}

void ShortcutUi::initCustom()
{
    customTitle         = new KLabel(this);
    customShortcutGroup = new SettingGroup(this);
    addButton           = new AddButton(this);
    QHBoxLayout *layout = new QHBoxLayout(this);
    //~ contents_path /Shortcut/Customize Shortcut
    customTitle->setText(tr("Customize Shortcut"));
    customTitle->setContentsMargins(16, 0, 0, 0);
    customLayout->setSpacing(0);
    customLayout->addWidget(customTitle);
    customLayout->addSpacing(8);
    customLayout->addWidget(customShortcutGroup);
    customLayout->addSpacing(1);
    customLayout->addLayout(layout);
    layout->addWidget(addButton);

    addButton->setRadiusType(UkccFrame::BorderRadiusStyle::Around);
    customShortcutGroup->setOneRadiusStyle(UkccFrame::BorderRadiusStyle::Top);
    customShortcutGroup->setLastRadiusStyle(UkccFrame::BorderRadiusStyle::None);

    connect(addButton, &AddButton::clicked, this, &ShortcutUi::addButtonClicked);

}

void ShortcutUi::updateGeneralShort(DoubleClickShortCut *shortCutEdit, QString key, QString value, bool isConflict)
{
    QString convertValue = keyToLib(value);
    qDebug() << Q_FUNC_INFO << key << value << isConflict << convertValue;
    if (isConflict) {
        for (int i = 0; i < mSystemEntryList.count(); i++) {
            QString systemValue = keyToLib(mSystemEntryList[i].valueStr);
            qDebug() << Q_FUNC_INFO << "update systemEntries detect" << systemValue << convertValue << key;
            if (systemValue.toLower() == convertValue.toLower() && !value.isEmpty()) {
                for (int j = 0; j < mGeneralLineEdit.size(); j++) {
                    QString systemLineEditShort = keyToLib(mGeneralLineEdit[j]->property("shortKey").toString());
                    qDebug() << Q_FUNC_INFO << "update systemLineEdit detect" << systemLineEditShort << convertValue << key;
                    if (systemLineEditShort.toLower() == convertValue.toLower() && shortCutEdit != mGeneralLineEdit[j]) {
                        mGeneralLineEdit[j]->blockSignals(true);
                        mGeneralLineEdit[j]->setText(tr("Null"));
                        mGeneralLineEdit[j]->blockSignals(false);
                        mGeneralLineEdit[j]->setProperty("shortKey", "Null");

                        mGeneralName[j]->blockSignals(true);
                        mGeneralName[j]->setText(tr("Null"));
                        mGeneralName[j]->blockSignals(false);
                        updateDefaultButtonStatus(true);
                        qDebug() << Q_FUNC_INFO << "set systemLineEdit Null" << key;
                    }
                }
                qDebug() << Q_FUNC_INFO << "update system shortcut" << mSystemEntryList[i].keyStr << "from" << mSystemEntryList[i].valueStr << "to Null";
                mSystemEntryList[i].valueStr = "Null";
                shortCutEdit->setProperty("shortKey", value);
                m_shortcutInterface->call("setSystemShortcut", mSystemEntryList[i].keyStr, "Null");
            }
        }

        for (int i = 0; i < m_windowEntryList.count(); i++) {
            QString windowValue = keyToLib(m_windowEntryList[i].valueStr);
            qDebug() << Q_FUNC_INFO << "update windowEntries detect" << windowValue << convertValue << key;
            if (windowValue.toLower() == convertValue.toLower() && !value.isEmpty()) {
                for (int j = 0; j < m_windowLineEdit.size(); j++) {
                    QString windowLineEditShort = keyToLib(m_windowLineEdit[j]->property("shortKey").toString());
                    qDebug() << Q_FUNC_INFO << "update windowLineEdit detect" << windowLineEditShort << convertValue << key;
                    if (windowLineEditShort.toLower() == convertValue.toLower() && shortCutEdit != m_windowLineEdit[j]) {
                        m_windowLineEdit[j]->blockSignals(true);
                        m_windowLineEdit[j]->setText(tr("Null"));
                        m_windowLineEdit[j]->blockSignals(false);
                        m_windowLineEdit[j]->setProperty("shortKey", "Null");

                        m_windowName[j]->blockSignals(true);
                        m_windowName[j]->setText(tr("Null"));
                        m_windowName[j]->blockSignals(false);
                        updateDefaultButtonStatus(true);
                        qDebug() << Q_FUNC_INFO << "set windowLineEdit Null" << key;
                    }
                }
                QString oldShortCut = m_windowEntryList[i].valueStr;
                m_windowEntryList[i].valueStr = "Null";
                m_shortcutInterface->call("setWindowShortcut", m_windowEntryList[i].keyStr, oldShortCut, "");
                qDebug() << Q_FUNC_INFO << "update window shortcut" << m_windowEntryList[i].keyStr << "from" << oldShortCut << "to Null";
            }
        }

        for (int i = 0; i < mCustomEntryList.count(); i++) {
            QString customValue = keyToLib(mCustomEntryList[i].bindingStr);
            qDebug() << Q_FUNC_INFO << "update customEntries detect" << customValue << convertValue << key;
            if (customValue.toLower() == convertValue.toLower()) {
                for (int j = 0; j < mCustomLineEdit.size(); j++) {
                    QString customLineEditShort = keyToLib(mCustomLineEdit[j]->property("shortKey").toString());
                    qDebug() << Q_FUNC_INFO << "update customLineEdit detect" << mCustomLineEdit[j]->keySequence().toString() << customLineEditShort << mCustomEntryList[i].bindingStr << key;
                    if (customLineEditShort.toLower() == convertValue.toLower() && shortCutEdit != mCustomLineEdit[j]) {
                        mCustomLineEdit[j]->blockSignals(true);
                        mCustomLineEdit[j]->setText(tr("Null"));
                        mCustomLineEdit[j]->blockSignals(false);
                        mCustomLineEdit[j]->setProperty("shortKey", "Null");

                        mCustomName[j]->blockSignals(true);
                        mCustomName[j]->setText(tr("Null"));
                        mCustomName[j]->blockSignals(false);
                        qDebug() << Q_FUNC_INFO << "set customLineEdit Null" << key;
                    }
                }
                qDebug() << Q_FUNC_INFO << "update custom shortcut" << mCustomEntryList[i].nameStr << "from" << mCustomEntryList[i].bindingStr << "to Null";
                mCustomEntryList[i].bindingStr = "Null";
                m_shortcutInterface->call("setCustomShortcut", mCustomEntryList[i].gsPath, "Null");
            }
        }
    }
    int g_customEntriesSize = mCustomEntryList.count();
    for (int i = 0; i < g_customEntriesSize; i++) { //bug#205721
        qDebug() << Q_FUNC_INFO << "update customEntries detect" << key << mCustomEntryList[i].nameStr;
        if (key == mCustomEntryList[i].nameStr) {
            qDebug() << Q_FUNC_INFO << "update custom shortcut" << key << "from" << mCustomEntryList[i].bindingStr << "to" << convertValue;
            mCustomEntryList[i].bindingStr = convertValue;
            shortCutEdit->setProperty("shortKey", value);
            if (convertValue.contains("Super")) {
                convertValue.replace("Super", "Win");
            }
            m_shortcutInterface->call("setCustomShortcut", mCustomEntryList[i].gsPath, convertValue);
        }
    }
    for (int i = 0; i < mSystemEntryList.count(); i++) {
        qDebug() << Q_FUNC_INFO << "update systemEntries detect" << key << mSystemEntryList[i].keyStr;
        if (key == mSystemEntryList[i].keyStr) {
            qDebug() << Q_FUNC_INFO << "update system shortcut" << key << "from" << mSystemEntryList[i].valueStr << "to" << convertValue;
            mSystemEntryList[i].valueStr = convertValue;
            shortCutEdit->setProperty("shortKey", value);
            if (convertValue.contains("Super")) {
                convertValue.replace("Super", "Win");
            }
            m_shortcutInterface->call("setSystemShortcut", key, convertValue);
        }
    }
    for (int i = 0; i < m_windowEntryList.count(); i++) {
        qDebug() << Q_FUNC_INFO << "update windowEntries detect" << key << m_windowEntryList[i].keyStr;
        if (key == m_windowEntryList[i].keyStr) {
            QString oldValue = m_windowEntryList[i].valueStr;
            m_windowEntryList[i].valueStr = value;
            shortCutEdit->setProperty("shortKey", value);
            if (oldValue == "Null") {
                oldValue = "";
            }
            if (value == "Null") {
                value = "";
            }
            if (value.contains("↑")) {
                value.replace("↑", "Up");
            }
            if (value.contains("→")) {
                value.replace("→", "Right");
            }
            if (value.contains("←")) {
                value.replace("←", "Left");
            }
            if (value.contains("↓")) {
                value.replace("↓", "Down");
            }
            m_shortcutInterface->call("setWindowShortcut", key, oldValue, value);
            qDebug() << Q_FUNC_INFO << "update window shortcut" << key << "from" << oldValue << "to" << value;
        }
    }
}

void ShortcutUi::lineEditFocusOutSlot(DoubleClickLineEdit* lineEdit,
                                      ClickFixLabel *fixLabel)
{
    if (!lineEdit || !fixLabel) {
        return;
    }
    fixLabel->show();
    lineEdit->hide();
}

void ShortcutUi::labelDoubleClickSlot(ClickFixLabel *fixLabel,
                                      DoubleClickShortCut* lineEdit)
{
    if (!fixLabel || !lineEdit) {
        return;
    }
    fixLabel->hide();
    lineEdit->show();
    lineEdit->setFocus();
}

void ShortcutUi::labelDoubleClickSlot(ClickFixLabel *fixLabel,
                                      DoubleClickLineEdit* lineEdit)
{
    if (!fixLabel || !lineEdit) {
        return;
    }
    fixLabel->hide();
    lineEdit->show();
    lineEdit->setFocus();
}

void ShortcutUi::lineEditFocusOutSlot(DoubleClickShortCut* lineEdit,
                                      ClickFixLabel *fixLabel)
{
    if (!lineEdit || !fixLabel) {
        return;
    }
    fixLabel->show();
    lineEdit->hide();
}

void ShortcutUi::lineEditChangeSlot(DoubleClickShortCut* lineEdit,
                                    ClickFixLabel *fixLabel,
                                    QString key)
{
    if (!lineEdit || !fixLabel) {
        return;
    }
    QString text = lineEdit->text();
    QString shortCutValue = lineEdit->keySequence().toString();
    if (text.contains("Start") && shortCutValue.contains("Meta")) {
        shortCutValue.replace("Meta", "Start");
        text.replace("Start", "Super");
    }
    updateGeneralShort(lineEdit, key, shortCutValue, false);
    lineEdit->blockSignals(true);
    lineEdit->setText(getShowShortcutString(lineEdit->text()));
    lineEdit->blockSignals(false);
    fixLabel->setText(text);
    updateDefaultButtonStatus(true);
}

void ShortcutUi::customLineEditStrChangeSlot(DoubleClickLineEdit* lineEdit,
                                             ClickFixLabel *fixLabel,
                                             KeyEntry* keyEntry)
{
    if (!lineEdit || !fixLabel || !keyEntry) {
        return;
    }
    Q_EMIT toCreateShortcut(keyEntry->gsPath, lineEdit->text(), keyEntry->actionStr, keyEntry->bindingStr, false, false); //只修改
    fixLabel->setText(lineEdit->text());
}

void ShortcutUi::customLineEditChangeSlot(DoubleClickShortCut* lineEdit,
                                          ClickFixLabel *fixLabel,
                                          KeyEntry* keyEntry)
{
    if (!lineEdit || !fixLabel || !keyEntry) {
        return;
    }
    Q_EMIT toCreateShortcut(keyEntry->gsPath, keyEntry->nameStr, keyEntry->actionStr, lineEdit->keySequence().toString(), false, true, lineEdit); //只修改
    lineEdit->blockSignals(true);
    QString text = lineEdit->text();
    if (text.contains("Start")) {
        text.replace("Start", "Super");
    }
    lineEdit->setText(getShowShortcutString(text));
    lineEdit->blockSignals(false);
    fixLabel->setText(lineEdit->text());
}

void ShortcutUi::customLineEditConflictSlot(DoubleClickShortCut* lineEdit,
                                ClickFixLabel *fixLabel,
                                KeyEntry* keyEntry) {
    if (!lineEdit || !fixLabel || !keyEntry)
    {
        return;
    }
    QString tipValue = conflictTip(lineEdit->m_conflictKey, lineEdit->m_conflictValue);
    QString text = lineEdit->text();
    if (text.contains("Start")) {
        text.replace("Start", "Super");
    }
    if (text.contains("Meta")) {
        text.replace("Meta", "Super");
    }
    QMessageBox msg;
    msg.setIcon(QMessageBox::Warning);
    msg.addButton(tr("Cancel"), QMessageBox::NoRole);
    msg.addButton(tr("Continue"), QMessageBox::YesRole);
    msg.setText(tr("Shortcut key conflict, use it?"));
    msg.setInformativeText(QString(tr("\"%1\" occuied, using this combination will invalidate \"%2\".")).
                           arg(text).arg(tipValue));
    int ret = msg.exec();
    if (ret) {
        QString shortCutValue = lineEdit->keySequence().toString();
        if (text.contains("Start") && shortCutValue.contains("Meta")) {
            shortCutValue.replace("Meta", "Super");
            text.replace("Start", "Super");
        }
        QString toName = keyEntry->nameStr;
        for (int i = 0; i < mCustomEntryList.size(); i++) {
            if (keyEntry->actionStr == mCustomEntryList[i].actionStr) {
                toName = mCustomEntryList[i].nameStr;
                qDebug() << Q_FUNC_INFO << "get new customEntries nameStr" << mCustomEntryList[i].actionStr << "from" << keyEntry->nameStr << "to" << mCustomEntryList[i].nameStr;
                break;
            }
        }
        updateGeneralShort(lineEdit, toName, shortCutValue, true);
        lineEdit->blockSignals(true);
        lineEdit->setText(getShowShortcutString(text));
        lineEdit->blockSignals(false);
        fixLabel->setText(getShowShortcutString(text));
    } else {
        Q_EMIT fixLabel->doubleClicked();
    }
}

void ShortcutUi::lineEditConflictSlot(DoubleClickShortCut* lineEdit,
                                      ClickFixLabel *fixLabel,
                                      QString key)
{
    if (!lineEdit || !fixLabel) {
        return;
    }
    QString tipValue = conflictTip(lineEdit->m_conflictKey, lineEdit->m_conflictValue);
    QString text = lineEdit->text();
    QMessageBox msg;
    msg.setIcon(QMessageBox::Warning);
    msg.addButton(tr("Cancel"), QMessageBox::NoRole);
    msg.addButton(tr("Use"), QMessageBox::ApplyRole);
    msg.setText(tr("Shortcut key conflict, use it?"));
    msg.setInformativeText(QString(tr("%1 occuied, using this combination will invalidate %2")).
                           arg(lineEdit->text()).arg(tipValue));
    int ret = msg.exec();

    if (ret == 1) {
        QString shortCutValue = lineEdit->keySequence().toString();
        if (text.contains("Start") && shortCutValue.contains("Meta")) {
            shortCutValue.replace("Meta", "Start");
            text.replace("Start", "Super");
        }
        updateGeneralShort(lineEdit, key, shortCutValue, true);
        lineEdit->blockSignals(true);
        lineEdit->setText(getShowShortcutString(text));
        lineEdit->blockSignals(false);
        fixLabel->setText(getShowShortcutString(text));
        updateDefaultButtonStatus(true);
    } else {
        Q_EMIT fixLabel->doubleClicked();
    }
}

void ShortcutUi::customAddDialogSlot(AddShortcutDialog *addDialog,
                                     DoubleClickLineEdit *lineEdit,
                                     DoubleClickShortCut *bingdLineEdit,
                                     ClickFixLabel* fixLabel,
                                     ClickFixLabel* bindFixLabel,
                                     KeyEntry* keyEntry,
                                     QString name, QString exec, QString key)
{
    if (!addDialog || !lineEdit || !bingdLineEdit || !fixLabel  || !bindFixLabel || !keyEntry)
    {
        return;
    }
    Q_EMIT toCreateShortcut(keyEntry->gsPath, name, exec, key, false);
    lineEdit->setToolTip(name);
    lineEdit->blockSignals(true);
    lineEdit->setText(name);
    lineEdit->blockSignals(false);
    bingdLineEdit->blockSignals(true);
    QString mKey = getShowShortcutString(addDialog->keyToLib(key));
    if (mKey.contains("Meta")) {
        mKey.replace("Meta", "Super");
    }
    if (mKey.contains("Win")) {
        mKey.replace("Win", "Super");
    }
    if (mKey.contains("Print")) {
        mKey.replace("Print", "PrtSc");
    }
    if (mKey.contains("Prtsc")) {
        mKey.replace("Prtsc", "PrtSc");
    }
    if (mKey == "") {
        mKey = tr("Null");
    }

    QString toSeq = keyToSequence(key);
    bingdLineEdit->setKeySequence(toSeq);
    bingdLineEdit->setText(mKey);
    bingdLineEdit->setProperty("shortKey", toSeq);
    bingdLineEdit->blockSignals(false);
    fixLabel->setText(name);
    bindFixLabel->setText(bingdLineEdit->text());
    qDebug() << Q_FUNC_INFO << "shortcutInfoSignal" << mKey << name << exec << bingdLineEdit->keySequence();
}

void ShortcutUi::lineEditOccupySlot(DoubleClickShortCut* lineEdit,
                                    ClickFixLabel *fixLabel)
{
    QMessageBox msg;
    msg.setIcon(QMessageBox::Warning);
    QString text = lineEdit->m_conflictKey;
    if (text.contains("Start")) {
        text.replace("Start", "Super");
    }
    if (text.contains("Meta")) {
        text.replace("Meta", "Super");
    }
    msg.setText(QString(tr("Shortcut \"%1\" occuied, please change the key combination")).arg(text));
    msg.exec();
    Q_EMIT fixLabel->doubleClicked();
}

void ShortcutUi::addSystemShortcut(const QString &name, const QString &shortcut, const QString &mediaKey, KeyEntryList *systemEntryList, KeyEntryList *windowEntryList, KeyEntryList *customEntryList)
{
    mSystemEntryList = *systemEntryList;

    int editWidth = 286;
    QString keyStr = mediaKey;
    QString value = shortcut;
    QStringList twiceValues;

    UkccFrame              *shortCutFrame         = new UkccFrame(this, UkccFrame::BorderRadiusStyle::Around, true);

    KLabel                 *nameLabel             = new KLabel(shortCutFrame);
    ClickFixLabel          *bingdingLabel         = new ClickFixLabel(shortCutFrame);
    ClickFixLabel          *bingdingLabelTwice    = nullptr;

    DoubleClickShortCut    *bingdingLineEditTwice = nullptr;
    DoubleClickShortCut    *bingdingLineEdit      = new DoubleClickShortCut(&mSystemEntryList, &m_windowEntryList, &mCustomEntryList, shortCutFrame);

    QHBoxLayout            *gHorLayout            = new QHBoxLayout(shortCutFrame);
    QHBoxLayout            *lineEditLayout        = new QHBoxLayout;
    QHBoxLayout            *lineEditLayoutTwice   = new QHBoxLayout;

#ifndef Nile
    KLabel *bindingLabel = new KLabel(shortCutFrame);
    bindingLabel->setText(getShowShortcutString(shortcut));
    bindingLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
#endif
    nameLabel->setText(name);
    gHorLayout->setContentsMargins(16, 8, 16, 8);

    bool isTwice = false;

    if (shortcut.contains("or")) {
        editWidth = 130;
        isTwice = true;
        twiceValues = shortcut.split("or");
        value = twiceValues.at(1);

        bingdingLineEditTwice = new DoubleClickShortCut(&mSystemEntryList, windowEntryList, customEntryList, shortCutFrame);
        bingdingLineEditTwice->setAttribute(Qt::WA_InputMethodEnabled, false);
        bingdingLabelTwice = new ClickFixLabel(shortCutFrame);
        bingdingLabelTwice->setStyleSheet("QLabel{background-color:palette(button);border-radius: 4px}");

        bingdingLineEditTwice->setFixedWidth(150);

        bingdingLabelTwice->setFixedWidth(150);
        QString showText = getShowShortcutString(value).trimmed();
        if (showText == "Null") {
            showText = tr("Null");
        }
        bingdingLabelTwice->setText(showText);

        lineEditLayoutTwice->addWidget(bingdingLineEditTwice, 1);
        lineEditLayoutTwice->addWidget(bingdingLabelTwice, 1);
        bingdingLineEditTwice->setVisible(false);

        bingdingLineEditTwice->blockSignals(true);
        bingdingLineEditTwice->setText(showText);
        bingdingLineEditTwice->setKeySequence(QKeySequence(value));
        bingdingLineEditTwice->setProperty("shortKey", value);
        bingdingLineEditTwice->setProperty("shortcutId", keyStr + "2");
        bingdingLineEditTwice->blockSignals(false);

        mAllKeyI18nName.insert(keyStr + "2", QString(name));

        mGeneralLineEdit.append(bingdingLineEditTwice);
        mGeneralName.append(bingdingLabelTwice);

        connect(bingdingLabelTwice, &ClickFixLabel::doubleClicked, this, [=]() {
            labelDoubleClickSlot(bingdingLabelTwice, bingdingLineEditTwice);
        });

        connect(bingdingLineEditTwice, &DoubleClickShortCut::focusOut, this, [=]() {
            lineEditFocusOutSlot(bingdingLineEditTwice, bingdingLabelTwice);
        });

        connect(bingdingLineEditTwice, &DoubleClickShortCut::shortcutChanged, this, [=]() {
            lineEditChangeSlot(bingdingLineEditTwice, bingdingLabelTwice, keyStr + "2");
        });

        connect(bingdingLineEditTwice, &DoubleClickShortCut::shortcutConflict, this, [=]() {
            lineEditConflictSlot(bingdingLineEditTwice, bingdingLabelTwice, keyStr + "2");
        });
    }

    if (isTwice) value = twiceValues.at(0);

    mGeneralLineEdit.append(bingdingLineEdit);
    mGeneralName.append(bingdingLabel);

    QString showText = getShowShortcutString(value).trimmed();
    if (showText == "Null") {
        showText = tr("Null");
    }
    bingdingLabel->setText(showText);
    bingdingLabel->setFixedSize(editWidth, 36);
    bingdingLabel->setStyleSheet("QLabel{background-color:palette(button);border-radius: 4px}");
    bingdingLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);

    bingdingLineEdit->setAttribute(Qt::WA_InputMethodEnabled, false);
    bingdingLineEdit->setFixedSize(editWidth, 36);
    bingdingLineEdit->setAlignment(Qt::AlignLeft);
    bingdingLineEdit->blockSignals(true);
    bingdingLineEdit->setText(showText);
    bingdingLineEdit->setKeySequence(QKeySequence(value));
    bingdingLineEdit->setProperty("shortKey", value);
    bingdingLineEdit->setProperty("shortcutId", keyStr);
    bingdingLineEdit->blockSignals(false);
    bingdingLineEdit->setVisible(false);

    QSizePolicy policy;
    policy = bingdingLabel->sizePolicy();
    policy.setHorizontalPolicy(QSizePolicy::Ignored);
    bingdingLabel->setSizePolicy(policy);

    policy = bingdingLineEdit->sizePolicy();
    policy.setHorizontalPolicy(QSizePolicy::Ignored);
    bingdingLineEdit->setSizePolicy(policy);

    policy = bingdingLabel->sizePolicy();
    policy.setHorizontalPolicy(QSizePolicy::Ignored);
    bingdingLabel->setSizePolicy(policy);

    mAllKeyI18nName.insert(keyStr, name);

    lineEditLayout->addWidget(bingdingLineEdit, 1);
    lineEditLayout->addWidget(bingdingLabel, 1);

    gHorLayout->addWidget(nameLabel, 1);

#ifdef Nile
    gHorLayout->addStretch();
    gHorLayout->addLayout(lineEditLayout, 1);
    gHorLayout->addLayout(lineEditLayoutTwice, 1);
#else
    bingdingLineEdit->setVisible(false);
    bingdingLabel->setVisible(false);
    if (bingdingLineEditTwice != nullptr) {
        bingdingLineEditTwice->setVisible(false);
        bingdingLabelTwice->setVisible(false);
    }
    gHorLayout->addWidget(bindingLabel, 1);
#endif

    shortCutFrame->setLayout(gHorLayout);

    systemShortcutGroup->addWidget(shortCutFrame);

    connect(bingdingLabel,&ClickFixLabel::doubleClicked,this,[=](){
        labelDoubleClickSlot(bingdingLabel, bingdingLineEdit);
    });

    connect(bingdingLineEdit,&DoubleClickShortCut::focusOut,this,[=](){
        lineEditFocusOutSlot(bingdingLineEdit, bingdingLabel);
    });

    connect(bingdingLineEdit, &DoubleClickShortCut::shortcutChanged, this, [=]() {
        lineEditChangeSlot(bingdingLineEdit, bingdingLabel, keyStr);
    });

    connect(bingdingLineEdit, &DoubleClickShortCut::shortcutConflict, this, [=]() {
        lineEditConflictSlot(bingdingLineEdit, bingdingLabel, keyStr);
    });

    connect(bingdingLineEdit, &DoubleClickShortCut::shortcutOccupy, this, [=]() {
        lineEditOccupySlot(bingdingLineEdit, bingdingLabel);
    });
}

void ShortcutUi::addWindowShortcut(const QString &name, const QString &shortcut, const QString &mediaKey, KeyEntryList *systemEntryList, KeyEntryList *windowEntryList, KeyEntryList *customEntryList)
{
    m_windowEntryList = *windowEntryList;

    int editWidth = 286;
    QString keyStr = mediaKey;
    QString value = shortcut;
    QStringList twiceValues;

    UkccFrame              *shortCutFrame         = new UkccFrame(this, UkccFrame::BorderRadiusStyle::Around, true);

    KLabel                 *nameLabel             = new KLabel(shortCutFrame);
    ClickFixLabel          *bingdingLabel         = new ClickFixLabel(shortCutFrame);
    ClickFixLabel          *bingdingLabelTwice    = nullptr;

    DoubleClickShortCut    *bingdingLineEditTwice = nullptr;
    DoubleClickShortCut    *bingdingLineEdit      = new DoubleClickShortCut(&mSystemEntryList, &m_windowEntryList, &mCustomEntryList, shortCutFrame);

    QHBoxLayout            *gHorLayout            = new QHBoxLayout(shortCutFrame);
    QHBoxLayout            *lineEditLayout        = new QHBoxLayout;
    QHBoxLayout            *lineEditLayoutTwice   = new QHBoxLayout;

#ifndef Nile
    FixLabel *bindingLabel = new FixLabel(shortCutFrame);
    bindingLabel->setText(getShowShortcutString(shortcut));
    bindingLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
#endif
    nameLabel->setText(name);

    gHorLayout->setContentsMargins(16, 8, 16, 8);

    bool isTwice = false;

    if (shortcut.contains("or")) {
        editWidth = 130;
        isTwice = true;
        twiceValues = shortcut.split("or");
        value = twiceValues.at(1);

        bingdingLineEditTwice = new DoubleClickShortCut(&mSystemEntryList, windowEntryList, customEntryList, shortCutFrame);
        bingdingLineEditTwice->setAttribute(Qt::WA_InputMethodEnabled, false);
        bingdingLabelTwice = new ClickFixLabel(shortCutFrame);
        bingdingLabelTwice->setStyleSheet("QLabel{background-color:palette(button);border-radius: 4px}");

        bingdingLineEditTwice->setFixedWidth(150);

        bingdingLabelTwice->setFixedWidth(150);
        QString showText = getShowShortcutString(value).trimmed();
        if (showText == "Null") {
            showText = tr("Null");
        }
        bingdingLabelTwice->setText(showText);

        lineEditLayoutTwice->addWidget(bingdingLineEditTwice, 1);
        lineEditLayoutTwice->addWidget(bingdingLabelTwice, 1);
        bingdingLineEditTwice->setVisible(false);

        bingdingLineEditTwice->blockSignals(true);
        bingdingLineEditTwice->setText(showText);
        bingdingLineEditTwice->setKeySequence(QKeySequence(value));
        bingdingLineEditTwice->setProperty("shortKey", value);
        bingdingLineEditTwice->setProperty("shortcutId", keyStr + "2");
        bingdingLineEditTwice->blockSignals(false);

        mAllKeyI18nName.insert(keyStr + "2", QString(name));

        m_windowLineEdit.append(bingdingLineEditTwice);
        m_windowName.append(bingdingLabelTwice);

        connect(bingdingLabelTwice, &ClickFixLabel::doubleClicked, this, [=]() {
            labelDoubleClickSlot(bingdingLabelTwice, bingdingLineEditTwice);
        });

        connect(bingdingLineEditTwice, &DoubleClickShortCut::focusOut, this, [=]() {
            lineEditFocusOutSlot(bingdingLineEditTwice, bingdingLabelTwice);
        });

        connect(bingdingLineEditTwice, &DoubleClickShortCut::shortcutChanged, this, [=]() {
            lineEditChangeSlot(bingdingLineEditTwice, bingdingLabelTwice, keyStr + "2");
        });

        connect(bingdingLineEditTwice, &DoubleClickShortCut::shortcutConflict, this, [=]() {
            lineEditConflictSlot(bingdingLineEditTwice, bingdingLabelTwice, keyStr + "2");
        });

        connect(bingdingLineEditTwice, &DoubleClickShortCut::shortcutOccupy, this, [=]() {
            lineEditOccupySlot(bingdingLineEditTwice, bingdingLabelTwice);
        });
    }

    if (isTwice) {
        value = twiceValues.at(0).trimmed();
    }

    m_windowLineEdit.append(bingdingLineEdit);
    m_windowName.append(bingdingLabel);

    QString showText = getShowShortcutString(value).trimmed();
    if (showText == "Null") {
        showText = tr("Null");
    }
    bingdingLabel->setText(showText);
    bingdingLabel->setFixedSize(editWidth, 36);
    bingdingLabel->setStyleSheet("QLabel{background-color:palette(button);border-radius: 4px}");
    bingdingLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);

    bingdingLineEdit->setAttribute(Qt::WA_InputMethodEnabled, false);
    bingdingLineEdit->setFixedSize(editWidth, 36);
    bingdingLineEdit->setAlignment(Qt::AlignLeft);
    bingdingLineEdit->blockSignals(true);
    bingdingLineEdit->setText(showText);
    bingdingLineEdit->setKeySequence(QKeySequence(value));
    bingdingLineEdit->setProperty("shortKey", value);
    bingdingLineEdit->setProperty("shortcutId", keyStr);
    bingdingLineEdit->blockSignals(false);
    bingdingLineEdit->setVisible(false);

    QSizePolicy policy;
    policy = bingdingLabel->sizePolicy();
    policy.setHorizontalPolicy(QSizePolicy::Ignored);
    bingdingLabel->setSizePolicy(policy);

    policy = bingdingLineEdit->sizePolicy();
    policy.setHorizontalPolicy(QSizePolicy::Ignored);
    bingdingLineEdit->setSizePolicy(policy);

    policy = bingdingLabel->sizePolicy();
    policy.setHorizontalPolicy(QSizePolicy::Ignored);
    bingdingLabel->setSizePolicy(policy);

    mAllKeyI18nName.insert(keyStr, name);

    lineEditLayout->addWidget(bingdingLineEdit, 1);
    lineEditLayout->addWidget(bingdingLabel, 1);

    gHorLayout->addWidget(nameLabel, 1);

#ifdef Nile
    gHorLayout->addStretch();
    gHorLayout->addLayout(lineEditLayout, 1);
    gHorLayout->addLayout(lineEditLayoutTwice, 1);
#else
    bingdingLineEdit->setVisible(false);
    bingdingLabel->setVisible(false);
    if (bingdingLineEditTwice != nullptr) {
        bingdingLineEditTwice->setVisible(false);
        bingdingLabelTwice->setVisible(false);
    }
    gHorLayout->addWidget(bindingLabel, 1);
#endif

    shortCutFrame->setLayout(gHorLayout);

    m_windowShortcutGroup->addWidget(shortCutFrame);

    connect(bingdingLabel, &ClickFixLabel::doubleClicked, this, [=]() {
        labelDoubleClickSlot(bingdingLabel, bingdingLineEdit);
    });

    connect(bingdingLineEdit, &DoubleClickShortCut::focusOut, this, [=]() {
        lineEditFocusOutSlot(bingdingLineEdit, bingdingLabel);
    });

    connect(bingdingLineEdit, &DoubleClickShortCut::shortcutChanged, this, [=]() {
        lineEditChangeSlot(bingdingLineEdit, bingdingLabel, keyStr);
    });

    connect(bingdingLineEdit, &DoubleClickShortCut::shortcutConflict, this, [=]() {
        lineEditConflictSlot(bingdingLineEdit, bingdingLabel, keyStr);
    });

    connect(bingdingLineEdit, &DoubleClickShortCut::shortcutOccupy, this, [=]() {
        lineEditOccupySlot(bingdingLineEdit, bingdingLabel);
    });
}

QString ShortcutUi::keyToSequence(QString key) {
    QString oldKey = key;
    key.replace(" ", "");
    if (key.contains("Super")) {
        key.replace("Super", "Meta");
    }

    if (key.contains("Start")) {
        key.replace("Start", "Meta");
    }
    if (key.contains("<")) {
        key.replace("<", "");
    }

    if (key.contains(">")) {
        key.replace(">", "+");
    }
    //qDebug() << Q_FUNC_INFO << "update" << oldKey << "to" << key;
    return key;
}

QList<QFrame*> ShortcutUi::getCustomFrameList() {
    return m_customFrameList;
}

void ShortcutUi::addCustomShortcut(KeyEntry keyEntry, KeyEntryList *systemEntryList, KeyEntryList *windowEntryList, KeyEntryList *customEntryList)
{
    mCustomEntryList = *customEntryList;

    UkccFrame           *frame            = new UkccFrame(this, UkccFrame::BorderRadiusStyle::Around, true);
    QHBoxLayout         *layout           = new QHBoxLayout(frame);
    QHBoxLayout         *lineEditLayout   = new QHBoxLayout;
    DoubleClickLineEdit *nameLineEdit     = new DoubleClickLineEdit(customEntryList, frame);
    DoubleClickShortCut *bingdingLineEdit = new DoubleClickShortCut(&mSystemEntryList, &m_windowEntryList, customEntryList, frame);
    ClickFixLabel       *nameLabel        = new ClickFixLabel(frame);
    ClickFixLabel       *bingdingLabel    = new ClickFixLabel(frame);
    KeyEntry            *mKeyEntry        = new KeyEntry;
    m_customFrameList.append(frame);

    mKeyEntry->gsSchema   = keyEntry.gsSchema;
    mKeyEntry->keyStr     = keyEntry.keyStr;
    mKeyEntry->valueStr   = keyEntry.valueStr;
    mKeyEntry->descStr    = keyEntry.descStr;
    mKeyEntry->gsPath     = keyEntry.gsPath;
    mKeyEntry->nameStr    = keyEntry.nameStr;
    mKeyEntry->bindingStr = keyEntry.bindingStr;
    mKeyEntry->actionStr  = keyEntry.actionStr;

    customShortcutGroup->addWidget(frame);
    addButton->setRadiusType(UkccFrame::BorderRadiusStyle::Bottom);
    mCustomLineEdit.append(bingdingLineEdit);
    mCustomName.append(bingdingLabel);

    // 大小写字母数字中文
    QRegularExpression rx("[a-zA-Z0-9\u4e00-\u9fa5]+");
    QRegularExpressionValidator *regValidator = new QRegularExpressionValidator(rx);
    // 输入限制
    nameLineEdit->setValidator(regValidator);
    nameLineEdit->setFixedHeight(36);
    static const int MAX_LENGTH = 256;
    nameLineEdit->setMaxLength(MAX_LENGTH);
    bingdingLineEdit->setFixedSize(130,36);

    bingdingLineEdit->setAlignment(Qt::AlignLeft);
    bingdingLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    bingdingLineEdit->setAttribute(Qt::WA_InputMethodEnabled, false);
    bingdingLabel->setFixedSize(130, 36);
    bingdingLabel->setStyleSheet("QLabel{background-color:palette(button);border-radius: 4px}");

    QToolButton *btn = new QToolButton(frame);
    btn->setAutoRaise(true);
    btn->setPopupMode(QToolButton::InstantPopup);
    QMenu *menu = new QMenu(btn);
    btn->setMenu(menu);
    QAction *edit = new QAction(btn);
    QAction *del = new QAction(btn);
    edit->setText(tr("Edit"));
    del->setText(tr("Delete"));
    menu->addAction(edit);
    menu->addAction(del);

    connect(del, &QAction::triggered, this, [=](){
        customShortcutGroup->removeWidget(frame);
        if (customShortcutGroup->showItemsCount() == 0) {
            addButton->setRadiusType(UkccFrame::BorderRadiusStyle::Around);
        }
        frame->deleteLater();
        Q_EMIT deleteShortcut(mKeyEntry->gsPath);
        for (int i = 0; i < customEntryList->size(); ++i) {
            if (customEntryList->at(i).nameStr == mKeyEntry->nameStr) {
                qDebug() << Q_FUNC_INFO << "remove shortcut" << mKeyEntry->nameStr;
                int index = 0;
                for (QList<DoubleClickShortCut *>::iterator iter = mCustomLineEdit.begin(); iter != mCustomLineEdit.end(); ++index) {
                    if (bingdingLineEdit == *iter) {
                        iter = mCustomLineEdit.erase(iter);
                        QList<ClickFixLabel *>::iterator mIter = mCustomName.begin();
                        mCustomName.erase(mIter + index);
                        qDebug() << Q_FUNC_INFO << "remove bingdingLineEdit from mCustomLineEdit" << bingdingLineEdit->text();
                    } else {
                        ++iter;
                    }
                }
                customEntryList->removeAt(i);
                break;
            }
        }
        delete mKeyEntry;
        UkccCommon::buriedSettings("Shortcut", QString("del"), QString("clicked"));
    });

    connect(edit, &QAction::triggered, this, [=](){
        AddShortcutDialog *addDialog = new AddShortcutDialog(*systemEntryList, *windowEntryList, *customEntryList, this);
        addDialog->setAttribute(Qt::WA_DeleteOnClose);
        addDialog->setSourceEnable(false);
        addDialog->setWindowTitle(QObject::tr("Edit Shortcut"));

        addDialog->setExecText(mKeyEntry->actionStr);
        addDialog->setNameText(mKeyEntry->nameStr);
        QString newBindingStr = mKeyEntry->bindingStr;
        for (int i = 0; i < customEntryList->size(); i++) {
            if (mKeyEntry->actionStr == customEntryList->at(i).actionStr) {
                newBindingStr = customEntryList->at(i).bindingStr;
                if (newBindingStr == "Null") {
                    newBindingStr = tr("Null");
                }
                qDebug() << Q_FUNC_INFO << "get new customEntries bindingStr" << customEntryList->at(i).actionStr << "from" << mKeyEntry->bindingStr << "to" << customEntryList->at(i).bindingStr;
                break;
            }
        }
        addDialog->setKeyText(newBindingStr);
        addDialog->setKeyIsAvailable(3);
        UkccCommon::buriedSettings("Shortcut", QString("edit"), QString("clicked"));
        connect(addDialog, &AddShortcutDialog::shortcutInfoSignal, this,
                [=](QString path, QString name, QString exec, QString key){
            customAddDialogSlot(addDialog, nameLineEdit, bingdingLineEdit,
                                nameLabel, bingdingLabel, mKeyEntry,
                                name, exec, key);
        });
        addDialog->exec();
    });

    btn->setIcon(QIcon::fromTheme("view-more-horizontal-symbolic"));
    btn->setProperty("useButtonPalette", true);
    btn->setFixedSize(36, 36);

    layout->setContentsMargins(8, 0, 16, 0);
    layout->setSpacing(24);
    layout->addLayout(lineEditLayout);
    layout->addWidget(btn);

    lineEditLayout->setContentsMargins(0, 0, 0, 0);
    lineEditLayout->setSpacing(140);

    QSizePolicy policy;
    policy = nameLineEdit->sizePolicy();
    policy.setHorizontalPolicy(QSizePolicy::Ignored);
    nameLineEdit->setSizePolicy(policy);

    policy = nameLabel->sizePolicy();
    policy.setHorizontalPolicy(QSizePolicy::Ignored);
    nameLabel->setSizePolicy(policy);

    policy = bingdingLineEdit->sizePolicy();
    policy.setHorizontalPolicy(QSizePolicy::Ignored);
    bingdingLineEdit->setSizePolicy(policy);

    policy = bingdingLabel->sizePolicy();
    policy.setHorizontalPolicy(QSizePolicy::Ignored);
    bingdingLabel->setSizePolicy(policy);

    lineEditLayout->addWidget(nameLineEdit, 1);
    lineEditLayout->addWidget(nameLabel, 1);
    lineEditLayout->addWidget(bingdingLineEdit, 1);
    lineEditLayout->addWidget(bingdingLabel, 1);
    nameLineEdit->setVisible(false);
    bingdingLineEdit->setVisible(false);

    nameLineEdit->blockSignals(true);
    nameLineEdit->setText(mKeyEntry->nameStr);
    nameLineEdit->blockSignals(false);
    bingdingLineEdit->blockSignals(true);
    QString displayText = getShowShortcutString(mKeyEntry->bindingStr);
    if (displayText == "Null") {
        displayText = tr("Null");
    }
    bingdingLineEdit->setText(displayText);
    bingdingLineEdit->setProperty("shortKey", mKeyEntry->bindingStr);
    bingdingLineEdit->setProperty("shortcutId", mKeyEntry->actionStr);
    bingdingLineEdit->blockSignals(false);

    nameLabel->setText(mKeyEntry->nameStr);
    bingdingLabel->setText(displayText);
    mAllKeyI18nName.insert(mKeyEntry->actionStr, mKeyEntry->nameStr);

    connect(nameLabel, &ClickFixLabel::doubleClicked, this, [=]() {
        labelDoubleClickSlot(nameLabel, nameLineEdit);
    });

    connect(bingdingLabel, &ClickFixLabel::doubleClicked, this, [=]() {
        labelDoubleClickSlot(bingdingLabel, bingdingLineEdit);
    });

    connect(nameLineEdit, &DoubleClickLineEdit::focusOut, this, [=]() {
        lineEditFocusOutSlot(nameLineEdit, nameLabel);
    });

    connect(bingdingLineEdit, &DoubleClickShortCut::focusOut, this, [=]() {
        lineEditFocusOutSlot(bingdingLineEdit, bingdingLabel);
    });

    connect(nameLineEdit, &DoubleClickLineEdit::strChanged, this, [=]() {
        customLineEditStrChangeSlot(nameLineEdit, nameLabel, mKeyEntry);
    });

    connect(bingdingLineEdit, &DoubleClickShortCut::shortcutChanged, this, [=](){
        customLineEditChangeSlot(bingdingLineEdit, bingdingLabel, mKeyEntry);
    });

    connect(bingdingLineEdit, &DoubleClickShortCut::shortcutConflict, this, [=]() {
        customLineEditConflictSlot(bingdingLineEdit, bingdingLabel, mKeyEntry);
    });
    connect(bingdingLineEdit, &DoubleClickShortCut::shortcutOccupy, this, [=]() {
        lineEditOccupySlot(bingdingLineEdit, bingdingLabel);
    });

    return;
}

QString ShortcutUi::getShowShortcutString(QString src)
{
    if (src.contains("Win")) {
        src.replace("Win", "Super");
    }
    if (src.contains("Meta")) {
        src.replace("Meta", "Super");
    }
    if (src.contains("Start")) {
        src.replace("Start", "Super");
    }
    src.replace("<","");
    src.replace(">","   ");
    src.replace(" or ",tr(" or "));
    src.replace("+", " ");
    QStringList temp_list = src.split(" ");
    QString str;
    int size = temp_list.count();
    for(qint32 i = 0; i < size; i++) {
        str += temp_list.at(i)
                .left(1).toUpper() +
                temp_list.at(i)
                .mid(1, temp_list.at(i).length() - 1);
        if (i != size - 1) {
            str += " ";
        }
    }
    str.replace("Or","or");
    str.replace(" Left", " \u2190");
    str.replace(" Right", " \u2192");
    str.replace(" Up", " \u2191");
    str.replace(" Down", " \u2193");
    return str;
}

QString ShortcutUi::keyToLib(QString key)
{
    if (key.contains("Meta")) {
        key.replace("Meta", "Super");
    }

    if (key.contains("Start")) {
        key.replace("Start", "Super");
    }

    if (key.contains("Win")) {
        key.replace("Win", "Super");
    }

    if (key.contains("Print", Qt::CaseInsensitive)) {
        key.replace("Print", "PrtSc", Qt::CaseInsensitive);
    }

    if (key.contains("+")) {
        QStringList keys = key.split("+");
        if (keys.count() == 2) {
            QString lower = keys.at(1);
            QString keyToLib = "<" + keys.at(0) + ">" + lower.toLower();
            return keyToLib;
        } else if (keys.count() == 3) {
            QString lower = keys.at(2);
            QString keyToLib = "<" + keys.at(0) + ">" + "<" + keys.at(1) + ">" + lower.toLower();
            return keyToLib;
        } else if (keys.count() == 4) {
            QString lower = keys.at(3);
            QString keyToLib = "<" + keys.at(0) + ">" + "<" + keys.at(1) + ">" + "<" + keys.at(2) + ">" + lower.toLower();
            return keyToLib;
        }
    }
    return key;
}

QString ShortcutUi::conflictTip(const QString &key, const QString &value)
{
    if (!value.isEmpty()) {
        return value;
    } else {
        QMap<QString, QString>::Iterator it;
        for (it = mAllKeyI18nName.begin(); it != mAllKeyI18nName.end(); it++) {
            qDebug() << Q_FUNC_INFO << it.key() << it.value();
            if (it.key() == key) {
                return it.value();
            }
        }
    }
    return value;
}

void ShortcutUi::clearCustomShorcutFrame()
{
    customShortcutGroup->removeAndDeleteAllWidget();
}

void ShortcutUi::setWindowValid(bool isValid) {
    m_windowShortcutValid = isValid;
}

void ShortcutUi::setWindowHide() {
    m_windowTitle->setVisible(false);
    m_windowShortcutGroup->setVisible(false);
}

void ShortcutUi::loadDefaultShortcut() {
    QGSettings ukcc("org.ukui.control-center");
    m_defaultShortcutList.clear();
    if (!ukcc.keys().contains("defaultShortcut")) {
        qDebug() << Q_FUNC_INFO << "org.ukui.control-center has no key defaultShortcut";
        return;
    }
    QString defaultShortcut = ukcc.get("defaultShortcut").toString();
    for (const auto& shortcutPair : defaultShortcut.split(";")) {
        QStringList shortcutPairList = shortcutPair.split(":");
        if (shortcutPairList.size() != 2) {
            continue;
        }
        QString pairKey = shortcutPairList.at(0);
        QString pairValue = shortcutPairList.at(1);
        QString valueStr = keyToLib(pairValue).toLower();
        m_defaultShortcutList.append(valueStr);
        //qDebug() << Q_FUNC_INFO << "load default shortcut" << pairKey << pairValue << valueStr;
    }
}

void ShortcutUi::setWindowShortcutToNull() {
    if (!m_windowShortcutValid) {
        return;
    }
    QDBusReply<QVariantMap> shortKeyValueReply = m_shortcutInterface->call("getShortKeyValue");
    QVariantMap shortKeyValueMap;
    if (shortKeyValueReply.isValid()) {
        shortKeyValueMap = shortKeyValueReply.value();
        qDebug() << Q_FUNC_INFO << "ShortKeyValue size:" << shortKeyValueMap.size();
    } else {
        qDebug() << Q_FUNC_INFO << "getShortKeyValue invalid" << shortKeyValueReply.error();
        return;
    }
    for (int j = 0; j < m_windowLineEdit.size(); j++) {
        QString shortKey = m_windowLineEdit.at(j)->property("shortcutId").toString();
        QString shortValue = m_windowLineEdit.at(j)->property("shortKey").toString();
        qDebug() << Q_FUNC_INFO << "before set window lineEdit to Null" << shortKey << shortValue << j << m_windowLineEdit.at(j)->text();
        if (shortKeyValueMap.contains(shortKey)) {
            QString oldValue = shortKeyValueMap[shortKey].toString().trimmed();
            m_shortcutInterface->call("setWindowShortcut", shortKey, oldValue, "");
            qDebug() << Q_FUNC_INFO << "set window shortcut" << shortKey << "from" << oldValue << "to Null";
        }
    }
}

void ShortcutUi::setCustomShortcutToNull() {
    for (int j = 0; j < mCustomLineEdit.size(); j++) {
        QString actionStr = mCustomLineEdit.at(j)->property("shortcutId").toString();
        for (int i = 0; i < mCustomEntryList.count(); i++) {
            if (actionStr != mCustomEntryList[i].actionStr) {
                qDebug() << Q_FUNC_INFO << "lineEdit" << actionStr << "not equal gsetting" << mCustomEntryList[i].actionStr;
                continue;
            }
            QString shortcut = mCustomEntryList[i].bindingStr.toLower();
            qDebug() << Q_FUNC_INFO << "before set custom lineEdit to Null" << actionStr << shortcut << mCustomEntryList[i].gsPath;
            if (!m_defaultShortcutList.contains(shortcut)) {
                qDebug() << Q_FUNC_INFO << "shortcut" << shortcut << "not find in default shortcut";
                continue;
            }
            QString oldValue = mCustomLineEdit[j]->text().trimmed();
            mCustomLineEdit[j]->blockSignals(true);
            mCustomLineEdit[j]->setText(tr("Null"));
            mCustomLineEdit[j]->blockSignals(false);
            mCustomLineEdit[j]->setProperty("shortKey", "Null");
            mCustomName[j]->blockSignals(true);
            mCustomName[j]->setText(tr("Null"));
            mCustomName[j]->blockSignals(false);
            qDebug() << Q_FUNC_INFO << "set customLineEdit" << mCustomEntryList[i].nameStr << "from" << oldValue << "to null";
            mCustomEntryList[i].bindingStr = "Null";
            m_shortcutInterface->call("setCustomShortcut", mCustomEntryList[i].gsPath, "Null");
        }
    }
}

void ShortcutUi::defaultShortcut() {
    m_shortcutInterface->call("defaultShortcut");

    QDBusReply<QVariantMap> shortKeyValueReply = m_shortcutInterface->call("getShortKeyValue");
    QVariantMap shortKeyValueMap;
    if (shortKeyValueReply.isValid()) {
        shortKeyValueMap = shortKeyValueReply.value();
        qDebug() << Q_FUNC_INFO << "ShortKeyValue size:" << shortKeyValueMap.size();
    } else {
        qDebug() << Q_FUNC_INFO << "getShortKeyValue invalid" << shortKeyValueReply.error();
        return;
    }

    // update system shortcut lineEdit
    mSystemEntryList.clear();
    QDBusReply<KeyEntryList> systemEntryReply = m_shortcutInterface->call("getSystemShortcutEntry");
    if (systemEntryReply.isValid()) {
        mSystemEntryList = systemEntryReply.value();
    }
    for (int j = 0; j < mGeneralLineEdit.size(); j++) {
        QString shortKey = mGeneralLineEdit.at(j)->property("shortcutId").toString();
        QString shortValue = mGeneralLineEdit.at(j)->property("shortKey").toString();
        qDebug() << Q_FUNC_INFO << "before default system lineEdit" << shortKey << shortValue << j << mGeneralLineEdit.at(j)->text();
        if (shortKeyValueMap.keys().contains(shortKey)) {
            QString newValue = shortKeyValueMap[shortKey].toString();
            QString showText = getShowShortcutString(newValue);
            qDebug() << Q_FUNC_INFO << "default system lineEdit" << shortKey << "from" << mGeneralLineEdit[j]->text() << "to" << showText;
            mGeneralLineEdit[j]->blockSignals(true);
            mGeneralLineEdit[j]->setText(showText);
            mGeneralLineEdit[j]->blockSignals(false);
            mGeneralLineEdit[j]->setProperty("shortKey", newValue);
            mGeneralName[j]->blockSignals(true);
            mGeneralName[j]->setText(showText);
            mGeneralName[j]->blockSignals(false);
        }
    }

    // update window shortcut lineEdit
    m_windowEntryList.clear();
    QDBusReply<KeyEntryList> windowEntryReply = m_shortcutInterface->call("getWindowShortcutEntry");
    if (windowEntryReply.isValid()) {
        m_windowEntryList = windowEntryReply.value();
        if (m_windowEntryList.empty()) {
            qDebug() << Q_FUNC_INFO << "default window shortcut is empty";
            m_windowShortcutValid = false;
        }
    } else {
        m_windowShortcutValid = false;
        qDebug() << Q_FUNC_INFO << "default window shortcut invalid";
    }
    for (int j = 0; j < m_windowLineEdit.size(); j++) {
        QString shortKey = m_windowLineEdit.at(j)->property("shortcutId").toString();
        QString shortValue = m_windowLineEdit.at(j)->property("shortKey").toString();
        qDebug() << Q_FUNC_INFO << "before default window lineEdit" << shortKey << shortValue << j << m_windowLineEdit.at(j)->text();
        if (shortKeyValueMap.contains(shortKey)) {
            QString newValue = shortKeyValueMap[shortKey].toString();
            QString showText = getShowShortcutString(newValue);
            qDebug() << Q_FUNC_INFO << "default window lineEdit" << shortKey << "from" << m_windowLineEdit[j]->text() << "to" << showText;
            m_windowLineEdit[j]->blockSignals(true);
            m_windowLineEdit[j]->setText(showText);
            m_windowLineEdit[j]->blockSignals(false);
            m_windowLineEdit[j]->setProperty("shortKey", newValue);
            m_windowName[j]->blockSignals(true);
            m_windowName[j]->setText(showText);
            m_windowName[j]->blockSignals(false);
        }
    }
}

void ShortcutUi::defaultButtonSlot() {
    // 1) window shortcut to null
    setWindowShortcutToNull();

    // 2) set conflict custom shortcut to null
    setCustomShortcutToNull();

    // 3) system shortcut to default, window shortcut to default
    defaultShortcut();

    // 4) reset m_defaultButton enable状态
    updateDefaultButtonStatus(false);

    UkccCommon::buriedSettings("Shortcut", QString("default"), QString("clicked"));
}

void ShortcutUi::addDefaultBtn() {
    //~ contents_path /Shortcut/Default
    m_defaultButton = new QPushButton(tr("Default"));
    m_defaultLayout->addWidget(m_defaultButton);
    m_defaultLayout->addStretch();
    m_defaultLayout->setContentsMargins(0, 8, 16, 24);
    bool enabled = true;
    if (m_ukccSetting && m_ukccSetting->keys().contains("shortcutDefaultEnabled")) {
        enabled = m_ukccSetting->get("shortcutDefaultEnabled").toBool();
        qDebug() << Q_FUNC_INFO << "set shortcut default button enabled" << enabled;
    }
    updateDefaultButtonStatus(enabled);
    connect(m_defaultButton, &QPushButton::clicked, this, [=]() {
        defaultButtonSlot();
    });
}
