/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 *
 * 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 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 "userinfo.h"
#include "ui_userinfo.h"

#include <QVBoxLayout>
#include <QHBoxLayout>

#include <QListView>

#include <QDBusInterface>
#include <QDBusConnection>
#include <QDBusError>
#include <QDBusReply>
#include <QDBusArgument>
#include <QDBusMetaType>
#include <QProcess>
#include <QDBusMessage>
#include <QDBusObjectPath>
#include <QDebug>
#include <QLineEdit>
#include <QMessageBox>
#include <QRadioButton>

#include <polkit-qt5-1/polkitqt1-authority.h>

#include <kysdk/kysdk-system/libkysysinfo.h>
#include <kysdk/applications/accessinfohelper.h>

#include "otpbinddialog.h"
#include "securitykeysetdlg.h"

#include "elipsemaskwidget.h"
#include "passwdcheckutil.h"
#include "loginedusers.h"

#include "ukcccommon.h"
using namespace ukcc;

/* qt会将glib里的signals成员识别为宏，所以取消该宏
 * 后面如果用到signals时，使用Q_SIGNALS代替即可
 **/
#ifdef signals
#undef signals
#endif

#include <glib.h>
#include <gio/gio.h>

#ifdef WITHKYSEC
#include <kysec/libkysec.h>
#include <kysec/status.h>
#endif
#define DEFAULTFACECOMMUNITY "/usr/share/ukui/faces/01-default-community.png"
#define DEFAULTFACECOMMERCIAL "/usr/share/ukui/faces/01-default-commercial.png"
#define DEFAULTFACE (UkccCommon::isCommunity() || UkccCommon::isOpenkylin())?DEFAULTFACECOMMUNITY:DEFAULTFACECOMMERCIAL
#define ITEMHEIGH 60

const static QString login1Service = QStringLiteral("org.freedesktop.login1");
const static QString login1Path = QStringLiteral("/org/freedesktop/login1");
const static QString login1ManagerInterface = QStringLiteral("org.freedesktop.login1.Manager");

UserInfo::UserInfo() : mFirstLoad(true)
{
    pluginName = QObject::tr("User Info");
    pluginType = ACCOUNT;
}

UserInfo::~UserInfo()
{
    if (!mFirstLoad) {
        delete ui;
        ui = nullptr;
        delete autoSettings;
        autoSettings = nullptr;
    }
}

QString UserInfo::plugini18nName()
{
    return pluginName;
}

int UserInfo::pluginTypes()
{
    return pluginType;
}

QWidget *UserInfo::pluginUi()
{
    if (mFirstLoad) {
        mFirstLoad = false;

        ui = new Ui::UserInfo;
        pluginWidget = new QWidget;
        pluginWidget->setAttribute(Qt::WA_DeleteOnClose);
        ui->setupUi(pluginWidget);

        /**/
        pluginWidget2 = new QWidget;
        pluginWidget2->setAttribute(Qt::WA_DeleteOnClose);

        m_pMulFactorDbus = new PwdlessService(this);

        initUI();

        // 构建System dbus调度对象
        sysdispatcher = new SystemDbusDispatcher(this);

        userSettingDbus =  new QDBusInterface("org.ukui.groupmanager",
                                              "/org/ukui/groupmanager",
                                              "org.ukui.groupmanager.interface",
                                              QDBusConnection::systemBus());
        // 将以后所有DBus调用的超时设置为 milliseconds
        userSettingDbus->setTimeout(2147483647); // -1 为默认的25s超时

        m_pUniauthBackendDbus = new UniAuthService();
        // 将以后所有DBus调用的超时设置为 milliseconds
        m_pUniauthBackendDbus->setTimeout(2147483647); // -1 为默认的25s超时

        m_pLoginMgrInterface = new QDBusInterface(login1Service,
                                                 login1Path,
                                                 login1ManagerInterface,
                                                 QDBusConnection::systemBus(),
                                                 this);

        // 获取系统全部用户信息，用户Uid大于等于1000的
        _acquireAllUsersInfo();

        readCurrentPwdConf();

        initSearchText();

        buildAndSetupUsers();
        setUserConnect();
        qApp->installEventFilter(this);
    }
    return pluginWidget2;
}

const QString UserInfo::name() const
{

    return QStringLiteral("Userinfo");
}

bool UserInfo::isShowOnHomePage() const
{
    return !UkccCommon::isTablet();
}

QIcon UserInfo::icon() const
{
    return QIcon::fromTheme("user-available-symbolic");
}

bool UserInfo::isEnable() const
{
    return !UkccCommon::isTablet();
}

void UserInfo::initSearchText()
{
    //~ contents_path /Userinfo/CurrentUser
    currentLabel->setText(tr("CurrentUser"));
//    //~ contents_path /Userinfo/LoginWithoutPwd
//    nopwdLoginLabel->setText(tr("LoginWithoutPwd"));
//    //~ contents_path /Userinfo/AutoLoginOnBoot
//    autoLoginLabel->setText(tr("AutoLoginOnBoot"));
    //~ contents_path /Userinfo/OthersUser
    othersLabel->setText(tr("OthersUser"));
    //~ contents_path /Userinfo/Add
    tr("Add");
}

/**3.1****begin************/

void UserInfo::initUI()
{
    //标题
    currentLabel = new TitleLabel();
    othersLabel = new TitleLabel();

    //当前用户区域
    currentFrame = new SettingGroup();

    //当前用户
    currentUserFrame = new UkccFrame();
    //分割线
    splitVLine1 = createVLine(currentUserFrame, 10);
    splitVLine2 = createVLine(currentUserFrame, 10);

    currentUserlogoBtn = new KLabel();
    currentUserlogoBtn->setObjectName("currentUserlogo");
    currentUserlogoBtn->setFixedSize(QSize(96, 96));
    KDK_EXTEND_ALL_INFO_FORMAT(currentUserlogoBtn, "Userinfo", "", "");

    changeCurrentPwdBtn = new KPushButton();
    //~ contents_path /Userinfo/Password
    changeCurrentPwdBtn->setText(tr("Password"));
    changeCurrentPwdBtn->setObjectName("Password");

    changeCurrentTypeBtn = new KPushButton();
    //~ contents_path /Userinfo/Type
    changeCurrentTypeBtn->setText(tr("Type"));
    changeCurrentTypeBtn->setObjectName("Type");

    changeCurrentGroupsBtn = new KPushButton();
    //~ contents_path /Userinfo/Groups
    changeCurrentGroupsBtn->setText(tr("Groups"));
    changeCurrentGroupsBtn->setObjectName("Groups");

    currentNickNameLabel = new KLabel();
    QFont font = currentNickNameLabel->font();
    qDebug() << "init font size : " << font.pointSize() << font.pixelSize();
    font.setPointSize(font.pointSize() + 2);
    currentNickNameLabel->setFont(font);

    currentNickNameChangeLabel = new QLabel();
    currentNickNameChangeLabel->setObjectName("currentNickNameChange");
    currentNickNameChangeLabel->setFixedSize(QSize(15, 22));
    currentNickNameChangeLabel->setProperty("useIconHighlightEffect", 0x8);
    currentNickNameChangeLabel->setPixmap(QIcon::fromTheme("document-edit-symbolic").pixmap(currentNickNameChangeLabel->size()));
    KDK_EXTEND_ALL_INFO_FORMAT(currentNickNameChangeLabel, "Userinfo", "", "");

    currentUserTypeLabel = new QLabel();
    currentUserTypeLabel->setEnabled(false);
    currentUserTypeLabel->setFixedHeight(20);
    currentUserTypeLabel->setFixedWidth(100);

    currentNickNameHorLayout = new QHBoxLayout();
    currentNickNameHorLayout->setSpacing(0);
    currentNickNameHorLayout->setContentsMargins(0, 0, 0, 0);
    currentNickNameHorLayout->addWidget(currentNickNameLabel);
    currentNickNameHorLayout->addWidget(currentNickNameChangeLabel);
    currentNickNameHorLayout->addStretch();

    currentUserinfoVerLayout = new QVBoxLayout();
    currentUserinfoVerLayout->setSpacing(4);
    currentUserinfoVerLayout->setContentsMargins(0, 0, 0, 0);
    currentUserinfoVerLayout->addStretch();
    currentUserinfoVerLayout->addLayout(currentNickNameHorLayout);
    currentUserinfoVerLayout->addWidget(currentUserTypeLabel, Qt::AlignHCenter);
    currentUserinfoVerLayout->addStretch();

    currentUserHorLayout = new QHBoxLayout();
    currentUserHorLayout->setSpacing(8);
    currentUserHorLayout->setContentsMargins(16, 0, 16, 0);
    currentUserHorLayout->addWidget(currentUserlogoBtn);
    currentUserHorLayout->addLayout(currentUserinfoVerLayout);
    currentUserHorLayout->addStretch();
    currentUserHorLayout->addWidget(changeCurrentPwdBtn);
    currentUserHorLayout->addWidget(splitVLine1);
    currentUserHorLayout->addWidget(changeCurrentTypeBtn);
    currentUserHorLayout->addWidget(splitVLine2);
    currentUserHorLayout->addWidget(changeCurrentGroupsBtn);

    currentUserFrame->setMinimumSize(QSize(550, 127));
    currentUserFrame->setMaximumSize(QSize(16777215, 127));
    currentUserFrame->setFrameShape(QFrame::WinPanel);
    currentUserFrame->setLayout(currentUserHorLayout);

    //免密登录
    //~ contents_path /Userinfo/LoginWithoutPwd
    nopwdLoginFrame = new SwitchWidget(tr("LoginWithoutPwd"));
    nopwdLoginFrame->setObjectName("LoginWithoutPwd");
    KDK_EXTEND_ALL_INFO_FORMAT(nopwdLoginFrame->switchButton(), "Userinfo", "", "");

    //开机自动登录
    //~ contents_path /Userinfo/AutoLoginOnBoot
    autoLoginFrame = new SwitchWidget(tr("AutoLoginOnBoot"), pluginWidget2, UkccFrame::Bottom);
    autoLoginFrame->setObjectName("AutoLoginOnBoot");
    KDK_EXTEND_ALL_INFO_FORMAT(autoLoginFrame->switchButton(), "Userinfo", "", "");

    currentFrame->insertWidget(0, currentUserFrame);
    currentFrame->insertWidget(1, nopwdLoginFrame);
    currentFrame->insertWidget(2, autoLoginFrame);

    // 开启了双因子认证的提示
    m_pTipMessage =  new MessageBar;
    m_pTipMessage->setMinimumSize(550, 36);
    m_pTipMessage->setMaximumSize(16777215, 36);
    m_pTipMessage->setContentsMargins(0,0,0,0);
    KLabel *tipLabel = new KLabel;
    tipLabel->setPixmap(QIcon::fromTheme("dialog-warning"), 16, 16);
    tipLabel->setText(tr("Two factor authentication has been enabled, but the \"password free login\" and \"automatic login upon startup\" functions cannot be activated."));
    QHBoxLayout *hlayout = new QHBoxLayout;
    hlayout->setContentsMargins(16,0,16,0);
    hlayout->addWidget(tipLabel);
    m_pTipMessage->setLayout(hlayout);
    m_pTipMessage->hide();

    //其他用户区域
    addUserBtn = new AddButton(pluginWidget2);
    addUserBtn->setObjectName("addUser");
    addUserBtn->setRadiusType(UkccFrame::Around);

    addUserHorLayout = new QHBoxLayout();
    addUserHorLayout->setContentsMargins(0, 0, 0, 0);
    addUserHorLayout->addWidget(addUserBtn);
    KDK_EXTEND_ALL_INFO_FORMAT(addUserBtn, "Userinfo", "", "");

    addUserFrame = new UkccFrame(pluginWidget2, UkccFrame::BorderRadiusStyle::Around, true);
    addUserFrame->setContentsMargins(0,0,0,0);
    addUserFrame->setObjectName("addUserframe");
    addUserFrame->setLayout(addUserHorLayout);

    othersFrame = new SettingGroup(pluginWidget2);
    othersFrame->insertWidget(0, addUserFrame);

    //界面主布局
    mainVerLayout = new QVBoxLayout(pluginWidget2);
    mainVerLayout->setSpacing(8);
    mainVerLayout->setContentsMargins(0, 0, 0, 0);

    mainVerLayout->addWidget(currentLabel);
    mainVerLayout->addWidget(currentFrame);
    mainVerLayout->addWidget(m_pTipMessage);

    mainVerLayout->addSpacing(40);

    mainVerLayout->addWidget(othersLabel);
    mainVerLayout->addWidget(othersFrame);

    // 服务器 && root用户
    if (UkccCommon::isExistMfa()) {
        if (UkccCommon::isServerVersion()) {
            if (!getuid()) {
                initMoreSettingsUI();
                initMoreSettingsStatus();
            }
        } else {
            initMoreSettingsUI();
            initMoreSettingsStatus();
        }
    }

    mainVerLayout->addStretch();

    pluginWidget2->setLayout(mainVerLayout);

#ifdef WITHKYSEC
    if (!kysec_is_disabled() && kysec_get_3adm_status() && (getuid() || geteuid())){
        addUserBtn->setEnabled(false);
    }
#endif

    //root需要屏蔽部分功能
    if (!getuid()){
        currentNickNameChangeLabel->setEnabled(false);
        currentNickNameLabel->setEnabled(false);
        changeCurrentTypeBtn->setEnabled(false);
        currentUserlogoBtn->setEnabled(false);
        autoLoginFrame->hide();
        nopwdLoginFrame->hide();
    }
    changeCurrentTypeBtn->setEnabled(false);
    hideComponent();
}

void UserInfo::initMoreSettingsUI()
{
    m_pMoreSettingsTitleLabel = new KLabel();
    m_pMoreSettingsTitleLabel->setContentsMargins(16, 0, 0, 0);
    //~ contents_path /Userinfo/More Settings
    m_pMoreSettingsTitleLabel->setText(tr("More Settings"));

    //~ contents_path /Userinfo/Enable two factor authentication
    m_pMultipleFactorFrame = new SwitchWidget(tr("Enable two factor authentication"), pluginWidget2,
                                            UkccFrame::None, tr("After activation, secondary verification is required when logging in with a password."));

    m_pMultipleFactorFrame->setHeightAdaptive(false);
    m_pMultipleFactorFrame->setFixedHeight(80);
    m_pMultipleFactorFrame->setObjectName("Enable two factor authentication");
    KDK_EXTEND_ALL_INFO_FORMAT(m_pMultipleFactorFrame, "Userinfo", "", "");
    KDK_EXTEND_ALL_INFO_FORMAT(m_pMultipleFactorFrame->switchButton(), "Userinfo", "", "");

    m_pOtpDynamicPasswordFrame = new UkccFrame();
    KDK_EXTEND_ALL_INFO_FORMAT(m_pOtpDynamicPasswordFrame, "Userinfo", "", "");
    QRadioButton *otpDynamicPasswordButton = new QRadioButton(tr("OTP Dynamic Password"));
    KDK_EXTEND_ALL_INFO_FORMAT(otpDynamicPasswordButton, "Userinfo", "", "");
    m_pIsBindOTPLabel = new KLabel();
    QHBoxLayout *optHLayout = new QHBoxLayout;
    optHLayout->addWidget(otpDynamicPasswordButton);
    optHLayout->addWidget(m_pIsBindOTPLabel);
    optHLayout->addStretch();
    m_pOtpDynamicPasswordFrame->setLayout(optHLayout);

    m_pSecurityKeyFrame = new UkccFrame();
    QRadioButton *securityKeyButton = new QRadioButton(tr("Security Key"));
    KDK_EXTEND_ALL_INFO_FORMAT(m_pSecurityKeyFrame, "Userinfo", "", "");
    KDK_EXTEND_ALL_INFO_FORMAT(securityKeyButton, "Userinfo", "", "");
    m_pIsBindSecurityLabel = new KLabel();
    QHBoxLayout *securityKeyHLayout = new QHBoxLayout;
    securityKeyHLayout->addWidget(securityKeyButton);
    securityKeyHLayout->addWidget(m_pIsBindSecurityLabel);
    securityKeyHLayout->addStretch();
    m_pSecurityKeyFrame->setLayout(securityKeyHLayout);

    m_pAllowSSHFrame = new UkccFrame();
    //~ contents_path /Userinfo/Allow SSH to log in through two factor login
    m_pAllowSShButton = new QCheckBox(tr("Allow SSH to log in through two factor login"));
    KDK_EXTEND_ALL_INFO_FORMAT(m_pSecurityKeyFrame, "Userinfo", "", "");
    KDK_EXTEND_ALL_INFO_FORMAT(m_pAllowSShButton, "Userinfo", "", "Allow SSH to log in through two factor login");
    QHBoxLayout *allowSSHHLayout = new QHBoxLayout;
    allowSSHHLayout->addWidget(m_pAllowSShButton);
    m_pAllowSSHFrame->setLayout(allowSSHHLayout);

    m_pFactoyButtonGroup = new QButtonGroup;
    m_pFactoyButtonGroup->addButton(otpDynamicPasswordButton, 0);
    m_pFactoyButtonGroup->addButton(securityKeyButton, 1);
    m_pMultipleFactorGroup = new SettingGroup;
    m_pMultipleFactorGroup->insertWidget(0, m_pMultipleFactorFrame);
    m_pMultipleFactorGroup->insertWidget(1, m_pOtpDynamicPasswordFrame);
    m_pMultipleFactorGroup->insertWidget(2, m_pSecurityKeyFrame);
    m_pMultipleFactorGroup->insertWidget(3, m_pAllowSSHFrame);

    mainVerLayout->addSpacing(40);
    mainVerLayout->addWidget(m_pMoreSettingsTitleLabel);
    mainVerLayout->addWidget(m_pMultipleFactorGroup);
}

void UserInfo::initFactoryStatus()
{
    // 判断是否绑定OTP
    QStringList authMethodList = m_pMulFactorDbus->GetBoundFactorMethods(g_get_user_name());
    if (authMethodList.contains("otp")) {
        m_pIsBindOTPLabel->setText(tr("Bound"));
        m_pIsBindOTPLabel->setFontColor(Qt::green);
    } else {
        m_pIsBindOTPLabel->setText(tr("Unbound"));
        m_pIsBindOTPLabel->setFontColor(Qt::red);
    }

    // 判断是否绑定安全密钥
    if (authMethodList.contains("ukey")) {
        m_pIsBindSecurityLabel->setText(tr("Bound"));
        m_pIsBindSecurityLabel->setFontColor(Qt::green);
    } else {
        m_pIsBindSecurityLabel->setText(tr("Unbound"));
        m_pIsBindSecurityLabel->setFontColor(Qt::red);
    }

    QString method;
    int result = m_pMulFactorDbus->GetDualFactorStatus(method);
    bool isOpen = (result == 1 ? true : false);

    m_pMultipleFactorFrame->switchButton()->blockSignals(true);
    m_pMultipleFactorFrame->switchButton()->setChecked(isOpen);
    m_pMultipleFactorFrame->switchButton()->blockSignals(false);
    m_pOtpDynamicPasswordFrame->setVisible(isOpen);
    m_pSecurityKeyFrame->setVisible(isOpen);

    // 402637要求 ukey 不支持 ssh，进行隐藏
    m_pAllowSSHFrame->setVisible(isOpen && !(method.compare("ukey") == 0) && UkccCommon::isExistOpensshServer());

    if (isOpen) {
        nopwdLoginFrame->blockSignals(true);
        nopwdLoginFrame->setChecked(false);
        nopwdLoginFrame->blockSignals(false);
        autoLoginFrame->blockSignals(true);
        autoLoginFrame->setChecked(false);
        autoLoginFrame->blockSignals(false);
        autoLoginFrame->setEnabled(false);
        nopwdLoginFrame->setEnabled(false);
        m_pTipMessage->setVisible(true);
    } else {
        autoLoginFrame->setEnabled(true);
        nopwdLoginFrame->setEnabled(true);
        m_pTipMessage->setVisible(false);
    }

    m_pFactoyButtonGroup->blockSignals(true);
    m_pFactoyButtonGroup->button(0)->setChecked(method.compare("otp") == 0);
    m_pFactoyButtonGroup->button(1)->setChecked(method.compare("ukey") == 0);
    m_pFactoyButtonGroup->blockSignals(false);

    m_pAllowSShButton->blockSignals(true);
    m_pAllowSShButton->setChecked((m_pMulFactorDbus->GetSshAuthStatus("otp")
                                   || m_pMulFactorDbus->GetSshAuthStatus("ukey")));
    m_pAllowSShButton->blockSignals(false);
}

void UserInfo::initMoreSettingsStatus()
{
    initFactoryStatus();

    connect(m_pMultipleFactorFrame->switchButton(), &KSwitchButton::stateChanged, this, &UserInfo::onSetFactoySlot);

    connect(m_pAllowSShButton, &QCheckBox::stateChanged, this, &UserInfo::onAllowSSHChangedSlot);

    connect(m_pFactoyButtonGroup, QOverload<int>::of(&QButtonGroup::buttonClicked), this, &UserInfo::onChangeDualFactor);


    QDBusConnection::systemBus().connect("com.kylin.pwdless.daemon",
                                         "/",
                                         "com.kylin.pwdless.daemon",
                                         "userBindStatusChanged",
                                         this,
                                         SLOT(onBindStatusChanged(QString,QString,int)));


    QDBusConnection::systemBus().connect("com.kylin.pwdless.daemon",
                                         "/",
                                         "com.kylin.pwdless.daemon",
                                         "mfaStatusChanged",
                                         this,
                                         SLOT(onMulEnableStatusChanged(bool, QString)));
}

void UserInfo::onMulEnableStatusChanged(bool isOpen, QString method)
{
    m_pMultipleFactorFrame->switchButton()->blockSignals(true);
    m_pMultipleFactorFrame->switchButton()->setChecked(isOpen);
    m_pMultipleFactorFrame->switchButton()->blockSignals(false);
    m_pOtpDynamicPasswordFrame->setVisible(isOpen);
    m_pSecurityKeyFrame->setVisible(isOpen);
    m_pAllowSSHFrame->setVisible(isOpen && !(method.compare("ukey") == 0));
    m_pFactoyButtonGroup->blockSignals(true);
    m_pFactoyButtonGroup->button(0)->setChecked(method.compare("otp") == 0);
    m_pFactoyButtonGroup->button(1)->setChecked(method.compare("ukey") == 0);
    m_pFactoyButtonGroup->blockSignals(false);

    if (isOpen) {
        nopwdLoginFrame->blockSignals(true);
        nopwdLoginFrame->setChecked(false);
        nopwdLoginFrame->blockSignals(false);
        autoLoginFrame->blockSignals(true);
        autoLoginFrame->setChecked(false);
        autoLoginFrame->blockSignals(false);
        autoLoginFrame->setEnabled(false);
        nopwdLoginFrame->setEnabled(false);
        m_pTipMessage->setVisible(true);
    } else {
        autoLoginFrame->setEnabled(true);
        nopwdLoginFrame->setEnabled(true);
        m_pTipMessage->setVisible(false);
    }
}

void UserInfo::onBindStatusChanged(QString user, QString method, int bind)
{
    if (user == mUserName) {
        QStringList authMethodList = m_pMulFactorDbus->GetBoundFactorMethods(mUserName);
        if (authMethodList.contains("otp")) {
            m_pIsBindOTPLabel->setText(tr("Bound"));
            m_pIsBindOTPLabel->setFontColor(Qt::green);
        } else {
            m_pIsBindOTPLabel->setText(tr("Unbound"));
            m_pIsBindOTPLabel->setFontColor(Qt::red);
        }

        // 判断是否绑定安全密钥
        if (authMethodList.contains("ukey")) {
            m_pIsBindSecurityLabel->setText(tr("Bound"));
            m_pIsBindSecurityLabel->setFontColor(Qt::green);
        } else {
            m_pIsBindSecurityLabel->setText(tr("Unbound"));
            m_pIsBindSecurityLabel->setFontColor(Qt::red);
        }
    }
}

void UserInfo::onChangeDualFactor(int id)
{
    qDebug() << __FUNCTION__ << id;

    // 当前已开启 点击的第二因子为选中状态，不调用接口，直接返回
    QString method;
    int result = m_pMulFactorDbus->GetDualFactorStatus(method);
    if ((id == 0 && method == "otp") || (id == 1 && method == "ukey")) {
        return;
    }

    UkccCommon::buriedSettings(name(), id == 0 ? QString("OTP Dynamic Password") : QString("Security Key"), QString("settings"), QString::number(id));

    m_factorUser = mUserName;

    // 判断选中是否是已绑定的，未绑定则先弹窗绑定
    QStringList authMethodList = m_pMulFactorDbus->GetBoundFactorMethods(m_factorUser);
    switch (id) {
    case 0:
        if (authMethodList.contains("otp")) {
            m_pMulFactorDbus->EnableDualFactor("otp");
        } else {
            showBindOtpDialog(m_factorUser);
        }
        break;
    case 1:
        if (authMethodList.contains("ukey")) {
            m_pMulFactorDbus->EnableDualFactor("ukey");
        } else {
            showSecurityKeyDialog(m_factorUser);
        }
        break;
    default:
        break;
    }

    // 绑定完成后，设置为第二因子
    QStringList authMethodList1 = m_pMulFactorDbus->GetBoundFactorMethods(m_factorUser);
    if (id == 0 && !authMethodList.contains("otp") && authMethodList1.contains("otp")) {
        m_pMulFactorDbus->EnableDualFactor("otp");
    }

    if (id == 1 && !authMethodList.contains("ukey") && authMethodList1.contains("ukey")) {
        m_pMulFactorDbus->EnableDualFactor("ukey");
    }

    initFactoryStatus();
}

void UserInfo::onSetFactoySlot(bool checked)
{
    UkccCommon::buriedSettings(name(), m_pMultipleFactorFrame->objectName(), QString("settings"), checked ? "true":"false");
    if (checked) {
        // 开启多因子认证，需要关闭所有用户的免密登录与自动登录，弹窗提示用户
        QMessageBox msg(this->pluginWidget2);
        msg.setIcon(QMessageBox::Warning);
        msg.setText(tr("Enabling two factor authentication will disable all user password free login and automatic login settings."));
        QPushButton *cancelBtn = msg.addButton(tr("Cancel"), QMessageBox::RejectRole);
        msg.setEscapeButton(cancelBtn);
        QTimer::singleShot(0, &msg, [&]() {
            cancelBtn->setVisible(false);
            qDebug() << "Cancel button status：" << (cancelBtn->isVisible() ? "visible" : "hidden");
        });
        QPushButton *confirmBtn = msg.addButton(tr("Confirm"), QMessageBox::AcceptRole);
        msg.setDefaultButton(confirmBtn);
        int ret = msg.exec();
        qDebug() << "ret = " << ret << msg.clickedButton() << confirmBtn;
        if (ret != QMessageBox::Accepted) {
            m_pMultipleFactorFrame->switchButton()->blockSignals(true);
            m_pMultipleFactorFrame->switchButton()->setChecked(false);
            m_pMultipleFactorFrame->switchButton()->blockSignals(false);
            return;
        }

        // 开启多因子认证，先弹窗选择第二因子
        m_factorUser = mUserName;
        mulDialog = new MulVerifyDialog(false, pluginWidget2);
        QStringList authMethodList = m_pMulFactorDbus->GetBoundFactorMethods(m_factorUser);
        qDebug() << authMethodList;
        mulDialog->refreshBindStatus("otp", authMethodList.contains("otp"));
        mulDialog->refreshBindStatus("ukey", authMethodList.contains("ukey"));
        // 根据选择的第二因子是否已绑定，进行绑定设置
        connect(mulDialog, &MulVerifyDialog::onSelectFactorySignal, this, [=](int id){
            onSelectFactorSlot(id);
            QStringList authMethodList = m_pMulFactorDbus->GetBoundFactorMethods(m_factorUser);
            mulDialog->refreshBindStatus("otp", authMethodList.contains("otp"));
            mulDialog->refreshBindStatus("ukey", authMethodList.contains("ukey"));
        });
        if (mulDialog->exec() != QDialog::Accepted) {
            // 选择弹窗未进行选择，直接关闭，恢复账户界面ui
            m_pMultipleFactorFrame->switchButton()->blockSignals(true);
            m_pMultipleFactorFrame->switchButton()->setChecked(false);
            m_pMultipleFactorFrame->switchButton()->blockSignals(false);
        } else {

            initFactoryStatus();
        }
    } else {
        // 关闭多因子认证
        int reply = m_pMulFactorDbus->DisableDualFactor();
        if (reply == 0) {
            m_pOtpDynamicPasswordFrame->setVisible(false);
            m_pSecurityKeyFrame->setVisible(false);
            m_pAllowSSHFrame->setVisible(false);
            nopwdLoginFrame->setEnabled(true);
            autoLoginFrame->setEnabled(true);
            m_pTipMessage->setVisible(false);
        } else {
            m_pMultipleFactorFrame->switchButton()->blockSignals(true);
            m_pMultipleFactorFrame->switchButton()->setChecked(!checked);
            m_pMultipleFactorFrame->switchButton()->blockSignals(false);
        }
    }
}

void UserInfo::onSelectFactorSlot(int id)
{
    QStringList authMethodList = m_pMulFactorDbus->GetBoundFactorMethods(m_factorUser);
    qDebug() << id << authMethodList;
    switch (id) {
    case 0:
        // otp 若未绑定则先进行绑定
        if (!authMethodList.contains("otp")) {
            // 弹窗绑定otp
            if (mulDialog != nullptr) {
                OtpBindDialog *otpBindDialog = new OtpBindDialog(m_factorUser, m_pMulFactorDbus, mulDialog);
                otpBindDialog->setQrCodePixmap(m_pMulFactorDbus->GetOtpQrCode(m_factorUser, 0));
                otpBindDialog->exec();
            } else {
                OtpBindDialog *otpBindDialog = new OtpBindDialog(m_factorUser, m_pMulFactorDbus, pluginWidget2);
                otpBindDialog->setQrCodePixmap(m_pMulFactorDbus->GetOtpQrCode(m_factorUser, 0));
                otpBindDialog->exec();
            }

        } else {
            // 设置otp为第二因子
            m_pMulFactorDbus->EnableDualFactor("otp");
        }
        break;
    case 1:
        // 安全密钥
        if (!authMethodList.contains("ukey")) {
            // 弹窗 绑定安全密钥
            if (mulDialog != nullptr) {
                SecurityKeySetDlg *securityKeySetDlg = new SecurityKeySetDlg(m_factorUser, m_pMulFactorDbus, mulDialog);
                securityKeySetDlg->setAttribute(Qt::WA_DeleteOnClose);
                int ret = securityKeySetDlg->exec();
            } else {
                SecurityKeySetDlg *securityKeySetDlg = new SecurityKeySetDlg(m_factorUser, m_pMulFactorDbus, pluginWidget2);
                securityKeySetDlg->setAttribute(Qt::WA_DeleteOnClose);
                int ret = securityKeySetDlg->exec();
            }
        } else {
            // 设置安全密钥为第二因子
            m_pMulFactorDbus->EnableDualFactor("ukey");
        }
        break;
    default:
        break;
    }
}

void UserInfo::onAllowSSHChangedSlot(bool checked)
{
    // 设置允许ssh连接
    UkccCommon::buriedSettings(name(), m_pAllowSShButton->objectName(), QString("settings"), checked ? "true":"false");

    int ret = m_pMulFactorDbus->SetSshAuthStatus(m_pFactoyButtonGroup->checkedId()==0?"otp":"ukey", checked);
    if (ret != 0) {
        m_pAllowSShButton->blockSignals(true);
        m_pAllowSShButton->setCheckState(checked ? Qt::Unchecked : Qt::Checked);
        m_pAllowSShButton->blockSignals(false);
    }
}

void UserInfo::hideComponent()
{
    if (QString(QLatin1String(kdk_system_get_hostCloudPlatform())) == "huawei") {
        ui->changePwdBtn->setVisible(false);
        changeCurrentPwdBtn->setVisible(false);
        splitVLine1->setVisible(false);
        autoLoginFrame->setVisible(false);
        nopwdLoginFrame->setVisible(false);
    }

    // ABC 项目要求隐藏
    kdk_custom_info info = kdk_system_get_custom_version();
    qDebug() << "custom_info = " << info.custom_info;
    if (QString(info.custom_info).compare("ABC", Qt::CaseInsensitive) == 0) {
        autoLoginFrame->setVisible(false);
        nopwdLoginFrame->setVisible(false);
    }

    // 香港警察要求本地用户与域用户修改密码按钮均置灰
#ifdef XGJC
    changeCurrentPwdBtn->setEnabled(false);
#endif
}

void UserInfo::setSecurityControl()
{
    // 安全管控 设置项的显示与隐藏
    QVariantMap ModuleMap = UkccCommon::getModuleHideStatus();
    QString moduleSettings = ModuleMap.value(name().toLower() + "Settings").toString();
    QStringList setItems = moduleSettings.split(",");
    qDebug() << __FUNCTION__ << moduleSettings;
    foreach (QString setItem, setItems) {
        QStringList item = setItem.split(":");
        if (item.size() != 2) {
            continue;
        }
        qDebug() << "set item Name: " << item.at(0) << item.at(1);
        if (item.at(0) == "noPwdLoginFrame") {
            nopwdLoginFrame->setVisible(item.at(1) == "true");
        }
        if (item.at(0) == "autoLoginFrame") {
            if (item.at(1) == "true") {
                nopwdLoginFrame->setRadiusType(UkccFrame::None);
            } else {
                nopwdLoginFrame->setRadiusType(UkccFrame::Bottom);
            }
            autoLoginFrame->setVisible(item.at(1) == "true");
        }
        if (item.at(0) == "changeCurrentPwdBtn") {
            changeCurrentPwdBtn->setVisible(item.at(1) == "true");
            splitVLine1->setVisible(item.at(1) == "true");
        }
        if (item.at(0) == "changeCurrentTypeBtn") {
            splitVLine2->setVisible(item.at(1) == "true");
            changeCurrentTypeBtn->setVisible(item.at(1) == "true");
        }
        if (item.at(0) == "changeCurrentGroupsBtn") {
            changeCurrentGroupsBtn->setVisible(item.at(1) == "true");
            if (changeCurrentGroupsBtn->isHidden()) {
                splitVLine2->setVisible(item.at(1) == "true");
            }
        }
        // 当前用户为管理员用户，才可修改其他用户密码、类型、删除用户，非管理员用户隐藏入口
        if (item.at(0) == "UtilsChangePwdBtn") {
            foreach (UtilsForUserinfo *utils, utilsUsers) {
                utils->setPwdVisible(item.at(1) == "true" && m_currentUserType != STANDARDUSER);
            }
        }

        if (item.at(0) == "UtilsChangeTypeBtn") {
            foreach (UtilsForUserinfo *utils, utilsUsers) {
                utils->setTypeVisible(item.at(1) == "true" && m_currentUserType != STANDARDUSER);
            }
        }

        if (item.at(0) == "UtilsDeleteBtn") {
            foreach (UtilsForUserinfo *utils, utilsUsers) {
                utils->setDelVisible(item.at(1) == "true" && m_currentUserType != STANDARDUSER);
            }
        }

        // 当前用户为管理员用户，才可添加用户，非管理员用户隐藏入口
        if (item.at(0) == "addUserBtn") {
            addUserFrame->setVisible(item.at(1) == "true" && m_currentUserType != STANDARDUSER);
        }

        if (item.at(0) == "currentNickNameChangeLabel") {
            currentNickNameChangeLabel->setVisible(item.at(1) == "true");
            currentNickNameLabel->setEnabled(item.at(1) == "true");
        }

        if (item.at(0) == "UtilsUsersAll") {
            othersFrame->setVisible(item.at(1) == "true");
            othersLabel->setVisible(item.at(1) == "true");
        }
    }

    if (changeCurrentTypeBtn->isHidden() && changeCurrentGroupsBtn->isHidden()) {
        splitVLine1->setVisible(false);
    }

    // 安全管控 设置项的启用与禁用
    QString moduleEnableSettings = ModuleMap.value(name().toLower() + "Enable").toString();
    QStringList enableSetItems = moduleEnableSettings.split(",");

    foreach (QString setItem, enableSetItems) {
        QStringList item = setItem.split(":");
        if (item.size() != 2) {
            continue;
        }
        qDebug() << "set item Name: " << item.at(0) << item.at(1);
        if (item.at(0) == "noPwdLoginFrame") {
            nopwdLoginFrame->setEnabled(item.at(1) == "true");
        }
        if (item.at(0) == "autoLoginFrame") {
            autoLoginFrame->setEnabled(item.at(1) == "true");
        }
        if (item.at(0) == "changeCurrentPwdBtn") {
            changeCurrentPwdBtn->setEnabled(item.at(1) == "true");
        }
        if (item.at(0) == "changeCurrentGroupsBtn") {
            changeCurrentGroupsBtn->setEnabled(item.at(1) == "true");
        }
        if (item.at(0) == "UtilsChangePwdBtn") {
            foreach (UtilsForUserinfo *utils, utilsUsers) {
                utils->refreshPwdStatus(item.at(1) == "true");
            }
        }
        if (item.at(0) == "UtilsChangeTypeBtn") {
            foreach (UtilsForUserinfo *utils, utilsUsers) {
                utils->refreshTypeStatus(item.at(1) == "true");
            }
        }

        if (item.at(0) == "UtilsDeleteBtn") {
            foreach (UtilsForUserinfo *utils, utilsUsers) {
                utils->refreshDelStatus(item.at(1) == "true");
            }
        }

        if (item.at(0) == "addUserBtn") {
            addUserFrame->setEnabled(item.at(1) == "true");
        }

        if (item.at(0) == "currentNickNameChangeLabel") {
            currentNickNameChangeLabel->setEnabled(item.at(1) == "true");
            currentNickNameLabel->setEnabled(item.at(1) == "true");
        }

        if (item.at(0) == "UtilsUsersAll") {
            othersFrame->setEnabled(item.at(1) == "true");
        }
    }

}

void UserInfo::buildAndSetupUsers()
{
    QMap<QString, UserInfomation>::iterator it = allUserInfoMap.begin();
    for (; it != allUserInfoMap.end(); it++){
        UserInfomation user = it.value();

        //当前用户
        if (user.username == QString(g_get_user_name())) {

            //设置用户头像
            QPixmap iconfile = makeRoundLogo(user.iconfile, currentUserlogoBtn->width(), currentUserlogoBtn->height(), currentUserlogoBtn->width()/2);
            currentUserlogoBtn->setPixmap(iconfile, currentUserlogoBtn->width(), currentUserlogoBtn->height());

            //设置用户昵称
            currentNickNameLabel->setText(user.realname);

            //用户类型
            QString cType = _accountTypeIntToString(user.accounttype);
            if (setTextDynamic(currentUserTypeLabel, cType)) {
                currentUserTypeLabel->setToolTip(cType);
            }
            fontSizeChange(user, nullptr);
            m_currentUserType = user.accounttype;
            if (m_currentUserType == STANDARDUSER) {
                addUserFrame->hide();
                if (m_pMoreSettingsTitleLabel != nullptr) {
                    m_pMoreSettingsTitleLabel->hide();
                }
                if (m_pMultipleFactorGroup != nullptr) {
                    m_pMultipleFactorGroup->hide();
                }
            }

            QProcess *process = new QProcess;
            process->start("dpkg -l | grep kim-client");
            process->waitForFinished();

            QByteArray ba = process->readAllStandardOutput();
            delete process;
            QString mOutput = QString(ba.data());
            // 域用户用户信息不可设置
            if (UkccCommon::isDomainUser(user.username.toLatin1().data())) {
                // 工行修改密码按钮置灰
                if (mOutput.contains("icbc")) {
                    changeCurrentPwdBtn->setEnabled(false);
                }
                currentNickNameChangeLabel->setEnabled(false);
                currentNickNameLabel->setEnabled(false);   
                changeCurrentGroupsBtn->setEnabled(false);
                changeCurrentTypeBtn->setEnabled(false);
                nopwdLoginFrame->setEnabled(false);
                autoLoginFrame->setEnabled(false);
                addUserBtn->setEnabled(false);
            }

            //设置自动登录状态
            autoLoginFrame->blockSignals(true);
            autoLoginFrame->setChecked(user.autologin);
            autoLoginFrame->blockSignals(false);

            //设置免密登录状态
            nopwdLoginFrame->blockSignals(true);
            nopwdLoginFrame->setChecked(user.noPwdLogin);
            nopwdLoginFrame->blockSignals(false);

            //绑定当前用户的属性改变回调
            setUserDBusPropertyConnect(user.objpath);

        } else {

            buildItemForUsersAndSetConnect(user);
        }
    }

    setSecurityControl();
    QDBusConnection::sessionBus().connect(QString(), QString("/"), "org.ukui.ukcc.session.interface", "configChanged", this, SLOT(setSecurityControl()));

    QDBusConnection::systemBus().connect(QString(), QString(), "org.freedesktop.Accounts", "UserAdded", this, SLOT(newUserCreateDoneSlot(QDBusObjectPath)));
    QDBusConnection::systemBus().connect(QString(), QString(), "org.freedesktop.Accounts", "UserDeleted", this, SLOT(existsUserDeleteDoneSlot(QDBusObjectPath)));
}

void UserInfo::buildItemForUsersAndSetConnect(UserInfomation user)
{
    UtilsForUserinfo * utils = new UtilsForUserinfo(this);
    utilsUsers << utils;
    utils->m_username = user.username;
    utils->refreshUserLogo(user.iconfile);
    utils->refreshUserNickname(user.realname);
    utils->refreshUserType(user.accounttype);
    utils->setObjectPathData(user.objpath);
    fontSizeChange(user, utils);
    // 香港警察要求所有用户修改密码按钮均置灰
#ifdef XGJC
    utils->refreshPwdStatus(false);
#endif

    if (m_currentUserType == STANDARDUSER) {
        utils->setDelVisible(false);
        utils->setPwdVisible(false);
        utils->setTypeVisible(false);
        utils->setMoreBtnVisible(false);
    }

    if (user.accounttype){
        utils->refreshDelStatus(!isLastAdmin(user.username));
    }
    utils->refreshTypeStatus(!isLastAdmin(user.username) && !user.logined);

    // 域用户按钮不可设置
    UserInfomation curruser = allUserInfoMap.value(g_get_user_name());
    if (UkccCommon::isDomainUser(curruser.username.toLatin1().data())) {
        utils->refreshDelStatus(false);
        utils->refreshPwdStatus(false);
        utils->refreshTypeStatus(false);
    }

#ifdef WITHKYSEC
    if (!kysec_is_disabled() && kysec_get_3adm_status()){
        if (user.username == "secadm" || user.username == "auditadm"){
            utils->refreshDelStatus(false);
            utils->refreshPwdStatus(false);
            utils->refreshTypeStatus(false);
        }
    }
#endif

    connect(utils, &UtilsForUserinfo::changeLogoBtnPressed, this, [=]{
        showChangeUserLogoDialog(user.username, utils);
    });
    connect(utils, &UtilsForUserinfo::changePwdBtnPressed, this, [=]{
        showChangeUserPwdDialog(user.username);
    });
    connect(utils, &UtilsForUserinfo::changeTypeBtnPressed, this, [=]{
        showChangeUserTypeDialog(user.username);
    });

    connect(utils, &UtilsForUserinfo::deleteUserBtnPressed, this, [=]{
        showDeleteUserExistsDialog(user.username);
    });

    connect(utils, &UtilsForUserinfo::bindOtpActPressed, this, [=]{
        showBindOtpDialog(user.username);
    });

    connect(utils, &UtilsForUserinfo::bindUkeyActPressed, this, [=]{
        showSecurityKeyDialog(user.username);
    });

    //用户类型发生变化，重置状态
    connect(this, &UserInfo::userTypeChanged, utils, [=](QString n){
        QStringList loginedUsers = getLoginedUsers();
        qDebug() << "update userType"<< user.username << loginedUsers.contains(user.username);
        utils->setDelVisible(m_currentUserType == STANDARDUSER ? false : true);
        utils->setPwdVisible(m_currentUserType == STANDARDUSER ? false : true);
        utils->setTypeVisible(m_currentUserType == STANDARDUSER ? false : true);
        addUserFrame->setVisible(m_currentUserType == STANDARDUSER ? false : true);
        utils->setMoreBtnVisible(m_currentUserType == STANDARDUSER ? false : true);

        utils->refreshDelStatus(!isLastAdmin(user.username));
        utils->refreshTypeStatus(!isLastAdmin(user.username) && !loginedUsers.contains(user.username));
#ifdef WITHKYSEC
        if (!kysec_is_disabled() && kysec_get_3adm_status()){
            if (user.username == "secadm" || user.username == "auditadm"){
                utils->refreshDelStatus(false);
                utils->refreshPwdStatus(false);
                utils->refreshTypeStatus(false);
            }
        }
#endif
    });

    QDBusInterface tmpProperty("org.freedesktop.Accounts",
                             user.objpath,
                             "org.freedesktop.DBus.Properties",
                             QDBusConnection::systemBus());

    tmpProperty.connection().connect("org.freedesktop.Accounts", user.objpath, "org.freedesktop.DBus.Properties", "PropertiesChanged",
                                    utils, SLOT(userPropertyChangedSlot(QString, QMap<QString, QVariant>, QStringList)));

    UkccFrame *newUserFrame = utils->buildItemForUsers();

    othersFrame->insertWidget(0, newUserFrame);
    addUserBtn->setRadiusType(UkccFrame::Bottom);
}

void UserInfo::showCreateUserNewDialog()
{
    //获取系统所有用户名列表，创建时判断重名
    QStringList usersStringList;
    QMap<QString, UserInfomation>::iterator it = allUserInfoMap.begin();
    for (; it != allUserInfoMap.end(); it++){
        UserInfomation user = it.value();
        usersStringList.append(user.realname);
    }

    CreateUserNew *dialog = new CreateUserNew(usersStringList, pluginWidget2);

    QList<AnswerInfo> securityQuestion;
    connect(dialog, &CreateUserNew::bindSecurityQuestion, this, [&](QString name, QList<AnswerInfo> answerInfo){
        securityQuestion = answerInfo;
    });
    QString passwordTips = "";
    connect(dialog, &CreateUserNew::bindPasswordTips, this, [&](const QString &text){
        passwordTips = text;
    });

    connect(dialog, &CreateUserNew::confirmCreated, this, [&](QString name, QString fullname, int accounttype, QString pwd){
        QDBusPendingCall call = userSettingDbus->asyncCall("createUser", name, fullname, accounttype, DEFAULTFACE, pwd);
        QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
        connect(watcher, &QDBusPendingCallWatcher::finished, this, [&, name, securityQuestion, passwordTips](QDBusPendingCallWatcher *call){
            const qint64 uid = getUserUid(name);
            if (!securityQuestion.isEmpty()) {
                int ret = m_pUniauthBackendDbus->BindUserSecurityAnswers(uid, securityQuestion);
                qDebug() << "ret of bind security question = " << ret;
            }

            if (!passwordTips.isEmpty()) {
                setPasswordTips(uid, passwordTips);
            }
        });
    });

    dialog->exec();
}

qint64 UserInfo::getUserUid(const QString &name)
{
    QStringList objectpaths = sysdispatcher->list_cached_users();
    qint64 uid = 0;
    for (QString objectpath : objectpaths){
        UserInfomation user;
        user = _acquireUserInfo(objectpath);
        if (user.username == name) {
            uid = user.uid;
        }
        allUserInfoMap.insert(user.username, user);
    }
    return uid;
}

void UserInfo::setPasswordTips(int uid, const QString &text)
{
    if (uid != 0) {
        int ret = m_pUniauthBackendDbus->SetUserPasswordHint(uid, text);
        qDebug() << "reply of SetUserPasswordHint = " << ret;
    }
}

void UserInfo::showDeleteUserExistsDialog(QString pName)
{
    QStringList loginedusers = getLoginedUsers();
    if (loginedusers.contains(pName)) {
        QMessageBox::warning(pluginWidget2, tr("Warning"), tr("The user is logged in, please delete the user after logging out"));
        return;
    }

    if (allUserInfoMap.keys().contains(pName)){
        UserInfomation user = allUserInfoMap.value(pName);

        DeleteUserExists *dialog = new DeleteUserExists(user.username, user.realname, pluginWidget2);
        connect(dialog, &DeleteUserExists::confirmChanged, this, [=](bool removeFiles){
            userSettingDbus->call("deleteUser", user.uid, removeFiles);
        });
        dialog->exec();
    }
}

void UserInfo::showBindOtpDialog(QString pName)
{
    m_factorUser = pName;
    OtpBindDialog *otpBindDialog = new OtpBindDialog(m_factorUser, m_pMulFactorDbus, pluginWidget2);
    otpBindDialog->setQrCodePixmap(m_pMulFactorDbus->GetOtpQrCode(m_factorUser, 0));
    otpBindDialog->exec();
}

void UserInfo::showSecurityKeyDialog(QString pName)
{
    m_factorUser = pName;
    SecurityKeySetDlg *securityKeySetDlg = new SecurityKeySetDlg(m_factorUser, m_pMulFactorDbus, pluginWidget2);
    securityKeySetDlg->setAttribute(Qt::WA_DeleteOnClose);
    int ret = securityKeySetDlg->exec();
}

void UserInfo::showChangeUserNicknameDialog()
{
    if (allUserInfoMap.keys().contains(g_get_user_name())){
        QStringList names;
        QMap<QString, UserInfomation>::iterator it = allUserInfoMap.begin();
        for (; it != allUserInfoMap.end(); it++){
            UserInfomation user = it.value();

            if (QString::compare(user.username, g_get_user_name()) == 0)
                continue;

            names.append(user.username);
            names.append(user.realname);
        }

        UserInfomation user = allUserInfoMap.value(g_get_user_name());

        ChangeUserNickname dialog(user.realname, names, user.objpath , pluginWidget2);
        dialog.exec();

    } else {
        qWarning() << "User Data Error When Change User Type";
    }

    _acquireAllUsersInfo();
}

void UserInfo::showChangeUserLogoDialog(QString username, UtilsForUserinfo *utilsUser)
{
    if (allUserInfoMap.keys().contains(username)) {
        UserInfomation user = allUserInfoMap.value(username);
        ChangeUserLogo *dialog = new ChangeUserLogo(user.realname, user.username, user.iconfile, pluginWidget2);
        dialog->setAttribute(Qt::WA_DeleteOnClose);

        //窗体显示在中间
        int move_x = pluginWidget2->topLevelWidget()->x() + (pluginWidget2->topLevelWidget()->width() - dialog->width())/2;
        int move_y = pluginWidget2->topLevelWidget()->y() + (pluginWidget2->topLevelWidget()->height() - dialog->height())/2;
        move_x = move_x > 0 ? move_x : 0;
        move_y = move_y > 0 ? move_y : 0;
        dialog->move(move_x, move_y);

        qDebug() << user.iconfile << ";" << __LINE__;
        connect(dialog, &ChangeUserLogo::confirmChanged, this, [=](QString filename, bool systemFaces) {

            QString reFilename = renameFaceName(filename, user.username);
            // 系统头像或历史头像不进行重命名，直接拷贝
            if (systemFaces || filename.contains(CUSTOMFACEPATH)) {
                reFilename = filename.split("/").at(filename.split("/").count() - 1);
            }

            qDebug() << "renamed filename = " << reFilename;
            if (g_get_user_name() == user.username) {
                QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.Accounts",
                                                                      user.objpath,
                                                                      "org.freedesktop.Accounts.User",
                                                                      "SetIconFileRename");
                message << filename << reFilename;
                QDBusMessage response = QDBusConnection::systemBus().call(message);
                if (response.type() == QDBusMessage::ErrorMessage){
                    qDebug() << "setIconFileRename failed" << filename;
                }
            } else {
                polkitisShow = true;
                QDBusReply<bool> reply = userSettingDbus->call("setIconFileRename", filename, reFilename, user.objpath);
                if (reply.value()){
                    changeUserFace(filename, user.username, utilsUser);
                }
                polkitisShow = false;
            }
        });

        connect(dialog, &ChangeUserLogo::deleteLogos, this, [=](QStringList filenameList){
            QDBusReply<bool> reply = userSettingDbus->call("delIconFile", filenameList, user.objpath);
        });
        dialog->show();
    } else {
        qWarning() << "User Info Data Error When Change User Pwd";
    }

    _acquireAllUsersInfo();
}

QString UserInfo::renameFaceName(QString fullFilename, QString username)
{
    // 拷贝文件名 原名-用户名-时间戳
    QDateTime time = QDateTime::currentDateTime();
    QString filename = fullFilename.split("/").at(fullFilename.split("/").count()-1);
    QString suffix = "." + filename.split(".").at(filename.split(".").count() - 1);
    filename = filename.left(filename.count() - suffix.count());
    qDebug() << filename;

    return filename + "-" + username + "-" + time.toString("yyyyMMddhhmmss") + suffix;
}

void UserInfo::changeUserFace(QString facefile, QString username, UtilsForUserinfo *utilsUser)
{
    if (utilsUser != nullptr) {
        QPixmap iconfile = makeRoundLogo(facefile, utilsUser->logoBtn->width(), utilsUser->logoBtn->height(), utilsUser->logoBtn->width()/2);
        utilsUser->logoBtn->setIcon(iconfile);
    } else {
        QPixmap iconfile = makeRoundLogo(facefile, currentUserlogoBtn->width(), currentUserlogoBtn->height(), currentUserlogoBtn->width()/2);
        currentUserlogoBtn->setPixmap(iconfile, currentUserlogoBtn->width(), currentUserlogoBtn->height());
    }
}

QPixmap UserInfo::makeRoundLogo(QString logo, int wsize, int hsize, int radius)
{
    QPixmap rectPixmap;
    QPixmap iconcop = QPixmap(logo);
    qreal dpi = currentUserlogoBtn->devicePixelRatioF();
    if (dpi > 1.0) {
        wsize = wsize * dpi;
        hsize = hsize * dpi;
    }
    if (iconcop.width() > iconcop.height()) {
        QPixmap iconPixmap = iconcop.copy((iconcop.width() - iconcop.height())/2, 0, iconcop.height(), iconcop.height());
        // 根据label高度等比例缩放图片
        rectPixmap = iconPixmap.scaledToHeight(hsize, Qt::SmoothTransformation);
    } else {
        QPixmap iconPixmap = iconcop.copy(0, (iconcop.height() - iconcop.width())/2, iconcop.width(), iconcop.width());
        // 根据label宽度等比例缩放图片
        rectPixmap = iconPixmap.scaledToWidth(wsize, Qt::SmoothTransformation);
    }

    if (rectPixmap.isNull()) {
        return QPixmap();
    }
    QPixmap pixmapa(rectPixmap);
    QPixmap pixmap(radius * 2 * dpi, radius * 2 * dpi);
    pixmap.fill(Qt::transparent);
    QPainter painter(&pixmap);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
    QPainterPath path;
    path.addEllipse(0, 0, radius * 2 * dpi, radius * 2 * dpi);
    painter.setClipPath(path);
    painter.drawPixmap(0, 0, radius * 2 * dpi, radius * 2 * dpi, pixmapa);
    pixmap.setDevicePixelRatio(dpi);
    return pixmap;
}

void UserInfo::showChangeUserPwdDialog(QString pName)
{
    if (allUserInfoMap.keys().contains(pName)) {
        ChangeUserPwd *dialog = new ChangeUserPwd(pName, pluginWidget2);
        QStringList objectpaths = sysdispatcher->list_cached_users();
        qint64 uid = 0;
        for (QString objectpath : objectpaths){
            UserInfomation user;
            user = _acquireUserInfo(objectpath);
            if (user.username == pName) {
                uid = user.uid;
            }
        }
        connect(dialog, &ChangeUserPwd::changeOtherUserPwd, this, [=](QString pwd) {
            userSettingDbus->call("changeOtherUserPasswd", pName, pwd);
        });

        connect(dialog, &ChangeUserPwd::changeOtherUserPrompt, this, [=](const QString &prompt) {
            setPasswordTips(uid, prompt);
        });

        dialog->exec();

    } else {
        qWarning() << "User Info Data Error When Change User Pwd";
    }
}

void UserInfo::showChangeUserTypeDialog(QString u)
{
    if (allUserInfoMap.keys().contains(u)){
        UserInfomation user = allUserInfoMap.value(u);

        ChangeUserType *dialog = new ChangeUserType(pluginWidget2);
        dialog->requireUserInfo(user.iconfile, user.realname, user.accounttype, _accountTypeIntToString(user.accounttype));
        connect(dialog, &ChangeUserType::confirmChanged, this, [=](int id){
            QDBusReply<bool> reply = userSettingDbus->call("setAccountType", user.objpath, id);
            if (reply) {
                //告知有用户的类型发生变化
                emit userTypeChanged(u);
            }
        });
        dialog->exec();
    } else {
        qWarning() << "User Data Error When Change User Nickname";
    }

    _acquireAllUsersInfo();
}


QFrame * UserInfo::createHLine(QFrame *f, int len){
    QFrame *line = new QFrame(f);
    if (len == 0){
        line->setMinimumSize(QSize(0, 1));
        line->setMaximumSize(QSize(16777215, 1));
    } else {
        line->setMinimumSize(QSize(len, 1));
        line->setMaximumSize(QSize(len, 1));
    }

    line->setLineWidth(0);
    line->setFrameShape(QFrame::HLine);
    line->setFrameShadow(QFrame::Sunken);
    return line;
}

QFrame * UserInfo::createVLine(QFrame *f, int len){
    QFrame *line = new QFrame(f);
    if (len == 0){
        line->setMinimumSize(QSize(1, 0));
        line->setMaximumSize(QSize(1, 16777215));
    } else {
        line->setMinimumSize(QSize(1, len));
        line->setMaximumSize(QSize(1, len));
    }

    line->setLineWidth(0);
    line->setFrameShape(QFrame::VLine);
    line->setFrameShadow(QFrame::Sunken);
    return line;
}

bool UserInfo::setTextDynamic(QLabel *label, QString string)
{
    bool isOverLength = false;
    QFontMetrics fontMetrics(label->font());
    int labelValueSize = 150;
    int fontSize = fontMetrics.width(string);
    QString str = string;
    qDebug() << "fontSize:" << fontSize << ";labelValueSize:" << labelValueSize;
    if (fontSize > labelValueSize) {
        str = fontMetrics.elidedText(string, Qt::ElideRight, labelValueSize);
        isOverLength = true;
    } else {

    }
    label->setText(str);
    return isOverLength;

}

void UserInfo::fontChangedSlot(const QString &key)
{
    if ("systemFont" == key || "systemFontSize" == key) {
        int fontSize = m_pFontSetting->get("system-font-size").toInt();
        qDebug() << "font size changed : " << fontSize;
        QFont ft;
        ft.setPointSize(fontSize + 2);
        currentNickNameLabel->setFont(ft);
    }
}

void UserInfo::setUserConnect()
{
    const QByteArray id("org.ukui.style");
    m_pFontSetting = new QGSettings(id, QByteArray(), this);
    connect(m_pFontSetting, &QGSettings::changed, this, &UserInfo::fontChangedSlot);

    connect(currentUserlogoBtn, &KLabel::clicked, this, [=]{
        UkccCommon::buriedSettings(name(), currentUserlogoBtn->objectName(), QString("clicked"));

        showChangeUserLogoDialog(QString(g_get_user_name()), nullptr);
    });

    connect(changeCurrentPwdBtn, &QPushButton::clicked, this, [=]{
        UkccCommon::buriedSettings(name(), changeCurrentPwdBtn->objectName(), QString("clicked"));

        showChangeUserPwdDialog(QString(g_get_user_name()));
    });

    connect(changeCurrentTypeBtn, &QPushButton::clicked, [=]{
        UkccCommon::buriedSettings(name(), changeCurrentTypeBtn->objectName(), QString("clicked"));

        showChangeUserTypeDialog(QString(g_get_user_name()));
    });

    connect(changeCurrentGroupsBtn, &QPushButton::clicked, this, [=](bool checked){
        Q_UNUSED(checked)
        UkccCommon::buriedSettings(name(), changeCurrentGroupsBtn->objectName(), QString("clicked"));

        showChangeGroupDialog();

    });
    //自动登录登录
    connect(autoLoginFrame, &SwitchWidget::stateChanged, this, [=](bool checked) {
        UkccCommon::buriedSettings(name(), autoLoginFrame->objectName(), QString("settings"), checked ? "true":"false");

        UserInfomation user = allUserInfoMap.value(g_get_user_name());
        QString autoUser = getAutomaticLogin();
        qDebug() << "Current Auto User:" << autoUser;
        //冲突，弹出提示窗口由用户选择
        if (checked && !autoUser.isEmpty()){
            if (!openAutoLoginMsg(user.username)){
                autoLoginFrame->blockSignals(true);
                autoLoginFrame->setChecked(false);
                autoLoginFrame->blockSignals(false);
                return;
            }
        }
        polkitisShow =true;
        QDBusPendingCall call = userSettingDbus->asyncCall("setAutomaticLogin", user.objpath, checked);
        QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call,this);
        connect(watcher,&QDBusPendingCallWatcher::finished,this, [=](QDBusPendingCallWatcher *call){
            QDBusPendingReply<bool> reply = *call;
            if (!reply.value()){
                autoLoginFrame->blockSignals(true);
                autoLoginFrame->setChecked(!checked);
                autoLoginFrame->blockSignals(false);
            }
            polkitisShow = false;
        });
    });

    //免密登录
    connect(nopwdLoginFrame, &SwitchWidget::stateChanged, this, [=](bool checked) {
        polkitisShow = true;
        UkccCommon::buriedSettings(name(), nopwdLoginFrame->objectName(), QString("settings"), checked ? "true":"false");

        UserInfomation user = allUserInfoMap.value(g_get_user_name());
        QDBusPendingCall call = userSettingDbus->asyncCall("setNoPwdLoginStatus", checked, user.username);
        QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
        connect(watcher,&QDBusPendingCallWatcher::finished,this, [=](QDBusPendingCallWatcher *call){
            QDBusPendingReply<bool> reply = *call;
            if (reply.value() == false) {
                nopwdLoginFrame->blockSignals(true);
                nopwdLoginFrame->setChecked(!checked);
                nopwdLoginFrame->blockSignals(false);
            }
            polkitisShow = false;
        });
    });

    connect(addUserBtn, &AddButton::clicked, [=]{
        UkccCommon::buriedSettings(name(), addUserBtn->objectName(), QString("settings"));

        showCreateUserNewDialog();
    });

    connect(m_pLoginMgrInterface, SIGNAL(UserNew(quint32,QDBusObjectPath)), this, SLOT(onUserNew(quint32,QDBusObjectPath)));
    connect(m_pLoginMgrInterface, SIGNAL(UserRemoved(quint32,QDBusObjectPath)), this, SLOT(onUserRemove(quint32,QDBusObjectPath)));
}

void UserInfo::setUserDBusPropertyConnect(const QString pObjPath){
    QDBusInterface iproperty("org.freedesktop.Accounts",
                             pObjPath,
                             "org.freedesktop.DBus.Properties",
                             QDBusConnection::systemBus());

    iproperty.connection().connect("org.freedesktop.Accounts", pObjPath, "org.freedesktop.DBus.Properties", "PropertiesChanged",
                                    this, SLOT(currentUserPropertyChangedSlot(QString, QMap<QString, QVariant>, QStringList)));

    QDBusInterface ukccProperty("org.ukui.groupmanager",
                                "/org/ukui/groupmanager",
                                "org.ukui.groupmanager.interface",
                                QDBusConnection::systemBus());
    ukccProperty.connection().connect("org.ukui.groupmanager", "/", "org.freedesktop.DBus.Properties", "PropertiesChanged",
                                       this, SLOT(ukccPropertyChangedSlot(QString, QMap<QString, QVariant>, QStringList)));
}

void UserInfo::ukccPropertyChangedSlot(QString property, QMap<QString, QVariant> propertyMap, QStringList propertyList) {
    qDebug() << "------------key:" << propertyMap.keys();
    Q_UNUSED(property);
    Q_UNUSED(propertyList);
    if (propertyMap.keys().contains("NoPwdLoginStatus")) {
        nopwdLoginFrame->blockSignals(true);
        nopwdLoginFrame->setChecked(getNoPwdStatus());
        nopwdLoginFrame->blockSignals(false);
    }
}
void UserInfo::currentUserPropertyChangedSlot(QString property, QMap<QString, QVariant> propertyMap, QStringList propertyList)
{
    Q_UNUSED(property);
    Q_UNUSED(propertyList);
    if (propertyMap.keys().contains("AutomaticLogin") && getuid()){
        bool current = propertyMap.value("AutomaticLogin").toBool();
        if (current != autoLoginFrame->isChecked()){
            autoLoginFrame->blockSignals(true);
            autoLoginFrame->setChecked(current);
            autoLoginFrame->blockSignals(false);
        }
    }

    if (propertyMap.keys().contains("RealName") && getuid()) {
        QString current = propertyMap.value("RealName").toString();
        if (QString::compare(current, currentNickNameLabel->text()) != 0) {
            //更新用户昵称
            currentNickNameLabel->setText(current);
        }
    }

    if (propertyMap.keys().contains("IconFile") && getuid()){
        QString current = propertyMap.value("IconFile").toString();
        QPixmap iconfile = makeRoundLogo(current, currentUserlogoBtn->width(), currentUserlogoBtn->height(), currentUserlogoBtn->width()/2);
        currentUserlogoBtn->setPixmap(iconfile, currentUserlogoBtn->width(), currentUserlogoBtn->height());
    }

    if (propertyMap.keys().contains("AccountType") && getuid()){
        bool current = propertyMap.value("AccountType").toBool();
        //刷新当前用户类型
        QString cType = _accountTypeIntToString(current);
        if (setTextDynamic(currentUserTypeLabel, cType)){
            currentUserTypeLabel->setToolTip(cType);
        }
        showMessageBox();
    }
    //刷新用户数据
    _acquireAllUsersInfo();

}

void UserInfo::showMessageBox()
{
    QMessageBox msg(qApp->activeWindow());
    msg.setIcon(QMessageBox::Warning);

    msg.setText(tr("The account type of “%1” has been modified, will take effect after logout, whether to logout?").arg(currentNickNameLabel->text()));
    msg.addButton(tr("logout later"), QMessageBox::NoRole);
    msg.addButton(tr("logout now"), QMessageBox::ApplyRole);

    int ret = msg.exec();

    if (ret == 1) {
        system("ukui-session-tools --logout");
    }
    return;
}

void UserInfo::newUserCreateDoneSlot(QDBusObjectPath op){
    //刷新用户数据
    _acquireAllUsersInfo();

    UserInfomation user;
    user = _acquireUserInfo(op.path());

    buildItemForUsersAndSetConnect(user);

    //
    emit userTypeChanged(user.username);
}

void UserInfo::existsUserDeleteDoneSlot(QDBusObjectPath op)
{
    //刷新用户数据
    _acquireAllUsersInfo();

    QObjectList list = othersFrame->children();
    foreach (QObject * obj, list) {
        if (obj->objectName() == op.path()){
            QFrame * f = qobject_cast<QFrame *>(obj);
            f->setParent(NULL);
            othersFrame->removeWidget(f);

            f->hide();
        }
    }

    if (othersFrame->layout()->count() == 1) {
        addUserBtn->setRadiusType(UkccFrame::Around);
    } else {
        addUserBtn->setRadiusType(UkccFrame::Bottom);
    }

    emit userTypeChanged("");
}

bool UserInfo::isLastAdmin(QString uname){
    QString cmd = QString("cat /etc/group | grep sudo | awk -F: '{ print $NF}'");
    QString output;

    FILE   *stream;
    char buf[256];

    if ((stream = popen(cmd.toLatin1().data(), "r" )) == NULL){
        return false;
    }

    while(fgets(buf, 256, stream) != NULL){
        output = QString(buf).simplified();
    }

    pclose(stream);

    QStringList users = output.split(",");
    int num = users.length();

    if (users.contains(uname)){
        if (num > 1){
            return false;
        } else {
            return true;
        }
    } else {
        return false;
    }
}

QString UserInfo::getAutomaticLogin() {

    QString filename = "/etc/lightdm/lightdm.conf";
    autoSettings = new QSettings(filename, QSettings::IniFormat);
    autoSettings->beginGroup("SeatDefaults");

    QString autoUser = autoSettings->value("autologin-user", "").toString();

    autoSettings->endGroup();

    return autoUser;
}

bool UserInfo::openAutoLoginMsg(const QString &userName){
    QString autoLoginedUser = this->getAutomaticLogin();
    bool res = true;
    int  ret;
    if (!autoLoginedUser.isEmpty() && userName != autoLoginedUser) {
        QMessageBox msg(this->pluginWidget2);
        msg.setWindowTitle(tr("Hint"));
        msg.setText(tr("The system only allows one user to log in automatically."
                       "After it is turned on, the automatic login of other users will be turned off."
                       "Is it turned on?"));
        QPushButton *confirmBtn = msg.addButton(tr("Trun on"), QMessageBox::AcceptRole);
        QPushButton *cancelBtn =msg.addButton(tr("Close on"), QMessageBox::RejectRole);
        msg.setDefaultButton(confirmBtn);

        ret = msg.exec();

        switch (ret) {
          case QMessageBox::AcceptRole:
              res = true;
              break;
          case QMessageBox::RejectRole:
              res = false;
              break;
        }
    }
    return res;
}


/**3.1****end**************/


QString UserInfo::_accountTypeIntToString(int type){
    QString atype;
    if (type == STANDARDUSER)
        atype = tr("Standard");
    else if (type == ADMINISTRATOR)
        atype = tr("Admin");
    else if (type == ROOT)
        atype = tr("root");

    return atype;
}

void UserInfo::_acquireAllUsersInfo()
{

    mUserName = qgetenv("USER");
    if (mUserName.isEmpty()) {
        mUserName = qgetenv("USERNAME");
    }

    QStringList objectpaths = sysdispatcher->list_cached_users();

    //初始化用户信息QMap
    allUserInfoMap.clear();

    //root
    if (!getuid()){
        UserInfomation root;
        root.username = g_get_user_name();
        root.realname = g_get_real_name();
        root.current = true;
        root.logined = true;
        root.autologin = false;
        root.uid = 0;
        root.accounttype = ADMINISTRATOR;
        root.iconfile = DEFAULTFACE;
        allUserInfoMap.insert(root.username, root);
    }

    for (QString objectpath : objectpaths){
        UserInfomation user;
        user = _acquireUserInfo(objectpath);
        allUserInfoMap.insert(user.username, user);
    }

    if (allUserInfoMap.isEmpty()) {
        ui->currentUserFrame->setVisible(false);
        ui->autoLoginFrame->setVisible(false);
    } else {
        ui->currentUserFrame->setVisible(true);
        ui->autoLoginFrame->setVisible(true);
    }
}

void UserInfo::onUserNew(quint32 uid, QDBusObjectPath opUser)
{
    qDebug() << "logind userNew " << uid << opUser.path();
    QStringList loginedusers = getLoginedUsers();
    foreach (UtilsForUserinfo *utils, utilsUsers) {
        utils->refreshTypeStatus(!isLastAdmin(utils->m_username) && !loginedusers.contains(utils->m_username));
    }
}

void UserInfo::onUserRemove(quint32 uid, QDBusObjectPath opUser)
{
    qDebug() << "logind userRemove " << uid << opUser.path();
    QStringList loginedusers = getLoginedUsers();
    foreach (UtilsForUserinfo *utils, utilsUsers) {
        utils->refreshTypeStatus(!isLastAdmin(utils->m_username) && !loginedusers.contains(utils->m_username));
    }
}

UserInfomation UserInfo::_acquireUserInfo(QString objpath)
{
    UserInfomation user;

    //默认值
    user.current = false;
    user.logined = false;
    user.autologin = false;
    user.objpath = objpath;

    QStringList loginedusers = getLoginedUsers();

    QDBusInterface * iproperty = new QDBusInterface("org.freedesktop.Accounts",
                                            objpath,
                                            "org.freedesktop.DBus.Properties",
                                            QDBusConnection::systemBus());
    QDBusReply<QMap<QString, QVariant> > reply = iproperty->call("GetAll", "org.freedesktop.Accounts.User");
    if (reply.isValid()){

        QMap<QString, QVariant> propertyMap;
        propertyMap = reply.value();
        user.username = propertyMap.find("UserName").value().toString();
        user.realname = propertyMap.find("RealName").value().toString();
        user.accounttype = propertyMap.find("AccountType").value().toInt();

        if (user.realname.isEmpty()){
            user.realname = propertyMap.find("UserName").value().toString();
        }

        if (user.username == QString(g_get_user_name())) {
            user.current = true;
            user.logined = true;
            user.noPwdLogin = getNoPwdStatus();
            m_currentUserType = user.accounttype;
            qDebug() << m_currentUserType << user.username << user.accounttype;
        }

        user.logined = loginedusers.contains(user.username);

        user.iconfile = propertyMap.find("IconFile").value().toString();
        user.passwdtype = propertyMap.find("PasswordMode").value().toInt();
        user.uid = propertyMap.find("Uid").value().toInt();
        user.autologin = propertyMap.find("AutomaticLogin").value().toBool();
        user.objpath = objpath;

        //用户头像文件不存在 使用DEFAULTFACE
        std::string iconpathString = user.iconfile.toStdString();
        const char *iconpath = iconpathString.c_str();
        if (!g_file_test(iconpath, G_FILE_TEST_EXISTS)){
            user.iconfile = DEFAULTFACE;
        }
    }
    else
        qDebug() << "reply failed";

    delete iproperty;
    iproperty = nullptr;

    return user;
}

void UserInfo::readCurrentPwdConf()
{
#ifdef ENABLEPQ
    int ret, status;
    void *auxerror;
    char buf[255];

    pwdconf = pwquality_default_settings();
    if (pwdconf == NULL) {
        enablePwdQuality = false;
        qDebug() << "init pwquality settings failed";
    } else {
        enablePwdQuality = true;
    }

    ret = pwquality_read_config(pwdconf, PWCONF, &auxerror);
    if (ret != 0){
        enablePwdQuality = false;
        qDebug() << "Reading pwquality configuration file failed: " << pwquality_strerror(buf, sizeof(buf), ret, auxerror);
    } else {
        enablePwdQuality = true;
    }

    if (PasswdCheckUtil::getCurrentPamState()){
        enablePwdQuality = true;
    } else {
        enablePwdQuality = false;
    }

    if (enablePwdQuality){
        int minLen;
        status = pwquality_get_int_value(pwdconf, PWQ_SETTING_MIN_LENGTH, &minLen);
        if (!status && minLen > 0){
            pwdOption.min_length = minLen;
        }

        int digCredit;
        status = pwquality_get_int_value(pwdconf, PWQ_SETTING_DIG_CREDIT, &digCredit);
        if (!status && digCredit > 0){
            pwdOption.dig_credit = digCredit;
        }

        int upCredit;
        status = pwquality_get_int_value(pwdconf, PWQ_SETTING_UP_CREDIT, &upCredit);
        if (!status && upCredit > 0){
            pwdOption.up_credit = upCredit;
        }

        int lowCredit;
        status = pwquality_get_int_value(pwdconf, PWQ_SETTING_LOW_CREDIT, &lowCredit);
        if (!status && lowCredit > 0){
            pwdOption.low_credit = lowCredit;
        }

        int othCredit;
        status = pwquality_get_int_value(pwdconf, PWQ_SETTING_OTH_CREDIT, &othCredit);
        if (!status && othCredit > 0){
            pwdOption.oth_credit = othCredit;
        }

        int minClass;
        status = pwquality_get_int_value(pwdconf, PWQ_SETTING_MIN_CLASS, &minClass);
        if (!status && minClass > 0){
            pwdOption.min_class = minClass;
        }

        int maxRepeat;
        status = pwquality_get_int_value(pwdconf, PWQ_SETTING_MAX_REPEAT, &maxRepeat);
        if (!status && maxRepeat > 0){
            pwdOption.max_repeat = maxRepeat;
        }

        int maxClassRepeat;
        status = pwquality_get_int_value(pwdconf, PWQ_SETTING_MAX_CLASS_REPEAT, &maxClassRepeat);
        if (!status && maxClassRepeat > 0){
            pwdOption.max_class_repeat = maxClassRepeat;
        }

        int maxSequence;
        status = pwquality_get_int_value(pwdconf, PWQ_SETTING_MAX_SEQUENCE, &maxSequence);
        if (!status && maxSequence > 0){
            pwdOption.max_class_repeat = maxSequence;
        }
    }

    qDebug() << "pwquality:" << pwdOption.min_length << pwdOption.min_class << pwdOption.dig_credit << pwdOption.low_credit << pwdOption.up_credit;
#endif
}

QStringList UserInfo::getLoginedUsers()
{
    m_loginedUser.clear();
    qRegisterMetaType<LoginedUsers>("LoginedUsers");
    qDBusRegisterMetaType<LoginedUsers>();
    QDBusInterface loginInterface("org.freedesktop.login1",
                                  "/org/freedesktop/login1",
                                  "org.freedesktop.login1.Manager",
                                  QDBusConnection::systemBus());

    if (loginInterface.isValid()) {
//        qDebug() << "create interface sucess";
    }

    QDBusMessage result = loginInterface.call("ListUsers");
    QList<QVariant> outArgs = result.arguments();
    QVariant first = outArgs.at(0);
    QDBusArgument dbvFirst = first.value<QDBusArgument>();
    QVariant vFirst = dbvFirst.asVariant();
    const QDBusArgument &dbusArgs = vFirst.value<QDBusArgument>();

    QVector<LoginedUsers> loginedUsers;

    dbusArgs.beginArray();
    while (!dbusArgs.atEnd()) {
        LoginedUsers user;
        dbusArgs >> user;
        loginedUsers.push_back(user);
    }
    dbusArgs.endArray();

    for (LoginedUsers user : loginedUsers) {

        QDBusInterface userPertyInterface("org.freedesktop.login1",
                                          user.objpath.path(),
                                          "org.freedesktop.DBus.Properties",
                                          QDBusConnection::systemBus());

        QDBusReply<QVariant> reply = userPertyInterface.call("Get", "org.freedesktop.login1.User", "State");
        if (reply.isValid()) {
            QString status = reply.value().toString();
            if ("closing" != status) {
                m_loginedUser.append(user.userName);
            }
        }
    }
    return m_loginedUser;
}

void UserInfo::showChangeGroupDialog()
{
    changeUserGroup *dialog = new changeUserGroup(pluginWidget2);
    connect(dialog, &changeUserGroup::showDialog, this, [=](){
        qDebug() << "user type = " << m_currentUserType << __FUNCTION__;
        if (m_currentUserType == STANDARDUSER) {
            dialog->setEnableStatus(false);
        }
        dialog->exec();
    });
}

bool UserInfo::eventFilter(QObject *watched, QEvent *event)
{
    if (polkitisShow){
        if (event->type() == QEvent::MouseButtonDblClick || event->type() == QEvent::MouseButtonPress
                || event->type() == QEvent::MouseButtonRelease) {
            return true;
        }
    }

    if (event->type() == QEvent::MouseButtonPress){
        QMouseEvent * mouseEvent = static_cast<QMouseEvent *>(event);
        if (mouseEvent->button() == Qt::LeftButton ){
            if ((watched == currentNickNameChangeLabel && currentNickNameChangeLabel->isEnabled())
                    || (watched == currentNickNameLabel && currentNickNameLabel->isEnabled())){
                UkccCommon::buriedSettings(name(), currentNickNameChangeLabel->objectName(), QString("settings"));
                showChangeUserNicknameDialog();
            }
        }
    }

    return QObject::eventFilter(watched, event);
}

bool UserInfo::getNoPwdStatus() {
    // 获取当前用户免密登录属性
    // 获取免密登录状态
    QDBusReply<QString> noPwdres;
    if (!userSettingDbus->isValid()) {
        qDebug() << "Create dbus error: " << QDBusConnection::systemBus().lastError();
        return false;
    }

    noPwdres  = userSettingDbus->call("getNoPwdLoginStatus");
    if (!noPwdres.isValid() || noPwdres.value().isEmpty()) {
        qDebug() << "noPwdres.error() = " << noPwdres.error() << "; noPwdres.value() = " << noPwdres.value();
        return false;
    }

    QStringList tmp = noPwdres.value().split(":", QString::SkipEmptyParts);

    QString noPasswdUsers = tmp.at(tmp.count()-1);
    QStringList noPasswdUsersList = noPasswdUsers.split(",", QString::SkipEmptyParts);
    foreach (QString noPasswdUser, noPasswdUsersList) {
        noPasswdUser.remove(QChar('\n'), Qt::CaseInsensitive);
        qDebug() << "nopasswduser:" << noPasswdUser;
        if (noPasswdUser.compare(mUserName) == 0) {
            return true;
        }
    }

    return false;

}

void UserInfo::fontSizeChange(UserInfomation user, UtilsForUserinfo * utils)
{
    const QByteArray styleID(STYLE_FONT_SCHEMA);
    QGSettings *stylesettings = new QGSettings(styleID, QByteArray(), this);
    connect(stylesettings, &QGSettings::changed, this, [=](const QString &key){
        if (key == "systemFontSize" || key == "systemFont") {
            if (utils == nullptr) {
                QMap<QString, UserInfomation>::iterator it = allUserInfoMap.begin();
                for (; it != allUserInfoMap.end(); it++){
                    UserInfomation currentUser = it.value();
                    //当前用户
                    if (currentUser.username == QString(g_get_user_name())){
                        //设置用户昵称
                        currentNickNameLabel->setText(currentUser.realname);

                        //用户类型
                        QString cType = _accountTypeIntToString(currentUser.accounttype);
                        if (setTextDynamic(currentUserTypeLabel, cType)){
                            currentUserTypeLabel->setToolTip(cType);
                        }
                    }
                }
            } else {
                utils->refreshUserNickname(user.realname);
                utils->refreshUserType(user.accounttype);
            }
        }
    });

}
