ukui-screensaver/0000755000175000017500000000000014205076742013000 5ustar fengfengukui-screensaver/BiometricAuth/0000755000175000017500000000000014205074760015535 5ustar fengfengukui-screensaver/BiometricAuth/biometricdeviceinfo.h0000644000175000017500000001002314205074704021711 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef BIOMETRICDEVICEINFO_H #define BIOMETRICDEVICEINFO_H #include #include #define BIOMETRIC_DBUS_SERVICE "org.ukui.Biometric" #define BIOMETRIC_DBUS_PATH "/org/ukui/Biometric" #define BIOMETRIC_DBUS_INTERFACE "org.ukui.Biometric" #define UKUI_BIOMETRIC_IMAGES_PATH "/usr/share/ukui-biometric/images/" #define UKUI_BIOMETRIC_CONFIG_PATH ".biometric_auth/ukui_biometric.conf" #define UKUI_BIOMETRIC_SYS_CONFIG_PATH "/etc/biometric-auth/ukui-biometric.conf" #define BIOMETRIC_PAM_DOUBLE "BIOMETRIC_PAM_DOUBLE" #define BIOMETRIC_PAM "BIOMETRIC_PAM" #define BIOMETRIC_IGNORE "BIOMETRIC_IGNORE" #define BIOMETRIC_SUCCESS "BIOMETRIC_SUCCESS" /** * @brief 设备类型 */ class DeviceType : public QObject { Q_OBJECT public: DeviceType(); enum Type { FingerPrint, FingerVein, Iris, Face, VoicePrint, __MAX_NR_TYPES }; Q_ENUM(Type) /** * @brief 获取设备类型的字符串表现形式 * @param deviceType 设备类型 * @return */ static QString getDeviceType(int deviceType); /** * @brief 获取设备类型的国际化字符串 * @param deviceType 设备类型 * @return */ static QString getDeviceType_tr(int deviceType); }; /** * @brief StatusChanged D-Bus 信号触发时的状态变化类型 */ enum StatusType { STATUS_DEVICE, STATUS_OPERATION, STATUS_NOTIFY }; /** * @brief 识别、终止操作等DBus调用的结果,即返回值里的 result */ enum DBusResult { DBUS_RESULT_SUCCESS = 0, DBUS_RESULT_NOTMATCH = -1, DBUS_RESULT_ERROR = -2, DBUS_RESULT_DEVICEBUSY = -3, DBUS_RESULT_NOSUCHDEVICE = -4, DBUS_RESULT_PERMISSIONDENIED = -5 }; /** * @brief 识别操作(Identify)的ops状态 */ enum IdentifyOpsStatus { IDENTIFY_MATCH = 400, IDENTIFY_NOTMATCH, IDENTIFY_ERROR, IDENTIFY_STOPBYUSER, IDENTIFY_TIMEOUT, IDENTIFY_MAX }; /** * @brief 设备的信息 */ struct DeviceInfo { int id; QString shortName; QString fullName; int driverEnable; int deviceNum; int deviceType; int storageType; int eigType; int verifyType; int identifyType; int busType; int deviceStatus; int OpsStatus; }; class QDBusArgument; QDBusArgument &operator <<(QDBusArgument &arg, const DeviceInfo &deviceInfo); const QDBusArgument &operator >>(const QDBusArgument &arg, DeviceInfo &deviceInfo); void registerMetaType(); typedef std::shared_ptr DeviceInfoPtr; typedef QList DeviceList; typedef QMap DeviceMap; QDebug operator <<(QDebug stream, const DeviceInfo &deviceInfo); Q_DECLARE_METATYPE(DeviceInfo) /** * @brief 获取默认设备 * @return */ QString GetDefaultDevice(const QString &userName); /** * @brief 获取失败后自动重新开始的最大次数 * @param userName * @return */ int GetMaxFailedAutoRetry(const QString &userName); /** * @brief 获取超时后自动重新开始的最大次数 * @param userName * @return */ int GetMaxTimeoutAutoRetry(const QString &userName); bool GetHiddenSwitchButton(); int GetFailedTimes(); #endif // BIOMETRICDEVICEINFO_H ukui-screensaver/BiometricAuth/biometricauthwidget.h0000644000175000017500000000507314205074760021756 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef BIOMETRICAUTHWIDGET_H #define BIOMETRICAUTHWIDGET_H #include #include "biometricproxy.h" class QLabel; //class QDBusPendingCallWatcher; //class BiometricProxy; //class DeviceIdentityPtr; class BiometricAuthWidget : public QWidget { Q_OBJECT public: explicit BiometricAuthWidget(BiometricProxy *proxy, QWidget *parent = 0); /** * @brief 进行生物识别认证 * @param deviceInfo 使用的设备 * @param uid 待认证的用户id */ void startAuth(DeviceInfoPtr device, int uid); /** * @brief 终止生物识别认证 */ void stopAuth(); bool isAuthenticating() { return isInAuth; } void setMinImage(float val); protected: void resizeEvent(QResizeEvent *event); Q_SIGNALS: /** * @brief 认证完成 * @param result 认证结果 */ void authComplete(bool result); private Q_SLOTS: void onIdentifyComplete(QDBusPendingCallWatcher *watcher); void onStatusChanged(int drvid, int status); void onFrameWritten(int drvid); void onMoviePixmapUpdate(); void startAuth_(); private: void initUI(); void updateImage(int type = 0); void setImage(const QString &path); bool getAuthDouble(); private: QLabel *lblNotify; QLabel *lblDevice; QLabel *lblImage; BiometricProxy *proxy; int uid; QString userName; DeviceInfoPtr device; bool isInAuth; QTimer *movieTimer; int failedCount; int timeoutCount; bool beStopped; QTimer *retrytimer; bool usebind; int fd = -1; int dup_fd = -1; }; #endif // BIOMETRICAUTHWIDGET_H ukui-screensaver/BiometricAuth/BiometricAuth.pro0000644000175000017500000000216014205074704021013 0ustar fengfeng#------------------------------------------------- # # Project created by QtCreator 2018-12-06T09:17:41 # #------------------------------------------------- QT += core gui dbus greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = BiometricAuth TEMPLATE = app # The following define makes your compiler emit warnings if you use # any feature of Qt which has been marked as deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS # You can also make your code fail to compile if you use deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 SOURCES += \ main.cpp \ biometricauthwidget.cpp \ biometricproxy.cpp \ biometricdeviceswidget.cpp HEADERS += \ biometricauthwidget.h \ biometricproxy.h \ biometricdeviceswidget.h FORMS += ukui-screensaver/BiometricAuth/biometricauthwidget.cpp0000644000175000017500000002216114205074760022306 0ustar fengfeng/** * Copyright (C) 2018 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, 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 "biometricauthwidget.h" #include #include #include #include #include #include #include #include #include #include "giodbus.h" BiometricAuthWidget::BiometricAuthWidget(BiometricProxy *proxy, QWidget *parent) : QWidget(parent), proxy(proxy), isInAuth(false), movieTimer(nullptr), failedCount(0), timeoutCount(0), beStopped(false), retrytimer(nullptr), usebind(false) { usebind = getAuthDouble(); initUI(); resize(400, 260); if(this->proxy) { connect(this->proxy, &BiometricProxy::StatusChanged, this, &BiometricAuthWidget::onStatusChanged); connect(this->proxy, &BiometricProxy::FrameWritten, this, &BiometricAuthWidget::onFrameWritten); } } void BiometricAuthWidget::initUI() { //显示提示信息 lblNotify = new QLabel(this); lblNotify->setWordWrap(true); lblNotify->setAlignment(Qt::AlignHCenter | Qt::AlignBottom); //显示当前设备 lblDevice = new QLabel(this); lblDevice->setWordWrap(true); lblDevice->setAlignment(Qt::AlignCenter); //显示图片 lblImage = new QLabel(this); lblImage->setFixedSize(100, 100); } void BiometricAuthWidget::resizeEvent(QResizeEvent */*event*/) { lblNotify->setGeometry(0, 0, width(), 45); lblDevice->setGeometry(0, lblNotify->geometry().bottom()+5, width(), 30); lblImage->setGeometry((width() - lblImage->width()) / 2, lblDevice->geometry().bottom() + 10, lblImage->width(), lblImage->height()); //qDebug() } void BiometricAuthWidget::startAuth(DeviceInfoPtr device, int uid) { if(!proxy) { qWarning() << "BiometricProxy doesn't exist."; return; } if(isInAuth) { qDebug() << "Identification is currently under way, stop it"; stopAuth(); } this->device = device; this->uid = uid; this->userName = getpwuid(uid)->pw_name; this->failedCount = 0; this->timeoutCount = 0; this->beStopped = false; proxy->StopOps(device->id); startAuth_(); if(device->deviceType != DeviceType::Type::Face){ updateImage(1); } } void BiometricAuthWidget::startAuth_() { lblDevice->setText(tr("Current device: ") + device->shortName); //qDebug().noquote() << QString("Identify:[drvid: %1, uid: %2]").arg(1).arg(2); isInAuth = true; dup_fd = -1; QDBusPendingCall call = proxy->Identify(device->id, uid); QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this); connect(watcher, &QDBusPendingCallWatcher::finished, this, &BiometricAuthWidget::onIdentifyComplete); } void BiometricAuthWidget::stopAuth() { beStopped = true; if(!isInAuth) { return; } proxy->StopOps(device->id); if(retrytimer&&retrytimer->isActive()){ retrytimer->stop(); delete retrytimer; retrytimer = nullptr; } isInAuth = false; updateImage(0); } void BiometricAuthWidget::onIdentifyComplete(QDBusPendingCallWatcher *watcher) { QDBusPendingReply reply = *watcher; if(reply.isError()) { qWarning() << "Identify error: " << reply.error().message(); Q_EMIT authComplete(false); updateImage(0); return; } int result = reply.argumentAt(0).toInt(); int authUid = reply.argumentAt(1).toInt(); // 特征识别成功,而且用户id匹配 if(result == DBUS_RESULT_SUCCESS && authUid == uid) { qDebug() << "Identify success"; Q_EMIT authComplete(true); } // 特征识别不匹配 else if(result == DBUS_RESULT_NOTMATCH) { if(usebind){ Q_EMIT authComplete(false); return; } qDebug() << "Identify failed"; failedCount++; if(failedCount >= GetMaxFailedAutoRetry(userName)) { Q_EMIT authComplete(false); } else { lblNotify->setText(tr("Identify failed, Please retry.")); if(!beStopped){ // QTimer::singleShot(1000, this, &BiometricAuthWidget::startAuth_); if(!retrytimer){ retrytimer = new QTimer(this); retrytimer->setSingleShot(true); connect(retrytimer, &QTimer::timeout, this, &BiometricAuthWidget::startAuth_); } retrytimer->start(1000); } } } //识别发生错误 else if(result == DBUS_RESULT_ERROR) { if(usebind){ Q_EMIT authComplete(false); return; } StatusReslut ret = proxy->UpdateStatus(device->id); //识别操作超时 if(ret.result == 0 && ret.opsStatus == IDENTIFY_TIMEOUT) { timeoutCount++; if(timeoutCount >= GetMaxTimeoutAutoRetry(userName)) { Q_EMIT authComplete(false); } else { QTimer::singleShot(1000, [&]{ if(!beStopped) { startAuth_(); } }); } }else{ Q_EMIT authComplete(false); } }else{ Q_EMIT authComplete(false); } updateImage(0); } void BiometricAuthWidget::onFrameWritten(int drvid) { if(dup_fd == -1){ dup_fd = get_server_gvariant_stdout(drvid); } if(dup_fd <= 0) return ; cv::Mat img; lseek(dup_fd, 0, SEEK_SET); char base64_bufferData[1024*1024]; int rc = read(dup_fd, base64_bufferData, 1024*1024); printf("rc = %d\n", rc); cv::Mat mat2(1, sizeof(base64_bufferData), CV_8U, base64_bufferData); img = cv::imdecode(mat2, cv::IMREAD_COLOR); cv::cvtColor(img,img,cv::COLOR_BGR2RGB); QImage srcQImage = QImage((uchar*)(img.data), img.cols, img.rows, QImage::Format_RGB888); lblImage->setFixedSize(160,160); lblImage->setGeometry((width() - lblImage->width()) / 2, lblDevice->geometry().bottom() + 10, lblImage->width(), lblImage->height()); lblImage->setPixmap(QPixmap::fromImage(srcQImage).scaled(lblImage->size())); } void BiometricAuthWidget::onStatusChanged(int drvid, int status) { if(!isInAuth) { return; } if(drvid != device->id) { return; } // 显示来自服务的提示信息 if(status == STATUS_NOTIFY) { QString notifyMsg = proxy->GetNotifyMesg(drvid); lblNotify->setText(notifyMsg); } } static int count = 0; void BiometricAuthWidget::updateImage(int type) { if(device->deviceType == DeviceType::Type::Face) return ; if(type == 0) { if(movieTimer && movieTimer->isActive()) { movieTimer->stop(); } QString imagePath = QString(UKUI_BIOMETRIC_IMAGES_PATH "%1/01.png") .arg(DeviceType::getDeviceType(device->deviceType)); setImage(imagePath); } else { if(!movieTimer) { movieTimer = new QTimer(this); movieTimer->setInterval(100); connect(movieTimer, &QTimer::timeout, this, &BiometricAuthWidget::onMoviePixmapUpdate); } count = 0; movieTimer->start(); } } void BiometricAuthWidget::onMoviePixmapUpdate() { if(count >= 18) { count = 0; } count++; QString fileName = (count < 10 ? "0" : "") + QString::number(count); QString imagePath = QString(UKUI_BIOMETRIC_IMAGES_PATH "%1/%2.png") .arg(DeviceType::getDeviceType(device->deviceType)) .arg(fileName); setImage(imagePath); } void BiometricAuthWidget::setImage(const QString &path) { QPixmap image(path); image = image.scaled(lblImage->width(), lblImage->height(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); lblImage->setPixmap(image); } bool BiometricAuthWidget::getAuthDouble() { QSettings settings("/etc/biometric-auth/ukui-biometric.conf", QSettings::IniFormat); bool distribId = settings.value("DoubleAuth").toBool(); return distribId; } void BiometricAuthWidget::setMinImage(float val) { resize(400,100+100*val); lblImage->setFixedSize(100*val, 100*val); } ukui-screensaver/BiometricAuth/biometricdeviceswidget.h0000644000175000017500000000452314205074704022434 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef BIOMETRICDEVICESWIDGET_H #define BIOMETRICDEVICESWIDGET_H #include #include "biometricproxy.h" class QLabel; class QPushButton; class QComboBox; class BiometricDevicesWidget : public QWidget { Q_OBJECT public: explicit BiometricDevicesWidget(BiometricProxy *proxy, int uid,QWidget *parent = nullptr); void setCurrentDevice(int drvid); void setCurrentDevice(const QString &deviceName); void setCurrentDevice(const DeviceInfoPtr &pDeviceInfo); DeviceInfoPtr findDeviceById(int drvid); DeviceInfoPtr findDeviceByName(const QString &name); bool deviceExists(int drvid); bool deviceExists(const QString &deviceName); void setUser(int user); protected: void resizeEvent(QResizeEvent *event); Q_SIGNALS: void deviceChanged(const DeviceInfoPtr &pDeviceInfo); void deviceCountChanged(int newCount); public Q_SLOTS: void onOKButtonClicked(); private Q_SLOTS: void onCmbDeviceTypeCurrentIndexChanged(int index); void onUSBDeviceHotPlug(int drvid, int action, int devNum); private: void initUI(); void updateDevice(); private: typedef QMap QButtonMap; QLabel *lblPrompt; QLabel *lblDeviceType; QLabel *lblDeviceName; QComboBox *cmbDeviceType; QComboBox *cmbDeviceName; QPushButton *btnOK; QPushButton *btnCancel; BiometricProxy *proxy; DeviceMap deviceMap; DeviceInfoPtr currentDevice; int m_uid; }; #endif // BIOMETRICDEVICESWIDGET_H ukui-screensaver/BiometricAuth/biometricdeviceinfo.cpp0000644000175000017500000001233014205074704022247 0ustar fengfeng/** * Copyright (C) 2018 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, 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 "biometricdeviceinfo.h" #include #include //#include QString DeviceType::getDeviceType(int deviceType) { if(deviceType >= __MAX_NR_TYPES) { return ""; } QMetaEnum meta = QMetaEnum::fromType(); const char *typeString = meta.valueToKey(deviceType); return QString(typeString); } QString DeviceType::getDeviceType_tr(int deviceType) { switch(deviceType) { case FingerPrint: return tr("FingerPrint"); case FingerVein: return tr("FingerVein"); case Iris: return tr("Iris"); case Face: return tr("Face"); case VoicePrint: return tr("VoicePrint"); default: return ""; } } QDebug operator <<(QDebug stream, const DeviceInfo &deviceInfo) { stream << "[" << deviceInfo.id << deviceInfo.shortName << deviceInfo.fullName << deviceInfo.deviceType << deviceInfo.driverEnable << deviceInfo.deviceNum << "]"; return stream; } QDBusArgument &operator <<(QDBusArgument &arg, const DeviceInfo &deviceInfo) { arg.beginStructure(); arg << deviceInfo.id << deviceInfo.shortName << deviceInfo.fullName << deviceInfo.driverEnable << deviceInfo.deviceNum << deviceInfo.deviceType << deviceInfo.storageType << deviceInfo.eigType << deviceInfo.verifyType << deviceInfo.identifyType << deviceInfo.busType << deviceInfo.deviceStatus << deviceInfo.OpsStatus; arg.endStructure(); return arg; } const QDBusArgument &operator >>(const QDBusArgument &arg, DeviceInfo &deviceInfo) { arg.beginStructure(); arg >> deviceInfo.id >> deviceInfo.shortName >> deviceInfo.fullName >> deviceInfo.driverEnable >> deviceInfo.deviceNum >> deviceInfo.deviceType >> deviceInfo.storageType >> deviceInfo.eigType >> deviceInfo.verifyType >> deviceInfo.identifyType >> deviceInfo.busType >> deviceInfo.deviceStatus >> deviceInfo.OpsStatus; arg.endStructure(); return arg; } void registerMetaType() { qRegisterMetaType("DeviceInfo"); qDBusRegisterMetaType(); } QString GetDefaultDevice(const QString &userName) { //QString configPath = QString("/home/%1/" UKUI_BIOMETRIC_CONFIG_PATH).arg(userName); QString configPath = QDir::homePath() + "/" + UKUI_BIOMETRIC_CONFIG_PATH; QSettings settings(configPath, QSettings::IniFormat); qDebug() << "configure path: " << settings.fileName(); QString defaultDevice = settings.value("DefaultDevice").toString(); if(defaultDevice.isEmpty()) { QSettings sysSettings(UKUI_BIOMETRIC_SYS_CONFIG_PATH, QSettings::IniFormat); defaultDevice = sysSettings.value("DefaultDevice").toString(); } return defaultDevice; } static int getValueFromSettings(const QString &userName, const QString &key, int defaultValue = 3) { //从家目录下的配置文件中获取 //QString configPath = QString("/home/%1/" UKUI_BIOMETRIC_CONFIG_PATH).arg(userName); QString configPath = QDir::homePath() + "/" + UKUI_BIOMETRIC_CONFIG_PATH; QSettings settings(configPath, QSettings::IniFormat); QString valueStr = settings.value(key).toString(); //如果没有获取到,则从系统配置文件中获取 if(valueStr.isEmpty()) { QSettings sysSettings(UKUI_BIOMETRIC_SYS_CONFIG_PATH, QSettings::IniFormat); valueStr = sysSettings.value(key).toString(); } bool ok; int value = valueStr.toInt(&ok); if( (value == 0 && !ok) || valueStr.isEmpty() ) { value = defaultValue; } return value; } bool GetHiddenSwitchButton() { QSettings sysSettings(UKUI_BIOMETRIC_SYS_CONFIG_PATH, QSettings::IniFormat); if(sysSettings.contains("HiddenSwitchButton")) return sysSettings.value("HiddenSwitchButton").toBool(); else return false; } int GetFailedTimes() { QSettings sysSettings(UKUI_BIOMETRIC_SYS_CONFIG_PATH, QSettings::IniFormat); if(sysSettings.contains("MaxFailedTimes")) return sysSettings.value("MaxFailedTimes").toInt(); else return 3; } int GetMaxFailedAutoRetry(const QString &userName) { return getValueFromSettings(userName, "MaxFailedAutoRetry"); } int GetMaxTimeoutAutoRetry(const QString &userName) { return getValueFromSettings(userName, "MaxTimeoutAutoRetry"); } ukui-screensaver/BiometricAuth/giodbus.h0000644000175000017500000000154714205074760017351 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef GIODBUS_H #define GIODBUS_H int get_server_gvariant_stdout(int drvid); #endif ukui-screensaver/BiometricAuth/giodbus.cpp0000644000175000017500000000561614205074760017705 0ustar fengfeng/** * Copyright (C) 2018 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, 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 "giodbus.h" #include #include #include int get_server_gvariant_stdout (int drvid) { GDBusMessage *method_call_message; GDBusMessage *method_reply_message; GUnixFDList *fd_list; GError **error = NULL; gint fd,dup_fd; const gchar * response; fd = -1; dup_fd = -1; method_call_message = NULL; method_reply_message = NULL; GDBusConnection *con = g_bus_get_sync(G_BUS_TYPE_SYSTEM,NULL,NULL); method_call_message = g_dbus_message_new_method_call ("org.ukui.Biometric", "/org/ukui/Biometric", "org.ukui.Biometric", "GetFrameFd"); g_dbus_message_set_body (method_call_message, g_variant_new ("(i)", drvid)); method_reply_message = g_dbus_connection_send_message_with_reply_sync (con, method_call_message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, /* out_serial */ NULL, /* cancellable */ error); if (method_reply_message == NULL) goto out; if (g_dbus_message_get_message_type (method_reply_message) == G_DBUS_MESSAGE_TYPE_ERROR) { g_dbus_message_to_gerror (method_reply_message, error); goto out; } g_print("%s",g_dbus_message_print(method_reply_message,0)); fd_list = g_dbus_message_get_unix_fd_list(method_reply_message); fd = g_unix_fd_list_get(fd_list,0,error); g_print("get fd : %d\n", fd); dup_fd = dup(fd); g_print("dup fd : %d\n", dup_fd); out: g_object_unref (method_call_message); g_object_unref (method_reply_message); return dup_fd; } ukui-screensaver/BiometricAuth/biometricdeviceswidget.cpp0000644000175000017500000002112614205074704022765 0ustar fengfeng/** * Copyright (C) 2018 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, 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 "biometricdeviceswidget.h" #include #include #include #include #include #include BiometricDevicesWidget::BiometricDevicesWidget(BiometricProxy *proxy, int uid,QWidget *parent) : QWidget(parent), proxy(proxy), m_uid(uid) { initUI(); if(proxy && proxy->isValid()) { connect(proxy, &BiometricProxy::USBDeviceHotPlug, this, &BiometricDevicesWidget::onUSBDeviceHotPlug); updateDevice(); } resize(500, 500); } void BiometricDevicesWidget::initUI() { lblPrompt = new QLabel(this); lblPrompt->setObjectName(QStringLiteral("lblBioetricDevicesPrompt")); lblPrompt->setText(tr("Please select the biometric device")); lblPrompt->setAlignment(Qt::AlignHCenter); lblDeviceType = new QLabel(this); lblDeviceType->setObjectName(QStringLiteral("lblDeviceType")); lblDeviceType->setText(tr("Device type:")); lblDeviceType->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); QStyledItemDelegate* itemDelegate = new QStyledItemDelegate(); cmbDeviceType = new QComboBox(this); cmbDeviceType->view()->parentWidget()->setWindowFlags(Qt::Popup|Qt::FramelessWindowHint); cmbDeviceType->view()->parentWidget()->setAttribute(Qt::WA_TranslucentBackground); cmbDeviceType->setObjectName(QStringLiteral("cmbDeviceType")); cmbDeviceType->setMaxVisibleItems(5); cmbDeviceType->setItemDelegate(itemDelegate); connect(cmbDeviceType, SIGNAL(currentIndexChanged(int)), this, SLOT(onCmbDeviceTypeCurrentIndexChanged(int))); lblDeviceName = new QLabel(this); lblDeviceName->setObjectName(QStringLiteral("lblDeviceName")); lblDeviceName->setText(tr("Device name:")); lblDeviceName->setAlignment(Qt::AlignLeft | Qt::AlignVCenter); cmbDeviceName = new QComboBox(this); cmbDeviceName->view()->parentWidget()->setWindowFlags(Qt::Popup|Qt::FramelessWindowHint); cmbDeviceName->view()->parentWidget()->setAttribute(Qt::WA_TranslucentBackground); cmbDeviceName->setObjectName(QStringLiteral("cmbDeviceName")); cmbDeviceName->setMaxVisibleItems(5); cmbDeviceName->setItemDelegate(itemDelegate); btnOK = new QPushButton(tr("OK"), this); btnOK->setObjectName(QStringLiteral("OKButton")); btnOK->setCursor(Qt::PointingHandCursor); connect(btnOK, &QPushButton::clicked, this, &BiometricDevicesWidget::onOKButtonClicked); } void BiometricDevicesWidget::setUser(int user) { m_uid = user; } void BiometricDevicesWidget::resizeEvent(QResizeEvent */*event*/) { lblPrompt->setGeometry(0, 0, width(), 40); lblDeviceType->setGeometry(100, lblPrompt->geometry().bottom() + 40, 120, 20); cmbDeviceType->setGeometry(100, lblDeviceType->geometry().bottom() + 15, 300, 40); lblDeviceName->setGeometry(100, cmbDeviceType->geometry().bottom() + 80, 120, 20); cmbDeviceName->setGeometry(100, lblDeviceName->geometry().bottom() + 15, 300, 40); btnOK->setGeometry(100, cmbDeviceName->geometry().bottom() + 80, 140, 38); } void BiometricDevicesWidget::updateDevice() { deviceMap.clear(); DeviceList deviceList = proxy->GetDevList(); for(auto pDeviceInfo : deviceList) { qDebug() << *pDeviceInfo; if(proxy->GetUserDevFeatureCount(m_uid,pDeviceInfo->id) > 0) deviceMap[pDeviceInfo->deviceType].push_back(pDeviceInfo); } cmbDeviceType->clear(); for(int type : deviceMap.keys()) { QString iconPath = QString(UKUI_BIOMETRIC_IMAGES_PATH"icon/%1.png") .arg(DeviceType::getDeviceType(type)); qDebug() << iconPath; cmbDeviceType->addItem(QIcon(iconPath), DeviceType::getDeviceType_tr(type), type); } if(deviceMap.size() > 0) { int index = deviceMap.keys().at(0); setCurrentDevice(deviceMap[index].at(0)); } } void BiometricDevicesWidget::setCurrentDevice(int drvid) { DeviceInfoPtr pDeviceInfo = findDeviceById(drvid); if(pDeviceInfo) { setCurrentDevice(pDeviceInfo); } } void BiometricDevicesWidget::setCurrentDevice(const QString &deviceName) { DeviceInfoPtr pDeviceInfo = findDeviceByName(deviceName); if(pDeviceInfo) { setCurrentDevice(pDeviceInfo); } } void BiometricDevicesWidget::setCurrentDevice(const DeviceInfoPtr &pDeviceInfo) { this->currentDevice = pDeviceInfo; cmbDeviceType->setCurrentText(DeviceType::getDeviceType_tr(pDeviceInfo->deviceType)); cmbDeviceName->setCurrentText(pDeviceInfo->shortName); } bool BiometricDevicesWidget::deviceExists(int drvid) { return (findDeviceById(drvid) != nullptr); } bool BiometricDevicesWidget::deviceExists(const QString &deviceName) { return (findDeviceByName(deviceName) != nullptr); } DeviceInfoPtr BiometricDevicesWidget::findDeviceById(int drvid) { for(int type : deviceMap.keys()) { DeviceList &deviceList = deviceMap[type]; auto iter = std::find_if(deviceList.begin(), deviceList.end(), [&](DeviceInfoPtr ptr){ return ptr->id == drvid; }); if(iter != deviceList.end()) { return *iter; } } return DeviceInfoPtr(); } DeviceInfoPtr BiometricDevicesWidget::findDeviceByName(const QString &name) { for(int type : deviceMap.keys()) { DeviceList &deviceList = deviceMap[type]; auto iter = std::find_if(deviceList.begin(), deviceList.end(), [&](DeviceInfoPtr ptr){ return ptr->shortName == name; }); if(iter != deviceList.end()) { return *iter; } } return DeviceInfoPtr(); } void BiometricDevicesWidget::onCmbDeviceTypeCurrentIndexChanged(int index) { if(index < 0 || index >= deviceMap.keys().size()) { return; } int type = cmbDeviceType->itemData(index).toInt(); cmbDeviceName->clear(); for(auto &deviceInfo : deviceMap.value(type)) { cmbDeviceName->addItem(deviceInfo->shortName); } } void BiometricDevicesWidget::onOKButtonClicked() { int type = cmbDeviceType->currentData().toInt(); int index = cmbDeviceName->currentIndex(); qDebug() << type << index; DeviceInfoPtr deviceInfo = deviceMap.value(type).at(index); Q_EMIT deviceChanged(deviceInfo); hide(); } void BiometricDevicesWidget::onUSBDeviceHotPlug(int drvid, int action, int /*devNum*/) { int savedDeviceId = currentDevice->id; int savedCount = 0; for(int type : deviceMap.keys()) savedCount += deviceMap.value(type).count(); switch(action) { case ACTION_ATTACHED: { //插入设备后,需要更新设备列表 deviceMap.clear(); updateDevice(); setCurrentDevice(savedDeviceId); break; } case ACTION_DETACHED: { DeviceInfoPtr pDeviceInfo = findDeviceById(drvid); if(pDeviceInfo) { int type = pDeviceInfo->deviceType; deviceMap[type].removeOne(pDeviceInfo); int index = cmbDeviceName->findText(pDeviceInfo->shortName); cmbDeviceName->removeItem(index); //如果该类型的设备全被移除,删除该类型相关的列表 if(deviceMap[type].isEmpty()) { deviceMap.remove(type); index = cmbDeviceType->findData(type); cmbDeviceType->removeItem(index); } } if(savedDeviceId != drvid) { setCurrentDevice(savedDeviceId); } break; } } int count = 0; for(int type : deviceMap.keys()) count += deviceMap.value(type).count(); //设备数量发生了变化 if(count != savedCount) { Q_EMIT deviceCountChanged(count); } } ukui-screensaver/BiometricAuth/biometricproxy.h0000644000175000017500000000746114205074704020773 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef BIOMETRICPROXY_H #define BIOMETRICPROXY_H #include #include #include #include "biometricdeviceinfo.h" /** * @brief UpdateStauts调用返回的结果 */ struct StatusReslut { int result; int enable; int devNum; int devStatus; int opsStatus; int notifyMessageId; }; /** * @brief USB设备插拔动作 */ enum USBDeviceAction { ACTION_ATTACHED = 1, ACTION_DETACHED = -1 }; /** * @brief DBus代理类,负责调用对应的DBus接口 */ class BiometricProxy : public QDBusAbstractInterface { Q_OBJECT public: explicit BiometricProxy(QObject *parent = nullptr); public Q_SLOTS: /** * @brief 使用指定id的设备进行用户认证 * @param drvid 驱动(设备)id * @param uid 用户id * @param indexStart 用于认证的特征索引范围 * @param indexEnd * @return 结果: (结果,用户id) */ QDBusPendingCall Identify(int drvid, int uid, int indexStart = 0, int indexEnd = -1); /** * @brief 终止设备上正在进行的操作 * @param drvid 设备id * @param waiting 等待时间(秒) * @return */ int StopOps(int drvid, int waiting = 3000); /** * @brief 获取当前用户已连接设备对应特征数目 * @param uid 用户id * @param indexStart 用于认证的特征索引范围 * @param indexEnd * @return */ int GetFeatureCount(int uid, int indexStart = 0, int indexEnd = -1); /** * @brief 获取已连接的设备列表 * @return */ DeviceList GetDevList(); /** * @brief 获取设备数量 * @return */ int GetDevCount(); /** * @brief 获取设备消息 * @param drvid 驱动id * @return */ QString GetDevMesg(int drvid); /** * @brief GetNotifyMesg 获取通知消息 * @param drvid 驱动id * @return */ QString GetNotifyMesg(int drvid); /** * @brief GetOpsMesg 获取操作消息 * @param drvid 驱动id * @return */ QString GetOpsMesg(int drvid); /** * @brief UpdateStatus 获取更新的设备状态 * @param drvid 驱动id * @return 结果: */ StatusReslut UpdateStatus(int drvid); int GetUserDevCount(int uid); int GetUserDevFeatureCount(int uid,int drvid); Q_SIGNALS: /** * @brief 设备状态发生变化 * @param drvid 设备id * @param status 设备状态 */ void StatusChanged(int drvid, int status); /** * @brief USB设备热插拔 * @param drvid 设备id * @param action 插拔动作(1:插入,-1:拔出) * @param deviceNum 插拔动作后该驱动拥有的设备数量 */ void USBDeviceHotPlug(int drvid, int action, int deviceNum); void FrameWritten(int drvid); }; #endif // BIOMETRICPROXY_H ukui-screensaver/BiometricAuth/CMakeLists.txt0000644000175000017500000000115614205074704020276 0ustar fengfengqt5_wrap_cpp(BiometricAuth_SRC biometricdeviceinfo.h biometricproxy.h biometricauthwidget.h biometricdeviceswidget.h giodbus.h ) set(BiometricAuth_SRC ${BiometricAuth_SRC} biometricdeviceinfo.cpp biometricproxy.cpp biometricauthwidget.cpp biometricdeviceswidget.cpp giodbus.cpp ) include_directories( ${Qt5Core_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5DBus_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS} ${GLIB2_INCLUDE_DIRS} ) add_library(BiometricAuth STATIC ${BiometricAuth_SRC}) target_link_libraries(BiometricAuth Qt5::Core Qt5::DBus Qt5::Widgets ${OpenCV_LIBS} ${GIOUNIX2_LIBRARIES}) ukui-screensaver/BiometricAuth/BiometricAuth.pri0000644000175000017500000000037514205074704021013 0ustar fengfengSOURCES += \ $$PWD/biometricproxy.cpp \ $$PWD/biometricauthwidget.cpp \ $$PWD/biometricdeviceswidget.cpp HEADERS += \ $$PWD/biometricproxy.h \ $$PWD/biometricauthwidget.h \ $$PWD/biometricdeviceswidget.h ukui-screensaver/BiometricAuth/biometricproxy.cpp0000644000175000017500000001510714205074704021322 0ustar fengfeng/** * Copyright (C) 2018 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, 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 "biometricproxy.h" #include BiometricProxy::BiometricProxy(QObject *parent) : QDBusAbstractInterface(BIOMETRIC_DBUS_SERVICE, BIOMETRIC_DBUS_PATH, BIOMETRIC_DBUS_INTERFACE, QDBusConnection::systemBus(), parent) { registerMetaType(); setTimeout(2147483647); } QDBusPendingCall BiometricProxy::Identify(int drvid, int uid, int indexStart, int indexEnd) { QList argList; argList << drvid << uid << indexStart << indexEnd; return asyncCallWithArgumentList(QStringLiteral("Identify"), argList); } int BiometricProxy::GetFeatureCount(int uid, int indexStart, int indexEnd) { QDBusMessage result = call(QStringLiteral("GetDevList")); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "GetDevList error:" << result.errorMessage(); return 0; } auto dbusArg = result.arguments().at(1).value(); QList variantList; dbusArg >> variantList; int res = 0; for(int i = 0; i < variantList.size(); i++) { DeviceInfoPtr pDeviceInfo = std::make_shared(); auto arg = variantList.at(i).value(); arg >> *pDeviceInfo; QDBusMessage FeatureResult = call(QStringLiteral("GetFeatureList"),pDeviceInfo->id,uid,indexStart,indexEnd); if(FeatureResult.type() == QDBusMessage::ErrorMessage) { qWarning() << "GetFeatureList error:" << FeatureResult.errorMessage(); return 0; } res += FeatureResult.arguments().takeFirst().toInt(); } return res; } int BiometricProxy::StopOps(int drvid, int waiting) { QDBusReply reply = call(QStringLiteral("StopOps"), drvid, waiting); if(!reply.isValid()) { qWarning() << "StopOps error:" << reply.error(); return -1; } return reply.value(); } int BiometricProxy::GetUserDevCount(int uid) { QDBusMessage result = call(QStringLiteral("GetDevList")); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "GetDevList error:" << result.errorMessage(); return 0; } auto dbusArg = result.arguments().at(1).value(); QList variantList; DeviceList deviceList; dbusArg >> variantList; for(int i = 0; i < variantList.size(); i++) { DeviceInfoPtr pDeviceInfo = std::make_shared(); auto arg = variantList.at(i).value(); arg >> *pDeviceInfo; int count = GetUserDevFeatureCount(uid,pDeviceInfo->id); if(count>0) deviceList.push_back(pDeviceInfo); } return deviceList.count(); } int BiometricProxy::GetUserDevFeatureCount(int uid,int drvid) { StopOps(drvid); QDBusMessage FeatureResult = call(QStringLiteral("GetFeatureList"),drvid,uid,0,-1); if(FeatureResult.type() == QDBusMessage::ErrorMessage) { qWarning() << "GetFeatureList error:" << FeatureResult.errorMessage(); return 0; } return FeatureResult.arguments().takeFirst().toInt(); } DeviceList BiometricProxy::GetDevList() { QDBusMessage result = call(QStringLiteral("GetDevList")); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "GetDevList error:" << result.errorMessage(); return DeviceList(); } auto dbusArg = result.arguments().at(1).value(); QList variantList; DeviceList deviceList; dbusArg >> variantList; for(int i = 0; i < variantList.size(); i++) { DeviceInfoPtr pDeviceInfo = std::make_shared(); auto arg = variantList.at(i).value(); arg >> *pDeviceInfo; deviceList.push_back(pDeviceInfo); } return deviceList; } int BiometricProxy::GetDevCount() { QDBusMessage result = call(QStringLiteral("GetDevList")); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "GetDevList error:" << result.errorMessage(); return 0; } int count = result.arguments().at(0).value(); return count; } QString BiometricProxy::GetDevMesg(int drvid) { QDBusMessage result = call(QStringLiteral("GetDevMesg"), drvid); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "GetDevMesg error:" << result.errorMessage(); return ""; } return result.arguments().at(0).toString(); } QString BiometricProxy::GetNotifyMesg(int drvid) { QDBusMessage result = call(QStringLiteral("GetNotifyMesg"), drvid); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "GetNotifyMesg error:" << result.errorMessage(); return ""; } return result.arguments().at(0).toString(); } QString BiometricProxy::GetOpsMesg(int drvid) { QDBusMessage result = call(QStringLiteral("GetOpsMesg"), drvid); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "GetOpsMesg error:" << result.errorMessage(); return ""; } return result.arguments().at(0).toString(); } StatusReslut BiometricProxy::UpdateStatus(int drvid) { StatusReslut status; QDBusMessage result = call(QStringLiteral("UpdateStatus"), drvid); if(result.type() == QDBusMessage::ErrorMessage) { qWarning() << "UpdateStatus error:" << result.errorMessage(); status.result = -1; return status; } status.result = result.arguments().at(0).toInt(); status.enable = result.arguments().at(1).toInt(); status.devNum = result.arguments().at(2).toInt(); status.devStatus = result.arguments().at(3).toInt(); status.opsStatus = result.arguments().at(4).toInt(); status.notifyMessageId = result.arguments().at(5).toInt(); return status; } ukui-screensaver/BiometricAuth/main.cpp0000644000175000017500000000317614205074704017172 0ustar fengfeng/** * Copyright (C) 2018 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, 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 #include #include "biometricproxy.h" #include "biometricauthwidget.h" #include "biometricdeviceswidget.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); BiometricProxy proxy; BiometricAuthWidget biometricAuthWidget(&proxy); biometricAuthWidget.hide(); BiometricDevicesWidget biometricDeviceWidget(&proxy); QObject::connect(&biometricDeviceWidget, &BiometricDevicesWidget::deviceChanged, &a, [&](const DeviceInfoPtr &pDeviceInfo){ biometricAuthWidget.startAuth(pDeviceInfo, 1000); biometricAuthWidget.show(); }); QObject::connect(&biometricDeviceWidget, &BiometricDevicesWidget::deviceCountChanged, &a, [&](int count){ qDebug() << "device count changed: " << count; }); biometricDeviceWidget.show(); return a.exec(); } ukui-screensaver/KylinNM/0000755000175000017500000000000014205075221014310 5ustar fengfengukui-screensaver/KylinNM/kylin-nm.pro0000644000175000017500000000770214205074704016603 0ustar fengfeng#------------------------------------------------- # # Project created by QtCreator 2018-10-19T15:29:47 # #------------------------------------------------- QT += core gui x11extras dbus greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = kylin-nm TEMPLATE = app LANGUAGE = C++ CONFIG += c++11 # CONFIG += link_pkgconfig # PKGCONFIG += gsettings-qt LIBS += -L/usr/lib/ -lgsettings-qt -lX11 target.path = /usr/bin target.source += $$TARGET desktop.path = /etc/xdg/autostart/ desktop.files = kylin-nm.desktop INSTALLS += target \ desktop # The following define makes your compiler emit warnings if you use # any feature of Qt which has been marked as deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS # You can also make your code fail to compile if you use deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 # QMAKE_CXXFLAGS += -Wno-unused-parameter QMAKE_CPPFLAGS *= $(shell dpkg-buildflags --get CPPFLAGS) QMAKE_CFLAGS *= $(shell dpkg-buildflags --get CFLAGS) QMAKE_CXXFLAGS *= $(shell dpkg-buildflags --get CXXFLAGS) QMAKE_LFLAGS *= $(shell dpkg-buildflags --get LDFLAGS) SOURCES += \ src/backthread.cpp \ src/confform.cpp \ src/ksimplenm.cpp \ src/kylin-dbus-interface.cpp \ src/kylin-network-interface.c \ src/loadingdiv.cpp \ src/main.cpp \ src/kylinnm.cpp \ src/oneconnform.cpp \ src/onelancform.cpp \ src/switchbutton.cpp \ src/utils.cpp \ wireless-security/dlgconnhidwifi.cpp \ wireless-security/dlgconnhidwifisecfast.cpp \ wireless-security/dlgconnhidwifisectunneltls.cpp \ wireless-security/dlgconnhidwifisecpeap.cpp \ wireless-security/dlgconnhidwifisectls.cpp \ wireless-security/dlgconnhidwifisecleap.cpp \ wireless-security/dlgconnhidwifisecpwd.cpp \ wireless-security/dlgconnhidwifiwep.cpp \ wireless-security/dlgconnhidwifileap.cpp \ wireless-security/dlgconnhidwifiwpa.cpp \ wireless-security/kylinheadfile.cpp \ hot-spot/dlghotspotcreate.cpp HEADERS += \ src/backthread.h \ src/confform.h \ src/ksimplenm.h \ src/kylin-dbus-interface.h \ src/kylin-network-interface.h \ src/loadingdiv.h \ src/kylinnm.h \ src/oneconnform.h \ src/onelancform.h \ src/switchbutton.h \ src/utils.h \ wireless-security/dlgconnhidwifi.h \ wireless-security/dlgconnhidwifisecfast.h \ wireless-security/dlgconnhidwifisectunneltls.h \ wireless-security/dlgconnhidwifisecpeap.h \ wireless-security/dlgconnhidwifisectls.h \ wireless-security/dlgconnhidwifisecleap.h \ wireless-security/dlgconnhidwifisecpwd.h \ wireless-security/dlgconnhidwifiwep.h \ wireless-security/dlgconnhidwifileap.h \ wireless-security/dlgconnhidwifiwpa.h \ wireless-security/kylinheadfile.h \ hot-spot/dlghotspotcreate.h FORMS += \ src/confform.ui \ src/kylinnm.ui \ src/oneconnform.ui \ src/onelancform.ui \ wireless-security/dlgconnhidwifi.ui \ wireless-security/dlgconnhidwifisecfast.ui \ wireless-security/dlgconnhidwifisectunneltls.ui \ wireless-security/dlgconnhidwifisecpeap.ui \ wireless-security/dlgconnhidwifisectls.ui \ wireless-security/dlgconnhidwifisecleap.ui \ wireless-security/dlgconnhidwifisecpwd.ui \ wireless-security/dlgconnhidwifiwep.ui \ wireless-security/dlgconnhidwifileap.ui \ wireless-security/dlgconnhidwifiwpa.ui \ hot-spot/dlghotspotcreate.ui RESOURCES += \ nmqrc.qrc unix { UI_DIR = .ui MOC_DIR = .moc OBJECTS_DIR = .obj } TRANSLATIONS = translations/kylin-nm_zh_CN.ts \ translations/kylin-nm_tr.ts \ translations/kylin-nm_bo.ts DISTFILES += ukui-screensaver/KylinNM/nmqrc.qrc0000644000175000017500000001034414205074704016146 0ustar fengfeng res/s/conning-b/1.png res/s/conning-b/2.png res/s/conning-b/3.png res/s/conning-b/4.png res/s/conning-b/5.png res/s/conning-b/6.png res/s/conning-b/7.png res/s/conning-b/8.png res/s/conning-b/9.png res/s/conning-b/10.png res/s/conning-b/11.png res/s/conning-b/12.png res/g/down_arrow.png res/g/checkbox-checked.svg res/g/checkbox-unchecked.svg res/s/rescan/1.png res/s/rescan/2.png res/s/rescan/3.png res/s/rescan/4.png res/s/rescan/5.png res/s/rescan/6.png res/s/rescan/7.png res/s/rescan/8.png res/s/rescan/9.png res/s/rescan/10.png res/s/rescan/11.png res/s/rescan/12.png res/h/hide-pwd.png res/h/right-pwd.png res/h/show-pwd.png res/h/no-pwd-wifi.png res/x/fly-mode-off.svg res/x/fly-mode-on.svg res/x/hot-spot-off.svg res/x/hot-spot-on.svg res/x/net-list-bg.svg res/x/wifi-list-bg.svg res/x/load-down.png res/x/load-up.png res/l/network-offline.png res/l/network-offline.svg res/l/network-online.png res/l/network-online.svg res/w/wifi-full.png res/w/wifi-full-pwd.png res/w/wifi-high.png res/w/wifi-high-pwd.png res/w/wifi-low.png res/w/wifi-low-pwd.png res/w/wifi-medium.png res/w/wifi-medium-pwd.png res/w/wifi-none.png res/w/wifi-none-pwd.png res/s/conning-a/1.png res/s/conning-a/2.png res/s/conning-a/3.png res/s/conning-a/4.png res/s/conning-a/5.png res/s/conning-a/6.png res/s/conning-a/7.png res/s/conning-a/8.png qss/style.qss res/g/close_black.png res/g/close_white.png res/s/conning-s/1.png res/s/conning-s/2.png res/s/conning-s/3.png res/s/conning-s/4.png res/s/conning-s/5.png res/s/conning-s/6.png res/s/conning-s/7.png res/s/conning-s/8.png res/s/conning-s/9.png res/s/conning-s/10.png res/s/conning-s/11.png res/s/conning-s/12.png res/x/setup.png res/x/pb-wifi-n.png res/x/pb-wifi-y.png res/x/pb-conn-dis.png res/l/pb-network-online.png res/l/pb-network-info.png res/l/pb-network-offline.png res/x/pb-newConn.png res/x/pb-close.png res/l/pb-top-network-offline.png res/w/pb-all-wifi-offline.png res/w/pb-top-wifi-offline.png res/w/wifi-full-off.png res/w/wifi-high-off.png res/w/wifi-low-off.png res/w/wifi-medium-off.png res/w/wifi-low-pwd-off.png res/w/wifi-full-pwd-off.png res/w/wifi-high-pwd-off.png res/w/wifi-medium-pwd-off.png res/w/wifi-none-off.png res/w/wifi-none-pwd-off.png ukui-screensaver/KylinNM/qss/0000755000175000017500000000000014205074704015123 5ustar fengfengukui-screensaver/KylinNM/qss/style.qss0000644000175000017500000000126614205074704017020 0ustar fengfengQScrollBar:vertical{margin:0px 2px 0px 2px;width:10px;background:rgba(48,48,51,0);border-radius:6px;} QScrollBar::up-arrow:vertical{height:0px;} QScrollBar::sub-line:vertical{border:0px solid;height:0px} QScrollBar::sub-page:vertical{background:transparent;} QScrollBar::handle:vertical{width:6px;background:rgba(72,72,76,1);border-radius:3px;} QScrollBar::handle:vertical:hover{width:6px;background:rgba(97,97,102,1);border-radius:3px;} QScrollBar::handle:vertical:pressed{width:6px;background:rgba(133,133,140,1);border-radius:3px;} QScrollBar::add-page:vertical{background:transparent;} QScrollBar::add-line:vertical{border:0px solid;height:0px} QScrollBar::down-arrow:vertical{height:0px;} ukui-screensaver/KylinNM/res.qrc0000644000175000017500000000000714205074704015612 0ustar fengfeng ukui-screensaver/KylinNM/CMakeLists.txt0000644000175000017500000000541614205074704017063 0ustar fengfengfind_package(Qt5 COMPONENTS Core Widgets REQUIRED) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) #pkg_check_modules(X11 REQUIRED x11) qt5_wrap_ui(Kylin_NM_SRC src/confform.ui src/kylinnm.ui src/oneconnform.ui src/onelancform.ui wireless-security/dlgconnhidwifi.ui wireless-security/dlgconnhidwifisecfast.ui wireless-security/dlgconnhidwifisectunneltls.ui wireless-security/dlgconnhidwifisecpeap.ui wireless-security/dlgconnhidwifisectls.ui wireless-security/dlgconnhidwifisecleap.ui wireless-security/dlgconnhidwifisecpwd.ui wireless-security/dlgconnhidwifiwep.ui wireless-security/dlgconnhidwifileap.ui wireless-security/dlgconnhidwifiwpa.ui hot-spot/dlghotspotcreate.ui ) #qt5_wrap_cpp(Kylin_NM_SRC # src/backthread.h # src/confform.h # src/ksimplenm.h # src/kylin-dbus-interface.h # src/kylin-network-interface.h # src/loadingdiv.h # src/kylinnm.h # src/oneconnform.h # src/onelancform.h # src/switchbutton.h # src/utils.h # wireless-security/dlgconnhidwifi.h # wireless-security/dlgconnhidwifisecfast.h # wireless-security/dlgconnhidwifisectunneltls.h # wireless-security/dlgconnhidwifisecpeap.h # wireless-security/dlgconnhidwifisectls.h # wireless-security/dlgconnhidwifisecleap.h # wireless-security/dlgconnhidwifisecpwd.h # wireless-security/dlgconnhidwifiwep.h # wireless-security/dlgconnhidwifileap.h # wireless-security/dlgconnhidwifiwpa.h # wireless-security/kylinheadfile.h # hot-spot/dlghotspotcreate.h # ) qt5_add_resources(Kylin_NM_SRC nmqrc.qrc res.qrc) set(Kylin_NM_SRC ${Kylin_NM_SRC} src/backthread.cpp src/confform.cpp src/ksimplenm.cpp src/kylin-dbus-interface.cpp src/kylin-network-interface.c src/loadingdiv.cpp src/kylinnm.cpp src/oneconnform.cpp src/onelancform.cpp src/switchbutton.cpp src/utils.cpp src/swipegesturerecognizer.cpp wireless-security/dlgconnhidwifi.cpp wireless-security/dlgconnhidwifisecfast.cpp wireless-security/dlgconnhidwifisectunneltls.cpp wireless-security/dlgconnhidwifisecpeap.cpp wireless-security/dlgconnhidwifisectls.cpp wireless-security/dlgconnhidwifisecleap.cpp wireless-security/dlgconnhidwifisecpwd.cpp wireless-security/dlgconnhidwifiwep.cpp wireless-security/dlgconnhidwifileap.cpp wireless-security/dlgconnhidwifiwpa.cpp wireless-security/kylinheadfile.cpp hot-spot/dlghotspotcreate.cpp nmqrc.qrc ) include_directories( ${Qt5Core_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5DBus_INCLUDE_DIRS} ) find_package(KF5WindowSystem) add_library(Kylin-nm STATIC ${Kylin_NM_SRC}) target_link_libraries(Kylin-nm Qt5::Core Qt5::Widgets KF5::WindowSystem Qt5::DBus Qt5::X11Extras) ukui-screensaver/KylinNM/res/0000755000175000017500000000000014205074704015106 5ustar fengfengukui-screensaver/KylinNM/res/h/0000755000175000017500000000000014205074704015335 5ustar fengfengukui-screensaver/KylinNM/res/h/no-pwd-wifi.png0000644000175000017500000000315314205074704020205 0ustar fengfengPNG  IHDRagzTXtRaw profile type exifxڽa =q13A߇Mɦdfb%>AB˟ߍ~lj|s>K zv~win1.c~=\_0?ӽl~pĻHr8R<)JY<goS!Yխw")Ьv8{|ԏܭA?wLrl.ˊ{ˈe,e_k5l+>cQ#L E4'`lkh7ZR'r2 or<#E/zYt%52P|od&ANa=^"WLa8FGûQk̙]ڵB^ itrYmhV}VA02',is1֖TVHɰ#;1f sQ/p YW;\ q6`G췄*C1XH!5b9UL[hfɲɧbRN%KVcr̖Sι-W$N~ SlJSʌ8ۜ<*U+ZM5ײRZؒZk| -6kVvj=#xPTgWj0]\p?NBgbĭ@AKg{/\g(Aé܉_XBݕܗ&QG䨣! ZVW@}BS K*J]zw_6JHj4}*Etfe];eMa?׎~ľ$?7w]^}]G-E>7.Vz_^{]O_*Obz:}}iW{5g1'2ô7g6m>qex̤ ?r]qs i*y^xwwgoisrbKGD pHYs.#.#x?vtIME 7:IDAT8˥m0 O~S47G(#d# @_B"B@Ё?Ǔ(I/Z@/)I%"&+pk2 8sbx;F`/d>]ncb04 G'[XtZ^v}f4R+ZFW L55uZ]XR%}H: R`vmLng :@~u+ g#<IuTP+<IENDB`ukui-screensaver/KylinNM/res/h/show-pwd.png0000644000175000017500000000241114205074704017611 0ustar fengfengPNG  IHDR FtEXtSoftwareAdobe ImageReadyqe<iTXtXML:com.adobe.xmp sIDATxbgL P@@ }.@ @y @14q,H) T:07d%@<b5 UU$3n): `&| @٧ ]@\;A ?1/bv  @ ԁ t^J ^@ $ Ӂ;x ?b)  >ę@`]hx8q@# ٠t0T$U5. ?] rZ 6h-O@OqT=:騏IENDB`ukui-screensaver/KylinNM/res/h/right-pwd.png0000644000175000017500000000256614205074704017761 0ustar fengfengPNG  IHDRhOGtEXtSoftwareAdobe ImageReadyqe<iTXtXML:com.adobe.xmp ԟIDATxb9h@#P Ȩ@D:gr&d b2 ^qK @<a@ VfƁ$q́:9 ևJ$B%@1@}@]0ǃ {@d4 cAZ#IA,G`b(d(~;u Inb1 n@x;'*0Wˡ T\Aa @MQ nP (΅+a b?hb@Á"T@|(((RX B@^PdFOTp"?3I "l3hI14^`)RP@2/Po4Cda SC4IENDB`ukui-screensaver/KylinNM/res/h/hide-pwd.png0000644000175000017500000000265414205074704017553 0ustar fengfengPNG  IHDR HLtEXtSoftwareAdobe ImageReadyqe<iTXtXML:com.adobe.xmp Za`IDATxb+' UUUfPNx_[T$d^ZHTցL dt dGyxx=XO*Zijoowx>@  @3ֻ@[KT :5cp'A} q)<|WfGp ^@|awpb_`H#p*`0E0, fwYT EO'^|IENDB`ukui-screensaver/KylinNM/res/l/0000755000175000017500000000000014205074704015341 5ustar fengfengukui-screensaver/KylinNM/res/l/network-online.svg0000644000175000017500000000142114205074704021033 0ustar fengfenggnome-dev-ethernet32ukui-screensaver/KylinNM/res/l/pb-top-network-offline.png0000644000175000017500000000233114205074704022356 0ustar fengfengPNG  IHDR00WIDAThCOh\Eǿ>/Z)EOAГ$ykz0mATA$ੂO-[V%Xegfo;n?lwKE3a}^TJnFj$`73""f_~DQ*oɈhH)m3?{B "(=D] $kJ!f A:yEI)xfhpi Xxj|||.Ḑ!B&)+ )TݫZ -,B<.GP`; R /Q"2RJWnٲHqԉ(c֞nR}!Dso=`8@XB[bs֧HG8E!7~x8/UR+@s6J ([/;4M/,FQ4mO!َRj+RMS(8 *m Q؃:O"$aopbFTBR76hg^z L|_1=[E.2M]fG8o-HĽTlxI X6 R"'3r NKq"=[zLv#AD?){]: MsPT* R"p*M'"j*Ƙg'+Hǫ-gC Ϗ,//X1@%ZF]!LZc;ODtY)Ӧ3 =GBq̵[JJ3[soZ#'jqUiIqRYce@D/(^[h<33Fĩ86NK2Q eitBR8ᙙ1k;^{G=ήwHRC wʺ;'uZ Ptp1㑠8ac}ej#S!8,p .p)\0D5}w?̯!4 {ee坲S?{BJiN8@RC|s!]aKBLuۨ|0h0۱'ن0݋kvNi>b;hѰ"r ~a/kgJ WջЯj!J^烱IENDB`ukui-screensaver/KylinNM/res/l/pb-network-offline.png0000644000175000017500000000326214205074704021562 0ustar fengfengPNG  IHDR00WyIDAThCYih\U>q:RKQU[kVE\RW܊=M2mg6t{j *ڊ  q)EZmAMDdwL3NjޟsιeWD}?(:>M&Μ9sΝ;ݾx"~A|7&Q'.D2KKKp4|8 6ȨgϞ%"04 )q0mzPx7ד+Vy(ԡ`դI::::~+  Qq0|ff9rq]ίjX;BJ &z{{y:Z/\xODZF Tjv.CթTr\q4Db ddoo"b_q&3BDϊ=qYaLCjؐJr|$r_kx)f~uNPٝۉDT1rcss---FH% 8a~HDE䶆!>wӊ1߄Zk!ZBDQr=DOfI )C;JM7wA) b ."hѢ7"rT 3?NDwȋ6%UνeDdYMMM.[7____O?j@,o^EqiFZI^i&rshRx4-XHbh@zfW[IENDB`ukui-screensaver/KylinNM/res/l/network-offline.svg0000644000175000017500000000234114205074704021173 0ustar fengfeng ukui-screensaver/KylinNM/res/l/pb-network-online.png0000644000175000017500000000341714205074704021426 0ustar fengfengPNG  IHDR00WIDAThCݙ{Tǿ33 cݹc+T 5`P;"aZ1XI_bBRĹ3@YLJ)l׽ԾA[̲`؝{~͝uݙ{f.?wptǏs`f2h 7F<ЉSz;H0q;Txc5 `y|kqjW)ݵ ^~=%~}M 2.6m3'1~⤌{10ĮD\@BTXz/#`FkE1/]+qn9p0hDlm?J=Re;Z :5m3HF7u!Ӗ2kr&%'i|y/ և~Xƣ5iV<2Ԏ@;)cʶ~%^3NιL`r?3/On2Nw 4gV?D~褌'̴&_9q* qhf(o>0ڎ[ [Z36uȗke*Dc.{ a /T^)݉pӞcsꙈ@9 0/XrScL~R_nHdti2-5~I*^~aDz w,AgN@qm܃`g67M0[@ %->Jit\*`ŇOŨS L4&*0ZDDU}vf tn2O}sZ `*"dN"߈ 3KDǙr!jNb^;HDw$>KDGCRɬ `|||SX|DtAO 5SR\._78 k#3f/S HM 13?%!<` b潵q+ʻ` p*RʯVnyd|2;_1 z#=՞X|»'n.3n9B$t033ab*sb1fA틌 WJy{ׇ9,ZڏQ_6ƘI7FR|NgDTBlX>LDlWJ vs(H)?M5 Gzw8ܟ!v-$Ck}:'Y!%l> *nDNkoV|BgCI; `+1&">hooBAܳ|'h73ߤu3ODƫρ0 _Na#"|{ܼ=ϟJƘgRO$( S>EmBlpLx2L{I:mι"3]ں9cťRWO|~BlRVtfg_BpX$+Bh[ZZrgn+2 ι3SJMc3> Û?vE>!QE ݀K߿$z߿:^SCl```( v g@Hht`xm,IENDB`ukui-screensaver/KylinNM/res/g/0000755000175000017500000000000014205074704015334 5ustar fengfengukui-screensaver/KylinNM/res/g/checkbox-checked.svg0000644000175000017500000000322514205074704021231 0ustar fengfeng ukui-screensaver/KylinNM/res/g/close_black.png0000644000175000017500000000031514205074704020302 0ustar fengfengPNG  IHDR;0IDATH E-a'{n &%zg8V__5Ir1/RʵQ"h 8t[LީVl㭘lb0yiPqRzZUɶt,>s~8_ k^WJIENDB`ukui-screensaver/KylinNM/res/g/close_white.png0000644000175000017500000000023014205074704020342 0ustar fengfengPNG  IHDR;0_IDATHA 0 DzKT!EBJX/BDd_|${w"ͷ?.RgWL=;EQOR*2OIENDB`ukui-screensaver/KylinNM/res/g/checkbox-unchecked.svg0000644000175000017500000000172014205074704021572 0ustar fengfeng ukui-screensaver/KylinNM/res/g/down_arrow.png0000644000175000017500000000016114205074704020221 0ustar fengfengPNG  IHDR8IDAT]I g>ha)`'Q)5as,ӽwIENDB`ukui-screensaver/KylinNM/res/x/0000755000175000017500000000000014205074704015355 5ustar fengfengukui-screensaver/KylinNM/res/x/pb-wifi-n.png0000644000175000017500000000325314205074704017656 0ustar fengfengPNG  IHDR00WrIDAThCXkhU&U j0nVQQAkQjE;3hvjdwNE V?b@Q+VAZ=r&۝r e9ι1C c d ٶ $"KDK)ЈRض-k>a^5͛7/<@fnC"Rk8ΟL@4̼qz1~8Pcddf20]]"x+g_apN9g|0Zu.ח@<?3< e|sM0wF萦iy^35heTbfn,盈4M7N)[is ?`[ K&wb쑑|+[YCDt╒Elv`hhH]!M6lmPňK(%_"h/߿rJ @|/%ESE4Yf=iӦ~ضxRJ4Mlmmݿz#~ig4 :mLP_e>Ft]7SW<ػwu|p^"B۶ }/ zﴵ-UȀeYwK)QN !D#ȹCD˙YMi  xsBO XQJ}n DNRfӧdfu,:dZ&yPo466>M30VPPT*58UyP̘뷧7&z{{ *iN8ZZZٶjnB ø!D4peOOϷ(b#fDq'9O9`EvRʟWf@[`}zHdrU0\H$~FHL&bDrs˲K)2fn_EG~UXmFD:::T۱VH)pr.M&jL|o,XA;H-fYfMs&Y"=uv0󬉂sbbY-pzQz|L&,lɓ,RWꥼ&qDӴŎ쬊2m!u]b5d2)GDn(bhn$BJ&Wv݅D4ZџK*^nF5M{)Q! ROϊsF/<à2L~9Ţݪh4󼝥7)sקi5H%Ue0|m'"|UhT<_Jޣh*:s_W] sTVNk;=(P;ϴ 亓ZQQLߊŲ)fVߍV !8OjG$lo?`e]+lq]w[5'W]n=PN:k"z9\QsNfj_iKQM.R 1>1BFD_!ή z_!0Xi!D?I@2Ms3#G 1)bԲGO34-8zE~O]k ik91%Bu.njB[ŃΉJSUg@~&FV ZOrVEIENDB`ukui-screensaver/KylinNM/res/x/fly-mode-on.svg0000644000175000017500000000175514205074704020234 0ustar fengfeng 画板 1 ukui-screensaver/KylinNM/res/x/pb-conn-dis.png0000644000175000017500000000123314205074704020173 0ustar fengfengPNG  IHDR szzbIDATXG͗?hAƿoxb$V(XXX %V`-lxTKԪr X&H}LVMXR`EBt$66 :SxnKgt "B+^•9|bJG}36ιbfl$#B?TiCxeEz>/*o{D=i7Kt~c6 _8]f:"(_Iڥ.Up`<[]ZfK~X뭜N4 ⬇澀o_I\'wu /[bc;@#Ҽ'E>vTP|a4|) -Buכ̉н1$ػ'rC_UΘ-s4q-į䋨q[K$) x#?2Ͷ^I;nsoThV3ƃ`QqB vz\r =5;ֹ .:(1 ksxE15A;[Ɏʊ z򇑏;g3vHwwȂ?Oc( 2A#E;t&v8eHB/޹5c7] ygJm +^)]ǿ|!PdcGYk زw}chy]3V{Ԉg5:/ZW#mP h E6Tc8EV )┈O$,]!+8etr ږzFn/7 q(.{,l^iT030w:T0 KOǘ-IENDB`ukui-screensaver/KylinNM/res/x/net-list-bg.svg0000644000175000017500000000154314205074704020226 0ustar fengfeng ukui-screensaver/KylinNM/res/x/pb-close.png0000644000175000017500000000115414205074704017570 0ustar fengfengPNG  IHDR<<:r3IDAThCJ@ghEA lB\|/E=HA{i7oJAJBi$;'ǒLo:Ag3^`gl8eN_8l )C[[:eNP)}UگVoq 8ΈX)sKZ%Ng7(B:8ۈ؞FIU*υ<"X,t/,>d3y^1.YŁGմ.XR`YhA<j4Pki(d pf +<ٔ{i} 6>q/rѕ*6 /D=$6}?Ӊ{"KM&x΍6;{/lnLLye8*VE,I1ٰI6(raU5)&6E.l&d&٠ȅ STդl$a•aLIENDB`ukui-screensaver/KylinNM/res/x/load-down.png0000644000175000017500000000030014205074704017740 0ustar fengfengPNG  IHDRatEXtSoftwareAdobe ImageReadyqe<bIDATxb`hK"BdBX2QQ`#; pNCB.X?@{hl AbP9aTxH" BH &q_1DIENDB`ukui-screensaver/KylinNM/res/x/pb-newConn.png0000644000175000017500000000042214205074704020067 0ustar fengfengPNG  IHDR00WIDAThCA0 wzH6"f{vK-OY~ He9 p`1.R̮"4Zk|b5嬔Mi7"BDI·yŠg?oo7@rv3E\ ;ݜA$ 2gTfˈ"B"o{ PрJPJPJPJPJP/?p1.IENDB`ukui-screensaver/KylinNM/res/x/fly-mode-off.svg0000644000175000017500000000225714205074704020370 0ustar fengfeng 画板 1 ukui-screensaver/KylinNM/res/x/hot-spot-on.svg0000644000175000017500000000175314205074704020273 0ustar fengfeng ukui-screensaver/KylinNM/res/x/wifi-list-bg.svg0000644000175000017500000000163714205074704020402 0ustar fengfeng 画板 1 ukui-screensaver/KylinNM/res/x/load-up.png0000644000175000017500000000030214205074704017417 0ustar fengfengPNG  IHDRatEXtSoftwareAdobe ImageReadyqe<dIDATxb`WB|Ƨ  P6VC:&lȶ`5 @,&| X43@K#63ĂQ`~F0>IENDB`ukui-screensaver/KylinNM/res/x/hot-spot-off.svg0000644000175000017500000000225514205074704020427 0ustar fengfeng ukui-screensaver/KylinNM/res/x/setup.png0000644000175000017500000000415014205074704017223 0ustar fengfengPNG  IHDRrP6 zTXtRaw profile type exifxW[( g$`fiَOܓ1E[ /\K YJ-%5WnXܯ=)IGPyߠ.crv4]GvzCu+^qs.Q(P0iinœ:% )]]d݀|{}òiɝv8m *99͹krD6]̠ZAQ܂nXl{\P:Ub2ehҺN.f^Y!;q%=9O MTH:ħ/[:FL0Fxk|9CDN{\ gΟBhǫAA`6Le7}VxN'00J` JB2+p49  psJw,\؛@`5)CMd)bAJ.RJ\ӤYEVm,X15jrMjqhVCKZ"KYt.#|zKn6xmbFmbX*kYum"fy,S:Cy5:X)'kՋ D30ƙ:hv΢Q9g20& r@a^esOĞb.8u`.G>amxc*tLcCpLj./fiU},Sg e +ӣ2\*|NW_xq0rjl^|Ww/j^dNJ} A_PQmur'/ Ѝ^#V.FGZ 0"cCuVUg73t !*O  -U8@6@g_,m+7kMsxnZpŷ"H`W2-8Dz٬VmoZ5|4ȳ7=qRHߺ,_Z 7 g 6=h(w? $3yxz̰TBKM N-`;%j6iCCPICC profilex}=H@_SE* VqP,8jP! :\!4iHR\ׂUg]\AIEJ_Rhq?{ܽziV鶙N&lnE "~ы,cVR_.γ9ռŀH< &^'ڴ QVUsQ.Hu7E539(XlcYԈ'cSXY+WYuCHb BA(FV iO]D.\`Gd ^R$t805>v |R?Iг \\4e ٔ])HS(3w tz5qd pp){=\rr*bKGD pHYs  tIMED$9IDAT8u]hq?Ye[Jhj^ʝxJF;.\jhqCSre)/yŤp0aiS{?s~tPiڥ*5_,:V/oWjZPuL` 'kAR﩯՛j][l $IHǁ@p1OکTY^mW?cTGejj uO=DO-04G7xT;I`pXF+SECVF_CZ@=89Vnȇj:. etqlW]Wƒ@wchˁV!ڠ dO[N2߭a_i>vS2=k^6dԇjjkLxuo|Dt[0߁z`?PF>CYXt-9uzA=>So Rd wRRuOA ۳+W,r92 8~ 6$ s"  |ARt˹xI ыMg [-Q=Q1GIENDB`ukui-screensaver/KylinNM/res/w/0000755000175000017500000000000014205074704015354 5ustar fengfengukui-screensaver/KylinNM/res/w/wifi-full-off.png0000644000175000017500000000325314205074704020533 0ustar fengfengPNG  IHDR00WrIDAThCXkhU&U j0nVQQAkQjE;3hvjdwNE V?b@Q+VAZ=r&۝r e9ι1C c d ٶ $"KDK)ЈRض-k>a^5͛7/<@fnC"Rk8ΟL@4̼qz1~8Pcddf20]]"x+g_apN9g|0Zu.ח@<?3< e|sM0wF萦iy^35heTbfn,盈4M7N)[is ?`[ K&wb쑑|+[YCDt╒Elv`hhH]!M6lmPňK(%_"h/߿rJ @|/%ESE4Yf=iӦ~ضxRJ4Mlmmݿz#~ig4 :mLP_e>Ft]7SW<ػwu|p^"B۶ }/ zﴵ-UȀeYwK)QN !D#ȹCD˙YMi  xsBO XQJ}n DNRfӧdfu,:dZ&yPo466>M30VPPT*58UyP̘뷧7&z{{ *iN8ZZZٶjnB ø!D4peOOϷ(b#fDq'9O9`EvRʟWf@[`}zHdrU0\H$~FHL&bDrs˲K)2fn_EG~UXmFD:::T۱VH)pr.M&jL|o,XA;H-fYfMs&Y"=uv0󬉂sbbY-pzQz|L&,lɓ,RWꥼ&qDӴŎ쬊2m!u]b5d2)GDn(bhn$BJ&Wv݅D4ZџK*^nF5M{)Q! ROϊsF/<à2L~9Ţݪh4󼝥7)sקi5H%Ue0|m'"|UhT<_Jޣh*:s_W] sTVNk;=(P;ϴ 亓ZQQLߊŲ)fVߍV !8OjG$lo?`e]+lq]w[5'W]n=PN:k"z9\QsNfj_iKQM.R 1>1BFD_!ή z_!0Xi!D?I@2Ms3#G 1)bԲGO34-8zE~O]k ik91%Bu.njB[ŃΉJSUg@~&FV ZOrVEIENDB`ukui-screensaver/KylinNM/res/w/wifi-none-pwd.png0000644000175000017500000000263114205074704020547 0ustar fengfengPNG  IHDR00W`IDAThCXO[e=-Z`sG 0vǥQo4^k0qxe4FDdsLGJAB{>攴+_sM8<}ރPV8~"wp[(%сjUjĘ@L5X@RXIE5Q5=T${u)Lɖ+,Zo w?Z'qu:!۸/Uúϩ![|qm#N &R :Ie% 33T#sH}B2"8cʫwz=W/\Qpduwo.X*e3ޓD@mh:T( 3Sn4fao:xm?.''Ol_:HR=f##-0@= z7U@xՂD@oZoh!`1"FƸ{QT>IoSc."IwE@w>vuqY>hr}n_HMȚxxmH-!ӗg1)a8ۊ&N5JHd~ [I;P\veA/_4s OB4c}MJ"@a 7@/Mqu$ߟL,ݎ.}et,~6V<)H;NoPP޻(n{`-WB-B[N<.T5S2:n%fZw5(: wn'7Qي#?>8TY {h]T,ı;nW"6<ۨk!<ȌŧD؞&%%_ےd+\*/J5O0^"IENDB`ukui-screensaver/KylinNM/res/w/wifi-low-pwd.png0000644000175000017500000000346114205074704020413 0ustar fengfengPNG  IHDR00WIDAThCX[O\^ks ` Nƕ7PEMBTԧK>"5RU@^}U ԤU8$jm`ؔ0s+: 3bHs^ַC?<$uWaV`'p`""<]Ju;3i`:IyjwCD}b/,3!"6:P%͏B_r'rIDk:wyW[WQ:Y[k^Kե|&]AR˦kd\,}wtm79H*d2 |`@F*ma%'2ۑ뫏d) E>7ߩv tGk ԑN9jsWL#+\,S^a2Yе8Rk!R5 '܃W$[%B& xd *yR_m~ a ֠HV4u|\(QػڮLR 8'Lќ/04+vkhIĊቦ!TżG :f[*b['^>kVf۷]FV3L f st/O$]'i//n/I1O~O&4c[v7[-?@)mWPQZ\CUvQ83Mi܎,:Y")'kB3vVtw7ȜSܑ G Z^FO!t]J3/$ti U^Q?CDX9>%wkn\n{#9#sWn r_M&-[,N}y#wxa1Ǔ}n{8)߹~!omU |CX?ԵoSMO&&D׆j'ÎHbjRN6J8á}YK¦"- MmбCܞ$Tqq4JET=pI<)n틀#KHTto;uJa.v.7RqritD*X*áZHbΗN`U{WѕCK9x U\{TWDkC%v()싅#/ym "sD oa/4T4xF '$2@/4CNO~} F^$KIENDB`ukui-screensaver/KylinNM/res/w/wifi-low.png0000644000175000017500000000336114205074704017622 0ustar fengfengPNG  IHDR00WIDAThCXKl7ZI(Q$qq-UB8Q-P]@Qt(Ȧn.я#YD)"۵ӒHJ>)μn1 34"}s?!7a;{#Fi%DDx|tѯ߃-1! hI0 >K<"#b/o@HP0" iB^(\ѺA=zhyT-qM໗-9Q (TK0$e[j]w.vyF-ABnm@^izʬ&=Y0O>^Dm"Dr T$?'jE9zsO, =l+bT׆@y.G) A)t:љwHtY*GF ԙkmT(6-!TEKt&N&S?J[*^ 8'.> 'e&{1)!XQ8Rb:6L 6?DmHߙ>V%`N,aAؔ$~uy?~hPǁd.R$׷/uPq_g;6ۀ/ԊA0iW^AM9MjX}&ϟߥvcO+MNxv(7S|ɘi~=~\d IFZ q%ט1$,^=׾Qn{b|iAǠjk~܁+}k9{w{Pkj>sy'Lm|HmvRQ~3Gly1ɏk@Xv=NY@ꑿF ĊTbOFYh zlUDPE_+N.w<$f :`ϳVG2qВ-˴>ã(P^,|UKzˊOom_3,ޞyI|p=d Z]z]utfBfjj" HkKs>$;e)p| di_PRv jӟ3,gKG<ߙĦ +WFR{Vg_6DϞDJQj2ӯ/V#R4JvBXEB^c ~n[$ >~؇mt+'_ /w*p?fתz`Ef{-- A˃4#BRJ,OIm~ݭ5v?bD>/_MN_gYpnkPeR+! Z5J'{r&oj0vy͹Kih@R+)ᱍW4ȆOF-h FZDD[In?{ClZ7iMƞ-M3k{_KKv.YGl]7YBg\ݜ?4뫡 l;gևw%0'jA i*TBcᏑy@D:Z[dn"sf|#i@/V$F&:^p o4&muDͺ DoHS`s7DUP $Eh; Mޅ3PmS2Ƕ.kM:$J> I2IQ.uU/(xz\,yux4|y `Ett2yvө~g3Nvf X?qiBϤC?WF} n5֮eEr6Ν9uj[-UYK"M|Ab1S"8Nʘ^gNA1<-%6Kvl|)TOXA}_J^2krV=RLuru,}AuoF$t!߿ٲXNm4iYԜW/e{dޙ}x]'v8J6$+_($UUB)ήPc xTuJbu}̽Yg#b)kw3wwsg9~C ܩ&w`$DDx$:ׅʘn2AU y Y3 6=jDlpp.CM@d~Iȝb-D]ػ_x 'kKc6L䎔kVQPyh$W=/n$#<H & <` @ZHeӻgl]/郀x)Q]  e tFfj$ȝ"r f%])2bYy] "Y#|~{Prg$'mÖ>-+>ʁGF .̻7ڄϜ!>o$T$`5O j=Vis"IgEZͦZbYc@Hxo/Bޕ XG;d-1MԵGr,{zk->\ΨP|lvux9:JM*"a//z'U!O 1p/闇O˔޷#0I-mWPRJXDߓ׍NZVcz;<$:>Hy-xODì]K<@H.D$b/}Լ|&{͉_8[[|Zuvead\WOnxl| ] Z‹P߉&S~qg?m灓7E, A:<O@s/*3ul?7 L_X(xp͒ίqI_?\*tK0<T%g 1D菅B`mQ ziEˈ cWH^%"u BUE=Q dKRP}>91"@Gj=ňf3csk#I+1 ;6M#[vϥuWU[D[B,ў't)ScMk/wS7_P$p։JB $~BRfFCMgo$隒)l,0U&)zǀS"| [S0O&cR.5.Dhhrmʱp0'hhtZ_-B-%^Dl[~e[^Bqn5Ъ)^ 7-"XqX` F#dxm|D) [vpBb+ctm%0pS*9E^tIENDB`ukui-screensaver/KylinNM/res/w/wifi-medium-pwd-off.png0000644000175000017500000000333214205074704021637 0ustar fengfengPNG  IHDR00WIDAThCX]U>L~vV[V--">X}*Q})3dӢ`gE& T}Ԋmmn6lf=rCLd6.t`Y29 3x'w2,[ ŋbs) !x<JCDWQWUUwbbbi{`6+JD`%"R8ˌ2T(J'Nat[e {p^]"BL^md2k8bX,"hV8t0eeYCBxK c#Gu B[mGݢ(#ED2Ʀ`uݪ^R׵VbW@X)HfL X s"^###۷/ ?:u*[#ȦBW:6qY"W#?l8[v|/ImL&iک 5"RRUl.m^^~}IyRQU''u]/;wF+Jhu7uLZhB6l^UT !:8[Oz'3D"g/53+#-D4k[' SA2BkCCC[&(Z"bSSS!b\v}4SdYsoW":](.K+Jyޖ+!rQvbqҟR^Ӵ-Bd''cU!Ds^sBiTV#D(JDBNDљ)WgسgOrnnށ 2 XcdqD!eCDM2ƮqN:,=ztQOж3"l6{)βjeY[  dr `޽nWsqm &"Q ;:11qUW릉y"zq9DBӴÝJ2%Q ~r7Z眿FD& (c\.iOD8ηAvJm'*Ѧi9HDo@t]_L:OD߄">" TqN!yq66ɲj?A%zJMD.9+/ t繦ce !D>QUξLD@}!c\.i^"uUD?mӧr<,X.cDX3"qgo0Q''8rzʀeY !>׮t\UU0 j9pU=Zx|0^v'a7.;/;p>"i>ц:-dpzz1Iq9zvfqi2Oslv@:^gd0MKVZJQ8SpY3`)k {Ҵ$Xq4ݮn 4,M!{*!阦)C+{gW~`+:1mMa(d!U#ذ؁&U[J2:Ȗӱ[% .C^IENDB`ukui-screensaver/KylinNM/res/w/wifi-full-pwd.png0000644000175000017500000000344414205074704020555 0ustar fengfengPNG  IHDR00WIDAThCX}lg|~k+teЗn4{`p i[tqsNdޢQd|a/Nw-tQ!EY@J.R5i26Zd\;z%҄~}o3Wo \PdEw-tiXhfXÖag%w"K&pg*r X&joxm`E7l)Xl22w,yCMZ MOxmiT,xPg/N1GkU}G[wNf `$ԓVFr_$zI`8*d Y"@Pvg9/ Km3F(suv]k8Z L~!N&+`)UpO=Mlao2omm.$"?xaZLrӾ%.?/yL z7}pCM9CڶH9ΰw֩Njۅt{ޘH|URY;^_8B5NvԾH [-X(S"`Y-sN}m8~RFB@@; 7~aѼVaŜ9(w6Z>̈_Z]~1O58tmq̳$ cMC1fu'\{ЋN!Ic8n5EbCxY.䤷>f0IreHqڵK̫Io \ 8f:" w$.yyf'iNFJ'(/ʸ`I7Yoʘ%[u,w?#ᩎ7 .)ʝ֏o?$a}ǍO 1Reߞ'w -|~2 ߐ^sfj!_w諜k/ 4JH:fvjТԼ%ĞXK4h|39f$g9rN YCLr%F%]sg 젅2C7 -pTt_M񘤆 ñp`k`[AMZ8)@c4Emˌ];*6\3tUZֲ+UKcg >%p &X)x;p_ϟ@tϋ\\mO@/ J%f #bẽE L{̷D0:pk)D @8w򏎝~Њṡ;nU*hz`Z 4DZ Bٱ_*i%o4KloQko :gTeC7c )hre^\e ˺y">S\74R lBb:eM'0K%? ^\<IENDB`ukui-screensaver/KylinNM/res/w/wifi-full-pwd-off.png0000644000175000017500000000332314205074704021321 0ustar fengfengPNG  IHDR00WIDAThCXih\UΛFC ujJB "uAŵ?{o*n}jH̻ u"E"UPj5[QjX:ɽG0^Y^&1w9|g?0ʼn8 50i.y588xch&c "=3577o&̯ۢl<`)Be\YsY$[epG)!"'ɳwэ,wDD{ ԗ \]cyAH&11"2A.uSqf^2J`$z3H]x\ɆlcX[OOX 9nfo/W7J9DD̘1kٶ}URMD4H$. ?/! Q.1rA5'h1fєXXiD1skHxѲoYr}'*퍒cݍuvv@%O6<T\􁆆>p:˲}_q],E;D$mmmn۶-6<<,L_g+3UOD*#۶3i0FD[R' u;1þ+q[d۶dfuttdrCk 8d°d=YLZ)%odm6:W74L^5xQjK<;2ڰpRJz?lUz zf)Zó8?E<ސ |'@:522"-㥮8.dz P frR lT>1Kt(|'S8*f#yR( ƘǦ,%뜒(Z"L^f7c(N,"S_0{M"MQ@LI-d)XT^GDu%^8IENDB`ukui-screensaver/KylinNM/res/w/pb-all-wifi-offline.png0000644000175000017500000000776414205074704021623 0ustar fengfengPNG  IHDRg-IDATx^ $e߫ꞙujVQD"A WfvYEFJAAE "E9]""";U=3;{Z홮'v󛿮@&Иh[LK@f@Ԛ~1. Z3 jM_ € Z/@a@k@05qPК844z~iחJfG'L8<۹#aJgM]+ @H"nsܹF&a;# "^,UnL(*` 0Zu/")њ(*(h浖eTbeP T[]D~Dڲ32@  \S(ߖZ3 @z"B,YH r4,k{ *t4O$24>1uSucuq657A4W[u[jz}0R\۶_ #T.&~.ވ wKTyb \8KaqLŗrkHdT*ӉDt32&UZuz3f8k֬YEiSQzDt@XOe$ )}r!m߯ eHx):)#aԌG e%ly^KM l9uvDD~*[ yDt+M.DZSD乇;sWt]p58w_ Uf39]욯۶}q0&$"ˉCv0d2 kzzzN7o/"8222VFDda [H.kqQFuxc*M L%J:g4WJ%{pddsP *^l汥R7mt]mHM-G{ˆ (,]8Sh `Ry{^< ; ʙ^w~ m6%CCC]v1f%4g5 c`]aÆ;wPRSLvLS 4ERFHD<{ŴXw'Zb>oo Vb&ov細y Lu(eRGQ\.d# 8Quf?r_վ_Zu ajV./ 8&8(fZ9*X촇 ~@Dgd6+lU mÈXmٔ/iW7'#㬜j¦y +#a$%( f7}$"u[}VZ TP )0 p)n'By!yYz!~յ"~ա , 81bc$/BWDCOO(S#@{ܙƔ7(ӧO_6gΜQE0{hEce*3g.me뎖 }4P,M*"KZ=|e9 uha%M T_!4ťRϷk-ϨjQ-y@;h4/YcccQ[/]ך7{)1^N?&!ю;xSe%>u|mj<+aJa㿔alٲw֭!ʀ@شnXgSd~E!B bqq__QDdCVV 7(W*}យD=_Uxd####8-0IQ4X0ykE&Q١DVG bqi I q`s#79jWͅ9\J@" gi^Aџ7qa+,}ɁZ f1qW.r<ODdu>!"Tj-u92&"/H`wҲ,j`pOxH^/&FXBXE$7m kM=;q0Vٶ&F:bu {{gNJ$!" 8ٲ{RN\}7Ĝ3Qm+-sQcV- 9W>d n"b0OXu{y ;3c^[kLxI۴v08ύiV)zΫe%Ia:| "~ڶēLv !GD+7SLzw|mʀ֕E 8۶k0;TGJx8ߏ0x0Y?#Bk+ " m0BD>d2a0t~hV0 yVީhT] m`0ND?#ev$l+W4g "VH;u$LVjlN[/F;{m L'hf*y͔5Hx!|+2;+@_!K53ټ@!#%iHC!p7)3\!(9^dB4Or#F)8{y)3ۜnM\0 sbS]ڶong<7JZpu<8Ƶ60!t]Pݟ!, ]CDgW'| }(YC' 8>̙nr`!}3|< pbqE0 B>pV":^ۻ%ͩ D/8o<ɃI<^_8M/"qڴiΝIFf \ JD]+UY3fX:{ u=0V*yD8WWWF wvq?"*M2w#b5)%=a1&OE?D|0Ŗe n:r `4bM{4n6r+t EiV_ϟ?ݬ=\|iMlAfjnToqm a87ٹs#DtXBd  RJBNW6os_6K+H|;[$gCPXZ*ֶؿ MJ~2NDDa"ƙʔ Dq>u ".m0yCVG·NՅ5MRtHչ#hh]v uCĭp8OFPkQ0bZ|#&v V1|ETkqV !D4/J庋^_\{  .@5ȵ`˯?xP r^_\{  .@5ȵ`˯?xP r^_\{  .@5ȵ`˯?xP r?}*IENDB`ukui-screensaver/KylinNM/res/w/wifi-none-pwd-off.png0000644000175000017500000000246214205074704021321 0ustar fengfengPNG  IHDR00WIDAThCYO#URe.论,_` F}$i:R &z1& <lQ&JJ "{m2[1m6a^܏s~s=[@=AGo^xZ|@*$Ɍ1%Rd%I%˲xCm |>`59 qRίQ/{״L Hl۾W)r;Jρw !Vdz" #H 1F([QZ8Re;Jz bcgkxc[&  [Vzq~``BQ-5 D!Ӯ,qc\4<9Ѯn$P(Aa3bE۶tD`_Ӵ S?ѩMB H PUU7まB cLKAX}6-πH=@2MJ\//۶=Rl3$ْ$QJc%MNvvv@TgcCkC:!1011TUu$$Ib !v#E"K,_We/N,d_Z p'T m%DI)p8! +qd$eyk .5Mçi?Uz0/j7u]ܼv܉LӴoVfZ$z!8;;;X.G%1Y^^p3f,.6UUyE\n0w(-ف@~2sdby{.]B]UU?e99l6~4( Ш(,^ObU麾9aih4::u0^<77/$DQUu=Jt=$Ƨ4Ms׵B0^jFB\B2ފF rzÆoS,,,WVV><7 D* yu@#"NgIV;I^/"\g=sJs8 `A`H!鬃x䪈]$I?EoߒBeRt`1~q,zS "OJ7Eֺ-eS-ȋZOPvwDdRD|]yv[?;;{k!me"ڃ?011aWf[BR9䖉ȯcJ)g r(rC< y;1ƘwAdwE7n_FGGwJj`~~Փ$ot:[(&Kj"bd+ɻ]PEV5ؑcPW'u~݉=ϻ $o?Ddw❞+ aߵa;|?%/qT*t bi4$?'yuL{pA)5]Tұ%Dĝa~?ܥu1DTVIZ S$3A`,|CrADH|@*uTRO?@1%")%Bre IΓܖ!zjFQ|a,Ž333+Ie1I&1veO4xEP7cȢ@L<%"m cA9ߜT+g0kM)A @Tϓ|=*ڗ1 e Ed[m?`C@?Ne%ZÐ0EVDk0 Oq7IENDB`ukui-screensaver/KylinNM/res/w/wifi-high-pwd.png0000644000175000017500000000354614205074704020535 0ustar fengfengPNG  IHDR00W-IDAThCXkl>dmصMLP*i]I@}W+QPKEL"WՇ MLX<%Z>Bĵ=kUa7wK_3}|;ô/^&woVfVUޖV}W~w8xiRSp ̩fM7J齤3 $P yl"!&7Pg7_)"jhyus]=pGZKh&Kv#KtXoz?WW3lrL26%ӞkK#W7R`{¸#@(;㗙;XTcrYd>zy6fPaw:h\6ؕ>D3$%3[ - U" u|U9)_Hn*Li b o bh 0DD9_ib_>Q1H`d[-h$fgCw~/$ .$0^o`3ͧw>R= Vc D$* c7CsZ4Rva9g YTHnY" c@Â0]!P' : {WfAЙ͒O$a4_L*nI..3wz=oSuM1E9[Bm }w3J78H_ؿS៺P|lwX-KB9[/@h$HDMn}1ibu=p`z%i|?\.Iq;yJdT>{ \U;Bef^&®hҞJnbGU%7aG!kDrqW@KxNϯY6Hq %tW :.@?) J'7Gk@VNt[*J+ޘn&vn+k*ܴ 3/_ijs&^vp"/^f<IENDB`ukui-screensaver/KylinNM/res/w/wifi-high.png0000644000175000017500000000343414205074704017741 0ustar fengfengPNG  IHDR00WIDAThCWkl[~q=^TE-Z6Q@U4 MӦ݄]bB&!u+Bb kgRKIsD{] _<9a? Ok\Z.u!#:喖ɮ%NA@ -r8LL.m_`f\&{"hZeK62 kI`^s{瞺e%6U3꼞Х'Y$ )$ad|51+"`MC))SMjmu;Z*>|y1'j?pP@`pr"m H]]i<̢KL!sPM\ ZiI/Ꚛ7΅B8 ܀r+bY@1(gTruG.ၣ&S6YTw4`^Qr#xn+S/\f ei:kN%6?uòĵ0hpc<aw6oh[Ĥn|ŀ8 2jQ,5 )gt>*9]7oxigH"Ku6Ӥs&?Nk7%HAM"rl !^K^oD//GBl -OuHZX(k"~w%g"ƽ5W2*?"#.m$2l*X e޹q2K4̝w4WKs}e"Q b2\91~y>Չu%qXd<{+l]RBSԲ@%b#R9–l1o=O@'[mUd$^۽aqe JwN[V^GL-@2ӻ,&ylT $KW]BZnGi:wד>s);!c2_DЗ gx?V';[Z]lÝ3L|UL)&>񧸶}"}Ւ3u:\_8L1%;5pͥG_jlœzV 0כֿ`V"9"Yf  (0QVi]DY72{ +"X5=j쓄WGB` Ódř'w.?^M2g/'Bmw`ٱ' ?lv~&`>R!P[k/31}^L-Pi$/7~eUXc$i-[xL^δyMǒ7[R'aN VfZF_DM LK`AGoLۀƣ3횆R{.54[+delDT?J38l7ٍ2m>`%@n"}xjꀝ+fG?ؿӏFI5Q"{!ߣ/L ۉPs$KNL#o\BICA6d&?%d׎bJ`9߅D ~u%5hF]1D3K=Q!48~x,ǒ ;fB0"K%9@%!?W"t?pֆc!C: Ծ=Q ẪP% mF6ZX:PV8O9%6IENDB`ukui-screensaver/KylinNM/res/w/wifi-medium-off.png0000644000175000017500000000324014205074704021045 0ustar fengfengPNG  IHDR00WgIDAThCX_h[e?7YIs! {>X]ӴfYrC)TPtRqݺ&]ӥ|%)YvoO{ ܜ ? w7"=ж""f27ܥ(*py^r"Ν[ADjzt]gl6HD~X@R(D䈸[gtŋJ D˲v!vιڌG@ r!|gg眮KYhtb/׈FeqrI4MBB &*+ϟ[ t]߼>cl|V.[kϧacYfX35k᰽  #Ȝ@;^w'sԩpjjJ0ƶ !Uk3T꟪E\,O'XDgՊN=K2.]c̱1(rcFuQw=1˲چ TUu}}}0y@.)x$[(7^yǙ3g\>o?<%@ ptϚPGhcl16sK݅nUU(['Y'i.|=//"Z$]2ӉDʖ\.KyPLyUUbJHeY2"=n"d2=\vbt3MӼ 6Z伝nWWnFw guc,..^EQ}llNIQ>izA"eY288ղcŮP lx<{.\cB@5"9/xU!DA3ܦihܛdo%`0(ɭ?9Hd bBvG=p\󌱻vyl߿vofwzٮq W%mm/0f"U@5M;h Dk)]lLPjvܮ!b:l u]rMk'ce'U#022iqJQyf Øsh$99#b#{(?ߝ"&Ws&! •ɅH%qj2`:H9DtF1 ?VWWx9 9www[=:7!xjn7<x%H8\.ZOSمH 952" `E\ wDT%bzW+Z"QME  mD~-ewB7uV"d2)gCC_+"iB/'oT|>oɇ{aL'FBP|Zl04&!aL4_m*%gϾ97SԷ4U_Rѯ6ry4EDGQ:"^s--Efm7Mk8`'d2)@[N[ BikAīaIۖnh  0ۂNGDmXX^iBOI0ƓH<ߖ6Z L8?6 CWO[k](zE~hvN@2Z`hՃoDU/xOC\*IENDB`ukui-screensaver/KylinNM/res/w/wifi-full.png0000644000175000017500000000335214205074704017763 0ustar fengfengPNG  IHDR00WIDAThCXle|޻lwBfƘ"cwEL&("5,sfH SJL cw݊YX7jBÍhacխwc7Z}<<=#G?38 L1e;B {򋪦e-ѐvXpxM톚vN{ʽdTuBk,pG8$8XUyyS&-9o ¼R6!yӆ'z&Yx<MFH 'dmI&`%B4++)3jLxE_`4Hu)iz!#̶JΆť TSIÁlY4bf܀%;Ȥd,VB\hvn&pWy}g4 y b뼙fӓ!6%DmPgxw.Nem=HZ5UdRУU|dݫ|oIXj!8JHSʳ|_|{NG{*rhg?1w=u#KڬdsOڿfVA 4:۩Z"0树z.:g219Ćxk`4bߴ P$DRME{Trbkア/3nQwFw,X"xI% /~Hp¸#m, GM< "B+^•9|bJG}36ιbfl$#B?TiCxeEz>/*o{D=i7Kt~c6 _8]f:"(_Iڥ.Up`<[]ZfK~X뭜N4 ⬇澀o_I\'wu /[bc;@#Ҽ'E>vTP|a4|) -Buכ̉н1$ػ'rC_UΘ-s4q-į䋨q[K$) x#?2Ͷ^I;nsoThV3ƃ`QqB vz\r =5;ֹ .:(1 ksxE15A;[Ɏʊ z򇑏;g3vHwwȂ?Oc( 2A#E;t&v8eHB/޹5c7] ygJm +^)]ǿ|!PdcGYk زw}chy]3V{Ԉg5:/ZW#mP h E6Tc8EV )┈O$,]!+8etr ږzFn/7 q(.{,l^iT030w:T0 KOǘ-IENDB`ukui-screensaver/KylinNM/res/w/wifi-high-off.png0000644000175000017500000000330314205074704020504 0ustar fengfengPNG  IHDR00WIDAThCWmlSU~s~Ь-Ct J 2CMLDP&Fv"tk{oYM :B JCv)ߨ$;y?=7›?#8聺DjF$Iyေ13$e,K{FUP%IcnKDR9@Qبa={rl縉@(ju}"6a@  g>(h%gE@G(9_l *݋ p\9iV,s8K/qP4L (2kttnR^"cWj&I9N}lll2NɈ캮ekcIuBQB8 z2Ddf#Eq%~Wp3ƚ8 (z`<hg."Zd\$~s\R) '1f* $ollTΝʕ-*DX,g.]zz3`XǛt]D c\nnn6afiӦy&%},GbrSˉh^!#cd$}ǎQD\-Dd5)E~8x(W_2\BD -D"1I-9oy8:]~J0^EčD4T)4 jvd`0x""-:u6{"h[Nzk8?YE|@Dk0Zouww- -LK\#"z5`YIj=y1g( tIj1ebf꺾"xTUիBٲen/JR{zzZz6vњb4!YY8/RTB"z`o^̏~GG{bbb9_7%I{{t:} "~AD4M;ZNdYs7rs/H&\i>Ŝ>"*THq۪UvVrwfe{pk"?cXD"p-pfٔp8, 7No%p(?Q-9& "ۤg' .3 !'啈.$}DM,OD_S4 EnwvvQcj {Oү 4 "AӴJm,VՆa$R܈]ꭜ$X,vR XXU7h10>/DDlxW4^u_u-貣>QJ!Pk@~&zVƾO6*IENDB`ukui-screensaver/KylinNM/res/w/wifi-none.png0000644000175000017500000000231514205074704017756 0ustar fengfengPNG  IHDR00WIDAThCS[EޛB !-K;:NtM[}|Sǿ":SE(S#2U:h{w`hܽi a (}{rP!q)pri; :+UN![DM4<4. `1h )8~Y&0x@kQ`t%XlZYx!@J ȇb1S1{/u-9K`!Ң5BVN- ?YHO+̕ Hz$}Sj{;\4俺R"r# d ;Kj| kEHlR@Ȣ=8qU0O 7e-e$Fp&iAMx9 ћ7Jx[HE@?$*[D \ kM 91vIϽABi{S& AbIcԬe:O@z[g*Ju',hUWk;C@L]A`(P&ᯗ̕r(@´My瑗6Hs3 Z[QI'UEvog y6hQ)uHlj_;bnG^8?7Y;gXWTo 1F: K#BD_k䦵Oeu_@罚\\**6Ew1!^RjSts drkT6 U؃f3ܓѓ7TE90);u\षq"^n(S1ojbf!smGU+I5^h8IENDB`ukui-screensaver/KylinNM/res/w/wifi-high-pwd-off.png0000644000175000017500000000340314205074704021275 0ustar fengfengPNG  IHDR00WIDAThCX]lW>׋vh Q! $skA#pb;ٹ}%J+D TE*pJJBk?{бvWzvD,;sιw~pآ-Ǔqu̲,K&#bͲm۵D-b_W뺢\.QZȊ 5"Vuy~~|yEUf B{qHkmw 1uu+GPm٧Nmf"J,%6$dvc#]&*+BӧOB [Tmȋ)"zSZV*򗗗:JYװ~/?̆B?\]iqv#(AědÇ7UΝ.]/2<ةpcfK:q nYODi.8Dydfff1 !BeYͺkv`KKK@P!mrճg€_YY}Bǎ[ =rH,J= o6H =(=Nɶ7W=[m}̙'CxF(_FċuorDNc!b:BZ'DxX,eZ"hWTiiC ;|ܱԵFzG -DbWY(dF&V&yLOoLOO_ k\!D5N @DLr'Ӧ{D"NNNL7:F@J@DI6EGMDOD|. "Ž|B-JmӯS<H UNyR'G!iN{}6q>`YBX.\RDuJTjD@w !Gۑذ rZ.")7ͮZ6u)t@.{\k"w_,DRS `LfPNѧm֫_"@!#yxkW\*0%<{ LDqL)548(4VJgk2W1?.m;sԩ"O4d{{{N8q3;::jz=lT*mpk}Jb qn.T*nJ٥T*=|}Eչ'R|VI"zT)5KH)_yv@>jO[SCJ+u@W-P+q.#@kwKaw p_߱8a)tOG:|=R(:RJ>MXL&~X,^)ԩm4JKYD|M @CDG/޵D)l;Eu@TO-=+^䫦IENDB`ukui-screensaver/KylinNM/res/w/wifi-low-off.png0000644000175000017500000000320114205074704020363 0ustar fengfengPNG  IHDR00WHIDAThCXoW3;Ch((-ʭT G@^CQUc;D@_@UE-R4PںI &~WMdGڎB^,om;3 l2m+!!٬j۶"I9W~?+ $,.]ZIk-;:r.!DC+61ov.nܸa7[+ӴXӲ~m[n lbwwfl6G,9gvUEQ2 pw*">|zApu@|0+)!sD\a0MBVׁ@@2MagYzU"b. u} H$1>x!'~qpp0{ĉL85=|vjjq&.3˻Bn%IAj8+;|'gn޼Ip]A:;;gu] +++G-uLey~``ѩSL7`d12b#yr֨>ɓ'@ 16 P(tbgM#B]NJsDPt²,lI4| =s\.wHrb́h4O5"I&j)MBsyP.EYGFFZE:+eAXGsxߝ WXˡ`8j96 +WٳgUUU;c} )Tۥ(H,%TBNPlLeeeevm?RԿ$tH?iIǶ闖Fm .2 Cx]9s&D"(ZM9thr+!3Ǐ_kX[3Mg._R-ObTD"3Ot:M-O[3Da{8LmA?w oh+W4Ms}"NR1/fF1!ZKT^mBD>{ԏmG^6lj(ץ `of#Y7>O hLAIENDB`ukui-screensaver/KylinNM/res/w/wifi-none-off.png0000644000175000017500000000220514205074704020524 0ustar fengfengPNG  IHDR00WLIDAThCKo[EϙMةix U#5;,ر"ۉ$D3! k@"(B#OT'F7Νڹ3s9̜~8:" xTh#!jSxޫT* @" l@xPTտ!תZpVH)ÜR*<<< [[[6"69P(\\\FD݋(zD"| uLkQ"JDl0Rz}uu(_@@J;xg.c~C8q;g&i J+UgNԋHc7 _tZBĿ mz,^Nk$'eDd |>]YT*g 9# !~8Wm=*炌BĻ###:{h9&[ Ad2g,ˢ5Y$2rߝ 5וRcDįK~Ӷh4BNO][{5^t:mchNrT96VZ荍1)eh"AmW5z{L&R^ G"klnJ8P(tɴ?{;i"^+˵ŇٍXu!8*P=*=hp2T*oy{`zzf3wB_ #*%vN"a?J}I!&WS؏bWPT*vΕR7~1fjsrdX[B0SRg[Bn[ DB?dWb?fz9$\n:@71POrIIENDB`ukui-screensaver/KylinNM/res/w/wifi-low-pwd-off.png0000644000175000017500000000330714205074704021162 0ustar fengfengPNG  IHDR00WIDAThCXMlUy럸MIiP~J !qT"Sǩ@j{J=Zq !JC*Ҕ`6Ɖ?oгhu6?o͛o~mn?#l[BD###Rm[$I+h*$I,s6i{}hrc 񟈤 F!y۶˅B|;^̺d2v˲z۶my#2;;;5M_@Dzd2}^۶c9`(Jattt:H Juq!c5#*?r/M_wE)"z[%4X̪T*bi"eFͬ@X9iڢ >xDA4-;"|411`us"Q|>e7y":g$IݍଵsUA c Iҿ퓚X3T$r\.u%0B WUEE"!/:N8bgiA>v$M=u^M,ڶ}3-ߋ333eYNض$iWIԉiX4555!"ڽ:L&0| l4MUTz86Xeyzllt:eY""P(4966vHTrn!(7sw*hy/î?l\Ƙ4ꬁQDÿ={vyHm?"54P(vɓ'Xu5DL200D" XW۶#Ecu}'DY&.4pWZ(/z4bD7M3MD [EQ>okSb>u#ͺkz,:*$\TUM<5M Zn5Z/clfiFa<}fH@ Dtfn 1 7?ϯbĻPϝN jv@D|z*d5( }-˲>} PeVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_FIDATxڌ=kTQnb/P"`V!(6vFE{ha0DXPcl<=g=w{sfۨKk` t_"uu:kި#(JNWq5`&m$;YRcQuwRՁTgA';tD:z{juk,?;dlR6+GiR6O9<֨ Bѷ_X&Lt﨧vioI6]6p.n"ODOsiu #u_p&~ /SVV OG_dY,<))fO̅pr x8l֫9#\ riUfz)*=!ޟ嚽; eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_FIDATxڬԻjQo&1XB "X j%/tJ, IB,#1$ʸlvwgƘ}:k_[IA>a|ChȻLt+xX-5<sX$^XIC𩩰EԶ|UN]~?Шr pJ}'*ǫ-jHc:ד1{U.m][6>U8QLicIn'Hs ^IENDB`ukui-screensaver/KylinNM/res/s/conning-a/4.png0000644000175000017500000000615414205074704020100 0ustar fengfengPNG  IHDR pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_FIDATxڌ=/DQAP[hUJQ QV4[눂% CNsdrs=3sf:IUn3̑RڑIY' T㧱OXVPJ\HBv0 xv.B~ZT`nku6`= eIENDB`ukui-screensaver/KylinNM/res/s/conning-a/2.png0000644000175000017500000000614214205074704020073 0ustar fengfengPNG  IHDR pHYs   MiCCPPhotoshop ICC profilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/%ҟ3 cHRMz%u0`:o_FIDATxڬ=kQgw&"n v`6Vb'ZX*#V ~Tb PlF`=6yY.Ł[;s9gHbd9ɓ$Θ` 1Ln,暀VU2.7?p7/_Zn+v\O($wlPxļT濋-S xeSYY]YwLouy/;w{bn8_\§ t߶'%)qUY|ZRUdf8]X8X>b Po'{oB؟UݲUk≝Rr8m~E(yIENDB`ukui-screensaver/KylinNM/res/s/conning-a/5.png0000644000175000017500000000054314205074704020075 0ustar fengfengPNG  IHDR *IDAT8JAK L,$`! y{%J!l|k A+;k  -h!/ sy{!? w3fHоו.Ѐ:Z} ĩ l[o 8.'Vc`j}%# x agM97k&_cЃ:`$rI#IHnYXR/֛:  ݵ*UOǡXf+_L$=J4R^Z8]mpfQ<aaWsWSuKv4]C tK<{gwp|R^( 020%7q $g&LDpe#OUC0✣LHA5`/Pa( 7(]_Dp `׏1L=ngfЭlwJ9K+6,X Xè[/PaN߷R]wR -lxޒ6 "zV~є"*""" CK*;p6?r#IENDB`ukui-screensaver/KylinNM/res/s/conning-s/0000755000175000017500000000000014205074704017243 5ustar fengfengukui-screensaver/KylinNM/res/s/conning-s/8.png0000644000175000017500000000123014205074704020114 0ustar fengfengPNG  IHDR szz pHYs%%IR$JIDATXW-S@}dd2PBP(TU Uiw2`ޖKKMZL\.ٷ{q{'D'gz2%ȗrO^$pjʟ(7l-6Ųwr_ʼ | 6V?,jF.,|ڨ*!EU<1[7>?ȗ`or܏QW~|4C$c29U[}^uAX?efTXJ_?i ϬX1:t_]+0uށKDsKm ʇ7/ l?Pqu]vhrwޞ Pl]:{/XpKQb X ظ X:$2'GT@>E)AAu"`J1䲣EqRk"Zn|+͂}6wW' PvV}½ϸIͷJ'YNum ycqMt-`AҶA1=l-t=մ>6C-v0*|iރ8d iUzN{nq4XdlLMSZî /}Kqt@bBY=ZȪv =O㿠IENDB`ukui-screensaver/KylinNM/res/s/conning-s/9.png0000644000175000017500000000114514205074704020122 0ustar fengfengPNG  IHDR szz pHYs%%IR$IDATX͗S@GeO=xP(TU / S|dLYmgI?HCÛdoovoFq @? 8y5 b]j,5g鬖q^8ۙΒߊ w,leg4YZl/:\ۭ @5oa@ >*m:40??^3m]y~CNW96$f=•p8sc! 8Z6xMvU0T-TdE24;gpYz 3ncޱt4 PV3eJ=eF# P[cmKg_ \ooICO;Sq-7[Xvk.cֹ+xAY:qݗ%PufC빸|vl=RIENDB`ukui-screensaver/KylinNM/res/s/conning-s/6.png0000644000175000017500000000124114205074704020114 0ustar fengfengPNG  IHDR szz pHYs%%IR$SIDATXW-P` }ps03BPSSSS)ۨm-|}ۇGr@Ǐ:I0스!Y{l!e7aZd1CH m/k?Y^AafbCb3Aݩj+&ic$k4 ߣ Q,atk8!`Rou7GL<5+723FIENDB`ukui-screensaver/KylinNM/res/s/conning-s/11.png0000644000175000017500000000120614205074704020171 0ustar fengfengPNG  IHDR szz pHYs%%IR$8IDATXWnA}GUU!_*> BꋧWU AU5Cޒz) Y\nw罝ݝM|Pp G#30Ϧ!pg+gI8X~Y-DӣX ଟ\35^5x4MÃHs`{>mclGZx !XmDYx\^- ;P'AwiT;,\VN7M.#";YR8/4l+x ``I\1 I&lRI z4v^3iu:".2m:ő rCf-2J11>C Υ>%ԒwB/9=R*|Og6S %͹F{@j9EжIg@krgUKǥUkv5!k7 D5U M-ӺzQ zSf"娫فBf}%\"G=WIENDB`ukui-screensaver/KylinNM/res/s/conning-s/12.png0000644000175000017500000000115714205074704020177 0ustar fengfengPNG  IHDR szz pHYs%%IR$!IDATXW-oA$BBP5)(?'avAW-R1A/p0[?^X;sR=8(D ~BK/X iDQu:Tf:)ݴ ( )|{S '|hR nioGn>\$kJv,IknLRkG4Re{qe?nri*6?WSe?s*^wI>s._Zr1J,B$i }=煨"R_|KaZMIENDB`ukui-screensaver/KylinNM/res/s/conning-s/3.png0000644000175000017500000000125614205074704020117 0ustar fengfengPNG  IHDR szz pHYs%%IR$`IDATX͗!p0_i(,\PHJT2򢡱񡡢$($!|6 S׳%}{$mbdIOGT?0p`Th0K!Vn?p` KN~/+T{K΀ϾsՈ\4Jh]VRP6/Yzg7i?C,}ȳtn[qTΙnQQ BsB li8(ȳ[(Mĩ@OHBAv @vo1HͮNKi9?gM8ZrYn< װ_._(xLp{7ucýڒ:1j\:8ȯ2:h؊Q1h @Zf80ɴ%2j04*z). @\0F*Gfk@"I忑N, ,]5}p?Tb4Zԣ%K cӳ!$tư BI(T,e9J[!IŪO)BZ){Fٳu7c. >W%f{9-9Y *svRIENDB`ukui-screensaver/KylinNM/res/s/conning-s/4.png0000644000175000017500000000140114205074704020110 0ustar fengfengPNG  IHDR szz pHYs%%IR$IDATXW!o@ICg ,,Qd4 ,h#CCEAAAA#  iHJYPJj[ jIq'E}{ޡ$v9i2+boGaʀl'T yF UDT87c4 ( 9=cKc\?Mg_~V`~o#MeƸs"}1}Hdh}6է }Ea Ú3"Ƕx>'aȈߒsK= k^S.y$K澿Ck(̰>\s)]_}[ }F̘Gڡ?t-(Džp;Nىhnޭrii[^#~6,$w^KJq7ruz7iI\'H R>Ig _ٻAńRReݜlqۺM;^||]c܎1Gcծs2%MRޫY5 Q\UbeRGiĨlf %Q IENDB`ukui-screensaver/KylinNM/res/s/conning-s/2.png0000644000175000017500000000130514205074704020111 0ustar fengfengPNG  IHDR szz pHYs%%IR$wIDATXW!oPJE(**ȆJ  E% *iPIglKEEE'Ǫ_l/'YMwww~^>wqg`GᓋJ@}0t%K\8*>*Vs9WɵyVDJ3RJOt7Qc٫"v8 + 0> O(u \+pL!ID`0btO\7 $| +#)V1L(H}>wlY<+5}ELsE&"!}firF$41 fA ,Md$~pcPF2xB7!1] SQsJxD݇=v"fiCe4"FK+?=ـ϶0g*wy 䅭䱂U!jZ6X %wرZ GkoT OtqgFxdHCOe)>PI-xq6![Lz#)YAK:I0cM̛_\Oz˕Oefb[-GVHco;+>Ay~vTsG'~_{`C9%gRã5?ݵ.meCE~ ҷh <~}aaHRƎ8jXj@MC%~!>+^SȇtWS&.9Lb/aDQːI5F7 AEC{ N~dVO t8F#ub. Qopo+w1QJNj6#yYH^5˹!ޑz 31~VpIENDB`ukui-screensaver/KylinNM/res/s/conning-s/5.png0000644000175000017500000000142314205074704020115 0ustar fengfengPNG  IHDR szz pHYs%%IR$IDATXWr@}UfZbp3{ݾۻWx!z 8eB jΔGw-T]'8 RJ {=c. t&P7d@koEރ(Q8TJH%ɶRzGuXb@@M<`yZkFoܞī4p1GW%6H$ h6w'+egX+8'$Dfe슓EHbʸhqOsEsx>tL(1+{"1 ~E]Y BE>v%!Zq¾׏Vn.y]ܥ̣Z$nsDr~d[ |,hLTJO*#]Tq.yRhXEK3/z,#vE'VRJUJK$AKuysˤ9hѳ ̐m٫˵g`/\8>U(AlVIENDB`ukui-screensaver/KylinNM/res/s/conning-s/1x/9.png0000644000175000017500000000054214205074704020452 0ustar fengfengPNG  IHDRa pHYs  ~IDAT8/nAƿʊ7`AHՠ8@ UBz*|sf2 h>&I_ɼ - Gc kiM ~wI| GlcKyz|Ts/r EWr7-:Uk] Jn:9?@YSwJ@RaDL9f6sa1d Ex'3ckri8p˔S`;)<+ߖas0u[g%j.x.GPIENDB`ukui-screensaver/KylinNM/res/s/conning-s/1x/6.png0000644000175000017500000000062614205074704020452 0ustar fengfengPNG  IHDRa pHYs  ~HIDAT8SN@}$ĬMs~)0*ԩ\GqsiZTQm0Kgms&iҝy䍏IQ[sԵ\&bf"ke۟0O<H<\"bUY|9䕂x̱ǕrT^Lԯ&n]lw tmq"f ^ļuUo`VĜ8th '@PforΣ@FDԞx0 .hdIkDa&#AY },D2MvWmģZv4;c]ãnU>IENDB`ukui-screensaver/KylinNM/res/s/conning-s/1x/11.png0000644000175000017500000000053114205074704020521 0ustar fengfengPNG  IHDRa pHYs  ~ IDAT81N@EźnWK@E WJ*U*NOBHH+X"FZg猽!w=5ڦH>]<)7F]쒀ȏXg C9D:""W@^mC- U_*p mtˮm|c`h<`dy()7yqUjk"dUm/˹jnU3MnfY* |4]h8IENDB`ukui-screensaver/KylinNM/res/s/conning-s/1x/12.png0000644000175000017500000000055414205074704020527 0ustar fengfengPNG  IHDRa pHYs  ~IDAT8SnA=,qf2/ Uz0(5UU*Qͮ 5I.f&C7ι2~z"#"u~]l"=G%ZE~LLu$-sADie*bG틘9mYߩM];$xD̋94uK!1^Pg~CfU )QSW":f'"I2RLM?bIJוlLE̘gY]1?gytSINIENDB`ukui-screensaver/KylinNM/res/s/conning-s/1x/3.png0000644000175000017500000000055714205074704020452 0ustar fengfengPNG  IHDRa pHYs  ~!IDAT8SN@= Sqd ~P(ZUYuU s{fvIENDB`ukui-screensaver/KylinNM/res/s/conning-s/1x/4.png0000644000175000017500000000062514205074704020447 0ustar fengfengPNG  IHDRa pHYs  ~GIDAT8NP?%ĭkӠfSS5@f,7)&U(rҕflI|==td@[ VټM Tk` $w@ $ N]Y1{$J@y_{gu34y͑R؁1}?*/cK&_O[&v{L v%[ϒ2@6b&M0NN 4r;6QI{:gns @~4k^BbLXWeYEmL8FUYiZu5ڷ};u/vwcIENDB`ukui-screensaver/KylinNM/res/s/conning-s/1x/2.png0000644000175000017500000000057014205074704020444 0ustar fengfengPNG  IHDRa pHYs  ~*IDAT8S-OA}YlUU`P SPrsݤy܅\^yf=XnkPXUYg5 O]pB*WufZ n][[&U9BBG'Ű1F)b!bܓ?1O\Lt,KhN><hN9M&bq}D;܉g瞪dZ$㏈qTS /D 'q*bD+ My)I@\ysz>~7mOIENDB`ukui-screensaver/KylinNM/res/s/conning-s/1x/10.png0000644000175000017500000000054314205074704020523 0ustar fengfengPNG  IHDRa pHYs  ~IDAT8=NP? s.Qt4TTTt4TT8@@OG \#heLd'[^μF1glb L ù9p ܸK]m_Ww[PWe>L\U  aidƙIM E28IyY+00Gށ?-7^Ȯ <.NK+<>U' Vn]ĽO;w-~qkfkN_96:oIV3вg{wdZee E۪aLu}%0q뜯qc>Vc>Y ui1RIENDB`ukui-screensaver/KylinNM/res/s/conning-s/1x/7.png0000644000175000017500000000057514205074704020456 0ustar fengfengPNG  IHDRa pHYs  ~/IDAT8N@E__@ZZg_W$(K)ͦr;w^:ѓ+p]#?{'1. M،nl]uvjtr_nMZ5v"u`puq,|zIDATXW!SA8InEEEI`2L&:$$ $ vdf!|ofcwݷmU1563~</lfHV9-Y@'G+L5/W8JIT@Yy#nr$oTqij|#@d<12(rCGD$Bb6>ʹ9ki$)w2.ϦAPSz]T+vx˸f`EқxDܨ+|̺,I Q0*x\{.]WZۅJXĈkA%3*i.0 Eu6tD‰  O1[ݻ$aN40C%ԟMw 4r IDATx]lU\α  @T;@ hћU&@  IJ@ZDN!%1}O{߮}#=qvf^PIPd~)rD"%(RLKJo& 2=)ÊQ !KǞ>Lurdmti&v} #4 %"u5  XDN% CIŵvԵ$-C[: I"uj|ZjA@ex LRɨdeNfI#4S] tՆN_|6䮆0lHK`J@˒" 5WiL iYY82TiNCFRg5!YNRͥT }L^`bL9g{ Gj#ź5( 6'H+M+6W;TBxQ54UPTLP3 {<>h-.Ikm8AYOU*])S\Kbkފ#hV Nb*/` Ap5 "W%Ž7SS(%^{L )S|hߙh;|F*6QeU]:moE~N C\%J@qbwdƟ؀uiO6 Yo~@&EBt#};خǰ8.$ g0 *65_6ԽXɚSxeIܯb{13G-|v2?0Z/_2$Y!PCB%r5I$Ȳox;mp}FZ><ޏQ>O# K~%AeaIn<)y$!$QEv.n,IqohPKҳ=XqcΌTyD©/Bn:ٖqVXL4Z[Y#&hۀ=+P_K(eǬua:bT--!)&`,edJ Vt02tpg@aBśr6Kzw t^~Wly+}SJBlK'"F~mSl}O@Έi=yit$0Nҷ=ͱ2s A(1P&cx}[AUimDnKɅ+P ~)Q>(Fo$>R~E _Jro) >G`!${ ( I;C#%(C~ .+uEzM̩l!Z syc3i4GIKQ p+2KQlm@,K|DuB&H$99٧(.lL*Ɛ"|#Ԁ o)[V8 k%X'Eߦ؉)w0l9i8ߗ&={%Hԡnp;%3~I.OBI/nDG"FiH)E Y>&sU\(aW`W,*ؽXy_%اp5GI-{Uj* ]]*<L ސ<,7V@gB. {\ B `hd'jJA1_Ɔ";\%%JVCݲ`J:%^cO`}d9ԟ"q6p*'0OJ(gثnz{T3ft̐^,6Au:NJ&ʽ;J.xſl$H2Ao^@p:\ j 鐭ˉm;9w?[Q%@")c+B] ]Xgek]%'V*%o"P*\sՊ/ew-DZI a IDATx]iSU>}StMMeAkԠ(L4bQ j&F?FĨKH2t:{xߥ鴝מޛ$_^f=߹眻H$Q (* V K Х xJ b Uel{3 "R W/Іk% K'^Z3S?+|Md(=5#^'{pO8*9IuHMo*v.&~Ի!%8w-|JK%~ %dJM nK]NE@)tYe($!$EN5e=guG` hԭP?O!}3fR Vc u4g:ƒ$ϥ`_`@F9NVUq0QdgޭЈ5_mGyw`g ^[ЖGôջ(v9- o&vBn"d~yµ 7A*`{UbG)L!ScUpC 2jf(BeD]X?^ohAO ud/+{Ly= FX@Y) ^WF3<|{j3?K bEnk! )?Ba Bݷٙxs)lW_V@m08W6IZe|9P~d\XnPi h.}+ dmg htD0[ BǑ01d6&}|r I#FLgx]P) H~pej҂~t}#}e7_@4Mz ZJK ; ;N%&( [ ˏ E% cҺR}$֯)@{BatPCkKz~G4P\gGOlsMۼץ㢐& t &+U#!FMǔkX ~s|DĪ0懤H~@N;WqIEp*ً#L6A,iidOKH$SЅwaX6d6-gR3RnkوR3Pa39P;EȅP><=uA׵H g[* D7cJc\R. )}3"3K[T^,W(\p MMHkL*g])㊔Á8v8W&d,U]*r4J[<~. E|>!-@U o {p F馤9Sf njD*e4Bam0\O7G1x$s 'Iz{GγAȘ<]#7x/\: ;%;*D$]$Ao`wXe#l@ :F{:uTL+S/T@>Jׁ)s *WI/DYyv.xsu-T"JLbZB$HQo8ShVJ794n~V~re2J9X[w:ՠL |O5Vq;JKEnHUS2<]T/i䱗yDžl]$@"%oԂ/^*}ADЧs:b{g Rz\Q1EU #ao@ӈbL;T"PFn:~D6}/!^s:陓.pS1Jn mxL1g+z_'(Y8wa#.&/|IENDB`ukui-screensaver/KylinNM/res/s/conning-b/6.png0000644000175000017500000000665014205074704020104 0ustar fengfengPNG  IHDR``w8tEXtSoftwareAdobe ImageReadyqe<iTXtXML:com.adobe.xmp e& IDATx]TU3; ̂v{ŎDcODh%j{F &K-; 2;=0}ݹɟݙr{w߻流Ţx*)IQ#H"Q T$|ДG@,^O!DA@u|mѮXΞүh x҇z%žDZtI+M0F2IDO/EP -"' X$Pz;z"}[?}"uDm}-aA= K姥 Lҟ$#6`[+'ߤȞ"rT~"s{b򻂏ZCZ̆_*m$dCMOo:ԛ&ibb=+ݓȰ(hQyxvC凑ba>AnPΧɞat\Zm$>S̕ A6Xb xU XMxR9G[X{𓊯HŸݥ+2OB Vrh-߳QsR{c%?x])דxmSኣ?*UTr쥘2<}08Q1'ܫx1 s9RYP9t3$N!IQKZw $򃊫.V&t+o8JSܧxJAcل ݍ=eki$3e^^P6G܆i* *1."#[(f$=󥾠AL9hQf_xݱMލ$Ɩy9] Lc-Qt(fmGGFbp9J@$°^J*J%*vFi*GeiOv`5 (SlD?hMsNŨ O L͌22\.+% m|`[oe[ z۠exlt$c%pY_JSu 5(r-;=Mt!2?)Ff "ì@6$ e8| K2!SO)04ͩq_S|-ɑC7 3q|^ z Bg_R VABL Byח UOT^q_+?w~.ɕ4::-6`C/&O<jE&ÑpjOpG<_/xQVX,m`HTieY̕2Fec @zH7ԝCkmzɶi$fc Ә3^E+0zu]WFۏ߬]%9 >/X Uv % \Q_'l/ycO1ښwF- @aDRsWŚ̐Ͳm[ T0_;aTC?Қ,xD> aЕ$J8tݙ|$Io(>R~E6XY'D:%\Fyu:TH/BPlljUr/)>4 W Q8cL a]'U3#`h vu{oa'V?Ŵ-O!Jtjp苠h~c#{7B~֡ $ ȮwpͲ2bxj&D{;Q2Bb@FK)rlp[> PG&jv=ml8Sؗ$`%T;09M>?ŖKL:f%آ knR[atXލUwz0{(Ps23W~hSV[h<=(ys1aD\I[@\oَs| @kP>{Y߇4aIn4{sL^.J_", z6TJ *`v*E句b0}K{3YY&nW#M, RSbMEF"fLYu=jt*v&߷,k9Y=rxs~?q>-qB_hSľɖ(isFI 4=ՅfNHٮ8\3g0rMIt]hfz/枪9Nn5֏(!-Z)~ݙ?tY]aKIWT}_=mRņTBhQ9ioPVJ s뵦¨*^ħX^cJEnƫ k^ey.۫ylc$ o1#GS1 $*>Oś& I)Ws]"޴ኀI7-~)N㒀RG,W+˩tq? :vr }q IDATx]gU>؅T[, 5co-E݈F(ј؍c,ذP)D&|-ι3;'o7f~{L>JFѝ)dHh^EQGA31"ZNqYQK4xޓ(s|mQt)z(*36g% Ùi6P3tI&v/#$ u"εg~ghzɂ8~$3 m؎:L2s|s`[߰:! 8YZTE2"#4d QГ%O\풀 F:4$n!m~*5jBVva_9*%s.`Ӟhx؅0U$kO:O]Ǖlc0ii"~p ((vUS Wa{iԀd{yLz n+}x%$(J&L@9< ϙS1h_{igr~^)VV,U-+Z#'IKueYk ƠO /ќmА1w;PA~^A&ʿ]iqw_psC~xE3m?g u !` 8+ŦNgD CZ5S@ ]a/gFJn5 .,jX4$nԂAbtlA(BLϞ$$@9%"{/Q DEϘ`UMHq3VKIӹmW3\-19*H->2 rq]P>~omxN}sny#=xH&ˆ @( ΢$GDTagaxFhq9ݛ\LyͰRg$4FzW3RPPF»2Lnm.JGν wNnݠzO46#^ω)^%^eG[Dm҃O! 0G+^v 1o ?MzIYPP%=3.5ck&ޮ47b"6!b_3px CȄdu{ ܾ0*u_*(C%^tsuI#F-hLjGYQ~X$XDe(a-a8c5O4u#SoرՐ psYI*#HN1*F\3h]K!r,T\+ʎH κt4 V?7H..-GB<؏LJzxw1v?ûqzz|}bz|}'a&) |/%}U :EnI_e1~^扚z< B: ~_ Y' ysPID._ρ7k^&n x!Ǽw x &qtƑK uطA+5t;x" ?.s|t5b[ #rLskXlcvdHS *O4Pϱܡb hoxIENDB`ukui-screensaver/KylinNM/res/s/conning-b/12.png0000644000175000017500000000661114205074704020156 0ustar fengfengPNG  IHDR``w8tEXtSoftwareAdobe ImageReadyqe<iTXtXML:com.adobe.xmp i IDATx]iE~3;{.x⁚(GL0&F? *JLD㭉WTJ4T"xTT/݅evm64]ݳ/U;%RTU"A䉜YEb Mň(Үh#r5Rzu^ a#eK@3jȗ}L 0I*Mz##$ D g~9V: Xr(9lG&)RJplaaPC姥g L&$ϕT~Oԡ3Wo(!OS<3/Eٟ6{%ŏu WB7sHVA1l~(b_튷-qbbbW¢(|A!uE"rF-oPk-1i~W\Xla\e n|cv{"P>Lge#C.ZH[ .!fTb2hMJ7I|L˽\ Fb)#|. A$p՗![=ɠ@\MG9CF'36j\ݧ=uSmŲZWf08c" qj$q|oCI3Ow@3T)8u|c ?x]]NUN;u1F-l&jB]i.5diA~bI/XLᑊ_~#)I`FYM] A&p:-v= g/e<= )NĖtU=8Oqv( OxB_au[nћ@%)cߧx@b]hj`Z{*T>E." y"fNS&I@Xc`PΠ}MԚc*N]wф}"LGiL}=C |iK460|2ay~Kq8;,'EmXBV2 l#\ xfezS%NFI4[15%\qOfMTEsirajY#[!`hF3 2!M10A ˟sGs&!,.LC054Ay$~wa!5?RE=GPZʐ('&iOfa M_+w0#Pr+u,Qqշ" g øŸGF'%g|ߌO}6/pp ;>FO3QC۪k/\SGËZd` c=a?9!t4.=Q*.F,(UKIuW'ϵ0nlưQ~wcHsqKSmEKpvl*MT؂}9q n,7x R3;|Š~.a78š-ݣGGSp"A < e&K([ŒG[$q|m<ͫM6}WP>A] "O ڃ:ҁtQh]ٲGش~MXԴr?MDsQ#@lP%dפG;ĠFs f) y )A en0@P21/ sA <%;$%jliKhcE2ޒNEMs+_\Nn}~3N{4agv{RS EYփܨ*nħpN$r"nHU$V2Y3^扚:< Bu֗7:{Ddxcli\EPùJnR ptxo`iE16 (t ba~e3Qk,Nj|"(jf*KITav]ş'rd9X6`NVIENDB`ukui-screensaver/KylinNM/res/s/conning-b/3.png0000644000175000017500000000661714205074704020104 0ustar fengfengPNG  IHDR``w8tEXtSoftwareAdobe ImageReadyqe<iTXtXML:com.adobe.xmp X# IDATx]ilTU>:L,e*. D[ .(FMĨ?DM&$j\Q n%ƨ(AQ)Lg_ؖ9I̴yoweJT2C:Bb.]D*h&E@D DFaDAFA3eP0Ԡi GRM3ƙQH`3uA`sV8Mz##S SЪ9i:$ $UQW FPJpcq|?A@dp LR3H1R 6)q&t&A0*Kι#n7)|r! 3k_MJ@6HBN ܫ9& 3HC͸f=rdU.Ԓ!YU&fS8e/S1'N'^l?$~ĠCQo"h_5 t5N&q t=`I-L 85.Lj dƚ4T荀 bId &/z-5Xϑo`6f,2/ OBO',g*T+CvcWįoZH{p"?<_ 6Xfmwwdx^@NEx-!3"MKJ#Ikop:KtqDLj\L[8JEtVe"0nfu$9,-!)^`/9'-E,My= E!?_PIP*F/`cxx-XDXm~Nw̲6F69Xv\m0?D3YPf$/DWsUV8ȋH.ڒ? w3rP.0wي '+DJ1zR=$'=̌{2 &h跈7r!qz26$ٞ(&kdd7 ٗS{.c$|l^cK61SMu AY/ȷM@& %G̴Eʤg W rŋ@1ݟLXLաJ׀3A$ 3au $&[o3rIEJY=ˤ UX_֙4 K6J ?9mgtzsq_fN]+/y0 6;||V%.v9HE]Նv&FsUer߲VRr2I irQZ,wAZ4=%:zotCB%TJZC7\0GnZ9XQU;5 X鎆,At1!+h5u ?[CL 9H8(HU$Nx9GlϹݨt.M`^sĨΥn*^g&ou]/Lu APP"o<@n!EK yJ BDlWK˅?c׺Nܮ US:my4L2Lf& rZ Z?<(~+86B3.h f,8Tdn384FԶY,b?m8<,t-"q83cxHtVL;YBjRwAYe0a3DGmԖ;b,6āQ os^X0/EŶ?,hZAasfhFnwD|Aqz% RnĚ!kseU)bgOilz>jU &mlEE B={)^ G.84MU( Xs( `zGL,`#U}Xn38?oĖo?zfpߘUSyHPQx)s--Qgm_P)hBSFIa;_b u*u5EcgP#j|\Hr6E_ǬⴍDUN5$n G|U6}> 2F-5|OS5T*z Z IDATx]iU=XX.JP &HL(#j^(#H ` \* }UavwvMT{vf{^zCX|*!F.È0.B#FC>"@DtRϨ8J/-d0jSB BB5]ZzyIDψu%3 I:^hĮ# Ht"Ps텖Dz!IqABWQ~Eu: QזJ7>߰?tԽDLR9bP<'$P  .18TTVYǃ>ܩ`̬ް D-]ZP3sHtI7njj=G^Z&$:K b~;q``C+87z,c_a=G:iI[?x)9!K06xݟQܜiR 硥iK)c93-(r8uC{ǐ)C` =iX $|,[-孥+"~҄aLB03b,E#OAoŸ9ΩE_2`: -vŤl`X˜eyYVoNhL FZ!(/BC8nHB%cNF@JNbp!:Kq.YfQDNf107ES<1q9"!3n/ =(K9/<;O1^E˘m^3A,lP\췴txY +8`:RYQ8T⨟甯W 2Aa /mUOh٪^~qg\|| '8_m't%^`mgp>Ow?'unWI>_bu,Ȥ| e$~ⵢFaWG\ϸ ;kόʹ<[@g_`lx͏c9I2?WnG(j5Ψ! Dz+VđMgB?IOVl0.49>7=n 7p>C:H\ppAd0+w_ $@߈d$ GiEJs-S~L-?&XP!`^hwRp&vz"%`7ZfA  4"Ds閐" 4 Q VBUo 1h) j1y&'t$%2F4 8LQ $'@+B ~U5C% Up(,$@t] Q8 w&ZQN8/'IKZ&R^ 1)_fo`RC4 Y㌀F#QQ+zB8*iq"`$~dcXy*p-aRôM1SlR7:.v!9K.[%vN7qZ"N84Y*TcKWJ'(^"OSO*^m,ʖ ST_0‡H%Gz:R~NGkG|H@LLѵ{LZvR" bܐAZQrRM=@{Dx:f}BZ.:@|m.?S$IZ9 ג=& qS"/&9"=X"a!9˕d#F* |Dtcz +tdZRXTb˂p+Ȇl5@nBiߒSj*{=wdT]`WS2o2na܌Ϥ:ivkD Y<ap0ZdM.d0)wsGzS BeVkjr$p7Nr0YhWGH{wݾς 9)10ɤseS JOߓ32tزIM{Y& 9Uh1^0u F8Nr\ pd-2*Xg,jcvh2'}3l!g7.Nv3kxv z[W}ͧP['=2_0Kh$C/{>7Hoʨ/gwIO]P;9.Te<$8 Yv(TIᕀSsV~wU_Mʤ>*=f'#2}['$(W2<]=)C䳇y&l3H oe(im F@D$79Ymoʮ)\+B-.x*ފbl ?WkZC>u\k)s8SU0SPzşБq`tm `O:4e7AtX`|VIIENDB`ukui-screensaver/KylinNM/res/s/conning-b/2.png0000644000175000017500000000660314205074704020076 0ustar fengfengPNG  IHDR``w8tEXtSoftwareAdobe ImageReadyqe<iTXtXML:com.adobe.xmp x-5 IDATx] lTU3R +bԈB%nF$Kc&jBQcqIFq hE`ގϷCig794}3w|>/1bQ)dHhUѦh!bE31"ZAsҬh"SIL;d4(S*A@B=_-j'71M@%]hׇГI{ZK{(`\7s u(IO;lC&jRG0'X6#~rN~V@%"}?L:r2M MQ0?%O*z:t߽ zC@%u~*ʚRwBn1u~1hU)s)jz;jKFV#N-&X+:Q1 z3Lt7>#?Ian=0; *)GqU8~B%K e b@BwBTpE%(s _+Sz"KG!(YyMX;\bM?-s*w{(: HTCRZ76"հ<š7V**^K7 ;G*TLPUbՔ(]*" Bŕq zSx }wS#{6|OZ;*VՉ _xXX))N/5$w=m "?HqbFV|12Eq٥kFa pG]%o;9H)銷Z.ԏ0ޣ@*ŗEwI\ qd t]Q/h}:A ]Ǭ :8Z~}\O~s(ppv" +ӵCzHť=Mx€2Ǖ zA)A k sxIKŌz p*tt\Y^T";zbOq**Ȫ4;iÌbFN>Wjh"Ŀ%| Sd1HVlnWOoPR+MaEdJFq>*j w]4hloHFE S)h0H.aK2G 8Z0~%^NwtB2Ym6JrpTg1%gL q4ZC WwKsU櫠! 0ou1j'71?YFXİ)s /c8QEĻtˑѵJE7K k2ߊw_&[wua|N댘ZI:AyմarPD@DVN$xwX1ѸbŻ;N쫺` r6C+mƄاĻcrxwCtVpҶ> .W>rD=!ޝѨe_~.TO$F]=.+dP;7xN* ] ; 9\WOMckq;EY:+nNϠw_u0.E2CV2UWI.F{6bIckP qjg[T5kV[ mFC??$-yWRtH:ƓC P@B#$ᜀUN;\ڂV!!՜HnAmՑyE: ]2$]\?+v5"6l0b`m <9uyڅq !ҤBV@THG$J+'5lBېy:q"xLz8*.wI@fJtT;4nqmEM@TAVNz"q"+Br>@F:rP~[Z[>[` sQEIENDB`ukui-screensaver/KylinNM/res/s/conning-b/10.png0000644000175000017500000000663314205074704020160 0ustar fengfengPNG  IHDR``w8tEXtSoftwareAdobe ImageReadyqe<iTXtXML:com.adobe.xmp g IDATx]WlUެc'q -PBD" >(D/BB @B h5 jK@(!Aĉ];]aΰÒػ3o{o)w+T*d6EN C@*D9bHpE3y*2\O?SuM,*ދ!HT\؏-Mœ(vAs Sܜd/m !(aPu Ҵݠg0g4a) TM4A+Q|2f&{v-S~ Zmm*k2E$/c+[ݭO(DQ>>jj>_^RZnΠe bI@9,iO&3QK@VlϦz\.ē7D)y꼜 ;, :n(yHenBk2t)V*EY㚀Ba t P9 8h.1_޷zn8 %Rp# ևg/ے3 [W`CHWvD=/WtZ:KгNrQ*>O  ˮCBWGaDš z+?8pwcRa.9Y pniQ%h &PBOV@:%I ;z@&k"Q] S6'vsH[PSvs+^&4qx%NV[DXllA\_zx`zEq% !øBĴ@Rr}x>`cZatA 8A UѥLt#sLByZXϋ흘'rPY(L$XCReF@6`6C2Lt Mp 8Rr"_c6r/l3cXcǢ+I2Y|W f@BbIw_%ޔ)/Ž!HCѨ@U~R@t_1˯ԟ2k4mPF31.S-r1+v wwIu*4FA Z2R4B8م6hmvB .oXķhd*   IDATx] le~3]wmPA4Q4AT+^ jIG4D##7F bbD A *A@ ]|?vov_e-J(b)(Dl,%$]H((4V`ƀ(^HaBdGq 󽙌 .E@BA&NK^!^ `DnavIa&z%20 gO/BEAj%2' 8 IX{  I?_A[RA"k\bÞB Ե]na='$Kh4A@Bp>kkaUT~k3ה;tYå(o:մzXGB`L5q}0ݑЫBM5ԪUI%課P\S< W&)m4Jxi$\u('^Z*,|@XFaoWEt$;M"X6syu?)4 Bٞ#%,{m3,@tЖ"g+ Arg *!&RN$ρ}ؔ ~uB9,m;#ݠzABOLKl1@H Š3{VPp6Ml""$NMz̿3H+RF*\)xֽJ$.5 ($2)"79*,ϑ@ |Ā_H)\/K CB_ m(U|qK*reSxd^b̉-[P6CE>nT$5&`<^ϣp PtY.BgQ` `΀$# 4*)tMr/pzـb@m[0׍EUZXЏT**FMօ8'g~ K z A&VD^,Ues ؊d oA.,B 1ʤ-l9tv6HIH$x)$Nbo% O?#' 1PRk_H뀔I(]]f|Q!NEYrVty*/WSDb$Yb  Y!U-p[ ?dyH| x=䎸l$ *kU8.Dp 9kOBqZ*\"CR Ld&VkR'g:k\Qro1]Lκ˩W>/Jj2O \pQ+{\# I=nfIn/RQ/*\B>ҝ_+<@l>lj$; WJ?%\VEoTyw+2M!ڸW>aO'ҽL}5$.GEysL AlYƕWt^<nMu #ϣ ^{OAj1g$g=Wve^l01R(nܒVbۂϵ.d1~,K[Ng!w=*MTla2,c(>E݀Cplm?ESJwX#0c];Tgo AU S+8hsqZăߊZ ryc+L?wh2`y~߉<`xn!ۑڙOx4<.5D@Z,=$N]lYOI2dP>fȶ; ca"&9t4bgoQYߡE;G.psm5ԻZőC|*1+-!G&zX _-aq8[̷ YQX Zb "R'xh)GlnIu ~tȈx@b$ =P*<7}cSRnBpm M9ŀJ@@ 6D@&B"KvT Hn@N&'2սv:IENDB`ukui-screensaver/KylinNM/res/s/conning-b/1.png0000644000175000017500000000536014205074704020074 0ustar fengfengPNG  IHDR``w8tEXtSoftwareAdobe ImageReadyqe<iTXtXML:com.adobe.xmp 8 IDATx]O\U?3ᣅ~k t&`jHM5eZRݸ5Ÿ- tc q}_ri3|UUDN@zM$/$aT!!Dy BsJp`BvفT"Jdl'RJ*0 [8v,9S Ŧʨv<ۇLC `~LEPsJX׈4`z$tXm;j`OQgc\l[ lP]`22#Yd U,U8m "҉a+[+Gƿͮf `\FZ3s3py VU/Y#g.m $kp: [pmME|lv-QE=XYc,+8$r \ 5DY1klc%4M@B,~=q(0 gLڳG'[V ^3{BaRVɃDfqt2LQdQj`}R=sr5Ez0]n6dÜ]sW*Gϊ6Q}sYiKXeop"MzcPfTY+ I: tJ延|wattSzHv'L 3(aIVİ2ɧj>ژ-kKF (y"w@>Mό?P^d=Z ʴF)cf?犏ٛ2IENDB`ukui-screensaver/KylinNM/res/s/conning-b/7.png0000644000175000017500000000557614205074704020113 0ustar fengfengPNG  IHDR``w8tEXtSoftwareAdobe ImageReadyqe<iTXtXML:com.adobe.xmp 8IDATx]SE%Rj`*8! wJYe-ZH*9ijg%K\vWh&0?vWjBf߯G)a(EAJ7KJQJIB!uMjRAh!H=%C)zNː{{Ra)E@>|"amK@#2{M2v"F{? TUxMAd2>- : KȜ8z$HY, (_ć%(䱯Oe1Ȃ ﯊ӚL!% w:B罴bډUjڔ; *qWX (#% %.TYYPT3[O&U) DS) jqR"] m`"$eQ?d-t\1,eT|y/ Xx0v&L^q)~H;RbUMɨ~]-rOʺ%Wy,lweF݆6+ AV)]ʏRގX=eӮEI &>@'76+PT1@(,) V"OD))s+#0ngWX8_OJo>H EcA^LU5a@p wF  m14C"U>W&JM+pUݦX@@gWS@&"8M6QNvE# .o?p4l>UrGKJ=>XnW/ж6sGwAB rrpmfpnR.N!pƂTỳñ*5@,3`.;Ls#嫬hgM|êü$TE'c|$ţH_Fb!ڲZ/Y#ߪ6! xS(|v/,p-o#t'9"0W5l0p&^$(ULׯs<4H_X:{iqPcEpkti3 F 8$uG>pgڬnH-5 m]!cgj@[U)px ڂ,q"p`ZE;a&V8ݭý uf7D~t8:9APU 2ʭo wQP0L\= SGWIM!m=c( aTW,gFiVy]&:P>kQ[)&3:bة"bDaIZuО=v6f `N-}D&D3"#6Z6n]>j0MLB 5* :cү){)o!`VpS-AL[I-@ԑ~&f'7`Q6|!|`7R>!17h:~l*7["N&@[E:\O[]`b xmp.did:eaa61c88-d2e6-7f41-bbed-73d1b7cbab27 xmp.did:3D325C9A0A8311E98914C2F2D3A308B3 xmp.iid:95bb0191-f431-ce46-9ca4-78bb214398a0 xmp.iid:d96babfe-a040-214a-bc06-feb643c37b81 adobe:docid:photoshop:9673d7dd-fc51-11e8-a001-be3e9f4db054 saved xmp.iid:95bb0191-f431-ce46-9ca4-78bb214398a0 2018-12-29T09:52:26+08:00 Adobe Photoshop CC 2017 (Windows) / Adobe Photoshop CC 2017 (Windows) 2018-12-10T16:04:16+08:00 2018-12-29T09:52:26+08:00 2018-12-29T09:52:26+08:00 image/png 3 1 720000/10000 720000/10000 2 65535 16 16 cHRMz%u0`:o_FIDATxb?` `1xQ{AֻY @R!3B?;/@Vn[ ?3VB`dtСPDG4h@Pĉϼ0;/]`=J1F!*̹Sv2{ZԧX%/+!YDۏS:!(0I(%*F@*T DӋ[Hl@OsA̙?Z*$ Ƹ_2VҔ 68J \x5c^ S xmp.did:eaa61c88-d2e6-7f41-bbed-73d1b7cbab27 xmp.did:40FFD2E90A8311E984D788ADC169D7FF xmp.iid:13deafe3-547e-5e42-8f4c-8f2b3d3fd3d7 xmp.iid:d96babfe-a040-214a-bc06-feb643c37b81 adobe:docid:photoshop:9673d7dd-fc51-11e8-a001-be3e9f4db054 saved xmp.iid:13deafe3-547e-5e42-8f4c-8f2b3d3fd3d7 2018-12-29T09:52:17+08:00 Adobe Photoshop CC 2017 (Windows) / Adobe Photoshop CC 2017 (Windows) 2018-12-10T16:04:25+08:00 2018-12-29T09:52:17+08:00 2018-12-29T09:52:17+08:00 image/png 3 1 720000/10000 720000/10000 2 65535 16 16 cHRMz%u0`:o_FIDATxb?#`1100 $200f``<105.b%3HITR9ԏz*ɍ ;J20_*\Ρ 0EaxS.Pmc ' &X0ذ7[2rWNn<lѱ P/ V: Z`a!2k<p8(rԙ0`! (ΈS*;xZܓO:xt`akidEh x,Yh[em`RP>O<}<~1OOWޖ(cJ{E5$^E GL )dpKN2q$Fb3'яu &-6b}7vYG|wIENDB`ukui-screensaver/KylinNM/res/s/rescan/6.png0000644000175000017500000003604114205074704017502 0ustar fengfengPNG  IHDRh pHYs  9iTXtXML:com.adobe.xmp xmp.did:eaa61c88-d2e6-7f41-bbed-73d1b7cbab27 xmp.did:36C792430A8311E9BE9BD3B013D354F4 xmp.iid:f80865c5-d93d-9449-8407-5ded44ab354f xmp.iid:d96babfe-a040-214a-bc06-feb643c37b81 adobe:docid:photoshop:9673d7dd-fc51-11e8-a001-be3e9f4db054 saved xmp.iid:f80865c5-d93d-9449-8407-5ded44ab354f 2018-12-29T09:52:48+08:00 Adobe Photoshop CC 2017 (Windows) / Adobe Photoshop CC 2017 (Windows) 2018-12-10T16:04:05+08:00 2018-12-29T09:52:48+08:00 2018-12-29T09:52:48+08:00 image/png 3 1 720000/10000 720000/10000 2 65535 16 16 Y cHRMz%u0`:o_FIDATxb?F(d1200300H300DwA;W8Mָ74I/tȚ`a0XX0%a f*fq}`2Ł Z ij0 "X>tNr{?>#WXhߘOX ȣ-|e裊:UMx|K ELN';x[#7SbsʸA#l>^HIENDB`ukui-screensaver/KylinNM/res/s/rescan/11.png0000644000175000017500000003602714205074704017562 0ustar fengfengPNG  IHDRh pHYs  9iTXtXML:com.adobe.xmp xmp.did:eaa61c88-d2e6-7f41-bbed-73d1b7cbab27 xmp.did:47D532CA0A8311E98A19C7A1ED55446A xmp.iid:900bf612-18ac-1142-9674-2b49a131bec2 xmp.iid:d96babfe-a040-214a-bc06-feb643c37b81 adobe:docid:photoshop:9673d7dd-fc51-11e8-a001-be3e9f4db054 saved xmp.iid:900bf612-18ac-1142-9674-2b49a131bec2 2018-12-29T09:51:54+08:00 Adobe Photoshop CC 2017 (Windows) / Adobe Photoshop CC 2017 (Windows) 2018-12-10T16:04:39+08:00 2018-12-29T09:51:54+08:00 2018-12-29T09:51:54+08:00 image/png 3 1 720000/10000 720000/10000 2 65535 16 16  cHRMz%u0`:o_FIDATxb?;#`d1X~3000200,```4˱ 0% t), pа{DSI^*Ia\α wpf!afeC* %.\رֽ(CHh?FPd!Aa pdflA̰%h.H6S7'yy$0G'@[G|JDRW4%"\jV" b}lQlԚS%/gt`aۄ`E&ALa`xb XEt1.XNwfY?`>ްE(Ztb)b8e0:ا>m_(b)FQ a˿~&xG*h83 /mvIENDB`ukui-screensaver/KylinNM/res/s/rescan/12.png0000644000175000017500000003572414205074704017566 0ustar fengfengPNG  IHDRh pHYs  9iTXtXML:com.adobe.xmp xmp.did:eaa61c88-d2e6-7f41-bbed-73d1b7cbab27 xmp.did:4B40959B0A8311E99E4DE2469BAC3BCF xmp.iid:f211972f-f026-104f-9f04-42d7b1b1a617 xmp.iid:d96babfe-a040-214a-bc06-feb643c37b81 adobe:docid:photoshop:9673d7dd-fc51-11e8-a001-be3e9f4db054 saved xmp.iid:f211972f-f026-104f-9f04-42d7b1b1a617 2018-12-29T09:51:30+08:00 Adobe Photoshop CC 2017 (Windows) / Adobe Photoshop CC 2017 (Windows) 2018-12-10T16:04:44+08:00 2018-12-29T09:51:30+08:00 2018-12-29T09:51:30+08:00 image/png 3 1 720000/10000 720000/10000 2 65535 16 16 e cHRMz%u0`:o_FIDATxb? `193 AֻQ lGR1J3\α !$2 !=]ʎ{$,h7+>T=l @X@CZB[cJ+H IDz7 &U<C W8ݹGl8ýNbOtW{ט眎Q( +Z"6<`% x O#7S<vJpae1?ehUSCܰ `ajɰE-9J &Ec_/x]=N8@,~wC׸8Jz(} IENDB`ukui-screensaver/KylinNM/res/s/rescan/3.png0000644000175000017500000003603714205074704017504 0ustar fengfengPNG  IHDRh pHYs  9iTXtXML:com.adobe.xmp xmp.did:eaa61c88-d2e6-7f41-bbed-73d1b7cbab27 xmp.did:2B06AA9A0A8311E9BD01B7EB82C639A0 xmp.iid:a3333cfd-5484-4246-804e-5c88ce396322 xmp.iid:d96babfe-a040-214a-bc06-feb643c37b81 adobe:docid:photoshop:9673d7dd-fc51-11e8-a001-be3e9f4db054 saved xmp.iid:a3333cfd-5484-4246-804e-5c88ce396322 2018-12-29T09:53:18+08:00 Adobe Photoshop CC 2017 (Windows) / Adobe Photoshop CC 2017 (Windows) 2018-12-10T16:03:48+08:00 2018-12-29T09:53:18+08:00 2018-12-29T09:53:18+08:00 image/png 3 1 720000/10000 720000/10000 2 65535 16 16 f cHRMz%u0`:o_FIDATxb?"#`1200, f``Hg`` 000|d`` P0- \Ρ 0ׄ@u hJ<&n8qaƎ /KVgFLH=:(P\б awE&f\f vrV!bhhk?7,3%0L2?0*eι XţYs<*gu:jp/4h=Lq/PE0m6A"l5 O hX&e.( ̙36tPEF0WC=/s|`T1o]n$yA0wlu'K"+EVq98\Ųx3"P6d%<$x;v IENDB`ukui-screensaver/KylinNM/res/s/rescan/4.png0000644000175000017500000003604514205074704017504 0ustar fengfengPNG  IHDRh pHYs  9iTXtXML:com.adobe.xmp xmp.did:eaa61c88-d2e6-7f41-bbed-73d1b7cbab27 xmp.did:2F8F03970A8311E98631AE1FB8E699EE xmp.iid:eacc68bb-2ba3-e046-a59f-50d8648b0e28 xmp.iid:d96babfe-a040-214a-bc06-feb643c37b81 adobe:docid:photoshop:9673d7dd-fc51-11e8-a001-be3e9f4db054 saved xmp.iid:eacc68bb-2ba3-e046-a59f-50d8648b0e28 2018-12-29T09:53:08+08:00 Adobe Photoshop CC 2017 (Windows) / Adobe Photoshop CC 2017 (Windows) 2018-12-10T16:03:54+08:00 2018-12-29T09:53:08+08:00 2018-12-29T09:53:08+08:00 image/png 3 1 720000/10000 720000/10000 2 65535 16 16 J cHRMz%u0`:o_FIDATxb?#b:M KAAL1C6f 100p000b%C;T000@`Z200200dϱ 7j6U%XQ+K~n~I8pFGB>4,(xTϿ Qϑɨ(?)N$waccʨlb4sx}jWwsg,7ZxGdqp"x8P8 0>aov πGL53_xO)WxBe|$=aD[4Q PGv3pR0MIENDB`ukui-screensaver/KylinNM/res/s/rescan/2.png0000644000175000017500000003603214205074704017476 0ustar fengfengPNG  IHDRh pHYs  9iTXtXML:com.adobe.xmp xmp.did:eaa61c88-d2e6-7f41-bbed-73d1b7cbab27 xmp.did:2787D4220A8311E99F59FE76C5C2B30E xmp.iid:0be02822-72a7-ba42-8d47-a648423add3e xmp.iid:d96babfe-a040-214a-bc06-feb643c37b81 adobe:docid:photoshop:9673d7dd-fc51-11e8-a001-be3e9f4db054 saved xmp.iid:0be02822-72a7-ba42-8d47-a648423add3e 2018-12-29T09:53:27+08:00 Adobe Photoshop CC 2017 (Windows) / Adobe Photoshop CC 2017 (Windows) 2018-12-10T16:00:30+08:00 2018-12-29T09:53:27+08:00 2018-12-29T09:53:27+08:00 image/png 3 1 720000/10000 720000/10000 2 65535 16 16 G>R cHRMz%u0`:o_FIDATxb?$#d1300x200l a``X 000iy ,P` T;0DSE<PX xI<>۝;;Q$}`Ê3 7C;?Ì+Blϡ Aз9Cr ( :  `4ZA6?s\ N8-f BUIQwnXᎶXV7\( c5X{s|9C(: '@  IhTa@x0(,#I ,[ӑ7LoѢ*4|U2bF9stȿGݠ <ްnHI4&=+gPK9B:Fo;{]DuПIENDB`ukui-screensaver/KylinNM/res/s/rescan/10.png0000644000175000017500000003603614205074704017561 0ustar fengfengPNG  IHDRh pHYs  9iTXtXML:com.adobe.xmp xmp.did:eaa61c88-d2e6-7f41-bbed-73d1b7cbab27 xmp.did:445012F60A8311E983D7BF86387D11C7 xmp.iid:cd8966a6-8e66-7347-989e-5d8c83ed07b4 xmp.iid:d96babfe-a040-214a-bc06-feb643c37b81 adobe:docid:photoshop:9673d7dd-fc51-11e8-a001-be3e9f4db054 saved xmp.iid:cd8966a6-8e66-7347-989e-5d8c83ed07b4 2018-12-29T09:52:04+08:00 Adobe Photoshop CC 2017 (Windows) / Adobe Photoshop CC 2017 (Windows) 2018-12-10T16:04:31+08:00 2018-12-29T09:52:04+08:00 2018-12-29T09:52:04+08:00 image/png 3 1 720000/10000 720000/10000 2 65535 16 16 cE_ cHRMz%u0`:o_FIDATxb?#`1100, 100c``(41 04p1= . 'W"b5DǸ\1 0D $ 6S8hؙZKK?^%w=phgKAZcČ Tl- QgE$ DIč,d1'ksfWl "|{"xx9?gid`n6l`QE%~IJ]V`z"!?<Xmys9xdK9&Q1.w^. K}"XW bW`76E r8# e3u:?|G^c;O`F&15AIqޅGìj %LF;l0O<<2rIENDB`ukui-screensaver/KylinNM/res/s/rescan/5.png0000644000175000017500000003602514205074704017503 0ustar fengfengPNG  IHDRh pHYs  9iTXtXML:com.adobe.xmp xmp.did:eaa61c88-d2e6-7f41-bbed-73d1b7cbab27 xmp.did:334B640A0A8311E9B7FA8CF95C228968 xmp.iid:01f85d47-7c05-e346-9f5d-e1b8e47a5e3e xmp.iid:d96babfe-a040-214a-bc06-feb643c37b81 adobe:docid:photoshop:9673d7dd-fc51-11e8-a001-be3e9f4db054 saved xmp.iid:01f85d47-7c05-e346-9f5d-e1b8e47a5e3e 2018-12-29T09:52:59+08:00 Adobe Photoshop CC 2017 (Windows) / Adobe Photoshop CC 2017 (Windows) 2018-12-10T16:03:59+08:00 2018-12-29T09:52:59+08:00 2018-12-29T09:52:59+08:00 image/png 3 1 720000/10000 720000/10000 2 65535 16 16 4 cHRMz%u0`:o_FIDATxb?/#d1100V100x100 a``Hic``hba```p ôc``8T͡ 0 f`l 1AavXČ#D\X xQ\! BQ«vE\.@M6݂ M-h˻˝63?@EUts{41V&>PNf', YsJ8)vآ|<:8M?5+c}Q %IENDB`ukui-screensaver/KylinNM/res/s/rescan/1.png0000644000175000017500000003566114205074704017504 0ustar fengfengPNG  IHDRh pHYs  9iTXtXML:com.adobe.xmp xmp.did:eaa61c88-d2e6-7f41-bbed-73d1b7cbab27 xmp.did:2403A0260A8311E99104E9BF0F8265BA xmp.iid:f30d9ed6-62c1-ab49-a509-e1f5d31aec3e xmp.iid:d96babfe-a040-214a-bc06-feb643c37b81 adobe:docid:photoshop:9673d7dd-fc51-11e8-a001-be3e9f4db054 saved xmp.iid:f30d9ed6-62c1-ab49-a509-e1f5d31aec3e 2018-12-29T09:53:37+08:00 Adobe Photoshop CC 2017 (Windows) / Adobe Photoshop CC 2017 (Windows) 2018-12-10T16:00:25+08:00 2018-12-29T09:53:37+08:00 2018-12-29T09:53:37+08:00 image/png 3 1 720000/10000 720000/10000 2 65535 16 16 3u cHRMz%u0`:o_FsIDATxb? b@9@_A6mc$&k~2€/h _ ÙA @`E2A1 R%RO 9.Ê ;`?Fw9җa C(@)y;GcH}NШC%A$D).2 ^i]Š 8beqNKA/^pQA&!7{Obi\?<AOz0IENDB`ukui-screensaver/KylinNM/res/s/rescan/7.png0000644000175000017500000003564714205074704017516 0ustar fengfengPNG  IHDRh pHYs  9iTXtXML:com.adobe.xmp xmp.did:eaa61c88-d2e6-7f41-bbed-73d1b7cbab27 xmp.did:3A055C320A8311E9A5B6FBCD249A229B xmp.iid:b7833fd5-5af2-8e48-85ea-930ecc35c4eb xmp.iid:d96babfe-a040-214a-bc06-feb643c37b81 adobe:docid:photoshop:9673d7dd-fc51-11e8-a001-be3e9f4db054 saved xmp.iid:b7833fd5-5af2-8e48-85ea-930ecc35c4eb 2018-12-29T09:52:37+08:00 Adobe Photoshop CC 2017 (Windows) / Adobe Photoshop CC 2017 (Windows) 2018-12-10T16:04:10+08:00 2018-12-29T09:52:37+08:00 2018-12-29T09:52:37+08:00 image/png 3 1 720000/10000 720000/10000 2 65535 16 16 Nk cHRMz%u0`:o_FiIDATxb?` `15 _A{a 蠫_?B5{-X\GB t 0 %QDa2A$hƑ^g+P, )V̀2Xwo6]#+1 ` a(S8z <*1ݔ%Oi;%yt?_Xe`o6>d #include #include #define MAX_LEN 2048 #define MAX_PATH 1024 KSimpleNM::KSimpleNM(QObject *parent) : QObject(parent) { runShellProcess = new QProcess(this); connect(runShellProcess, &QProcess::readyRead, this, &KSimpleNM::readProcess); connect(runShellProcess, SIGNAL(finished(int)), this, SLOT(finishedProcess(int))); } //获取有线网络列表数据 void KSimpleNM::execGetLanList() { if (isExecutingGetWifiList) { syslog(LOG_DEBUG, "It is running getting wifi list when getting lan list"); qDebug()<<"debug: it is running getting wifi list when getting lan list"; isUseOldLanSlist = true; } isExecutingGetLanList = true; shellOutput = ""; type = 0; qDebug() << "runShellProcess->start ---1"; runShellProcess->start("nmcli -f type,device,name connection show"); qDebug() << "runShellProcess->start ---2"; } //获取无线网络列表数据 void KSimpleNM::execGetWifiList() { isExecutingGetWifiList = true; shellOutput = ""; type = 1; runShellProcess->start("nmcli -f in-use,signal,security,freq,bssid,ssid,dbus-path device wifi"); } //读取获取到的结果 void KSimpleNM::readProcess() { QString output = runShellProcess->readAll(); shellOutput += output; } //读取完所有列表数据后发信号,将数据发往mainwindow用于显示网络列表 void KSimpleNM::finishedProcess(int msg) { QStringList slist = shellOutput.split("\n"); if (type == 0) { emit getLanListFinished(slist); isExecutingGetLanList = false; } else { emit getWifiListFinished(slist); isExecutingGetWifiList = false; } } ukui-screensaver/KylinNM/src/oneconnform.cpp0000644000175000017500000010672614205074704020147 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include extern int currentActWifiSignalLv; OneConnForm::OneConnForm(QWidget *parent, KylinNM *mainWindow, ConfForm *confForm, KSimpleNM *ksnm) : QWidget(parent), ui(new Ui::OneConnForm) { ui->setupUi(this); ui->btnConnSub->setText(tr("Connect"));//"设置" ui->btnConn->setText(tr("Connect"));//"连接" ui->btnConnPWD->setText(tr("Connect"));//"连接" ui->btnDisConn->setText(tr("Disconnect"));//"断开连接" ui->btnHideConn->setText(tr("Connect"));//"连接" ui->lePassword->setPlaceholderText(tr("Input Password..."));//"输入密码..." ui->lePassword->setContextMenuPolicy(Qt::NoContextMenu); ui->lePassword->setTextMargins(0,0,20,0); ui->lbConned->setAlignment(Qt::AlignLeft); ui->lePassword->setEchoMode(QLineEdit::Normal); ui->btnConnPWD->setEnabled(false); leQssLow = "QLineEdit{border:none;background:transparent;font-size:14px;color:rgba(255,255,255,0.57);font-family:Noto Sans CJK SC;}"; leQssHigh = "QLineEdit{border:none;background:transparent;font-size:14px;color:rgba(255,255,255,0.91);font-family:Noto Sans CJK SC;}"; ui->leInfo_1->setStyleSheet(leQssLow); ui->leInfo_2->setStyleSheet(leQssLow); ui->leInfo_3->setStyleSheet(leQssLow); ui->leInfo_1->setEnabled(false); ui->leInfo_2->setEnabled(false); ui->leInfo_3->setEnabled(false); ui->btnInfo->setStyleSheet("QPushButton{border:none;background:transparent;}"); ui->wbg->setStyleSheet("#wbg{border-radius:8px;background-color:rgba(255,255,255,0);}"); ui->wbg_2->setStyleSheet("#wbg_2{border-radius:8px;background-color:rgba(38, 38, 38, 0.1)}"); ui->wbg_3->setStyleSheet("#wbg_3{border-radius:4px;background-color:rgba(255,255,255,0.1);}"); ui->lbName->setStyleSheet("QLabel{font-size:14px;color:rgba(38,38,38,1);}"); ui->lbConned->setStyleSheet("QLabel{font-size:14px;color:rgba(255,255,255,0.57);}"); ui->lePassword->setStyleSheet("QLineEdit{border:2px solid rgba(47, 179, 232, 1);border-radius:4px;" "background:rgba(255,255,255,1);color:rgba(38, 38, 38, 1);font-size:14px;}"); ui->checkBoxPwd->setStyleSheet("QCheckBox::indicator {width: 18px; height: 9px;}" "QCheckBox::indicator:checked {image: url(:/res/h/show-pwd.png);}" "QCheckBox::indicator:unchecked {image: url(:/res/h/hide-pwd.png);}"); ui->btnConnSub->setStyleSheet("QPushButton{border:0px;border-radius:4px;background-color:rgba(61,107,229,1);color:white;font-size:14px;}" "QPushButton:Hover{border:0px solid rgba(255,255,255,0.2);border-radius:4px;background-color:rgba(107,142,235,1);}" "QPushButton:Pressed{border-radius:4px;background-color:rgba(50,87,202,1);}"); ui->btnConn->setStyleSheet("QPushButton{border:0px;border-radius:4px;background-color:rgba(61,107,229,1);color:white;font-size:14px;}" "QPushButton:Hover{border:0px solid rgba(255,255,255,0.2);border-radius:4px;background-color:rgba(107,142,235,1);}" "QPushButton:Pressed{border-radius:4px;background-color:rgba(50,87,202,1);}"); ui->btnConnPWD->setStyleSheet("QPushButton{border:0px;border-radius:4px;background-color:rgba(47, 179, 232, 1);color:rgba(255, 255, 255, 1);font-size:14px;}" "QPushButton:Hover{border:0px solid rgba(255,255,255,0.2);border-radius:4px;background-color:rgba(70, 193, 243, 1);}" "QPushButton:Pressed{border-radius:4px;background-color:rgba(27, 160, 213, 1);}" "QPushButton:Disabled{border-radius:4px;background-color:rgba(168, 168, 168, 1)}"); ui->btnDisConn->setStyleSheet("#btnDisConn{font-family: NotoSansCJKsc-Regular, NotoSansCJKsc;" "font-weight: 400;color: rgba(38,38,38,0.75);line-height: 20px;font-size:14px;" "border:0px;background-color:rgba(38,38,38,0.1);border-radius:8px;}" "#btnDisConn:Hover{border:0px solid rgba(255,255,255,0.2);border-radius:8px;background-color:rgba(38,38,38,0.2);}" "#btnDisConn:Pressed{border-radius:8px;background-color:rgba(38,38,38,0.06);}");//断开链接按钮 ui->btnInfo_2->setStyleSheet("border:0px;border-radius:8px;border-image:url(:/res/l/pb-network-info.png);"); ui->btnHideConn->setStyleSheet("QPushButton{border:0px;border-radius:4px;background-color:rgba(61,107,229,1);color:white;font-size:14px;}" "QPushButton:Hover{border:0px solid rgba(255,255,255,0.2);border-radius:4px;background-color:rgba(107,142,235,1);}" "QPushButton:Pressed{border-radius:4px;background-color:rgba(50,87,202,1);}"); ui->lbWaiting->setStyleSheet("QLabel{border:0px;border-radius:10px;background-color:rgba(61,107,229,1);}"); ui->lbWaitingIcon->setStyleSheet("QLabel{border:0px;background-color:transparent;}"); ui->autoConn->setStyleSheet("QCheckBox::indicator {width: 16px; height: 16px;}" "QCheckBox::indicator:checked {image: url(:/res/g/checkbox-checked.svg);}" "QCheckBox::indicator:unchecked {image: url(:/res/g/checkbox-unchecked.svg);}"); ui->btnInfo->setCursor(QCursor(Qt::PointingHandCursor)); ui->btnInfo->setFocusPolicy(Qt::NoFocus); ui->checkBoxPwd->setFocusPolicy(Qt::NoFocus); ui->btnConnSub->setFocusPolicy(Qt::NoFocus); ui->btnConn->setFocusPolicy(Qt::NoFocus); ui->btnConnPWD->setFocusPolicy(Qt::NoFocus); ui->btnDisConn->setFocusPolicy(Qt::NoFocus); ui->btnHideConn->setFocusPolicy(Qt::NoFocus); ui->wbg->show(); ui->wbg_2->hide(); ui->wbg_3->hide(); ui->lbName->show(); ui->leInfo_1->hide(); ui->leInfo_2->hide(); ui->leInfo_3->hide(); ui->lePassword->hide(); ui->checkBoxPwd->hide(); ui->checkBoxPwd->setChecked(false); ui->lePassword ->setEchoMode(QLineEdit::Password); ui->btnConnSub->hide(); ui->btnConn->hide(); ui->btnDisConn->hide(); ui->btnConnPWD->hide(); ui->btnHideConn->hide(); ui->line->show(); ui->autoConn->hide(); ui->lbWaiting->hide(); ui->lbWaitingIcon->hide(); ui->btnInfo->hide(); this->mw = mainWindow; this->cf = confForm; this->ks = ksnm; this->isSelected = false; this->isActive = false; this->setAttribute(Qt::WA_Hover,true); this->installEventFilter(this); ui->lePassword->setAttribute(Qt::WA_Hover,true); ui->lePassword->installEventFilter(this); ui->btnInfo->setAttribute(Qt::WA_Hover,true); ui->btnInfo->installEventFilter(this); //m_notify = new NotifySend(); connect(ui->lePassword, SIGNAL(returnPressed()), this, SLOT(on_btnConnPWD_clicked())); ui->btnConn->setShortcut(Qt::Key_Return);//将字母区回车键与登录按钮绑定在一起 this->waitTimer = new QTimer(this); connect(waitTimer, SIGNAL(timeout()), this, SLOT(waitAnimStep())); connect(mw, SIGNAL(waitWifiStop()), this, SLOT(stopWaiting())); connect(ui->btnInfo_2,&QPushButton::clicked,this,&OneConnForm::on_btnInfo_2_clicked); ui->btnInfo_2->hide(); // connect(ui->autoConn,&QCheckBox::toggled,this,&OneConnForm::on_autoConn_toggled); ui->autoConn->setText(tr("Automatically join the network")); // ui->autoConn->setText(tr("自动连接")); ui->lbWaitingIcon->move(316+194*mw->isTabletStyle,20);// YYF tabletStyle();//平板模式PC桌面样式 } void OneConnForm::tabletStyle()//平板桌面模式特有设置 { this->setFixedWidth(414+194*mw->isTabletStyle); ui->wbg->setFixedWidth(414+194*mw->isTabletStyle); ui->wbg_2->setFixedWidth(414+194*mw->isTabletStyle); ui->wbg_3->setFixedWidth(414+194*mw->isTabletStyle); ui->lbName->setFixedWidth(190+194*mw->isTabletStyle); ui->btnInfo->setFixedWidth(230+194*mw->isTabletStyle); ui->leInfo_1->setFixedWidth(230+194*mw->isTabletStyle); ui->leInfo_2->setFixedWidth(230+194*mw->isTabletStyle); ui->leInfo_3->setFixedWidth(230+194*mw->isTabletStyle); ui->lePassword->setFixedWidth(254+172*mw->isTabletStyle); ui->checkBoxPwd->move(286+172*mw->isTabletStyle,75); ui->btnConnPWD->move(318+172*mw->isTabletStyle,56); ui->btnDisConn->move(316+194*mw->isTabletStyle,8 + 18*mw->isTabletStyle); ui->btnInfo_2->move(364+194*mw->isTabletStyle,18); ui->lbName->move(63,18); } OneConnForm::~OneConnForm() { delete ui; } void OneConnForm::mousePressEvent(QMouseEvent *event) { if (event->button() != Qt::LeftButton) { event->ignore(); return; } // emit selectedOneWifiForm(wifiName, H_WIFI_ITEM_BIG_EXTEND); ui->wbg_2->setStyleSheet("#wbg_2{border-radius:8px;background-color:rgba(38,38,38,0.1);}"); } void OneConnForm::mouseReleaseEvent(QMouseEvent *event) { if (event->button() != Qt::LeftButton || !rect().contains(event->pos())) { event->ignore(); return; } if(ui->lePassword->isVisible()){ Q_EMIT selectedOneWifiForm(wifiName, H_WIFI_ITEM_BIG_EXTEND); }else{ if (!this->isTopItem) { if (!is_connecting) { toConnectWirelessNetwork(); } } } ui->wbg_2->setStyleSheet("#wbg_2{border-radius:8px;background-color:rgba(255,255,255,0);}"); } //事件过滤器 bool OneConnForm::eventFilter(QObject *obj, QEvent *event) { if (obj == ui->btnInfo) { if (event->type() == QEvent::HoverEnter) { ui->leInfo_1->setStyleSheet(leQssHigh); ui->leInfo_2->setStyleSheet(leQssHigh); ui->leInfo_3->setStyleSheet(leQssHigh); return true; } else if(event->type() == QEvent::HoverLeave) { ui->leInfo_1->setStyleSheet(leQssLow); ui->leInfo_2->setStyleSheet(leQssLow); ui->leInfo_3->setStyleSheet(leQssLow); return true; } } else if (obj == this) { if(event->type() == QEvent::HoverEnter) { if (!this->isTopItem) { if (!this->isSelected) { //ui->btnConn->show(); ui->wbg->setStyleSheet("#wbg{border-radius:8px;background-color:rgba(38,38,38,0.05);}"); ui->wbg->show(); } } return true; } else if (event->type() == QEvent::HoverLeave) { ui->btnConn->hide(); ui->wbg->setStyleSheet("#wbg{border-radius:8px;background-color:rgba(255,255,255,0);}"); ui->wbg->hide(); return true; } } if (obj == ui->lePassword) { if (event->type() == QEvent::MouseButtonPress) { Q_EMIT onLineEditClicked(); } } return QWidget::eventFilter(obj,event); } void OneConnForm::on_autoConn_toggled(bool val) { // kylin_network_set_autoconnect(wifiName.toLatin1().data(),val); } // 是否当前连接的网络,字体设置不同 void OneConnForm::setAct(bool isAct) { if (isAct) { ui->lbConned->hide(); } else { ui->lbConned->hide(); } ui->lbName->move(63,18); isActive = isAct; } //点击窗口最上面的item时 void OneConnForm::setTopItem(bool isSelected) { if (isSelected) { resize(W_ITEM+194*mw->isTabletStyle, H_ITEM_BIG); ui->wbg_3->show(); ui->leInfo_1->show(); ui->leInfo_2->show(); ui->leInfo_3->show(); this->isSelected = true; } else { resize(W_ITEM+194*mw->isTabletStyle, H_ITEM); ui->lePassword->setText(""); ui->wbg_3->hide(); ui->leInfo_1->hide(); ui->leInfo_2->hide(); ui->leInfo_3->hide(); this->isSelected = false; } ui->wbg->hide(); ui->wbg_2->hide(); ui->lbSignal->show(); ui->lePassword->hide(); ui->checkBoxPwd->hide(); ui->line->hide(); ui->btnConn->hide(); ui->btnConnPWD->hide(); ui->btnHideConn->hide(); ui->btnInfo->show(); if (isConnected) { if (this->isWaiting) { ui->lbName->setStyleSheet("QLabel{font-size:14px;color:rgba(38,38,38,0.45);}"); ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/pb-top-wifi-offline.png);}"); ui->btnDisConn->hide(); // ui->btnInfo_2->hide(); } else { ui->lbName->setStyleSheet("QLabel{font-size:14px;color:rgba(47, 179, 232, 1);}"); setSignalOn(signalStrong,signalHasPw); ui->btnDisConn->show(); // ui->btnInfo_2->show(); } ui->btnInfo_2->hide(); } else { ui->lbName->setStyleSheet("QLabel{font-size:14px;color:rgba(38,38,38,0.45);}"); ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/pb-top-wifi-offline.png);}"); ui->btnDisConn->hide(); ui->btnInfo_2->hide(); } this->isTopItem = true; } // 点击窗口下面的item时 void OneConnForm::setSelected(bool isSelected, bool isCurrName) { if (isSelected) { resize(W_ITEM+194*mw->isTabletStyle, H_ITEM_BIG); ui->line->move(X_LINE_BIG_EXTEND, Y_LINE_BIG_EXTEND); ui->wbg->hide(); ui->wbg_2->hide(); ui->wbg_3->show(); ui->leInfo_1->show(); ui->leInfo_2->show(); ui->leInfo_3->show(); ui->btnConn->hide(); ui->btnConnSub->show(); this->isSelected = true; } else { resize(W_ITEM+194*mw->isTabletStyle, H_ITEM); ui->lePassword->setStyleSheet("QLineEdit{border:2px solid rgba(47, 179, 232, 1);border-radius:4px;" "background:rgba(255,255,255,1);color:rgba(38, 38, 38, 1);font-size:14px;}"); ui->line->move(X_LINE, Y_LINE); ui->wbg->show(); ui->wbg_2->hide(); ui->wbg_3->hide(); ui->leInfo_1->hide(); ui->leInfo_2->hide(); ui->leInfo_3->hide(); if (isCurrName) { //ui->btnConn->show(); } else { ui->btnConn->hide(); } ui->btnConnSub->hide(); this->isSelected = false; } ui->lePassword->hide(); ui->checkBoxPwd->hide(); ui->btnConnPWD->hide(); ui->lbSignal->show(); ui->btnDisConn->hide(); ui->btnHideConn->hide(); ui->btnInfo->hide(); this->isTopItem = false; } // 点击连接隐藏wifi的item时 void OneConnForm::setHideItem(bool isHideItem, bool isShowHideBtn) { if (isHideItem) { ui->lbName->move(14, 30); ui->wbg->hide(); ui->btnConn->hide(); } else { ui->lbName->move(62, 18); ui->wbg->show(); //ui->btnConn->show(); } if (isShowHideBtn) { ui->btnHideConn->show(); } else{ ui->btnHideConn->hide(); } } void OneConnForm::setConnedString(bool showLable, QString str, QString str1) { if (!showLable) { ui->lbConned->setText(str1); ui->lbConned->hide(); } else { ui->lbConned->setText(str); } ui->lbName->move(63, 18); } void OneConnForm::setName(QString name) { ui->lbName->setText(name); wifiName = name; } void OneConnForm::setSpecialName(QString name) { ui->lbName->setText(tr("Connect to Hidden Wi-Fi Network")); //连接到隐藏的 Wi-Fi 网络 wifiName = name; } QString OneConnForm::getName() { return ui->lbName->text(); } void OneConnForm::setRate(QString rate) { // QString txt(tr("Rate"));//"速率" // this->setToolTip("  " + txt + ": " + rate + "  "); // this->setToolTip(txt + ":" + rate); } void OneConnForm::setLine(bool isShow) { if (isShow) { ui->line->show(); } else { ui->line->hide(); } } void OneConnForm::setSignalOn(QString lv, QString secu) { int signal = lv.toInt(); if (secu == "--" || secu == "") { hasPwd = false; } else { hasPwd = true; } if (signal > 75) { if (hasPwd) { ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/wifi-full-pwd.png);}"); } else { ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/wifi-full.png);}"); } signalLv = 1; } if (signal > 55 && signal <= 75) { if (hasPwd) { ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/wifi-high-pwd.png);}"); } else { ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/wifi-high.png);}"); } signalLv = 2; } if (signal > 35 && signal <= 55) { if (hasPwd) { ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/wifi-medium-pwd.png);}"); } else { ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/wifi-medium.png);}"); } signalLv = 3; } if (signal > 15 && signal <= 35) { if (hasPwd) { ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/wifi-low-pwd.png);}"); } else { ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/wifi-low.png);}"); } signalLv = 4; } if (signal <= 15) { if (hasPwd) { ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/wifi-none-pwd.png);}"); } else { ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/wifi-none.png);}"); } signalLv = 4; } } void OneConnForm::setSignal(QString lv, QString secu) { signalStrong=lv; signalHasPw=secu; int signal = lv.toInt(); if (secu == "--" || secu == "") { hasPwd = false; } else { hasPwd = true; } if (signal > 75) { if (hasPwd) { ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/wifi-full-pwd-off.png);}"); } else { ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/wifi-full-off.png);}"); } signalLv = 1; } if (signal > 55 && signal <= 75) { if (hasPwd) { ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/wifi-high-pwd-off.png);}"); } else { ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/wifi-high-off.png);}"); } signalLv = 2; } if (signal > 35 && signal <= 55) { if (hasPwd) { ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/wifi-medium-pwd-off.png);}"); } else { ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/wifi-medium-off.png);}"); } signalLv = 3; } if (signal > 15 && signal <= 35) { if (hasPwd) { ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/wifi-low-pwd-off.png);}"); } else { ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/wifi-low-off.png);}"); } signalLv = 4; } if (signal <= 15) { if (hasPwd) { ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/wifi-none-pwd-off.png);}"); } else { ui->lbSignal->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/w/wifi-none-off.png);}"); } signalLv = 4; } } void OneConnForm::setWifiInfo(QString str1, QString str2, QString str3) { if (str1 == "--" || str1 == ""){ str1 = tr("None"); }; QString strSecurity = QString(tr("WiFi Security:")); QString strSignal = QString(tr("Signal:")); QString strMAC = QString(tr("MAC:")); ui->leInfo_1->setText(strSecurity + str1); ui->leInfo_2->setText(strSignal + str2); ui->leInfo_3->setText(strMAC + str3); } void OneConnForm::slotConnWifi() { //mw->startLoading(); this->startWaiting(true); emit sigConnWifi(ui->lbName->text()); } void OneConnForm::slotConnWifiPWD() { //mw->startLoading(); this->startWaiting(true); emit sigConnWifiPWD(ui->lbName->text(), ui->lePassword->text()); } //点击后断开wifi网络 void OneConnForm::on_btnDisConn_clicked() { syslog(LOG_DEBUG, "DisConnect button about wifi net is clicked, current wifi name is %s .", ui->lbName->text().toUtf8().data()); qDebug()<<"DisConnect button about wifi net is clicked, current wifi name is "<lbName->text(); this->startWaiting(false); mw->is_stop_check_net_state = 1; mw->on_btnHotspotState(); QString name = ui->lbName->text(); kylin_network_set_con_down(name.replace("\"","\\\"").toUtf8().data()); disconnect(this, SIGNAL(selectedOneWifiForm(QString,int)), mw, SLOT(oneWifiFormSelected(QString,int))); emit disconnActiveWifi(); } //点击列表item扩展时会出现该按钮 用于连接网络 void OneConnForm::on_btnConnSub_clicked() { syslog(LOG_DEBUG, "A button named on_btnConnSub about wifi net is clicked."); qDebug()<<"A button named on_btnConnSub about wifi net is clicked."; toConnectWirelessNetwork(); } //无需密码的wifi连接 void OneConnForm::on_btnConn_clicked() { // syslog(LOG_DEBUG, "A button named btnConn about wifi net is clicked."); // qDebug()<<"A button named btnConn about wifi net is clicked."; // toConnectWirelessNetwork(); on_btnInfo_clicked(); } void OneConnForm::toConnectWirelessNetwork() { if (ui->lbConned->text() == "--" || ui->lbConned->text() == " ") { if (!isWifiConfExist(ui->lbName->text())) { //没有配置文件,使用有密码的wifi连接 on_btnConnPWD_clicked(); return; } } mw->is_stop_check_net_state = 1; QThread *t = new QThread(); BackThread *bt = new BackThread(); bt->moveToThread(t); connect(t, SIGNAL(finished()), t, SLOT(deleteLater())); connect(t, SIGNAL(started()), this, SLOT(slotConnWifi())); connect(this, SIGNAL(sigConnWifi(QString)), bt, SLOT(execConnWifi(QString))); connect(bt, &BackThread::connDone, this,[=](int t) { mw->connWifiDone(t); }); connect(bt, SIGNAL(connDone(int)), this, SLOT(slotConnWifiResult(int))); connect(bt, SIGNAL(btFinish()), t, SLOT(quit())); t->start(); is_connecting = true; } //需要密码的wifi连接 void OneConnForm::on_btnConnPWD_clicked() { syslog(LOG_DEBUG, "A button named btnConnPWD about wifi net is clicked."); qDebug()<<"A button named btnConnPWD about wifi net is clicked."; ui->btnConnPWD->setStyleSheet("QPushButton{border:0px;border-radius:4px;background-color:rgba(47, 179, 232, 1);color:white;font-size:14px;}" "QPushButton:Hover{border:0px solid rgba(255,255,255,0.2);border-radius:4px;background-color:rgba(70, 193, 243, 1);}" "QPushButton:Pressed{border-radius:4px;background-color:rgba(27,160,213,1);}" "QPushButton:Disabled{border-radius:4px;background-color:#BEBEBE;}"); ui->btnConnPWD->setEnabled(false); mw->is_stop_check_net_state = 1; QThread *t = new QThread(); BackThread *bt = new BackThread(); bt->moveToThread(t); connect(t, SIGNAL(finished()), t, SLOT(deleteLater())); connect(t, SIGNAL(started()), this, SLOT(slotConnWifiPWD())); connect(this, SIGNAL(sigConnWifiPWD(QString, QString)), bt, SLOT(execConnWifiPWD(QString, QString))); connect(bt, SIGNAL(connDone(int)), mw, SLOT(connWifiDone(int))); connect(bt, SIGNAL(connDone(int)), this, SLOT(slotConnWifiResult(int))); connect(bt, SIGNAL(btFinish()), t, SLOT(quit())); ui->lePassword->setEnabled(false); t->start(); } //点击后弹出连接隐藏wifi网络窗口 void OneConnForm::on_btnHideConn_clicked() { // QApplication::setQuitOnLastWindowClosed(false); DlgConnHidWifi *connHidWifi = new DlgConnHidWifi(0, mw, this->parentWidget()); connect(connHidWifi, SIGNAL(reSetWifiList() ), mw, SLOT(on_btnWifiList_clicked()) ); connHidWifi->show(); } bool OneConnForm::isWifiConfExist(QString netName) { //dbusWifiMac = ""; //这个函数之前是用来获取已经连接的wifi的MAC地址 QDBusInterface m_interface("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager/Settings", "org.freedesktop.NetworkManager.Settings", QDBusConnection::systemBus() ); QDBusReply> m_reply = m_interface.call("ListConnections"); QList m_objNets = m_reply.value(); foreach (QDBusObjectPath objNet, m_objNets){ QDBusInterface m_interface("org.freedesktop.NetworkManager", objNet.path(), "org.freedesktop.NetworkManager.Settings.Connection", QDBusConnection::systemBus()); QDBusMessage reply = m_interface.call("GetSettings"); const QDBusArgument &dbusArg = reply.arguments().at( 0 ).value(); QMap> map; dbusArg >> map; for(QString key : map.keys() ){ QMap innerMap = map.value(key); if (key == "connection") { for (QString inner_key : innerMap.keys()) { if (inner_key == "id"){ if (netName == innerMap.value(inner_key).toString()) { return true; } } } } } } // end foreach (QDBusObjectPath objNet, m_objNets) return false; } //设置密码隐藏或可见 void OneConnForm::on_checkBoxPwd_stateChanged(int arg1) { if (arg1 == 0) { ui->lePassword ->setEchoMode(QLineEdit::Password); } else { ui->lePassword->setEchoMode(QLineEdit::Normal); } } void OneConnForm::on_lePassword_textEdited(const QString &arg1) { ui->lePassword->setStyleSheet("QLineEdit{border:2px solid rgba(47, 179, 232, 1);border-radius:4px;" "background:rgba(255,255,255,1);color:rgba(38, 38, 38, 1);font-size:14px;}"); if (ui->lePassword->text().size() < 8){ ui->btnConnPWD->setStyleSheet("QPushButton{border:0px;border-radius:4px;background-color:rgba(47, 179, 232, 1);color:white;font-size:14px;}" "QPushButton:Hover{border:0px solid rgba(255,255,255,0.2);border-radius:4px;background-color:rgba(70, 193, 243, 1);}" "QPushButton:Pressed{border-radius:4px;background-color:rgba(27,160,213,1);}" "QPushButton:Disabled{border-radius:4px;background-color:rgba(168, 168, 168, 1)}"); ui->btnConnPWD->setEnabled(false);//连接时设置为不可点击 if (ui->lePassword->text().size() == 0){ ui->lePassword->setStyleSheet("QLineEdit{border:2px solid rgba(47, 179, 232, 1);border-radius:4px;" "background:rgba(255,255,255,1);color:red;font-size:14px;}"); } } else { ui->btnConnPWD->setStyleSheet("QPushButton{border:0px;border-radius:4px;background-color:rgba(47, 179, 232, 1);color:white;font-size:14px;}" "QPushButton:Hover{border:0px solid rgba(255,255,255,0.2);border-radius:4px;background-color:rgba(70,193,243,1);}" "QPushButton:Pressed{border-radius:4px;background-color:rgba(27,160,213,1);}"); ui->btnConnPWD->setEnabled(true); } } void OneConnForm::on_btnInfo_2_clicked(){ on_btnInfo_clicked(); } void OneConnForm::on_btnInfo_clicked() { QPoint pos = QCursor::pos(); QRect primaryGeometry; for (QScreen *screen : qApp->screens()) { if (screen->geometry().contains(pos)) { primaryGeometry = screen->geometry(); } } if (primaryGeometry.isEmpty()) { primaryGeometry = qApp->primaryScreen()->geometry(); } BackThread *bt = new BackThread(); QString connProp = bt->getConnProp(ui->lbName->text()); QStringList propList = connProp.split("|"); QString v4method, addr, mask, gateway, dns; foreach (QString line, propList) { if (line.startsWith("method:")) { v4method = line.split(":").at(1); } if (line.startsWith("addr:")) { addr = line.split(":").at(1); } if (line.startsWith("mask:")) { mask = line.split(":").at(1); } if (line.startsWith("gateway:")) { gateway= line.split(":").at(1); } if (line.startsWith("dns:")) { dns = line.split(":").at(1); } } // qDebug()<<"v4method:"<setProp(ui->lbName->text(), v4method, addr, mask, gateway, dns, this->isActive); cf->move(primaryGeometry.width() / 2 - cf->width() / 2, primaryGeometry.height() / 2 - cf->height() / 2); cf->show(); cf->raise(); bt->deleteLater(); } // Wifi连接结果,0成功 1失败 2没有配置文件 void OneConnForm::slotConnWifiResult(int connFlag) { mw->connWifiDone(connFlag); qDebug()<<"Function slotConnWifiResult receives a number: "<currSelNetName = ""; emit selectedOneWifiForm(ui->lbName->text(), H_WIFI_ITEM_SMALL_EXTEND); resize(W_ITEM, H_ITEM_MIDDLE); ui->wbg->hide(); ui->wbg_2->show(); ui->wbg_3->hide(); ui->leInfo_1->hide(); ui->leInfo_2->hide(); ui->leInfo_3->hide(); ui->btnHideConn->hide(); ui->btnDisConn->hide(); ui->btnConn->hide(); ui->btnConnSub->hide(); // ui->line->move(X_LINE_SMALL_EXTEND, Y_LINE_SMALL_EXTEND); ui->lePassword->show(); ui->lePassword->setFocus(); Q_EMIT onLineEditClicked(); ui->checkBoxPwd->show(); ui->btnConnPWD->show(); ui->autoConn->show(); ui->autoConn->setChecked(true); this->isSelected = true; } if (connFlag == 1) { // 使用配置文件连接失败,需要删除该配置文件 QString txt(tr("Conn Wifi Failed"));//"连接 Wifi 失败" syslog(LOG_DEBUG, "Try to connect wifi named %s, but failed, will delete it's configuration file", ui->lbName->text().toUtf8().data()); //YYF 20200922 // ui->lePassword->setText(""); KylinDBus kylindbus; kylindbus.showDesktopNotify(txt); //QString cmd = "export LANG='en_US.UTF-8';export LANGUAGE='en_US';nmcli connection delete '" + ui->lbName->text() + "';notify-send '" + txt + "...' -t 3800"; QString name = ui->lbName->text(); QString cmd = "export LANG='en_US.UTF-8';export LANGUAGE='en_US';nmcli connection delete \"" + name.replace("\"","\\\"") + "\""; int status = system(cmd.toUtf8().data()); if (status != 0) { syslog(LOG_ERR, "execute 'nmcli connection delete' in function 'slotConnWifiResult' failed"); } // ui->btnConnPWD->setStyleSheet("QPushButton{border:0px;border-radius:4px;background-color:rgba(47, 179, 232, 1);color:white;font-size:14px;}" // "QPushButton:Hover{border:0px solid rgba(255,255,255,0.2);border-radius:4px;background-color:rgba(70,193,243,1);}" // "QPushButton:Pressed{border-radius:4px;background-color:rgba(27,160,213,1);}"); // ui->btnConnPWD->setEnabled(true); ui->lePassword->setEnabled(true); ui->lePassword->setFocus(); Q_EMIT onLineEditClicked(); ui->lePassword->selectAll(); ui->lePassword->setStyleSheet("QLineEdit{border:2px solid rgba(255, 0, 0, 0.5);border-radius:4px;" "background:palette(base);color:rgba(38, 38, 38, 1);font-size:14px;" "selection-background-color: rgba(255, 0, 0, 0.5);}"); } if (connFlag == 0){ //连接成功,配置是否自启动 //若含中文的QString直接转换,会出现乱码,使用如下转换方式解决此问题(必须分两句转换) QString wifi_name = wifiName; wifi_name.replace("\"","\\\""); QByteArray ba = wifi_name.toLocal8Bit(); char *name = ba.data(); if (ui->autoConn->isVisible()) { //仅当首次连接配置时执行此操作 kylin_network_set_autoconnect(name,ui->autoConn->isChecked()); } } // 设置全局变量,当前连接Wifi的信号强度 currentActWifiSignalLv = signalLv; this->stopWaiting(); is_connecting = false; //if (connFlag != 0){ // mw->stopLoading(); //} } void OneConnForm::waitAnimStep() { //YYF 平板模式设计稿中没有此图标 // QString qpmQss = "QLabel{background-image:url(':/res/s/conning-a/"; // qpmQss.append(QString::number(this->waitPage)); // qpmQss.append(".png');}"); // ui->lbWaitingIcon->setStyleSheet(qpmQss); // this->waitPage --; // if (this->waitPage < 1) { // this->waitPage = TOTAL_PAGE; //循环播放8张图片 // } // this->countCurrentTime += FRAME_SPEED; // if (this->countCurrentTime >= LIMIT_TIME) { // QString cmd = "kill -9 $(pidof nmcli)"; //杀掉当前正在进行的有关nmcli命令的进程 // int status = system(cmd.toUtf8().data()); // if (status != 0) { // qDebug()<<"execute 'kill -9 $(pidof nmcli)' in function 'waitAnimStep' failed"; // syslog(LOG_ERR, "execute 'kill -9 $(pidof nmcli)' in function 'waitAnimStep' failed"); // } // this->stopWaiting(); //动画超出时间限制,强制停止动画 // mw->is_stop_check_net_state = 0; // } } void OneConnForm::startWaiting(bool isConn) { //YYF 平板模式设计稿中没有此图标 // this->isWaiting = true; // if (isConn) { // ui->lbWaiting->setStyleSheet("QLabel{border:0px;border-radius:10px;background-color:rgba(61,107,229,1);}"); // } else { // ui->btnDisConn->hide(); // ui->lbWaiting->setStyleSheet("QLabel{border:0px;border-radius:10px;background-color:rgba(255,255,255,0.12);}"); // } // this->countCurrentTime = 0; // this->waitPage = TOTAL_PAGE; //总共有8张图片 // this->waitTimer->start(FRAME_SPEED); // ui->lbWaiting->show(); // ui->lbWaitingIcon->show(); // mw->setTrayLoading(true); } void OneConnForm::stopWaiting() { //YYF 平板模式设计稿中没有此图标 // this->isWaiting = false; // this->waitTimer->stop(); // ui->lbWaiting->hide(); // ui->lbWaitingIcon->hide(); // mw->setTrayLoading(false); // mw->getActiveInfo(); } ukui-screensaver/KylinNM/src/confform.cpp0000644000175000017500000004544314205074704017433 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include extern QString llname, lwname; ConfForm::ConfForm(QWidget *parent) : QWidget(parent), ui(new Ui::ConfForm) { ui->setupUi(this); this->setWindowFlags(Qt::FramelessWindowHint); //Qt::WindowStaysOnTopHint this->setWindowTitle(tr("edit network"));//"网络设置" this->setAttribute(Qt::WA_TranslucentBackground); //需要添加 void paintEvent(QPaintEvent *event) 函数 QPainterPath path; auto rect = this->rect(); rect.adjust(1, 1, -1, -1); path.addRoundedRect(rect, 6, 6); setProperty("blurRegion", QRegion(path.toFillPolygon().toPolygon())); this->setStyleSheet("QWidget{border-radius:16px;border:none;}"); // KylinDBus mkylindbus; QString strTrans; strTrans = QString::number(1, 10, 2); QString sty = "#centralWidget{border:1px solid rgba(255,255,255,0.05);border-radius:16px;background:rgba(255,255,255," + strTrans + ");}"; ui->centralWidget->setStyleSheet(sty); labelQss = "QLabel{border:0px;color:rgba(38,38,38,1);background-color:transparent;}"; cbxQss = "QComboBox{padding-left:20px;font-size:13px;color:rgba(38,38,38,1);" "border:1px solid rgba(255, 255, 255, 0.05);border-radius:4px;background:rgba(255,255,255,0.08);}" "QComboBox::drop-down{border:0px;width:30px;}" "QComboBox::down-arrow{image:url(:/res/g/down_arrow.png);}" "QComboBox QAbstractItemView {margin:0px 0px 0px 0px;padding: 0px 0px;border-radius:0px;background-color:#48484C;outline:0px;}" "QComboBox QAbstractItemView::item{padding-left:17px;border-radius:0px;font-size:13px;color:rgba(255,255,255,0.91);height: 32px;background-color:#48484C;outline:0px;}" "QComboBox QAbstractItemView::item:hover{padding-left:17px;border-radius:0px;font-size:13px;color:rgba(255,255,255,0.91);background-color:#3D6BE5;outline:0px;}"; leQss = "QLineEdit{padding-left:20px;color:rgba(38,38,38,1);background:rgba(245,245,245,1);}"; btnOffQss = "QPushButton{border:1px solid rgba(44,44,44,1);border-radius:4px;background-color:rgba(255,255,255,0.12);color:rgba(44,44,44,1);font-size:14px;}"; // "QPushButton:Hover{border:0px solid rgba(255,255,255,0.2);border-radius:4px;background-color:rgba(255,255,255,0.2);}" // "QPushButton:Pressed{border-radius:4px;background-color:rgba(255,255,255,0.08);}"; btnOnQss = "QPushButton{border:0px;border-radius:4px;background-color:rgba(61,107,229,1);color:white;font-size:14px;}" "QPushButton:Hover{border:0px solid rgba(255,255,255,0.2);border-radius:4px;background-color:rgba(107,142,235,1);}" "QPushButton:Pressed{border-radius:4px;background-color:rgba(50,87,202,1);}"; lineQss = "background:rgba(255,255,255,0.08);"; // ui->centralWidget->setStyleSheet("#centralWidget{border:1px solid #297a97;background-color:#ffffff;}"); ui->wdHead->setStyleSheet("#wdHead{border:none}"); ui->wgManual->setStyleSheet("#wgManual{border:none}"); ui->wdBottom->setStyleSheet("#wdBottom{border:none}"); ui->lbLeftupTitle->setStyleSheet("QLabel{border:0px;font-size:14px;color:rgba(38,38,38,1);background-color:transparent;}"); ui->lbName->setStyleSheet(labelQss); ui->lbTxt1->setStyleSheet(labelQss); ui->lbTxt2->setStyleSheet(labelQss); ui->lbTxt3->setStyleSheet(labelQss); ui->lbTxt4->setStyleSheet(labelQss); ui->lbTxt5->setStyleSheet(labelQss); ui->lbTxt6->setStyleSheet(labelQss); //YYF ui->btnClose->setStyleSheet("border-image:url(:/res/x/pb-close.png);"); connect(ui->btnClose,&QPushButton::clicked,ui->btnCancel,&QPushButton::clicked); ui->isDHCP->setStyleSheet("QCheckBox::indicator {width: 16px; height: 16px;}" "QCheckBox::indicator:checked {image: url(:/res/g/checkbox-checked.svg);}" "QCheckBox::indicator:unchecked {image: url(:/res/g/checkbox-unchecked.svg);}"); ui->notDHCP->setStyleSheet("QCheckBox::indicator {width: 16px; height: 16px;}" "QCheckBox::indicator:checked {image: url(:/res/g/checkbox-checked.svg);}" "QCheckBox::indicator:unchecked {image: url(:/res/g/checkbox-unchecked.svg);}"); ui->cbType->setStyleSheet(cbxQss); ui->cbType->setView(new QListView()); ui->cbType->hide(); ui->cbMask->setStyleSheet(cbxQss); ui->cbMask->setView(new QListView()); ui->leName->setStyleSheet(leQss); ui->leAddr->setStyleSheet(leQss); ui->leGateway->setStyleSheet(leQss); ui->leDns->setStyleSheet(leQss); ui->leDns2->setStyleSheet(leQss); ui->btnCancel->setStyleSheet(btnOffQss); ui->btnOk->setStyleSheet(btnOnQss); ui->btnCreate->setStyleSheet(btnOnQss); ui->lineUp->setStyleSheet(lineQss); ui->lineDown->setStyleSheet(lineQss); ui->lineUp->hide(); ui->lineDown->hide(); ui->lbName->setText(tr("LAN name: "));//"网络名称:" ui->lbTxt1->setText(tr("Method: "));//"编辑IP设置:" ui->lbTxt2->setText(tr("Address: "));//"IP地址:" ui->lbTxt3->setText(tr("Netmask: "));//"子网掩码:" ui->lbTxt4->setText(tr("Gateway: "));//"默认网关:" ui->lbTxt5->setText(tr("DNS 1: "));//"首选DNS:" ui->lbTxt6->setText(tr("DNS 2: "));//"备选DNS:" ui->lbLeftupTitle->setText(tr("Edit Conn"));//"网络设置" ui->cbType->addItem(tr("Auto(DHCP)"));//"自动(DHCP)" ui->cbType->addItem(tr("Manual"));//"手动" ui->isDHCP->setText(tr("Auto(DHCP)")); ui->notDHCP->setText(tr("Manual")); connect(ui->cbType, SIGNAL(currentIndexChanged(int)), this, SLOT(cbTypeChanged(int))); ui->cbMask->addItem("255.255.255.0"); //24 ui->cbMask->addItem("255.255.254.0"); //23 ui->cbMask->addItem("255.255.252.0"); //22 ui->cbMask->addItem("255.255.0.0"); //16 ui->cbMask->addItem("255.0.0.0"); //8 // ui->cbMask->setWindowFlags(Qt::X11BypassWindowManagerHint); ui->cbMask->view()->setWindowFlags(Qt::Popup | Qt::X11BypassWindowManagerHint); ui->cbMask->view()->setParent(this); ui->cbMask->view()->hide(); ui->cbMask->installEventFilter(this); ui->cbMask->view()->installEventFilter(this); connect(ui->cbMask->view(), &QAbstractItemView::pressed, this, [=](QModelIndex index){ // qDebug() << "-----------------------pressed:" << index.row(); // qDebug() << "-----------------------itemText:" << ui->cbMask->itemText(index.row()); Q_EMIT ui->cbMask->setCurrentIndex(index.row()); ui->cbMask->view()->hide(); }); // connect(ui->cbMask->view(), &QAbstractItemView::entered, this, [=](QModelIndex index){ // qDebug() << "-----------------------entered:" << index.row(); // }); ui->cbMask->view()->setGeometry(QRect(ui->cbMask->geometry().left(), ui->wgManual->geometry().top() + ui->cbMask->geometry().bottom(), ui->cbMask->view()->width(), ui->cbMask->view()->height())); ui->btnCancel->setText(tr("Cancel"));//"取消" ui->btnOk->setText(tr("Save"));//"保存" ui->btnCreate->setText(tr("Ok"));//"确定" ui->btnCancel->setFocusPolicy(Qt::NoFocus); ui->btnOk->setFocusPolicy(Qt::NoFocus); ui->btnCreate->setFocusPolicy(Qt::NoFocus); // IP的正则格式限制 QRegExp rx("\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b"); ui->leAddr->setValidator(new QRegExpValidator(rx, this)); ui->leGateway->setValidator(new QRegExpValidator(rx, this)); ui->leDns->setValidator(new QRegExpValidator(rx, this)); ui->leDns2->setValidator(new QRegExpValidator(rx, this)); } void ConfForm::setMainWindow(KylinNM *mainwindow) { this->mw = mainwindow; } ConfForm::~ConfForm() { delete ui; } bool ConfForm::eventFilter(QObject *obj, QEvent *ev) { if(obj == ui->cbMask) { if(ev->type() == QEvent::MouseButtonPress) { ui->cbMask->view()->setVisible(!ui->cbMask->view()->isVisible()); if(ui->cbMask->view()->isVisible()) ui->cbMask->view()->setFocus(); } } else if (obj != ui->cbMask->view()) { ui->cbMask->view()->hide(); } return false; } void ConfForm::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { this->isPress = true; this->winPos = this->pos(); this->dragPos = event->globalPos(); event->accept(); } } void ConfForm::mouseReleaseEvent(QMouseEvent *event) { this->isPress = false; } void ConfForm::mouseMoveEvent(QMouseEvent *event) { if (this->isPress) { this->move(this->winPos - (this->dragPos - event->globalPos())); event->accept(); } } void ConfForm::tabletStyle(bool isTablet) { isTabletStyle = isTablet; ui->leName->resize(290+194*isTabletStyle,48); ui->leName->resize(290+194*isTabletStyle,48); ui->btnOk->move(312+194*isTabletStyle,25); ui->btnCreate->move(312+194*isTabletStyle,25); ui->btnCancel->move(180+194*isTabletStyle,25); ui->btnClose->move(408+194*isTabletStyle,8); ui->isDHCP->move(180+194*isTabletStyle,130); ui->notDHCP->move(356+194*isTabletStyle,130); ui->wdBottom->setFixedWidth(446+194*isTabletStyle); ui->wdHead->setFixedWidth(446+194*isTabletStyle); ui->wgManual->setFixedWidth(446+194*isTabletStyle); ui->upTitle->setFixedWidth(446+194*isTabletStyle); } //网络配置参数设置界面的显示内容 void ConfForm::setProp(QString connName, QString v4method, QString addr, QString mask, QString gateway, QString dns, bool isActConf) { this->isActConf = isActConf; ui->leName->setText(connName); if (v4method == "auto" || v4method == "") { ui->isDHCP->setChecked(true); ui->notDHCP->setChecked(false); ui->cbType->setCurrentIndex(0); cbTypeChanged(0); } else { ui->isDHCP->setChecked(false); ui->notDHCP->setChecked(true); ui->cbType->setCurrentIndex(1); cbTypeChanged(1); } ui->leAddr->setText(addr); ui->leGateway->setText(gateway); // 配置中有多个DNS,只处理前两个 if (dns.indexOf(",") != -1) { QStringList dnss = dns.split(","); ui->leDns->setText(dnss.at(0)); ui->leDns2->setText(dnss.at(1)); } else { ui->leDns->setText(dns); ui->leDns2->setText(""); } if (mask == "24") { ui->cbMask->setCurrentIndex(0); } else if(mask == "23") { ui->cbMask->setCurrentIndex(1); } else if(mask == "22") { ui->cbMask->setCurrentIndex(2); } else if(mask == "16") { ui->cbMask->setCurrentIndex(3); } else if(mask == "8") { ui->cbMask->setCurrentIndex(4); } else { ui->cbMask->setCurrentIndex(0); } } //点击了创建新的网络的按钮 void ConfForm::on_btnCreate_clicked() { if (mw->lanNameList.contains(ui->leName->text())) { qWarning() << "Warn : 已有同名LAN存在:" << ui->leName->text(); // ui->tipLabel->show(); return; } KylinDBus kylindbus; kylindbus.getWiredCardName(); QString mIfname = kylindbus.dbusLanCardName; if (mIfname == "") { QString tip(tr("Can not create new wired network for without wired card")); // kylindbus.showDesktopNotify(tip); this->hide(); return; } QString name = ui->leName->text(); QString cmdStr = "nmcli connection add con-name \"" + name.replace("\"","\\\"") + "\" type ethernet"; //由于样机存在veth虚拟网卡,故不指定有线设备,将自动选择 Utils::m_system(cmdStr.toUtf8().data()); //int status = system(cmdStr.toUtf8().data()); //if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection add con-name' in function 'on_btnCreate_clicked' failed");} if (ui->cbType->currentIndex() == 1) { //config the ipv4 and netmask and gateway if select Manual this->isCreateNewNet = true; this->on_btnOk_clicked(); } else { QString txt(tr("New network already created")); // kylindbus.showDesktopNotify(txt); } this->hide(); } //点击了保存更改网络设置的按钮 void ConfForm::on_btnOk_clicked() { QString mask = ""; if (ui->cbMask->currentIndex() == 0) { mask = "24"; } else if(ui->cbMask->currentIndex() == 1) { mask = "23"; } else if(ui->cbMask->currentIndex() == 2) { mask = "22"; } else if(ui->cbMask->currentIndex() == 3) { mask = "16"; } else if(ui->cbMask->currentIndex() == 4) { mask = "8"; } else { mask = "24"; } if (ui->cbType->currentIndex() == 0) { QString name = ui->leName->text(); name.replace("\"","\\\""); kylin_network_set_automethod(name.toUtf8().data()); } else { QString dnss = ui->leDns->text(); if (ui->leDns2->text() != "") { dnss.append(","); dnss.append(ui->leDns2->text()); } QString name = ui->leName->text(); name.replace("\"","\\\""); kylin_network_set_manualall(name.toUtf8().data(), ui->leAddr->text().toUtf8().data(), mask.toUtf8().data(), ui->leGateway->text().toUtf8().data(), dnss.toUtf8().data()); } KylinDBus kylindbus; this->hide(); QString txt(tr("New network settings already finished")); kylindbus.showDesktopNotify(txt); if (!this->isCreateNewNet) { if (this->isActConf == true) { // 如果是修改当前连接的网络,则修改设置后简略重连网络 //QString cmd = "/usr/share/kylin-nm/shell/connup.sh '" + ui->leName->text() + "'"; kylindbus.connectWiredNet(ui->leName->text()); //reconnect this wired network QString m_txt(tr("New settings already effective")); kylindbus.showDesktopNotify(m_txt); //show desktop notify } //需要更新一下有线网界面 qDebug()<<"debug: request refresh Lan list"; emit requestRefreshLanList(0); } this->isCreateNewNet = false; } //点击取消按钮 void ConfForm::on_btnCancel_clicked() { this->hide(); } //根据需要设置的种类(自动或手动等)显示界面内容 void ConfForm::cbTypeChanged(int index) { if (isShowSaveBtn) { ui->leName->setEnabled(false); ui->btnOk->show(); //显示保存按钮 ui->btnCreate->hide(); //隐藏创建按钮 ui->lbLeftupTitle->setText(tr("Edit Network")); } if (index == 0) { ui->lineUp->hide(); ui->lineDown->hide(); ui->wgManual->hide(); ui->centralWidget->resize(446+194*isTabletStyle, 443); ui->wdBottom->move(0, 347); this->setEnableOfBtn(); this->resize(446+194*isTabletStyle,443); } if (index == 1) { ui->lineUp->show(); ui->lineDown->show(); ui->wgManual->show(); ui->centralWidget->resize(446+194*isTabletStyle, 576); ui->wdBottom->move(0, 480); this->setEnableOfBtn(); this->resize(446+194*isTabletStyle, 576); } if (index == 3) { ui->isDHCP->setChecked(true); ui->notDHCP->setChecked(false); ui->btnOk->setStyleSheet(btnOffQss); ui->btnOk->setEnabled(false); ui->btnCreate->setStyleSheet(btnOffQss); ui->btnCreate->setEnabled(false); ui->leName->setEnabled(true); ui->btnOk->hide(); ui->btnCreate->show(); ui->lbLeftupTitle->setText(tr("Add Wired Network")); isShowSaveBtn = false; ui->lineUp->hide(); ui->lineDown->hide(); ui->wgManual->hide(); ui->centralWidget->resize(446+194*isTabletStyle, 443); ui->wdBottom->move(0, 347); this->resize(446+194*isTabletStyle, 443); } } //编辑网络名称 void ConfForm::on_leName_textEdited(const QString &arg1) { this->setEnableOfBtn(); } //编辑网络ip void ConfForm::on_leAddr_textEdited(const QString &arg1) { this->setEnableOfBtn(); } //编辑网络网关 void ConfForm::on_leGateway_textEdited(const QString &arg1) { this->setEnableOfBtn(); } //编辑网络DNS void ConfForm::on_leDns_textEdited(const QString &arg1) { this->setEnableOfBtn(); } //编辑网络备用DNS void ConfForm::on_leDns2_textEdited(const QString &arg1) { // this->setEnableOfBtn(); } //设置界面按钮是否可点击 void ConfForm::setEnableOfBtn() { if (ui->leName->text().size() == 0 ) { this->setBtnEnableFalse(); return; } if (ui->cbType->currentIndex() == 1) { if (!this->getTextEditState(ui->leAddr->text()) ) { this->setBtnEnableFalse(); return; } if (!this->getTextEditState(ui->leGateway->text()) ) { this->setBtnEnableFalse(); return; } if (!this->getTextEditState(ui->leDns->text()) ) { this->setBtnEnableFalse(); return; } } ui->btnOk->setStyleSheet(btnOnQss); ui->btnOk->setEnabled(true); ui->btnCreate->setStyleSheet(btnOnQss); ui->btnCreate->setEnabled(true); } //文本的输入要符合ip的格式要求 bool ConfForm::getTextEditState(QString text) { QRegExp rx("\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b"); bool match = false; match = rx.exactMatch(text); // qDebug()<<"the match result is: " << match; return match; } //设置创建或保存按钮不可点击 void ConfForm::setBtnEnableFalse() { ui->btnOk->setStyleSheet(btnOffQss); ui->btnOk->setEnabled(false); ui->btnCreate->setStyleSheet(btnOffQss); ui->btnCreate->setEnabled(false); } void ConfForm::paintEvent(QPaintEvent *event) { QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); QWidget::paintEvent(event); } void ConfForm::on_isDHCP_clicked() { ui->isDHCP->setEnabled(false); ui->notDHCP->setEnabled(true); ui->notDHCP->setChecked(false); ui->cbType->setCurrentIndex(0); cbTypeChanged(0); } void ConfForm::on_notDHCP_clicked() { ui->notDHCP->setEnabled(false); ui->isDHCP->setEnabled(true); ui->isDHCP->setChecked(false); ui->cbType->setCurrentIndex(1); cbTypeChanged(1); } ukui-screensaver/KylinNM/src/switchbutton.cpp0000644000175000017500000000630014205074760020346 0ustar fengfeng/** * Copyright (C) 2018 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, 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 "switchbutton.h" SwitchButton::SwitchButton(QWidget *parent) : QWidget(parent) { setFixedSize(50,24); m_fWidth = (float)width(); m_fHeight = (float)height(); m_cTimer = new QTimer(this); m_cTimer->setInterval(5); if(m_bIsOn == 1) { m_fCurrentValue = m_fWidth - 16 - 4; } else { m_fCurrentValue = 4; } connect(m_cTimer,SIGNAL(timeout()),this,SLOT(startAnimation())); } void SwitchButton::setSwitchStatus(bool check) { if(check == true) { m_bIsOn = 1; } else { m_bIsOn = 0; } m_cTimer->start(); //开始播放动画 } /* 播放按钮开启关闭动画 */ void SwitchButton::startAnimation() { //滑动按钮动作播放 int pos = 4; int size = m_fWidth - 16; if(m_bIsOn) { m_fCurrentValue ++; //往右滑动 if(m_fCurrentValue >= size - pos) { //到达边界停下来 m_fCurrentValue = size - pos; m_cTimer->stop(); } } else { m_fCurrentValue --; if(m_fCurrentValue <= pos) { //到达最小值,停止继续前进 m_fCurrentValue = pos; m_cTimer->stop(); } } update(); } /* 按钮按下处理 */ void SwitchButton::mousePressEvent(QMouseEvent *event) { Q_UNUSED(event); m_bIsOn = !m_bIsOn; Q_EMIT clicked(m_bIsOn); return QWidget::mousePressEvent(event); } /* 绘制滑动按钮主体 */ void SwitchButton::paintEvent(QPaintEvent *event) { Q_UNUSED(event); QPainter painter(this); painter.setRenderHint(QPainter::SmoothPixmapTransform); painter.setRenderHint(QPainter::Antialiasing); //抗锯齿效果 painter.setPen(Qt::NoPen); QColor colorActive(61,107,229); QColor colorInactive(111,111,111); colorInactive.setAlphaF(0.12); if(m_bIsOn) { painter.save(); painter.setBrush(colorActive); QRectF active_rect = QRectF(0,0,m_fWidth,m_fHeight); painter.drawRoundedRect(active_rect, 0.5 * m_fHeight, 0.5 * m_fHeight); //画开启状态 } else { painter.save(); painter.setBrush(colorInactive); QRectF inactive_rect = QRectF(0 ,0,m_fWidth,m_fHeight); painter.drawRoundedRect(inactive_rect, 0.5 * m_fHeight, 0.5 * m_fHeight); //画关闭状态 } painter.restore(); painter.save(); painter.setBrush(Qt::white); painter.drawEllipse(m_fCurrentValue,4, 16, 16); painter.restore(); } ukui-screensaver/KylinNM/src/swipegesturerecognizer.cpp0000644000175000017500000001150414205074760022431 0ustar fengfeng/** * Copyright (C) 2018 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, 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 #include #include #include "swipegesturerecognizer.h" SwipeGestureRecognizer::SwipeGestureRecognizer(QObject *parent) : QObject(parent) { } bool SwipeGestureRecognizer::IsValidMove(int dx, int dy) { // The moved distance is to small to count as not just a glitch. if ((qAbs(dx) < MINIMUM_DISTANCE) && (qAbs(dy) < MINIMUM_DISTANCE)) { return false; } return true; } // virtual QGesture* SwipeGestureRecognizer::create(QObject* pTarget) { QGesture *pGesture = new QSwipeGesture(pTarget); return pGesture; } // virtual QGestureRecognizer::Result SwipeGestureRecognizer::recognize(QGesture* pGesture, QObject *pWatched, QEvent *pEvent) { QGestureRecognizer::Result result = QGestureRecognizer::Ignore; QSwipeGesture *pSwipe = static_cast(pGesture); switch(pEvent->type()) { case QEvent::MouseButtonPress: { QMouseEvent* pMouseEvent = static_cast(pEvent); #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) pSwipe->setProperty("startPoint", pMouseEvent->posF()); #else pSwipe->setProperty("startPoint", pMouseEvent->localPos()); #endif result = QGestureRecognizer::MayBeGesture; //qDebug() << "Swipe gesture started (start point=" << pSwipe->property("startPoint").toPointF() << ")"; } break; case QEvent::MouseButtonRelease: { QMouseEvent* pMouseEvent = static_cast(pEvent); const QVariant& propValue = pSwipe->property("startPoint"); QPointF startPoint = propValue.toPointF(); #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) QPointF endPoint = pMouseEvent->posF(); #else QPointF endPoint = pMouseEvent->localPos(); #endif // process distance and direction int dx = endPoint.x() - startPoint.x(); int dy = endPoint.y() - startPoint.y(); //bugfix: startPoint.isNull because we sometimes get false events with startpoint 0 -> wrong swipe detected! if ( (!IsValidMove(dx, dy)) || ( startPoint.isNull() ) ) { // Just a click, so no gesture. result = QGestureRecognizer::CancelGesture; //qDebug("Swipe gesture canceled"); } else { // Compute the angle. // qDebug() << " startPoint= " << startPoint << " endPoint=" << endPoint << " dx=" << dx << " dy=" << dy; Q_EMIT onSwipeGesture(dx, dy); qreal angle = ComputeAngle(dx, dy); pSwipe->setSwipeAngle(angle); result = QGestureRecognizer::FinishGesture; //qDebug("Swipe gesture finished"); } } break; default: break; } return result; } void SwipeGestureRecognizer::reset(QGesture *pGesture) { pGesture->setProperty("startPoint", QVariant(QVariant::Invalid)); parent::reset(pGesture); } qreal SwipeGestureRecognizer::ComputeAngle(int dx, int dy) { double PI = 3.14159265; // Need to convert from screen coordinates direction // into classical coordinates direction. dy = -dy; double result = atan2((double)dy, (double)dx) ; result = (result * 180) / PI; // Always return positive angle. if (result < 0) { result += 360; } return result; } /* ========================================================================== */ QSwipeGesture::SwipeDirection SwipeGestureUtil::GetHorizontalDirection(QSwipeGesture *pSwipeGesture) { qreal angle = pSwipeGesture->swipeAngle(); if (0 <= angle && angle <= 45) { return QSwipeGesture::Right; } if (135 <= angle && angle <= 225) { return QSwipeGesture::Left; } if (315 <= angle && angle <= 360) { return QSwipeGesture::Right; } return QSwipeGesture::NoDirection; } QSwipeGesture::SwipeDirection SwipeGestureUtil::GetVerticalDirection(QSwipeGesture *pSwipeGesture) { qreal angle = pSwipeGesture->swipeAngle(); if (45 < angle && angle < 135) { return QSwipeGesture::Up; } if (225 < angle && angle < 315) { return QSwipeGesture::Down; } return QSwipeGesture::NoDirection; } ukui-screensaver/KylinNM/src/switchbutton.h0000644000175000017500000000266214205074760020022 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef SWITCHBUTTON_H #define SWITCHBUTTON_H #include #include #include #include class SwitchButton : public QWidget { Q_OBJECT public: explicit SwitchButton(QWidget *parent = nullptr); void setSwitchStatus(bool check); private: int m_bIsOn = 1; QTimer *m_cTimer; float m_fWidth; float m_fHeight; float m_fCurrentValue; void paintEvent(QPaintEvent *event); void mousePressEvent(QMouseEvent *event); Q_SIGNALS: void clicked(int check); private Q_SLOTS: void startAnimation(); }; #endif // SWITCHBUTTON_H ukui-screensaver/KylinNM/src/kylinnm.h0000644000175000017500000002472614205074704016751 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "oneconnform.h" #include "onelancform.h" #include "hot-spot/dlghotspotcreate.h" #include "wireless-security/dlgconnhidwifi.h" #define W_LEFT_AREA 16 //#define W_VERTICAL_LINE 1 //左边竖线宽度 #define W_RIGHT_AREA 438 //41 + 1 + 438 = 480 #define L_VERTICAL_LINE_TO_ITEM 4 //竖线到item左侧的距离 #define X_LEFT_WIFI_BALL 416 //白色小球在左边 #define X_RIGHT_WIFI_BALL 440 //白色小球在右边 #define Y_WIFI_BALL 23 //白色小球y坐标 #define X_ITEM 46 //item到窗口左侧的距离 41 + 1 + 4 = 46 #define W_ITEM 424 #define Y_TOP_ITEM 100 //顶部item、topLanListWidget、topWifiListWidget的y坐标 #define H_NORMAL_ITEM 56 #define H_GAP_UP -5 #define H_MIDDLE_WORD 46 //"显示‘可用网络列表’的label" #define H_GAP_DOWN 5 //57 + 60 + 10 + 46 + 5 = 178 #define X_MIDDLE_WORD 0 #define W_MIDDLE_WORD 260 #define H_LAN_ITEM_EXTEND 102 //162 - 60 #define H_WIFI_ITEM_BIG_EXTEND 90 //150 - 60 #define H_WIFI_ITEM_SMALL_EXTEND 100 //156 - 56 #define Y_SCROLL_AREA 192//列表纵坐标 #define W_SCROLL_AREA 414 //#define H_SCROLL_AREA 200 #define H_SCROLL_AREA H_NORMAL_ITEM*4 //平板中去掉了添加新网络按钮,设置为4倍的item,防止最后一栏被遮挡 #define W_TOP_LIST_WIDGET 435 #define W_LIST_WIDGET 414 #define W_BTN_FUN 128 #define H_BTN_FUN 24 #define X_BTN_FUN 36 #define Y_BTN_FUN 400 //新建网络,加入网络按钮的宽高、x坐标、y坐标 #define W_NO_ITEM_TIP 220 #define H_NO_ITEM_TIP 20 class OneConnForm; class ConfForm; namespace Ui { class KylinNM; } class KylinNM : public QWidget { Q_OBJECT public slots: void onPhysicalCarrierChanged(bool flag); void onCarrierUpHandle(); void onCarrierDownHandle(); void onDeleteLan(); void onNetworkDeviceAdded(QDBusObjectPath objPath); void onNetworkDeviceRemoved(QDBusObjectPath objPath); void getLanBandWidth(); void onExternalConnectionChange(QString type); void onExternalLanChange(); void onExternalWifiChange(); void onExternalWifiSwitchChange(bool wifiEnabled); void oneLanFormSelected(QString lanName, QString uniqueName); void oneTopLanFormSelected(QString lanName, QString uniqueName); void oneWifiFormSelected(QString wifiName, int extendLength); void oneTopWifiFormSelected(QString wifiName, int extendLength); void on_btnHotspot_clicked(); void on_btnHotspotState(); //flag =0或1为普通点击、2为收到打开信息、3为收到关闭信息、4为无线网卡插入、5为无线网卡拔出 void onBtnWifiClicked(int flag = 0); void connLanDone(int connFlag); void connWifiDone(int connFlag); void activeGetWifiList(); protected: bool eventFilter(QObject *obj, QEvent *event); public: explicit KylinNM(QWidget *parent = 0); ~KylinNM(); void onSwipeGesture(int dx, int dy); void editQssString(); void createTopLanUI(); void createTopWifiUI(); void createOtherUI(); void createListAreaUI(); void createLeftAreaUI(); void startLoading(); void stopLoading(); void setTrayIcon(QIcon icon); void setTrayLoading(bool isLoading); void getActiveInfo(); void initTimer(); void checkIsWirelessDeviceOn(); void updateNetList(); void updateWifiList(); int getConnectStatus();//获取网络连接状态,返回值 -1 无连接; 0 有线连接; 1无线连接; 2有线和无线都已连接 QIcon iconLanOnline, iconLanOffline; QIcon iconWifiFull, iconWifiHigh, iconWifiMedium, iconWifiLow; QIcon iconConnecting; QList loadIcons; QString mwBandWidth; KylinDBus *objKyDBus = nullptr; NetworkSpeed *objNetSpeed = nullptr; SwitchButton *btnWireless; QStringList lanNameList; //状态设置,0为假,1为真 int is_update_wifi_list = 0; //是否是update wifi列表,而不是load wifi列表 int is_by_click_connect = 0; //是否是通过点击连接按钮进行的连接 int is_btnNetList_clicked = 1; //是否处于有线网界面 int is_btnWifiList_clicked = 0; //是否处于无线网界面 int is_wired_line_ready = 1; //主机是否连接网线 int is_wireless_adapter_ready = 1; //主机是否插入无线网卡 int is_keep_wifi_turn_on_state = 1; //是否要执行wifi开关变为打开样式 int is_stop_check_net_state = 0; //是否要在进行其他操作时停止检查网络状态 int is_connect_wifi_failed = 0; //刚才是否连接wifi失败 int is_fly_mode_on = 0; //是否已经打开飞行模式 int is_hot_sopt_on = 0; //是否已经打开热点 QString currSelNetName = ""; //当前ScrollArea中选中的网络名称 int currSelNetNum = 0; //当前选中的item序号 bool isTabletStyle=false;//YYF 平板桌面模式 static void reflashWifiUi(); static bool m_is_reflashWifiUi; private: void tabletStyle();//YYF 平板桌面模式特有设置 void checkSingle(); void initNetwork(); void createTrayIcon(); void handleIconClicked(); void showTrayIconMenu(); bool checkLanOn(); bool checkWlOn(); void getLanList(); void getWifiList(); void getInitLanSlist(); Ui::KylinNM *ui; LoadingDiv *loading = nullptr; QDesktopWidget desktop; KSimpleNM *ksnm = nullptr; ConfForm *confForm = nullptr; QWidget *topLanListWidget = nullptr; QWidget *topWifiListWidget = nullptr; QWidget *lanListWidget = nullptr; QWidget *wifiListWidget = nullptr; QWidget *optWifiWidget = nullptr; QLabel *lbLoadDown = nullptr; QLabel *lbLoadDownImg = nullptr; QLabel *lbLoadUp = nullptr; QLabel *lbLoadUpImg = nullptr; QLabel *lbNoItemTip = nullptr; bool ifLanConnected; bool ifWLanConnected; QScrollArea *scrollAreal = nullptr; QScrollArea *scrollAreaw = nullptr; QLabel *lbTopLanList = nullptr; QLabel *lbTopWifiList = nullptr; QLabel *lbLanList = nullptr; QLabel *lbWifiList = nullptr; QPushButton *btnAddNet = nullptr; QPushButton *btnCreateNet = nullptr; QSystemTrayIcon *trayIcon = nullptr; QMenu *trayIconMenu = nullptr; QAction *mShowWindow = nullptr; QAction *mAdvConf = nullptr; QWidget *widShowWindow = nullptr; QWidget *widAdvConf = nullptr; QString lname, wname; // 以太网卡和无线网卡名称 QString btnOffQss, btnOnQss, btnBgOffQss, btnBgOnQss, btnBgHoverQss, btnBgLeaveQss; // 主界面按钮底色 QString scrollBarQss, leftBtnQss, funcBtnQss; QStringList oldLanSlist; //上一次获取Lan列表 QStringList oldWifiSlist; //上一次获取wifi列表 //平板 QLabel *lbNetListText=nullptr;//有线网络 QLabel *lbWifiListText=nullptr;//无线网络 //循环检测网络连接状态 QTimer *iconTimer = nullptr; QTimer *wiredCableUpTimer = nullptr; QTimer *wiredCableDownTimer = nullptr; QTimer *deleteLanTimer = nullptr; QTimer *checkWifiListChanged = nullptr; QTimer *checkIfLanConnect = nullptr; QTimer *checkIfWifiConnect = nullptr; QTimer *checkIfNetworkOn = nullptr; QTimer *setNetSpeed = nullptr; int currentIconIndex; int activeWifiSignalLv; long int start_rcv_rates = 0; //保存开始时的流量计数 long int end_rcv_rates = 0; //保存结束时的流量计数 long int start_tx_rates = 0; //保存开始时的流量计数 long int end_tx_rates = 0; //保存结束时的流量计数 QString actWifissid = "--";//当前连接wifi的ssid QString actWifiuuid = "--";//当前连接wifi的uuid QStringList actWifiBssidList; //当前连接wifi的bssid private slots: void iconActivated(QSystemTrayIcon::ActivationReason reason); bool nativeEvent(const QByteArray &eventType, void *message, long *result); void on_btnNet_clicked(); void on_btnWifiList_clicked(); void onBtnNetListClicked(int flag=0); void getLanListDone(QStringList slist); void getWifiListDone(QStringList slist); void loadWifiListDone(QStringList slist); void updateWifiListDone(QStringList slist); void on_showWindowAction(); void on_btnAdvConf_clicked(); void on_btnNetList_pressed(); void on_btnWifiList_pressed(); void activeLanDisconn(); void activeWifiDisconn(); void activeStartLoading(); void on_btnAdvConf_pressed(); void on_btnAdvConf_released(); void on_checkWifiListChanged(); void on_setNetSpeed(); void on_checkOverTime(); // 后台回调 void enNetDone(); void disNetDone(); void enWifiDone(); void launchLanDone(); void disWifiDone(); void disWifiStateKeep(); void disWifiDoneChangeUI(); void iconStep(); void on_btnFlyMode_clicked(); void onBtnAddNetClicked(); void onBtnCreateNetClicked(); signals: void disConnSparedNet(QString type); void waitWifiStop(); void waitLanStop(); void onLineEditClicked(); void onConnectChanged(); // 网络连接变化时发送该信号 }; #endif ukui-screensaver/KylinNM/src/kylin-network-interface.h0000644000175000017500000001441414205074704022034 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #ifdef __cplusplus extern "C"{ #endif typedef struct { char *if_name; }ifname; typedef struct { char *ssid;//wifi名称 int signal;//信号强度 char *safety;//安全性 }wifilist;//存放wifi信息的结构体 typedef struct { char *con_name;//网络连接名称 char *type;//网络连接类型 }conlist;//存放所有网络连接 typedef struct { char *con_name;//活动网络连接名称 char *type;//活动网络连接类型 char *dev;//活动网络所属设备 }activecon;//存放当前活动网络连接 /* * Get the network interface name. * return the struct pointer. */ ifname *kylin_network_get_ifacename(); /* * Get the all network connection. * return the struct pointer. */ conlist *kylin_network_get_conlist_info(); /* * Get the active network connection. * return the struct pointer. */ activecon *kylin_network_get_activecon_info(); /* * Create a new Ethernet connection. * @con_name is the connection name. * @if_name is the interface name. */ void kylin_network_create_new_ethernet(char *con_name,char *if_name); /* * Create a new Wifi connection. * @con_name is the connection name. * @if_name is the interface name. */ void kylin_network_create_new_wifi(char *con_name, char *if_name); /* * Delete ethernet connection. * @con_name is the connection name. */ void kylin_network_del_ethernet_con(char *con_name); /* * Set up dynamic IP allocation. * @con_name is the connection name. */ void kylin_network_set_automethod(char *con_name); /* * Set up manual IP assignment. * @con_name is the connection name. * @ip is the ip address(for example,"192.168.68.160/16") */ void kylin_network_set_manualmethod(char *con_name,char *ip); /* * Set up manual all prop. */ void kylin_network_set_manualall(char *con_name, char *addr, char *mask, char *gateway, char *dns); /* * Sets whether the connection is automatic. * @con_name is the connection name. * @autocon is the automatic connection option. */ void kylin_network_set_autoconnect(char *con_name,bool autocon); /* * Modify the ip address. * @con_name is the connection name. * @ip is the ip address(for example,"192.168.68.160/16") */ void kylin_network_mod_ip(char *con_name,char *ip); /* * Modify the gateway. * @con_name is the connection name. * @gw is the gateway address. */ void kylin_network_mod_gateway(char *con_name,char *gw); /* * Modify the dns address. * @con_name is the connection name. * @dns is the dns address. */ void kylin_network_mod_dns(char *con_name,char *dns); /* * Connect the ethernet. * @con_name is the connection name. */ void kylin_network_set_con_up(char *con_name); /* * Disconnect the ethernet. * @con_name is the connection name. */ void kylin_network_set_con_down(char *con_name); /* * Connect the wifi. * @con_name is the wifi name. * @passwd is the wifi password. */ void kylin_network_set_wifi_up(char *con_name,char *passwd); /* * Disconnect the wifi. * @if_name is the network interface name. */ void kylin_network_set_wifi_down(char *if_name); /* * Get wifi list information. * Return the struct pointer. */ wifilist *kylin_network_get_wifilist_info(); /* * Enable networking. */ void kylin_network_enable_networking(); /* * Disable networking. */ void kylin_network_disable_networking(); /* * Enable wifi. */ void kylin_network_enable_wifi(); /* * Disable wifi. */ void kylin_network_disable_wifi(); /* Get the ip address. * @if_name is the interface name. * @ipaddr is used to save the ip address. */ int kylin_network_get_ipaddr(char *if_name,char *ipaddr); /* * Get the broadcast address. * @if_name is the interface name. * @brdaddr is used to save the broadcast address. */ int kylin_network_get_brdaddr(char *if_name,char *brdaddr); /* * Get the subnet mask. * @if_name is the interface name. * @netmask is used to save the subnet mask. */ int kylin_network_get_netmask(char *if_name,char *netmask); /* * Get MAC address. * @if_name is the interface name. * @macaddr is used to save the MAC address. */ int kylin_network_get_mac(char *if_name,char *macaddr); /* Get the MTU. * @if_name is the interface name. * return the MTU value. */ int kylin_network_get_mtu(char *if_name); /* * Total upload and download data volume. * @if_name is the network interface name. * return the address of the first element of a one-dimensional long integer array. */ long *kylin_network_get_bytes(char *if_name); /* * Total upload and download data packets. * @if_name is the network interface name. * return the address of the first element of a one-dimensional long integer array. */ long *kylin_network_get_packets(char *if_name); /* * Total wrong data packets number of uploading and downloading. * @if_name is the network interface name. * return the address of the first element of a one-dimensional long integer array. */ long *kylin_network_get_errs(char *if_name); /* * Total discarded data packets number of uploading and downloading. * @if_name is the network interface name. * return the address of the first element of a one-dimensional long integer array. */ long *kylin_network_get_drop(char *if_name); /* * Total overloaded data packets number of uploading and downloading. * @if_name is the network interface name. * return the address of the first element of a one-dimensional long integer array. */ long *kylin_network_get_fifo(char *if_name); #ifdef __cplusplus } #endif #endif ukui-screensaver/KylinNM/src/backthread.cpp0000644000175000017500000003672714205074704017717 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include "kylinnm.h" //逼不得已,引入kylinnm头文件 BackThread::BackThread(QObject *parent) : QObject(parent) { cmdConnWifi = new QProcess(this); connect(cmdConnWifi , SIGNAL(readyReadStandardOutput()) , this , SLOT(on_readoutput())); connect(cmdConnWifi , SIGNAL(readyReadStandardError()) , this , SLOT(on_readerror())); cmdConnWifi->start("bash"); cmdConnWifi->waitForStarted(); } BackThread::~BackThread() { cmdConnWifi->close(); } //get the connection state of wired and wireles network IFace* BackThread::execGetIface() { IFace *iface = new IFace(); QString tmpPath = "/tmp/kylin-nm-iface-" + QDir::home().dirName(); QString cmd = "export LANG='en_US.UTF-8';export LANGUAGE='en_US';nmcli -f TYPE,DEVICE,STATE device > " + tmpPath; Utils::m_system(cmd.toUtf8().data()); // int status = system(cmd.toUtf8().data()); // if (status != 0){ syslog(LOG_ERR, "execute 'nmcli device' in function 'execGetIface' failed");} QFile file(tmpPath); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { // print information if can not open file ~/.config/kylin-nm-iface syslog(LOG_ERR, "Can't open the file ~/.config/kylin-nm-iface!"); qDebug()<<"Can't open the file ~/.config/kylin-nm-iface!"; } QString txt = file.readAll(); QStringList txtList = txt.split("\n"); file.close(); iface->lstate = 2; iface->wstate = 2; for (int i = 1; i < txtList.size(); i ++) { QString line = txtList.at(i); if (line != "") { int index1 = line.indexOf(" "); QString type = line.left(index1); QString lastStr = line.mid(index1).trimmed(); int index2 = lastStr.indexOf(" "); QString iname = lastStr.left(index2); QString istateStr = lastStr.mid(index2).trimmed(); if (type == "ethernet" && iface->lstate != 0) { // if type is wired network iface->lname = iname; if (istateStr == "unmanaged") { iface->lstate = 2; //switch of wired device is off } if (istateStr == "disconnected" || istateStr == "unavailable") { iface->lstate = 1; //wired network is disconnected } if (istateStr == "connected") { iface->lstate = 0; //wired network is connected } } if (type == "wifi" && iface->wstate != 0) { // if type is wireless network iface->wname = iname; if (istateStr == "unmanaged" || istateStr == "unavailable") { iface->wstate = 2; //switch of wireless device is off } if (istateStr == "disconnected") { iface->wstate = 1; //wireless network is disconnected } if (istateStr == "connected") { iface->wstate = 0; //wireless network is connected } } } } return iface; } //turn on the switch of network void BackThread::execEnNet() { char *chr = "nmcli networking on"; Utils::m_system(chr); // int status = system("nmcli networking on"); // if (status != 0){ syslog(LOG_ERR, "execute 'nmcli networking on' in function 'execEnNet' failed");} while (1) { if (execGetIface()->lstate != 2) { sleep(3); emit enNetDone(); emit btFinish(); break; } sleep(1); } } //turn off the switch of wireless network first, then turn off the switch of network void BackThread::execDisNet() { if (execGetIface()->wstate != 2) { char *chr = "nmcli radio wifi off"; Utils::m_system(chr); // int status = system("nmcli radio wifi off"); // if (status != 0){ syslog(LOG_ERR, "execute 'nmcli radio wifi off' in function 'execDisNet' failed");} while (1) { if (execGetIface()->wstate == 2) { emit disWifiDone(); emit btFinish(); break; } sleep(1); } } char *chr1 = "nmcli networking off"; Utils::m_system(chr1); // int status1 = system("nmcli networking off"); // if (status1 != 0){ syslog(LOG_ERR, "execute 'nmcli networking off' in function 'execDisNet' failed");} while (1) { if (execGetIface()->lstate == 2) { emit disNetDone(); emit btFinish(); break; } sleep(1); } } //turn on the switch of wireless network void BackThread::execEnWifi() { //if (execGetIface()->lstate == 2){ // char *chr = "nmcli networking on"; // Utils::m_system(chr); // //int status = system("nmcli networking on"); // //if (status != 0){ syslog(LOG_ERR, "execute 'nmcli networking on' in function 'execEnWifi' failed");} // while(1){ // if (execGetIface()->lstate != 2){ // emit launchLanDone(); // break; // } // sleep(1); // } //} char *chr1 = "nmcli radio wifi on"; Utils::m_system(chr1); //int status1 = system("nmcli radio wifi on"); //if (status1 != 0){ syslog(LOG_ERR, "execute 'nmcli radio wifi on' in function 'execEnWifi' failed");} while (1) { if (execGetIface()->wstate != 2) { KylinDBus objKyDbus; while (1) { if (objKyDbus.getAccessPointsNumber() > 0) { // objKyDbus.getAccessPointsNumber()>0 standard can get wireless accesspoints now KylinNM::reflashWifiUi(); emit enWifiDone(); emit btFinish(); break; } sleep(2); } break; } sleep(1); } } //turn off the switch of wireless network void BackThread::execDisWifi() { char *chr = "nmcli radio wifi off"; Utils::m_system(chr); // int status = system("nmcli radio wifi off"); // if (status != 0){ syslog(LOG_ERR, "execute 'nmcli radio wifi off' in function 'execDisWifi' failed");} while (1) { if (execGetIface()->wstate == 2) { KylinNM::reflashWifiUi(); emit disWifiDone(); emit btFinish(); break; } sleep(1); } } //to connect wired network void BackThread::execConnLan(QString connName) { disConnLanOrWifi("ethernet"); KylinDBus objKyDbus; if (objKyDbus.isWiredCableOn) { // only if wired cable is plug in, can connect wired network QString cmd = "export LANG='en_US.UTF-8';export LANGUAGE='en_US';nmcli connection up \"" + connName.replace("\"","\\\"") + "\""; Utils::m_system(cmd.toUtf8().data()); // int status = system(cmd.toUtf8().data()); // if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection up' in function 'execConnLan' failed");} qDebug()<<"debug: in function execConnLan, wired net state is: "<lstate); syslog(LOG_DEBUG, "In function execConnLan, wired net state is: %d", execGetIface()->lstate); emit connDone(0); } else { qDebug()<<"connect wired network failed for without wired cable plug in."; syslog(LOG_DEBUG, "connect wired network failed for without wired cable plug in."); emit connDone(1); } emit btFinish(); } //to connected wireless network need a password void BackThread::execConnWifiPWD(QString connName, QString password) { //disConnLanOrWifi("wifi"); QString tmpPath = "/tmp/kylin-nm-btoutput-" + QDir::home().dirName(); QString cmdStr = "export LANG='en_US.UTF-8';export LANGUAGE='en_US';nmcli device wifi connect \"" + connName.replace("\"","\\\"") + "\" password \"" + password.replace("\"","\\\"") + "\" > " + tmpPath; Utils::m_system(cmdStr.toUtf8().data()); // int status = system(cmdStr.toUtf8().data()); // if (status != 0){ syslog(LOG_ERR, "execute 'nmcli device wifi connect' in function 'execConnWifiPWD' failed");} QFile file(tmpPath); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { syslog(LOG_DEBUG, "Can't open the file /tmp/kylin-nm-btoutput !"); qDebug()<<"Can't open the file /tmp/kylin-nm-btoutput !"<wstate); syslog(LOG_DEBUG, "In function execConnWifiPWD, wireless net state is: %d", execGetIface()->wstate); } else { emit connDone(1); } emit btFinish(); } //to connected wireless network driectly do not need a password void BackThread::execConnWifi(QString connName) { //disConnLanOrWifi("wifi"); QString cmdStr = "export LANG='en_US.UTF-8';export LANGUAGE='en_US';nmcli connection up \"" + connName.replace("\"","\\\"") + "\"\n"; cmdConnWifi->write(cmdStr.toUtf8().data()); } void BackThread::on_readoutput() { QString str = cmdConnWifi->readAllStandardOutput(); cmdConnWifi->close(); qDebug()<<"on_readoutput: "<< str; if (str.indexOf("successfully") != -1) { emit connDone(0); //send this signal if connect net successfully qDebug()<<"debug: in function on_readoutput, wireless net state is: "<wstate); syslog(LOG_DEBUG, "In function on_readoutput, wireless net state is: %d", execGetIface()->wstate); } else if(str.indexOf("unknown") != -1) { emit connDone(2); } else { emit connDone(1); } emit btFinish(); } void BackThread::on_readerror() { QString str = cmdConnWifi->readAllStandardError(); cmdConnWifi->close(); qDebug()<<"on_readerror: "<< str; if (str.indexOf("successfully") != -1) { emit connDone(0); } else if(str.indexOf("unknown") != -1 || str.indexOf("not exist") != -1) { emit connDone(2); //send this signal if the network we want to connect has not a configuration file } else { emit connDone(1); //send this signal if connect net failed } emit btFinish(); } //get property of connected network QString BackThread::getConnProp(QString connName) { QString tmpPath = "/tmp/kylin-nm-connprop-" + QDir::home().dirName(); QString cmd = "export LANG='zh_CN.UTF-8';export LANGUAGE='zh_CN';nmcli connection show \"" + connName.replace("\"","\\\"") + "\" > " + tmpPath; Utils::m_system(cmd.toUtf8().data()); // int status = system(cmd.toUtf8().data()); // if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection show' in function 'getConnProp' failed");} QFile file(tmpPath); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { syslog(LOG_ERR, "Can't open the file /tmp/kylin-nm-connprop!"); qDebug()<<"Can't open the file /tmp/kylin-nm-connprop!"< " + tmpPath; Utils::m_system(cmd.toUtf8().data()); // int status = system(cmd.toUtf8().data()); // if (status != 0){ syslog(LOG_ERR, "execute 'ethtool' in function 'execChkLanWidth' failed");} QFile file(tmpPath); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { syslog(LOG_ERR, "Can't open the file /tmp/kylin-nm-bandwidth!"); qDebug()<<"Can't open the file /tmp/kylin-nm-bandwidth!"< ConfForm 0 0 446 576 0 0 446 581 0 200 446 280 175 15 250 32 10 175 60 250 32 10 175 105 250 32 10 175 150 250 32 10 20 20 80 20 Noto Sans CJK SC 11 20 65 80 20 Noto Sans CJK SC 11 20 110 80 20 Noto Sans CJK SC 11 20 155 80 20 Noto Sans CJK SC 11 175 195 250 32 10 20 200 80 20 Noto Sans CJK SC 11 0 0 446 200 170 60 182 32 10 20 135 80 20 Noto Sans CJK SC 11 20 90 80 20 Noto Sans CJK SC 11 135 75 290 48 10 0 0 446 48 408 8 24 24 24 10 240 22 180 130 111 28 356 130 50 28 0 480 446 96 312 25 112 48 10 180 25 112 48 10 312 25 112 48 10 200 426 1 Qt::Horizontal 10 480 426 1 Qt::Horizontal ukui-screensaver/KylinNM/src/kylinnm.cpp0000644000175000017500000032435114205074704017301 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include "kylinnm.h" #include "ui_kylinnm.h" #include "swipegesturerecognizer.h" QString llname, lwname, hideWiFiConn; int currentActWifiSignalLv, count_loop; bool KylinNM::m_is_reflashWifiUi = false; QMutex mutexIsReflashWifi; KylinNM::KylinNM(QWidget *parent) : QWidget(parent), ui(new Ui::KylinNM) { ui->setupUi(this); qDebug() << "99999999999999999999999999--------------9"; //checkSingle(); syslog(LOG_DEBUG, "Using the icon theme named 'ukui-icon-theme-default'"); //QIcon::setThemeName("ukui-icon-theme-default"); // 如果使用Qt::Popup 任务栏不显示且保留X事件如XCB_FOCUS_OUT, 但如果indicator点击鼠标右键触发,XCB_FOCUS_OUT事件依然会失效 // 如果使用Qt::ToolTip, Qt::Tool + Qt::WindowStaysOnTopHint, Qt::X11BypassWindowManagerHint等flag则会导致X事件失效 // this->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint); this->setWindowFlags(Qt::FramelessWindowHint);//QTool this->setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 //UseQssFile::setStyle("style.qss"); QPainterPath path; auto rect = this->rect(); rect.adjust(1, 1, -1, -1); path.addRoundedRect(rect, 6, 6); setProperty("blurRegion", QRegion(path.toFillPolygon().toPolygon())); this->setStyleSheet("QWidget{border:none;border-radius:16px;}"); ui->centralWidget->setStyleSheet("#centralWidget{border:none;border-radius:16px;background:rgba(255,255,255,1);}"); editQssString(); //编辑部分控件QSS createTopLanUI(); //创建顶部有线网item createTopWifiUI(); //创建顶部无线网item createOtherUI(); //创建上传下载控件,列表区无item时的说明控件 createListAreaUI(); //创建列表区域的控件 createLeftAreaUI(); //创建左侧区域控件 lname = "-1"; wname = "-1"; llname = "-1"; lwname = "-1"; hideWiFiConn = "Connect to Hidden Wi-Fi Network"; currentActWifiSignalLv = -1; count_loop = 0; createTrayIcon(); connect(trayIcon, &QSystemTrayIcon::activated, this, &KylinNM::iconActivated); connect(mShowWindow,SIGNAL(triggered()),this,SLOT(on_showWindowAction())); connect(mAdvConf,SIGNAL(triggered()),this,SLOT(on_btnAdvConf_clicked())); trayIcon->show(); objKyDBus = new KylinDBus(this); objKyDBus->initBtnWifiGsetting(); objKyDBus->initConnectionInfo(); objKyDBus->initTaskbarGsetting(); // objKyDBus->setWifiSignal(-1, ""); objNetSpeed = new NetworkSpeed(); this->confForm = new ConfForm(this->parentWidget()); this->confForm->setMainWindow(this); this->confForm->hide(); this->ksnm = new KSimpleNM(); connect(ksnm, SIGNAL(getLanListFinished(QStringList)), this, SLOT(getLanListDone(QStringList))); connect(ksnm, SIGNAL(getWifiListFinished(QStringList)), this, SLOT(getWifiListDone(QStringList))); loading = new LoadingDiv(this); connect(loading, SIGNAL(toStopLoading() ), this, SLOT(on_checkOverTime() )); checkIsWirelessDeviceOn(); //检测无线网卡是否插入 getInitLanSlist(); //初始化有线网列表 initNetwork(); //初始化网络 initTimer(); //初始化定时器 connect(ui->btnNetList, &QPushButton::clicked, this, &KylinNM::onBtnNetListClicked); connect(btnWireless, &SwitchButton::clicked,this, &KylinNM::onBtnWifiClicked); //auto app = static_cast(QCoreApplication::instance()); //app->setStyle(new CustomStyle()); //设置自定义主题 ui->btnNetList->setAttribute(Qt::WA_Hover,true); ui->btnNetList->installEventFilter(this); ui->btnWifiList->setAttribute(Qt::WA_Hover,true); ui->btnWifiList->installEventFilter(this); SwipeGestureRecognizer *fftRecognizer = new SwipeGestureRecognizer(this); Qt::GestureType fftType = QGestureRecognizer::registerRecognizer(fftRecognizer); // grabGesture(fftType); connect(fftRecognizer, &SwipeGestureRecognizer::onSwipeGesture, this, &KylinNM::onSwipeGesture); } KylinNM::~KylinNM() { trayIcon->deleteLater(); trayIconMenu->deleteLater(); delete ui; } void KylinNM::onSwipeGesture(int dx, int dy) { // qDebug() << "info: [KylinNM] onSwipeGesture dy=" << dy; if(scrollAreal->isVisible()) { // qDebug() << "info: [KylinNM] onSwipeGesture before moved " << scrollAreal->verticalScrollBar()->value(); scrollAreal->verticalScrollBar()->setValue(scrollAreal->verticalScrollBar()->value() - dy/5); // qDebug() << "info: [KylinNM] onSwipeGesture after moved " << scrollAreal->verticalScrollBar()->value(); } else if (scrollAreaw->isVisible()) { // qDebug() << "info: [KylinNM] onSwipeGesture before moved " << scrollAreaw->verticalScrollBar()->value(); scrollAreaw->verticalScrollBar()->setValue(scrollAreaw->verticalScrollBar()->value() - dy/5); // qDebug() << "info: [KylinNM] onSwipeGesture after moved " << scrollAreaw->verticalScrollBar()->value(); } } void KylinNM::checkSingle() { int fd = 0; try { QStringList homePath = QStandardPaths::standardLocations(QStandardPaths::HomeLocation); QString lockPath = homePath.at(0) + "/.config/kylin-nm-lock"; fd = open(lockPath.toUtf8().data(), O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (fd < 0) { throw -1; } } catch(...) { fd = open("/tmp/kylin-nm-lock", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); if (fd < 0) { exit(0); } } if (lockf(fd, F_TLOCK, 0)) { syslog(LOG_ERR, "Can't lock single file, kylin-network-manager is already running!"); qDebug()<<"Can't lock single file, kylin-network-manager is already running!"; exit(0); } } bool KylinNM::nativeEvent(const QByteArray &eventType, void *message, long *result) { Q_UNUSED(result); if (eventType != "xcb_generic_event_t") { return false; } xcb_generic_event_t *event = (xcb_generic_event_t*)message; switch (event->response_type & ~0x80) { case XCB_FOCUS_OUT: this->hide(); break; } return false; } bool KylinNM::eventFilter(QObject *obj, QEvent *event) { if (obj == ui->btnNetList) { if (event->type() == QEvent::HoverEnter) { if (!is_btnNetList_clicked) { ui->lbNetListBG->setStyleSheet(btnBgHoverQss); } return true; } else if(event->type() == QEvent::HoverLeave) { if (!is_btnNetList_clicked) { ui->lbNetListBG->setStyleSheet(btnBgLeaveQss); } return true; } } if (obj == ui->btnWifiList) { if (event->type() == QEvent::HoverEnter) { if (!is_btnWifiList_clicked) { ui->lbWifiListBG->setStyleSheet(btnBgHoverQss); } return true; } else if(event->type() == QEvent::HoverLeave) { if (!is_btnWifiList_clicked) { ui->lbWifiListBG->setStyleSheet(btnBgLeaveQss); } return true; } } return QWidget::eventFilter(obj,event); } /////////////////////////////////////////////////////////////////////////////// void KylinNM::tabletStyle()//平板桌面模式特有设置 { this->setFixedWidth(446+194*isTabletStyle); ui->centralWidget->setFixedWidth(446+194*isTabletStyle); ui->btnNetList->setFixedWidth(223+97*isTabletStyle); ui->btnWifiList->setFixedWidth(223+97*isTabletStyle); ui->btnWifiList->move(223+97*isTabletStyle,0); ui->lbWifiListBG->move(223+97*isTabletStyle,0); ui->lbNetListImg->move(16+95*isTabletStyle,17); ui->lbWifiListImg->move(288+144*isTabletStyle,17); scrollAreal->resize(W_SCROLL_AREA+194*isTabletStyle, H_SCROLL_AREA); scrollAreaw->resize(W_SCROLL_AREA+194*isTabletStyle, H_SCROLL_AREA); lbNetListText->move(98+48*isTabletStyle,2); lbWifiListText->move(98+48*isTabletStyle,2); confForm->tabletStyle(isTabletStyle); btnWireless->move(385+194*isTabletStyle,73); lbNoItemTip->move(this->width()/2 - lbNoItemTip->width()/2, this->height()/2+30); if(isTabletStyle) { btnOffQss = "QLabel{min-width: 320px; min-height: 56px;max-width:320px; max-height: 56px;border-radius: 16px; background-color:rgba(255,255,255,0);}"; btnOnQss = "QLabel{min-width: 320px; min-height: 56px;max-width:320px; max-height: 56px;border-radius: 16px; background-color:rgba(61,107,229,1);}"; } else { btnOffQss = "QLabel{min-width: 221px; min-height: 56px;max-width:221px; max-height: 56px;border-radius: 16px; background-color:rgba(255,255,255,0)}"; btnOnQss = "QLabel{min-width: 221px; min-height: 56px;max-width:221px; max-height: 56px;border-radius: 16px; background-color:rgba(61,107,229,1);}"; } if(scrollAreal->isHidden())//首次运行初始化大按钮状态 { ui->btnNetList->setStyleSheet(btnOffQss); ui->btnWifiList->setStyleSheet(btnOnQss); ui->lbNetListBG->setStyleSheet(btnOffQss); ui->lbWifiListBG->setStyleSheet(btnOnQss); ui->lbNetListImg->setStyleSheet("QLabel{border-image:url(:/res/l/pb-network-offline.png);background-position:center;background-repeat:no-repeat;}"); ui->lbWifiListImg->setStyleSheet("QLabel{border-image:url(:/res/x/pb-wifi-y.png);background-position:center;background-repeat:no-repeat;}"); lbNetListText->setStyleSheet("QLabel{color:rgba(38, 38, 38, 0.75);background-color:transparent;}"); lbWifiListText->setStyleSheet("QLabel{color:rgba(47, 179, 232, 1);background-color:transparent;}"); } } // 初始化控件、网络、定时器 // 初始化界面各控件 void KylinNM::editQssString() { btnOffQss = "QLabel{min-width: 221px; min-height: 56px;max-width:221px; max-height: 56px;border-radius: 16px; background-color:rgba(38,38,38,0.15)}"; btnOnQss = "QLabel{min-width: 221px; min-height: 56px;max-width:221px; max-height: 56px;border-radius: 16px; background-color:rgba(255,255,255,0.2)}"; btnBgOffQss = "QLabel{min-width: 48px; min-height: 22px;max-width:48px; max-height: 22px;border-radius: 16px; background-color:rgba(38,38,38,0.15)}"; btnBgOnQss = "QLabel{min-width: 48px; min-height: 22px;max-width:48px; max-height: 22px;border-radius: 16px; background-color:rgba(255,255,255,0.2);}"; btnBgHoverQss = "QLabel{border-radius: 16px; background-color:rgba(38,38,38,0.2)}"; btnBgLeaveQss = "QLabel{border-radius: 16px; background-color:rgba(38,38,38,0.15)}"; leftBtnQss = "QPushButton{border:0px;border-radius:4px;background-color:rgba(255,255,255,0);}" "QPushButton:Hover{border:0px solid rgba(255,255,255,0.2);border-radius:4px;background-color:rgba(255,255,255,0.12);}" "QPushButton:Pressed{border-radius:4px;background-color:rgba(255,255,255,0.12);}"; // funcBtnQss = "QPushButton{border:0px;border-radius:4px;background-color:rgba(255,255,255,0);color:rgba(107,142,235,0.97);font-size:14px;}" // "QPushButton:Hover{border:0px;border-radius:4px;background-color:rgba(255,255,255,0);color:rgba(151,175,241,0.97);font-size:14px;}" // "QPushButton:Pressed{border-radius:4px;background-color:rgba(255,255,255,0);color:rgba(61,107,229,0.97);font-size:14px;}"; funcBtnQss="QPushButton{border:0px;border-radius:4px;background-color:rgba(255,255,255,0);color:rgba(38,38,38,1);font-size:14px;text-align:left;}"; } void KylinNM::createTopLanUI() { topLanListWidget = new QWidget(ui->centralWidget); topLanListWidget->move(W_LEFT_AREA, Y_TOP_ITEM); topLanListWidget->resize(W_TOP_LIST_WIDGET, H_NORMAL_ITEM + H_GAP_UP + X_ITEM); /*顶部的一个item*/ lbTopLanList = new QLabel(topLanListWidget); lbTopLanList->setText(tr("Ethernet Networks"));//"可用网络列表" lbTopLanList->resize(W_MIDDLE_WORD, H_MIDDLE_WORD); lbTopLanList->move(X_MIDDLE_WORD, H_NORMAL_ITEM + H_GAP_UP); lbTopLanList->setStyleSheet("QLabel{font-size:14px;color:rgba(38, 38, 38, 0.45);}"); lbTopLanList->show(); /*新建有线网按钮*/ // btnCreateNet = new QPushButton(ui->centralWidget); // btnCreateNet->resize(W_BTN_FUN, H_BTN_FUN); // btnCreateNet->move(X_BTN_FUN, Y_BTN_FUN); // btnCreateNet->setText(" "+tr("New LAN"));//"新建网络" // btnCreateNet->setIcon(QIcon(":/res/x/pb-newConn.png")); // btnCreateNet->setStyleSheet(funcBtnQss); // btnCreateNet->setFocusPolicy(Qt::NoFocus); // btnCreateNet->show(); // connect(btnCreateNet,SIGNAL(clicked()),this,SLOT(onBtnCreateNetClicked())); } void KylinNM::createTopWifiUI() { topWifiListWidget = new QWidget(ui->centralWidget); topWifiListWidget->move(W_LEFT_AREA, Y_TOP_ITEM); topWifiListWidget->resize(W_TOP_LIST_WIDGET+194*isTabletStyle, H_NORMAL_ITEM + H_GAP_UP + X_ITEM); /*顶部的一个item*/ lbTopWifiList = new QLabel(topWifiListWidget); lbTopWifiList->setText(tr("Wifi Networks"));//"可用网络列表" lbTopWifiList->resize(W_MIDDLE_WORD, H_MIDDLE_WORD); lbTopWifiList->move(X_MIDDLE_WORD, H_NORMAL_ITEM + H_GAP_UP); lbTopWifiList->setStyleSheet("QLabel{font-size:14px;color:rgba(38, 38, 38, 0.45);}"); lbTopWifiList->show(); // /*新建无线网按钮*/ // if(!btnAddNet){ // btnAddNet = new QPushButton(ui->centralWidget); // connect(btnAddNet,SIGNAL(clicked()),this,SLOT(onBtnAddNetClicked())); // } // btnAddNet->resize(W_BTN_FUN, H_BTN_FUN); // btnAddNet->move(X_BTN_FUN, Y_BTN_FUN); // btnAddNet->setText(" "+tr("Hide WiFi"));//"加入网络" // btnAddNet->setIcon(QIcon(":/res/x/pb-newConn.png")); // btnAddNet->setStyleSheet(funcBtnQss); // btnAddNet->setFocusPolicy(Qt::NoFocus); } void KylinNM::createOtherUI() { lbLoadDown = new QLabel(ui->centralWidget); lbLoadDown->move(X_ITEM + 129, Y_TOP_ITEM + 32); lbLoadDown->resize(65, 20); lbLoadDownImg = new QLabel(ui->centralWidget); lbLoadDownImg->move(X_ITEM + 112, Y_TOP_ITEM + 35); lbLoadDownImg->resize(16, 16); lbLoadUp = new QLabel(ui->centralWidget); lbLoadUp->move(X_ITEM + 187, Y_TOP_ITEM + 32); lbLoadUp->resize(65, 20); lbLoadUpImg = new QLabel(ui->centralWidget); lbLoadUpImg->move(X_ITEM + 170, Y_TOP_ITEM + 35); lbLoadUpImg->resize(16, 16); //YYF lbLoadDownImg->setStyleSheet("QLabel{background-image:url(:/res/x/load-down.png);}"); //YYF lbLoadUpImg->setStyleSheet("QLabel{background-image:url(:/res/x/load-up.png);}"); lbNoItemTip = new QLabel(ui->centralWidget); lbNoItemTip->resize(W_NO_ITEM_TIP, H_NO_ITEM_TIP); lbNoItemTip->move(this->width()/2 - W_NO_ITEM_TIP/2 + W_LEFT_AREA/2, this->height()/2); lbNoItemTip->setStyleSheet("QLabel{border:none;background:transparent;font-size:14px;color:rgba(38, 38, 38, 0.45);}"); lbNoItemTip->setText(tr("No usable network in the list"));//列表暂无可连接网络 lbNoItemTip->setAlignment(Qt::AlignCenter); lbNoItemTip->hide(); } void KylinNM::createListAreaUI() { scrollAreal = new QScrollArea(ui->centralWidget); scrollAreal->move(W_LEFT_AREA, Y_TOP_ITEM + H_NORMAL_ITEM + H_GAP_UP + X_ITEM + H_GAP_DOWN); scrollAreal->resize(W_SCROLL_AREA, H_SCROLL_AREA); scrollAreal->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); scrollAreal->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); scrollAreaw = new QScrollArea(ui->centralWidget); scrollAreaw->move(W_LEFT_AREA, Y_TOP_ITEM + H_NORMAL_ITEM + H_GAP_UP + X_ITEM + H_GAP_DOWN); scrollAreaw->resize(W_SCROLL_AREA, H_SCROLL_AREA); scrollAreaw->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); scrollAreaw->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); lanListWidget = new QWidget(scrollAreal); wifiListWidget = new QWidget(scrollAreaw); lbLanList = new QLabel(lanListWidget); lbWifiList = new QLabel(wifiListWidget); ui->lbNetwork->setStyleSheet("QLabel{font-size:14px;color:rgba(38, 38, 38, 0.45);}"); ui->lbNetwork->show(); topLanListWidget->setStyleSheet("QWidget{border:none;}"); topLanListWidget->setStyleSheet("background-color:transparent;"); topWifiListWidget->setStyleSheet("QWidget{border:none;}"); topWifiListWidget->setStyleSheet("background-color:transparent;"); lbLoadUp->setStyleSheet("QLabel{font-size:14px;color:rgba(38, 38, 38, 0.45);}"); lbLoadDown->setStyleSheet("QLabel{font-size:14px;color:rgba(38, 38, 38, 0.45);}"); //YYF lbLoadUp->setText("0KB/s"); //YYF lbLoadDown->setText("0KB/s "); //YYF this->on_setNetSpeed(); scrollAreal->setStyleSheet("QScrollArea{border:none;}"); scrollAreal->viewport()->setStyleSheet("background-color:transparent;"); //scrollAreal->verticalScrollBar()->setStyleSheet(scrollBarQss); scrollAreaw->setStyleSheet("QScrollArea{border:none;}"); scrollAreaw->viewport()->setStyleSheet("background-color:transparent;"); //scrollAreaw->verticalScrollBar()->setStyleSheet(scrollBarQss); } void KylinNM::createLeftAreaUI() { btnWireless = new SwitchButton(this); // btnWireless->setStyleSheet("SwitchButton{border:none;background-color:rgba(255,255,255,0.12);}"); ui->btnNetList->setFocusPolicy(Qt::NoFocus); QString txtEthernet(tr("Ethernet")); ui->btnNetList->setToolTip(txtEthernet); ui->lbNetListBG->setStyleSheet(btnOffQss); lbNetListText =new QLabel(ui->lbNetListBG); lbNetListText->setFocusPolicy(Qt::NoFocus); lbNetListText->setText(tr("Ethernet")); lbNetListText->move(98,2); lbNetListText->setStyleSheet("QLabel{color:rgba(47, 179, 232, 1);background-color:transparent;}"); ui->lbNetListImg->setStyleSheet("QLabel{border-image:url(:/res/l/pb-network-online.png);background-position:center;background-repeat:no-repeat;}"); ui->btnWifiList->setFocusPolicy(Qt::NoFocus); QString txtWifi(tr("Wifi")); ui->btnWifiList->setToolTip(txtWifi); ui->lbWifiListBG->setStyleSheet(btnOffQss); lbWifiListText =new QLabel(ui->lbWifiListBG); lbWifiListText->setFocusPolicy(Qt::NoFocus); lbWifiListText->setText(tr("Wifi")); lbWifiListText->move(98,2); lbWifiListText->setStyleSheet("QLabel{color:rgba(38, 38, 38, 0.75);background-color:transparent;}"); ui->lbWifiListImg->setStyleSheet("QLabel{border-image:url(:/res/x/pb-wifi-n.png);background-position:center;background-repeat:no-repeat;}"); ui->btnNet->hide(); btnWireless->move(385,73); ui->btnHotspot->setStyleSheet(leftBtnQss); ui->btnHotspot->setFocusPolicy(Qt::NoFocus); QString txtHotSpot(tr("HotSpot")); ui->btnHotspot->setToolTip(txtHotSpot); ui->btnHotspot->hide(); ui->lbHotImg->hide(); ui->lbHotImg->setStyleSheet("QLabel{background-image:url(:/res/x/hot-spot-off.svg);}"); ui->lbHotBG->hide(); ui->lbHotBG->setStyleSheet(btnOffQss); ui->btnFlyMode->setStyleSheet(leftBtnQss); ui->btnFlyMode->setFocusPolicy(Qt::NoFocus); QString txtFlyMode(tr("FlyMode")); ui->btnFlyMode->setToolTip(txtFlyMode); ui->btnFlyMode->hide(); ui->lbFlyImg->hide(); ui->lbFlyImg->setStyleSheet("QLabel{background-image:url(:/res/x/fly-mode-off.svg);}"); ui->lbFlyBG->hide(); ui->lbFlyBG->setStyleSheet(btnOffQss); ui->btnAdvConf->setStyleSheet(leftBtnQss); ui->btnAdvConf->setFocusPolicy(Qt::NoFocus); QString txtAdvanced(tr("Advanced")); ui->btnAdvConf->setToolTip(txtAdvanced); //ui->lbBtnConfImg->setStyleSheet("QLabel{background-image:url(:/res/x/setup.png);}"); ui->btnConfImg->setStyleSheet("QPushButton{background-image:url(:/res/x/setup.png);}"); //ui->btnConfImg->setIcon(QIcon::fromTheme("settings-app-symbolic.svg", QIcon(":/res/x/setup.png")) ); } // 初始化有线网列表 void KylinNM::getInitLanSlist() { const int BUF_SIZE = 1024; char buf[BUF_SIZE]; FILE * p_file = NULL; p_file = popen("export LANG='en_US.UTF-8';export LANGUAGE='en_US';nmcli -f type,device,name connection show", "r"); if (!p_file) { syslog(LOG_ERR, "Error occurred when popen cmd 'nmcli connection show'"); qDebug()<<"Error occurred when popen cmd 'nmcli connection show"; } while (fgets(buf, BUF_SIZE, p_file) != NULL) { QString strSlist = ""; QString line(buf); strSlist = line.trimmed(); if (strSlist.indexOf("UUID") != -1 || strSlist.indexOf("NAME") != -1) { oldLanSlist.append(strSlist); } if (strSlist.indexOf("802-3-ethernet") != -1 || strSlist.indexOf("ethernet") != -1) { oldLanSlist.append(strSlist); } } pclose(p_file); } // 初始化网络 void KylinNM::initNetwork() { BackThread *bt = new BackThread(); IFace *iface = bt->execGetIface(); wname = iface->wname; lwname = iface->wname; lname = iface->lname; llname = iface->lname; mwBandWidth = bt->execChkLanWidth(lname); // 开关状态 qDebug()<<"==="; qDebug()<<"state of network: '0' is connected, '1' is disconnected, '2' is net device switch off"; syslog(LOG_DEBUG, "state of network: '0' is connected, '1' is disconnected, '2' is net device switch off"); qDebug()<<"current network state: lan state ="<lstate<<", wifi state ="<wstate ; syslog(LOG_DEBUG, "current network state: wired state =%d, wifi state =%d", iface->lstate, iface->wstate); qDebug()<<"==="; //ui->lbBtnNetBG->setStyleSheet(btnOnQss); if (iface->wstate == 0 || iface->wstate == 1) { // ui->lbBtnWifiBG->setStyleSheet(btnBgOnQss); //ui->lbBtnWifiBall->move(X_RIGHT_WIFI_BALL, Y_WIFI_BALL); btnWireless->setSwitchStatus(true); } else { btnWireless->setSwitchStatus(false); //ui->lbBtnWifiBG->setStyleSheet(btnBgOffQss); //ui->lbBtnWifiBall->move(X_LEFT_WIFI_BALL, Y_WIFI_BALL); } // 初始化网络列表 if (iface->wstate != 2) { if (iface->wstate == 0) { connWifiDone(3); } else { if (iface->lstate == 0) { connLanDone(3); } } on_btnWifiList_clicked(); ui->btnNetList->setStyleSheet("QPushButton{border:0px solid rgba(255,255,255,0);background-color:rgba(255,255,255,0);}"); ui->btnWifiList->setStyleSheet("QPushButton{border:none;}"); } else { objKyDBus->setWifiSwitchState(false); //通知控制面板wifi未开启 if (iface->lstate != 2) { if (iface->lstate == 0) { connLanDone(3); } onBtnNetListClicked(); ui->btnNetList->setStyleSheet("QPushButton{border:0px solid rgba(255,255,255,0);background-color:rgba(255,255,255,0);}"); ui->btnWifiList->setStyleSheet("QPushButton{border:none;}"); } else { /*没看懂这段断开连接是什么意思,暂时关闭这段操作,会导致页面卡顿、某些情景还会自动断开网络 // BackThread *m_bt = new BackThread(); // IFace *m_iface = m_bt->execGetIface(); // m_bt->disConnLanOrWifi("ethernet"); // sleep(1); // m_bt->disConnLanOrWifi("ethernet"); // sleep(1); // m_bt->disConnLanOrWifi("ethernet"); // delete m_iface; // m_bt->deleteLater(); */ char *chr = "nmcli networking on"; Utils::m_system(chr); } } //第一次加载时,加载完lan列表会继续加载WIFI列表,先加载lan后加载WIFI是为了保证在加载WIFI时打开的计时器不会被直接关闭 onBtnNetListClicked(); //平板上默认展示wifi界面 // on_btnWifiList_clicked(); } // 初始化定时器 void KylinNM::initTimer() { //循环检测wifi列表的变化,可用于更新wifi列表 checkWifiListChanged = new QTimer(this); checkWifiListChanged->setTimerType(Qt::PreciseTimer); QObject::connect(checkWifiListChanged, SIGNAL(timeout()), this, SLOT(on_checkWifiListChanged())); checkWifiListChanged->start(7000); //网线插入时定时执行 wiredCableUpTimer = new QTimer(this); wiredCableUpTimer->setTimerType(Qt::PreciseTimer); QObject::connect(wiredCableUpTimer, SIGNAL(timeout()), this, SLOT(onCarrierUpHandle())); //网线拔出时定时执行 wiredCableDownTimer = new QTimer(this); wiredCableDownTimer->setTimerType(Qt::PreciseTimer); QObject::connect(wiredCableDownTimer, SIGNAL(timeout()), this, SLOT(onCarrierDownHandle())); //定时处理异常网络,即当点击Lan列表按钮时,若lstate=2,但任然有有线网连接的情况 deleteLanTimer = new QTimer(this); deleteLanTimer->setTimerType(Qt::PreciseTimer); QObject::connect(deleteLanTimer, SIGNAL(timeout()), this, SLOT(onDeleteLan())); //定时获取网速 setNetSpeed = new QTimer(this); setNetSpeed->setTimerType(Qt::PreciseTimer); //YYF QObject::connect(setNetSpeed, SIGNAL(timeout()), this, SLOT(on_setNetSpeed())); setNetSpeed->start(3000); } /////////////////////////////////////////////////////////////////////////////// // 任务栏托盘管理、托盘图标处理 void KylinNM::createTrayIcon() { trayIcon = new QSystemTrayIcon(); trayIcon->setToolTip(QString(tr("kylin-nm"))); trayIconMenu = new QMenu(); mShowWindow = new QAction(tr("Show KylinNM"),this); mAdvConf = new QAction(tr("Advanced"),this); mAdvConf->setIcon(QIcon::fromTheme("document-page-setup", QIcon(":/res/x/setup.png")) ); trayIconMenu->addAction(mShowWindow); //trayIconMenu->addSeparator(); trayIconMenu->addAction(mAdvConf); //trayIconMenu->setAttribute(Qt::WA_TranslucentBackground);//设置窗口背景透明 //trayIconMenu->setWindowOpacity(0.8); trayIcon->setContextMenu(trayIconMenu); // 初始化托盘所有Icon iconLanOnline = QIcon::fromTheme("network-wired-symbolic"); iconLanOffline = QIcon::fromTheme("network-wired-offline-symbolic"); iconWifiFull = QIcon::fromTheme("network-wireless-signal-excellent-symbolic"); iconWifiHigh = QIcon::fromTheme("network-wireless-signal-good-symbolic"); iconWifiMedium = QIcon::fromTheme("network-wireless-signal-ok"); iconWifiLow = QIcon::fromTheme("network-wireless-signal-low"); loadIcons.append(QIcon::fromTheme("kylin-network-1")); loadIcons.append(QIcon::fromTheme("kylin-network-2")); loadIcons.append(QIcon::fromTheme("kylin-network-3")); loadIcons.append(QIcon::fromTheme("kylin-network-4")); loadIcons.append(QIcon::fromTheme("kylin-network-5")); loadIcons.append(QIcon::fromTheme("kylin-network-6")); loadIcons.append(QIcon::fromTheme("kylin-network-7")); loadIcons.append(QIcon::fromTheme("kylin-network-8")); loadIcons.append(QIcon::fromTheme("kylin-network-9")); loadIcons.append(QIcon::fromTheme("kylin-network-10")); loadIcons.append(QIcon::fromTheme("kylin-network-11")); loadIcons.append(QIcon::fromTheme("kylin-network-12")); iconTimer = new QTimer(this); connect(iconTimer, SIGNAL(timeout()), this, SLOT(iconStep())); setTrayIcon(iconLanOnline); } void KylinNM::iconStep() { if (currentIconIndex < 0) { currentIconIndex = 11; } setTrayIcon(loadIcons.at(currentIconIndex)); currentIconIndex --; } void KylinNM::setTrayIcon(QIcon icon) { trayIcon->setIcon(icon); } void KylinNM::setTrayLoading(bool isLoading) { if (isLoading) { currentIconIndex = 11; iconTimer->start(60); } else { iconTimer->stop(); } } void KylinNM::updateNetList() { QString strTrans; strTrans = QString::number(1, 10, 2); //QString sty = "#centralWidget{background:rgba(19,19,20," + strTrans + ");}"; //YYF QString sty = "#centralWidget{background:rgba(255,255,255," + strTrans + ");}"; ui->centralWidget->setStyleSheet(sty); this->showNormal(); if (is_btnNetList_clicked == 1) { onBtnNetListClicked(0); } is_stop_check_net_state = 1; if (is_btnWifiList_clicked == 1) { BackThread *loop_bt = new BackThread(); IFace *loop_iface = loop_bt->execGetIface(); if (loop_iface->wstate != 2) { is_update_wifi_list = 1; this->ksnm->execGetWifiList(); //更新wifi列表 } delete loop_iface; loop_bt->deleteLater(); } is_stop_check_net_state = 0; } void KylinNM::updateWifiList() { //每次展示都要显示无线 on_btnWifiList_clicked(); } void KylinNM::iconActivated(QSystemTrayIcon::ActivationReason reason) { switch (reason) { case QSystemTrayIcon::Trigger: case QSystemTrayIcon::MiddleClick: handleIconClicked(); if (this->isHidden()) { QString strTrans; strTrans = QString::number(1, 10, 2); //QString sty = "#centralWidget{background:rgba(19,19,20," + strTrans + ");}"; //YYF QString sty = "#centralWidget{background:rgba(255,255,255," + strTrans + ");}"; ui->centralWidget->setStyleSheet(sty); this->showNormal(); if (is_btnNetList_clicked == 1) { onBtnNetListClicked(0); } is_stop_check_net_state = 1; if (is_btnWifiList_clicked == 1) { BackThread *loop_bt = new BackThread(); IFace *loop_iface = loop_bt->execGetIface(); if (loop_iface->wstate != 2) { is_update_wifi_list = 1; this->ksnm->execGetWifiList(); //更新wifi列表 } delete loop_iface; loop_bt->deleteLater(); } is_stop_check_net_state = 0; } else { this->hide(); } break; case QSystemTrayIcon::DoubleClick: this->hide(); break; case QSystemTrayIcon::Context: //右键点击托盘图标弹出菜单 showTrayIconMenu(); break; default: break; } } void KylinNM::handleIconClicked() { tabletStyle(); if(isTabletStyle)//平板桌面模式 { //在屏幕中央显示 QRect availableGeometry = qApp->primaryScreen()->availableGeometry(); this->move((availableGeometry.width() - this->width())/2, (availableGeometry.height() - this->height())/2); return; } QRect availableGeometry = qApp->primaryScreen()->availableGeometry(); QRect screenGeometry = qApp->primaryScreen()->geometry(); QDesktopWidget* desktopWidget = QApplication::desktop(); QRect deskMainRect = desktopWidget->availableGeometry(0);//获取可用桌面大小 QRect screenMainRect = desktopWidget->screenGeometry(0);//获取设备屏幕大小 QRect deskDupRect = desktopWidget->availableGeometry(1);//获取可用桌面大小 QRect screenDupRect = desktopWidget->screenGeometry(1);//获取设备屏幕大小 int n = objKyDBus->getTaskBarPos("position"); int m = objKyDBus->getTaskBarHeight("height"); int d = 2; //窗口边沿到任务栏距离 if (screenGeometry.width() == availableGeometry.width() && screenGeometry.height() == availableGeometry.height()) { if (n == 0) { //任务栏在下侧 this->move(availableGeometry.x() + availableGeometry.width() - this->width(), screenMainRect.y() + availableGeometry.height() - this->height() - m - d); } else if(n == 1) { //任务栏在上侧 this->move(availableGeometry.x() + availableGeometry.width() - this->width(), screenMainRect.y() + screenGeometry.height() - availableGeometry.height() + m + d); } else if (n == 2) { //任务栏在左侧 if (screenGeometry.x() == 0) {//主屏在左侧 this->move(m + d, screenMainRect.y() + screenMainRect.height() - this->height()); } else {//主屏在右侧 this->move(screenMainRect.x() + m + d, screenMainRect.y() + screenMainRect.height() - this->height()); } } else if (n == 3) { //任务栏在右侧 if (screenGeometry.x() == 0) {//主屏在左侧 this->move(screenMainRect.width() - this->width() - m - d, screenMainRect.y() + screenMainRect.height() - this->height()); } else {//主屏在右侧 this->move(screenMainRect.x() + screenMainRect.width() - this->width() - m - d, screenMainRect.y() + screenMainRect.height() - this->height()); } } } else if(screenGeometry.width() == availableGeometry.width() ) { if (trayIcon->geometry().y() > availableGeometry.height()/2) { //任务栏在下侧 this->move(availableGeometry.x() + availableGeometry.width() - this->width(), screenMainRect.y() + availableGeometry.height() - this->height() - d); } else { //任务栏在上侧 this->move(availableGeometry.x() + availableGeometry.width() - this->width(), screenMainRect.y() + screenGeometry.height() - availableGeometry.height() + d); } } else if (screenGeometry.height() == availableGeometry.height()) { if (trayIcon->geometry().x() > availableGeometry.width()/2) { //任务栏在右侧 this->move(availableGeometry.x() + availableGeometry.width() - this->width() - d, screenMainRect.y() + screenGeometry.height() - this->height()); } else { //任务栏在左侧 this->move(screenGeometry.width() - availableGeometry.width() + d, screenMainRect.y() + screenGeometry.height() - this->height()); } } } void KylinNM::showTrayIconMenu() { QRect availableGeometry = qApp->primaryScreen()->availableGeometry(); QRect screenGeometry = qApp->primaryScreen()->geometry(); QDesktopWidget* desktopWidget = QApplication::desktop(); // QRect deskMainRect = desktopWidget->availableGeometry(0);//获取可用桌面大小 QRect screenMainRect = desktopWidget->screenGeometry(0);//获取设备屏幕大小 // QRect deskDupRect = desktopWidget->availableGeometry(1);//获取可用桌面大小 QRect screenDupRect = desktopWidget->screenGeometry(1);//获取设备屏幕大小 QPoint cursorPoint = QCursor::pos();//返回相对显示器的全局坐标 int cursor_x = cursorPoint.x(); int cursor_y = cursorPoint.y(); int n = objKyDBus->getTaskBarPos("position"); int m = objKyDBus->getTaskBarHeight("height"); int d = 0; //窗口边沿到任务栏距离 int s = 80; //窗口边沿到屏幕边沿距离 if (screenGeometry.width() == availableGeometry.width() && screenGeometry.height() == availableGeometry.height()) { if (n == 0) { //任务栏在下侧 trayIconMenu->move(availableGeometry.x() + cursor_x - trayIconMenu->width()/2, screenMainRect.y() + availableGeometry.height() - trayIconMenu->height() - m - d); } else if(n == 1) { //任务栏在上侧 trayIconMenu->move(availableGeometry.x() + cursor_x - trayIconMenu->width()/2, screenMainRect.y() + screenGeometry.height() - availableGeometry.height() + m + d); } else if (n == 2) { //任务栏在左侧 trayIconMenu->move(m + d, cursor_y - trayIconMenu->height()/2); //if (screenGeometry.x() == 0){//主屏在左侧 // trayIconMenu->move(screenGeometry.width() - availableGeometry.width() + m + d, screenMainRect.y() + screenMainRect.height() - trayIconMenu->height() - s); //}else{//主屏在右侧 // trayIconMenu->move(screenGeometry.width() - availableGeometry.width() + m + d,screenDupRect.y() + screenDupRect.height() - trayIconMenu->height() - s); //} } else if (n == 3) { //任务栏在右侧 trayIconMenu->move(screenMainRect.width() - trayIconMenu->width() - m - d, cursor_y - trayIconMenu->height()/2); //if (screenGeometry.x() == 0){//主屏在左侧 // trayIconMenu->move(screenMainRect.width() + screenDupRect.width() - trayIconMenu->width() - m - d, screenDupRect.y() + screenDupRect.height() - trayIconMenu->height() - s); //}else{//主屏在右侧 // trayIconMenu->move(availableGeometry.x() + availableGeometry.width() - trayIconMenu->width() - m - d, screenMainRect.y() + screenMainRect.height() - trayIconMenu->height() - s); //} } } else if(screenGeometry.width() == availableGeometry.width() ) { if (trayIcon->geometry().y() > availableGeometry.height()/2) { //任务栏在下侧 trayIconMenu->move(availableGeometry.x() + cursor_x - trayIconMenu->width()/2, screenMainRect.y() + availableGeometry.height() - trayIconMenu->height() - d); } else { //任务栏在上侧 trayIconMenu->move(availableGeometry.x() + cursor_x - trayIconMenu->width()/2, screenMainRect.y() + screenGeometry.height() - availableGeometry.height() + d); } } else if (screenGeometry.height() == availableGeometry.height()) { if (trayIcon->geometry().x() > availableGeometry.width()/2) { //任务栏在右侧 trayIconMenu->move(availableGeometry.x() + availableGeometry.width() - trayIconMenu->width() - d, cursor_y - trayIconMenu->height()/2); } else { //任务栏在左侧 trayIconMenu->move(screenGeometry.width() - availableGeometry.width() + d, cursor_y - trayIconMenu->height()/2); } } } void KylinNM::on_showWindowAction() { handleIconClicked(); this->showNormal(); } /////////////////////////////////////////////////////////////////////////////// //加载动画,获取当前连接的网络和状态并设置图标 void KylinNM::startLoading() { // loading->startLoading(); setTrayLoading(true); } void KylinNM::stopLoading() { loading->stopLoading(); setTrayLoading(false); getActiveInfo(); } void KylinNM::on_checkOverTime() { QString cmd = "kill -9 $(pidof nmcli)"; //杀掉当前正在进行的有关nmcli命令的进程 int status = system(cmd.toUtf8().data()); if (status != 0) { qDebug()<<"execute 'kill -9 $(pidof nmcli)' in function 'on_checkOverTime' failed"; syslog(LOG_ERR, "execute 'kill -9 $(pidof nmcli)' in function 'on_checkOverTime' failed"); } this->stopLoading(); //超时停止等待动画 is_stop_check_net_state = 0; } void KylinNM::getActiveInfo() { QString actLanName = "--"; QString actWifiName = "--"; activecon *act = kylin_network_get_activecon_info(); int index = 0; while (act[index].con_name != NULL) { if (QString(act[index].type) == "ethernet" || QString(act[index].type) == "802-3-ethernet") { actLanName = QString(act[index].con_name); } if (QString(act[index].type) == "wifi" || QString(act[index].type) == "802-11-wireless") { actWifiName = QString(act[index].con_name); } index ++; } //ukui3.0中获取currentActWifiSignalLv的值 if (activeWifiSignalLv > 75) { currentActWifiSignalLv = 1; } else if(activeWifiSignalLv > 55 && activeWifiSignalLv <= 75) { currentActWifiSignalLv = 2; } else if(activeWifiSignalLv > 35 && activeWifiSignalLv <= 55) { currentActWifiSignalLv = 3; } else if( activeWifiSignalLv <= 35) { currentActWifiSignalLv = 4; } // 设置图标 if (actLanName != "--") { setTrayIcon(iconLanOnline); } else if (actWifiName != "--") { switch (currentActWifiSignalLv) { case 1: setTrayIcon(iconWifiFull); break; case 2: setTrayIcon(iconWifiHigh); break; case 3: setTrayIcon(iconWifiMedium); break; case 4: setTrayIcon(iconWifiLow); break; default: setTrayIcon(iconWifiFull); break; } } else { setTrayIcon(iconLanOffline); } } /////////////////////////////////////////////////////////////////////////////// //网络设备管理 //网线插拔处理,由kylin-dbus-interface.cpp调用 void KylinNM::onPhysicalCarrierChanged(bool flag) { this->startLoading(); if (flag) { is_stop_check_net_state = 1; qDebug()<<"插入了有线网的网线"; syslog(LOG_DEBUG,"wired physical cable is already plug in"); wiredCableUpTimer->start(2000); } else { qDebug()<<"拔出了有线网的网线"; syslog(LOG_DEBUG,"wired physical cable is already plug out"); BackThread *bt = new BackThread(); IFace *iface = bt->execGetIface(); if (iface->lstate != 0) { is_stop_check_net_state = 1; wiredCableDownTimer->start(2000); } delete iface; bt->deleteLater(); } } void KylinNM::onCarrierUpHandle() { wiredCableUpTimer->stop(); //BackThread *up_bt = new BackThread(); //up_bt->disConnLanOrWifi("ethernet"); //sleep(1); //up_bt->disConnLanOrWifi("ethernet"); //sleep(1); //up_bt->disConnLanOrWifi("ethernet"); //up_bt->deleteLater(); this->stopLoading(); onBtnNetListClicked(1); is_stop_check_net_state = 0; } void KylinNM::onCarrierDownHandle() { wiredCableDownTimer->stop(); this->stopLoading(); onBtnNetListClicked(0); is_stop_check_net_state = 0; } void KylinNM::onDeleteLan() { deleteLanTimer->stop(); BackThread *btn_bt = new BackThread(); btn_bt->disConnLanOrWifi("ethernet"); sleep(1); btn_bt->disConnLanOrWifi("ethernet"); sleep(1); btn_bt->disConnLanOrWifi("ethernet"); btn_bt->deleteLater(); this->stopLoading(); onBtnNetListClicked(0); is_stop_check_net_state = 0; } //无线网卡插拔处理 void KylinNM::onNetworkDeviceAdded(QDBusObjectPath objPath) { //仅处理无线网卡插入情况 objKyDBus->isWirelessCardOn = false; objKyDBus->getObjectPath(); if (objKyDBus->wirelessPath.path() == objPath.path()) { //证明添加的是无线网卡 is_wireless_adapter_ready = 0; if (objKyDBus->isWirelessCardOn) { syslog(LOG_DEBUG,"wireless device is already plug in"); qDebug()<<"wireless device is already plug in"; is_wireless_adapter_ready = 1; onBtnWifiClicked(4); } } } void KylinNM::onNetworkDeviceRemoved(QDBusObjectPath objPath) { //仅处理无线网卡拔出情况 if (objKyDBus->wirelessPath.path() == objPath.path()) { objKyDBus->isWirelessCardOn = false; objKyDBus->getObjectPath(); //检查是不是还有无线网卡 if (!objKyDBus->isWirelessCardOn) { syslog(LOG_DEBUG,"wireless device is already plug out"); qDebug()<<"wireless device is already plug out"; is_wireless_adapter_ready = 0; onBtnWifiClicked(5); } else { syslog(LOG_DEBUG,"wireless device is already plug out, but one more wireless exist"); qDebug()<<"wireless device is already plug out, but one more wireless exist"; } } } void KylinNM::checkIsWirelessDeviceOn() { //启动时判断是否有无线网卡 //KylinDBus kDBus3; if (objKyDBus->isWirelessCardOn) { is_wireless_adapter_ready = 1; } else { is_wireless_adapter_ready = 0; } } void KylinNM::getLanBandWidth() { BackThread *bt = new BackThread(); IFace *iface = bt->execGetIface(); lname = iface->lname; mwBandWidth = bt->execChkLanWidth(lname); } //检测网络设备状态 bool KylinNM::checkLanOn() { BackThread *bt = new BackThread(); IFace *iface = bt->execGetIface(); if (iface->lstate == 2) { return false; } else { return true; } delete iface; bt->deleteLater(); } bool KylinNM::checkWlOn() { BackThread *bt = new BackThread(); IFace *iface = bt->execGetIface(); bool ret = true; if (iface->wstate == 2) { ret = false; } delete iface; bt->deleteLater(); return ret; } /////////////////////////////////////////////////////////////////////////////// //有线网与无线网按钮响应 void KylinNM::on_btnNet_clicked() { if (checkLanOn()) { QThread *t = new QThread(); BackThread *bt = new BackThread(); bt->moveToThread(t); connect(t, SIGNAL(finished()), t, SLOT(deleteLater())); connect(t, SIGNAL(started()), bt, SLOT(execDisNet())); connect(bt, SIGNAL(disNetDone()), this, SLOT(disNetDone())); connect(bt, SIGNAL(btFinish()), t, SLOT(quit())); t->start(); } else { is_stop_check_net_state = 1; QThread *t = new QThread(); BackThread *bt = new BackThread(); bt->moveToThread(t); connect(t, SIGNAL(finished()), t, SLOT(deleteLater())); connect(t, SIGNAL(started()), bt, SLOT(execEnNet())); connect(bt, SIGNAL(enNetDone()), this, SLOT(enNetDone())); connect(bt, SIGNAL(btFinish()), t, SLOT(quit())); t->start(); } this->startLoading(); } void KylinNM::onBtnWifiClicked(int flag) { qDebug()<<"Value of flag passed into function 'onBtnWifiClicked' is: "<setWifiSwitchState(false); lbTopWifiList->hide(); // btnAddNet->hide(); QThread *t = new QThread(); BackThread *bt = new BackThread(); bt->moveToThread(t); btnWireless->setSwitchStatus(true); connect(t, SIGNAL(finished()), t, SLOT(deleteLater())); connect(t, SIGNAL(started()), bt, SLOT(execDisWifi())); connect(bt, SIGNAL(disWifiDone()), this, SLOT(disWifiDone())); connect(bt, SIGNAL(btFinish()), t, SLOT(quit())); /**锁屏多线程信号槽消息传递异常,暂时以定时器方式检测,需调整pam验证的fork方式 */ QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, [=]{ if(m_is_reflashWifiUi) { disWifiDone(); mutexIsReflashWifi.lock(); m_is_reflashWifiUi = false; mutexIsReflashWifi.unlock(); timer->stop(); } }); timer->start(200); QTimer::singleShot(8*1000, this, [=]{ if(timer->isActive()) timer->stop(); }); /**锁屏多线程信号槽消息传递异常,暂时以定时器方式检测,需调整pam验证的fork方式 */ t->start(); this->startLoading(); } } else { if (is_fly_mode_on == 0) { //on_btnWifiList_clicked(); is_stop_check_net_state = 1; qDebug() << "aaa222"; objKyDBus->setWifiCardState(true); objKyDBus->setWifiSwitchState(true); //lbTopWifiList->show(); //btnAddNet->show(); QThread *t = new QThread(); BackThread *bt = new BackThread(); bt->moveToThread(t); btnWireless->setSwitchStatus(true); connect(t, SIGNAL(finished()), t, SLOT(deleteLater())); connect(t, SIGNAL(started()), bt, SLOT(execEnWifi())); connect(bt, SIGNAL(enWifiDone()), this, SLOT(enWifiDone())); connect(bt, SIGNAL(launchLanDone()), this, SLOT(launchLanDone())); connect(bt, SIGNAL(btFinish()), t, SLOT(quit())); /**锁屏多线程信号槽消息传递异常,暂时以定时器方式检测,需调整pam验证的fork方式 */ QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, [=]{ if(m_is_reflashWifiUi) { enWifiDone(); mutexIsReflashWifi.lock(); m_is_reflashWifiUi = false; mutexIsReflashWifi.unlock(); timer->stop(); } }); timer->start(200); QTimer::singleShot(8*1000, this, [=]{ if(timer->isActive()) timer->stop(); }); t->start(); this->startLoading(); } } } else if(flag == 2) { if (is_fly_mode_on == 0) { //on_btnWifiList_clicked(); is_stop_check_net_state = 1; lbTopWifiList->show(); // btnAddNet->show(); QThread *t = new QThread(); BackThread *bt = new BackThread(); btnWireless->setSwitchStatus(true); bt->moveToThread(t); connect(t, SIGNAL(finished()), t, SLOT(deleteLater())); connect(t, SIGNAL(started()), bt, SLOT(execEnWifi())); connect(bt, SIGNAL(enWifiDone()), this, SLOT(enWifiDone())); connect(bt, SIGNAL(launchLanDone()), this, SLOT(launchLanDone())); connect(bt, SIGNAL(btFinish()), t, SLOT(quit())); t->start(); this->startLoading(); } } else if(flag == 3) { is_stop_check_net_state = 1; lbTopWifiList->hide(); // btnAddNet->hide(); QThread *t = new QThread(); BackThread *bt = new BackThread(); btnWireless->setSwitchStatus(true); bt->moveToThread(t); connect(t, SIGNAL(finished()), t, SLOT(deleteLater())); connect(t, SIGNAL(started()), bt, SLOT(execDisWifi())); connect(bt, SIGNAL(disWifiDone()), this, SLOT(disWifiDone())); connect(bt, SIGNAL(btFinish()), t, SLOT(quit())); t->start(); this->startLoading(); } else { qDebug()<<"receive an invalid value in function onBtnWifiClicked"; syslog(LOG_DEBUG, "receive an invalid value in function onBtnWifiClicked"); } } else { lbTopWifiList->hide(); // btnAddNet->hide(); if (flag == 0) { objKyDBus->setWifiSwitchState(false); objKyDBus->setWifiCardState(false); } QString txt(tr("No wireless card detected")); //未检测到无线网卡 objKyDBus->showDesktopNotify(txt); qDebug()<<"No wireless card detected"; syslog(LOG_DEBUG, "No wireless card detected"); //QString cmd = "export LANG='en_US.UTF-8';export LANGUAGE='en_US';notify-send '" + txt + "' -t 3800"; //int status = system(cmd.toUtf8().data()); //if (status != 0){ syslog(LOG_ERR, "execute 'notify-send' in function 'onBtnWifiClicked' failed");} disWifiStateKeep(); } } void KylinNM::onBtnNetListClicked(int flag) { this->is_btnNetList_clicked = 1; this->is_btnWifiList_clicked = 0; ui->lbNetListBG->setStyleSheet(btnOnQss); ui->lbWifiListBG->setStyleSheet(btnOffQss); BackThread *bt = new BackThread(); IFace *iface = bt->execGetIface(); lbLoadDown->show(); lbLoadUp->show(); lbLoadDownImg->show(); lbLoadUpImg->show(); if (iface->lstate != 0) { lbLoadDown->hide(); lbLoadUp->hide(); lbLoadDownImg->hide(); lbLoadUpImg->hide(); } lbNoItemTip->hide(); ui->lbNetwork->setText(tr("Ethernet")); btnWireless->hide(); //ui->lbBtnWifiBG->hide(); //ui->lbBtnWifiBall->hide(); // 强行设置为打开 if (flag == 1) { this->startLoading(); this->ksnm->execGetLanList(); this->scrollAreal->show(); this->topLanListWidget->show(); this->scrollAreaw->hide(); this->topWifiListWidget->hide(); on_btnNetList_pressed(); return; } if (iface->lstate != 2) { this->startLoading(); this->ksnm->execGetLanList(); } else { this->startLoading(); this->ksnm->execGetLanList(); } // btnCreateNet->show(); // btnAddNet->hide(); this->scrollAreal->show(); this->topLanListWidget->show(); this->scrollAreaw->hide(); this->topWifiListWidget->hide(); on_btnNetList_pressed(); //YYF ui->lbNetListImg->setStyleSheet("QLabel{border-image:url(:/res/l/pb-network-online.png);background-position:center;background-repeat:no-repeat;}"); ui->lbWifiListImg->setStyleSheet("QLabel{border-image:url(:/res/x/pb-wifi-n.png);background-position:center;background-repeat:no-repeat;}"); lbNetListText->setStyleSheet("QLabel{color:rgba(47, 179, 232, 1);background-color:transparent;}"); lbWifiListText->setStyleSheet("QLabel{color:rgba(38, 38, 38, 0.75);background-color:transparent;}"); delete iface; bt->deleteLater(); } // 当点击wifi标题的时候执行 void KylinNM::on_btnWifiList_clicked() { this->is_btnWifiList_clicked = 1; this->is_btnNetList_clicked = 0; BackThread *bt = new BackThread(); IFace *iface = bt->execGetIface(); lbLoadDown->show(); lbLoadUp->show(); lbLoadDownImg->show(); lbLoadUpImg->show(); if (iface->wstate != 0) { lbLoadDown->hide(); lbLoadUp->hide(); lbLoadDownImg->hide(); lbLoadUpImg->hide(); } ui->lbNetListBG->setStyleSheet(btnOffQss); ui->lbWifiListBG->setStyleSheet(btnOnQss); lbNoItemTip->hide(); ui->lbNetwork->setText(tr("Wifi")); btnWireless->show(); //ui->lbBtnWifiBG->show(); //ui->lbBtnWifiBall->show(); if (iface->wstate == 0 || iface->wstate == 1) { //ui->lbBtnWifiBG->setStyleSheet(btnBgOnQss); //ui->lbBtnWifiBall->move(X_RIGHT_WIFI_BALL, Y_WIFI_BALL); btnWireless->setSwitchStatus(true); } else { //ui->lbBtnWifiBG->setStyleSheet(btnBgOffQss); //ui->lbBtnWifiBall->move(X_LEFT_WIFI_BALL, Y_WIFI_BALL); btnWireless->setSwitchStatus(false); } if (iface->wstate != 2) { //ui->lbBtnWifiBG->setStyleSheet(btnBgOnQss); //ui->lbBtnWifiBall->move(X_RIGHT_WIFI_BALL, Y_WIFI_BALL); btnWireless->setSwitchStatus(true); lbTopWifiList->show(); // btnAddNet->show(); this->startLoading(); this->ksnm->execGetWifiList(); } else { //ui->lbBtnWifiBG->setStyleSheet(btnBgOffQss); //ui->lbBtnWifiBall->move(X_LEFT_WIFI_BALL, Y_WIFI_BALL); btnWireless->setSwitchStatus(false); delete topWifiListWidget; //清空top列表 createTopWifiUI(); //创建顶部无线网item lbTopWifiList->hide(); ui->lbNetListImg->setStyleSheet("QLabel{border-image:url(:/res/l/pb-network-offline.png);background-position:center;background-repeat:no-repeat;}"); ui->lbWifiListImg->setStyleSheet("QLabel{border-image:url(:/res/x/pb-wifi-y.png);background-position:center;background-repeat:no-repeat;}"); lbNetListText->setStyleSheet("QLabel{color:rgba(38, 38, 38, 0.75);background-color:transparent;}"); lbWifiListText->setStyleSheet("QLabel{color:rgba(47, 179, 232, 1);background-color:transparent;}"); // 清空wifi列表 wifiListWidget = new QWidget(scrollAreaw); wifiListWidget->resize(W_LIST_WIDGET+173*isTabletStyle, H_WIFI_ITEM_BIG_EXTEND); scrollAreaw->setWidget(wifiListWidget); scrollAreaw->move(W_LEFT_AREA, Y_SCROLL_AREA); // 当前连接的wifi OneConnForm *ccf = new OneConnForm(topWifiListWidget, this, confForm, ksnm); ccf->setName(tr("Not connected"));//"当前未连接任何 Wifi" ccf->setSignal("0", "--"); ccf->setRate("0"); ccf->setConnedString(1, tr("Disconnected"), "");//"未连接" ccf->isConnected = false; ccf->setTopItem(false); ccf->setAct(true); ccf->move(L_VERTICAL_LINE_TO_ITEM, 0); ccf->show(); this->lanListWidget->hide(); this->wifiListWidget->show(); getActiveInfo(); is_stop_check_net_state = 0; } // btnCreateNet->hide(); // if(is_wireless_adapter_ready == 1) // { // btnAddNet->show(); // } this->scrollAreal->hide(); this->topLanListWidget->hide(); this->scrollAreaw->show(); this->topWifiListWidget->show(); on_btnWifiList_pressed(); delete iface; bt->deleteLater(); } void KylinNM::on_btnNetList_pressed() { //ui->btnNetList->setStyleSheet("#btnNetList{font-size:12px;color:white;border:1px solid rgba(255,255,255,0.1);border:1px solid rgba(255,255,255,0.5);background:transparent;background-color:rgba(255,255,255,0.1);}"); //ui->btnWifiList->setStyleSheet("#btnWifiList{font-size:12px;color:white;border:1px solid rgba(255,255,255,0.1);background:transparent;background-color:rgba(0,0,0,0.2);}" // "#btnWifiList:Pressed{border:1px solid rgba(255,255,255,0.5);background:transparent;background-color:rgba(255,255,255,0.1);}"); } void KylinNM::on_btnWifiList_pressed() { //YYF 复制自tabletStyle方法,后期考虑合并 ui->btnNetList->setStyleSheet(btnOffQss); ui->btnWifiList->setStyleSheet(btnOnQss); ui->lbNetListBG->setStyleSheet(btnOffQss); ui->lbWifiListBG->setStyleSheet(btnOnQss); ui->lbNetListImg->setStyleSheet("QLabel{border-image:url(:/res/l/pb-network-offline.png);background-position:center;background-repeat:no-repeat;}"); ui->lbWifiListImg->setStyleSheet("QLabel{border-image:url(:/res/x/pb-wifi-y.png);background-position:center;background-repeat:no-repeat;}"); lbNetListText->setStyleSheet("QLabel{color:rgba(38, 38, 38, 0.75);background-color:transparent;}"); lbWifiListText->setStyleSheet("QLabel{color:rgba(47, 179, 232, 1);background-color:transparent;}"); //ui->btnWifiList->setStyleSheet("#btnWifiList{font-size:12px;color:white;border:1px solid rgba(255,255,255,0.1);border:1px solid rgba(255,255,255,0.5);background:transparent;background-color:rgba(255,255,255,0.1);}"); //ui->btnNetList->setStyleSheet("#btnNetList{font-size:12px;color:white;border:1px solid rgba(255,255,255,0.1);background:transparent;background-color:rgba(0,0,0,0.2);}" // "#btnNetList:Pressed{border:1px solid rgba(255,255,255,0.5);background:transparent;background-color:rgba(255,255,255,0.1);}"); } /////////////////////////////////////////////////////////////////////////////// //网络列表加载与更新 // 获取lan列表回调 void KylinNM::getLanListDone(QStringList slist) { if (this->ksnm->isUseOldLanSlist) { slist = oldLanSlist; this->ksnm->isUseOldLanSlist = false; } delete topLanListWidget; // 清空top列表 createTopLanUI(); //创建顶部有线网item // 清空lan列表 lanListWidget = new QWidget(scrollAreal); lanListWidget->resize(W_LIST_WIDGET, H_NORMAL_ITEM + H_LAN_ITEM_EXTEND); scrollAreal->setWidget(lanListWidget); scrollAreal->move(W_LEFT_AREA, Y_SCROLL_AREA); lanNameList.clear(); // 获取当前连接的lan name QString actLanName = "--"; activecon *act = kylin_network_get_activecon_info(); int index = 0; while (act[index].con_name != NULL) { if (QString(act[index].type) == "ethernet" || QString(act[index].type) == "802-3-ethernet") { actLanName = QString(act[index].con_name); break; } index ++; } // 若当前lan name为"--",设置OneConnForm OneLancForm *ccf = new OneLancForm(topLanListWidget, this, confForm, ksnm); topLanListWidget->resize(W_TOP_LIST_WIDGET+173*isTabletStyle, H_NORMAL_ITEM + H_GAP_UP + X_ITEM); ccf->setFixedWidth(414+194*isTabletStyle); if (actLanName == "--") { ccf->setName(tr("Not connected"), "");//"当前未连接任何 以太网" ccf->setIcon(false); ccf->setConnedString(1, tr("Disconnected"));//"未连接" ccf->isConnected = false; ifLanConnected = false; lbLoadDown->hide(); lbLoadUp->hide(); lbLoadDownImg->hide(); lbLoadUpImg->hide(); ccf->setTopItem(false); ccf->setAct(false); } else ccf->setAct(true); ccf->move(L_VERTICAL_LINE_TO_ITEM, 0); ccf->show(); // 填充可用网络列表 QString headLine = slist.at(0); int indexDevice, indexName; headLine = headLine.trimmed(); bool isChineseExist = headLine.contains(QRegExp("[\\x4e00-\\x9fa5]+")); if (isChineseExist) { indexDevice = headLine.indexOf("设备") + 2; indexName = headLine.indexOf("名称") + 4; } else { indexDevice = headLine.indexOf("DEVICE"); indexName = headLine.indexOf("NAME"); } QString order = "a"; //为避免同名情况,这里给每一个有线网设定一个唯一标志 for(int i = 1, j = 0; i < slist.size(); i ++) { QString line = slist.at(i); QString ltype = line.mid(0, indexDevice).trimmed(); QString nname = line.mid(indexName).trimmed(); if (ltype != "802-11-wireless" && ltype != "wifi" && ltype != "" && ltype != "--") { lanNameList.append(nname); // 当前连接的lan if (nname == actLanName) { objKyDBus->getConnectNetIp(); actLanName = "--"; if (mwBandWidth == "Unknown!") { getLanBandWidth(); } connect(ccf, SIGNAL(selectedOneLanForm(QString, QString)), this, SLOT(oneTopLanFormSelected(QString, QString))); connect(ccf, SIGNAL(disconnActiveLan()), this, SLOT(activeLanDisconn())); ccf->setName(nname, nname + order); ccf->setIcon(true); ccf->setLanInfo(objKyDBus->dbusActiveLanIpv4, objKyDBus->dbusActiveLanIpv6, mwBandWidth, objKyDBus->dbusLanMac); ccf->setConnedString(1, tr("NetOn,"));//"已连接" ccf->isConnected = true; ifLanConnected = true; lbLoadDown->show(); lbLoadUp->show(); lbLoadDownImg->show(); lbLoadUpImg->show(); ccf->setTopItem(false); currSelNetName = ""; objKyDBus->dbusActiveLanIpv4 = ""; objKyDBus->dbusActiveLanIpv6 = ""; syslog(LOG_DEBUG, "already insert an active lannet in the top of lan list"); } else { objKyDBus->getLanIp(nname); OneLancForm *ocf = new OneLancForm(lanListWidget, this, confForm, ksnm); // connect(ocf, SIGNAL(selectedOneLanForm(QString, QString)), this, SLOT(oneLanFormSelected(QString, QString))); ocf->setName(nname, nname + order); ocf->setIcon(false); //YYF ocf->setLine(true); ocf->setLanInfo(objKyDBus->dbusLanIpv4, objKyDBus->dbusLanIpv6, tr("Disconnected"), objKyDBus->dbusLanMac); ocf->setConnedString(0, tr("Disconnected"));//"未连接" ocf->move(L_VERTICAL_LINE_TO_ITEM, j * H_NORMAL_ITEM); lanListWidget->resize(W_LIST_WIDGET+194*isTabletStyle, lanListWidget->height() + H_NORMAL_ITEM); ocf->setFixedWidth(W_LIST_WIDGET+194*isTabletStyle); //YYF ocf->setSelected(false, false); ocf->show(); j ++; } order += "a"; } } QList itemList = lanListWidget->findChildren(); int n = itemList.size(); if (n >= 1) { OneLancForm *lastItem = itemList.at(n-1); lastItem->setLine(false); lbNoItemTip->hide(); } else { if (!ifLanConnected) { lbNoItemTip->hide(); // lbTopLanList->hide(); // btnCreateNet->hide(); } else { lbNoItemTip->show(); lbNoItemTip->setText(tr("No Other Wired Network Scheme")); } } this->lanListWidget->show(); this->topLanListWidget->show(); this->wifiListWidget->hide(); this->topWifiListWidget->hide(); this->stopLoading(); oldLanSlist = slist; is_stop_check_net_state = 0; } // 获取wifi列表回调 void KylinNM::getWifiListDone(QStringList slist) { qDebug()<<"debug: oldWifiSlist.size()="< 1) { actWifiuuid = currConnWifiBSsidUuid.at(0); for (int i=1; isetName(tr("Not connected"));//"当前未连接任何 Wifi" ccf->setSignal("0", "--"); activeWifiSignalLv = 0; ccf->setConnedString(1, tr("Disconnected"), "");//"未连接" ccf->isConnected = false; ifWLanConnected = false; lbLoadDown->hide(); lbLoadUp->hide(); lbLoadDownImg->hide(); lbLoadUpImg->hide(); ccf->setTopItem(false); } ccf->setAct(true); ccf->move(L_VERTICAL_LINE_TO_ITEM, 0); ccf->show(); // 填充可用网络列表 QString headLine = slist.at(0); int indexSignal,indexSecu, indexFreq, indexBSsid, indexName, indexPath; headLine = headLine.trimmed(); bool isChineseExist = headLine.contains(QRegExp("[\\x4e00-\\x9fa5]+")); if (isChineseExist) { indexSignal = headLine.indexOf("SIGNAL"); indexSecu = headLine.indexOf("安全性"); indexFreq = headLine.indexOf("频率") + 4; indexBSsid = headLine.indexOf("BSSID") + 6; indexName = indexBSsid + 19; indexPath = headLine.indexOf("DBUS-PATH"); } else { indexSignal = headLine.indexOf("SIGNAL"); indexSecu = headLine.indexOf("SECURITY"); indexFreq = headLine.indexOf("FREQ"); indexBSsid = headLine.indexOf("BSSID"); indexName = indexBSsid + 19; indexPath = headLine.indexOf("DBUS-PATH"); } QStringList wnames; int count = 0; QString actWifiBssid = " "; for (int i = 1; i < slist.size(); i ++) { QString line = slist.at(i); QString wbssid = line.mid(indexBSsid, 17).trimmed(); QString wname = line.mid(indexName, indexPath - indexName).trimmed(); if (actWifiBssidList.contains(wbssid)) { actWifiName = wname; } if ("*" == line.mid(0,indexSignal).trimmed()){ actWifiBssid = wbssid; } } if (actWifiBssidList.size()==1 && actWifiBssidList.at(0)=="--") { actWifiId = actWifiName; actWifiName = "--"; } for (int i = 1, j = 0; i < slist.size(); i ++) { QString line = slist.at(i); //QString wsignal = line.mid(0, indexRate).trimmed(); //QString wrate = line.mid(indexRate, indexSecu - indexRate).trimmed(); QString wsignal = line.mid(indexSignal, 3).trimmed(); QString wsecu = line.mid(indexSecu, indexFreq - indexSecu).trimmed(); QString wbssid = line.mid(indexBSsid, 17).trimmed(); QString wname = line.mid(indexName, indexPath - indexName).trimmed(); bool isContinue = false; foreach (QString addName, wnames) { // 重复的网络名称,跳过不处理 if(addName == wname){ isContinue = true; } } if(isContinue){ continue; } if (actWifiName != "--" && actWifiName == wname) { if (!actWifiBssidList.contains(wbssid)) { continue; //若当前热点ssid名称和已经连接的wifi的ssid名称相同,但bssid不同,则跳过 } } if (wname != "" && wname != "--") { // 当前连接的wifi if (wname == actWifiName) { connect(ccf, SIGNAL(selectedOneWifiForm(QString,int)), this, SLOT(oneTopWifiFormSelected(QString,int))); connect(ccf, SIGNAL(disconnActiveWifi()), this, SLOT(activeWifiDisconn())); QString path = line.mid(indexPath).trimmed(); QString m_name = this->objKyDBus->getWifiSsid(QString("/org/freedesktop/NetworkManager/AccessPoint/%1").arg(path.mid(path.lastIndexOf("/") + 1))); // ccf->setName(m_name); if (m_name.isEmpty() || m_name == "") { ccf->setName(wname); } else { ccf->setName(m_name); } //ccf->setRate(wrate); int signal = wsignal.toInt() + 11; ccf->setSignal(QString::number(signal), wsecu); activeWifiSignalLv = wsignal.toInt(); objKyDBus->getWifiMac(wname); ccf->setWifiInfo(wsecu, wsignal, objKyDBus->dbusWifiMac); ccf->setConnedString(1, tr("NetOn,"), wsecu);//"已连接" ccf->isConnected = true; ifWLanConnected = true; lbLoadDown->show(); lbLoadUp->show(); lbLoadDownImg->show(); lbLoadUpImg->show(); ccf->setTopItem(false); currSelNetName = ""; syslog(LOG_DEBUG, "already insert an active wifi in the top of wifi list"); } else { wifiListWidget->resize(W_LIST_WIDGET+173*isTabletStyle, wifiListWidget->height() + H_NORMAL_ITEM); OneConnForm *ocf = new OneConnForm(wifiListWidget, this, confForm, ksnm); connect(ocf, SIGNAL(selectedOneWifiForm(QString,int)), this, SLOT(oneWifiFormSelected(QString,int))); connect(ocf,&OneConnForm::onLineEditClicked, this, &KylinNM::onLineEditClicked); QString path = line.mid(indexPath).trimmed(); QString m_name = this->objKyDBus->getWifiSsid(QString("/org/freedesktop/NetworkManager/AccessPoint/%1").arg(path.mid(path.lastIndexOf("/") + 1))); // ocf->setName(m_name); if (m_name.isEmpty() || m_name == "") { ocf->setName(wname); } else { ocf->setName(m_name); } //ocf->setRate(wrate); ocf->setLine(true); ocf->setSignal(wsignal, wsecu); objKyDBus->getWifiMac(wname); ocf->setWifiInfo(wsecu, wsignal, objKyDBus->dbusWifiMac); ocf->setConnedString(0, tr("Disconnected"), wsecu); ocf->move(L_VERTICAL_LINE_TO_ITEM, j * H_NORMAL_ITEM); ocf->setSelected(false, false); ocf->show(); j ++; count ++; } wnames.append(wname); } } QList itemList = wifiListWidget->findChildren(); int n = itemList.size(); if (n >= 1) { OneConnForm *lastItem = itemList.at(n-1); lastItem->setLine(false); lbNoItemTip->hide(); } else { if (ifWLanConnected) { lbNoItemTip->show(); lbNoItemTip->setText(tr("No Other Wireless Network Scheme")); } else { lbNoItemTip->hide(); lbTopWifiList->hide(); // btnAddNet->hide(); } } this->lanListWidget->hide(); this->topLanListWidget->hide(); this->wifiListWidget->show(); this->topWifiListWidget->show(); this->stopLoading(); is_stop_check_net_state = 0; actWifiBssidList.clear(); wnames.clear(); } // 更新wifi列表 void KylinNM::updateWifiListDone(QStringList slist) { if (this->ksnm->isExecutingGetLanList){ return;} //获取表头信息 QString lastHeadLine = oldWifiSlist.at(0); //int lastIndexName = lastHeadLine.indexOf("SSID"); int lastIndexName, lastIndexPath; lastHeadLine = lastHeadLine.trimmed(); bool isChineseInIt = lastHeadLine.contains(QRegExp("[\\x4e00-\\x9fa5]+")); if (isChineseInIt) { lastIndexName = lastHeadLine.indexOf("BSSID") + 6 + 19; } else { lastIndexName = lastHeadLine.indexOf("BSSID") + 19; } lastIndexPath = lastHeadLine.indexOf("DBUS-PATH"); QString headLine = slist.at(0); int indexSecu, indexFreq, indexBSsid, indexName, indexPath; headLine = headLine.trimmed(); bool isChineseExist = headLine.contains(QRegExp("[\\x4e00-\\x9fa5]+")); if (isChineseExist) { indexSecu = headLine.indexOf("安全性"); indexFreq = headLine.indexOf("频率") + 4; indexBSsid = headLine.indexOf("BSSID") + 6; //indexName = headLine.indexOf("SSID") + 6; indexName = indexBSsid + 19; indexPath = headLine.indexOf("DBUS-PATH"); } else { indexSecu = headLine.indexOf("SECURITY"); indexFreq = headLine.indexOf("FREQ"); indexBSsid = headLine.indexOf("BSSID"); indexName = indexBSsid + 19; indexPath = headLine.indexOf("DBUS-PATH"); } //列表中去除已经减少的wifi for (int i=1; i wifiList = wifiListWidget->findChildren(); for (int pos = 0; pos < wifiList.size(); pos ++) { OneConnForm *ocf = wifiList.at(pos); if (ocf->getName() == lastWname) { if (ocf->isActive == true){break; } else { delete ocf; //删除元素下面的的所有元素上移 for (int after_pos = pos+1; after_pos < wifiList.size(); after_pos ++) { OneConnForm *after_ocf = wifiList.at(after_pos); if (lastWname == currSelNetName) {after_ocf->move(L_VERTICAL_LINE_TO_ITEM, after_ocf->y() - H_NORMAL_ITEM - H_WIFI_ITEM_BIG_EXTEND);} else {after_ocf->move(L_VERTICAL_LINE_TO_ITEM, after_ocf->y() - H_NORMAL_ITEM);} } wifiListWidget->resize(W_LIST_WIDGET+173*isTabletStyle, wifiListWidget->height() - H_NORMAL_ITEM); break; } } } } //end if (j == slist.size()-1) } //end (int j=1; j wifiList = wifiListWidget->findChildren(); int n = wifiList.size(); int posY = 0; if (n >= 1) { OneConnForm *lastOcf = wifiList.at(n-1); lastOcf->setLine(true); if (lastOcf->wifiName == currSelNetName) { posY = lastOcf->y()+H_NORMAL_ITEM + H_WIFI_ITEM_BIG_EXTEND; } else { posY = lastOcf->y()+H_NORMAL_ITEM; } } wifiListWidget->resize(W_LIST_WIDGET+173*isTabletStyle, wifiListWidget->height() + H_NORMAL_ITEM); OneConnForm *addItem = new OneConnForm(wifiListWidget, this, confForm, ksnm); connect(addItem, SIGNAL(selectedOneWifiForm(QString,int)), this, SLOT(oneWifiFormSelected(QString,int))); connect(addItem,&OneConnForm::onLineEditClicked, this, &KylinNM::onLineEditClicked); QString path = slist.at(i).mid(indexPath).trimmed(); QString m_name = this->objKyDBus->getWifiSsid(QString("/org/freedesktop/NetworkManager/AccessPoint/%1").arg(path.mid(path.lastIndexOf("/") + 1))); if (m_name.isEmpty() || m_name == "") { addItem->setName(wname); } else { addItem->setName(m_name); } addItem->setLine(false); addItem->setSignal(wsignal, wsecu); objKyDBus->getWifiMac(wname); addItem->setWifiInfo(wsecu, wsignal, objKyDBus->dbusWifiMac); addItem->setConnedString(0, tr("Disconnected"), wsecu);//"未连接" addItem->move(L_VERTICAL_LINE_TO_ITEM, posY); addItem->setSelected(false, false); addItem->show(); count += 1; } } } this->lanListWidget->hide(); this->topLanListWidget->hide(); this->wifiListWidget->show(); this->topWifiListWidget->show(); this->stopLoading(); } /////////////////////////////////////////////////////////////////////////////// //主窗口其他按钮点击响应 void KylinNM::on_btnAdvConf_clicked() { QProcess *qprocess = new QProcess(this); qprocess->start("nm-connection-editor &"); // int status = system("nm-connection-editor &"); // if (status != 0){ syslog(LOG_ERR, "execute 'nm-connection-editor &' in function 'on_btnAdvConf_clicked' failed");} } void KylinNM::on_btnAdvConf_pressed() { //ui->lbBtnConfBG->setStyleSheet(btnOnQss); } void KylinNM::on_btnAdvConf_released() { //ui->lbBtnConfBG->setStyleSheet(btnOffQss); } void KylinNM::on_btnFlyMode_clicked() { if (is_fly_mode_on == 0) { ui->lbFlyImg->setStyleSheet("QLabel{background-image:url(:/res/x/fly-mode-on.svg);}"); ui->lbFlyBG->setStyleSheet(btnOnQss); is_fly_mode_on = 1; onBtnWifiClicked(0); on_btnWifiList_clicked(); } else { ui->lbFlyImg->setStyleSheet("QLabel{background-image:url(:/res/x/fly-mode-off.svg);}"); ui->lbFlyBG->setStyleSheet(btnOffQss); is_fly_mode_on = 0; } } void KylinNM::on_btnHotspot_clicked() { if (is_wireless_adapter_ready == 1) { if (is_hot_sopt_on == 0) { ui->lbHotImg->setStyleSheet("QLabel{background-image:url(:/res/x/hot-spot-on.svg);}"); ui->lbHotBG->setStyleSheet(btnOnQss); is_hot_sopt_on = 1; QApplication::setQuitOnLastWindowClosed(false); DlgHotspotCreate *hotCreate = new DlgHotspotCreate(objKyDBus->dbusWiFiCardName); connect(hotCreate,SIGNAL(updateHotspotList()),this,SLOT(on_btnWifiList_clicked() )); connect(hotCreate,SIGNAL(btnHotspotState()),this,SLOT(on_btnHotspotState() )); hotCreate->show(); } else { on_btnHotspotState(); BackThread objBT; objBT.disConnLanOrWifi("wifi"); sleep(2); on_btnWifiList_clicked(); } } } void KylinNM::onBtnAddNetClicked() { // QApplication::setQuitOnLastWindowClosed(false); DlgConnHidWifi *connHidWifi = new DlgConnHidWifi(0, this, this->parentWidget()); connect(connHidWifi, SIGNAL(reSetWifiList() ), this, SLOT(on_btnWifiList_clicked()) ); connHidWifi->show(); } void KylinNM::onBtnCreateNetClicked() { QPoint pos = QCursor::pos(); QRect primaryGeometry; for (QScreen *screen : qApp->screens()) { if (screen->geometry().contains(pos)) { primaryGeometry = screen->geometry(); } } if (primaryGeometry.isEmpty()) { primaryGeometry = qApp->primaryScreen()->geometry(); } ConfForm *m_cf = new ConfForm(this->parentWidget()); m_cf->setMainWindow(this); m_cf->cbTypeChanged(3); m_cf->move(primaryGeometry.width() / 2 - m_cf->width() / 2, primaryGeometry.height() / 2 - m_cf->height() / 2); m_cf->show(); } /////////////////////////////////////////////////////////////////////////////// //处理窗口变化、网络状态变化 //列表中item的扩展与收缩 void KylinNM::oneLanFormSelected(QString lanName, QString uniqueName) { QList topLanList = topLanListWidget->findChildren(); QList lanList = lanListWidget->findChildren(); //**********************先处理下方列表********************// // 下方所有元素回到原位 for (int i = 0, j = 0;i < lanList.size(); i ++) { OneLancForm *ocf = lanList.at(i); if (ocf->isActive == true) { ocf->move(L_VERTICAL_LINE_TO_ITEM, 0); } if (ocf->isActive == false) { ocf->move(L_VERTICAL_LINE_TO_ITEM, j * H_NORMAL_ITEM); j ++; } } //是否与上一次选中同一个网络框 if (currSelNetName == uniqueName) { // 缩小所有选项卡 for (int i = 0;i < lanList.size(); i ++) { OneLancForm *ocf = lanList.at(i); if (ocf->uniqueName == uniqueName) { ocf->setSelected(false, true); } else { ocf->setSelected(false, false); } } currSelNetName = ""; } else { int selectY = 0; for (int i = 0;i < lanList.size(); i ++) { OneLancForm *ocf = lanList.at(i); if (ocf->uniqueName == uniqueName) { selectY = ocf->y(); //获取选中item的y坐标 break; } } // 选中元素下面的所有元素下移 H_LAN_ITEM_EXTEND for (int i = 0;i < lanList.size(); i ++) { OneLancForm *ocf = lanList.at(i); if (ocf->y() > selectY) { ocf->move(L_VERTICAL_LINE_TO_ITEM, ocf->y() + H_LAN_ITEM_EXTEND); } } for (int i = 0;i < lanList.size(); i ++) { OneLancForm *ocf = lanList.at(i); if (ocf->uniqueName == uniqueName) { ocf->setSelected(true, false); selectY = ocf->y(); } else { ocf->setSelected(false, false); } } currSelNetName = uniqueName; } QList itemList = lanListWidget->findChildren(); int n = itemList.size(); if (n >= 1) { OneLancForm *lastItem = itemList.at(n-1); lastItem->setLine(false); } //**********************处理上方列表-界面所有控件回原位********************// topLanListWidget->resize(W_TOP_LIST_WIDGET, H_NORMAL_ITEM + H_GAP_UP + X_ITEM); // 顶部的item缩小 lbTopLanList->move(X_MIDDLE_WORD, H_NORMAL_ITEM + H_GAP_UP); // btnCreateNet->move(X_BTN_FUN, Y_BTN_FUN); scrollAreal->move(W_LEFT_AREA, Y_SCROLL_AREA); lbNoItemTip->move(this->width()/2 - W_NO_ITEM_TIP/2 + W_LEFT_AREA/2, this->height()/2); OneLancForm *ocf = topLanList.at(0); ocf->setTopItem(false); } void KylinNM::oneTopLanFormSelected(QString lanName, QString uniqueName) { currSelNetName = uniqueName; } void KylinNM::oneWifiFormSelected(QString wifiName, int extendLength) { QListtopWifiList = topWifiListWidget->findChildren(); QList wifiList = wifiListWidget->findChildren(); //******************先处理下方列表****************// // 下方所有元素回到原位 for (int i = 0, j = 0;i < wifiList.size(); i ++) { OneConnForm *ocf = wifiList.at(i); if (ocf->isActive == true) { ocf->move(L_VERTICAL_LINE_TO_ITEM, 0); } if (ocf->isActive == false) { ocf->move(L_VERTICAL_LINE_TO_ITEM, j * H_NORMAL_ITEM); j ++; } } //是否与上一次选中同一个网络框 if (currSelNetName == wifiName) { // 缩小所有选项卡 for (int i = 0;i < wifiList.size(); i ++) { OneConnForm *ocf = wifiList.at(i); if (ocf->wifiName == wifiName) { if (ocf->wifiName == hideWiFiConn) { ocf->setHideItem(true, true); } else { ocf->setSelected(false, true); } } else { if (ocf->wifiName == hideWiFiConn) { ocf->setHideItem(true, true); } else { ocf->setSelected(false, false); } } } currSelNetName = ""; } else { int selectY = 0; for (int i = 0;i < wifiList.size(); i ++) { OneConnForm *ocf = wifiList.at(i); if (ocf->wifiName == wifiName) { selectY = ocf->y(); //获取选中item的y坐标 this->scrollAreaw->verticalScrollBar()->setValue(selectY); break; } } // 选中元素下面的所有元素下移 H_WIFI_ITEM_BIG_EXTEND for (int i = 0;i < wifiList.size(); i ++) { OneConnForm *ocf = wifiList.at(i); if (ocf->y() > selectY) { ocf->move(L_VERTICAL_LINE_TO_ITEM, ocf->y() + extendLength); } } for (int i = 0;i < wifiList.size(); i ++) { OneConnForm *ocf = wifiList.at(i); if (ocf->wifiName == wifiName) { if (ocf->wifiName == hideWiFiConn) { ocf->setHideItem(true, true); } else { ocf->setSelected(true, false); } } else { if (ocf->wifiName == hideWiFiConn) { ocf->setHideItem(true, true); } else { ocf->setSelected(false, false); } } } currSelNetName = wifiName; } //最后一个item没有下划线 QList itemList = wifiListWidget->findChildren(); int n = itemList.size(); if (n >= 1) { OneConnForm *lastItem = itemList.at(n-1); lastItem->setLine(false); } //********************处理上方列表-界面所有控件回原位******************// // 顶部的item缩小 topWifiListWidget->resize(W_TOP_LIST_WIDGET+194*isTabletStyle, H_NORMAL_ITEM + H_GAP_UP + X_ITEM); lbTopWifiList->move(X_MIDDLE_WORD, H_NORMAL_ITEM + H_GAP_UP); // btnAddNet->move(X_BTN_FUN, Y_BTN_FUN); scrollAreaw->move(W_LEFT_AREA, Y_SCROLL_AREA); lbNoItemTip->move(this->width()/2 - W_NO_ITEM_TIP/2 + W_LEFT_AREA/2, this->height()/2); OneConnForm *ocf = topWifiList.at(0); ocf->setTopItem(false); } void KylinNM::oneTopWifiFormSelected(QString wifiName, int extendLength) { QListtopWifiList = topWifiListWidget->findChildren(); QList wifiList = wifiListWidget->findChildren(); if (currSelNetName == wifiName) { // 与上一次选中同一个网络框,缩小当前选项卡 topWifiListWidget->resize(W_TOP_LIST_WIDGET+194*isTabletStyle, H_NORMAL_ITEM + H_GAP_UP + X_ITEM); lbTopWifiList->move(X_MIDDLE_WORD, H_NORMAL_ITEM + H_GAP_UP); // btnAddNet->move(X_BTN_FUN, Y_BTN_FUN); scrollAreaw->move(W_LEFT_AREA, Y_SCROLL_AREA); lbNoItemTip->move(this->width()/2 - W_NO_ITEM_TIP/2 + W_LEFT_AREA/2, this->height()/2); OneConnForm *ocf = topWifiList.at(0); ocf->setTopItem(false); currSelNetName = ""; } else { // 没有与上一次选中同一个网络框,放大当前选项卡 for(int i = 0;i < wifiList.size(); i ++) { // 所有元素回到原位 OneConnForm *ocf = wifiList.at(i); ocf->setSelected(false, false); ocf->move(L_VERTICAL_LINE_TO_ITEM, i * H_NORMAL_ITEM); } topWifiListWidget->resize(W_TOP_LIST_WIDGET+194*isTabletStyle, H_NORMAL_ITEM + H_WIFI_ITEM_BIG_EXTEND + H_GAP_UP + X_ITEM); lbTopWifiList->move(X_MIDDLE_WORD, H_NORMAL_ITEM + H_WIFI_ITEM_BIG_EXTEND + H_GAP_UP); // btnAddNet->move(X_BTN_FUN, Y_BTN_FUN + H_WIFI_ITEM_BIG_EXTEND); scrollAreaw->move(W_LEFT_AREA, Y_SCROLL_AREA + H_WIFI_ITEM_BIG_EXTEND); lbNoItemTip->move(this->width()/2 - W_NO_ITEM_TIP/2 + W_LEFT_AREA/2, this->height()/2 + 65); OneConnForm *ocf = topWifiList.at(0); ocf->setTopItem(true); currSelNetName = wifiName; } } //断开网络处理 void KylinNM::activeLanDisconn() { syslog(LOG_DEBUG, "Wired net is disconnected"); QString txt(tr("Wired net is disconnected")); objKyDBus->showDesktopNotify(txt); //QString cmd = "export LANG='en_US.UTF-8';export LANGUAGE='en_US';notify-send '" + txt + "...' -t 3800"; //int status1 = system(cmd.toUtf8().data()); //if (status1 != 0){ syslog(LOG_ERR, "execute 'notify-send' in function 'execConnWifiPWD' failed");} currSelNetName = ""; //this->startLoading(); emit this->waitLanStop(); this->ksnm->execGetLanList(); QTimer::singleShot(200, this, &KylinNM::onConnectChanged); } void KylinNM::activeWifiDisconn() { QThread *tt = new QThread(); BackThread *btt = new BackThread(); btt->moveToThread(tt); connect(tt, SIGNAL(finished()), tt, SLOT(deleteLater())); connect(this, SIGNAL(disConnSparedNet(QString)), btt, SLOT(disConnSparedNetSlot(QString)),Qt::DirectConnection); connect(btt, SIGNAL(disFinish()), this, SLOT(activeGetWifiList()), Qt::DirectConnection); connect(btt, SIGNAL(ttFinish()), tt, SLOT(quit()),Qt::DirectConnection); tt->start(); activeStartLoading(); QTimer::singleShot(200, this, &KylinNM::onConnectChanged); } void KylinNM::reflashWifiUi() { mutexIsReflashWifi.lock(); m_is_reflashWifiUi = true; mutexIsReflashWifi.unlock(); } void KylinNM::activeStartLoading() { syslog(LOG_DEBUG, "Wi-Fi is disconnected"); emit this->disConnSparedNet("wifi"); } void KylinNM::activeGetWifiList() { emit this->waitWifiStop(); this->ksnm->execGetWifiList(); } //网络开关处理,打开与关闭网络 void KylinNM::enNetDone() { BackThread *bt = new BackThread(); mwBandWidth = bt->execChkLanWidth(lname); ui->lbBtnNetBG->setStyleSheet(btnOnQss); // 打开网络开关时如果Wifi开关是打开的,设置其样式 if (checkWlOn()) { btnWireless->setSwitchStatus(true); //ui->lbBtnWifiBG->setStyleSheet(btnBgOnQss); //ui->lbBtnWifiBall->move(X_RIGHT_WIFI_BALL, Y_WIFI_BALL); } onBtnNetListClicked(1); is_stop_check_net_state = 0; qDebug()<<"debug: already turn on the switch of lan network"; syslog(LOG_DEBUG, "Already turn on the switch of lan network"); } void KylinNM::disNetDone() { this->is_btnNetList_clicked = 1; this->is_btnWifiList_clicked = 0; ui->lbNetListBG->setStyleSheet(btnOnQss); ui->lbWifiListBG->setStyleSheet(btnOffQss); ui->lbNetwork->setText("有线网络"); btnWireless->hide(); //ui->lbBtnWifiBG->hide(); //ui->lbBtnWifiBall->hide(); delete topLanListWidget; // 清空top列表 createTopLanUI(); //创建顶部有线网item // 清空lan列表 lanListWidget = new QWidget(scrollAreal); lanListWidget->resize(W_LIST_WIDGET, H_NORMAL_ITEM + H_LAN_ITEM_EXTEND); scrollAreal->setWidget(lanListWidget); scrollAreal->move(W_LEFT_AREA, Y_SCROLL_AREA); // 当前连接的lan OneLancForm *ccf = new OneLancForm(topLanListWidget, this, confForm, ksnm); ccf->setName(tr("Not connected"), "");//"当前未连接任何 以太网" ccf->setIcon(false); ccf->setConnedString(1, tr("Disconnected"));//"未连接" ccf->isConnected = false; ccf->setTopItem(false); ccf->setAct(true); ccf->move(L_VERTICAL_LINE_TO_ITEM, 0); ccf->show(); ui->lbBtnNetBG->setStyleSheet(btnOffQss); btnWireless->setSwitchStatus(false); this->lanListWidget->show(); this->wifiListWidget->hide(); this->scrollAreal->show(); this->topLanListWidget->show(); this->scrollAreaw->hide(); this->topWifiListWidget->hide(); on_btnNetList_pressed(); qDebug()<<"debug: already turn off the switch of lan network"; syslog(LOG_DEBUG, "Already turn off the switch of lan network"); this->stopLoading(); QTimer::singleShot(200, this, &KylinNM::onConnectChanged); } void KylinNM::launchLanDone() { ui->lbBtnNetBG->setStyleSheet(btnOnQss); } void KylinNM::enWifiDone() { //ui->lbBtnWifiBG->setStyleSheet(btnBgOnQss); //ui->lbBtnWifiBall->move(X_RIGHT_WIFI_BALL, Y_WIFI_BALL); is_update_wifi_list = 0; if (is_btnWifiList_clicked) { this->ksnm->execGetWifiList(); } else { on_btnWifiList_clicked(); } qDebug()<<"debug: already turn on the switch of wifi network"; syslog(LOG_DEBUG, "Already turn on the switch of wifi network"); } void KylinNM::disWifiDone() { disWifiDoneChangeUI(); on_btnWifiList_pressed(); qDebug()<<"debug: already turn off the switch of wifi network"; syslog(LOG_DEBUG, "Already turn off the switch of wifi network"); this->stopLoading(); is_stop_check_net_state = 0; QTimer::singleShot(200, this, &KylinNM::onConnectChanged); } void KylinNM::disWifiStateKeep() { if (this->is_btnNetList_clicked == 1) { btnWireless->setSwitchStatus(false); //ui->lbBtnWifiBG->setStyleSheet(btnBgOffQss); //ui->lbBtnWifiBall->move(X_LEFT_WIFI_BALL, Y_WIFI_BALL); } if (this->is_btnWifiList_clicked== 1) { disWifiDoneChangeUI(); // this->stopLoading(); getActiveInfo(); } } void KylinNM::disWifiDoneChangeUI() { wifiListWidget = new QWidget(scrollAreaw); wifiListWidget->resize(W_LIST_WIDGET+173*isTabletStyle, H_WIFI_ITEM_BIG_EXTEND); scrollAreaw->setWidget(wifiListWidget); scrollAreaw->move(W_LEFT_AREA, Y_SCROLL_AREA); lbTopWifiList->move(X_MIDDLE_WORD, H_NORMAL_ITEM + H_GAP_UP); // btnAddNet->move(X_BTN_FUN, Y_BTN_FUN); topWifiListWidget->resize(W_TOP_LIST_WIDGET+194*isTabletStyle, H_NORMAL_ITEM + H_GAP_UP + X_ITEM); QList wifiList = topWifiListWidget->findChildren(); for (int i = 0; i < wifiList.size(); i ++) { OneConnForm *ocf = wifiList.at(i); if (ocf->isActive == true) { ocf->setSelected(false, false); ocf->setName(tr("Not connected"));//"当前未连接任何 Wifi" ocf->setSignal("0", "--"); ocf->setConnedString(1, tr("Disconnected"), "");//"未连接" lbLoadDown->hide(); lbLoadUp->hide(); lbLoadDownImg->hide(); lbLoadUpImg->hide(); ocf->isConnected = false; ocf->setTopItem(false); disconnect(ocf, SIGNAL(selectedOneWifiForm(QString,int)), this, SLOT(oneTopWifiFormSelected(QString,int))); } else { ocf->deleteLater(); } } btnWireless->setSwitchStatus(false); //ui->lbBtnWifiBG->setStyleSheet(btnBgOffQss); //ui->lbBtnWifiBall->move(X_LEFT_WIFI_BALL, Y_WIFI_BALL); this->lanListWidget->hide(); this->topLanListWidget->hide(); this->wifiListWidget->show(); this->topWifiListWidget->show(); this->scrollAreal->hide(); this->scrollAreaw->show(); } void KylinNM::on_btnHotspotState() { ui->lbHotImg->setStyleSheet("QLabel{background-image:url(:/res/x/hot-spot-off.svg);}"); ui->lbHotBG->setStyleSheet(btnOffQss); is_hot_sopt_on = 0; } //处理外界对网络的连接与断开 void KylinNM::onExternalConnectionChange(QString type) { qDebug() <is_btnWifiList_clicked==1 && this->isVisible()) { BackThread *loop_bt = new BackThread(); IFace *loop_iface = loop_bt->execGetIface(); if (loop_iface->wstate != 2) { is_update_wifi_list = 1; this->ksnm->execGetWifiList(); //更新wifi列表 } delete loop_iface; loop_bt->deleteLater(); } } void KylinNM::on_setNetSpeed() { if (this->isVisible() && is_stop_check_net_state==0) { if (is_btnWifiList_clicked == 1) { if ( objNetSpeed->getCurrentDownloadRates(objKyDBus->dbusWiFiCardName.toUtf8().data(), &start_rcv_rates, &start_tx_rates) == -1) { start_rcv_rates = end_rcv_rates; } } else if(is_btnNetList_clicked == 1) { if ( objNetSpeed->getCurrentDownloadRates(objKyDBus->dbusLanCardName.toUtf8().data(), &start_rcv_rates, &start_tx_rates) == -1) { start_tx_rates = end_tx_rates; } } long int delta_rcv = (start_rcv_rates - end_rcv_rates)/800; long int delta_tx = (start_tx_rates - end_tx_rates)/8; if (delta_rcv>=10000 || delta_rcv<0){delta_rcv = 0;} if (delta_tx>=10000 || delta_tx<0){delta_tx = 0;} int rcv_num = delta_rcv/3; int tx_num = delta_tx/3; QString str_rcv; QString str_tx; if (rcv_num < 1000) { str_rcv = QString::number(rcv_num) + "KB/s."; } else { int remainder; if (rcv_num%1000 < 100) { remainder = 0; } else { remainder = (rcv_num%1000)/100; } str_rcv = QString::number(rcv_num/1000) + "." + QString::number(remainder) + "MB/s."; } if (tx_num < 1000) { str_tx = QString::number(tx_num) + "KB/s"; } else { int remainder; if (tx_num%1000 < 100) { remainder = 0; } else { remainder = (tx_num%1000)/100; } str_tx = QString::number(tx_num/1000) + "." + QString::number(remainder) + "MB/s"; } lbLoadDown->setText(str_rcv); lbLoadUp->setText(str_tx); switch (str_rcv.size()) { case 6: lbLoadUp->move(X_ITEM + 187, Y_TOP_ITEM + 32); lbLoadUpImg->move(X_ITEM + 170, Y_TOP_ITEM + 35); break; case 7: lbLoadUp->move(X_ITEM + 194, Y_TOP_ITEM + 32); lbLoadUpImg->move(X_ITEM + 176, Y_TOP_ITEM + 35); break; case 8: lbLoadUp->move(X_ITEM + 199, Y_TOP_ITEM + 32); lbLoadUpImg->move(X_ITEM + 186, Y_TOP_ITEM + 35); break; default: break; } end_rcv_rates = start_rcv_rates; end_tx_rates = start_tx_rates; } } void KylinNM::connLanDone(int connFlag) { emit this->waitLanStop(); //停止加载动画 // Lan连接结果,0点击连接成功 1失败 3开机启动网络工具时已经连接 if (connFlag == 0) { syslog(LOG_DEBUG, "Wired net already connected by clicking button"); this->is_wired_line_ready = 1; this->is_by_click_connect = 1; this->ksnm->execGetLanList(); QString txt(tr("Conn Ethernet Success")); objKyDBus->showDesktopNotify(txt); //QString cmd = "export LANG='en_US.UTF-8';export LANGUAGE='en_US';notify-send '" + txt + "' -t 3800"; //int status = system(cmd.toUtf8().data()); //if (status != 0){ syslog(LOG_ERR, "execute 'notify-send' in function 'connLanDone' failed");} } if (connFlag == 1) { qDebug()<<"without net line connect to computer"; this->is_wired_line_ready = 0; //without net line connect to computer is_stop_check_net_state = 0; QString txt(tr("Conn Ethernet Fail")); objKyDBus->showDesktopNotify(txt); //QString cmd = "export LANG='en_US.UTF-8';export LANGUAGE='en_US';notify-send '" + txt + "' -t 3800"; //int status = system(cmd.toUtf8().data()); //if (status != 0){ syslog(LOG_ERR, "execute 'notify-send' in function 'connLanDone' failed");} } if (connFlag == 3) { syslog(LOG_DEBUG, "Launch kylin-nm, Lan already connected"); this->is_wired_line_ready = 1; } this->stopLoading(); QTimer::singleShot(200, this, &KylinNM::onConnectChanged); } void KylinNM::connWifiDone(int connFlag) { emit this->waitWifiStop(); //停止加载动画 // Wifi连接结果,0点击连接成功 1失败 2没有配置文件 3开机启动网络工具时已经连接 if (connFlag == 0) { syslog(LOG_DEBUG, "Wi-Fi already connected by clicking button"); this->is_by_click_connect = 1; this->ksnm->execGetWifiList(); QString txt(tr("Conn Wifi Success")); objKyDBus->showDesktopNotify(txt); //QString cmd = "export LANG='en_US.UTF-8';export LANGUAGE='en_US';notify-send '" + txt + "' -t 3800"; //int status = system(cmd.toUtf8().data()); //if (status != 0){ syslog(LOG_ERR, "execute 'notify-send' in function 'connWifiDone' failed");} } else if (connFlag == 1) { is_stop_check_net_state = 0; is_connect_wifi_failed = 1; QString txt(tr("Confirm your Wi-Fi password or usable of wireless card")); objKyDBus->showDesktopNotify(txt); //QString cmd = "export LANG='en_US.UTF-8';export LANGUAGE='en_US';notify-send '" + txt + "...' -t 3800"; //int status1 = system(cmd.toUtf8().data()); //if (status1 != 0){ syslog(LOG_ERR, "execute 'notify-send' in function 'execConnWifiPWD' failed");} } else if (connFlag == 3) { syslog(LOG_DEBUG, "Launch kylin-nm, Wi-Fi already connected"); } QTimer::singleShot(200, this, &KylinNM::onConnectChanged); } int KylinNM::getConnectStatus() { int ret = -1; QString actLanName = "--"; QString actWifiName = "--"; activecon *act = kylin_network_get_activecon_info(); int index = 0; while (act[index].con_name != NULL) { if (QString(act[index].type) == "ethernet" || QString(act[index].type) == "802-3-ethernet") { actLanName = QString(act[index].con_name); } if (QString(act[index].type) == "wifi" || QString(act[index].type) == "802-11-wireless") { actWifiName = QString(act[index].con_name); } index ++; } //ukui3.0中获取currentActWifiSignalLv的值 if (activeWifiSignalLv > 75) { currentActWifiSignalLv = 1; } else if(activeWifiSignalLv > 55 && activeWifiSignalLv <= 75) { currentActWifiSignalLv = 2; } else if(activeWifiSignalLv > 35 && activeWifiSignalLv <= 55) { currentActWifiSignalLv = 3; } else if( activeWifiSignalLv <= 35) { currentActWifiSignalLv = 4; } // 设置图标 if (actLanName != "--") { ret = 0; } else if (actWifiName != "--") { ret = 1; } else { ret = -1; } return ret; } ukui-screensaver/KylinNM/src/loadingdiv.h0000644000175000017500000000235314205074704017400 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include class LoadingDiv : public QWidget { Q_OBJECT public: explicit LoadingDiv(QWidget *parent = nullptr); signals: void toStopLoading(); public slots: void switchAnimStep(); void startLoading(); void stopLoading(); private: QLabel *loadingGif = nullptr; QTimer *switchTimer = nullptr; int currentPage; int countCurrentTime; }; #endif // LOADINGDIV_H ukui-screensaver/KylinNM/src/onelancform.ui0000644000175000017500000001202614205074704017747 0ustar fengfeng OneLancForm 0 0 424 250 Form 63 8 190 20 316 14 100 34 316 14 100 34 316 18 80 40 63 31 52 20 0 0 424 162 63 64 238 85 63 62 238 20 63 86 250 20 63 110 238 20 63 134 238 20 leInfo_1 leInfo_2 leInfo_3 leInfo_4 btnInfo 14 14 24 24 2 59 421 2 background-color: rgba(255, 255, 255,0.05); Qt::Horizontal 0 0 340 56 316 14 100 34 356 20 20 20 364 18 16 16 lbName lbConned lbIcon line wbg wbg_2 btnConnSub btnDisConn btnConn lbWaiting lbWaitingIcon btnConnCfg ukui-screensaver/KylinNM/src/confform.h0000644000175000017500000000523014205074704017066 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include namespace Ui { class ConfForm; } class KylinNM; class ConfForm : public QWidget { Q_OBJECT public: explicit ConfForm(QWidget *parent = 0); ~ConfForm(); void setProp(QString connName, QString v4method, QString addr, QString mask, QString gateway, QString dns, bool isActConf ); void setMainWindow(KylinNM *mainwindow); public slots: void tabletStyle(bool isTablet);//YYF 平板桌面模式特有设置 void cbTypeChanged(int index); protected: void paintEvent(QPaintEvent *event); bool eventFilter(QObject *obj, QEvent *ev) override; private slots: void on_btnOk_clicked(); void on_btnCancel_clicked(); void on_btnCreate_clicked(); void on_leName_textEdited(const QString &arg1); void on_leAddr_textEdited(const QString &arg1); void on_leGateway_textEdited(const QString &arg1); void on_leDns_textEdited(const QString &arg1); void on_leDns2_textEdited(const QString &arg1); void setEnableOfBtn(); bool getTextEditState(QString text); void setBtnEnableFalse(); void on_isDHCP_clicked(); void on_notDHCP_clicked(); private: Ui::ConfForm *ui; void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); bool isPress; QPoint winPos; QPoint dragPos; bool isActConf; //是否对已经连接的网络进行的更改 bool isCreateNewNet = false; //是否是创建的新网络 bool isShowSaveBtn = true; //是否显示保存按钮,即是否是编辑网络界面 bool isTabletStyle=false;//YYF 平板桌面模式特有设置 QString labelQss, cbxQss, leQss, lineQss, btnOnQss, btnOffQss; KylinNM *mw = nullptr; signals: void requestRefreshLanList(int updateType); }; #endif // CONFFORM_H ukui-screensaver/KylinNM/src/utils.cpp0000644000175000017500000002201014205074704016743 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include /////////////////////////////////////////////////////////////////////////////// // The Utils class Utils::Utils(){} int Utils::m_system(char *cmd) { int status = 0; pid_t pid; if ((pid = vfork()) <0) { qDebug()<<"failed to create a subprocess by using vfork"; syslog(LOG_ERR, "failed to create a subprocess by using vfork"); status = -1; } else if (pid==0) { const char *new_argv[4]; struct sigaction sa_cld; sa_cld.sa_handler = SIG_DFL; sa_cld.sa_flags = 0; // 在子进程中放开SIGINT信号 sigemptyset(&sa_cld.sa_mask); sigaction (SIGINT, &sa_cld, NULL); sigaction (SIGQUIT, &sa_cld, NULL); new_argv[0] = "sh"; new_argv[1] = "-c"; new_argv[2] = cmd; new_argv[3] = NULL; // execl("/bin/sh","sh","-c" ,cmd,(char *)0); if (execve("/bin/sh",(char *const *) new_argv, NULL) <0) { qDebug()<<"failed to execve a shell command in function m_system"; syslog(LOG_ERR, "failed to execve %s! errno: %d\n",cmd, errno); exit(1); } else { exit(0); } } else { waitpid(pid,&status,0); } return status; } void Utils::onRequestSendDesktopNotify(QString message) { QDBusInterface iface("org.freedesktop.Notifications", "/org/freedesktop/Notifications", "org.freedesktop.Notifications", QDBusConnection::sessionBus()); QList args; args<<(QCoreApplication::applicationName()) <<((unsigned int) 0) <resize(480, 538); this->loadingGif = new QLabel(this); this->loadingGif->resize(96, 96); this->loadingGif->move(this->width()/2 - 96/2 + 41/2, this->height()/2 + 20); this->loadingGif->show(); this->switchTimer = new QTimer(this); //QTimer对象,控制等待动画播放 connect(switchTimer, SIGNAL(timeout()), this, SLOT(switchAnimStep())); this->raise(); this->hide(); } //加载动画控件'loadingGif' void LoadingDiv::switchAnimStep() { QString qpmQss = "QLabel{background-image:url(':/res/s/conning-b/"; qpmQss.append(QString::number(this->currentPage)); qpmQss.append(".png');}"); loadingGif->setStyleSheet(qpmQss); this->currentPage --; if (this->currentPage < 1) { this->currentPage = 12; //循环播放 } this->countCurrentTime += FRAMESPEED; if (this->countCurrentTime >= ALLTIME) { emit this->toStopLoading(); //发出信号停止主界面和托盘区的等待动画 } } //开始播放动画 void LoadingDiv::startLoading() { this->currentPage = 12; this->countCurrentTime = 0; this->switchTimer->start(FRAMESPEED); this->show(); } //结束播放动画 void LoadingDiv::stopLoading() { this->switchTimer->stop(); this->hide(); } ukui-screensaver/KylinNM/src/kylin-dbus-interface.cpp0000644000175000017500000013344114205074704021635 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include namespace { void quitThread(QThread *thread) { Q_ASSERT(thread); if (thread) { thread->quit(); if (!thread->wait(2000)) { thread->terminate(); thread->wait(); } } } } // namespace KylinDBus::KylinDBus(KylinNM *mainWindow, QObject *parent) :QObject(parent) { this->mw = mainWindow; getObjectPath(); //获取dbus中 lan 与 WiFi 的device路径 getPhysicalCarrierState(0); //初始化获取网线插入状态 getLanHwAddressState(); //获取有线网Mac地址 getWiredCardName(); //获取有线网卡名称 //initTaskbarGsetting(); //初始化taskbar的GSetting方法 getWifiSwitchState(); //初始化wifi开关GSetting通信方法 initTransparentState(); //初始化窗口透明度的GSetting方法 QDBusConnection::systemBus().connect(QString("org.freedesktop.NetworkManager"), QString("/org/freedesktop/NetworkManager"), QString("org.freedesktop.NetworkManager"), QString("PropertiesChanged"), this, SLOT(onPropertiesChanged(QVariantMap) ) ); QDBusConnection::systemBus().connect(QString("org.freedesktop.NetworkManager"), QString("/org/freedesktop/NetworkManager"), QString("org.freedesktop.NetworkManager"), QString("DeviceAdded"), mw, SLOT(onNetworkDeviceAdded(QDBusObjectPath) ) ); QDBusConnection::systemBus().connect(QString("org.freedesktop.NetworkManager"), QString("/org/freedesktop/NetworkManager"), QString("org.freedesktop.NetworkManager"), QString("DeviceRemoved"), mw, SLOT(onNetworkDeviceRemoved(QDBusObjectPath) ) ); QDBusConnection::systemBus().connect(QString("org.freedesktop.NetworkManager"), QString("/org/freedesktop/NetworkManager/Settings"), QString("org.freedesktop.NetworkManager.Settings"), QString("NewConnection"), this, SLOT(onNewConnection(QDBusObjectPath) ) ); QDBusConnection::systemBus().connect(QString("org.freedesktop.NetworkManager"), QString("/org/freedesktop/NetworkManager/Settings"), QString("org.freedesktop.NetworkManager.Settings"), QString("ConnectionRemoved"), this, SLOT(onConnectionRemoved(QDBusObjectPath) ) ); if (wiredPath.path() != "") { QDBusConnection::systemBus().connect(QString("org.freedesktop.NetworkManager"), QString(wiredPath.path()), QString("org.freedesktop.NetworkManager.Device.Wired"), QString("PropertiesChanged"), this, SLOT(onLanPropertyChanged(QVariantMap) ) ); } else { qDebug()<<"Can not find wired device object path when using dbus."; } if (wirelessPath.path() != "") { QDBusConnection::systemBus().connect(QString("org.freedesktop.NetworkManager"), QString(wirelessPath.path()), QString("org.freedesktop.NetworkManager.Device.Wireless"), QString("PropertiesChanged"), this, SLOT(onWifiPropertyChanged(QVariantMap) ) ); QDBusConnection::systemBus().connect(QString("org.freedesktop.NetworkManager"), QString(wirelessPath.path()), QString("org.freedesktop.NetworkManager.Device.Wireless"), QString("AccessPointAdded"), this, SLOT(onAccessPointAdded(QDBusObjectPath) ) ); getWirelessCardName();//获取无线网卡名称 } else { qDebug()<<"Can not find wireless device object path when using dbus."; } time = new QTimer(this); time->setTimerType(Qt::PreciseTimer); QObject::connect(time, SIGNAL(timeout()), this, SLOT(slot_timeout())); QObject::connect(this, SIGNAL(updateWiredList(int)), mw, SLOT(onBtnNetListClicked(int))); mUtils = new Utils(); mUtilsThread = new QThread(this); mUtils->moveToThread(mUtilsThread); connect(mUtilsThread, &QThread::finished, mUtils, &Utils::deleteLater); connect(this, SIGNAL(requestSendDesktopNotify(QString)), mUtils, SLOT(onRequestSendDesktopNotify(QString)), Qt::QueuedConnection); QTimer::singleShot(1, this, [=] { mUtilsThread->start(); }); } KylinDBus::~KylinDBus() { quitThread(mUtilsThread); } /////////////////////////////////////////////////////////////////////////////// //下方使用Dbus 进程通信方法 //获取dbus中 lan 与 WiFi 的device路径 void KylinDBus::getObjectPath() { foreach (QDBusObjectPath mPath, multiWiredPaths) { multiWiredPaths.removeOne(mPath); } QDBusInterface m_interface( "org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", "org.freedesktop.NetworkManager", QDBusConnection::systemBus() ); //先获取所有的网络设备的设备路径 QDBusReply> obj_reply = m_interface.call("GetAllDevices"); if (!obj_reply.isValid()) { qDebug()<<"execute dbus method 'GetAllDevices' is invalid in func getObjectPath()"; } QList obj_paths = obj_reply.value(); //再判断有无有线设备和无线设备的路径 foreach (QDBusObjectPath obj_path, obj_paths) { QDBusInterface interface( "org.freedesktop.NetworkManager", obj_path.path(), "org.freedesktop.DBus.Introspectable", QDBusConnection::systemBus() ); QDBusReply reply = interface.call("Introspect"); if (!reply.isValid()) { qDebug()<<"execute dbus method 'Introspect' is invalid in func getObjectPath()"; } if(reply.value().indexOf("org.freedesktop.NetworkManager.Device.Wired") != -1) { //表明有有线网设备 wiredPath = obj_path; multiWiredPaths.append(obj_path); } else if (reply.value().indexOf("org.freedesktop.NetworkManager.Device.Wireless") != -1) { //表明有wifi设备 wirelessPath = obj_path; isWirelessCardOn = true; } } } //获取是否连接有线网网线 void KylinDBus::getPhysicalCarrierState(int n) { multiWiredCableState.clear(); foreach (QDBusObjectPath localPath, multiWiredPaths) { QDBusInterface interface( "org.freedesktop.NetworkManager", localPath.path(), "org.freedesktop.DBus.Properties", QDBusConnection::systemBus() ); //Carrier值为true,插了网线;为false,未插网线 QDBusReply reply = interface.call("Get", "org.freedesktop.NetworkManager.Device.Wired", "Carrier"); try { if (reply.value().toString() == "true") { //isWiredCableOn = true; QDBusReply managed = interface.call("Get", "org.freedesktop.NetworkManager.Device", "Managed"); //针对intel特殊环境的二次判断,当设备未托管时,即时carrier为true,仍认为有线设备未连接 if (managed.value().toString() == "true") { //isWiredCableOn = true; multiWiredCableState.append("true"); } else { multiWiredCableState.append("false"); } } else if (reply.value().toString() == "false") { //isWiredCableOn = false; multiWiredCableState.append("false"); //if (n == 1){ this->mw->onPhysicalCarrierChanged(isWiredCableOn);} } else { throw -1; //出现异常 } } catch(...) { syslog(LOG_ERR, "Error occurred when get the property 'Carrier' of Wired"); qDebug()<<"Error occurred when get the property 'Carrier' of Wired"; } } isWiredCableOn = false; foreach (QString state, multiWiredCableState) { if (state == "true") { isWiredCableOn = true; } } if (n == 1) { this->mw->onPhysicalCarrierChanged(isWiredCableOn);} } //获取有线网Mac地址 void KylinDBus::getLanHwAddressState() { QDBusInterface lanInterface( "org.freedesktop.NetworkManager", wiredPath.path(), "org.freedesktop.DBus.Properties", QDBusConnection::systemBus() ); QDBusReply lanReply = lanInterface.call("Get", "org.freedesktop.NetworkManager.Device.Wired", "HwAddress"); if (!lanReply.isValid()) { qDebug()<<"can not get the attribute 'HwAddress' in func getLanHwAddressState()"; } else { dbusLanMac = lanReply.value().toString(); } } //获取有线网卡名称 void KylinDBus::getWiredCardName() { if (wiredPath.path() == "") { dbusLanCardName = ""; } else { QDBusInterface lanInterface( "org.freedesktop.NetworkManager", wiredPath.path(), "org.freedesktop.DBus.Properties", QDBusConnection::systemBus() ); QDBusReply lanReply = lanInterface.call("Get", "org.freedesktop.NetworkManager.Device", "Interface"); if (!lanReply.isValid()) { qDebug()<<"can not get the attribute 'Interface' in func getWiredCardName()"; dbusLanCardName = ""; } else { dbusLanCardName = lanReply.value().toString(); } } } //获取无线网卡名称 void KylinDBus::getWirelessCardName() { QDBusInterface lanInterface( "org.freedesktop.NetworkManager", wirelessPath.path(), "org.freedesktop.DBus.Properties", QDBusConnection::systemBus() ); QDBusReply lanReply = lanInterface.call("Get", "org.freedesktop.NetworkManager.Device", "Interface"); if (!lanReply.isValid()) { qDebug()<<"can not get the attribute 'Interface' in func getWirelessCardName()"; } else { dbusWiFiCardName = lanReply.value().toString(); } } //获取没有连接的有线网ip void KylinDBus::getLanIp(QString netName) { QDBusInterface m_interface("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager/Settings", "org.freedesktop.NetworkManager.Settings", QDBusConnection::systemBus() ); QDBusReply> m_reply = m_interface.call("ListConnections"); QList m_objNets = m_reply.value(); foreach (QDBusObjectPath objNet, m_objNets) { QDBusInterface m_interface("org.freedesktop.NetworkManager", objNet.path(), "org.freedesktop.NetworkManager.Settings.Connection", QDBusConnection::systemBus()); QDBusMessage result = m_interface.call("GetSettings"); //get information of this network const QDBusArgument &dbusArg1st = result.arguments().at( 0 ).value(); //DBus type : a{sa{sv}}, a map with a key of QString, which maps to another map of QString,QVariant QMap> map; dbusArg1st >> map; for (QString outside_key : map.keys() ) { QMap outsideMap = map.value(outside_key); if (outside_key == "connection") { for (QString search_key : outsideMap.keys()) { if (search_key == "id") { //const QDBusArgument &dbusArg2nd = innerMap.value(inner_key).value(); if (netName == outsideMap.value(search_key).toString()) { // qDebug()<<"aaaaaa"< innerMap = map.value(key); //qDebug() << "Key: " << key; if (key == "ipv4") { for (QString inner_key : innerMap.keys()) { if (inner_key == "address-data") { const QDBusArgument &dbusArg2nd = innerMap.value(inner_key).value(); QMap m_map; dbusArg2nd.beginArray(); while (!dbusArg2nd.atEnd()) { dbusArg2nd >> m_map;// append map to a vector here if you want to keep it } dbusArg2nd.endArray(); //qDebug()<<" " << m_map.value("address").toString(); dbusLanIpv4 = m_map.value("address").toString(); } } } if (key == "ipv6") { for (QString inner_key : innerMap.keys()) { if (inner_key == "address-data"){ const QDBusArgument &dbusArg2nd = innerMap.value(inner_key).value(); QMap m_map; dbusArg2nd.beginArray(); while (!dbusArg2nd.atEnd()) { dbusArg2nd >> m_map;// append map to a vector here if you want to keep it } dbusArg2nd.endArray(); //qDebug()<<" " << m_map.value("address").toString(); dbusLanIpv6 = m_map.value("address").toString(); } } } } //end for(QString key : map.keys() ) } } } //end for (QString search_key : outsideMap.keys()) } } // end for(QString outside_key : map.keys() ) } //end foreach (QDBusObjectPath objNet, m_objNets) } //获取已经连接的有线网ip void KylinDBus::getConnectNetIp() { QDBusInterface interface( "org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", "org.freedesktop.DBus.Properties", QDBusConnection::systemBus() ); //获取已经连接了那些网络,及这些网络对应的网络类型(ethernet or wifi) QDBusMessage result = interface.call("Get", "org.freedesktop.NetworkManager", "ActiveConnections"); QList outArgs = result.arguments(); QVariant first = outArgs.at(0); QDBusVariant dbvFirst = first.value(); QVariant vFirst = dbvFirst.variant(); QDBusArgument dbusArgs = vFirst.value(); QDBusObjectPath objPath; dbusArgs.beginArray(); while (!dbusArgs.atEnd()) { dbusArgs >> objPath; QDBusInterface interfacePro( "org.freedesktop.NetworkManager", objPath.path(), "org.freedesktop.DBus.Properties", QDBusConnection::systemBus() ); QDBusReply reply = interfacePro.call("Get", "org.freedesktop.NetworkManager.Connection.Active", "Type"); if (reply.value().toString() == "ethernet" || reply.value().toString() == "802-3-ethernet") { //ipv4的路径信息和ip信息 QDBusInterface interfaceIp4( "org.freedesktop.NetworkManager", objPath.path(), "org.freedesktop.DBus.Properties", QDBusConnection::systemBus() ); QDBusMessage replyIp4 = interfaceIp4.call("Get", "org.freedesktop.NetworkManager.Connection.Active", "Ip4Config"); QList outArgsIp4 = replyIp4.arguments(); QVariant firstIp4 = outArgsIp4.at(0); QDBusVariant dbvFirstIp4 = firstIp4.value(); QVariant vFirstIp4 = dbvFirstIp4.variant(); QDBusObjectPath dbusPathIp4 = vFirstIp4.value(); QDBusInterface interfaceIpv4( "org.freedesktop.NetworkManager", dbusPathIp4.path(), "org.freedesktop.DBus.Properties", QDBusConnection::systemBus() ); QDBusMessage replyIpv4 = interfaceIpv4.call("Get", "org.freedesktop.NetworkManager.IP4Config", "AddressData"); QList outArgsIpv4 = replyIpv4.arguments(); QVariant firstIpv4 = outArgsIpv4.at(0); QDBusVariant dbvFirstIpv4 = firstIpv4.value(); QVariant vFirstIpv4 = dbvFirstIpv4.variant(); const QDBusArgument &dbusArgIpv4 = vFirstIpv4.value(); QList mDatasIpv4; dbusArgIpv4 >> mDatasIpv4; foreach (QVariantMap mDataIpv4, mDatasIpv4) { dbusActiveLanIpv4 = mDataIpv4.value("address").toString(); } //ipv6的路径信息和ip信息 QDBusInterface interfaceIp6( "org.freedesktop.NetworkManager", objPath.path(), "org.freedesktop.DBus.Properties", QDBusConnection::systemBus() ); QDBusMessage replyIp6 = interfaceIp6.call("Get", "org.freedesktop.NetworkManager.Connection.Active", "Ip6Config"); QList outArgsIp6 = replyIp6.arguments(); QVariant firstIp6 = outArgsIp6.at(0); QDBusVariant dbvFirstIp6 = firstIp6.value(); QVariant vFirstIp6 = dbvFirstIp6.variant(); QDBusObjectPath dbusPathIp6 = vFirstIp6.value(); QDBusInterface interfaceIpv6( "org.freedesktop.NetworkManager", dbusPathIp6.path(), "org.freedesktop.DBus.Properties", QDBusConnection::systemBus() ); QDBusMessage replyIpv6 = interfaceIpv6.call("Get", "org.freedesktop.NetworkManager.IP6Config", "AddressData"); QList outArgsIpv6 = replyIpv6.arguments(); QVariant firstIpv6 = outArgsIpv6.at(0); QDBusVariant dbvFirstIpv6 = firstIpv6.value(); QVariant vFirstIpv6 = dbvFirstIpv6.variant(); const QDBusArgument &dbusArgIpv6 = vFirstIpv6.value(); QList mDatasIpv6; dbusArgIpv6 >> mDatasIpv6; foreach (QVariantMap mDataIpv6, mDatasIpv6) { dbusActiveLanIpv6 = mDataIpv6.value("address").toString(); } } } dbusArgs.endArray(); } //获取wifi的mac地址 void KylinDBus::getWifiMac(QString netName) { dbusWifiMac = ""; QDBusInterface interface( "org.freedesktop.NetworkManager", wirelessPath.path(), "org.freedesktop.NetworkManager.Device.Wireless", QDBusConnection::systemBus() ); QDBusReply> reply = interface.call("GetAllAccessPoints"); //get accesspoint for each wifi QList objPaths = reply.value(); foreach (QDBusObjectPath objPath, objPaths) { QDBusInterface ssid_interface( "org.freedesktop.NetworkManager", objPath.path(), "org.freedesktop.DBus.Properties", QDBusConnection::systemBus() ); QDBusReply ssid_replys = ssid_interface.call("Get", "org.freedesktop.NetworkManager.AccessPoint", "Ssid"); QString str_name = ssid_replys.value().toString(); if (str_name == netName) { //if the ssid of the accesspoint is just the netName, we can get this hardware address QDBusInterface path_interface( "org.freedesktop.NetworkManager", objPath.path(), "org.freedesktop.DBus.Properties", QDBusConnection::systemBus() ); QDBusReply path_reply = path_interface.call("Get", "org.freedesktop.NetworkManager.AccessPoint", "HwAddress"); dbusWifiMac = path_reply.value().toString(); } } } //获取当前能获取到的wifi的数量, 每个accesspoint 代表一个wifi int KylinDBus::getAccessPointsNumber() { QDBusInterface interface( "org.freedesktop.NetworkManager", wirelessPath.path(), "org.freedesktop.NetworkManager.Device.Wireless", QDBusConnection::systemBus() ); QDBusReply> reply = interface.call("GetAllAccessPoints"); QList objPaths = reply.value(); return objPaths.size(); } //新增了一个网络,伴随着多了一个网络配置文件 void KylinDBus::onNewConnection(QDBusObjectPath objPath) { QDBusInterface m_interface("org.freedesktop.NetworkManager", objPath.path(), "org.freedesktop.NetworkManager.Settings.Connection", QDBusConnection::systemBus()); QDBusMessage result = m_interface.call("GetSettings"); const QDBusArgument &dbusArg1st = result.arguments().at( 0 ).value(); QMap> map; dbusArg1st >> map; for(QString key : map.keys() ) { if (key == "802-3-ethernet") { emit this->updateWiredList(0); //send this signal to update wired network list syslog(LOG_DEBUG, "A new wired network was created."); qDebug()<<"A new wired network was created."; } } } //减少了一个网络,伴随着减少了一个网络配置文件 void KylinDBus::onConnectionRemoved(QDBusObjectPath objPath) { syslog(LOG_DEBUG, "An old network was removed from configure directory."); qDebug()<<"An old network was removed from configure directory."; if (mw->is_btnNetList_clicked == 1) { emit this->updateWiredList(0); //send this signal to update wired network list } } //应用启动时,获取已经连接的网络信息,包括该网络的路径和类型 void KylinDBus::initConnectionInfo() { QDBusInterface interface( "org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", "org.freedesktop.DBus.Properties", QDBusConnection::systemBus() ); //获取已经连接了那些网络,及这些网络对应的网络类型(ethernet or wifi) QDBusMessage result = interface.call("Get", "org.freedesktop.NetworkManager", "ActiveConnections"); QList outArgs = result.arguments(); QVariant first = outArgs.at(0); QDBusVariant dbvFirst = first.value(); QVariant vFirst = dbvFirst.variant(); QDBusArgument dbusArgs = vFirst.value(); QDBusObjectPath objPath; // qDebug()<<" "; dbusArgs.beginArray(); while (!dbusArgs.atEnd()) { dbusArgs >> objPath; oldPaths.append(objPath); // qDebug() <<"debug: *****path is: "<< objPath.path(); QDBusInterface interface( "org.freedesktop.NetworkManager", objPath.path(), "org.freedesktop.DBus.Properties", QDBusConnection::systemBus() ); QDBusReply reply = interface.call("Get", "org.freedesktop.NetworkManager.Connection.Active", "Type"); // qDebug()<<"debug: *****connection type is: "< m_result = interface.call("Get", "org.freedesktop.NetworkManager", "WirelessEnabled"); qDebug()<<"debug: *****初始的无线网络开关状态是: "<(); QList newPaths; dbusArg >> newPaths; QStringList newPathInfo; qDebug()<<" "; foreach (QDBusObjectPath objPath, newPaths) { qDebug()<<"dbug: bbbbb "< reply = interface.call("Get", "org.freedesktop.NetworkManager.Connection.Active", "Type"); qDebug()<<"dbug: ccccc "<onExternalConnectionChange(oldPathInfo.at(i)); } else { for (int j=0; jonExternalConnectionChange(oldPathInfo.at(i)); } } } } } // 第三步 同上一次获取的已连接网络相比较,处理相比于上次增加的网络连接 for (int i=0; ionExternalConnectionChange(newPathInfo.at(i)); } else { for (int j=0; jonExternalConnectionChange(newPathInfo.at(i)); } } } } bool isChangeOldPathInfo = true; for (int k=0; konExternalWifiSwitchChange(true); setBtnWifiGsetting(true); } if (oldWifiSwitchState == true && newWifiSwitchState == false) { qDebug()<<"debug: wifi开关已经关闭"; is_wificonnected = false; mw->onExternalWifiSwitchChange(false); setBtnWifiGsetting(false); } oldWifiSwitchState = newWifiSwitchState; //更新状态用于下一次 } } } //有线网属性变化时,执行该函数。由于可能在短时间收到几条相同属性变化信息,所以在短时间内,执行一次 void KylinDBus::onLanPropertyChanged(QVariantMap qvm) { if (!isRunningFunction) { syslog(LOG_DEBUG, "kylin-nm receive a signal 'Device.Wired PropertiesChanged' about interface."); qDebug()<<"kylin-nm receive a signal 'Device.Wired PropertiesChanged' about interface."; isRunningFunction = true; //function onLanPropertyChanged is running time->start(3000); QString str = qvm.value("Carrier").toString(); if (str == "false" || str == "true") { getPhysicalCarrierState(1); } } else { a = 0; } } void KylinDBus::slot_timeout() { isRunningFunction = false; time->stop(); } //无线网属性变化时,执行该函数 void KylinDBus::onWifiPropertyChanged(QVariantMap qvm) { //qDebug()<<"debug: *************"<> m_reply = m_interface.call("ListConnections"); QDBusObjectPath active_connection; active_connection.setPath("/"); QList m_objNets = m_reply.value(); foreach (QDBusObjectPath objNet, m_objNets) { QDBusInterface m_interface("org.freedesktop.NetworkManager", objNet.path(), "org.freedesktop.NetworkManager.Settings.Connection", QDBusConnection::systemBus()); QDBusMessage result = m_interface.call("GetSettings"); const QDBusArgument &dbusArg1st = result.arguments().at( 0 ).value(); QMap> map; dbusArg1st >> map; for (QString outside_key : map.keys() ) { QMap outsideMap = map.value(outside_key); if (outside_key == "connection") { for (QString search_key : outsideMap.keys()) { if (search_key == "id") { if (netName == outsideMap.value(search_key).toString()) { QDBusInterface m_interface("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", "org.freedesktop.NetworkManager", QDBusConnection::systemBus() ); QDBusReply connectionReply = m_interface.call("ActivateConnection", QVariant::fromValue(objNet), QVariant::fromValue(wiredPath), QVariant::fromValue(active_connection)); } } } } } // end for(QString outside_key : map.keys() ) } //end foreach (QDBusObjectPath objNet, m_objNets) } //显示桌面通知 void KylinDBus::showDesktopNotify(QString message) { //锁屏不发送该通知 // emit requestSendDesktopNotify(message); } //获取任务栏位置,上下左右 int KylinDBus::getTaskBarPos(QString str) { QDBusInterface interface( "com.ukui.panel.desktop", "/", "com.ukui.panel.desktop", QDBusConnection::sessionBus() ); QDBusReply reply = interface.call("GetPanelPosition", str); if (reply.isValid()) { return reply; } else { return 0; //如果没有成功获取,返回一个默认值 } } //获取任务栏高度 int KylinDBus::getTaskBarHeight(QString str) { QDBusInterface interface( "com.ukui.panel.desktop", "/", "com.ukui.panel.desktop", QDBusConnection::sessionBus() ); QDBusReply reply = interface.call("GetPanelSize", str); if (reply.isValid()) { return reply; } else { return 46; //如果没有成功获取,返回一个默认值 } } /////////////////////////////////////////////////////////////////////////////// //下方使用Gsetting 进程通信方法 //创建获取任务栏信息的GSetting对象 void KylinDBus::initTaskbarGsetting() { if (QGSettings::isSchemaInstalled("org.ukui.panel.settings")) { m_tastbar_gsettings = new QGSettings("org.ukui.panel.settings"); } if (QGSettings::isSchemaInstalled("org.kylinnm.settings")) { m_nm_gsettings = new QGSettings("org.kylinnm.settings"); if (m_nm_gsettings->keys().contains("wifiswitch")) { m_nm_gsettings->set("wifiswitch",oldWifiSwitchState); } } } //使用GSetting方法获取任务栏高度 int KylinDBus::getTaskbarHeight() { if (!m_tastbar_gsettings) { return 46; } QStringList keys = m_tastbar_gsettings->keys(); if (keys.contains("panelsize")) { int hh = m_tastbar_gsettings->get("panelsize").toInt(); return hh; } else { return 46; } } //使用GSetting方法写入WIFW信号强度 void KylinDBus::setWifiSignal(int wifiSignal, QString wifiname) { if(!m_tastbar_gsettings || !m_nm_gsettings) return; if (m_tastbar_gsettings->keys().contains("wifisignal")) { m_tastbar_gsettings->set("wifisignal",wifiSignal); } if (m_nm_gsettings->keys().contains("wifisignal")) { m_nm_gsettings->set("wifisignal",wifiSignal); } if (m_nm_gsettings->keys().contains("wifiname")) { m_nm_gsettings->set("wifiname",wifiname); } } //使用GSetting方法获取任务栏位置,上下左右 int KylinDBus::getTaskbarPos() { if (!m_tastbar_gsettings) { return 0; } QStringList keys = m_tastbar_gsettings->keys(); if (keys.contains("panelposition")) { int pp = m_tastbar_gsettings->get("panelposition").toInt(); return pp; } else { return 0; } } //创建监听wifi打开或关闭信息的GSetting对象 void KylinDBus::getWifiSwitchState() { if (QGSettings::isSchemaInstalled("org.ukui.control-center.wifi.switch")) { m_gsettings = new QGSettings("org.ukui.control-center.wifi.switch"); // 监听key的value是否发生了变化 connect(m_gsettings, &QGSettings::changed, this, [=] (const QString &key) { if (key == "switch") { if (isWirelessCardOn) { bool judge = getSwitchStatus(key); if (judge) { mw->onBtnWifiClicked(2); //打开wifi开关 qDebug()<<"receive a signal to turn on wifi switch from control-center"; syslog(LOG_DEBUG, "receive a signal to turn on wifi switch from control-center"); } else { if (!is_wificonnected) { return; } mw->onBtnWifiClicked(3); //关闭wifi开关 qDebug()<<"receive a signal to turn off wifi switch from control-center"; syslog(LOG_DEBUG, "receive a signal to turn off wifi switch from control-center"); } } } }); } } //收到控制面板发来的消息后,获取wifi开关信息 bool KylinDBus::getSwitchStatus(QString key) { if (!m_gsettings) { return true; } const QStringList list = m_gsettings->keys(); if (!list.contains(key)) { return true; } bool res = m_gsettings->get(key).toBool(); return res; } //通知控制面板wifi开关的信息 void KylinDBus::setWifiSwitchState(bool signal) { if (!m_gsettings) { return ; } const QStringList list = m_gsettings->keys(); if (!list.contains("switchor")) { return ; } m_gsettings->set("switchor",signal); if (!m_nm_gsettings) { return ; } if (m_nm_gsettings->keys().contains("wifiswitch")) { m_nm_gsettings->set("wifiswitch",signal); } } void KylinDBus::setWifiConnStatus(bool is_wifi_connected) { // qDebug()<<"WIFI连接状态:"<keys().contains("wificonn")) { m_nm_gsettings->set("wificonn",is_wifi_connected); } } void KylinDBus::setLanConnStatus(bool is_lan_connected) { // qDebug()<<"LAN连接状态:"<keys().contains("lanconn")) { m_nm_gsettings->set("lanconn",is_lan_connected); } } //通知控制面板无线网卡的状态信息 void KylinDBus::setWifiCardState(bool signal) { if (!m_gsettings) { return ; } const QStringList list = m_gsettings->keys(); if (!list.contains("wificard")) { return ; } m_gsettings->set("wificard",signal); } //创建获取窗口透明度信息的GSetting的对象 void KylinDBus::initTransparentState() { if (QGSettings::isSchemaInstalled("org.ukui.control-center.personalise")) { m_transparency_gsettings = new QGSettings("org.ukui.control-center.personalise"); } } //创建WIFI开关状态的GSetting的对象 void KylinDBus::initBtnWifiGsetting() { if (QGSettings::isSchemaInstalled("org.ukui.control-center.wifi.switch")) { m_btnWifi_gsettings = new QGSettings("org.ukui.control-center.wifi.switch"); } } void KylinDBus::setBtnWifiGsetting(bool bl) { if(m_btnWifi_gsettings->get("switch").toBool()!=bl) { m_btnWifi_gsettings->set("switch",bl); } } //根据Dbus路径获取wifi的ssid(排除空格干扰) QString KylinDBus::getWifiSsid(QString accessPointPath) { QDBusInterface interface( "org.freedesktop.NetworkManager", accessPointPath, "org.freedesktop.DBus.Properties", QDBusConnection::systemBus() ); QDBusMessage result = interface.call("Get", "org.freedesktop.NetworkManager.AccessPoint", "Ssid"); if (result.arguments().isEmpty()) return ""; return result.arguments().at(0).value().variant().toString(); } //获取已经连接无线网络的ssid和uuid QList KylinDBus::getAtiveWifiBSsidUuid(QStringList wifilist) { QList strBSsidUuid; QDBusInterface interface( "org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", "org.freedesktop.DBus.Properties", QDBusConnection::systemBus() ); //获取已经连接了那些网络,及这些网络对应的网络类型(ethernet or wifi) QDBusMessage result = interface.call("Get", "org.freedesktop.NetworkManager", "ActiveConnections"); QList outArgs = result.arguments(); QVariant first = outArgs.at(0); QDBusVariant dbvFirst = first.value(); QVariant vFirst = dbvFirst.variant(); QDBusArgument dbusArgs = vFirst.value(); QDBusObjectPath objPath; dbusArgs.beginArray(); while (!dbusArgs.atEnd()) { dbusArgs >> objPath; QDBusInterface interfaceType( "org.freedesktop.NetworkManager", objPath.path(), "org.freedesktop.DBus.Properties", QDBusConnection::systemBus() ); QDBusReply reply = interfaceType.call("Get", "org.freedesktop.NetworkManager.Connection.Active", "Type"); if (reply.value().toString() == "wifi" || reply.value().toString() == "802-11-wireless") { QDBusInterface interfaceInfo( "org.freedesktop.NetworkManager", objPath.path(), "org.freedesktop.DBus.Properties", QDBusConnection::systemBus() ); //获取已经连接wifi的uuid QDBusReply replyUuid = interfaceInfo.call("Get", "org.freedesktop.NetworkManager.Connection.Active", "Uuid"); //qDebug() << "wifi uuid : "<< replyUuid.value().toString(); strBSsidUuid.append(replyUuid.value().toString()); //再获取bssid QDBusMessage resultConnection = interfaceInfo.call("Get", "org.freedesktop.NetworkManager.Connection.Active", "Connection"); QList outArgsConnection = resultConnection.arguments(); QVariant firstConnection = outArgsConnection.at(0); QDBusVariant dbvFirstConnection = firstConnection.value(); QVariant vFirstConnection = dbvFirstConnection.variant(); QDBusObjectPath dbusArgsConnection = vFirstConnection.value(); QDBusInterface interfaceSet("org.freedesktop.NetworkManager", dbusArgsConnection.path(), "org.freedesktop.NetworkManager.Settings.Connection", QDBusConnection::systemBus()); QDBusMessage resultSet = interfaceSet.call("GetSettings"); const QDBusArgument &dbusArg1stSet = resultSet.arguments().at( 0 ).value(); QMap> mapSet; dbusArg1stSet >> mapSet; for (QString setKey : mapSet.keys() ) { QMap subSetMap = mapSet.value(setKey); if (setKey == "802-11-wireless") { for (QString searchKey : subSetMap.keys()) { if (searchKey == "seen-bssids") { //qDebug() << "wifi bssid : "<keys(); if (keys.contains("transparency")) { double tp = m_transparency_gsettings->get("transparency").toDouble(); return tp; } else { return 0.7; } } ukui-screensaver/KylinNM/src/utils.h0000644000175000017500000001226314205074704016421 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /////////////////////////////////////////////////////////////////////////////// // The Utils class, used to do some assist function class Utils : public QObject { Q_OBJECT public: Utils(); static int m_system(char *cmd); public slots: void onRequestSendDesktopNotify(QString message); }; /////////////////////////////////////////////////////////////////////////////// // The UseQssFile class, set control style by using .qss file class UseQssFile { public: static void setStyle(const QString &style) { QString styleName = ":/qss/" + style; QFile qss(styleName); qss.open(QFile::ReadOnly); qApp->setStyleSheet(qss.readAll()); qss.close(); } }; /////////////////////////////////////////////////////////////////////////////// // The NetworkSpeed class, get the network upload and download speed class NetworkSpeed : public QObject { Q_OBJECT public: explicit NetworkSpeed(QObject *parent = nullptr); int getCurrentDownloadRates(char *netname,long int * save_rate,long int * tx_rate); //获取当前的流量,参数为将获取到的流量保 }; /////////////////////////////////////////////////////////////////////////////// // The CustomStyle class, inherit from class QProxyStyle, to change control style customize class CustomStyle : public QProxyStyle { Q_OBJECT public: explicit CustomStyle(const QString &proxyStyleName = "windows", QObject *parent = nullptr); virtual void drawComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget = nullptr) const; virtual void drawControl(QStyle::ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr) const; virtual void drawItemPixmap(QPainter *painter, const QRect &rectangle, int alignment, const QPixmap &pixmap) const; virtual void drawItemText(QPainter *painter, const QRect &rectangle, int alignment, const QPalette &palette, bool enabled, const QString &text, QPalette::ColorRole textRole = QPalette::NoRole) const; virtual void drawPrimitive(QStyle::PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = nullptr) const; virtual QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *option) const; virtual QStyle::SubControl hitTestComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, const QPoint &position, const QWidget *widget = nullptr) const; virtual QRect itemPixmapRect(const QRect &rectangle, int alignment, const QPixmap &pixmap) const; virtual QRect itemTextRect(const QFontMetrics &metrics, const QRect &rectangle, int alignment, bool enabled, const QString &text) const; //virtual int layoutSpacing(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2, Qt::Orientation orientation, const QStyleOption *option, const QWidget *widget); virtual int pixelMetric(QStyle::PixelMetric metric, const QStyleOption *option = nullptr, const QWidget *widget = nullptr) const; virtual void polish(QWidget *widget); virtual void polish(QApplication *application); virtual void polish(QPalette &palette); virtual void unpolish(QWidget *widget); virtual void unpolish(QApplication *application); virtual QSize sizeFromContents(QStyle::ContentsType type, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget = nullptr) const; virtual QIcon standardIcon(QStyle::StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const; virtual QPalette standardPalette() const; virtual int styleHint(QStyle::StyleHint hint, const QStyleOption *option = nullptr, const QWidget *widget = nullptr, QStyleHintReturn *returnData = nullptr) const; virtual QRect subControlRect(QStyle::ComplexControl control, const QStyleOptionComplex *option, QStyle::SubControl subControl, const QWidget *widget = nullptr) const; virtual QRect subElementRect(QStyle::SubElement element, const QStyleOption *option, const QWidget *widget = nullptr) const; signals: public slots: }; #endif // UTILS_H ukui-screensaver/KylinNM/src/backthread.h0000644000175000017500000000403214205074704017344 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include class IFace{ public: QString lname; QString wname; int lstate; // 0已连接 1未连接 2已关闭 int wstate; // 0已连接 1未连接 2已关闭 }; class BackThread : public QObject { Q_OBJECT public: explicit BackThread(QObject *parent = nullptr); ~BackThread(); IFace* execGetIface(); QString getConnProp(QString connName); QString execChkLanWidth(QString ethName); QProcess *cmdConnWifi = nullptr; public slots: void execEnNet(); void execDisNet(); void execEnWifi(); void execDisWifi(); void execConnLan(QString connName); void execConnWifi(QString connName); void execConnWifiPWD(QString connName, QString password); void disConnSparedNetSlot(QString type); void disConnLanOrWifi(QString type); void on_readoutput(); void on_readerror(); signals: void enNetDone(); void disNetDone(); void enWifiDone(); void launchLanDone(); void disWifiDone(); void connDone(int connFlag); void btFinish(); void disFinish(); void ttFinish(); }; #endif // BACKTHREAD_H ukui-screensaver/KylinNM/src/ksimplenm.h0000644000175000017500000000300614205074704017253 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include class KSimpleNM : public QObject { Q_OBJECT public: explicit KSimpleNM(QObject *parent = nullptr); QProcess *runShellProcess = nullptr; QString shellOutput; int type; bool isExecutingGetLanList = false; //是否正在执行获取有线网列表 bool isExecutingGetWifiList = false; //是否正在执行获取无线网列表 bool isUseOldLanSlist = false; //是否应该要用上一次获取的有线列表 void execGetLanList(); void execGetWifiList(); signals: void getLanListFinished(QStringList slist); void getWifiListFinished(QStringList slist); public slots: void readProcess(); void finishedProcess(int msg); }; #endif // KSIMPLENM_H ukui-screensaver/KylinNM/src/kylin-dbus-interface.h0000644000175000017500000001022014205074704021267 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include #include #include #include class KylinNM; class Utils; class KylinDBus : public QObject { Q_OBJECT public: explicit KylinDBus(KylinNM *mw = 0, QObject *parent = nullptr); ~KylinDBus(); void getObjectPath(); int getAccessPointsNumber(); void showDesktopNotify(QString message); void initConnectionInfo(); void connectWiredNet(QString netName); void getConnectNetIp(); int getTaskBarPos(QString str); int getTaskBarHeight(QString str); void initTaskbarGsetting(); int getTaskbarHeight(); int getTaskbarPos(); void getWifiSwitchState(); bool getSwitchStatus(QString key); void setWifiSwitchState(bool signal); void setWifiCardState(bool signal); void initTransparentState(); double getTransparentData(); void initBtnWifiGsetting(); void setBtnWifiGsetting(bool bl); QString getWifiSsid(QString accessPointPath); QList getAtiveWifiBSsidUuid(QStringList wifilist); QDBusObjectPath wiredPath; //有线设备的路径 QDBusObjectPath wirelessPath; //无线设备的路径 QList multiWiredPaths; //已连接网络的对象路径列表 QList multiWiredCableState; bool isWiredCableOn = false; //是否插入了网线 bool isWirelessCardOn = false; //是否插入了无线网卡 QString dbusLanCardName = ""; QString dbusLanIpv4 = ""; QString dbusLanIpv6 = ""; QString dbusActiveLanIpv4 = ""; QString dbusActiveLanIpv6 = ""; QString dbusLanGateway = ""; QString dbusLanMac = ""; QString dbusWiFiCardName = ""; QString dbusWifiMac = ""; public slots: void onNewConnection(QDBusObjectPath objPath); void onConnectionRemoved(QDBusObjectPath objPath); void onPropertiesChanged(QVariantMap qvm); void onLanPropertyChanged(QVariantMap qvm); void onWifiPropertyChanged(QVariantMap qvm); void onAccessPointAdded(QDBusObjectPath objPath); void getPhysicalCarrierState(int n); void getLanHwAddressState(); void getWiredCardName(); void getWirelessCardName(); void getLanIp(QString netName); void getWifiMac(QString netName); void slot_timeout(); void setWifiSignal(int wifiSignal, QString wifiname); void setWifiConnStatus(bool is_wifi_connected); void setLanConnStatus(bool is_lan_connected); private: KylinNM *mw; Utils *mUtils; QThread *mUtilsThread; int a = 0; bool isRunningFunction = false; QTimer *time = nullptr; QList oldPaths; //已连接网络的对象路径列表 QStringList oldPathInfo; //某个已连接网络对象路径对应的网络类型(ethernet or wifi) bool oldWifiSwitchState; //上一次获取到的wifi开关状态 QGSettings *m_tastbar_gsettings = nullptr; QGSettings *m_nm_gsettings = nullptr; QGSettings *m_gsettings = nullptr; QGSettings *m_transparency_gsettings = nullptr; QGSettings *m_btnWifi_gsettings = nullptr; bool is_wificonnected = false; signals: void updateWiredList(int n); void requestSendDesktopNotify(QString message); }; #endif // KYLINDBUSINTERFACE_H ukui-screensaver/KylinNM/src/kylin-network-interface.c0000644000175000017500000006374614205074704022043 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include #include #include #include //获取网络接口名 ifname *kylin_network_get_ifacename() { int i = 0; int sockfd; struct ifconf ifconf; struct ifreq *ifreq; unsigned char buf[1024]; //初始化ifconf ifconf.ifc_len = 1024; //字符串指针ifconf.ifc_buf指向buf ifconf.ifc_buf = buf; if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror("socket error"); return 0; } //获取所有接口信息 ioctl(sockfd, SIOCGIFCONF, &ifconf); // printf("%s\n",ifconf.ifc_buf); //逐个获取Ip地址 //结构体指针ifreq指向buf,即ifconf.ifc_buf ifreq = (struct ifreq*)buf; int number=ifconf.ifc_len/sizeof(struct ifreq); // printf("%d\n",number); ifname *ifn=(ifname *)malloc(sizeof(ifname)*(number+1)); for(i = number; i>0; i--) { // printf("name = [%s] \n",ifreq->ifr_name); int j=number-i; ifn[j].if_name=(char *)malloc(sizeof(char)*10); strcpy(ifn[j].if_name,ifreq->ifr_name); // ifn[j].if_name=ifreq->ifr_name; // printf("if_name[%d]:%s\n",j,if_name[j]); ifreq++; } ifn[number].if_name=NULL; return ifn; } //获取所有网络连接 conlist *kylin_network_get_conlist_info() { int status = system("nmcli connection show > /tmp/conlist.txt"); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection show' in function 'kylin_network_get_conlist_info' failed");} char *filename="/tmp/conlist.txt"; FILE *confp; int connum=0; char ConStrLine[1024]; if((confp=fopen(filename,"r"))==NULL) { printf("error!"); } fgets(ConStrLine,1024,confp); while(!feof(confp)) { fgets(ConStrLine,1024,confp); connum++; } // printf("%d\n",connum); fclose(confp); conlist *clist=(conlist *)malloc(sizeof(conlist)*connum); int count=0; FILE *fp; char StrLine[1024]; if((fp=fopen(filename,"r"))==NULL) { printf("error!"); } fgets(StrLine,1024,fp); while(!feof(fp)) { if(count==connum-1)break; fgets(StrLine,1024,fp); char *index=StrLine; char conname[100]; //截取连接名称 int num=0; for(index;*index!='\n';index++) { if(*index==' ') { if(*(index+1)==' ') break; } num++; } // printf("连接名称长度:%d\n",num); clist[count].con_name=(char *)malloc(sizeof(char)*(num+1)); strncpy(conname,StrLine,num+1); conname[num]='\0'; strncpy(clist[count].con_name,conname,num+1); // printf("%s\n",clist[count].con_name); //截取连接类型 char type[100]; for(index;*index!='\n';index++) { if(*index==' ') { if(*(index+1)=' ') if(*(index+2)!=' ') break; } } char *index1=index+2; for(index1;*index1!='\n';index1++) { if(*index1==' ') { if(*(index1+1)==' ') break; } } int num1=0; char *index2=index1+2; for(index2;*index2!='\n';index2++) { if(*index2==' ')break; num1++; } clist[count].type=(char *)malloc(sizeof(char)*(num1+1)); strncpy(type,index1+2,num1+1); type[num1]='\0'; strncpy(clist[count].type,type,num1+1); // printf("%s\n",clist[count].type); count++; } fclose(fp); clist[count].con_name=NULL; clist[count].type=NULL; return clist; } //获取当前活动网络连接 activecon *kylin_network_get_activecon_info() { struct passwd *pwd; pwd = getpwuid(getuid()); char *name = pwd->pw_name; char *tmpPrefix = "/tmp/kylin-nm-activecon-"; char *chr = "nmcli connection show -active > "; char *cmd; asprintf(&cmd, "%s%s%s", chr, tmpPrefix, name); char *path; asprintf(&path, "%s%s", tmpPrefix, name); int status = system(cmd); //int status = system("nmcli connection show -active > /tmp/activecon.txt"); if (status != 0) syslog(LOG_ERR, "execute 'nmcli connection show -active' in function 'kylin_network_get_activecon_info' failed"); free(cmd); char *filename = path; FILE *activefp; int activenum=0; char activeStrLine[1024]; if((activefp=fopen(filename,"r"))==NULL) { printf("error!"); } fgets(activeStrLine,1024,activefp); while(!feof(activefp)) { fgets(activeStrLine,1024,activefp); activenum++; } // printf("%d\n",activenum); fclose(activefp); activecon *activelist=(activecon *)malloc(sizeof(activecon)*activenum); int count=0; FILE *fp; char StrLine[1024]; if((fp=fopen(filename,"r"))==NULL) { printf("error!"); } free(path); fgets(StrLine,1024,fp); while(!feof(fp)) { if(count==activenum-1)break; fgets(StrLine,1024,fp); char *index=StrLine; char conname[100]; //截取连接名称 int num=0; for(index;*index!='\n';index++) { if(*index==' ') { if(*(index+1)==' ') break; } num++; } // printf("连接名称长度:%d\n",num); activelist[count].con_name=(char *)malloc(sizeof(char)*(num+1)); strncpy(conname,StrLine,num+1); conname[num]='\0'; strncpy(activelist[count].con_name,conname,num+1); // printf("%s\n",activelist[count].con_name); //截取连接类型 char type[100]; for(index;*index!='\n';index++) { if(*index==' ') { if(*(index+1)=' ') if(*(index+2)!=' ') break; } } char *index1=index+2; for(index1;*index1!='\n';index1++) { if(*index1==' ') { if(*(index1+1)==' ') break; } } int num1=0; char *index2=index1+2; for(index2;*index2!='\n';index2++) { if(*index2==' ')break; num1++; } activelist[count].type=(char *)malloc(sizeof(char)*(num1+1)); strncpy(type,index1+2,num1+1); type[num1]='\0'; strncpy(activelist[count].type,type,num1+1); // printf("%s\n",activelist[count].type); //截取连接所属设备 char *index3=index2; char dev[100]; for(index3;*index3!='\n';index3++) { if(*index3==' ') { if(*(index3+1)!=' ') break; } } int num2=0; char *index4=index3+1; for(index4;*index4!='\n';index4++) { if(*index4==' ')break; num2++; } activelist[count].dev=(char *)malloc(sizeof(char)*(num2+1)); strncpy(dev,index3+1,num2+1); dev[num2]='\0'; strncpy(activelist[count].dev,dev,num2+1); // printf("%s\n",activelist[count].dev); count++; } fclose(fp); activelist[count].con_name=NULL; activelist[count].type=NULL; activelist[count].dev=NULL; return activelist; } //创建新的以太网连接 void kylin_network_create_new_ethernet(char *con_name,char *if_name) { char str[100]; char *net_type="ethernet"; sprintf(str,"nmcli connection add con-name \"%s\" ifname %s type %s",con_name,if_name,net_type); int status = system(str); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection add con-name' in function 'kylin_network_create_new_ethernet' failed");} } // 创建新的wifi连接配置 void kylin_network_create_new_wifi(char *con_name, char *if_name) { char str[200]; sprintf(str, "nmcli connection add con-name \"%s\" ifname \"%s\" type wifi ssid \"%s\"", con_name, if_name, con_name); int status = system(str); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection add con-name' in function 'kylin_network_create_new_wifi' failed");} } //删除以太网连接 void kylin_network_del_ethernet_con(char *con_name) { char str[100]; sprintf(str,"nmcli connection delete \"%s\"",con_name); int status = system(str); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection delete' in function 'kylin_network_del_ethernet_con' failed");} } //设置动态分配ip void kylin_network_set_automethod(char *con_name) { char str[100]; char *automethod="auto"; sprintf(str,"nmcli connection modify \"%s\" ipv4.method %s ipv4.address '' ipv4.gateway ''",con_name,automethod); int status = system(str); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection modify' in function 'kylin_network_set_automethod' failed");} } //设置手动分配ip void kylin_network_set_manualmethod(char *con_name,char *ip) { char str[100]; char *method="manual"; sprintf(str,"nmcli connection modify \"%s\" ipv4.method %s ipv4.address %s",con_name,method,ip); int status = system(str); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection modify' in function 'kylin_network_set_manualmethod' failed");} } // 设置手动分配all void kylin_network_set_manualall(char *con_name, char *addr, char *mask, char *gateway, char *dns){ char str[200]; sprintf(str, "nmcli connection modify \"%s\" ipv4.method manual ipv4.address %s/%s ipv4.gateway %s ipv4.dns %s", con_name, addr, mask, gateway, dns); int status = system(str); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection modify' in function 'kylin_network_set_manualall' failed");} } //设置是否自动连接 void kylin_network_set_autoconnect(char *con_name,bool autocon) { char str[200]; if(autocon==false) { char *ac="no"; sprintf(str,"export LANG='en_US.UTF-8';export LANGUAGE='en_US';nmcli connection modify \"%s\" connection.autoconnect %s",con_name,ac); } else{ char *ac="yes"; sprintf(str,"export LANG='en_US.UTF-8';export LANGUAGE='en_US';nmcli connection modify \"%s\" connection.autoconnect %s",con_name,ac); } int status = system(str); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection modify' in function 'kylin_network_set_autoconnect' failed");} } //修改ip void kylin_network_mod_ip(char *con_name,char *ip) { char str[100]; sprintf(str,"nmcli connection modify \"%s\" ipv4.address %s",con_name,ip); int status = system(str); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection modify' in function 'kylin_network_mod_ip' failed");} } //修改网关 void kylin_network_mod_gateway(char *con_name,char *gw) { char str[100]; sprintf(str,"nmcli connection modify \"%s\" ipv4.gateway %s",con_name,gw); int status = system(str); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection modify' in function 'kylin_network_mod_gateway' failed");} } //修改dns void kylin_network_mod_dns(char *con_name,char *dns) { char str[100]; sprintf(str,"nmcli connection modify \"%s\" ipv4.dns %s",con_name,dns); int status = system(str); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection modify' in function 'kylin_network_mod_dns' failed");} } //连接以太网 void kylin_network_set_con_up(char *con_name) { char str[100]; sprintf(str,"nmcli connection up \"%s\"",con_name); int status = system(str); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection up' in function 'kylin_network_set_con_up' failed");} } //断开以太网 void kylin_network_set_con_down(char *con_name) { char str[100]; sprintf(str,"nmcli connection down \"%s\"",con_name); int status = system(str); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection down' in function 'kylin_network_set_con_down' failed");} } //连接wifi void kylin_network_set_wifi_up(char *con_name,char *passwd) { char str[100]; sprintf(str,"export LANG='en_US.UTF-8';export LANGUAGE='en_US';nmcli device wifi connect \"%s\" password \"%s\"", con_name,passwd); int status = system(str); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli device wifi connect' in function 'kylin_network_set_wifi_up' failed");} } //断开wifi连接 void kylin_network_set_wifi_down(char *if_name) { char str[100]; sprintf(str,"nmcli device disconnect \"%s\"",if_name); int status = system(str); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli device disconnect' in function 'kylin_network_set_wifi_down' failed");} } //获取wifi列表信息 wifilist *kylin_network_get_wifilist_info() { int status = system("nmcli device wifi > /tmp/wflist.txt"); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli device wifi' in function 'kylin_network_get_wifilist_info' failed");} char *filename="/tmp/wflist.txt"; FILE *wffp; int wfnum=0; char WfStrLine[1024]; if((wffp=fopen(filename,"r"))==NULL) { printf("error!"); } fgets(WfStrLine,1024,wffp); while(!feof(wffp)) { fgets(WfStrLine,1024,wffp); wfnum++; } // printf("wifi数量:%d\n",wfnum); fclose(wffp); //wifi实际数量是wfnum-1 wifilist *wflist=(wifilist *)malloc(sizeof(wifilist)*wfnum); int count=0; FILE *fp; char StrLine[1024]; if((fp=fopen(filename,"r"))==NULL) { printf("error!"); } fgets(StrLine,1024,fp); while(!feof(fp)) { if(count==wfnum-1)break; fgets(StrLine,1024,fp); // printf("%s\n",StrLine+3); char *index=StrLine+3; //截取ssid char *str1="Infra"; int num=0; for(index;strcmp(index+5,"\n")!=0;index++) { int result=strncmp(index,str1,5); if(result==0) { // printf("%s\n",index); break; } num++; } char ssid[100]; char *ssidindex=index-1; int ssidnum=0; for(ssidindex;*ssidindex==' ';ssidindex--)ssidnum++; // printf("空格数量:%d\n",ssidnum); // if(ssidnum==1) strncpy(ssid,StrLine+3,num-1); ssid[num-ssidnum]='\0'; // printf("-6666--%s---\n",ssid); wflist[count].ssid=(char *)malloc(sizeof(char)*(num-ssidnum)); strncpy(wflist[count].ssid,ssid,num-ssidnum+1); // printf("第%d个:%s ",count,wflist[count].ssid); //截取信号强度 char *str2="Mbit/s"; for(index;strcmp(index+6,"\n")!=0;index++) { int result=strncmp(index,str2,6); if(result==0) { // printf("%s\n",index); break; } } char signal[10]; char *signalindex=index+8; int signalnum=0; for(signalindex;*signalindex!=' ';signalindex++)signalnum++; strncpy(signal,index+8,signalnum); signal[signalnum]='\0'; // printf("-7777--%s---\n",signal); wflist[count].signal=atoi(signal); // printf("%d ",wflist[count].signal); //截取安全性 char *str3="WPA"; for(index;strcmp(index+3,"\n")!=0;index++) { int result=strncmp(index,str3,3); if(result==0) { // printf("%s\n",index); break; } } char safety[20]; char *safetyindex=index; int safetynum=0; for(safetyindex;strcmp(safetyindex+2,"\n")!=0;safetyindex++) { int result=strncmp(safetyindex," ",2); if(result==0)break; safetynum++; } strncpy(safety,index,safetynum+1); safety[safetynum+1]='\0'; // printf("-8888--%s---\n",safety); wflist[count].safety=(char *)malloc(sizeof(char)*(safetynum+1)); strncpy(wflist[count].safety,safety,safetynum+2); // printf("%s\n",wflist[count].safety); count++; } fclose(fp); wflist[count].ssid=NULL; wflist[count].signal=0; wflist[count].safety=NULL; return wflist; } //启用联网 void kylin_network_enable_networking() { int status = system("nmcli networking on"); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli networking on' in function 'kylin_network_enable_networking' failed");} } //禁用联网 void kylin_network_disable_networking() { int status = system("nmcli networking off"); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli networking off' in function 'kylin_network_disable_networking' failed");} } //启用wifi void kylin_network_enable_wifi() { int status = system("nmcli radio wifi on;sleep 3"); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli radio wifi on' in function 'kylin_network_enable_wifi' failed");} } //禁用wifi void kylin_network_disable_wifi() { int status = system("nmcli radio wifi off;sleep 2"); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli radio wifi off' in function 'kylin_network_disable_wifi' failed");} } //获取ip地址 int kylin_network_get_ipaddr(char *if_name,char *ipaddr) { int sock_ip; struct sockaddr_in sin_ip; struct ifreq ifr_ip; if((sock_ip=socket(AF_INET,SOCK_STREAM,0))<0) { perror("sockket error"); return -1; } strcpy(ifr_ip.ifr_name,if_name); if(ioctl(sock_ip,SIOCGIFADDR,&ifr_ip)<0)//直接获取ip地址 { perror("Not setup interface\n"); return -1; } memcpy(&sin_ip,&ifr_ip.ifr_addr,sizeof(sin_ip)); strcpy(ipaddr,inet_ntoa(sin_ip.sin_addr));//#include close(sock_ip); return 0; } //获取广播地址 int kylin_network_get_brdaddr(char *if_name,char *brdaddr) { int sock_brdaddr; struct sockaddr_in sin_brd; struct ifreq ifr_brd; if((sock_brdaddr=socket(AF_INET,SOCK_STREAM,0))<0) { perror("sockket error"); return -1; } strcpy(ifr_brd.ifr_name,if_name); if(ioctl(sock_brdaddr,SIOCGIFBRDADDR,&ifr_brd)<0)//直接获取广播地址 { perror("Not setup interface\n"); return -1; } memcpy(&sin_brd,&ifr_brd.ifr_broadaddr,sizeof(sin_brd)); strcpy(brdaddr,inet_ntoa(sin_brd.sin_addr)); close(sock_brdaddr); return 0; } //获取子网掩码 int kylin_network_get_netmask(char *if_name,char *netmask) { int sock_mask; struct sockaddr_in sin_netmask; struct ifreq ifr_mask; if((sock_mask=socket(AF_INET,SOCK_STREAM,0))<0) { perror("sockket error"); return -1; } strcpy(ifr_mask.ifr_name,if_name); if(ioctl(sock_mask,SIOCGIFNETMASK,&ifr_mask)<0)//直接获取子网掩码 { perror("Not setup interface\n"); return -1; } memcpy(&sin_netmask,&ifr_mask.ifr_netmask,sizeof(sin_netmask)); strcpy(netmask,inet_ntoa(sin_netmask.sin_addr)); close(sock_mask); return 0; } //获取MAC int kylin_network_get_mac(char *if_name,char *macaddr) { int sock_mac; struct ifreq ifr_mac; struct sockaddr_in sin_mac; struct ether_addr ethaddr;//#include sock_mac=socket(AF_INET,SOCK_STREAM,0); strcpy(ifr_mac.ifr_name,if_name); if(-1==ioctl(sock_mac,SIOCGIFHWADDR,&ifr_mac)) { perror("Not setup interface\n"); return -1; } memcpy(ðaddr,&ifr_mac.ifr_hwaddr.sa_data,sizeof(ethaddr)); strcpy(macaddr,ether_ntoa(ðaddr));//#include // strcpy(macaddr,ether_ntoa((struct ether_addr*)ifr_mac.ifr_hwaddr.sa_data)); close(sock_mac); return 0; } //获取MTU int kylin_network_get_mtu(char *if_name) { int sock_mtu; // struct sockaddr_in sin_ip; struct ifreq ifr_MTU; if((sock_mtu=socket(AF_INET,SOCK_STREAM,0))<0) { perror("sockket error"); return -1; } strcpy(ifr_MTU.ifr_name,if_name); if(ioctl(sock_mtu,SIOCGIFMTU,&ifr_MTU)) { perror("Not setup interface\n"); return -1; } int mtu=ifr_MTU.ifr_mtu; // printf("%d\n",ifr_MTU.ifr_mtu); // printf("%d\n",mtu); close(sock_mtu); return mtu; } static void getBuf(char *bufstr) { //O_RDONLY以只读方式打开文件 int fd=open("/proc/net/dev", O_RDONLY); if(-1==fd) { printf("/proc/net/dev not exists!\n"); } char buf[1024*2]; //将读写位置移到文件开头 lseek(fd,0,SEEK_SET); int nBytes=read(fd,buf,sizeof(buf)-1); if(-1==nBytes) { perror("read error"); close(fd); } buf[nBytes]='\0'; strcpy(bufstr,buf); } //总计上传下载数据量 long *kylin_network_get_bytes(char *if_name) { char buf[1024*2]; getBuf(buf); //返回第一次指向if_name位置的指针 char *pDev=strstr(buf,if_name); if(NULL==pDev) { printf("don't find dev %s\n",if_name); return NULL; } char *p; char *value; int i=0; static long rtbyt[2]; /*去除空格,制表符,换行符等不需要的字段*/ for (p = strtok(pDev, " \t\r\n"); p; p = strtok(NULL, " \t\r\n")) { i++; value = (char*)malloc(20); strcpy(value, p); /*得到的字符串中的第二个字段是接收流量*/ if(i == 2) { rtbyt[0] = atol(value); } /*得到的字符串中的第十个字段是发送流量*/ if(i == 10) { rtbyt[1] = atol(value); break; } free(value); } return rtbyt; } //总计上传下载数据包 long *kylin_network_get_packets(char *if_name) { char buf[1024*2]; getBuf(buf); //返回第一次指向if_name位置的指针 char *pDev=strstr(buf,if_name); if(NULL==pDev) { printf("don't find dev %s\n",if_name); return NULL; } char *p; char *value; int i=0; static long rtpkt[2]; /*去除空格,制表符,换行符等不需要的字段*/ for (p = strtok(pDev, " \t\r\n"); p; p = strtok(NULL, " \t\r\n")) { i++; value = (char*)malloc(20); strcpy(value, p); /*得到的字符串中的第三个字段是接收流量*/ if(i == 3) { rtpkt[0] = atol(value); } /*得到的字符串中的第十一个字段是发送流量*/ if(i == 11) { rtpkt[1] = atol(value); break; } free(value); } return rtpkt; } //总计上传下载错误数据包数量 long *kylin_network_get_errs(char *if_name) { char buf[1024*2]; getBuf(buf); //返回第一次指向if_name位置的指针 char *pDev=strstr(buf,if_name); if(NULL==pDev) { printf("don't find dev %s\n",if_name); return NULL; } char *p; char *value; int i=0; static long rterrs[2]; /*去除空格,制表符,换行符等不需要的字段*/ for (p = strtok(pDev, " \t\r\n"); p; p = strtok(NULL, " \t\r\n")) { i++; value = (char*)malloc(20); strcpy(value, p); /*得到的字符串中的第四个字段是接收流量*/ if(i == 4) { rterrs[0] = atol(value); } /*得到的字符串中的第十二个字段是发送流量*/ if(i == 12) { rterrs[1] = atol(value); break; } free(value); } return rterrs; } //总计上传下载丢弃数据包数量 long *kylin_network_get_drop(char *if_name) { char buf[1024*2]; getBuf(buf); //返回第一次指向if_name位置的指针 char *pDev=strstr(buf,if_name); if(NULL==pDev) { printf("don't find dev %s\n",if_name); return NULL; } char *p; char *value; int i=0; static long rtdrop[2]; /*去除空格,制表符,换行符等不需要的字段*/ for (p = strtok(pDev, " \t\r\n"); p; p = strtok(NULL, " \t\r\n")) { i++; value = (char*)malloc(20); strcpy(value, p); /*得到的字符串中的第五个字段是接收流量*/ if(i == 5) { rtdrop[0] = atol(value); } /*得到的字符串中的第十三个字段是发送流量*/ if(i == 13) { rtdrop[1] = atol(value); break; } free(value); } return rtdrop; } //总计上传下载过载数据包数量 long *kylin_network_get_fifo(char *if_name) { char buf[1024*2]; getBuf(buf); //返回第一次指向if_name位置的指针 char *pDev=strstr(buf,if_name); if(NULL==pDev) { printf("don't find dev %s\n",if_name); return NULL; } char *p; char *value; int i=0; static long rtfifo[2]; /*去除空格,制表符,换行符等不需要的字段*/ for (p = strtok(pDev, " \t\r\n"); p; p = strtok(NULL, " \t\r\n")) { i++; value = (char*)malloc(20); strcpy(value, p); /*得到的字符串中的第六个字段是接收流量*/ if(i == 6) { rtfifo[0] = atol(value); } /*得到的字符串中的第十四个字段是发送流量*/ if(i == 14) { rtfifo[1] = atol(value); break; } free(value); } return rtfifo; } ukui-screensaver/KylinNM/src/onelancform.cpp0000644000175000017500000004164514205074704020125 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see OneLancForm::OneLancForm(QWidget *parent, KylinNM *mainWindow, ConfForm *confForm, KSimpleNM *ksnm) : QWidget(parent), ui(new Ui::OneLancForm) { ui->setupUi(this); ui->btnConnSub->setText(tr("Connect"));//"设置" ui->btnConn->setText(tr("Connect"));//"连接" ui->btnConn->hide();//YYF ui->btnDisConn->setText(tr("Disconnect"));//"断开连接" ui->lbConned->setAlignment(Qt::AlignLeft); leQssLow = "QLineEdit{border:none;background:transparent;font-size:14px;color:rgba(255,255,255,0.57);font-family:Noto Sans CJK SC;}"; leQssHigh = "QLineEdit{border:none;background:transparent;font-size:14px;color:rgba(255,255,255,0.91);font-family:Noto Sans CJK SC;}"; ui->leInfo_1->setStyleSheet(leQssLow); ui->leInfo_2->setStyleSheet(leQssLow); ui->leInfo_3->setStyleSheet(leQssLow); ui->leInfo_4->setStyleSheet(leQssLow); ui->btnInfo->setStyleSheet("QPushButton{border:none;background:transparent;}"); ui->wbg->setStyleSheet("#wbg{border-radius:8px;background-color:rgba(255,255,255,0.1);border:1px solid red;}");//主窗口(展开) ui->wbg_2->setStyleSheet("#wbg_2{border-radius:8px;background-color:rgba(255,255,255,0);}");//列表窗口(闭合) ui->lbName->setStyleSheet("QLabel{font-size:14px;color:rgba(38, 38, 38, 1);}");//列表名称 ui->lbConned->setStyleSheet("QLabel{font-size:14px;color:rgba(47, 179, 232, 1);}");//已连接 ui->btnConnSub->setStyleSheet("QPushButton{border:0px;border-radius:4px;background-color:rgba(61,107,229,1);color:white;font-size:14px;}" "QPushButton:Hover{border:0px solid rgba(255,255,255,0.2);border-radius:4px;background-color:rgba(107,142,235,1);}" "QPushButton:Pressed{border-radius:4px;background-color:rgba(50,87,202,1);}"); ui->btnConn->setStyleSheet("QPushButton{border:0px;border-radius:4px;background-color:rgba(61,107,229,1);color:white;font-size:14px;}" //连接按钮 "QPushButton:Hover{border:0px solid rgba(255,255,255,0.2);border-radius:4px;background-color:rgba(107,142,235,1);}" "QPushButton:Pressed{border-radius:4px;background-color:rgba(50,87,202,1);}"); // ui->btnDisConn->setStyleSheet("QPushButton{border:0px;border-radius:4px;background-color:rgba(255,255,255,0.12);color:white;font-size:14px;}" // "QPushButton:Hover{border:0px solid rgba(255,255,255,0.2);border-radius:4px;background-color:rgba(255,255,255,0.2);}" // "QPushButton:Pressed{border-radius:8px;background-color:rgba(255,255,255,0.08);}"); ui->btnDisConn->setStyleSheet("#btnDisConn{font-family: NotoSansCJKsc-Regular, NotoSansCJKsc;" "font-weight: 400;color: rgba(38,38,38,0.75);line-height: 20px;font-size:14px;" "border:0px;background-color:rgba(38,38,38,0.1);border-radius:8px;}" "#btnDisConn:Hover{border:0px solid rgba(255,255,255,0.2);border-radius:8px;background-color:rgba(38,38,38,0.2);}" "#btnDisConn:Pressed{border-radius:8px;background-color:rgba(38,38,38,0.06);}");//断开链接按钮 ui->btnConnCfg->setStyleSheet("border:0px;border-radius:4px;border-image:url(:/res/l/pb-network-info.png);");//链接详情按钮 connect(ui->btnConnCfg,&QPushButton::clicked,this,&OneLancForm::on_btnInfo_clicked); ui->btnConnCfg->hide(); ui->btnInfo->setCursor(QCursor(Qt::PointingHandCursor)); ui->btnInfo->setFocusPolicy(Qt::NoFocus); ui->btnConnSub->setFocusPolicy(Qt::NoFocus); ui->btnConn->setFocusPolicy(Qt::NoFocus); ui->btnDisConn->setFocusPolicy(Qt::NoFocus); ui->wbg->hide(); ui->wbg_2->show(); ui->lbName->show(); ui->btnConnSub->hide(); //YYF ui->btnConn->hide(); ui->btnDisConn->hide(); ui->line->show(); ui->lbWaiting->hide(); ui->lbWaitingIcon->hide(); this->mw = mainWindow; this->cf = confForm; this->ks = ksnm; this->isSelected = false; this->isActive = false; this->setAttribute(Qt::WA_Hover,true); this->installEventFilter(this); ui->btnInfo->setAttribute(Qt::WA_Hover,true); ui->btnInfo->installEventFilter(this); this->waitTimer = new QTimer(this); connect(waitTimer, SIGNAL(timeout()), this, SLOT(waitAnimStep())); connect(mw, SIGNAL(waitLanStop()), this, SLOT(stopWaiting())); srand((unsigned)time(NULL)); ui->lbWaiting->setStyleSheet("QLabel{border:0px;border-radius:4px;background-color:rgba(61,107,229,1);}"); //ui->lbWaitingIcon->setStyleSheet("QLabel{border:0px;background-color:transparent;}"); ui->lbWaitingIcon->setStyleSheet("QLabel{border:0px;background-color:transparent;}"); ui->lbWaitingIcon->move(316+194*mw->isTabletStyle,20);// YYF tabletStyle();//平板模式PC桌面样式 } void OneLancForm::tabletStyle()//平板桌面模式特有设置 { ui->lbName->setFixedWidth(190+194*mw->isTabletStyle); ui->btnInfo->setFixedWidth(414+194*mw->isTabletStyle); ui->wbg_2->setFixedWidth(414+194*mw->isTabletStyle); ui->btnDisConn->move(316+194*mw->isTabletStyle,8 + 18*mw->isTabletStyle); ui->btnConnCfg->move(364+194*mw->isTabletStyle,18 + 18*mw->isTabletStyle); } OneLancForm::~OneLancForm() { delete ui; } void OneLancForm::mousePressEvent(QMouseEvent *event) { if (event->button() != Qt::LeftButton) { event->ignore(); return; } ui->wbg_2->setStyleSheet("#wbg_2{border-radius:8px;background-color:rgba(38,38,38,0.1);}"); } void OneLancForm::mouseReleaseEvent(QMouseEvent *event) { if (event->button() != Qt::LeftButton || !rect().contains(event->pos())) { event->ignore(); return; } if(ui->btnDisConn->isHidden()) { on_btnConn_clicked();// YYF } ui->wbg_2->setStyleSheet("#wbg_2{border-radius:8px;background-color:rgba(255,255,255,0);}"); } //事件过滤器 bool OneLancForm::eventFilter(QObject *obj, QEvent *event) { if (obj == ui->btnInfo) { if(event->type() == QEvent::HoverEnter) { ui->leInfo_1->setStyleSheet(leQssHigh); ui->leInfo_2->setStyleSheet(leQssHigh); ui->leInfo_3->setStyleSheet(leQssHigh); ui->leInfo_4->setStyleSheet(leQssHigh); return true; } else if(event->type() == QEvent::HoverLeave) { ui->leInfo_1->setStyleSheet(leQssLow); ui->leInfo_2->setStyleSheet(leQssLow); ui->leInfo_3->setStyleSheet(leQssLow); ui->leInfo_4->setStyleSheet(leQssLow); return true; } } else if (obj == this) { if (event->type() == QEvent::HoverEnter) { if (!this->isTopItem) { if (!this->isSelected) { //YYF ui->btnConn->show(); ui->wbg_2->setStyleSheet("#wbg_2{border-radius:8px;background-color:rgba(38,38,38,0.05);}"); ui->wbg_2->show(); } } return true; } else if(event->type() == QEvent::HoverLeave) { //YYF ui->btnConn->hide(); ui->wbg_2->setStyleSheet("#wbg_2{border-radius:8px;background-color:rgba(255,255,255,0);}"); ui->wbg_2->hide(); return true; } } return QWidget::eventFilter(obj,event); } // 是否当前连接的网络,字体设置不同 void OneLancForm::setAct(bool isAct) { if (isAct) { ui->lbName->setStyleSheet("QLabel{font-size:14px;color:rgba(47, 179, 232, 1);}"); ui->lbConned->show(); ui->btnConnSub->hide(); } else { ui->lbName->setStyleSheet("QLabel{font-size:14px;color:rgba(38, 38, 38, 0.45);}"); ui->lbConned->hide(); ui->btnConnSub->hide(); } isActive = isAct; } // 是否选中 void OneLancForm::setSelected(bool isSelected, bool isCurrName) { if (isSelected) { resize(W_ITEM, H_ITEM_EXTEND); ui->wbg->show(); ui->wbg_2->hide(); ui->line->move(X_LINE_EXTEND, Y_LINE_EXTEND); //YYF ui->btnConn->hide(); ui->btnConnSub->show(); this->isSelected = true; } else { resize(W_ITEM, H_ITEM); ui->wbg->hide(); ui->wbg_2->show(); ui->line->move(X_LINE, Y_LINE); if(isCurrName){ //YYF ui->btnConn->show(); }else{ //YYF ui->btnConn->hide(); } ui->btnConnSub->hide(); this->isSelected = false; } ui->btnDisConn->hide(); this->isTopItem = false; } //设置顶部这个item的显示 void OneLancForm::setTopItem(bool isSelected) { // if (isSelected) { // resize(W_ITEM, H_ITEM_EXTEND); // ui->wbg->show(); // ui->btnConnSub->hide(); // this->isSelected = true; // } else { // resize(W_ITEM, H_ITEM); // ui->wbg->hide(); // ui->btnConnSub->hide(); // this->isSelected = false; // } if (isConnected) { ui->lbIcon->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/l/pb-network-online.png);}"); ui->btnDisConn->show(); // ui->btnConnCfg->show(); } else { ui->lbIcon->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/l/pb-top-network-offline.png);}"); // ui->btnConnCfg->hide(); ui->btnDisConn->hide(); } ui->btnConnCfg->hide(); //YYF ui->btnConn->hide(); ui->wbg_2->hide(); ui->line->hide(); this->isTopItem = true; } //设置网络名称 void OneLancForm::setName(QString name, QString uniName) { ui->lbName->setText(name); lanName = name; uniqueName = uniName; } //根据有线网络连接与否,设置显示'已连接'文字的控件的可见与否 void OneLancForm::setConnedString(bool showLable, QString str) { if (!showLable) { ui->lbConned->hide(); ui->lbName->move(63, 18); } else { str="";//YYF 平板模式 ui->lbConned->setText(str); ui->lbName->move(63, 18); //YYF } } //设置item被扩展后出现的网络信息 void OneLancForm::setLanInfo(QString str1, QString str2, QString str3, QString str4) { if (str1 == "" || str1 == "auto") { str1 = tr("No Configuration"); } if (str2 == "" || str2 == "auto") { str2 = tr("No Configuration"); } QString strIPv4 = QString(tr("IPv4:")); QString strIPv6 = QString(tr("IPv6:")); QString strBW = QString(tr("BandWidth:")); QString strMAC = QString(tr("MAC:")); ui->leInfo_1->setText(strIPv4 + str1); ui->leInfo_2->setText(strIPv6 + str2); ui->leInfo_3->setText(strBW + str3); ui->leInfo_4->setText(strMAC + str4); } //根据网络是否连接,设置网络状态图标 void OneLancForm::setIcon(bool isOn) { if (isOn) { ui->lbIcon->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/l/pb-network-online.png);}"); } else { ui->lbIcon->setStyleSheet("QLabel{border-radius:0px;border-image:url(:/res/l/pb-network-offline.png);}"); } } //设置item下方横线的可见与否 void OneLancForm::setLine(bool isShow) { if (isShow) { ui->line->show(); } else { ui->line->hide(); } } void OneLancForm::slotConnLan() { //mw->startLoading(); this->startWaiting(true); emit sigConnLan(ui->lbName->text()); } //点击网络断开按钮,执行该函数 void OneLancForm::on_btnDisConn_clicked() { syslog(LOG_DEBUG, "DisConnect button about lan net is clicked, current wired net name is %s .", ui->lbName->text().toUtf8().data()); qDebug()<<"DisConnect button about lan net is clicked, current wired net name is "<lbName->text(); this->startWaiting(false); mw->is_stop_check_net_state = 1; kylin_network_set_con_down(ui->lbName->text().toUtf8().data()); disconnect(this, SIGNAL(selectedOneLanForm(QString, QString)), mw, SLOT(oneTopLanFormSelected(QString, QString))); emit disconnActiveLan(); } //点击了连接网络按钮,执行该函数 void OneLancForm::on_btnConn_clicked() { syslog(LOG_DEBUG, "A button named btnConn about lan net is clicked."); qDebug()<<"A button named btnConn about lan net is clicked."; toConnectWiredNetwork(); } //点击了item被扩展中的连接网络按钮,执行该函数 void OneLancForm::on_btnConnSub_clicked() { syslog(LOG_DEBUG, "A button named btnConnSub about lan net is clicked."); qDebug()<<"A button named btnConnSub about lan net is clicked."; toConnectWiredNetwork(); } void OneLancForm::toConnectWiredNetwork() { mw->is_stop_check_net_state = 1; QThread *t = new QThread(); BackThread *bt = new BackThread(); bt->moveToThread(t); connect(t, SIGNAL(finished()), t, SLOT(deleteLater())); connect(t, SIGNAL(started()), this, SLOT(slotConnLan())); connect(this, SIGNAL(sigConnLan(QString)), bt, SLOT(execConnLan(QString))); // connect(bt, SIGNAL(connDone(int)), mw, SLOT(connLanDone(int))); connect(bt, &BackThread::connDone, this, [=](int f) { mw->connLanDone(f); }); connect(bt, SIGNAL(btFinish()), t, SLOT(quit())); t->start(); } //点击列表中item扩展后显示信息的位置时,执行该函数,用于显示网络配置界面 void OneLancForm::on_btnInfo_clicked() { QPoint pos = QCursor::pos(); QRect primaryGeometry; for (QScreen *screen : qApp->screens()) { if (screen->geometry().contains(pos)) { primaryGeometry = screen->geometry(); } } if (primaryGeometry.isEmpty()) { primaryGeometry = qApp->primaryScreen()->geometry(); } BackThread *bt = new BackThread(); QString connProp = bt->getConnProp(ui->lbName->text()); QStringList propList = connProp.split("|"); QString v4method, addr, mask, gateway, dns; foreach (QString line, propList) { if (line.startsWith("method:")) { v4method = line.split(":").at(1); } if (line.startsWith("addr:")) { addr = line.split(":").at(1); } if (line.startsWith("mask:")) { mask = line.split(":").at(1); } if (line.startsWith("gateway:")) { gateway= line.split(":").at(1); } if (line.startsWith("dns:")) { dns = line.split(":").at(1); } } // qDebug()<setProp(ui->lbName->text(), v4method, addr, mask, gateway, dns, this->isActive); connect(cf, SIGNAL(requestRefreshLanList(int)), mw, SLOT(onBtnNetListClicked(int))); cf->move(primaryGeometry.width() / 2 - cf->width() / 2, primaryGeometry.height() / 2 - cf->height() / 2); cf->show(); cf->raise(); cf->activateWindow(); } void OneLancForm::waitAnimStep() { QString qpmQss = "QLabel{background-image:url(':/res/s/conning-a/"; qpmQss.append(QString::number(this->waitPage)); qpmQss.append(".png');}"); ui->lbWaitingIcon->setStyleSheet(qpmQss); this->waitPage --; if (this->waitPage < 1) { this->waitPage = TOTAL_PAGE; //循环播放8张图片 } this->countCurrentTime += FRAME_SPEED; if (this->countCurrentTime >= LIMIT_TIME) { QString cmd = "kill -9 $(pidof nmcli)"; //杀掉当前正在进行的有关nmcli命令的进程 int status = system(cmd.toUtf8().data()); if (status != 0) { qDebug()<<"execute 'kill -9 $(pidof nmcli)' in function 'waitAnimStep' failed"; syslog(LOG_ERR, "execute 'kill -9 $(pidof nmcli)' in function 'waitAnimStep' failed"); } this->stopWaiting(); //动画超出时间限制,强制停止动画 mw->is_stop_check_net_state = 0; } } void OneLancForm::startWaiting(bool isConn) { if (isConn) { ui->lbWaiting->setStyleSheet("QLabel{border:0px;border-radius:4px;background-color:rgba(61,107,229,1);}"); } else { ui->btnDisConn->hide(); ui->lbWaiting->setStyleSheet("QLabel{border:0px;border-radius:4px;background-color:rgba(255,255,255,0.12);}"); } this->countCurrentTime = 0; this->waitPage = TOTAL_PAGE; //总共有8张图片 this->waitTimer->start(FRAME_SPEED); // ui->lbWaiting->show(); YYF ui->lbWaitingIcon->show(); mw->setTrayLoading(true); } void OneLancForm::stopWaiting() { this->waitTimer->stop(); ui->lbWaiting->hide(); ui->lbWaitingIcon->hide(); mw->setTrayLoading(false); mw->getActiveInfo(); } ukui-screensaver/KylinNM/src/oneconnform.ui0000644000175000017500000001453114205074704017772 0ustar fengfeng OneConnForm 0 0 424 156 Form 63 8 190 20 316 14 100 34 316 14 100 34 14 14 28 28 63 31 140 20 0 0 424 156 56 56 254 48 286 75 16 8 56 110 414 40 326 14 80 40 318 56 80 48 316 14 100 34 0 0 424 138 63 64 230 56 63 62 230 20 63 86 230 20 63 110 230 20 leInfo_1 leInfo_2 leInfo_3 btnInfo 2 59 421 2 background-color: rgba(255, 255, 255,0.05); Qt::Horizontal 0 0 414 56 280 20 20 20 280 20 20 20 372 14 16 16 wbg_3 wbg_2 lbName lbSignal lbConned line wbg btnConnSub btnConn btnConnPWD btnDisConn btnHideConn lbWaiting lbWaitingIcon btnInfo_2 ukui-screensaver/KylinNM/src/swipegesturerecognizer.h0000644000175000017500000000402314205074760022074 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef SWIPEGESTURERECOGNIZER_H #define SWIPEGESTURERECOGNIZER_H #include #include #include #include "kylinnm.h" /** * @brief The SwipeGestureRecognizer class * needed because the defalt implementation of swipe is a little bit odd: it only triggers on 3 finger swipes! (5.3) * * http://developer.android.com/design/patterns/gestures.html * http://qt-project.org/doc/qt-5/gestures-overview.html */ class SwipeGestureRecognizer :public QObject, public QGestureRecognizer { Q_OBJECT public: SwipeGestureRecognizer(QObject *parent = nullptr); private: static const int MINIMUM_DISTANCE = 10; typedef QGestureRecognizer parent; bool IsValidMove(int dx, int dy); qreal ComputeAngle(int dx, int dy); virtual QGesture* create(QObject* pTarget); virtual QGestureRecognizer::Result recognize(QGesture* pGesture, QObject *pWatched, QEvent *pEvent); void reset (QGesture *pGesture); signals: void onSwipeGesture(int dx, int dy); }; class SwipeGestureUtil { public: static QSwipeGesture::SwipeDirection GetHorizontalDirection(QSwipeGesture *pSwipeGesture); static QSwipeGesture::SwipeDirection GetVerticalDirection(QSwipeGesture *pSwipeGesture); }; #endif // SWIPEGESTURERECOGNIZER_H ukui-screensaver/KylinNM/src/onelancform.h0000644000175000017500000000545314205074704017567 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include "confform.h" #include "kylin-network-interface.h" #include "backthread.h" #include "ksimplenm.h" #define FRAME_SPEED 150 #define LIMIT_TIME 20*1000 #define TOTAL_PAGE 8 #define W_ITEM 424 #define H_ITEM 60 #define H_ITEM_EXTEND 162 #define Y_LINE 59 #define X_LINE 2 #define Y_LINE_EXTEND 161 #define X_LINE_EXTEND 2 class KylinNM; namespace Ui { class OneLancForm; } class OneLancForm : public QWidget { Q_OBJECT public: explicit OneLancForm(QWidget *parent = 0, KylinNM *mw = 0, ConfForm *confForm = 0, KSimpleNM *ksnm = 0); ~OneLancForm(); void setName(QString name, QString uniName); void setIcon(bool isOn); void setLine(bool isShow); void setLanInfo(QString str1, QString str2, QString str3, QString str4); void setSelected(bool isSelected, bool isCurrName); void setTopItem(bool isSelected); void setAct(bool isAct); void setConnedString(bool showLable, QString str); bool isSelected; bool isTopItem; bool isActive; bool isConnected; QString lanName; QString uniqueName; protected: void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event) override; bool eventFilter(QObject *obj, QEvent *event); private slots: void on_btnConn_clicked(); void on_btnConnSub_clicked(); void on_btnDisConn_clicked(); void toConnectWiredNetwork(); void slotConnLan(); void waitAnimStep(); void startWaiting(bool isConn); void stopWaiting(); void on_btnInfo_clicked(); private: void tabletStyle();//YYF 平板桌面模式特有设置 QTimer *waitTimer = nullptr; int waitPage; int countCurrentTime; Ui::OneLancForm *ui = nullptr; KylinNM *mw = nullptr; ConfForm *cf = nullptr; KSimpleNM *ks = nullptr; QString leQssLow, leQssHigh; signals: void selectedOneLanForm(QString lanName, QString uniqueName); void connDone(int connFlag); void disconnActiveLan(); void sigConnLan(QString); }; #endif // ONELANCFORM_H ukui-screensaver/KylinNM/src/main.cpp0000644000175000017500000000430314205074704016534 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #define LOG_IDENT "ukui_kylin_nm" int main(int argc, char *argv[]) { //QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); Display *disp = XOpenDisplay(NULL); Screen *scrn = DefaultScreenOfDisplay(disp); if (NULL == scrn) { return 0; } int width = scrn->width; if (width > 2560) { #if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); #endif } if (NULL != disp) { XCloseDisplay(disp); } QApplication a(argc, argv); openlog(LOG_IDENT, LOG_NDELAY | LOG_NOWAIT | LOG_PID, LOG_USER); syslog(LOG_DEBUG, "Kylin Network Manager Is Already Launched"); // Internationalization QString locale = QLocale::system().name(); QTranslator trans_global; if (locale == "zh_CN") { trans_global.load(":/translations/kylin-nm_zh_CN.qm"); //trans_global.load(":/translations/kylin-nm_bo.qm"); a.installTranslator(&trans_global); } if (locale == "tr_TR") { trans_global.load(":/translations/kylin-nm_tr.qm"); a.installTranslator(&trans_global); } KylinNM w; return a.exec(); } ukui-screensaver/KylinNM/src/kylinnm.ui0000644000175000017500000001440214205074704017125 0ustar fengfeng KylinNM 0 0 441 443 kylin-nm 0 0 442 437 1 200 37 37 2 200 37 37 385 73 50 24 400 400 37 37 2 348 37 37 2 395 37 37 16 72 80 20 413 75 20 20 11 359 19 19 11 405 19 19 0 0 37 37 221 0 37 37 63 17 24 24 288 16 24 24 2 348 37 37 2 395 37 37 0 0 221 56 221 0 221 56 409 409 19 19 btnConfImg lbFlyBG lbHotBG lbFlyImg lbHotImg lbBtnNetBG btnNet lbBtnWifiBG btnAdvConf btnHotspot btnFlyMode lbBtnWifiBall lbNetListBG lbWifiListBG lbWifiListImg lbNetListImg btnNetList btnWifiList lbNetwork ukui-screensaver/KylinNM/src/oneconnform.h0000644000175000017500000000734614205074704017612 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include #include #include "confform.h" #include "backthread.h" #include "ksimplenm.h" #define FRAME_SPEED 150 #define LIMIT_TIME 20*1000 #define TOTAL_PAGE 8 #define W_ITEM 414 #define H_ITEM 60 #define H_ITEM_BIG 138 #define H_ITEM_MIDDLE 156 #define H_WIFI_ITEM_BIG_EXTEND 78 //138 - 60 #define H_WIFI_ITEM_SMALL_EXTEND 96 //156 - 56 #define Y_LINE 59 #define X_LINE 2 #define Y_LINE_SMALL_EXTEND 105 #define X_LINE_SMALL_EXTEND 2 #define Y_LINE_BIG_EXTEND 137 #define X_LINE_BIG_EXTEND 2 class KylinNM; namespace Ui { class OneConnForm; } class OneConnForm : public QWidget { Q_OBJECT public: explicit OneConnForm(QWidget *parent = 0, KylinNM *mw = 0, ConfForm *confForm = 0, KSimpleNM *ksnm = 0); ~OneConnForm(); void setSignal(QString lv, QString secu); void setSignalOn(QString lv, QString secu); void setName(QString name); void setSpecialName(QString name); QString getName(); void setRate(QString rate); void setLine(bool isShow); void setWifiInfo(QString str1, QString str2, QString str3); void setSelected(bool isSelected, bool isCurrName); void setHideItem(bool isHideItem, bool isShowHideBtn); void setTopItem(bool isSelected); void setAct(bool isAct); void setConnedString(bool showLable, QString str, QString str1); bool isWifiConfExist(QString netName); QString wifiName; bool isSelected; bool isActive; bool isConnected; bool isTopItem; int signalLv; protected: void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event) override; bool eventFilter(QObject *obj, QEvent *event); private slots: void tabletStyle(); void on_btnConn_clicked(); void on_btnConnSub_clicked(); void on_btnDisConn_clicked(); void on_btnInfo_2_clicked(); void toConnectWirelessNetwork(); void on_autoConn_toggled(bool val); void slotConnWifi(); void slotConnWifiPWD(); void slotConnWifiResult(int connFlag); void on_btnConnPWD_clicked(); void on_btnHideConn_clicked(); void on_checkBoxPwd_stateChanged(int arg1); void on_lePassword_textEdited(const QString &arg1); void waitAnimStep(); void startWaiting(bool isConn); void stopWaiting(); void on_btnInfo_clicked(); private: QTimer *waitTimer = nullptr; int waitPage; int countCurrentTime; bool isWaiting = false; Ui::OneConnForm *ui = nullptr; KylinNM *mw = nullptr; ConfForm *cf = nullptr; KSimpleNM *ks = nullptr; bool hasPwd; QString leQssLow, leQssHigh; QString signalStrong="0"; QString signalHasPw="--"; bool is_connecting = false; signals: void selectedOneWifiForm(QString wifiName, int extendLength); void connDone(int connFlag); void disconnActiveWifi(); void sigConnWifi(QString); void sigConnWifiPWD(QString, QString); void onLineEditClicked(); }; #endif // ONECONNFORM_H ukui-screensaver/KylinNM/hot-spot/0000755000175000017500000000000014205074704016072 5ustar fengfengukui-screensaver/KylinNM/hot-spot/dlghotspotcreate.cpp0000644000175000017500000001355314205074704022160 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see setupUi(this); this->setWindowFlags(Qt::FramelessWindowHint); this->setStyleSheet("background-color:white;"); ui->lbLeftup->setStyleSheet("QLabel{background-color:#266ab5;}"); ui->lbLeftupIcon->setStyleSheet("QLabel{background-image:url(:/res/h/no-pwd-wifi.png);background-color:transparent;}"); ui->lbLeftupTitle->setStyleSheet("QLabel{font-size:12px;color:#ffffff;background-color:transparent;}"); ui->btnCancel->setStyleSheet("QPushButton{border:1px solid #aaaaaa;background-color:#f5f5f5;}" "QPushButton:Hover{border:2px solid #629ee8;background-color:#eeeeee;}" "QPushButton:Pressed{border:1px solid #aaaaaa;background-color:#d8d8d8;}"); ui->btnOk->setStyleSheet("QPushButton{border:1px solid #aaaaaa;background-color:#f5f5f5;}" "QPushButton:Hover{border:2px solid #629ee8;background-color:#eeeeee;}" "QPushButton:Pressed{border:1px solid #aaaaaa;background-color:#d8d8d8;}"); ui->checkBoxPwd->setStyleSheet("QCheckBox::indicator {width: 18px; height: 9px;}" "QCheckBox::indicator:checked {image: url(:/res/h/show-pwd.png);}" "QCheckBox::indicator:unchecked {image: url(:/res/h/hide-pwd.png);}"); ui->lbLeftupTitle->setText(tr("Create Hotspot")); //创建个人热点 ui->lbNetName->setText(tr("Network name")); //网络名称: ui->lbSecurity->setText(tr("Wi-Fi security")); //Wi-Fi 安全性: ui->lbPassword->setText(tr("Password")); //密码: ui->btnCancel->setText(tr("Cancel")); //取消 ui->btnOk->setText(tr("Ok")); //确定 ui->btnOk->setEnabled(false); ui->cbxSecurity->addItem(tr("None")); //无 ui->cbxSecurity->addItem(tr("WPA & WPA2 Personal")); //WPA 及 WPA2 个人 ui->cbxSecurity->setCurrentIndex(1); connect(ui->cbxSecurity,SIGNAL(currentIndexChanged(QString)),this,SLOT(changeDialog())); } DlgHotspotCreate::~DlgHotspotCreate() { delete ui; } void DlgHotspotCreate::mousePressEvent(QMouseEvent *event){ if(event->button() == Qt::LeftButton){ this->isPress = true; this->winPos = this->pos(); this->dragPos = event->globalPos(); event->accept(); } } void DlgHotspotCreate::mouseReleaseEvent(QMouseEvent *event){ this->isPress = false; this->setWindowOpacity(1); } void DlgHotspotCreate::mouseMoveEvent(QMouseEvent *event){ if(this->isPress){ this->move(this->winPos - (this->dragPos - event->globalPos())); this->setWindowOpacity(0.9); event->accept(); } } void DlgHotspotCreate::on_btnCancel_clicked() { this->close(); emit btnHotspotState(); } void DlgHotspotCreate::on_btnOk_clicked() { //nmcli device wifi hotspot [ifname ifname] [con-name name] [ssid SSID] [band {a | bg}] [channel channel] [password password] //example: nmcli device wifi hotspot ifname wlan0 con-name MyHostspot ssid MyHostspotSSID password 12345678 QString str; if(ui->cbxSecurity->currentIndex() == 0 ){ str = "nmcli device wifi hotspot ifname " + wirelessCardName + " con-name " + ui->leNetName->text() + " ssid " + ui->leNetName->text() + "SSID"; }else{ str = "nmcli device wifi hotspot ifname " + wirelessCardName + " con-name " + ui->leNetName->text() + " ssid " + ui->leNetName->text() + " password " + ui->lePassword->text(); } Utils::m_system(str.toUtf8().data()); // int status = system(str.toUtf8().data()); // if (status != 0){ syslog(LOG_ERR, "execute 'nmcli device wifi hotspot' in function 'on_btnOk_clicked' failed");} this->close(); emit updateHotspotList(); } void DlgHotspotCreate::on_checkBoxPwd_stateChanged(int arg1) { if (arg1 == 0) { ui->lePassword ->setEchoMode(QLineEdit::Password); } else { ui->lePassword->setEchoMode(QLineEdit::Normal); } } void DlgHotspotCreate::on_leNetName_textEdited(const QString &arg1) { if(ui->cbxSecurity->currentIndex() == 0 ){ if (ui->leNetName->text() == ""){ ui->btnOk->setEnabled(false); } else { ui->btnOk->setEnabled(true); } }else{ if (ui->leNetName->text() == "" || ui->lePassword->text().size() < 5){ ui->btnOk->setEnabled(false); } else { ui->btnOk->setEnabled(true); } } } void DlgHotspotCreate::on_lePassword_textEdited(const QString &arg1) { if (ui->leNetName->text() == "" || ui->lePassword->text().size() < 5){ ui->btnOk->setEnabled(false); } else { ui->btnOk->setEnabled(true); } } void DlgHotspotCreate::changeDialog() { if(ui->cbxSecurity->currentIndex()==0){ ui->lbPassword->setEnabled(false); ui->lePassword->setEnabled(false); ui->checkBoxPwd->setEnabled(false); } else { ui->lbPassword->setEnabled(true); ui->lePassword->setEnabled(true); ui->checkBoxPwd->setEnabled(true); } } ukui-screensaver/KylinNM/hot-spot/dlghotspotcreate.ui0000644000175000017500000000654614205074704022017 0ustar fengfeng DlgHotspotCreate 0 0 432 250 Dialog 0 0 120 32 9 9 16 16 34 6 80 20 215 210 90 30 315 210 90 30 76 60 90 20 175 55 200 32 76 105 90 20 175 100 200 32 76 150 90 20 175 145 200 32 QLineEdit::Password 350 157 18 9 ukui-screensaver/KylinNM/hot-spot/dlghotspotcreate.h0000644000175000017500000000326614205074704021625 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include namespace Ui { class DlgHotspotCreate; } class DlgHotspotCreate : public QDialog { Q_OBJECT public: explicit DlgHotspotCreate(QString wiFiCardName, QWidget *parent = nullptr); ~DlgHotspotCreate(); public slots: void changeDialog(); private slots: void on_btnCancel_clicked(); void on_btnOk_clicked(); void on_checkBoxPwd_stateChanged(int arg1); void on_leNetName_textEdited(const QString &arg1); void on_lePassword_textEdited(const QString &arg1); private: Ui::DlgHotspotCreate *ui; QString wirelessCardName; void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); bool isPress; QPoint winPos; QPoint dragPos; signals: void updateHotspotList(); void btnHotspotState(); }; #endif // DLGHOTSPOTCREATE_H ukui-screensaver/KylinNM/wireless-security/0000755000175000017500000000000014205074704020017 5ustar fengfengukui-screensaver/KylinNM/wireless-security/dlgconnhidwifisectls.ui0000644000175000017500000003102514205074704024565 0ustar fengfeng DlgConnHidWifiSecTls 0 0 432 705 Connect to Hidden Wi-Fi Network 180 185 200 32 10 180 145 200 32 10 180 505 200 32 10 QLineEdit::Password 180 385 200 32 10 QLineEdit::Password 357 397 18 9 10 76 80 90 20 10 76 150 90 20 10 76 310 90 20 10 76 350 90 20 10 180 465 200 32 10 76 270 90 20 10 76 510 90 20 10 215 660 90 30 10 76 590 90 20 10 180 345 200 32 10 76 550 90 20 10 76 390 90 20 10 180 305 200 32 10 357 597 18 9 10 180 265 200 32 10 180 585 200 32 10 QLineEdit::Password 76 470 90 20 10 76 230 90 20 10 180 225 200 32 10 315 660 90 30 10 180 425 200 25 10 180 75 200 32 10 180 545 200 32 10 76 190 90 20 10 0 0 432 705 30 30 140 22 10 125 412 1 Qt::Horizontal 10 640 412 1 Qt::Horizontal lbBoder cbxSecurity leNetName leUserCertifyPwd leCaPwd checkBoxPwd lbConn lbNetName lbDomain lbCA cbxUserCertify lbIdentity lbUserCertifyPwd btnCancel lbUserKeyPwd cbxCA lbUserPriKey lbCaPwd leDomain leIdentity leUserKeyPwd lbUserCertify lbAuth cbxAuth btnConnect checkBoxCA cbxConn cbxUserPriKey lbSecurity lbLeftupTitle checkBoxPwdSec lineUp lineDown ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifisectunneltls.h0000644000175000017500000000430514205074704025626 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include namespace Ui { class DlgConnHidWifiSecTunnelTLS; } class DlgConnHidWifiSecTunnelTLS : public QDialog { Q_OBJECT public: explicit DlgConnHidWifiSecTunnelTLS(int type, QWidget *parent = 0); ~DlgConnHidWifiSecTunnelTLS(); protected: void paintEvent(QPaintEvent *event); public slots: void changeDialogSecu(); void changeDialogAuth(); private slots: void on_btnCancel_clicked(); void on_btnConnect_clicked(); void on_cbxCA_currentIndexChanged(const QString &arg1); void on_checkBoxPwd_stateChanged(int arg1); void on_checkBoxCA_stateChanged(int arg1); void on_checkBoxPwdSec_stateChanged(int arg1); void on_leNetName_textEdited(const QString &arg1); void on_leAnonyId_textEdited(const QString &arg1); void on_leDomain_textEdited(const QString &arg1); void on_leCaPwd_textEdited(const QString &arg1); void on_leUserName_textEdited(const QString &arg1); void on_lePwd_textEdited(const QString &arg1); private: Ui::DlgConnHidWifiSecTunnelTLS *ui; int WepOrWpa = 0;//0 WEP;1WPA void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); // QString labelQss, cbxQss, leQss, btnConnQss, btnCancelQss, lineQss, checkBoxQss, checkBoxCAQss; bool isPress; QPoint winPos; QPoint dragPos; }; #endif // DLGCONNHIDWIFISECTUNNELTLS_H ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifisecpeap.ui0000644000175000017500000003061514205074704024714 0ustar fengfeng DlgConnHidWifiSecPeap 0 0 432 700 Connect to Hidden Wi-Fi Network 180 141 200 32 10 180 341 200 32 10 76 76 90 20 10 180 301 200 32 10 180 71 200 32 10 180 381 200 32 10 QLineEdit::Password 315 650 90 30 10 180 181 200 32 10 180 261 200 32 10 183 421 200 25 10 76 146 90 20 10 215 650 90 30 10 76 306 90 20 10 76 386 90 20 10 357 593 18 9 10 357 393 18 9 10 76 186 90 20 10 180 461 200 32 10 76 226 90 20 10 76 466 90 20 10 180 221 200 32 10 76 346 90 20 10 76 266 90 20 10 76 586 90 20 10 180 541 200 32 10 180 501 200 32 10 180 581 200 32 10 QLineEdit::Password 76 506 90 20 10 76 546 90 20 10 0 0 432 700 30 28 140 22 10 121 412 1 Qt::Horizontal 10 631 412 1 Qt::Horizontal lbBoder leNetName cbxCA lbConn leDomain cbxConn leCaPwd btnConnect cbxSecurity leAnonyId checkBoxCA lbNetName btnCancel lbDomain lbCaPwd checkBoxPwd lbSecurity cbxPEAPver lbAuth lbPEAPver cbxAuth lbCA lbAnonyId lbPassword leUserName cbxInnerAuth lePassword lbInnerAuth lbUserName checkBoxPwdSec lbLeftupTitle lineUp lineDown ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifi.ui0000644000175000017500000001156614205074704023357 0ustar fengfeng DlgConnHidWifi 0 0 432 358 Connect to Hidden Wi-Fi Network 76 80 90 20 10 Qt::LeftToRight 175 75 182 32 10 76 221 90 20 10 175 170 182 32 10 76 176 90 20 10 175 215 182 32 10 315 310 90 30 10 215 310 90 30 10 30 30 240 22 9 0 0 432 358 10 140 412 1 Qt::Horizontal 10 280 412 1 Qt::Horizontal lbBoder lbConn cbxConn lbNetName cbxSecurity lbSecurity leNetName btnConnect btnCancel lbLeftupTitle lineUp lineDown ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifi.h0000644000175000017500000000423614205074704023165 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include class KylinNM; namespace Ui { class DlgConnHidWifi; } class DlgConnHidWifi : public QDialog { Q_OBJECT public: explicit DlgConnHidWifi(int type, KylinNM *mw = 0, QWidget *parent = 0); ~DlgConnHidWifi(); protected: void paintEvent(QPaintEvent *event); /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---START---- ** 手动绑定下拉框视图和下拉框 过滤点击事件 **/ bool eventFilter(QObject *obj, QEvent *ev) override; public slots: void changeDialog(); void changeWindow(); void emitSignal(); void on_execSecConn(); void slotStartLoading(); private slots: void on_btnCancel_clicked(); void on_btnConnect_clicked(); void on_leNetName_textEdited(const QString &arg1); signals: void reSetWifiList(); void sendMessage(); void execSecConn(); void stopSignal(); private: Ui::DlgConnHidWifi *ui; int isUsed;//=0 current wifi not used before; >=1 used KylinNM *mw; QString strWifiname; // QString labelQss, cbxQss, leQss, btnConnQss, btnCancelQss, lineQss; void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); bool isPress; QPoint winPos; QPoint dragPos; }; #endif // DLGCONNHIDWIFI_H ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifileap.cpp0000644000175000017500000002562414205074704024366 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see DlgConnHidWifiLeap::DlgConnHidWifiLeap(QWidget *parent) : QDialog(parent), ui(new Ui::DlgConnHidWifiLeap) { ui->setupUi(this); this->setWindowFlags(Qt::FramelessWindowHint); this->setAttribute(Qt::WA_TranslucentBackground); //需要添加 void paintEvent(QPaintEvent *event) 函数 QPainterPath path; auto rect = this->rect(); rect.adjust(1, 1, -1, -1); path.addRoundedRect(rect, 6, 6); setProperty("blurRegion", QRegion(path.toFillPolygon().toPolygon())); this->setStyleSheet("QWidget{border-radius:6px;background-color:rgba(19,19,20,0.7);border:1px solid rgba(255, 255, 255, 0.05);}"); MyQss objQss; ui->lbBoder->setStyleSheet("QLabel{border-radius:6px;background-color:rgba(19,19,20,0.95);border:1px solid rgba(255, 255, 255, 0.05);}"); ui->lbBoder->hide(); ui->lbLeftupTitle->setStyleSheet("QLabel{border:0px;font-size:20px;color:rgba(255,255,255,0.97);background-color:transparent;}"); ui->lbConn->setStyleSheet(objQss.labelQss); ui->lbNetName->setStyleSheet(objQss.labelQss); ui->lbSecurity->setStyleSheet(objQss.labelQss); ui->lbUserName->setStyleSheet(objQss.labelQss); ui->lbPassword->setStyleSheet(objQss.labelQss); ui->cbxConn->setStyleSheet(objQss.cbxQss); ui->cbxConn->setView(new QListView()); ui->leNetName->setStyleSheet(objQss.leQss); ui->leUserName->setStyleSheet(objQss.leQss); ui->lePassword->setStyleSheet(objQss.leQss); ui->cbxSecurity->setStyleSheet(objQss.cbxQss); ui->cbxSecurity->setView(new QListView()); ui->checkBoxPwd->setStyleSheet(objQss.checkBoxQss); ui->btnCancel->setStyleSheet(objQss.btnCancelQss); ui->btnConnect->setStyleSheet(objQss.btnConnQss); ui->lineUp->setStyleSheet(objQss.lineQss); ui->lineDown->setStyleSheet(objQss.lineQss); ui->lbLeftupTitle->setText(tr("Add hidden Wi-Fi")); //加入隐藏Wi-Fi ui->lbConn->setText(tr("Connection")); //连接设置: ui->lbNetName->setText(tr("Network name")); //网络名称: ui->lbSecurity->setText(tr("Wi-Fi security")); //Wi-Fi安全性: ui->lbUserName->setText(tr("Username")); //用户名: ui->lbPassword->setText(tr("Password")); //密码: ui->btnCancel->setText(tr("Cancel")); //取消 ui->btnConnect->setText(tr("Connect")); //连接 ui->cbxConn->addItem(tr("C_reate…")); //新建... int status = system("nmcli connection show>/tmp/kylin-nm-connshow"); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection show' in function 'DlgConnHidWifiLeap' failed");} QFile file("/tmp/kylin-nm-connshow"); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){ qDebug()<<"Can't open the file!"; } QString txt = file.readAll(); QStringList txtLine = txt.split("\n"); file.close(); foreach (QString line, txtLine) { if(line.indexOf("wifi") != -1){ QStringList subLine = line.split(" "); ui->cbxConn->addItem(subLine[0]); } } ui->cbxConn->setCurrentIndex(0); ui->cbxSecurity->addItem(tr("None")); //无 ui->cbxSecurity->addItem(tr("WPA & WPA2 Personal")); //WPA 及 WPA2 个人 ui->cbxSecurity->addItem(tr("WEP 40/128-bit Key (Hex or ASCII)")); //WEP 40/128 位密钥(十六进制或ASCII) ui->cbxSecurity->addItem(tr("WEP 128-bit Passphrase")); //WEP 128 位密码句 ui->cbxSecurity->addItem("LEAP"); ui->cbxSecurity->addItem(tr("Dynamic WEP (802.1X)")); //动态 WEP (802.1x) ui->cbxSecurity->addItem(tr("WPA & WPA2 Enterprise")); //WPA 及 WPA2 企业 ui->cbxSecurity->setCurrentIndex(4); connect(ui->cbxSecurity,SIGNAL(currentIndexChanged(QString)),this,SLOT(changeDialog())); ui->btnConnect->setEnabled(false); this->setFixedSize(432,434); /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---START---- ** 手动绑定下拉框视图和下拉框 **/ ui->cbxConn->view()->setWindowFlags(Qt::Popup | Qt::X11BypassWindowManagerHint); ui->cbxConn->view()->setParent(this); ui->cbxConn->view()->hide(); ui->cbxConn->installEventFilter(this); ui->cbxSecurity->view()->setWindowFlags(Qt::Popup | Qt::X11BypassWindowManagerHint); ui->cbxSecurity->view()->setParent(this); ui->cbxSecurity->view()->hide(); ui->cbxSecurity->installEventFilter(this); connect(ui->cbxConn->view(), &QAbstractItemView::pressed, this, [=](QModelIndex index){ Q_EMIT ui->cbxConn->setCurrentIndex(index.row()); ui->cbxConn->view()->hide(); }); connect(ui->cbxSecurity->view(), &QAbstractItemView::pressed, this, [=](QModelIndex index){ ui->cbxSecurity->view()->hide(); Q_EMIT ui->cbxSecurity->setCurrentIndex(index.row()); }); ui->cbxConn->view()->setGeometry(QRect(ui->cbxConn->geometry().left(), ui->cbxConn->geometry().bottom(), ui->cbxConn->view()->width(), ui->cbxConn->view()->height())); ui->cbxSecurity->view()->setGeometry(QRect(ui->cbxSecurity->geometry().left(), ui->cbxSecurity->geometry().bottom(), ui->cbxSecurity->view()->width(), ui->cbxSecurity->view()->height())); /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---END---- ** 手动绑定下拉框视图和下拉框 **/ } DlgConnHidWifiLeap::~DlgConnHidWifiLeap() { delete ui; } /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---START---- ** 手动绑定下拉框视图和下拉框 **/ bool DlgConnHidWifiLeap::eventFilter(QObject *obj, QEvent *ev) { if(ev->type() == QEvent::MouseButtonPress) { if(obj == ui->cbxConn) { ui->cbxConn->view()->setVisible(!ui->cbxConn->view()->isVisible()); if(ui->cbxConn->view()->isVisible()) ui->cbxConn->view()->setFocus(); } else if (obj == ui->cbxSecurity) { ui->cbxSecurity->view()->setVisible(!ui->cbxSecurity->view()->isVisible()); if(ui->cbxSecurity->view()->isVisible()) ui->cbxSecurity->view()->setFocus(); } } return false; } /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---END---- ** 手动绑定下拉框视图和下拉框 **/ void DlgConnHidWifiLeap::mousePressEvent(QMouseEvent *event){ if(event->button() == Qt::LeftButton){ this->isPress = true; this->winPos = this->pos(); this->dragPos = event->globalPos(); event->accept(); } } void DlgConnHidWifiLeap::mouseReleaseEvent(QMouseEvent *event){ this->isPress = false; } void DlgConnHidWifiLeap::mouseMoveEvent(QMouseEvent *event){ if(this->isPress){ this->move(this->winPos - (this->dragPos - event->globalPos())); event->accept(); } } //切换到其他Wi-Fi安全类型 void DlgConnHidWifiLeap::changeDialog() { if(ui->cbxSecurity->currentIndex()==0){ // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifi *connHidWifi = new DlgConnHidWifi(0, 0,this->parentWidget()); connHidWifi->show(); } else if(ui->cbxSecurity->currentIndex()==1) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWpa *connHidWifiWpa = new DlgConnHidWifiWpa(0, 0, this->parentWidget()); connHidWifiWpa->show(); } else if(ui->cbxSecurity->currentIndex()==2) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWep *connHidWifiWep = new DlgConnHidWifiWep(0, this->parentWidget()); connHidWifiWep->show(); } else if(ui->cbxSecurity->currentIndex()==3) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWep *connHidWifiWep = new DlgConnHidWifiWep(1, this->parentWidget()); connHidWifiWep->show(); } else if(ui->cbxSecurity->currentIndex()==4) { qDebug()<<"it's not need to change dialog"; } else if(ui->cbxSecurity->currentIndex()==5) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecTls *connHidWifiSecTls = new DlgConnHidWifiSecTls(0, this->parentWidget()); connHidWifiSecTls->show(); } else { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecTls *connHidWifiSecTls = new DlgConnHidWifiSecTls(1, this->parentWidget()); connHidWifiSecTls->show(); } } void DlgConnHidWifiLeap::on_btnCancel_clicked() { this->close(); } void DlgConnHidWifiLeap::on_btnConnect_clicked() { this->close(); } void DlgConnHidWifiLeap::on_checkBoxPwd_stateChanged(int arg1) { if (arg1 == 0) { ui->lePassword ->setEchoMode(QLineEdit::Password); } else { ui->lePassword->setEchoMode(QLineEdit::Normal); } } void DlgConnHidWifiLeap::on_leNetName_textEdited(const QString &arg1) { if (ui->leNetName->text() == "" || ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leNetName->text() == "" || ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->lePassword->text() == "" || ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); } else { ui->btnConnect->setEnabled(true); } } void DlgConnHidWifiLeap::on_leUserName_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); } else { ui->btnConnect->setEnabled(true); } } void DlgConnHidWifiLeap::on_lePassword_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); } else { ui->btnConnect->setEnabled(true); } } void DlgConnHidWifiLeap::paintEvent(QPaintEvent *event) { QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); QWidget::paintEvent(event); } ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifisecleap.cpp0000644000175000017500000003176114205074704025060 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see DlgConnHidWifiSecLeap::DlgConnHidWifiSecLeap(int type, QWidget *parent) : WepOrWpa(type), QDialog(parent), ui(new Ui::DlgConnHidWifiSecLeap) { ui->setupUi(this); this->setWindowFlags(Qt::FramelessWindowHint); this->setAttribute(Qt::WA_TranslucentBackground); //需要添加 void paintEvent(QPaintEvent *event) 函数 QPainterPath path; auto rect = this->rect(); rect.adjust(1, 1, -1, -1); path.addRoundedRect(rect, 6, 6); setProperty("blurRegion", QRegion(path.toFillPolygon().toPolygon())); this->setStyleSheet("QWidget{border-radius:6px;background-color:rgba(19,19,20,0.7);border:1px solid rgba(255, 255, 255, 0.05);}"); MyQss objQss; ui->lbBoder->setStyleSheet("QLabel{border-radius:6px;background-color:rgba(19,19,20,0.95);border:1px solid rgba(255, 255, 255, 0.05);}"); ui->lbBoder->hide(); ui->lbLeftupTitle->setStyleSheet("QLabel{border:0px;font-size:20px;color:rgba(255,255,255,0.97);background-color:transparent;}"); ui->lbConn->setStyleSheet(objQss.labelQss); ui->lbNetName->setStyleSheet(objQss.labelQss); ui->lbSecurity->setStyleSheet(objQss.labelQss); ui->lbAuth->setStyleSheet(objQss.labelQss); ui->lbUserName->setStyleSheet(objQss.labelQss); ui->lbPassword->setStyleSheet(objQss.labelQss); ui->cbxConn->setStyleSheet(objQss.cbxQss); ui->cbxConn->setView(new QListView()); ui->leNetName->setStyleSheet(objQss.leQss); ui->cbxSecurity->setStyleSheet(objQss.cbxQss); ui->cbxSecurity->setView(new QListView()); ui->cbxAuth->setStyleSheet(objQss.cbxQss); ui->cbxAuth->setView(new QListView()); ui->leUserName->setStyleSheet(objQss.leQss); ui->lePassword->setStyleSheet(objQss.leQss); ui->checkBox->setStyleSheet(objQss.checkBoxQss); ui->btnCancel->setStyleSheet(objQss.btnCancelQss); ui->btnConnect->setStyleSheet(objQss.btnConnQss); ui->lineUp->setStyleSheet(objQss.lineQss); ui->lineDown->setStyleSheet(objQss.lineQss); ui->lbLeftupTitle->setText(tr("Add hidden Wi-Fi")); //加入隐藏Wi-Fi ui->lbConn->setText(tr("Connection")); //连接设置: ui->lbNetName->setText(tr("Network name")); //网络名称: ui->lbSecurity->setText(tr("Wi-Fi security")); //Wi-Fi安全性: ui->lbAuth->setText(tr("Authentication")); //认证: ui->lbUserName->setText(tr("Username")); //用户名: ui->lbPassword->setText(tr("Password")); //密码: ui->btnCancel->setText(tr("Cancel")); //取消 ui->btnConnect->setText(tr("Connect")); //连接 ui->cbxConn->addItem(tr("C_reate…")); //新建... int status = system("nmcli connection show>/tmp/kylin-nm-connshow"); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection show' in function 'DlgConnHidWifiSecLeap' failed");} QFile file("/tmp/kylin-nm-connshow"); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){ qDebug()<<"Can't open the file!"; } QString txt = file.readAll(); QStringList txtLine = txt.split("\n"); file.close(); foreach (QString line, txtLine) { if(line.indexOf("wifi") != -1){ QStringList subLine = line.split(" "); ui->cbxConn->addItem(subLine[0]); } } ui->cbxConn->setCurrentIndex(0); ui->cbxSecurity->addItem(tr("None")); //无 ui->cbxSecurity->addItem(tr("WPA & WPA2 Personal")); //WPA 及 WPA2 个人 ui->cbxSecurity->addItem(tr("WEP 40/128-bit Key (Hex or ASCII)")); //WEP 40/128 位密钥(十六进制或ASCII) ui->cbxSecurity->addItem(tr("WEP 128-bit Passphrase")); //WEP 128 位密码句 ui->cbxSecurity->addItem("LEAP"); ui->cbxSecurity->addItem(tr("Dynamic WEP (802.1X)")); //动态 WEP (802.1x) ui->cbxSecurity->addItem(tr("WPA & WPA2 Enterprise")); //WPA 及 WPA2 企业 if (WepOrWpa == 0) { ui->cbxSecurity->setCurrentIndex(5); } else if (WepOrWpa == 1) { ui->cbxSecurity->setCurrentIndex(6); } connect(ui->cbxSecurity,SIGNAL(currentIndexChanged(QString)),this,SLOT(changeDialogSecu())); ui->cbxAuth->addItem("TLS"); ui->cbxAuth->addItem("LEAP"); ui->cbxAuth->addItem("PWD"); ui->cbxAuth->addItem("FAST"); ui->cbxAuth->addItem(tr("Tunneled TLS"));//隧道 TLS ui->cbxAuth->addItem(tr("Protected EAP (PEAP)")); //受保护的 EAP ui->cbxAuth->setCurrentIndex(1); connect(ui->cbxAuth,SIGNAL(currentIndexChanged(QString)),this,SLOT(changeDialogAuth())); ui->btnConnect->setEnabled(false); this->setFixedSize(432,487); /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---START---- ** 手动绑定下拉框视图和下拉框 **/ ui->cbxConn->view()->setWindowFlags(Qt::Popup | Qt::X11BypassWindowManagerHint); ui->cbxConn->view()->setParent(this); ui->cbxConn->view()->hide(); ui->cbxConn->installEventFilter(this); ui->cbxSecurity->view()->setWindowFlags(Qt::Popup | Qt::X11BypassWindowManagerHint); ui->cbxSecurity->view()->setParent(this); ui->cbxSecurity->view()->hide(); ui->cbxSecurity->installEventFilter(this); connect(ui->cbxConn->view(), &QAbstractItemView::pressed, this, [=](QModelIndex index){ Q_EMIT ui->cbxConn->setCurrentIndex(index.row()); ui->cbxConn->view()->hide(); }); connect(ui->cbxSecurity->view(), &QAbstractItemView::pressed, this, [=](QModelIndex index){ ui->cbxSecurity->view()->hide(); Q_EMIT ui->cbxSecurity->setCurrentIndex(index.row()); }); ui->cbxConn->view()->setGeometry(QRect(ui->cbxConn->geometry().left(), ui->cbxConn->geometry().bottom(), ui->cbxConn->view()->width(), ui->cbxConn->view()->height())); ui->cbxSecurity->view()->setGeometry(QRect(ui->cbxSecurity->geometry().left(), ui->cbxSecurity->geometry().bottom(), ui->cbxSecurity->view()->width(), ui->cbxSecurity->view()->height())); /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---END---- ** 手动绑定下拉框视图和下拉框 **/ } DlgConnHidWifiSecLeap::~DlgConnHidWifiSecLeap() { delete ui; } /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---START---- ** 手动绑定下拉框视图和下拉框 **/ bool DlgConnHidWifiSecLeap::eventFilter(QObject *obj, QEvent *ev) { if(ev->type() == QEvent::MouseButtonPress) { if(obj == ui->cbxConn) { ui->cbxConn->view()->setVisible(!ui->cbxConn->view()->isVisible()); if(ui->cbxConn->view()->isVisible()) ui->cbxConn->view()->setFocus(); } else if (obj == ui->cbxSecurity) { ui->cbxSecurity->view()->setVisible(!ui->cbxSecurity->view()->isVisible()); if(ui->cbxSecurity->view()->isVisible()) ui->cbxSecurity->view()->setFocus(); } } return false; } /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---END---- ** 手动绑定下拉框视图和下拉框 **/ void DlgConnHidWifiSecLeap::mousePressEvent(QMouseEvent *event){ if(event->button() == Qt::LeftButton){ this->isPress = true; this->winPos = this->pos(); this->dragPos = event->globalPos(); event->accept(); } } void DlgConnHidWifiSecLeap::mouseReleaseEvent(QMouseEvent *event){ this->isPress = false; } void DlgConnHidWifiSecLeap::mouseMoveEvent(QMouseEvent *event){ if(this->isPress){ this->move(this->winPos - (this->dragPos - event->globalPos())); event->accept(); } } void DlgConnHidWifiSecLeap::changeDialogSecu() { if(ui->cbxSecurity->currentIndex()==0){ // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifi *connHidWifi = new DlgConnHidWifi(0, 0, this->parentWidget()); connHidWifi->show(); } else if(ui->cbxSecurity->currentIndex()==1) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWpa *connHidWifiWpa = new DlgConnHidWifiWpa(0, 0, this->parentWidget()); connHidWifiWpa->show(); } else if(ui->cbxSecurity->currentIndex()==2) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWep *connHidWifiWep = new DlgConnHidWifiWep(0, this->parentWidget()); connHidWifiWep->show(); } else if(ui->cbxSecurity->currentIndex()==3) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWep *connHidWifiWep = new DlgConnHidWifiWep(1, this->parentWidget()); connHidWifiWep->show(); } else if(ui->cbxSecurity->currentIndex()==4) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiLeap *connHidWifiLeap = new DlgConnHidWifiLeap(this->parentWidget()); connHidWifiLeap->show(); } else if(ui->cbxSecurity->currentIndex()==5) { if (WepOrWpa == 1) { ui->cbxSecurity->setCurrentIndex(5); WepOrWpa = 0; } } else { if (WepOrWpa == 0){ ui->cbxSecurity->setCurrentIndex(6); WepOrWpa = 1; } } } void DlgConnHidWifiSecLeap::changeDialogAuth() { if(ui->cbxAuth->currentIndex()==0){ // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecTls *connHidWifiSecTls = new DlgConnHidWifiSecTls(WepOrWpa, this->parentWidget()); connHidWifiSecTls->show(); } else if(ui->cbxAuth->currentIndex()==1) { qDebug()<<"it's not need to change dialog"; } else if(ui->cbxAuth->currentIndex()==2) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecPwd *connHidWifiSecPwd = new DlgConnHidWifiSecPwd(WepOrWpa, this->parentWidget()); connHidWifiSecPwd->show(); } else if(ui->cbxAuth->currentIndex()==3) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecFast *connHidWifiSecFast = new DlgConnHidWifiSecFast(WepOrWpa, this->parentWidget()); connHidWifiSecFast->show(); } else if(ui->cbxAuth->currentIndex()==4) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecTunnelTLS *connHidWifiSecTuTls = new DlgConnHidWifiSecTunnelTLS(WepOrWpa, this->parentWidget()); connHidWifiSecTuTls->show(); } else { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecPeap *connHidWifiSecPeap = new DlgConnHidWifiSecPeap(WepOrWpa, this->parentWidget()); connHidWifiSecPeap->show(); } } void DlgConnHidWifiSecLeap::on_btnCancel_clicked() { this->close(); } void DlgConnHidWifiSecLeap::on_btnConnect_clicked() { this->close(); } void DlgConnHidWifiSecLeap::on_checkBox_stateChanged(int arg1) { if (arg1 == 0) { ui->lePassword ->setEchoMode(QLineEdit::Password); } else { ui->lePassword->setEchoMode(QLineEdit::Normal); } } void DlgConnHidWifiSecLeap::on_leNetName_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); } else { ui->btnConnect->setEnabled(true); } } void DlgConnHidWifiSecLeap::on_leUserName_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); } else { ui->btnConnect->setEnabled(true); } } void DlgConnHidWifiSecLeap::on_lePassword_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); } else { ui->btnConnect->setEnabled(true); } } void DlgConnHidWifiSecLeap::paintEvent(QPaintEvent *event) { QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); QWidget::paintEvent(event); } ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifisecpwd.h0000644000175000017500000000352114205074704024367 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include namespace Ui { class DlgConnHidWifiSecPwd; } class DlgConnHidWifiSecPwd : public QDialog { Q_OBJECT public: explicit DlgConnHidWifiSecPwd(int type, QWidget *parent = 0); ~DlgConnHidWifiSecPwd(); protected: void paintEvent(QPaintEvent *event); public slots: void changeDialogSecu(); void changeDialogAuth(); private slots: void on_btnCancel_clicked(); void on_btnConnect_clicked(); void on_checkBox_stateChanged(int arg1); void on_leNetName_textEdited(const QString &arg1); void on_leUserName_textEdited(const QString &arg1); void on_lePassword_textEdited(const QString &arg1); private: Ui::DlgConnHidWifiSecPwd *ui; int WepOrWpa = 0;//0 WEP;1WPA void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); // QString labelQss, cbxQss, leQss, btnConnQss, btnCancelQss, lineQss, checkBoxQss, checkBoxCAQss; bool isPress; QPoint winPos; QPoint dragPos; }; #endif // DLGCONNHIDWIFISECPWD_H ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifisecfast.ui0000644000175000017500000002434014205074704024722 0ustar fengfeng DlgConnHidWifiSecFast 0 0 432 673 Connect to Hidden Wi-Fi Network 332 542 18 9 11 76 176 90 20 10 180 170 182 30 10 76 80 90 20 10 180 260 182 30 10 180 530 182 32 10 QLineEdit::Password 180 485 182 30 10 76 491 90 20 10 180 215 182 30 10 76 536 90 20 10 315 620 90 30 10 180 75 182 32 10 76 266 90 20 10 76 221 90 20 10 215 620 90 30 10 76 311 90 20 10 180 305 182 32 10 76 356 100 25 10 180 350 182 32 10 76 401 90 20 10 180 395 182 32 10 76 446 90 20 10 180 440 182 32 10 30 30 140 22 9 0 0 432 673 10 140 412 1 Qt::Horizontal 10 590 412 1 Qt::Horizontal lbBoder lbNetName leNetName lbConn cbxAuth lePassword leUserName lbUserName cbxSecurity lbPassword btnConnect cbxConn lbAuth lbSecurity btnCancel lbAnonyId leAnonyId checkBoxAutoPCA cbxAutoPCA lbPCAfile lePCAfile lbInnerAuth cbxInnerAuth checkBoxPwd lbLeftupTitle lineUp lineDown ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifileap.h0000644000175000017500000000372614205074704024032 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include namespace Ui { class DlgConnHidWifiLeap; } class DlgConnHidWifiLeap : public QDialog { Q_OBJECT public: explicit DlgConnHidWifiLeap(QWidget *parent = 0); ~DlgConnHidWifiLeap(); protected: void paintEvent(QPaintEvent *event); /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---START---- ** 手动绑定下拉框视图和下拉框 过滤点击事件 **/ bool eventFilter(QObject *obj, QEvent *ev) override; public slots: void changeDialog(); private slots: void on_btnCancel_clicked(); void on_btnConnect_clicked(); void on_checkBoxPwd_stateChanged(int arg1); void on_leNetName_textEdited(const QString &arg1); void on_leUserName_textEdited(const QString &arg1); void on_lePassword_textEdited(const QString &arg1); private: Ui::DlgConnHidWifiLeap *ui; void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); // QString labelQss, cbxQss, leQss, btnConnQss, btnCancelQss, lineQss, checkBoxQss; bool isPress; QPoint winPos; QPoint dragPos; }; #endif // DLGCONNHIDWIFILEAP_H ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifiwpa.ui0000644000175000017500000001345614205074704024067 0ustar fengfeng DlgConnHidWifiWpa 0 0 432 397 Connect to Hidden Wi-Fi Network 76 221 90 20 10 76 176 90 20 10 215 350 90 30 10 175 75 182 32 10 332 272 18 9 10 76 266 90 20 10 175 170 182 32 10 175 261 182 32 10 QLineEdit::Password 315 350 90 30 10 76 80 90 20 10 Qt::LeftToRight 175 215 182 32 10 0 0 432 397 30 30 240 22 10 140 412 1 Qt::Horizontal 10 320 412 1 Qt::Horizontal lbBoder lePassword lbNetName lbSecurity btnCancel cbxConn checkBoxPwd lbPassword cbxSecurity btnConnect lbConn leNetName lbLeftupTitle lineUp lineDown ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifiwep.ui0000644000175000017500000001647014205074704024072 0ustar fengfeng DlgConnHidWifiWep 0 0 432 493 Connect to Hidden Wi-Fi Network 76 266 90 20 10 76 311 90 20 10 76 356 90 20 10 175 215 182 32 10 315 440 90 30 10 175 350 182 32 10 76 80 90 20 10 Qt::LeftToRight 175 305 182 32 10 215 440 90 30 10 332 272 18 9 10 76 176 90 20 10 175 260 182 32 10 QLineEdit::Password 175 170 182 32 10 76 221 90 20 10 175 75 182 32 10 0 0 432 493 30 30 140 22 10 140 412 1 Qt::Horizontal 10 410 412 1 Qt::Horizontal lbBoder leKey lbKey lbWEPindex lbAuth cbxSecurity btnConnect cbxAuth lbConn cbxWEPindex btnCancel checkBoxPwd lbNetName leNetName lbSecurity cbxConn lbLeftupTitle lineUp lineDown ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifisecpwd.ui0000644000175000017500000001625414205074704024564 0ustar fengfeng DlgConnHidWifiSecPwd 0 0 432 487 Connect to Hidden Wi-Fi Network 333 363 18 9 10 215 440 90 30 10 0 0 432 487 30 30 140 22 175 170 182 32 10 76 266 90 20 10 76 311 90 20 10 76 80 90 20 10 175 75 182 32 10 315 440 90 30 10 175 215 182 32 10 175 305 182 32 10 175 350 182 32 10 QLineEdit::Password 76 176 90 20 10 76 221 90 20 10 76 356 90 20 10 175 260 182 32 10 10 140 412 1 Qt::Horizontal 10 410 412 1 Qt::Horizontal lbBoder btnCancel leNetName lbAuth lbUserName lbConn cbxConn btnConnect cbxSecurity leUserName lePassword lbNetName lbSecurity lbPassword cbxAuth lbLeftupTitle lineUp lineDown checkBox ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifisectunneltls.ui0000644000175000017500000002732414205074704026022 0ustar fengfeng DlgConnHidWifiSecTunnelTLS 0 0 432 665 Connect to Hidden Wi-Fi Network 180 75 200 32 10 180 385 200 32 10 QLineEdit::Password 180 145 200 32 10 315 620 90 30 10 180 545 200 32 10 QLineEdit::Password 215 620 90 30 10 76 310 90 20 10 357 557 18 9 10 76 510 90 20 10 76 190 90 20 10 180 185 200 32 10 180 345 200 32 10 180 465 200 32 10 180 505 200 32 10 QLineEdit::Normal 76 350 90 20 10 180 225 200 32 10 76 270 90 20 10 76 150 90 20 10 180 425 200 25 10 76 470 90 20 10 180 305 200 32 10 76 230 90 20 10 76 80 90 20 10 76 390 90 20 10 76 550 90 20 10 357 397 18 9 10 180 265 200 32 10 0 0 432 665 30 30 140 22 10 125 412 1 Qt::Horizontal 10 600 412 1 Qt::Horizontal lbBoder cbxConn leCaPwd leNetName btnConnect lePassword btnCancel lbDomain checkBoxPwdSec lbUserName lbSecurity cbxSecurity cbxCA cbxInnerAuth leUserName lbCA cbxAuth lbAnonyId lbNetName checkBoxCA lbInnerAuth leDomain lbAuth lbConn lbCaPwd lbPassword checkBoxPwd leAnonyId lbLeftupTitle lineUp lineDown ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifi.cpp0000644000175000017500000003467514205074704023532 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include DlgConnHidWifi::DlgConnHidWifi(int type, KylinNM *mainWindow, QWidget *parent) : isUsed(type), QDialog(parent), ui(new Ui::DlgConnHidWifi()) { ui->setupUi(this); this->setWindowFlags(Qt::FramelessWindowHint); this->setAttribute(Qt::WA_TranslucentBackground); //需要添加 void paintEvent(QPaintEvent *event) 函数 QPainterPath path; auto rect = this->rect(); rect.adjust(1, 1, -1, -1); path.addRoundedRect(rect, 6, 6); setProperty("blurRegion", QRegion(path.toFillPolygon().toPolygon())); KylinDBus mkylindbus; QString strTrans; strTrans = QString::number(1, 10, 2); QString sty = "QWidget{border-radius:6px;background-color:rgba(255,255,255,1);border:1px solid rgba(255, 255, 255, 1);}"; this->setStyleSheet(sty); //this->setStyleSheet("QWidget{border-radius:6px;background-color:rgba(19,19,20,0.7);border:1px solid rgba(255, 255, 255, 0.05);}"); MyQss objQss; ui->lbBoder->setStyleSheet("QLabel{border-radius:6px;background-color:rgba(19,19,20,0.95);border:1px solid rgba(255, 255, 255, 0.05);}"); ui->lbBoder->hide(); ui->lbLeftupTitle->setStyleSheet("QLabel{border:0px;font-size:20px;color:rgba(255,255,255,0.97);background-color:transparent;}"); ui->lbConn->setStyleSheet(objQss.labelQss); ui->lbNetName->setStyleSheet(objQss.labelQss); ui->lbSecurity->setStyleSheet(objQss.labelQss); ui->cbxConn->setStyleSheet(objQss.cbxQss); ui->cbxConn->setView(new QListView()); ui->leNetName->setStyleSheet(objQss.leQss); ui->cbxSecurity->setStyleSheet(objQss.cbxQss); ui->cbxSecurity->setView(new QListView()); ui->btnConnect->setStyleSheet(objQss.btnConnQss); ui->btnCancel->setStyleSheet(objQss.btnCancelQss); ui->lineUp->setStyleSheet(objQss.lineQss); ui->lineDown->setStyleSheet(objQss.lineQss); ui->lbLeftupTitle->setText(tr("Add Hidden Wi-Fi")); //加入隐藏Wi-Fi ui->lbConn->setText(tr("Connection")); //连接设置: ui->lbNetName->setText(tr("Wi-Fi name")); //网络名称: ui->lbSecurity->setText(tr("Wi-Fi security")); //Wi-Fi安全性: ui->btnCancel->setText(tr("Cancel")); //取消 ui->btnConnect->setText(tr("Connect")); //连接 ui->cbxConn->addItem(tr("C_reate…")); //新建... QString tmpPath = "/tmp/kylin-nm-connshow-" + QDir::home().dirName(); QString cmd = "nmcli connection show>" + tmpPath; int status = system(cmd.toUtf8().data()); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection show' in function 'DlgConnHidWifi' failed");} QFile file(tmpPath); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){ qDebug()<<"Can't open the file!"; } QString txt = file.readAll(); QStringList txtLine = txt.split("\n"); file.close(); foreach (QString line, txtLine) { if (line.indexOf("wifi") != -1 || line.indexOf("802-11-wireless") != -1) { QStringList subLine = line.split(" "); ui->cbxConn->addItem(subLine[0]); } } ui->cbxConn->setCurrentIndex(0); connect(ui->cbxConn,SIGNAL(currentIndexChanged(QString)),this,SLOT(changeWindow())); ui->cbxSecurity->addItem(tr("None")); //无 ui->cbxSecurity->addItem(tr("WPA & WPA2 Personal")); //WPA 及 WPA2 个人 //ui->cbxSecurity->addItem(tr("WEP 40/128-bit Key (Hex or ASCII)")); //WEP 40/128 位密钥(十六进制或ASCII) //ui->cbxSecurity->addItem(tr("WEP 128-bit Passphrase")); //WEP 128 位密码句 //ui->cbxSecurity->addItem("LEAP"); //ui->cbxSecurity->addItem(tr("Dynamic WEP (802.1X)")); //动态 WEP (802.1x) //ui->cbxSecurity->addItem(tr("WPA & WPA2 Enterprise")); //WPA 及 WPA2 企业 ui->cbxSecurity->setCurrentIndex(0); connect(ui->cbxSecurity,SIGNAL(currentIndexChanged(QString)),this,SLOT(changeDialog())); if (isUsed == 0){ ui->btnConnect->setEnabled(false); }else{ ui->cbxConn->setCurrentIndex(isUsed); ui->leNetName->setText(ui->cbxConn->currentText()); ui->lbNetName->setEnabled(false); ui->leNetName->setEnabled(false); ui->lbSecurity->setEnabled(false); ui->cbxSecurity->setEnabled(false); ui->btnConnect->setEnabled(true); } this->setFixedSize(432,358); this->mw = mainWindow; /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---START---- ** 手动绑定下拉框视图和下拉框 **/ ui->cbxConn->view()->setWindowFlags(Qt::Popup | Qt::X11BypassWindowManagerHint); ui->cbxConn->view()->setParent(this); ui->cbxConn->view()->hide(); ui->cbxConn->installEventFilter(this); ui->cbxSecurity->view()->setWindowFlags(Qt::Popup | Qt::X11BypassWindowManagerHint); ui->cbxSecurity->view()->setParent(this); ui->cbxSecurity->view()->hide(); ui->cbxSecurity->installEventFilter(this); connect(ui->cbxConn->view(), &QAbstractItemView::pressed, this, [=](QModelIndex index){ Q_EMIT ui->cbxConn->setCurrentIndex(index.row()); ui->cbxConn->view()->hide(); }); connect(ui->cbxSecurity->view(), &QAbstractItemView::pressed, this, [=](QModelIndex index){ ui->cbxSecurity->view()->hide(); Q_EMIT ui->cbxSecurity->setCurrentIndex(index.row()); }); ui->cbxConn->view()->setGeometry(QRect(ui->cbxConn->geometry().left(), ui->cbxConn->geometry().bottom(), ui->cbxConn->view()->width(), ui->cbxConn->view()->height())); ui->cbxSecurity->view()->setGeometry(QRect(ui->cbxSecurity->geometry().left(), ui->cbxSecurity->geometry().bottom(), ui->cbxSecurity->view()->width(), ui->cbxSecurity->view()->height())); /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---END---- ** 手动绑定下拉框视图和下拉框 **/ } DlgConnHidWifi::~DlgConnHidWifi() { delete ui; } /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---START---- ** 手动绑定下拉框视图和下拉框 **/ bool DlgConnHidWifi::eventFilter(QObject *obj, QEvent *ev) { if(ev->type() == QEvent::MouseButtonPress) { if(obj == ui->cbxConn) { ui->cbxConn->view()->setVisible(!ui->cbxConn->view()->isVisible()); if(ui->cbxConn->view()->isVisible()) ui->cbxConn->view()->setFocus(); } else if (obj == ui->cbxSecurity) { ui->cbxSecurity->view()->setVisible(!ui->cbxSecurity->view()->isVisible()); if(ui->cbxSecurity->view()->isVisible()) ui->cbxSecurity->view()->setFocus(); } } return false; } /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---END---- ** 手动绑定下拉框视图和下拉框 **/ void DlgConnHidWifi::mousePressEvent(QMouseEvent *event){ if(event->button() == Qt::LeftButton){ this->isPress = true; this->winPos = this->pos(); this->dragPos = event->globalPos(); event->accept(); } } void DlgConnHidWifi::mouseReleaseEvent(QMouseEvent *event){ this->isPress = false; } void DlgConnHidWifi::mouseMoveEvent(QMouseEvent *event){ if(this->isPress){ this->move(this->winPos - (this->dragPos - event->globalPos())); event->accept(); } } //切换到其他Wi-Fi安全类型 void DlgConnHidWifi::changeDialog() { if(ui->cbxSecurity->currentIndex()==0){ qDebug()<<"it's not need to change dialog"; } else if(ui->cbxSecurity->currentIndex()==1) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWpa *connHidWifiWpa = new DlgConnHidWifiWpa(0, mw, this->parentWidget()); connHidWifiWpa->show(); connect(connHidWifiWpa, SIGNAL(reSetWifiList() ), mw, SLOT(on_btnWifiList_clicked()) ); } else if(ui->cbxSecurity->currentIndex()==2) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWep *connHidWifiWep = new DlgConnHidWifiWep(0,this->parentWidget()); connHidWifiWep->show(); } else if(ui->cbxSecurity->currentIndex()==3) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWep *connHidWifiWep = new DlgConnHidWifiWep(1,this->parentWidget()); connHidWifiWep->show(); } else if(ui->cbxSecurity->currentIndex()==4) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiLeap *connHidWifiLeap = new DlgConnHidWifiLeap(this->parentWidget()); connHidWifiLeap->show(); } else if(ui->cbxSecurity->currentIndex()==5) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecTls *connHidWifiSecTls = new DlgConnHidWifiSecTls(0,this->parentWidget()); connHidWifiSecTls->show(); } else { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecTls *connHidWifiSecTls = new DlgConnHidWifiSecTls(1,this->parentWidget()); connHidWifiSecTls->show(); } } //同一 Wi-Fi安全类型的窗口变换 void DlgConnHidWifi::changeWindow(){ if (ui->cbxConn->currentIndex() == 0){ isUsed = ui->cbxConn->currentIndex(); ui->cbxConn->setCurrentIndex(0); ui->leNetName->setText(""); ui->lbNetName->setEnabled(true); ui->leNetName->setEnabled(true); ui->lbSecurity->setEnabled(true); ui->cbxSecurity->setEnabled(true); ui->btnConnect->setEnabled(false); }else if (ui->cbxConn->currentIndex() >= 1){ QString tmpPath = "/tmp/kylin-nm-connshow-" + QDir::home().dirName(); QString name = ui->cbxConn->currentText(); QString currStr = "nmcli connection show \"" + name.replace("\"","\\\"") + "\" >" + tmpPath; int status = system(currStr.toUtf8().data()); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection show' in function 'changeWindow' failed");} QFile file(tmpPath); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){ qDebug()<<"Can't open the file!"; } QString txt = file.readAll(); file.close(); if (txt.indexOf("802-11-wireless-security.key-mgmt:") != -1){ // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWpa *connHidWifiWpa = new DlgConnHidWifiWpa(ui->cbxConn->currentIndex(), mw, this->parentWidget()); connHidWifiWpa->show(); connect(connHidWifiWpa, SIGNAL(reSetWifiList() ), mw, SLOT(on_btnWifiList_clicked()) ); }else { isUsed = ui->cbxConn->currentIndex(); ui->leNetName->setText(ui->cbxConn->currentText()); ui->lbNetName->setEnabled(false); ui->leNetName->setEnabled(false); ui->lbSecurity->setEnabled(false); ui->cbxSecurity->setEnabled(false); ui->btnConnect->setEnabled(true); } } } void DlgConnHidWifi::on_btnCancel_clicked() { this->close(); } void DlgConnHidWifi::on_btnConnect_clicked() { QThread *t = new QThread(); connect(t, SIGNAL(finished()), t, SLOT(deleteLater())); connect(t, SIGNAL(started()), this, SLOT(slotStartLoading())); connect(this, SIGNAL(stopSignal()), t, SLOT(quit())); t->start(); QString wifiName = ui->leNetName->text(); BackThread *bt = new BackThread(); strWifiname = wifiName; //点击连接按钮以连接隐藏WiFi if (isUsed == 0) { int x = 0; do { sleep(1); QString tmpPath = "/tmp/kylin-nm-btoutput-" + QDir::home().dirName(); QString cmd = "nmcli device wifi connect \"" + wifiName.replace("\"","\\\"") + "\" password '' hidden yes > " + tmpPath; int status = system(cmd.toUtf8().data()); if (status != 0) syslog(LOG_ERR, "execute 'nmcli device wifi connect' in function 'on_btnConnect_clicked' failed"); QFile file(tmpPath); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug()<<"Can't open the file!"<execConnWifi(wifiName); connect(this, SIGNAL(sendMessage()), this,SLOT(emitSignal() )); QTimer::singleShot(4*1000, this, SLOT(emitSignal() )); } this->close(); } void DlgConnHidWifi::on_leNetName_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); } else { ui->btnConnect->setEnabled(true); } } void DlgConnHidWifi::slotStartLoading() { mw->startLoading(); } void DlgConnHidWifi::on_execSecConn() { QString name = strWifiname; QString str = "nmcli device wifi connect \"" + name.replace("\"","\\\"") + "\" password ''"; int status = system(str.toUtf8().data()); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli device wifi connect' in function 'on_execSecConn' failed");} connect(this, SIGNAL(sendMessage()), this,SLOT(emitSignal() )); QTimer::singleShot(3*1000, this, SLOT(emitSignal() )); } void DlgConnHidWifi::emitSignal() { emit reSetWifiList(); mw->stopLoading(); emit this->stopSignal(); } void DlgConnHidWifi::paintEvent(QPaintEvent *event) { QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); QWidget::paintEvent(event); } ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifisectunneltls.cpp0000644000175000017500000004111114205074704026155 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see DlgConnHidWifiSecTunnelTLS::DlgConnHidWifiSecTunnelTLS(int type, QWidget *parent) : WepOrWpa(type), QDialog(parent), ui(new Ui::DlgConnHidWifiSecTunnelTLS) { ui->setupUi(this); this->setWindowFlags(Qt::FramelessWindowHint); this->setAttribute(Qt::WA_TranslucentBackground); //需要添加 void paintEvent(QPaintEvent *event) 函数 QPainterPath path; auto rect = this->rect(); rect.adjust(1, 1, -1, -1); path.addRoundedRect(rect, 6, 6); setProperty("blurRegion", QRegion(path.toFillPolygon().toPolygon())); this->setStyleSheet("QWidget{border-radius:6px;background-color:rgba(19,19,20,0.7);border:1px solid rgba(255, 255, 255, 0.05);}"); MyQss objQss; ui->lbBoder->setStyleSheet("QLabel{border-radius:6px;background-color:rgba(19,19,20,0.95);border:1px solid rgba(255, 255, 255, 0.05);}"); ui->lbBoder->hide(); ui->lbLeftupTitle->setStyleSheet("QLabel{border:0px;font-size:20px;color:rgba(255,255,255,0.97);background-color:transparent;}"); ui->lbConn->setStyleSheet(objQss.labelQss); ui->lbNetName->setStyleSheet(objQss.labelQss); ui->lbSecurity->setStyleSheet(objQss.labelQss); ui->lbAuth->setStyleSheet(objQss.labelQss); ui->lbAnonyId->setStyleSheet(objQss.labelQss); ui->lbDomain->setStyleSheet(objQss.labelQss); ui->lbCA->setStyleSheet(objQss.labelQss); ui->lbCaPwd->setStyleSheet(objQss.labelQss); ui->lbInnerAuth->setStyleSheet(objQss.labelQss); ui->lbUserName->setStyleSheet(objQss.labelQss); ui->lbPassword->setStyleSheet(objQss.labelQss); ui->cbxConn->setStyleSheet(objQss.cbxQss); ui->cbxConn->setView(new QListView()); ui->leNetName->setStyleSheet(objQss.leQss); ui->cbxSecurity->setStyleSheet(objQss.cbxQss); ui->cbxSecurity->setView(new QListView()); ui->cbxAuth->setStyleSheet(objQss.cbxQss); ui->cbxAuth->setView(new QListView()); ui->leAnonyId->setStyleSheet(objQss.leQss); ui->leDomain->setStyleSheet(objQss.leQss); ui->cbxCA->setStyleSheet(objQss.cbxQss); ui->cbxCA->setView(new QListView()); ui->leCaPwd->setStyleSheet(objQss.leQss); ui->checkBoxPwd->setStyleSheet(objQss.checkBoxQss); ui->checkBoxCA->setStyleSheet(objQss.checkBoxCAQss); ui->cbxInnerAuth->setStyleSheet(objQss.cbxQss); ui->cbxInnerAuth->setView(new QListView()); ui->leUserName->setStyleSheet(objQss.leQss); ui->lePassword->setStyleSheet(objQss.leQss); ui->checkBoxPwdSec->setStyleSheet(objQss.checkBoxQss); ui->btnCancel->setStyleSheet(objQss.btnCancelQss); ui->btnConnect->setStyleSheet(objQss.btnConnQss); ui->lineUp->setStyleSheet(objQss.lineQss); ui->lineDown->setStyleSheet(objQss.lineQss); ui->checkBoxCA->setFocusPolicy(Qt::NoFocus); ui->lbLeftupTitle->setText(tr("Add hidden Wi-Fi")); //加入隐藏Wi-Fi ui->lbConn->setText(tr("Connection")); //连接设置: ui->lbNetName->setText(tr("Network name")); //网络名称: ui->lbSecurity->setText(tr("Wi-Fi security")); //Wi-Fi安全性: ui->lbAuth->setText(tr("Authentication")); //认证: ui->lbAnonyId->setText(tr("Anonymous identity")); //匿名身份: ui->lbDomain->setText(tr("Domain")); //域名: ui->lbCA->setText(tr("CA certificate")); //CA 证书: ui->lbCaPwd->setText(tr("CA certificate password")); //CA 证书密码: ui->checkBoxCA->setText(tr("No CA certificate is required")); //不需要CA证书 ui->lbInnerAuth->setText(tr("Inner authentication")); //内部认证: ui->lbUserName->setText(tr("Username")); //用户名: ui->lbPassword->setText(tr("Password")); //密码: ui->btnCancel->setText(tr("Cancel")); //取消 ui->btnConnect->setText(tr("Connect")); //连接 ui->cbxConn->addItem(tr("C_reate…")); //新建... int status = system("nmcli connection show>/tmp/kylin-nm-connshow"); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection show' in function 'DlgConnHidWifiSecTunnelTLS' failed");} QFile file("/tmp/kylin-nm-connshow"); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){ qDebug()<<"Can't open the file!"; } QString txt = file.readAll(); QStringList txtLine = txt.split("\n"); file.close(); foreach (QString line, txtLine) { if(line.indexOf("wifi") != -1){ QStringList subLine = line.split(" "); ui->cbxConn->addItem(subLine[0]); } } ui->cbxConn->setCurrentIndex(0); ui->cbxSecurity->addItem(tr("None")); //无 ui->cbxSecurity->addItem(tr("WPA & WPA2 Personal")); //WPA 及 WPA2 个人 ui->cbxSecurity->addItem(tr("WEP 40/128-bit Key (Hex or ASCII)")); //WEP 40/128 位密钥(十六进制或ASCII) ui->cbxSecurity->addItem(tr("WEP 128-bit Passphrase")); //WEP 128 位密码句 ui->cbxSecurity->addItem("LEAP"); ui->cbxSecurity->addItem(tr("Dynamic WEP (802.1X)")); //动态 WEP (802.1x) ui->cbxSecurity->addItem(tr("WPA & WPA2 Enterprise")); //WPA 及 WPA2 企业 if (WepOrWpa == 0) { ui->cbxSecurity->setCurrentIndex(5); } else if (WepOrWpa == 1) { ui->cbxSecurity->setCurrentIndex(6); } connect(ui->cbxSecurity,SIGNAL(currentIndexChanged(QString)),this,SLOT(changeDialogSecu())); ui->cbxAuth->addItem("TLS"); ui->cbxAuth->addItem("LEAP"); ui->cbxAuth->addItem("PWD"); ui->cbxAuth->addItem("FAST"); ui->cbxAuth->addItem(tr("Tunneled TLS"));//隧道 TLS ui->cbxAuth->addItem(tr("Protected EAP (PEAP)")); //受保护的 EAP ui->cbxAuth->setCurrentIndex(4); connect(ui->cbxAuth,SIGNAL(currentIndexChanged(QString)),this,SLOT(changeDialogAuth())); ui->cbxCA->addItem(tr("None")); //无 ui->cbxCA->addItem(tr("Choose from file")); //从文件选择... ui->cbxCA->setCurrentIndex(0); ui->cbxInnerAuth->addItem("PAP"); ui->cbxInnerAuth->addItem("MSCHAP"); ui->cbxInnerAuth->addItem("MSCHAPv2"); ui->cbxInnerAuth->addItem("MSCHAPv2(no EAP)"); ui->cbxInnerAuth->addItem("CHAP"); ui->cbxInnerAuth->addItem("MDS"); ui->cbxInnerAuth->addItem("GTC"); ui->cbxInnerAuth->setCurrentIndex(0); ui->btnConnect->setEnabled(false); this->setFixedSize(432,665); } DlgConnHidWifiSecTunnelTLS::~DlgConnHidWifiSecTunnelTLS() { delete ui; } void DlgConnHidWifiSecTunnelTLS::mousePressEvent(QMouseEvent *event){ if(event->button() == Qt::LeftButton){ this->isPress = true; this->winPos = this->pos(); this->dragPos = event->globalPos(); event->accept(); } } void DlgConnHidWifiSecTunnelTLS::mouseReleaseEvent(QMouseEvent *event){ this->isPress = false; } void DlgConnHidWifiSecTunnelTLS::mouseMoveEvent(QMouseEvent *event){ if(this->isPress){ this->move(this->winPos - (this->dragPos - event->globalPos())); event->accept(); } } void DlgConnHidWifiSecTunnelTLS::changeDialogSecu() { if(ui->cbxSecurity->currentIndex()==0){ // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifi *connHidWifi = new DlgConnHidWifi(0, 0, this->parentWidget()); connHidWifi->show(); } else if(ui->cbxSecurity->currentIndex()==1) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWpa *connHidWifiWpa = new DlgConnHidWifiWpa(0, 0, this->parentWidget()); connHidWifiWpa->show(); } else if(ui->cbxSecurity->currentIndex()==2) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWep *connHidWifiWep = new DlgConnHidWifiWep(0, this->parentWidget()); connHidWifiWep->show(); } else if(ui->cbxSecurity->currentIndex()==3) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWep *connHidWifiWep = new DlgConnHidWifiWep(1, this->parentWidget()); connHidWifiWep->show(); } else if(ui->cbxSecurity->currentIndex()==4) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiLeap *connHidWifiLeap = new DlgConnHidWifiLeap(this->parentWidget()); connHidWifiLeap->show(); } else if(ui->cbxSecurity->currentIndex()==5) { if (WepOrWpa == 1) { ui->cbxSecurity->setCurrentIndex(5); WepOrWpa = 0; } } else { if (WepOrWpa == 0){ ui->cbxSecurity->setCurrentIndex(6); WepOrWpa = 1; } } } void DlgConnHidWifiSecTunnelTLS::changeDialogAuth() { if(ui->cbxAuth->currentIndex()==0){ // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecTls *connHidWifiSecTls = new DlgConnHidWifiSecTls(WepOrWpa, this->parentWidget()); connHidWifiSecTls->show(); } else if(ui->cbxAuth->currentIndex()==1) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecLeap *connHidWifiSecLeap = new DlgConnHidWifiSecLeap(WepOrWpa, this->parentWidget()); connHidWifiSecLeap->show(); } else if(ui->cbxAuth->currentIndex()==2) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecPwd *connHidWifiSecPwd = new DlgConnHidWifiSecPwd(WepOrWpa, this->parentWidget()); connHidWifiSecPwd->show(); } else if(ui->cbxAuth->currentIndex()==3) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecFast *connHidWifiSecFast = new DlgConnHidWifiSecFast(WepOrWpa, this->parentWidget()); connHidWifiSecFast->show(); } else if(ui->cbxAuth->currentIndex()==4) { qDebug()<<"it's not need to change dialog"; } else { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecPeap *connHidWifiSecPeap = new DlgConnHidWifiSecPeap(WepOrWpa, this->parentWidget()); connHidWifiSecPeap->show(); } } void DlgConnHidWifiSecTunnelTLS::on_cbxCA_currentIndexChanged(const QString &arg1) { if (ui->cbxCA->currentIndex() == 0){ ui->leCaPwd->setText(""); ui->lbCaPwd->setEnabled(false); ui->leCaPwd->setEnabled(false); } else { ui->leCaPwd->setText(""); ui->lbCaPwd->setEnabled(true); ui->leCaPwd->setEnabled(true); } } void DlgConnHidWifiSecTunnelTLS::on_btnCancel_clicked() { this->close(); } void DlgConnHidWifiSecTunnelTLS::on_btnConnect_clicked() { this->close(); } void DlgConnHidWifiSecTunnelTLS::on_checkBoxPwd_stateChanged(int arg1) { if (arg1 == 0) { ui->leCaPwd->setEchoMode(QLineEdit::Password); } else { ui->leCaPwd->setEchoMode(QLineEdit::Normal); } } void DlgConnHidWifiSecTunnelTLS::on_checkBoxCA_stateChanged(int arg1) { if (arg1 == 0) { ui->cbxCA->setCurrentIndex(0); ui->leCaPwd->setText(""); ui->lbCA->setEnabled(true); ui->cbxCA->setEnabled(true); } else { ui->cbxCA->setCurrentIndex(0); ui->leCaPwd->setText(""); ui->lbCA->setEnabled(false); ui->cbxCA->setEnabled(false); } } void DlgConnHidWifiSecTunnelTLS::on_checkBoxPwdSec_stateChanged(int arg1) { if (arg1 == 0) { ui->lePassword->setEchoMode(QLineEdit::Password); } else { ui->lePassword->setEchoMode(QLineEdit::Normal); } } void DlgConnHidWifiSecTunnelTLS::on_leNetName_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leAnonyId->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leDomain->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); }else{ if (ui->cbxCA->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else if(ui->leCaPwd->text() == ""){ ui->btnConnect->setEnabled(false); }else{ ui->btnConnect->setEnabled(true); } } } void DlgConnHidWifiSecTunnelTLS::on_leAnonyId_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leAnonyId->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leDomain->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); }else{ if (ui->cbxCA->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else if(ui->leCaPwd->text() == ""){ ui->btnConnect->setEnabled(false); }else{ ui->btnConnect->setEnabled(true); } } } void DlgConnHidWifiSecTunnelTLS::on_leDomain_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leAnonyId->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leDomain->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); }else{ if (ui->cbxCA->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else if(ui->leCaPwd->text() == ""){ ui->btnConnect->setEnabled(false); }else{ ui->btnConnect->setEnabled(true); } } } void DlgConnHidWifiSecTunnelTLS::on_leCaPwd_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leAnonyId->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leDomain->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leCaPwd->text() == ""){ ui->btnConnect->setEnabled(false); }else{ ui->btnConnect->setEnabled(true); } } void DlgConnHidWifiSecTunnelTLS::on_leUserName_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leAnonyId->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leDomain->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); }else{ if (ui->cbxCA->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else if(ui->leCaPwd->text() == ""){ ui->btnConnect->setEnabled(false); }else{ ui->btnConnect->setEnabled(true); } } } void DlgConnHidWifiSecTunnelTLS::on_lePwd_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leAnonyId->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leDomain->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); }else{ if (ui->cbxCA->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else if(ui->leCaPwd->text() == ""){ ui->btnConnect->setEnabled(false); }else{ ui->btnConnect->setEnabled(true); } } } void DlgConnHidWifiSecTunnelTLS::paintEvent(QPaintEvent *event) { QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); QWidget::paintEvent(event); } ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifisecpwd.cpp0000644000175000017500000002504414205074704024726 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see DlgConnHidWifiSecPwd::DlgConnHidWifiSecPwd(int type, QWidget *parent) : WepOrWpa(type), QDialog(parent), ui(new Ui::DlgConnHidWifiSecPwd) { ui->setupUi(this); this->setWindowFlags(Qt::FramelessWindowHint); this->setAttribute(Qt::WA_TranslucentBackground); //需要添加 void paintEvent(QPaintEvent *event) 函数 QPainterPath path; auto rect = this->rect(); rect.adjust(1, 1, -1, -1); path.addRoundedRect(rect, 6, 6); setProperty("blurRegion", QRegion(path.toFillPolygon().toPolygon())); this->setStyleSheet("QWidget{border-radius:6px;background-color:rgba(19,19,20,0.7);border:1px solid rgba(255, 255, 255, 0.05);}"); MyQss objQss; ui->lbBoder->setStyleSheet("QLabel{border-radius:6px;background-color:rgba(19,19,20,0.95);border:1px solid rgba(255, 255, 255, 0.05);}"); ui->lbBoder->hide(); ui->lbLeftupTitle->setStyleSheet("QLabel{border:0px;font-size:20px;color:rgba(255,255,255,0.97);background-color:transparent;}"); ui->lbConn->setStyleSheet(objQss.labelQss); ui->lbNetName->setStyleSheet(objQss.labelQss); ui->lbSecurity->setStyleSheet(objQss.labelQss); ui->lbAuth->setStyleSheet(objQss.labelQss); ui->lbUserName->setStyleSheet(objQss.labelQss); ui->lbPassword->setStyleSheet(objQss.labelQss); ui->cbxConn->setStyleSheet(objQss.cbxQss); ui->cbxConn->setView(new QListView()); ui->leNetName->setStyleSheet(objQss.leQss); ui->cbxSecurity->setStyleSheet(objQss.cbxQss); ui->cbxSecurity->setView(new QListView()); ui->cbxAuth->setStyleSheet(objQss.cbxQss); ui->cbxAuth->setView(new QListView()); ui->leUserName->setStyleSheet(objQss.leQss); ui->lePassword->setStyleSheet(objQss.leQss); ui->checkBox->setStyleSheet(objQss.checkBoxQss); ui->btnCancel->setStyleSheet(objQss.btnCancelQss); ui->btnConnect->setStyleSheet(objQss.btnConnQss); ui->lineUp->setStyleSheet(objQss.lineQss); ui->lineDown->setStyleSheet(objQss.lineQss); ui->lbLeftupTitle->setText(tr("Add hidden Wi-Fi")); //加入隐藏Wi-Fi ui->lbConn->setText(tr("Connection")); //连接设置: ui->lbNetName->setText(tr("Network name")); //网络名称: ui->lbSecurity->setText(tr("Wi-Fi security")); //Wi-Fi安全性: ui->lbAuth->setText(tr("Authentication")); //认证: ui->lbUserName->setText(tr("Username")); //用户名: ui->lbPassword->setText(tr("Password")); //密码: ui->btnCancel->setText(tr("Cancel")); //取消 ui->btnConnect->setText(tr("Connect")); //连接 ui->cbxConn->addItem(tr("C_reate…")); //新建... int status = system("nmcli connection show>/tmp/kylin-nm-connshow"); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection show' in function 'DlgConnHidWifiSecPwd' failed");} QFile file("/tmp/kylin-nm-connshow"); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){ qDebug()<<"Can't open the file!"; } QString txt = file.readAll(); QStringList txtLine = txt.split("\n"); file.close(); foreach (QString line, txtLine) { if(line.indexOf("wifi") != -1){ QStringList subLine = line.split(" "); ui->cbxConn->addItem(subLine[0]); } } ui->cbxConn->setCurrentIndex(0); ui->cbxSecurity->addItem(tr("None")); //无 ui->cbxSecurity->addItem(tr("WPA & WPA2 Personal")); //WPA 及 WPA2 个人 ui->cbxSecurity->addItem(tr("WEP 40/128-bit Key (Hex or ASCII)")); //WEP 40/128 位密钥(十六进制或ASCII) ui->cbxSecurity->addItem(tr("WEP 128-bit Passphrase")); //WEP 128 位密码句 ui->cbxSecurity->addItem("LEAP"); ui->cbxSecurity->addItem(tr("Dynamic WEP (802.1X)")); //动态 WEP (802.1x) ui->cbxSecurity->addItem(tr("WPA & WPA2 Enterprise")); //WPA 及 WPA2 企业 if (WepOrWpa == 0) { ui->cbxSecurity->setCurrentIndex(5); } else if (WepOrWpa == 1) { ui->cbxSecurity->setCurrentIndex(6); } connect(ui->cbxSecurity,SIGNAL(currentIndexChanged(QString)),this,SLOT(changeDialogSecu())); ui->cbxAuth->addItem("TLS"); ui->cbxAuth->addItem("LEAP"); ui->cbxAuth->addItem("PWD"); ui->cbxAuth->addItem("FAST"); ui->cbxAuth->addItem(tr("Tunneled TLS"));//隧道 TLS ui->cbxAuth->addItem(tr("Protected EAP (PEAP)")); //受保护的 EAP ui->cbxAuth->setCurrentIndex(2); connect(ui->cbxAuth,SIGNAL(currentIndexChanged(QString)),this,SLOT(changeDialogAuth())); ui->btnConnect->setEnabled(false); this->setFixedSize(432,487); } DlgConnHidWifiSecPwd::~DlgConnHidWifiSecPwd() { delete ui; } void DlgConnHidWifiSecPwd::mousePressEvent(QMouseEvent *event){ if(event->button() == Qt::LeftButton){ this->isPress = true; this->winPos = this->pos(); this->dragPos = event->globalPos(); event->accept(); } } void DlgConnHidWifiSecPwd::mouseReleaseEvent(QMouseEvent *event){ this->isPress = false; } void DlgConnHidWifiSecPwd::mouseMoveEvent(QMouseEvent *event){ if(this->isPress){ this->move(this->winPos - (this->dragPos - event->globalPos())); event->accept(); } } void DlgConnHidWifiSecPwd::changeDialogSecu() { if(ui->cbxSecurity->currentIndex()==0){ // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifi *connHidWifi = new DlgConnHidWifi(0, 0, this->parentWidget()); connHidWifi->show(); } else if(ui->cbxSecurity->currentIndex()==1) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWpa *connHidWifiWpa = new DlgConnHidWifiWpa(0, 0, this->parentWidget()); connHidWifiWpa->show(); } else if(ui->cbxSecurity->currentIndex()==2) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWep *connHidWifiWep = new DlgConnHidWifiWep(0, this->parentWidget()); connHidWifiWep->show(); } else if(ui->cbxSecurity->currentIndex()==3) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWep *connHidWifiWep = new DlgConnHidWifiWep(1, this->parentWidget()); connHidWifiWep->show(); } else if(ui->cbxSecurity->currentIndex()==4) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiLeap *connHidWifiLeap = new DlgConnHidWifiLeap(this->parentWidget()); connHidWifiLeap->show(); } else if(ui->cbxSecurity->currentIndex()==5) { if (WepOrWpa == 1) { ui->cbxSecurity->setCurrentIndex(5); WepOrWpa = 0; } } else { if (WepOrWpa == 0){ ui->cbxSecurity->setCurrentIndex(6); WepOrWpa = 1; } } } void DlgConnHidWifiSecPwd::changeDialogAuth() { if(ui->cbxAuth->currentIndex()==0){ // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecTls *connHidWifiSecTls = new DlgConnHidWifiSecTls(WepOrWpa, this->parentWidget()); connHidWifiSecTls->show(); } else if(ui->cbxAuth->currentIndex()==1) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecLeap *connHidWifiSecLeap = new DlgConnHidWifiSecLeap(WepOrWpa, this->parentWidget()); connHidWifiSecLeap->show(); } else if(ui->cbxAuth->currentIndex()==2) { qDebug()<<"it's not need to change dialog"; } else if(ui->cbxAuth->currentIndex()==3) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecFast *connHidWifiSecFast = new DlgConnHidWifiSecFast(WepOrWpa); connHidWifiSecFast->show(); } else if(ui->cbxAuth->currentIndex()==4) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecTunnelTLS *connHidWifiSecTuTls = new DlgConnHidWifiSecTunnelTLS(WepOrWpa); connHidWifiSecTuTls->show(); } else { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecPeap *connHidWifiSecPeap = new DlgConnHidWifiSecPeap(WepOrWpa); connHidWifiSecPeap->show(); } } void DlgConnHidWifiSecPwd::on_btnCancel_clicked() { this->close(); } void DlgConnHidWifiSecPwd::on_btnConnect_clicked() { this->close(); } void DlgConnHidWifiSecPwd::on_checkBox_stateChanged(int arg1) { if (arg1 == 0) { ui->lePassword ->setEchoMode(QLineEdit::Password); } else { ui->lePassword->setEchoMode(QLineEdit::Normal); } } void DlgConnHidWifiSecPwd::on_leNetName_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); } else { ui->btnConnect->setEnabled(true); } } void DlgConnHidWifiSecPwd::on_leUserName_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); } else { ui->btnConnect->setEnabled(true); } } void DlgConnHidWifiSecPwd::on_lePassword_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); } else { ui->btnConnect->setEnabled(true); } } void DlgConnHidWifiSecPwd::paintEvent(QPaintEvent *event) { QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); QWidget::paintEvent(event); } ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifiwep.h0000644000175000017500000000335314205074704023700 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include namespace Ui { class DlgConnHidWifiWep; } class DlgConnHidWifiWep : public QDialog { Q_OBJECT public: explicit DlgConnHidWifiWep(int type, QWidget *parent = 0); ~DlgConnHidWifiWep(); protected: void paintEvent(QPaintEvent *event); public slots: void changeDialog(); private slots: void on_btnCancel_clicked(); void on_btnConnect_clicked(); void on_checkBoxPwd_stateChanged(int arg1); void on_leKey_textEdited(const QString &arg1); void on_leNetName_textEdited(const QString &arg1); private: Ui::DlgConnHidWifiWep *ui; int WepPwdOrCode = 0; //0 WEP password;1 WEP Code Sentence void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); // QString labelQss, cbxQss, leQss, btnConnQss, btnCancelQss, lineQss, checkBoxQss; bool isPress; QPoint winPos; QPoint dragPos; }; #endif // DLGCONNHIDWIFIWEP_H ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifisecfast.cpp0000644000175000017500000003633214205074704025073 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see DlgConnHidWifiSecFast::DlgConnHidWifiSecFast(int type, QWidget *parent) : WepOrWpa(type), QDialog(parent), ui(new Ui::DlgConnHidWifiSecFast) { ui->setupUi(this); this->setWindowFlags(Qt::FramelessWindowHint); this->setAttribute(Qt::WA_TranslucentBackground); //需要添加 void paintEvent(QPaintEvent *event) 函数 QPainterPath path; auto rect = this->rect(); rect.adjust(1, 1, -1, -1); path.addRoundedRect(rect, 6, 6); setProperty("blurRegion", QRegion(path.toFillPolygon().toPolygon())); this->setStyleSheet("QWidget{border-radius:6px;background-color:rgba(19,19,20,0.7);border:1px solid rgba(255, 255, 255, 0.05);}"); MyQss objQss; ui->lbBoder->setStyleSheet("QLabel{border-radius:6px;background-color:rgba(19,19,20,0.95);border:1px solid rgba(255, 255, 255, 0.05);}"); ui->lbBoder->hide(); ui->lbLeftupTitle->setStyleSheet("QLabel{border:0px;font-size:20px;color:rgba(255,255,255,0.97);background-color:transparent;}"); ui->lbConn->setStyleSheet(objQss.labelQss); ui->lbNetName->setStyleSheet(objQss.labelQss); ui->lbSecurity->setStyleSheet(objQss.labelQss); ui->lbAuth->setStyleSheet(objQss.labelQss); ui->lbAnonyId->setStyleSheet(objQss.labelQss); ui->checkBoxAutoPCA->setStyleSheet(objQss.checkBoxCAQss); ui->lbPCAfile->setStyleSheet(objQss.labelQss); ui->lbInnerAuth->setStyleSheet(objQss.labelQss); ui->lbUserName->setStyleSheet(objQss.labelQss); ui->lbPassword->setStyleSheet(objQss.labelQss); ui->cbxConn->setStyleSheet(objQss.cbxQss); ui->cbxConn->setView(new QListView()); ui->leNetName->setStyleSheet(objQss.leQss); ui->cbxSecurity->setStyleSheet(objQss.cbxQss); ui->cbxSecurity->setView(new QListView()); ui->cbxAuth->setStyleSheet(objQss.cbxQss); ui->cbxAuth->setView(new QListView()); ui->leAnonyId->setStyleSheet(objQss.leQss); ui->cbxAutoPCA->setStyleSheet(objQss.cbxQss); ui->cbxAutoPCA->setView(new QListView()); ui->lePCAfile->setStyleSheet(objQss.leQss); ui->cbxInnerAuth->setStyleSheet(objQss.cbxQss); ui->cbxInnerAuth->setView(new QListView()); ui->leUserName->setStyleSheet(objQss.leQss); ui->lePassword->setStyleSheet(objQss.leQss); ui->checkBoxPwd->setStyleSheet(objQss.checkBoxQss); ui->btnCancel->setStyleSheet(objQss.btnCancelQss); ui->btnConnect->setStyleSheet(objQss.btnConnQss); ui->lineUp->setStyleSheet(objQss.lineQss); ui->lineDown->setStyleSheet(objQss.lineQss); ui->lbLeftupTitle->setText(tr("Add hidden Wi-Fi")); //加入隐藏Wi-Fi ui->lbConn->setText(tr("Connection")); //连接设置: ui->lbNetName->setText(tr("Network name")); //网络名称: ui->lbSecurity->setText(tr("Wi-Fi security")); //Wi-Fi安全性: ui->lbAuth->setText(tr("Authentication")); //认证: ui->lbAnonyId->setText(tr("Anonymous identity")); //匿名身份: ui->checkBoxAutoPCA->setText(tr("Allow automatic PAC pro_visioning")); //自动PAC配置: ui->lbPCAfile->setText(tr("PAC file"));//PAC文件: ui->lbInnerAuth->setText(tr("Inner authentication")); //内部认证: ui->lbUserName->setText(tr("Username")); //用户名: ui->lbPassword->setText(tr("Password")); //密码: ui->btnCancel->setText(tr("Cancel")); //取消 ui->btnConnect->setText(tr("Connect")); //连接 ui->checkBoxAutoPCA->setFocusPolicy(Qt::NoFocus); ui->checkBoxPwd->setFocusPolicy(Qt::NoFocus); ui->cbxConn->addItem(tr("C_reate…")); //新建... int status = system("nmcli connection show>/tmp/kylin-nm-connshow"); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection show' in function 'DlgConnHidWifiSecFast' failed");} QFile file("/tmp/kylin-nm-connshow"); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){ qDebug()<<"Can't open the file!"; } QString txt = file.readAll(); QStringList txtLine = txt.split("\n"); file.close(); foreach (QString line, txtLine) { if(line.indexOf("wifi") != -1){ QStringList subLine = line.split(" "); ui->cbxConn->addItem(subLine[0]); } } ui->cbxConn->setCurrentIndex(0); ui->cbxSecurity->addItem(tr("None")); //无 ui->cbxSecurity->addItem(tr("WPA & WPA2 Personal")); //WPA 及 WPA2 个人 ui->cbxSecurity->addItem(tr("WEP 40/128-bit Key (Hex or ASCII)")); //WEP 40/128 位密钥(十六进制或ASCII) ui->cbxSecurity->addItem(tr("WEP 128-bit Passphrase")); //WEP 128 位密码句 ui->cbxSecurity->addItem("LEAP"); ui->cbxSecurity->addItem(tr("Dynamic WEP (802.1X)")); //动态 WEP (802.1x) ui->cbxSecurity->addItem(tr("WPA & WPA2 Enterprise")); //WPA 及 WPA2 企业 if (WepOrWpa == 0) { ui->cbxSecurity->setCurrentIndex(5); } else if (WepOrWpa == 1) { ui->cbxSecurity->setCurrentIndex(6); } connect(ui->cbxSecurity,SIGNAL(currentIndexChanged(QString)),this,SLOT(changeDialogSecu())); ui->cbxAuth->addItem("TLS"); ui->cbxAuth->addItem("LEAP"); ui->cbxAuth->addItem("PWD"); ui->cbxAuth->addItem("FAST"); ui->cbxAuth->addItem(tr("Tunneled TLS"));//隧道 TLS ui->cbxAuth->addItem(tr("Protected EAP (PEAP)")); //受保护的 EAP ui->cbxAuth->setCurrentIndex(3); connect(ui->cbxAuth,SIGNAL(currentIndexChanged(QString)),this,SLOT(changeDialogAuth())); ui->checkBoxAutoPCA->setCheckState(Qt::Checked); ui->cbxAutoPCA->addItem(tr("Anonymous")); //匿名 ui->cbxAutoPCA->addItem(tr("Authenticated")); //已认证 ui->cbxAutoPCA->addItem(tr("Both")); //两者兼用 ui->cbxAutoPCA->setCurrentIndex(0); ui->lePCAfile->setText(tr("None")); //(无) ui->cbxInnerAuth->addItem("GTC"); ui->cbxInnerAuth->addItem("MSCHAPv2"); ui->cbxInnerAuth->setCurrentIndex(0); ui->btnConnect->setEnabled(false); this->setFixedSize(432,673); /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---START---- ** 手动绑定下拉框视图和下拉框 **/ ui->cbxConn->view()->setWindowFlags(Qt::Popup | Qt::X11BypassWindowManagerHint); ui->cbxConn->view()->setParent(this); ui->cbxConn->view()->hide(); ui->cbxConn->installEventFilter(this); ui->cbxSecurity->view()->setWindowFlags(Qt::Popup | Qt::X11BypassWindowManagerHint); ui->cbxSecurity->view()->setParent(this); ui->cbxSecurity->view()->hide(); ui->cbxSecurity->installEventFilter(this); connect(ui->cbxConn->view(), &QAbstractItemView::pressed, this, [=](QModelIndex index){ Q_EMIT ui->cbxConn->setCurrentIndex(index.row()); ui->cbxConn->view()->hide(); }); connect(ui->cbxSecurity->view(), &QAbstractItemView::pressed, this, [=](QModelIndex index){ ui->cbxSecurity->view()->hide(); Q_EMIT ui->cbxSecurity->setCurrentIndex(index.row()); }); ui->cbxConn->view()->setGeometry(QRect(ui->cbxConn->geometry().left(), ui->cbxConn->geometry().bottom(), ui->cbxConn->view()->width(), ui->cbxConn->view()->height())); ui->cbxSecurity->view()->setGeometry(QRect(ui->cbxSecurity->geometry().left(), ui->cbxSecurity->geometry().bottom(), ui->cbxSecurity->view()->width(), ui->cbxSecurity->view()->height())); /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---END---- ** 手动绑定下拉框视图和下拉框 **/ } DlgConnHidWifiSecFast::~DlgConnHidWifiSecFast() { delete ui; } /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---START---- ** 手动绑定下拉框视图和下拉框 **/ bool DlgConnHidWifiSecFast::eventFilter(QObject *obj, QEvent *ev) { if(ev->type() == QEvent::MouseButtonPress) { if(obj == ui->cbxConn) { ui->cbxConn->view()->setVisible(!ui->cbxConn->view()->isVisible()); if(ui->cbxConn->view()->isVisible()) ui->cbxConn->view()->setFocus(); } else if (obj == ui->cbxSecurity) { ui->cbxSecurity->view()->setVisible(!ui->cbxSecurity->view()->isVisible()); if(ui->cbxSecurity->view()->isVisible()) ui->cbxSecurity->view()->setFocus(); } } return false; } /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---END---- ** 手动绑定下拉框视图和下拉框 **/ void DlgConnHidWifiSecFast::mousePressEvent(QMouseEvent *event){ if(event->button() == Qt::LeftButton){ this->isPress = true; this->winPos = this->pos(); this->dragPos = event->globalPos(); event->accept(); } } void DlgConnHidWifiSecFast::mouseReleaseEvent(QMouseEvent *event){ this->isPress = false; } void DlgConnHidWifiSecFast::mouseMoveEvent(QMouseEvent *event){ if(this->isPress){ this->move(this->winPos - (this->dragPos - event->globalPos())); event->accept(); } } void DlgConnHidWifiSecFast::changeDialogSecu() { if(ui->cbxSecurity->currentIndex()==0){ // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifi *connHidWifi = new DlgConnHidWifi(0, 0, this->parentWidget()); connHidWifi->show(); } else if(ui->cbxSecurity->currentIndex()==1) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWpa *connHidWifiWpa = new DlgConnHidWifiWpa(0, 0, this->parentWidget()); connHidWifiWpa->show(); } else if(ui->cbxSecurity->currentIndex()==2) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWep *connHidWifiWep = new DlgConnHidWifiWep(0, this->parentWidget()); connHidWifiWep->show(); } else if(ui->cbxSecurity->currentIndex()==3) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWep *connHidWifiWep = new DlgConnHidWifiWep(1, this->parentWidget()); connHidWifiWep->show(); } else if(ui->cbxSecurity->currentIndex()==4) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiLeap *connHidWifiLeap = new DlgConnHidWifiLeap(this->parentWidget()); connHidWifiLeap->show(); } else if(ui->cbxSecurity->currentIndex()==5) { if (WepOrWpa == 1) { ui->cbxSecurity->setCurrentIndex(5); WepOrWpa = 0; } } else { if (WepOrWpa == 0){ ui->cbxSecurity->setCurrentIndex(6); WepOrWpa = 1; } } } void DlgConnHidWifiSecFast::changeDialogAuth() { if(ui->cbxAuth->currentIndex()==0){ // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecTls *connHidWifiSecTls = new DlgConnHidWifiSecTls(WepOrWpa, this->parentWidget()); connHidWifiSecTls->show(); } else if(ui->cbxAuth->currentIndex()==1) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecLeap *connHidWifiSecLeap = new DlgConnHidWifiSecLeap(WepOrWpa, this->parentWidget()); connHidWifiSecLeap->show(); } else if(ui->cbxAuth->currentIndex()==2) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecPwd *connHidWifiSecPwd = new DlgConnHidWifiSecPwd(WepOrWpa, this->parentWidget()); connHidWifiSecPwd->show(); } else if(ui->cbxAuth->currentIndex()==3) { qDebug()<<"it's not need to change dialog"; } else if(ui->cbxAuth->currentIndex()==4) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecTunnelTLS *connHidWifiSecTuTls = new DlgConnHidWifiSecTunnelTLS(WepOrWpa, this->parentWidget()); connHidWifiSecTuTls->show(); } else { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecPeap *connHidWifiSecPeap = new DlgConnHidWifiSecPeap(WepOrWpa); connHidWifiSecPeap->show(); } } void DlgConnHidWifiSecFast::on_btnCancel_clicked() { this->close(); } void DlgConnHidWifiSecFast::on_btnConnect_clicked() { this->close(); } void DlgConnHidWifiSecFast::on_checkBoxAutoPCA_stateChanged(int arg1) { if (arg1 == 0) { ui->cbxAutoPCA->setEnabled(false); } else { ui->cbxAutoPCA->setEnabled(true); } } void DlgConnHidWifiSecFast::on_checkBoxPwd_stateChanged(int arg1) { if (arg1 == 0) { ui->lePassword ->setEchoMode(QLineEdit::Password); } else { ui->lePassword->setEchoMode(QLineEdit::Normal); } } void DlgConnHidWifiSecFast::on_leNetName_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); } else if(ui->leAnonyId->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); } else { ui->btnConnect->setEnabled(true); } } void DlgConnHidWifiSecFast::on_leAnonyId_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); } else if(ui->leAnonyId->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); } else { ui->btnConnect->setEnabled(true); } } void DlgConnHidWifiSecFast::on_leUserName_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); } else if(ui->leAnonyId->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); } else { ui->btnConnect->setEnabled(true); } } void DlgConnHidWifiSecFast::on_lePassword_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); } else if(ui->leAnonyId->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); } else { ui->btnConnect->setEnabled(true); } } void DlgConnHidWifiSecFast::paintEvent(QPaintEvent *event) { QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); QWidget::paintEvent(event); } ukui-screensaver/KylinNM/wireless-security/kylinheadfile.cpp0000644000175000017500000000562514205074704023343 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include DlgConnHidWifiWpa::DlgConnHidWifiWpa(int type, KylinNM *mainWindow, QWidget *parent) : isUsed(type), QDialog(parent), ui(new Ui::DlgConnHidWifiWpa) { ui->setupUi(this); this->setWindowFlags(Qt::FramelessWindowHint); this->setAttribute(Qt::WA_TranslucentBackground); //需要添加 void paintEvent(QPaintEvent *event) 函数 QPainterPath path; auto rect = this->rect(); rect.adjust(1, 1, -1, -1); path.addRoundedRect(rect, 6, 6); setProperty("blurRegion", QRegion(path.toFillPolygon().toPolygon())); KylinDBus mkylindbus; double trans = mkylindbus.getTransparentData(); QString strTrans; strTrans = QString::number(trans, 10, 2); QString sty = "QWidget{border-radius:6px;background-color:rgba(255,255,255,1);border:1px solid rgba(255, 255, 255, 0.05);}"; this->setStyleSheet(sty); //this->setStyleSheet("QWidget{border-radius:6px;background-color:rgba(19,19,20,0.7);border:1px solid rgba(255, 255, 255, 0.05);}"); MyQss objQss; ui->lbBoder->setStyleSheet("QLabel{border-radius:6px;background-color:rgba(19,19,20,0.95);border:1px solid rgba(255, 255, 255, 0.05);}"); ui->lbBoder->hide(); ui->lbLeftupTitle->setStyleSheet("QLabel{border:0px;font-size:20px;color:rgba(255,255,255,0.97);background-color:transparent;}"); ui->lbConn->setStyleSheet(objQss.labelQss); ui->lbNetName->setStyleSheet(objQss.labelQss); ui->lbSecurity->setStyleSheet(objQss.labelQss); ui->lbPassword->setStyleSheet(objQss.labelQss); ui->cbxConn->setStyleSheet(objQss.cbxQss); ui->cbxConn->setView(new QListView()); ui->leNetName->setStyleSheet(objQss.leQss); ui->lePassword->setStyleSheet(objQss.leQss); ui->cbxSecurity->setStyleSheet(objQss.cbxQss); ui->cbxSecurity->setView(new QListView()); ui->checkBoxPwd->setStyleSheet(objQss.checkBoxQss); ui->btnCancel->setStyleSheet(objQss.btnCancelQss); ui->btnConnect->setStyleSheet(objQss.btnConnQss); ui->lineUp->setStyleSheet(objQss.lineQss); ui->lineDown->setStyleSheet(objQss.lineQss); ui->btnCancel->setFocusPolicy(Qt::NoFocus); ui->checkBoxPwd->setFocusPolicy(Qt::NoFocus); ui->lbLeftupTitle->setText(tr("Add Hidden Wi-Fi")); //加入隐藏Wi-Fi ui->lbConn->setText(tr("Connection")); //连接设置: ui->lbNetName->setText(tr("Wi-Fi name")); //网络名称: ui->lbSecurity->setText(tr("Wi-Fi security")); //Wi-Fi 安全性: ui->lbPassword->setText(tr("Password")); //密码: ui->btnCancel->setText(tr("Cancel")); //取消 ui->btnConnect->setText(tr("Connect")); //连接 ui->cbxConn->addItem(tr("C_reate…")); //新建... QString tmpPath = "/tmp/kylin-nm-connshow-" + QDir::home().dirName(); QString cmd = "nmcli connection show > " + tmpPath; int status = system(cmd.toUtf8().data()); if (status != 0) { syslog(LOG_ERR, "execute 'nmcli connection show' in function 'DlgConnHidWifiWpa' failed"); } QFile file(tmpPath); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){ qDebug()<<"Can't open the file!"; } QString txt = file.readAll(); QStringList txtLine = txt.split("\n"); file.close(); foreach (QString line, txtLine) { if (line.indexOf("wifi") != -1 || line.indexOf("802-11-wireless") != -1) { QStringList subLine = line.split(" "); ui->cbxConn->addItem(subLine[0]); } } ui->cbxConn->setCurrentIndex(0); connect(ui->cbxConn,SIGNAL(currentIndexChanged(QString)),this,SLOT(changeWindow())); ui->cbxSecurity->addItem(tr("None")); //无 ui->cbxSecurity->addItem(tr("WPA & WPA2 Personal")); //WPA 及 WPA2 个人 //ui->cbxSecurity->addItem(tr("WEP 40/128-bit Key (Hex or ASCII)")); //WEP 40/128 位密钥(十六进制或ASCII) //ui->cbxSecurity->addItem(tr("WEP 128-bit Passphrase")); //WEP 128 位密码句 //ui->cbxSecurity->addItem("LEAP"); //ui->cbxSecurity->addItem(tr("Dynamic WEP (802.1X)")); //动态 WEP (802.1x) //ui->cbxSecurity->addItem(tr("WPA & WPA2 Enterprise")); //WPA 及 WPA2 企业 ui->cbxSecurity->setCurrentIndex(1); connect(ui->cbxSecurity,SIGNAL(currentIndexChanged(QString)),this,SLOT(changeDialog())); if (isUsed == 0){ ui->btnConnect->setEnabled(false); } else { ui->cbxConn->setCurrentIndex(isUsed); ui->leNetName->setText(ui->cbxConn->currentText()); ui->leNetName->setEnabled(false); ui->lbNetName->setEnabled(false); ui->lbSecurity->setEnabled(false); ui->cbxSecurity->setEnabled(false); ui->lbPassword->setEnabled(false); ui->lePassword->setText(""); ui->lePassword->setEnabled(false); ui->btnConnect->setEnabled(true); ui->checkBoxPwd->setEnabled(false); } this->setFixedSize(432,397); this->mw = mainWindow; /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---START---- ** 手动绑定下拉框视图和下拉框 **/ ui->cbxConn->view()->setWindowFlags(Qt::Popup | Qt::X11BypassWindowManagerHint); ui->cbxConn->view()->setParent(this); ui->cbxConn->view()->hide(); ui->cbxConn->installEventFilter(this); ui->cbxSecurity->view()->setWindowFlags(Qt::Popup | Qt::X11BypassWindowManagerHint); ui->cbxSecurity->view()->setParent(this); ui->cbxSecurity->view()->hide(); ui->cbxSecurity->installEventFilter(this); connect(ui->cbxConn->view(), &QAbstractItemView::pressed, this, [=](QModelIndex index){ Q_EMIT ui->cbxConn->setCurrentIndex(index.row()); ui->cbxConn->view()->hide(); }); connect(ui->cbxSecurity->view(), &QAbstractItemView::pressed, this, [=](QModelIndex index){ ui->cbxSecurity->view()->hide(); Q_EMIT ui->cbxSecurity->setCurrentIndex(index.row()); }); ui->cbxConn->view()->setGeometry(QRect(ui->cbxConn->geometry().left(), ui->cbxConn->geometry().bottom(), ui->cbxConn->view()->width(), ui->cbxConn->view()->height())); ui->cbxSecurity->view()->setGeometry(QRect(ui->cbxSecurity->geometry().left(), ui->cbxSecurity->geometry().bottom(), ui->cbxSecurity->view()->width(), ui->cbxSecurity->view()->height())); /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---END---- ** 手动绑定下拉框视图和下拉框 **/ } DlgConnHidWifiWpa::~DlgConnHidWifiWpa() { delete ui; } /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---START---- ** 手动绑定下拉框视图和下拉框 **/ bool DlgConnHidWifiWpa::eventFilter(QObject *obj, QEvent *ev) { if(ev->type() == QEvent::MouseButtonPress) { if(obj == ui->cbxConn) { ui->cbxConn->view()->setVisible(!ui->cbxConn->view()->isVisible()); if(ui->cbxConn->view()->isVisible()) ui->cbxConn->view()->setFocus(); } else if (obj == ui->cbxSecurity) { ui->cbxSecurity->view()->setVisible(!ui->cbxSecurity->view()->isVisible()); if(ui->cbxSecurity->view()->isVisible()) ui->cbxSecurity->view()->setFocus(); } } return false; } /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---END---- ** 手动绑定下拉框视图和下拉框 **/ void DlgConnHidWifiWpa::mousePressEvent(QMouseEvent *event){ if(event->button() == Qt::LeftButton){ this->isPress = true; this->winPos = this->pos(); this->dragPos = event->globalPos(); event->accept(); } } void DlgConnHidWifiWpa::mouseReleaseEvent(QMouseEvent *event){ this->isPress = false; } void DlgConnHidWifiWpa::mouseMoveEvent(QMouseEvent *event){ if(this->isPress){ this->move(this->winPos - (this->dragPos - event->globalPos())); event->accept(); } } //切换到其他Wi-Fi安全类型 void DlgConnHidWifiWpa::changeDialog() { if(ui->cbxSecurity->currentIndex()==0){ // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifi *connHidWifi = new DlgConnHidWifi(0,mw, this->parentWidget()); connHidWifi->show(); connect(connHidWifi, SIGNAL(reSetWifiList() ), mw, SLOT(on_btnWifiList_clicked()) ); } else if(ui->cbxSecurity->currentIndex()==1) { qDebug()<<"it's not need to change dialog"; } else if(ui->cbxSecurity->currentIndex()==2) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWep *connHidWifiWep = new DlgConnHidWifiWep(0, this->parentWidget()); connHidWifiWep->show(); } else if(ui->cbxSecurity->currentIndex()==3) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWep *connHidWifiWep = new DlgConnHidWifiWep(1,this->parentWidget()); connHidWifiWep->show(); } else if(ui->cbxSecurity->currentIndex()==4) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiLeap *connHidWifiLeap = new DlgConnHidWifiLeap(this->parentWidget()); connHidWifiLeap->show(); } else if(ui->cbxSecurity->currentIndex()==5) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecTls *connHidWifiSecTls = new DlgConnHidWifiSecTls(0, this->parentWidget()); connHidWifiSecTls->show(); } else { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecTls *connHidWifiSecTls = new DlgConnHidWifiSecTls(1, this->parentWidget()); connHidWifiSecTls->show(); } } //同一 Wi-Fi安全类型的窗口变换 void DlgConnHidWifiWpa::changeWindow() { if (ui->cbxConn->currentIndex() == 0){ // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifi *connHidWifi = new DlgConnHidWifi(0, mw, this->parentWidget()); connHidWifi->show(); connect(connHidWifi, SIGNAL(reSetWifiList() ), mw, SLOT(on_btnWifiList_clicked()) ); }else if (ui->cbxConn->currentIndex() >= 1){ QString tmpPath = "/tmp/kylin-nm-connshow-" + QDir::home().dirName(); QString name = ui->cbxConn->currentText(); QString currStr = "nmcli connection show \"" + name.replace("\"","\\\"") + "\" > " + tmpPath; int status = system(currStr.toUtf8().data()); if(status != 0){ syslog(LOG_ERR, "execute 'nmcli connection show' in function 'changeWindow' failed"); } QFile file(tmpPath); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){ qDebug()<<"Can't open the file!"; } QString txt = file.readAll(); file.close(); if (txt.indexOf("802-11-wireless-security.key-mgmt:") != -1){ isUsed = ui->cbxConn->currentIndex(); ui->lbNetName->setEnabled(false); ui->leNetName->setText(ui->cbxConn->currentText()); ui->leNetName->setEnabled(false); ui->lbSecurity->setEnabled(false); ui->cbxSecurity->setEnabled(false); ui->lePassword->setText(""); ui->lbPassword->setEnabled(false); ui->lePassword->setEnabled(false); ui->btnConnect->setEnabled(true); }else { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifi *connHidWifi = new DlgConnHidWifi(ui->cbxConn->currentIndex(), mw); connHidWifi->show(); connect(connHidWifi, SIGNAL(reSetWifiList() ), mw, SLOT(on_btnWifiList_clicked()) ); } } } void DlgConnHidWifiWpa::on_btnCancel_clicked() { this->close(); } void DlgConnHidWifiWpa::on_btnConnect_clicked() { QThread *t = new QThread(); connect(t, SIGNAL(finished()), t, SLOT(deleteLater())); connect(t, SIGNAL(started()), this, SLOT(slotStartLoading())); connect(this, SIGNAL(stopSignal()), t, SLOT(quit())); t->start(); QString wifiName = ui->leNetName->text(); QString wifiPassword = ui->lePassword->text(); BackThread *bt = new BackThread(); strWifiname = wifiName; strWifiPassword = wifiPassword; if (isUsed == 0){ int x = 0; do{ sleep(1); QString tmpPath = "/tmp/kylin-nm-btoutput-" + QDir::home().dirName(); QString cmd = "nmcli device wifi connect \"" + wifiName.replace("\"","\\\"") + "\" password \"" + wifiPassword.replace("\"","\\\"") + "\" hidden yes > " + tmpPath; int status = system(cmd.toUtf8().data()); if (status != 0) { syslog(LOG_ERR, "execute 'nmcli device wifi connect' in function 'on_btnConnect_clicked' failed"); } QFile file(tmpPath); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug()<<"Can't open the file!"<execConnWifi(wifiName); connect(this, SIGNAL(sendMessage()), this,SLOT(emitSignal() )); QTimer::singleShot(4*1000, this, SLOT(emitSignal() )); } this->close(); } void DlgConnHidWifiWpa::on_checkBoxPwd_stateChanged(int arg1) { if (arg1 == 0) { ui->lePassword ->setEchoMode(QLineEdit::Password); } else { ui->lePassword->setEchoMode(QLineEdit::Normal); } } void DlgConnHidWifiWpa::on_leNetName_textEdited(const QString &arg1) { if (ui->leNetName->text() == "" || ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); } else { ui->btnConnect->setEnabled(true); } } void DlgConnHidWifiWpa::on_lePassword_textEdited(const QString &arg1) { if (ui->leNetName->text() == "" || ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); } else { ui->btnConnect->setEnabled(true); } } void DlgConnHidWifiWpa::slotStartLoading() { mw->startLoading(); } void DlgConnHidWifiWpa::on_execSecConn() { QString name = strWifiname; QString pwd = strWifiPassword; QString str = "nmcli device wifi connect \"" + name.replace("\"","\\\"") + "\" password\"" + pwd.replace("\"","\\\"") + "\""; int status = system(str.toUtf8().data()); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli device wifi connect' in function 'on_execSecConn' failed");} connect(this, SIGNAL(sendMessage()), this,SLOT(emitSignal() )); QTimer::singleShot(3*1000, this, SLOT(emitSignal() )); } void DlgConnHidWifiWpa::emitSignal() { emit reSetWifiList(); mw->stopLoading(); emit this->stopSignal(); } void DlgConnHidWifiWpa::paintEvent(QPaintEvent *event) { QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); QWidget::paintEvent(event); } ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifiwep.cpp0000644000175000017500000002070514205074704024233 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see DlgConnHidWifiWep::DlgConnHidWifiWep(int type, QWidget *parent) : WepPwdOrCode(type), QDialog(parent), ui(new Ui::DlgConnHidWifiWep) { ui->setupUi(this); this->setWindowFlags(Qt::FramelessWindowHint); this->setAttribute(Qt::WA_TranslucentBackground); //需要添加 void paintEvent(QPaintEvent *event) 函数 QPainterPath path; auto rect = this->rect(); rect.adjust(1, 1, -1, -1); path.addRoundedRect(rect, 6, 6); setProperty("blurRegion", QRegion(path.toFillPolygon().toPolygon())); this->setStyleSheet("QWidget{border-radius:6px;background-color:rgba(19,19,20,0.7);border:1px solid rgba(255, 255, 255, 0.05);}"); MyQss objQss; ui->lbBoder->setStyleSheet("QLabel{border-radius:6px;background-color:rgba(19,19,20,0.95);border:1px solid rgba(255, 255, 255, 0.05);}"); ui->lbBoder->hide(); ui->lbLeftupTitle->setStyleSheet("QLabel{border:0px;font-size:20px;color:rgba(255,255,255,0.97);background-color:transparent;}"); ui->lbConn->setStyleSheet(objQss.labelQss); ui->lbNetName->setStyleSheet(objQss.labelQss); ui->lbSecurity->setStyleSheet(objQss.labelQss); ui->lbKey->setStyleSheet(objQss.labelQss); ui->lbWEPindex->setStyleSheet(objQss.labelQss); ui->lbAuth->setStyleSheet(objQss.labelQss); ui->cbxConn->setStyleSheet(objQss.cbxQss); ui->cbxConn->setView(new QListView()); ui->leNetName->setStyleSheet(objQss.leQss); ui->leKey->setStyleSheet(objQss.leQss); ui->checkBoxPwd->setStyleSheet(objQss.checkBoxQss); ui->cbxSecurity->setStyleSheet(objQss.cbxQss); ui->cbxSecurity->setView(new QListView()); ui->cbxWEPindex->setStyleSheet(objQss.cbxQss); ui->cbxWEPindex->setView(new QListView()); ui->cbxAuth->setStyleSheet(objQss.cbxQss); ui->cbxAuth->setView(new QListView()); ui->btnCancel->setStyleSheet(objQss.btnCancelQss); ui->btnConnect->setStyleSheet(objQss.btnConnQss); ui->lineUp->setStyleSheet(objQss.lineQss); ui->lineDown->setStyleSheet(objQss.lineQss); ui->lbLeftupTitle->setText(tr("Add hidden Wi-Fi")); //加入隐藏Wi-Fi ui->lbConn->setText(tr("Connection")); //连接设置: ui->lbNetName->setText(tr("Network name")); //网络名称: ui->lbSecurity->setText(tr("Wi-Fi security")); //Wi-Fi 安全性: ui->lbKey->setText(tr("Key")); //密钥: ui->lbWEPindex->setText(tr("WEP index")); //WEP 检索: ui->lbAuth->setText(tr("Authentication")); //认证: ui->btnCancel->setText(tr("Cancel")); //取消 ui->btnConnect->setText(tr("Connect")); //连接 ui->cbxConn->addItem(tr("C_reate…")); //新建... int status = system("nmcli connection show>/tmp/kylin-nm-connshow"); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection show' in function 'DlgConnHidWifiWep' failed");} QFile file("/tmp/kylin-nm-connshow"); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){ qDebug()<<"Can't open the file!"; } QString txt = file.readAll(); QStringList txtLine = txt.split("\n"); file.close(); foreach (QString line, txtLine) { if(line.indexOf("wifi") != -1){ QStringList subLine = line.split(" "); ui->cbxConn->addItem(subLine[0]); } } ui->cbxConn->setCurrentIndex(0); ui->cbxSecurity->addItem(tr("None")); //无 ui->cbxSecurity->addItem(tr("WPA & WPA2 Personal")); //WPA 及 WPA2 个人 ui->cbxSecurity->addItem(tr("WEP 40/128-bit Key (Hex or ASCII)")); //WEP 40/128 位密钥(十六进制或ASCII) ui->cbxSecurity->addItem(tr("WEP 128-bit Passphrase")); //WEP 128 位密码句 ui->cbxSecurity->addItem("LEAP"); ui->cbxSecurity->addItem(tr("Dynamic WEP (802.1X)")); //动态 WEP (802.1x) ui->cbxSecurity->addItem(tr("WPA & WPA2 Enterprise")); //WPA 及 WPA2 企业 if (WepPwdOrCode == 0) { ui->cbxSecurity->setCurrentIndex(2); } else if (WepPwdOrCode == 1) { ui->cbxSecurity->setCurrentIndex(3); } connect(ui->cbxSecurity,SIGNAL(currentIndexChanged(QString)),this,SLOT(changeDialog())); ui->cbxWEPindex->addItem(tr("1(default)")); //1(默认) ui->cbxWEPindex->addItem("2"); ui->cbxWEPindex->addItem("3"); ui->cbxWEPindex->addItem("4"); ui->cbxWEPindex->setCurrentIndex(0); ui->cbxAuth->addItem(tr("Open System")); //开放式系统 ui->cbxAuth->addItem(tr("Shared Key")); //共享密钥 ui->cbxAuth->setCurrentIndex(0); ui->btnConnect->setEnabled(false); this->setFixedSize(432,493); } DlgConnHidWifiWep::~DlgConnHidWifiWep() { delete ui; } void DlgConnHidWifiWep::mousePressEvent(QMouseEvent *event){ if(event->button() == Qt::LeftButton){ this->isPress = true; this->winPos = this->pos(); this->dragPos = event->globalPos(); event->accept(); } } void DlgConnHidWifiWep::mouseReleaseEvent(QMouseEvent *event){ this->isPress = false; } void DlgConnHidWifiWep::mouseMoveEvent(QMouseEvent *event){ if(this->isPress){ this->move(this->winPos - (this->dragPos - event->globalPos())); event->accept(); } } //切换到其他Wi-Fi安全类型 void DlgConnHidWifiWep::changeDialog() { if(ui->cbxSecurity->currentIndex()==0){ // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifi *connHidWifi = new DlgConnHidWifi(0, 0, this->parentWidget()); connHidWifi->show(); } else if(ui->cbxSecurity->currentIndex()==1) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWpa *connHidWifiWpa = new DlgConnHidWifiWpa(0, 0, this->parentWidget()); connHidWifiWpa->show(); } else if(ui->cbxSecurity->currentIndex()==2) { if (WepPwdOrCode == 1) { ui->cbxSecurity->setCurrentIndex(2); WepPwdOrCode = 0; } } else if(ui->cbxSecurity->currentIndex()==3) { if (WepPwdOrCode == 0) { ui->cbxSecurity->setCurrentIndex(3); WepPwdOrCode = 1; } } else if(ui->cbxSecurity->currentIndex()==4) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiLeap *connHidWifiLeap = new DlgConnHidWifiLeap(this->parentWidget()); connHidWifiLeap->show(); } else if(ui->cbxSecurity->currentIndex()==5) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecTls *connHidWifiSecTls = new DlgConnHidWifiSecTls(0, this->parentWidget()); connHidWifiSecTls->show(); } else { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecTls *connHidWifiSecTls = new DlgConnHidWifiSecTls(1, this->parentWidget()); connHidWifiSecTls->show(); } } void DlgConnHidWifiWep::on_btnCancel_clicked() { this->close(); } void DlgConnHidWifiWep::on_btnConnect_clicked() { this->close(); } void DlgConnHidWifiWep::on_checkBoxPwd_stateChanged(int arg1) { if (arg1 == 0) { ui->leKey->setEchoMode(QLineEdit::Password); } else { ui->leKey->setEchoMode(QLineEdit::Normal); } } void DlgConnHidWifiWep::on_leKey_textEdited(const QString &arg1) { if (ui->leNetName->text() == "" || ui->leKey->text() == ""){ ui->btnConnect->setEnabled(false); } else { ui->btnConnect->setEnabled(true); } } void DlgConnHidWifiWep::on_leNetName_textEdited(const QString &arg1) { if (ui->leNetName->text() == "" || ui->leKey->text() == ""){ ui->btnConnect->setEnabled(false); } else { ui->btnConnect->setEnabled(true); } } void DlgConnHidWifiWep::paintEvent(QPaintEvent *event) { QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); QWidget::paintEvent(event); } ukui-screensaver/KylinNM/wireless-security/kylinheadfile.h0000644000175000017500000000255414205074704023006 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include #include #include #include class MyQss { public: MyQss(); QString labelQss, cbxQss, leQss, btnConnQss, btnCancelQss, lineQss, checkBoxQss, checkBoxCAQss; }; #endif // KYLINHEADFILE_H ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifiwpa.h0000644000175000017500000000445014205074704023673 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include #include class KylinNM; namespace Ui { class DlgConnHidWifiWpa; } class DlgConnHidWifiWpa : public QDialog { Q_OBJECT public: explicit DlgConnHidWifiWpa(int type, KylinNM *mw = 0, QWidget *parent = 0); ~DlgConnHidWifiWpa(); protected: void paintEvent(QPaintEvent *event); /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---START---- ** 手动绑定下拉框视图和下拉框 过滤点击事件 **/ bool eventFilter(QObject *obj, QEvent *ev) override; public slots: void changeDialog(); void changeWindow(); void emitSignal(); void on_execSecConn(); void slotStartLoading(); private slots: void on_btnCancel_clicked(); void on_btnConnect_clicked(); void on_checkBoxPwd_stateChanged(int arg1); void on_leNetName_textEdited(const QString &arg1); void on_lePassword_textEdited(const QString &arg1); signals: void reSetWifiList(); void sendMessage(); void execSecConn(); void stopSignal(); private: Ui::DlgConnHidWifiWpa *ui; int isUsed;//=0 current wifi not used before; >=1 used KylinNM *mw; QString strWifiname; QString strWifiPassword; void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); // QString labelQss, cbxQss, leQss, btnConnQss, btnCancelQss, lineQss, checkBoxQss; bool isPress; QPoint winPos; QPoint dragPos; }; #endif // DLGCONNHIDWIFIWPA_H ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifisecleap.h0000644000175000017500000000410714205074704024517 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include namespace Ui { class DlgConnHidWifiSecLeap; } class DlgConnHidWifiSecLeap : public QDialog { Q_OBJECT public: explicit DlgConnHidWifiSecLeap(int type, QWidget *parent = 0); ~DlgConnHidWifiSecLeap(); protected: void paintEvent(QPaintEvent *event); /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---START---- ** 手动绑定下拉框视图和下拉框 过滤点击事件 **/ bool eventFilter(QObject *obj, QEvent *ev) override; public slots: void changeDialogSecu(); void changeDialogAuth(); private slots: void on_btnCancel_clicked(); void on_btnConnect_clicked(); void on_checkBox_stateChanged(int arg1); void on_leNetName_textEdited(const QString &arg1); void on_leUserName_textEdited(const QString &arg1); void on_lePassword_textEdited(const QString &arg1); private: Ui::DlgConnHidWifiSecLeap *ui; int WepOrWpa = 0;//0 WEP;1WPA void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); // QString labelQss, cbxQss, leQss, btnConnQss, btnCancelQss, lineQss, checkBoxQss, checkBoxCAQss; bool isPress; QPoint winPos; QPoint dragPos; }; #endif // DLGCONNHIDWIFISECLEAP_H ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifisecpeap.h0000644000175000017500000000424214205074704024523 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include namespace Ui { class DlgConnHidWifiSecPeap; } class DlgConnHidWifiSecPeap : public QDialog { Q_OBJECT public: explicit DlgConnHidWifiSecPeap(int type, QWidget *parent = 0); ~DlgConnHidWifiSecPeap(); protected: void paintEvent(QPaintEvent *event); public slots: void changeDialogSecu(); void changeDialogAuth(); private slots: void on_btnCancel_clicked(); void on_btnConnect_clicked(); void on_cbxCA_currentIndexChanged(const QString &arg1); void on_checkBoxPwd_stateChanged(int arg1); void on_checkBoxCA_stateChanged(int arg1); void on_checkBoxPwdSec_stateChanged(int arg1); void on_leNetName_textEdited(const QString &arg1); void on_leAnonyId_textEdited(const QString &arg1); void on_leDomain_textEdited(const QString &arg1); void on_leCaPwd_textEdited(const QString &arg1); void on_leUserName_textEdited(const QString &arg1); void on_lePassword_textEdited(const QString &arg1); private: Ui::DlgConnHidWifiSecPeap *ui; int WepOrWpa = 0;//0 WEP;1WPA void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); // QString labelQss, cbxQss, leQss, btnConnQss, btnCancelQss, lineQss, checkBoxQss, checkBoxCAQss; bool isPress; QPoint winPos; QPoint dragPos; }; #endif // DLGCONNHIDWIFISECPEAP_H ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifisecleap.ui0000644000175000017500000001625614205074704024715 0ustar fengfeng DlgConnHidWifiSecLeap 0 0 432 487 Connect to Hidden Wi-Fi Network 175 215 182 32 10 175 350 182 32 10 QLineEdit::Password 332 362 18 9 10 76 176 90 20 10 76 221 90 20 10 175 305 182 32 10 315 440 90 30 10 175 75 182 32 10 76 311 90 20 10 215 440 90 30 10 175 260 182 32 10 76 266 90 20 10 175 170 182 32 10 76 356 90 20 10 76 80 90 20 10 30 30 140 22 0 0 432 487 10 140 412 1 Qt::Horizontal 10 410 412 1 Qt::Horizontal lbBoder cbxSecurity lePassword checkBox lbNetName lbSecurity leUserName btnConnect cbxConn lbUserName btnCancel cbxAuth lbAuth leNetName lbPassword lbConn lbLeftupTitle lineUp lineDown ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifisecpeap.cpp0000644000175000017500000004111614205074704025057 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see DlgConnHidWifiSecPeap::DlgConnHidWifiSecPeap(int type, QWidget *parent) : WepOrWpa(type), QDialog(parent), ui(new Ui::DlgConnHidWifiSecPeap) { ui->setupUi(this); this->setWindowFlags(Qt::FramelessWindowHint); this->setAttribute(Qt::WA_TranslucentBackground); //需要添加 void paintEvent(QPaintEvent *event) 函数 QPainterPath path; auto rect = this->rect(); rect.adjust(1, 1, -1, -1); path.addRoundedRect(rect, 6, 6); setProperty("blurRegion", QRegion(path.toFillPolygon().toPolygon())); this->setStyleSheet("QWidget{border-radius:6px;background-color:rgba(19,19,20,0.7);border:1px solid rgba(255, 255, 255, 0.05);}"); MyQss objQss; ui->lbBoder->setStyleSheet("QLabel{border-radius:6px;background-color:rgba(19,19,20,0.95);border:1px solid rgba(255, 255, 255, 0.05);}"); ui->lbBoder->hide(); ui->lbLeftupTitle->setStyleSheet("QLabel{border:0px;font-size:20px;color:rgba(255,255,255,0.97);background-color:transparent;}"); ui->lbConn->setStyleSheet(objQss.labelQss); ui->lbNetName->setStyleSheet(objQss.labelQss); ui->lbSecurity->setStyleSheet(objQss.labelQss); ui->lbAuth->setStyleSheet(objQss.labelQss); ui->lbAnonyId->setStyleSheet(objQss.labelQss); ui->lbDomain->setStyleSheet(objQss.labelQss); ui->lbCA->setStyleSheet(objQss.labelQss); ui->lbCaPwd->setStyleSheet(objQss.labelQss); ui->lbPEAPver->setStyleSheet(objQss.labelQss); ui->lbInnerAuth->setStyleSheet(objQss.labelQss); ui->lbUserName->setStyleSheet(objQss.labelQss); ui->lbPassword->setStyleSheet(objQss.labelQss); ui->cbxConn->setStyleSheet(objQss.cbxQss); ui->cbxConn->setView(new QListView()); ui->leNetName->setStyleSheet(objQss.leQss); ui->cbxSecurity->setStyleSheet(objQss.cbxQss); ui->cbxSecurity->setView(new QListView()); ui->cbxAuth->setStyleSheet(objQss.cbxQss); ui->cbxAuth->setView(new QListView()); ui->leAnonyId->setStyleSheet(objQss.leQss); ui->leDomain->setStyleSheet(objQss.leQss); ui->cbxCA->setStyleSheet(objQss.cbxQss); ui->cbxCA->setView(new QListView()); ui->leCaPwd->setStyleSheet(objQss.leQss); ui->checkBoxPwd->setStyleSheet(objQss.checkBoxQss); ui->checkBoxCA->setStyleSheet(objQss.checkBoxCAQss); ui->cbxPEAPver->setStyleSheet(objQss.cbxQss); ui->cbxPEAPver->setView(new QListView()); ui->cbxInnerAuth->setStyleSheet(objQss.cbxQss); ui->cbxInnerAuth->setView(new QListView()); ui->leUserName->setStyleSheet(objQss.leQss); ui->lePassword->setStyleSheet(objQss.leQss); ui->checkBoxPwdSec->setStyleSheet(objQss.checkBoxQss); ui->btnCancel->setStyleSheet(objQss.btnCancelQss); ui->btnConnect->setStyleSheet(objQss.btnConnQss); ui->lineUp->setStyleSheet(objQss.lineQss); ui->lineDown->setStyleSheet(objQss.lineQss); ui->lbLeftupTitle->setText(tr("Add hidden Wi-Fi")); //加入隐藏Wi-Fi ui->lbConn->setText(tr("Connection")); //连接设置: ui->lbNetName->setText(tr("Network name")); //网络名称: ui->lbSecurity->setText(tr("Wi-Fi security")); //Wi-Fi安全性: ui->lbAuth->setText(tr("Authentication")); //认证: ui->lbAnonyId->setText(tr("Anonymous identity")); //匿名身份: ui->lbDomain->setText(tr("Domain")); //域名: ui->lbCA->setText(tr("CA certificate")); //CA 证书: ui->lbCaPwd->setText(tr("CA certificate password")); //CA 证书密码: ui->checkBoxCA->setText(tr("No CA certificate is required")); //不需要CA证书 ui->lbPEAPver->setText(tr("PEAP version")); //PEAP版本: ui->lbInnerAuth->setText(tr("Inner authentication")); //内部认证: ui->lbUserName->setText(tr("Username")); //用户名: ui->lbPassword->setText(tr("Password")); //密码: ui->btnCancel->setText(tr("Cancel")); //取消 ui->btnConnect->setText(tr("Connect")); //连接 ui->cbxConn->addItem("新建..."); int status = system("nmcli connection show>/tmp/kylin-nm-connshow"); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection show' in function 'DlgConnHidWifiSecPeap' failed");} QFile file("/tmp/kylin-nm-connshow"); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){ qDebug()<<"Can't open the file!"; } QString txt = file.readAll(); QStringList txtLine = txt.split("\n"); file.close(); foreach (QString line, txtLine) { if(line.indexOf("wifi") != -1){ QStringList subLine = line.split(" "); ui->cbxConn->addItem(subLine[0]); } } ui->cbxConn->setCurrentIndex(0); ui->cbxSecurity->addItem(tr("None")); //无 ui->cbxSecurity->addItem(tr("WPA & WPA2 Personal")); //WPA 及 WPA2 个人 ui->cbxSecurity->addItem(tr("WEP 40/128-bit Key (Hex or ASCII)")); //WEP 40/128 位密钥(十六进制或ASCII) ui->cbxSecurity->addItem(tr("WEP 128-bit Passphrase")); //WEP 128 位密码句 ui->cbxSecurity->addItem("LEAP"); ui->cbxSecurity->addItem(tr("Dynamic WEP (802.1X)")); //动态 WEP (802.1x) ui->cbxSecurity->addItem(tr("WPA & WPA2 Enterprise")); //WPA 及 WPA2 企业 if (WepOrWpa == 0) { ui->cbxSecurity->setCurrentIndex(5); } else if (WepOrWpa == 1) { ui->cbxSecurity->setCurrentIndex(6); } connect(ui->cbxSecurity,SIGNAL(currentIndexChanged(QString)),this,SLOT(changeDialogSecu())); ui->cbxAuth->addItem("TLS"); ui->cbxAuth->addItem("LEAP"); ui->cbxAuth->addItem("PWD"); ui->cbxAuth->addItem("FAST"); ui->cbxAuth->addItem(tr("Tunneled TLS"));//隧道 TLS ui->cbxAuth->addItem(tr("Protected EAP (PEAP)")); //受保护的 EAP ui->cbxAuth->setCurrentIndex(5); connect(ui->cbxAuth,SIGNAL(currentIndexChanged(QString)),this,SLOT(changeDialogAuth())); ui->cbxCA->addItem(tr("None")); //无 ui->cbxCA->addItem(tr("Choose from file")); //从文件选择... ui->cbxCA->setCurrentIndex(0); ui->cbxPEAPver->addItem(tr("Automatic")); //自动 ui->cbxPEAPver->addItem(tr("Version 0")); //版本 0 ui->cbxPEAPver->addItem(tr("Version 1")); //版本 1 ui->cbxPEAPver->setCurrentIndex(0); ui->cbxInnerAuth->addItem("MSCHAPv2"); ui->cbxInnerAuth->addItem("MDS"); ui->cbxInnerAuth->addItem("GTC"); ui->cbxInnerAuth->setCurrentIndex(0); ui->btnConnect->setEnabled(false); this->setFixedSize(432,700); } DlgConnHidWifiSecPeap::~DlgConnHidWifiSecPeap() { delete ui; } void DlgConnHidWifiSecPeap::mousePressEvent(QMouseEvent *event){ if(event->button() == Qt::LeftButton){ this->isPress = true; this->winPos = this->pos(); this->dragPos = event->globalPos(); event->accept(); } } void DlgConnHidWifiSecPeap::mouseReleaseEvent(QMouseEvent *event){ this->isPress = false; } void DlgConnHidWifiSecPeap::mouseMoveEvent(QMouseEvent *event){ if(this->isPress){ this->move(this->winPos - (this->dragPos - event->globalPos())); event->accept(); } } void DlgConnHidWifiSecPeap::changeDialogSecu() { if(ui->cbxSecurity->currentIndex()==0){ // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifi *connHidWifi = new DlgConnHidWifi(0, 0,this->parentWidget()); connHidWifi->show(); } else if(ui->cbxSecurity->currentIndex()==1) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWpa *connHidWifiWpa = new DlgConnHidWifiWpa(0, 0, this->parentWidget()); connHidWifiWpa->show(); } else if(ui->cbxSecurity->currentIndex()==2) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWep *connHidWifiWep = new DlgConnHidWifiWep(0, this->parentWidget()); connHidWifiWep->show(); } else if(ui->cbxSecurity->currentIndex()==3) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWep *connHidWifiWep = new DlgConnHidWifiWep(1, this->parentWidget()); connHidWifiWep->show(); } else if(ui->cbxSecurity->currentIndex()==4) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiLeap *connHidWifiLeap = new DlgConnHidWifiLeap(this->parentWidget()); connHidWifiLeap->show(); } else if(ui->cbxSecurity->currentIndex()==5) { if (WepOrWpa == 1) { ui->cbxSecurity->setCurrentIndex(5); WepOrWpa = 0; } } else { if (WepOrWpa == 0){ ui->cbxSecurity->setCurrentIndex(6); WepOrWpa = 1; } } } void DlgConnHidWifiSecPeap::changeDialogAuth() { if(ui->cbxAuth->currentIndex()==0){ // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecTls *connHidWifiSecTls = new DlgConnHidWifiSecTls(WepOrWpa, this->parentWidget()); connHidWifiSecTls->show(); } else if(ui->cbxAuth->currentIndex()==1) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecLeap *connHidWifiSecLeap = new DlgConnHidWifiSecLeap(WepOrWpa, this->parentWidget()); connHidWifiSecLeap->show(); } else if(ui->cbxAuth->currentIndex()==2) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecPwd *connHidWifiSecPwd = new DlgConnHidWifiSecPwd(WepOrWpa); connHidWifiSecPwd->show(); } else if(ui->cbxAuth->currentIndex()==3) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecFast *connHidWifiSecFast = new DlgConnHidWifiSecFast(WepOrWpa); connHidWifiSecFast->show(); } else if(ui->cbxAuth->currentIndex()==4) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecTunnelTLS *connHidWifiSecTuTls = new DlgConnHidWifiSecTunnelTLS(WepOrWpa); connHidWifiSecTuTls->show(); } else { qDebug()<<"it's not need to change dialog"; } } void DlgConnHidWifiSecPeap::on_cbxCA_currentIndexChanged(const QString &arg1) { if (ui->cbxCA->currentIndex() == 0){ ui->leCaPwd->setText(""); ui->lbCaPwd->setEnabled(false); ui->leCaPwd->setEnabled(false); } else { ui->leCaPwd->setText(""); ui->lbCaPwd->setEnabled(true); ui->leCaPwd->setEnabled(true); } } void DlgConnHidWifiSecPeap::on_btnCancel_clicked() { this->close(); } void DlgConnHidWifiSecPeap::on_btnConnect_clicked() { this->close(); } void DlgConnHidWifiSecPeap::on_checkBoxPwd_stateChanged(int arg1) { if (arg1 == 0) { ui->leCaPwd->setEchoMode(QLineEdit::Password); } else { ui->leCaPwd->setEchoMode(QLineEdit::Normal); } } void DlgConnHidWifiSecPeap::on_checkBoxCA_stateChanged(int arg1) { if (arg1 == 0) { ui->cbxCA->setCurrentIndex(0); ui->leCaPwd->setText(""); ui->lbCA->setEnabled(true); ui->cbxCA->setEnabled(true); } else { ui->cbxCA->setCurrentIndex(0); ui->leCaPwd->setText(""); ui->lbCA->setEnabled(false); ui->cbxCA->setEnabled(false); } } void DlgConnHidWifiSecPeap::on_checkBoxPwdSec_stateChanged(int arg1) { if (arg1 == 0) { ui->lePassword->setEchoMode(QLineEdit::Password); } else { ui->lePassword->setEchoMode(QLineEdit::Normal); } } void DlgConnHidWifiSecPeap::on_leNetName_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leAnonyId->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leDomain->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); }else{ if (ui->cbxCA->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else if(ui->leCaPwd->text() == ""){ ui->btnConnect->setEnabled(false); }else{ ui->btnConnect->setEnabled(true); } } } void DlgConnHidWifiSecPeap::on_leAnonyId_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leAnonyId->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leDomain->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); }else{ if (ui->cbxCA->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else if(ui->leCaPwd->text() == ""){ ui->btnConnect->setEnabled(false); }else{ ui->btnConnect->setEnabled(true); } } } void DlgConnHidWifiSecPeap::on_leDomain_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leAnonyId->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leDomain->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); }else{ if (ui->cbxCA->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else if(ui->leCaPwd->text() == ""){ ui->btnConnect->setEnabled(false); }else{ ui->btnConnect->setEnabled(true); } } } void DlgConnHidWifiSecPeap::on_leCaPwd_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leAnonyId->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leDomain->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leCaPwd->text() == ""){ ui->btnConnect->setEnabled(false); }else{ ui->btnConnect->setEnabled(true); } } void DlgConnHidWifiSecPeap::on_leUserName_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leAnonyId->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leDomain->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); }else{ if (ui->cbxCA->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else if(ui->leCaPwd->text() == ""){ ui->btnConnect->setEnabled(false); }else{ ui->btnConnect->setEnabled(true); } } } void DlgConnHidWifiSecPeap::on_lePassword_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leAnonyId->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leDomain->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leUserName->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->lePassword->text() == ""){ ui->btnConnect->setEnabled(false); }else{ if (ui->cbxCA->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else if(ui->leCaPwd->text() == ""){ ui->btnConnect->setEnabled(false); }else{ ui->btnConnect->setEnabled(true); } } } void DlgConnHidWifiSecPeap::paintEvent(QPaintEvent *event) { QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); QWidget::paintEvent(event); } ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifisecfast.h0000644000175000017500000000425014205074704024532 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include namespace Ui { class DlgConnHidWifiSecFast; } class DlgConnHidWifiSecFast : public QDialog { Q_OBJECT public: explicit DlgConnHidWifiSecFast(int type, QWidget *parent = 0); ~DlgConnHidWifiSecFast(); protected: void paintEvent(QPaintEvent *event); /**解决锁屏设置 X11BypassWindowManagerHint 属性导致QCombox弹框异常的问题---START---- ** 手动绑定下拉框视图和下拉框 过滤点击事件 **/ bool eventFilter(QObject *obj, QEvent *ev) override; public slots: void changeDialogSecu(); void changeDialogAuth(); private slots: void on_btnCancel_clicked(); void on_btnConnect_clicked(); void on_checkBoxAutoPCA_stateChanged(int arg1); void on_checkBoxPwd_stateChanged(int arg1); void on_leNetName_textEdited(const QString &arg1); void on_leAnonyId_textEdited(const QString &arg1); void on_leUserName_textEdited(const QString &arg1); void on_lePassword_textEdited(const QString &arg1); private: Ui::DlgConnHidWifiSecFast *ui; int WepOrWpa = 0;//0 WEP;1WPA void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); // QString labelQss, cbxQss, leQss, btnConnQss, btnCancelQss, lineQss, checkBoxQss; bool isPress; QPoint winPos; QPoint dragPos; }; #endif // DLGCONNHIDWIFISECFAST_H ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifisectls.cpp0000644000175000017500000005622714205074704024745 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see DlgConnHidWifiSecTls::DlgConnHidWifiSecTls(int type, QWidget *parent) : WepOrWpa(type), QDialog(parent), ui(new Ui::DlgConnHidWifiSecTls) { ui->setupUi(this); this->setWindowFlags(Qt::FramelessWindowHint); this->setAttribute(Qt::WA_TranslucentBackground); //需要添加 void paintEvent(QPaintEvent *event) 函数 QPainterPath path; auto rect = this->rect(); rect.adjust(1, 1, -1, -1); path.addRoundedRect(rect, 6, 6); setProperty("blurRegion", QRegion(path.toFillPolygon().toPolygon())); this->setStyleSheet("QWidget{border-radius:6px;background-color:rgba(19,19,20,0.7);border:1px solid rgba(255, 255, 255, 0.05);}"); MyQss objQss; ui->lbBoder->setStyleSheet("QLabel{border-radius:6px;background-color:rgba(19,19,20,0.95);border:1px solid rgba(255, 255, 255, 0.05);}"); ui->lbBoder->hide(); ui->lbLeftupTitle->setStyleSheet("QLabel{border:0px;font-size:20px;color:rgba(255,255,255,0.97);background-color:transparent;}"); ui->lbConn->setStyleSheet(objQss.labelQss); ui->lbNetName->setStyleSheet(objQss.labelQss); ui->lbSecurity->setStyleSheet(objQss.labelQss); ui->lbAuth->setStyleSheet(objQss.labelQss); ui->lbIdentity->setStyleSheet(objQss.labelQss); ui->lbDomain->setStyleSheet(objQss.labelQss); ui->lbCA->setStyleSheet(objQss.labelQss); ui->lbCaPwd->setStyleSheet(objQss.labelQss); ui->lbUserCertify->setStyleSheet(objQss.labelQss); ui->lbUserCertifyPwd->setStyleSheet(objQss.labelQss); ui->lbUserPriKey->setStyleSheet(objQss.labelQss); ui->lbUserKeyPwd->setStyleSheet(objQss.labelQss); ui->cbxConn->setStyleSheet(objQss.cbxQss); ui->cbxConn->setView(new QListView()); ui->leNetName->setStyleSheet(objQss.leQss); ui->cbxSecurity->setStyleSheet(objQss.cbxQss); ui->cbxSecurity->setView(new QListView()); ui->cbxAuth->setStyleSheet(objQss.cbxQss); ui->cbxAuth->setView(new QListView()); ui->leIdentity->setStyleSheet(objQss.leQss); ui->leDomain->setStyleSheet(objQss.leQss); ui->cbxCA->setStyleSheet(objQss.cbxQss); ui->cbxCA->setView(new QListView()); ui->leCaPwd->setStyleSheet(objQss.leQss); ui->checkBoxPwd->setStyleSheet(objQss.checkBoxQss); ui->checkBoxCA->setStyleSheet(objQss.checkBoxCAQss); ui->cbxUserCertify->setStyleSheet(objQss.cbxQss); ui->cbxUserCertify->setView(new QListView()); ui->leUserCertifyPwd->setStyleSheet(objQss.leQss); ui->cbxUserPriKey->setStyleSheet(objQss.cbxQss); ui->cbxUserPriKey->setView(new QListView()); ui->leUserKeyPwd->setStyleSheet(objQss.leQss); ui->checkBoxPwdSec->setStyleSheet(objQss.checkBoxQss); ui->btnCancel->setStyleSheet(objQss.btnCancelQss); ui->btnConnect->setStyleSheet(objQss.btnCancelQss); ui->lineUp->setStyleSheet(objQss.lineQss); ui->lineDown->setStyleSheet(objQss.lineQss); ui->checkBoxCA->setFocusPolicy(Qt::NoFocus); ui->lbLeftupTitle->setText(tr("Add hidden Wi-Fi")); //加入隐藏Wi-Fi ui->lbConn->setText(tr("Connection")); //连接设置: ui->lbNetName->setText(tr("Network name")); //网络名称: ui->lbSecurity->setText(tr("Wi-Fi security")); //Wi-Fi安全性: ui->lbAuth->setText(tr("Authentication")); //认证: ui->lbIdentity->setText(tr("Identity")); //身份: ui->lbDomain->setText(tr("Domain")); //域名: ui->lbCA->setText(tr("CA certificate")); //CA 证书: ui->lbCaPwd->setText(tr("CA certificate password")); //CA 证书密码: ui->checkBoxCA->setText(tr("No CA certificate is required")); //不需要CA证书 ui->lbUserCertify->setText(tr("User certificate")); //用户证书: ui->lbUserCertifyPwd->setText(tr("User certificate password")); //用户证书密码: ui->lbUserPriKey->setText(tr("User private key")); //用户私钥: ui->lbUserKeyPwd->setText(tr("User key password")); //用户密钥密码: ui->btnCancel->setText(tr("Cancel")); //取消 ui->btnConnect->setText(tr("Connect")); //连接 ui->cbxConn->addItem(tr("C_reate…")); //新建... int status = system("nmcli connection show>/tmp/kylin-nm-connshow"); if (status != 0){ syslog(LOG_ERR, "execute 'nmcli connection show' in function 'DlgConnHidWifiSecTls' failed");} QFile file("/tmp/kylin-nm-connshow"); if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){ qDebug()<<"Can't open the file!"; } QString txt = file.readAll(); QStringList txtLine = txt.split("\n"); file.close(); foreach (QString line, txtLine) { if(line.indexOf("wifi") != -1){ QStringList subLine = line.split(" "); ui->cbxConn->addItem(subLine[0]); } } ui->cbxConn->setCurrentIndex(0); ui->cbxSecurity->addItem(tr("None")); //无 ui->cbxSecurity->addItem(tr("WPA & WPA2 Personal")); //WPA 及 WPA2 个人 ui->cbxSecurity->addItem(tr("WEP 40/128-bit Key (Hex or ASCII)")); //WEP 40/128 位密钥(十六进制或ASCII) ui->cbxSecurity->addItem(tr("WEP 128-bit Passphrase")); //WEP 128 位密码句 ui->cbxSecurity->addItem("LEAP"); ui->cbxSecurity->addItem(tr("Dynamic WEP (802.1X)")); //动态 WEP (802.1x) ui->cbxSecurity->addItem(tr("WPA & WPA2 Enterprise")); //WPA 及 WPA2 企业 if (WepOrWpa == 0) { ui->cbxSecurity->setCurrentIndex(5); } else if (WepOrWpa == 1) { ui->cbxSecurity->setCurrentIndex(6); } connect(ui->cbxSecurity,SIGNAL(currentIndexChanged(QString)),this,SLOT(changeDialogSecu())); ui->cbxAuth->addItem("TLS"); ui->cbxAuth->addItem("LEAP"); ui->cbxAuth->addItem("PWD"); ui->cbxAuth->addItem("FAST"); ui->cbxAuth->addItem(tr("Tunneled TLS"));//隧道 TLS ui->cbxAuth->addItem(tr("Protected EAP (PEAP)")); //受保护的 EAP ui->cbxAuth->setCurrentIndex(0); connect(ui->cbxAuth,SIGNAL(currentIndexChanged(QString)),this,SLOT(changeDialogAuth())); ui->cbxCA->addItem(tr("None")); //无 ui->cbxCA->addItem(tr("Choose from file")); //从文件选择... ui->cbxCA->setCurrentIndex(0); ui->cbxUserCertify->addItem(tr("None")); //无 ui->cbxUserCertify->addItem(tr("Choose from file")); //从文件选择... ui->cbxUserCertify->setCurrentIndex(0); ui->cbxUserPriKey->addItem(tr("None")); //无 ui->cbxUserPriKey->addItem(tr("Choose from file")); //从文件选择... ui->cbxUserPriKey->setCurrentIndex(0); ui->btnConnect->setEnabled(false); ui->lbCaPwd->setEnabled(false); ui->leCaPwd->setEnabled(false); ui->lbUserCertifyPwd->setEnabled(false); ui->leUserCertifyPwd->setEnabled(false); ui->lbUserPriKey->setEnabled(false); ui->cbxUserPriKey->setEnabled(false); ui->lbUserKeyPwd->setEnabled(false); ui->leUserKeyPwd->setEnabled(false); this->setFixedSize(432,705); } DlgConnHidWifiSecTls::~DlgConnHidWifiSecTls() { delete ui; } void DlgConnHidWifiSecTls::mousePressEvent(QMouseEvent *event){ if(event->button() == Qt::LeftButton){ this->isPress = true; this->winPos = this->pos(); this->dragPos = event->globalPos(); event->accept(); } } void DlgConnHidWifiSecTls::mouseReleaseEvent(QMouseEvent *event){ this->isPress = false; } void DlgConnHidWifiSecTls::mouseMoveEvent(QMouseEvent *event){ if(this->isPress){ this->move(this->winPos - (this->dragPos - event->globalPos())); event->accept(); } } void DlgConnHidWifiSecTls::changeDialogSecu() { if(ui->cbxSecurity->currentIndex()==0){ // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifi *connHidWifi = new DlgConnHidWifi(0, 0, this->parentWidget()); connHidWifi->show(); } else if(ui->cbxSecurity->currentIndex()==1) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWpa *connHidWifiWpa = new DlgConnHidWifiWpa(0, 0, this->parentWidget()); connHidWifiWpa->show(); } else if(ui->cbxSecurity->currentIndex()==2) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWep *connHidWifiWep = new DlgConnHidWifiWep(0, this->parentWidget()); connHidWifiWep->show(); } else if(ui->cbxSecurity->currentIndex()==3) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiWep *connHidWifiWep = new DlgConnHidWifiWep(1, this->parentWidget()); connHidWifiWep->show(); } else if(ui->cbxSecurity->currentIndex()==4) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiLeap *connHidWifiLeap = new DlgConnHidWifiLeap(this->parentWidget()); connHidWifiLeap->show(); } else if(ui->cbxSecurity->currentIndex()==5) { if (WepOrWpa == 1) { ui->cbxSecurity->setCurrentIndex(5); WepOrWpa = 0; } } else { if (WepOrWpa == 0){ ui->cbxSecurity->setCurrentIndex(6); WepOrWpa = 1; } } } void DlgConnHidWifiSecTls::changeDialogAuth() { if(ui->cbxAuth->currentIndex()==0){ qDebug()<<"it's not need to change dialog"; } else if(ui->cbxAuth->currentIndex()==1) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecLeap *connHidWifiSecLeap = new DlgConnHidWifiSecLeap(WepOrWpa); connHidWifiSecLeap->show(); } else if(ui->cbxAuth->currentIndex()==2) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecPwd *connHidWifiSecPwd = new DlgConnHidWifiSecPwd(WepOrWpa); connHidWifiSecPwd->show(); } else if(ui->cbxAuth->currentIndex()==3) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecFast *connHidWifiSecFast = new DlgConnHidWifiSecFast(WepOrWpa); connHidWifiSecFast->show(); } else if(ui->cbxAuth->currentIndex()==4) { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecTunnelTLS *connHidWifiSecTuTls = new DlgConnHidWifiSecTunnelTLS(WepOrWpa); connHidWifiSecTuTls->show(); } else { // QApplication::setQuitOnLastWindowClosed(false); this->hide(); DlgConnHidWifiSecPeap *connHidWifiSecPeap = new DlgConnHidWifiSecPeap(WepOrWpa); connHidWifiSecPeap->show(); } } void DlgConnHidWifiSecTls::on_cbxCA_currentIndexChanged(const QString &arg1) { if (ui->cbxCA->currentIndex() == 0){ ui->leCaPwd->setText(""); ui->lbCaPwd->setEnabled(false); ui->leCaPwd->setEnabled(false); }else{ ui->leCaPwd->setText(""); ui->lbCaPwd->setEnabled(true); ui->leCaPwd->setEnabled(true); } } void DlgConnHidWifiSecTls::on_cbxUserCertify_currentIndexChanged(const QString &arg1) { if (ui->cbxUserCertify->currentIndex() == 0){ ui->leUserCertifyPwd->setText(""); ui->lbUserCertifyPwd->setEnabled(false); ui->leUserCertifyPwd->setEnabled(false); ui->lbUserPriKey->setEnabled(false); ui->cbxUserPriKey->setEnabled(false); ui->cbxUserPriKey->setCurrentIndex(0); ui->leUserKeyPwd->setText(""); ui->lbUserKeyPwd->setEnabled(false); ui->leUserKeyPwd->setEnabled(false); }else{ ui->leUserCertifyPwd->setText(""); ui->lbUserCertifyPwd->setEnabled(true); ui->leUserCertifyPwd->setEnabled(true); ui->lbUserPriKey->setEnabled(true); ui->cbxUserPriKey->setEnabled(true); ui->cbxUserPriKey->setCurrentIndex(0); ui->leUserKeyPwd->setText(""); ui->lbUserKeyPwd->setEnabled(false); ui->leUserKeyPwd->setEnabled(false); } } void DlgConnHidWifiSecTls::on_cbxUserPriKey_currentIndexChanged(const QString &arg1) { if (ui->cbxUserPriKey->currentIndex() == 0){ ui->leUserKeyPwd->setText(""); ui->lbUserKeyPwd->setEnabled(false); ui->leUserKeyPwd->setEnabled(false); }else{ ui->leUserKeyPwd->setText(""); ui->lbUserKeyPwd->setEnabled(true); ui->leUserKeyPwd->setEnabled(true); } } void DlgConnHidWifiSecTls::on_btnCancel_clicked() { this->close(); } void DlgConnHidWifiSecTls::on_btnConnect_clicked() { this->close(); } void DlgConnHidWifiSecTls::on_checkBoxCA_stateChanged(int arg1) { if (arg1 == 0) { ui->cbxCA->setCurrentIndex(0); ui->lbCA->setEnabled(true); ui->cbxCA->setEnabled(true); } else { ui->cbxCA->setCurrentIndex(0); ui->lbCA->setEnabled(false); ui->cbxCA->setEnabled(false); } } void DlgConnHidWifiSecTls::on_checkBoxPwd_stateChanged(int arg1) { if (arg1 == 0) { ui->leCaPwd->setEchoMode(QLineEdit::Password); } else { ui->leCaPwd->setEchoMode(QLineEdit::Normal); } } void DlgConnHidWifiSecTls::on_checkBoxPwdSec_stateChanged(int arg1) { if (arg1 == 0) { ui->leUserCertifyPwd->setEchoMode(QLineEdit::Password); ui->leUserKeyPwd->setEchoMode(QLineEdit::Password); } else { ui->leUserCertifyPwd->setEchoMode(QLineEdit::Normal); ui->leUserKeyPwd->setEchoMode(QLineEdit::Normal); } } void DlgConnHidWifiSecTls::on_leNetName_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leIdentity->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leDomain->text() == ""){ ui->btnConnect->setEnabled(false); } else { if (ui->cbxCA->currentIndex() == 0){ if (ui->cbxUserCertify->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else { if (ui->leUserCertifyPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else { if (ui->cbxUserPriKey->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else if (ui->leUserKeyPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else{ ui->btnConnect->setEnabled(true); } } } } else { if (ui->leCaPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else { if (ui->cbxUserCertify->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else { if (ui->leUserCertifyPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else { if (ui->cbxUserPriKey->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else if (ui->leUserKeyPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else{ ui->btnConnect->setEnabled(true); } } } } } } } void DlgConnHidWifiSecTls::on_leIdentity_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leIdentity->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leDomain->text() == ""){ ui->btnConnect->setEnabled(false); } else { if (ui->cbxCA->currentIndex() == 0){ if (ui->cbxUserCertify->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else { if (ui->leUserCertifyPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else { if (ui->cbxUserPriKey->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else if (ui->leUserKeyPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else{ ui->btnConnect->setEnabled(true); } } } } else { if (ui->leCaPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else { if (ui->cbxUserCertify->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else { if (ui->leUserCertifyPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else { if (ui->cbxUserPriKey->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else if (ui->leUserKeyPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else{ ui->btnConnect->setEnabled(true); } } } } } } } void DlgConnHidWifiSecTls::on_leDomain_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leIdentity->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leDomain->text() == ""){ ui->btnConnect->setEnabled(false); } else { if (ui->cbxCA->currentIndex() == 0){ if (ui->cbxUserCertify->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else { if (ui->leUserCertifyPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else { if (ui->cbxUserPriKey->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else if (ui->leUserKeyPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else{ ui->btnConnect->setEnabled(true); } } } } else { if (ui->leCaPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else { if (ui->cbxUserCertify->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else { if (ui->leUserCertifyPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else { if (ui->cbxUserPriKey->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else if (ui->leUserKeyPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else{ ui->btnConnect->setEnabled(true); } } } } } } } void DlgConnHidWifiSecTls::on_leCaPwd_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leIdentity->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leDomain->text() == ""){ ui->btnConnect->setEnabled(false); } else if(ui->leCaPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else { if (ui->cbxUserCertify->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else { if (ui->leUserCertifyPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else { if (ui->cbxUserPriKey->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else if (ui->leUserKeyPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else{ ui->btnConnect->setEnabled(true); } } } } } void DlgConnHidWifiSecTls::on_leUserCertifyPwd_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leIdentity->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leDomain->text() == ""){ ui->btnConnect->setEnabled(false); } else { if (ui->cbxCA->currentIndex() == 0){ if (ui->leUserCertifyPwd->text() == ""){ ui->btnConnect->setEnabled(false); }else{ if (ui->cbxUserPriKey->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else if (ui->leUserKeyPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else{ ui->btnConnect->setEnabled(true); } } } else { if (ui->leCaPwd->text() == ""){ ui->btnConnect->setEnabled(false); }else{ if (ui->leUserCertifyPwd->text() == ""){ ui->btnConnect->setEnabled(false); }else{ if (ui->cbxUserPriKey->currentIndex() == 0){ ui->btnConnect->setEnabled(true); }else if (ui->leUserKeyPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else{ ui->btnConnect->setEnabled(true); } } } } } } void DlgConnHidWifiSecTls::on_leUserKeyPwd_textEdited(const QString &arg1) { if (ui->leNetName->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leIdentity->text() == ""){ ui->btnConnect->setEnabled(false); } else if (ui->leDomain->text() == ""){ ui->btnConnect->setEnabled(false); } else { if (ui->cbxCA->currentIndex() == 0){ if (ui->leUserCertifyPwd->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leUserKeyPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else{ ui->btnConnect->setEnabled(true); } } else { if (ui->leCaPwd->text() == ""){ ui->btnConnect->setEnabled(false); }else{ if (ui->leUserCertifyPwd->text() == ""){ ui->btnConnect->setEnabled(false); }else if (ui->leUserKeyPwd->text() == ""){ ui->btnConnect->setEnabled(false); } else{ ui->btnConnect->setEnabled(true); } } } } } void DlgConnHidWifiSecTls::paintEvent(QPaintEvent *event) { QStyleOption opt; opt.init(this); QPainter p(this); style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this); QWidget::paintEvent(event); } ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifileap.ui0000644000175000017500000001477414205074704024225 0ustar fengfeng DlgConnHidWifiLeap 0 0 432 434 Connect to Hidden Wi-Fi Network 175 264 182 32 10 175 219 182 32 10 215 390 90 30 10 76 84 90 20 10 Qt::LeftToRight 175 79 182 32 10 76 270 90 20 10 332 321 18 9 10 76 315 90 20 10 76 180 90 20 10 76 225 90 20 10 315 390 90 30 10 175 309 182 32 10 QLineEdit::Password 175 174 182 32 10 0 0 432 434 30 32 140 22 10 134 412 1 Qt::Horizontal 10 364 412 1 Qt::Horizontal lbBoder leUserName cbxSecurity btnCancel lbConn cbxConn lbUserName lbPassword lbNetName lbSecurity btnConnect lePassword leNetName checkBoxPwd lbLeftupTitle lineUp lineDown ukui-screensaver/KylinNM/wireless-security/dlgconnhidwifisectls.h0000644000175000017500000000445614205074704024407 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see #include namespace Ui { class DlgConnHidWifiSecTls; } class DlgConnHidWifiSecTls : public QDialog { Q_OBJECT public: explicit DlgConnHidWifiSecTls(int type, QWidget *parent = 0); ~DlgConnHidWifiSecTls(); protected: void paintEvent(QPaintEvent *event); public slots: void changeDialogSecu(); void changeDialogAuth(); private slots: void on_btnCancel_clicked(); void on_btnConnect_clicked(); void on_checkBoxCA_stateChanged(int arg1); void on_checkBoxPwd_stateChanged(int arg1); void on_checkBoxPwdSec_stateChanged(int arg1); void on_leNetName_textEdited(const QString &arg1); void on_leIdentity_textEdited(const QString &arg1); void on_leDomain_textEdited(const QString &arg1); void on_leCaPwd_textEdited(const QString &arg1); void on_leUserCertifyPwd_textEdited(const QString &arg1); void on_leUserKeyPwd_textEdited(const QString &arg1); void on_cbxCA_currentIndexChanged(const QString &arg1); void on_cbxUserCertify_currentIndexChanged(const QString &arg1); void on_cbxUserPriKey_currentIndexChanged(const QString &arg1); private: Ui::DlgConnHidWifiSecTls *ui; int WepOrWpa = 0;//0 WEP;1WPA void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); // QString labelQss, cbxQss, leQss, btnConnQss, btnCancelQss, lineQss, checkBoxQss, checkBoxCAQss; bool isPress; QPoint winPos; QPoint dragPos; }; #endif // DLGCONNHIDWIFISECTLS_H ukui-screensaver/KylinNM/README.md0000644000175000017500000000155614205074704015603 0ustar fengfeng# NAME kylin-nm - kylin network monitor used in ubuntu-kylin operation system # DESCRIPTION kylin-nm is a Qt based applet and uses some interface provided by NetworkManager. It provides a GUI for users to connect or disconnect wired or wireless network which managed by NetworkManager. Users can also create new wired network and configure a old network. By click button at left bottom in the main window, a network configure window of NetworkManager will show in the screen. Users can get some information about network directly by clicking one item in the network list, these information shown in extension area. # BUILD KYLIN-NM down the source sode install dependency packages(see cntrol files in the debian directory) execute debuild command in the root directory of project execute sudo dpkg -i packagename.deb to install ukui-screensaver/data/0000755000175000017500000000000014205100370013672 5ustar fengfengukui-screensaver/data/ukui-screensaver.desktop0000644000175000017500000000112614205074704020573 0ustar fengfeng[Desktop Entry] Type=Application Name=Screensaver Name[tr]=Ekran Koruyucu Name[zh_CN]=屏幕保护程序 Name[zh_HK]=螢幕保護程式 Name[zh_TW]=螢幕保護程式 Comment[tr]=Ekran koruyucuyu çalıştır ve programı kilitler Comment[zh_CN]=运行屏幕保护及锁定程序 Comment[zh_TW]=啟動螢幕保護程式以及鎖定程式 Exec=ukui-screensaver-backend NoDisplay=true X-UKUI-Autostart-Phase=Application X-UKUI-Autostart-Notify=true X-UKUI-Bugzilla-Bugzilla=UKUI X-UKUI-Bugzilla-Product=ukui-screensaver X-UKUI-Bugzilla-Component=general X-UKUI-Bugzilla-Version=1.0.0 OnlyShowIn=UKUI ukui-screensaver/data/ukui-screensaver.directory0000644000175000017500000001630114205074704021127 0ustar fengfeng[Desktop Entry] Encoding=UTF-8 Name=Screensavers Name[am]=የመመልከቻው ማዳኛዎች Name[ar]=حافظات الشاشة Name[as]=স্ক্ৰীনছেভাৰ Name[ast]=Curiapantalles Name[be]=Ахоўнікі экрану Name[be@latin]=Źbierahalniki ekranu Name[bg]=Предпазители на екрана Name[bn]=স্ক্রীন সেভার Name[bn_IN]=স্ক্রীনসেভার Name[br]=Damanterioù skramm Name[ca]=Estalvis de pantalla Name[ca@valencia]=Estalvis de pantalla Name[cmn]=螢幕保護程式 Name[crh]=Ekran qoruyıcıları Name[cs]=Šetřiče obrazovky Name[cy]=Arbedwyr Sgrin Name[da]=Pauseskærme Name[de]=Bildschirmschoner Name[dz]=གསལ་གཞི་ཉེན་སྲུང་ཚུ། Name[el]=Θέματα Name[en_AU]=Screensavers Name[en_CA]=Screensavers Name[en_GB]=Screensavers Name[es]=Salvapantallas Name[es_AR]=Protectores de pantalla Name[et]=Ekraanisäästjad Name[eu]=Pantaila-babeslea Name[fa]=محافظ‌های صفحهٔ نمایش Name[fi]=Näytönsäästäjät Name[fr]=Économiseurs d'écran Name[ga]=Spárálaithe Scáileáin Name[gl]=Protectores de pantalla Name[gu]=સ્ક્રીનસેવરો Name[he]=שומרי מסך Name[hi]=स्क्रीनसेवरs Name[hr]=Zaslonski čuvari Name[hu]=Képernyővédők Name[id]=Screensaver Name[is]=Skjáhvílur Name[it]=Salvaschermo Name[ja]=いろいろなスクリーンセーバーを格納するフォルダ Name[ka]=ეკრანმზოგები Name[kn]=ಸ್ಕ್ರೀನ್‌ಸೇವರುಗಳು Name[ko]=화면 보호기 Name[ku]=Parêzvanên ekranê Name[ky]=Экран сактагычтар Name[lt]=Ekrano užsklandos Name[lv]=Ekrānsaudzētāji Name[mai]=स्क्रीनसेवर Name[mg]=Sary mitsitsy Name[mk]=Чувари на екранот Name[ml]=സ്ക്രീന്‍സേവറുകള്‍ Name[mn]=_Дэлгэц гамнагчүүд Name[mr]=स्क्रीनसेवर Name[ms]=Penyelamat skrin Name[nb]=Skjermsparere Name[nds]=Billschirmschoners Name[ne]=स्क्रिनसेभर Name[nl]=Screensavers Name[nn]=Skjermsparare Name[oc]=Estalviaires d'ecran Name[or]=ପରଦା ସଂରକ୍ଷକ Name[pa]=ਸਕਰੀਨ-ਸੇਵਰ Name[pl]=Wygaszacze ekranu Name[ps]=پرده ساتونکي Name[pt]=Protetores de Ecrã Name[pt_BR]=Proteções de tela Name[ro]=Economizoare de ecran Name[ru]=Хранители экрана Name[si]=තිරආවරක Name[sk]=Šetriče obrazovky Name[sl]=Ohranjevalniki zaslona Name[sq]=Ruajtës ekrani Name[sr]=Чувари екрана Name[sr@latin]=Čuvari ekrana Name[sv]=Skärmsläckare Name[ta]=திரைசேமிப்பிகள் Name[te]=తెరకాపరులు Name[th]=โปรแกรมรักษาหน้าจอ Name[tr]=Ekran koruyucular Name[uk]=Заставки екрану Name[ur]=سکرین سیور Name[vi]=Ảnh bảo vệ màn hình Name[zh_CN]=屏幕保护程序 Name[zh_HK]=螢幕保護程式 Name[zh_TW]=螢幕保護程式 Comment=Screensaver themes Comment[am]=የመመልከቻው ማዳኛ ገጽታዎች Comment[ar]=سِمات حافظة الشاشة Comment[as]=স্ক্ৰীনছেভাৰ থিম Comment[ast]=Temes del Curiapantalles Comment[be]=Тэмы ахоўніка экрану Comment[be@latin]=Matyvy źbierahalnika ekranu Comment[bg]=Теми за предпазителя Comment[bn]=স্ক্রীনসেভার থীম Comment[bn_IN]=স্ক্রীনসেভার থিম Comment[br]=Neuzioù an damanter skramm Comment[ca]=Temes de l'estalvi de pantalla Comment[ca@valencia]=Temes de l'estalvi de pantalla Comment[cmn]=螢幕保護程式布景主題 Comment[crh]=Ekran qoruyıcısı temaları Comment[cs]=Motivy šetřiče obrazovky Comment[cy]=Themâu arbedwr sgrin Comment[da]=Pauseskærm temaer Comment[de]=Bildschirmschonerthemen Comment[dz]=གསལ་གཞི་ཉེན་སྲུང་བརྗོད་དོན་ཚུ། Comment[el]=Θέματα προστασίας οθόνης Comment[en@shaw]=𐑕𐑒𐑮𐑰𐑯𐑕𐑱𐑝𐑼 𐑔𐑰𐑥𐑟 Comment[en_AU]=Screensaver themes Comment[en_CA]=Screensaver themes Comment[en_GB]=Screensaver themes Comment[es]=Temas del salvapantallas Comment[es_AR]=Temas de protector de pantalla Comment[et]=Ekraanisäästja teemad Comment[eu]=Pantaila-babeslearen gaiak Comment[fa]=تم‌های محافظ صفحهٔ نمایش Comment[fi]=Näytönsäästäjän teemat Comment[fr]=Thèmes de l'économiseur d'écran Comment[ga]=Téamaí spárálaí scáileáin Comment[gl]=Temas do protector de pantalla Comment[gu]=સ્ક્રીનસેવર થીમો Comment[he]=ערכות נושא לשומר המסך Comment[hi]=स्क्रीनसेवर थीम Comment[hr]=Teme zaslonskog čuvara Comment[hu]=Képernyővédő-témák Comment[id]=Tema screensaver Comment[is]=Ásýnd skjáhvílu Comment[it]=Temi del salvaschermo Comment[ja]=スクリーンセーバーのテーマ Comment[ka]=ეკრანმზოგის გაფორმების თემები Comment[kn]=ಸ್ಕ್ರೀನ್‌ಸೇವರ್ ಥೀಮ್‌ಗಳು Comment[ko]=화면 보호기 테마 Comment[ku]=Dirbên dîmenderparêzê Comment[ky]=Экран сактагыч темалары Comment[lt]=Ekrano užsklandos temos Comment[lv]=Ekrānsaudzētāja tēmas Comment[mai]=स्क्रीनसेवर थीम Comment[mg]=Endri-tsary mitsitsy Comment[mk]=Теми за чуварот на екранот Comment[ml]=സ്ക്രീന്‍സേവറിന്റെ പ്രമേയങ്ങള്‍ Comment[mn]=_Дэлгэц гамнагчийн загварууд Comment[mr]=स्क्रीनसेवर सुत्रयोजना Comment[ms]=Tema penyelamat skrin Comment[nb]=Tema for skjermsparer Comment[nds]=Billschirmschonerthemen Comment[ne]=स्क्रिनसेभर विषयवस्तु Comment[nl]=Screensavers Comment[nn]=Tema for skjermsparar Comment[oc]=Tèmas d'estalviaire d'ecran Comment[or]=ପରଦା ସଂରକ୍ଷକ ପ୍ରସଙ୍ଗ Comment[pa]=ਸਕਰੀਨ-ਸੇਵਰ ਥੀਮ Comment[pl]=Motywy wygaszacza ekranu Comment[ps]=د پرده ساتونکي کوندې Comment[pt]=Temas do Protetor de Ecrã Comment[pt_BR]=Temas de proteção de tela Comment[ro]=Teme pentru economizor Comment[ru]=Темы хранителя экрана Comment[si]=තිරආවරකයේ තේමා Comment[sk]=Témy šetriča obrazovky Comment[sl]=Teme ohranjevalnika zaslona Comment[sq]=Temat e ruajtësit të ekranit Comment[sr]=Теме чувара екрана Comment[sr@latin]=Teme čuvara ekrana Comment[sv]=Skärmsläckarteman Comment[ta]=திரைசேமிப்பி சூழல்கள் Comment[te]=తెరకాపరి వైవిద్యాంశాలు Comment[th]=ชุดโปรแกรมรักษาหน้าจอ Comment[tr]=Ekran koruyucu temaları Comment[uk]=Теми збереження екрану Comment[ur]=سکرین سیور کی تھیم Comment[vi]=Sắc thái của ảnh bảo vệ màn hình Comment[zh_CN]=屏幕保护程序主题 Comment[zh_HK]=螢幕保護程式佈景主題 Comment[zh_TW]=螢幕保護程式布景主題 Icon=screensaver Type=Directory NoDisplay=false ukui-screensaver/data/org.ukui.screensaver.gschema.xml0000644000175000017500000001774414205074760022136 0ustar fengfeng false Automatic switching background Set this to TRUE to activate the automatic switching background. true show rest time on screensaver Set this to TRUE to show rest time on screensaver. "" set user text on screensaver. set user text on screensaver. "/usr/share/backgrounds" set background path on screensaver. set background path on screensaver. true set text postion Set this to TRUE to show text on screensaver center. 300 Time to update background on ukui-screensavaer-default The number of seconds to change screensaver background. true Activate when idle Set this to TRUE to activate the screensaver when the session is idle. true Lock on activation Set this to TRUE to lock the screen when the screensaver goes active. 5 idle delay to lock Wait idle delay to lock true Lock when sleep Set this to TRUE to lock the screen when the system goes sleep. 'default-ukui' Screensaver theme selection mode The selection mode used by screensaver. May be "blank-only" to enable the screensaver without using any theme on activation, "single" to enable screensaver using only one theme on activation (specified in "themes" key), and "random" to enable the screensaver using a random theme on activation. 'fade-in-out' Effect for images transition The selection effect used by screensaer which play images. May be "none" to play images without any transition effect. It's ignored when "mode" is not "image". 60 Time interval of switching images The number of seconds of time interval of switching images [] Screensaver themes This key specifies the list of themes to be used by the screensaver. It's ignored when "mode" key is "blank-only", should provide the theme name when "mode" is "single", and should provide a list of themes when "mode" is "random". 30 Time before power management baseline The number of seconds of inactivity before signalling to power management. This key is set and maintained by the session power management agent. 10 Time before theme change The number of minutes to run before changing the screensaver theme. 0 Time before locking The number of minutes after screensaver activation before locking the screen. false Allow embedding a keyboard into the window Set this to TRUE to allow embedding a keyboard into the window when trying to unlock. The "keyboard_command" key must be set with the appropriate command. '' Embedded keyboard command The command that will be run, if the "embedded_keyboard_enabled" key is set to TRUE, to embed a keyboard widget into the window. This command should implement an XEMBED plug interface and output a window XID on the standard output. false Allow logout Set this to TRUE to offer an option in the unlock dialog to allow logging out after a delay. The delay is specified in the "logout_delay" key. 120 Time before logout option The number of minutes after the screensaver activation before a logout option will appear in the unlock dialog. This key has effect only if the "logout_enable" key is set to TRUE. '' Logout command The command to invoke when the logout button is clicked. This command should simply log the user out without any interaction. This key has effect only if the "logout_enable" key is set to TRUE. true Allow user switching Set this to TRUE to offer an option in the unlock dialog to switch to a different user account. true Allow the session status message to be displayed Allow the session status message to be displayed when the screen is locked. '/usr/share/backgrounds/warty-final-ubuntukylin.jpg' the background iamge of lockscreen Allow the user to set the background iamge of lockscreen. 0 Number of side-bar notify messages The number of sider notify messages true Allow to show messages Set this to TRUE to if u want to see how many masseges not read ukui-screensaver/data/ukui-screensaver-qt0000644000175000017500000000054014205074704017544 0ustar fengfengauth requisite pam_nologin.so auth sufficient pam_succeed_if.so user ingroup nopasswdlogin @include common-auth auth optional pam_gnome_keyring.so #If you are using Arch,comment out the #above and use the following. #auth include system-auth #account include system-auth #password include system-auth #session include system-auth ukui-screensaver/data/CMakeLists.txt0000644000175000017500000000055714205100370016441 0ustar fengfenginstall(FILES org.ukui.screensaver.gschema.xml DESTINATION /usr/share/glib-2.0/schemas) install(FILES ukui-screensaver.desktop DESTINATION /etc/xdg/autostart) install(FILES ukui-screensaver.directory DESTINATION /usr/share/desktop-directories) install(FILES ukui-screensavers.menu DESTINATION /etc/xdg/menus) install(FILES ukui-screensaver-qt DESTINATION /etc/pam.d) ukui-screensaver/data/screensaver-startup.sh0000755000175000017500000000017714205074704020271 0ustar fengfeng/usr/lib/ukui-screensaver/screensaver-focus-helper & >/dev/null 2>&1 ukui-screensaver-dialog --lock-startup & >/dev/null 2>&1 ukui-screensaver/data/ukui-screensavers.menu0000644000175000017500000000074714205074704020261 0ustar fengfeng Screensavers ukui-screensaver.directory Screensaver ukui-screensaver/config.h.in0000644000175000017500000000020414205074704015013 0ustar fengfeng#cmakedefine USE_INTEL // == 下面是测试用的 #cmakedefine01 TEST_ON #cmakedefine01 TEST_OF #ifndef __${VAR}___@VAR@ #endif ukui-screensaver/screensaver/0000755000175000017500000000000014205074704015314 5ustar fengfengukui-screensaver/screensaver/sleeptime.h0000644000175000017500000000241314205074704017454 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef SLEEPTIME_H #define SLEEPTIME_H #include #include #include #include #include #include class SleepTime : public QWidget { Q_OBJECT public: explicit SleepTime(QWidget *parent = nullptr); ~SleepTime(); int setTime(QDateTime time); void setSmallMode(); private: QLabel *restTime; QList list; QHBoxLayout *layout; int sleepTime; QDateTime initTime; void init(); void setSeconds(int seconds); void setMinute(int minutes); }; #endif // SLEEPTIME_H ukui-screensaver/screensaver/weathermanager.cpp0000644000175000017500000002600714205074704021017 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * Authors: ZHAI Kang-ning **/ #include "weathermanager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include const QString weatherServerAddr = "http://service.ubuntukylin.com:8001/weather/api/3.0/heweather_data_s6/"; const QString defaultCityId = "101030100"; //"101030100" 默认天津 const int weatherReqInterval = 1000 * 60 * 20; //定时更新天气,和麒麟天气保持一致 const QByteArray schemaWeather = "org.china-weather-data.settings"; static const QMap weatherMap { {"晴", "100"},{"多云", "101"},{"少云", "102"},{"晴间多云", "103"},{"阴", "104"}, {"有风", "200"},{"平静", "201"},{"微风", "202"},{"和风", "203"},{"清风", "204"},{"强风劲风", "205"},{"疾风", "206"},{"大风", "207"},{"烈风", "208"},{"风暴", "209"}, {"狂暴风", "210"},{"飓风", "211"},{"龙卷风", "212"},{"热带风暴", "213"}, {"阵雨", "300"},{"强阵雨", "301"},{"雷阵雨", "302"},{"强雷阵雨", "303"},{"雷阵雨伴有冰雹", "304"},{"小雨", "305"},{"中雨", "306"},{"大雨", "307"},{"极端降雨", "308"},{"毛毛雨细雨", "309"}, {"暴雨", "310"},{"大暴雨", "311"},{"特大暴雨", "312"},{"冻雨", "313"},{"小到中雨", "314"},{"中到大雨", "315"},{"大到暴雨", "316"},{"暴雨到大暴雨", "317"},{"大暴雨到特大暴雨", "318"}, {"雨", "399"}, {"小雪", "400"},{"中雪", "401"},{"大雪", "402"},{"暴雪", "403"},{"雨夹雪", "404"},{"雨雪天气", "405"},{"阵雨夹雪", "406"},{"阵雪", "407"},{"小到中雪", "408"},{"中到大雪", "409"}, {"大到暴雪", "410"},{"雪", "499"}, {"薄雾", "500"},{"雾", "501"},{"霾", "502"},{"扬沙", "503"},{"浮尘", "504"},{"沙尘暴", "507"},{"强沙尘暴", "508"},{"大雾", "509"}, {"强浓雾", "510"},{"中度霾", "511"},{"重度霾", "512"},{"严重霾", "513"},{"大雾", "514"},{"特强浓雾", "515"}, {"热", "900"},{"冷", "901"}, {"未知", "999"} }; WeatherManager::WeatherManager(QObject *parent) : QObject(parent) { //初始化m_net_manager请求天气 m_net_manager = new QNetworkAccessManager(this); QObject::connect(m_net_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*))); m_timer = new QTimer(this); m_timer->setInterval(weatherReqInterval); m_local_weather_info = new LocalWeatherInfo(this); connect(m_timer, &QTimer::timeout, this, &WeatherManager::weatherRequest); m_networkWatcher = new NetWorkWatcher(this); connect(m_networkWatcher, &NetWorkWatcher::NetworkStateChanged, this, &WeatherManager::onNetworkStateChanged); m_networkWatcher->checkOnline(); } void WeatherManager::onNetworkStateChanged(uint state) { qDebug() << state; if (NM_STATE_CONNECTED_GLOBAL != state) emit onWeatherUpdate("天气不可用", NULL, NULL); else getWeather(); } void WeatherManager::getWeather() { weatherRequest(); if (m_timer != NULL) { m_timer->start(); } return; } void WeatherManager::weatherRequest() { if (updateLocation()) return; QNetworkRequest request(QUrl(weatherServerAddr + m_city_id + "/")); m_net_manager->get(request); } bool WeatherManager::updateLocation() { //更新城市信息 未实现 麒麟天气提供gsettings,完成后对接 if (QGSettings::isSchemaInstalled(schemaWeather)) { m_settings = new QGSettings(schemaWeather,"",this); //org/ukui/indicator-china-weather path if(getLogcalWeather()) { emit onWeatherUpdate(m_local_weather_info->getCityName(), m_local_weather_info->getCondText(), m_local_weather_info->getTemperature()); m_networkWatcher->checkOnline(); return true; } m_city_id = getLogcalCityId(); } if (m_city_id.isEmpty()) m_city_id = defaultCityId; return false; } bool WeatherManager::getLogcalWeather() { if (m_settings != nullptr) { //"1920-08-27 10:17:42,101310204,澄迈,小雨,95%,25℃,北风,1级," 时间,城市编码,城市名称,天气,湿度,温度,风向,风力 QString weather = m_settings->get("weather").toString(); QStringList weatherInfoList = weather.split(","); if (weatherInfoList.size() < 9) return false; m_local_weather_info->setTime(weatherInfoList.at(0)); if(!m_local_weather_info->isTimeValid()) return false; m_local_weather_info->setCityId(weatherInfoList.at(1)); m_local_weather_info->setCityName(weatherInfoList.at(2)); m_local_weather_info->setCondText(weatherInfoList.at(3)); m_local_weather_info->setAirHumidity(weatherInfoList.at(4)); m_local_weather_info->setTemperature(weatherInfoList.at(5)); m_local_weather_info->setWindDirection(weatherInfoList.at(6)); m_local_weather_info->setWindForce(weatherInfoList.at(7)); return true; } return false; } QString WeatherManager::getLogcalCityId() { if (m_settings != nullptr) { QString citys = m_settings->get("citylist").toString();//"101010100," if (citys.isEmpty()) return ""; QStringList cityList = citys.split(","); if (cityList.size() >= 1) { QString s = cityList.at(0); qDebug() << "local city id = " << s; return s; } } return ""; } void WeatherManager::replyFinished(QNetworkReply *reply) { if(reply != nullptr && reply->error() != QNetworkReply::NoError) { qWarning() << "[WeatherManager][replyFinished] get weather error:(" << reply->error() << ")" << reply->errorString(); if (m_networkTryNum < 15) { m_networkTryNum++; QTimer::singleShot(1000, this, [=]{ weatherRequest(); }); } else { m_networkTryNum = 0; } emit onWeatherUpdate("天气不可用", "", ""); return; } //注:天气信息只解析了锁屏需要展示的部分 QByteArray BA; QJsonDocument JD; QJsonParseError JPE; BA = reply->readAll(); // QTextCodec *codec = QTextCodec::codecForName("UTF-8"); // QString all = codec->toUnicode(BA); // qDebug() << "reply is:" << all; JD = QJsonDocument::fromJson(BA, &JPE); if (JPE.error == QJsonParseError::NoError) { if (JD.isObject()) { QJsonObject kylinWeatherObj = JD.object().value("KylinWeather").toObject(); QString nowWeather = kylinWeatherObj.value("weather").toObject().value("now").toString(); m_city_name = kylinWeatherObj.value("weather").toObject().value("location").toString(); QStringList nowList = nowWeather.split(","); for(QString now : nowList) { if(now.contains("cond_txt")) { m_cond_txt = now.mid(9); } if (now.contains("tmp")){ m_temperature = now.mid(4) + "°C"; } } emit onWeatherUpdate(m_city_name, m_cond_txt, m_temperature); } } else { qWarning() << "get weather info error : " << JPE.errorString(); emit onWeatherUpdate("天气不可用", "", ""); } reply->deleteLater(); } QPixmap WeatherManager::getWeatherIcon() { return getWeatherIcon(m_cond_txt); } QPixmap WeatherManager::getWeatherIcon(QString cond) { if (cond.isEmpty()) { qWarning() << "cond info is unknown"; return QPixmap(":/weather/assets/weather-icon/999.svg").scaled(32,32); } //根据m_cond_txt QString numStr = weatherMap.value(cond); if (!numStr.isEmpty()) { qDebug() << "----------------numStr=" + numStr; return QPixmap(":/weather/assets/weather-icon/" + numStr +".svg").scaled(32,32); } qWarning() << "天气为|" << cond << "|"; return QPixmap(":/weather/assets/weather-icon/999.svg").scaled(32,32); } QString WeatherManager::getCityName() { return ""; } QString WeatherManager::getCond() { return ""; } QString WeatherManager::getTemperature() { return ""; } LocalWeatherInfo::LocalWeatherInfo(QObject *parent) { } bool LocalWeatherInfo::isTimeValid() { if (m_update_time != nullptr && !m_update_time.isEmpty()) { QString strBuffer; QDateTime time = QDateTime::fromString(m_update_time, "yyyy-MM-dd hh:mm:ss"); QDateTime currentTime = QDateTime::currentDateTime(); if (!time.isValid()) return false; uint timeInterval = currentTime.toTime_t() - time.toTime_t(); if((timeInterval <= 21 * 60) && (timeInterval > 0)) { //麒麟天气更新时间为20分钟,加入1分钟容错机制 return true; } } return false; } void LocalWeatherInfo::setTime(QString time) { m_update_time = time; } QString LocalWeatherInfo::getTime() { return m_update_time; } void LocalWeatherInfo::setCityId(QString cityId) { m_city_id = cityId; } QString LocalWeatherInfo::getCityId() { return m_city_id; } void LocalWeatherInfo::setCityName(QString cityName) { m_city_name = cityName; } QString LocalWeatherInfo::getCityName() { return m_city_name; } void LocalWeatherInfo::setCondText(QString condText) { m_cond_text = condText; } QString LocalWeatherInfo::getCondText() { return m_cond_text; } void LocalWeatherInfo::setAirHumidity(QString airHumidity) { m_air_humidity = airHumidity; } QString LocalWeatherInfo::getAirHumidity() { return m_air_humidity; } void LocalWeatherInfo::setTemperature(QString temperature) { m_temperature = temperature; } QString LocalWeatherInfo::getTemperature() { return m_temperature; } void LocalWeatherInfo::setWindDirection(QString windDirection) { m_wind_direction = windDirection; } QString LocalWeatherInfo::getWindDirection() { return m_wind_direction; } void LocalWeatherInfo::setWindForce(QString windForce) { m_wind_force = windForce; } QString LocalWeatherInfo::getWindForce() { return m_wind_force; } ukui-screensaver/screensaver/mbackground.h0000644000175000017500000000216114205074704017761 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef MBACKGROUND_H #define MBACKGROUND_H #include #include #include #include #include #include "scconfiguration.h" class MBackground { public: MBackground(); QString getCurrent(); QString getNext(); QString getPrev(); QString getRand(); private: void getAllPixmap(); QStringList list; int currentIndex; }; #endif // MBACKGROUND_H ukui-screensaver/screensaver/cyclelabel.cpp0000644000175000017500000000525314205074704020124 0ustar fengfeng/* -*- 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 "cyclelabel.h" CycleLabel::CycleLabel(QWidget *parent) :QFrame(parent), m_width(20), m_height(20) { this->setFixedSize(QSize(m_width, m_height)); setWindowFlags(Qt::FramelessWindowHint); setAttribute(Qt::WA_TranslucentBackground, true); } void CycleLabel::paintEvent(QPaintEvent *){ //启用反锯齿 QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); drawBg(&painter); drawSlider(&painter); } void CycleLabel::setSize(QSize size) { m_width = size.width(); m_height = size.height(); setFixedSize(size); repaint(); } void CycleLabel::drawBg(QPainter *painter) { painter->save(); if (!checked){ painter->setPen(QColor(0,0,0,66)); painter->setBrush(QColor(0,0,0,66)); } else{ painter->setPen(Qt::NoPen); painter->setBrush(bgColorOn); } //circle in QRect rect(0, 0, width(), height()); //半径为高度的一半 int radius = rect.height() / 2; //圆的宽度为高度 int circleWidth = rect.height(); QPainterPath path; path.moveTo(radius, rect.left()); path.arcTo(QRectF(rect.left(), rect.top(), circleWidth, circleWidth), 90, 180); path.lineTo(rect.width() - radius, rect.height()); path.arcTo(QRectF(rect.width() - rect.height(), rect.top(), circleWidth, circleWidth), 270, 180); path.lineTo(radius, rect.top()); painter->drawPath(path); painter->restore(); } void CycleLabel::drawSlider(QPainter *painter){ painter->save(); painter->setPen(Qt::NoPen); painter->setBrush(QColor("#ffffff")); //circle in QRect rect(0, 0, m_width, m_height); int sliderWidth = m_width/2; QRect sliderRect(sliderWidth/2, sliderWidth/2, sliderWidth, sliderWidth); painter->drawEllipse(sliderRect); painter->restore(); } ukui-screensaver/screensaver/ukui-screensaver-default.pro0000644000175000017500000000254114205074704022755 0ustar fengfeng#------------------------------------------------- # # Project created by QtCreator 2020-01-10T17:10:24 # #------------------------------------------------- QT += core gui x11extras greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = ukui-screensaver-default TEMPLATE = app # The following define makes your compiler emit warnings if you use # any feature of Qt which as been marked as deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS # You can also make your code fail to compile if you use deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 LIBS += -lX11 SOURCES += \ main.cpp \ screensaver.cpp \ sleeptime.cpp \ chinesedate.cpp \ mbackground.cpp \ scconfiguration.cpp HEADERS += \ screensaver.h \ sleeptime.h \ chinesedate.h \ mbackground.h \ scconfiguration.h TRANSLATIONS = ../i18n_ts/zh_CN.ts \ ../i18n_ts/ru.ts \ ../i18n_ts/fr.ts \ ../i18n_ts/pt.ts \ ../i18n_ts/es.ts RESOURCES = default.qrc ukui-screensaver/screensaver/scconfiguration.cpp0000644000175000017500000001444214205074704021222 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "scconfiguration.h" #include "commonfunc.h" #include #include #include #include #define GSETTINGS_SCHEMA_SCREENSAVER "org.ukui.screensaver" #define GSETTINGS_SCHEMA_MATE_BACKGROUND "org.mate.background" #define GSETTINGS_SCHEMA_SCREENSAVER_DEFAULT "org.ukui.screensaver-default" #define TIME_TYPE_SCHEMA "org.ukui.control-center.panel.plugins" SCConfiguration* SCConfiguration::instance_ = nullptr; SCConfiguration::SCConfiguration(QObject *parent) : QObject(parent), mgsettings(nullptr), ukgsettings(nullptr), udgsettings(nullptr), timegsettings(nullptr) { initGsettings(); } SCConfiguration* SCConfiguration::instance(QObject *parent) { if(instance_ == nullptr) instance_ = new SCConfiguration(parent); return instance_; } void SCConfiguration::initGsettings() { if(QGSettings::isSchemaInstalled(GSETTINGS_SCHEMA_MATE_BACKGROUND)) mgsettings = new QGSettings(GSETTINGS_SCHEMA_MATE_BACKGROUND, "", this); if(QGSettings::isSchemaInstalled(GSETTINGS_SCHEMA_SCREENSAVER)) ukgsettings = new QGSettings(GSETTINGS_SCHEMA_SCREENSAVER, "", this); if(QGSettings::isSchemaInstalled(GSETTINGS_SCHEMA_SCREENSAVER_DEFAULT)) udgsettings = new QGSettings(GSETTINGS_SCHEMA_SCREENSAVER_DEFAULT,"",this); if(QGSettings::isSchemaInstalled(TIME_TYPE_SCHEMA)) timegsettings = new QGSettings(TIME_TYPE_SCHEMA,"",this); connect(udgsettings, &QGSettings::changed, this, &SCConfiguration::onConfigurationChanged); connect(ukgsettings, &QGSettings::changed, this, &SCConfiguration::onConfigurationChanged); connect(timegsettings, &QGSettings::changed, this, &SCConfiguration::onConfigurationChanged); } void SCConfiguration::initDefaultSettings() { } void SCConfiguration::onConfigurationChanged(QString key) { if(key == "cycleTime"){ int cycleTime = getCycleTime(); Q_EMIT cycleTimeChanged(cycleTime); }else if(key == "automaticSwitchingEnabled"){ bool changed = getAutoSwitch(); Q_EMIT autoSwitchChanged(changed); }else if(key == "backgroundPath"){ QString path = getBackgroundPath(); Q_EMIT backgroundPathChanged(path); }else if(key == "mytext"){ QString text = getMyText(); Q_EMIT myTextChanged(text); }else if(key == "showRestTime"){ bool ret = getShowRestTime(); Q_EMIT showRestTimeChanged(ret); }else if(key == "textIsCenter"){ bool ret = getTextIsCenter(); Q_EMIT textIsCenterChanged(ret); }else if(key == "showMessageEnabled"){ bool ret = getMessageShowEnable(); Q_EMIT messageShowEnableChanged(ret); }else if(key == "messageNumber"){ int num = getMessageNumber(); Q_EMIT messageNumberChanged(num); }else if(key == "hoursystem"){ int timeType = timegsettings->get("hoursystem").toInt(); Q_EMIT timeTypeChanged(timeType); }else if(key == "type"){ QString dateType = timegsettings->get("date").toString(); Q_EMIT dateTypeChanged(dateType); } } QString SCConfiguration::getDefaultBackground() { QString backgroundFile = ""; if(ukgsettings){ backgroundFile = ukgsettings->get("background").toString(); } if(ispicture(backgroundFile)) return backgroundFile; else return "/usr/share/backgrounds/warty-final-ubuntukylin.jpg"; } int SCConfiguration::getTimeType() { int timeType = 24; if(timegsettings){ QStringList keys = timegsettings->keys(); if (keys.contains("hoursystem")) { timeType = timegsettings->get("hoursystem").toInt(); } } return timeType; } QString SCConfiguration::getDateType() { QString dateType = "cn"; if(timegsettings){ QStringList keys = timegsettings->keys(); if (keys.contains("date")) { dateType = timegsettings->get("date").toString(); } } return dateType; } bool SCConfiguration::getAutoSwitch() { bool ret = false; if(udgsettings){ ret = udgsettings->get("automatic-switching-enabled").toBool(); } return ret; } bool SCConfiguration::getIsCustom() { bool ret = false; if(ukgsettings){ ret = (ukgsettings->get("mode").toString() == "default-ukui-custom"); } return ret; } bool SCConfiguration::getMessageShowEnable() { bool ret = false; if(ukgsettings){ ret = ukgsettings->get("show-message-enabled").toBool(); } return ret; } int SCConfiguration::getMessageNumber() { bool ret = false; if(ukgsettings){ ret = (ukgsettings->get("mode").toString() == "default-ukui-custom"); } return ret; } bool SCConfiguration::getShowRestTime() { bool ret = true; if(udgsettings){ QStringList keys = udgsettings->keys(); ret = udgsettings->get("show-rest-time").toBool(); } return ret; } int SCConfiguration::getCycleTime() { int cycleTime = 300; if(udgsettings){ cycleTime = udgsettings->get("cycle-time").toInt(); } return cycleTime; } QString SCConfiguration::getBackgroundPath() { QString backgroundPath = "/usr/share/backgrounds"; if(udgsettings){ backgroundPath = udgsettings->get("background-path").toString(); } return backgroundPath; } bool SCConfiguration::getTextIsCenter() { bool ret = true; if(udgsettings){ ret = udgsettings->get("text-is-center").toBool(); } return ret; } QString SCConfiguration::getMyText() { QString myText = ""; if(udgsettings){ myText = udgsettings->get("mytext").toString(); } return myText; } ukui-screensaver/screensaver/scconfiguration.h0000644000175000017500000000506714205074704020672 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef SCCONFIGURATION_H #define SCCONFIGURATION_H #ifndef QT_NO_KEYWORDS #define QT_NO_KEYWORDS #endif #include #include class QGSettings; class SCConfiguration : public QObject { Q_OBJECT public: explicit SCConfiguration(QObject *parent = nullptr); static SCConfiguration *instance(QObject *parent = nullptr); QString getDefaultBackground(); //获取屏保默认背景 int getTimeType(); //获取显示时间格式 QString getDateType(); //获取日期格式 bool getAutoSwitch(); //获取是否自动切换 bool getShowRestTime(); //是否显示休息时间 bool getIsCustom(); //屏保是否自定义 int getCycleTime(); //背景图片切换间隔时间 QString getBackgroundPath(); //背景图片来源 bool getTextIsCenter(); //文字是否居中 QString getMyText(); //获取文字 bool getMessageShowEnable(); //获取是否显示消息 int getMessageNumber(); //获取消息数量 public: public Q_SLOTS: void onConfigurationChanged(QString key); Q_SIGNALS: void cycleTimeChanged(int cycleTime); bool autoSwitchChanged(bool changed); QString backgroundPathChanged(QString path); QString myTextChanged(QString text); bool showRestTimeChanged(bool isShow); bool textIsCenterChanged(bool isCenter); int messageNumberChanged(int number); bool messageShowEnableChanged(bool enabled); int timeTypeChanged(int time); QString dateTypeChanged(QString type); private: void initGsettings(); void initDefaultSettings(); private: QGSettings *mgsettings; QGSettings *ukgsettings; QGSettings *udgsettings; QGSettings *timegsettings; static SCConfiguration *instance_; }; #endif // CONFIGURATION_H ukui-screensaver/screensaver/chinesedate.h0000644000175000017500000000367514205074704017754 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef CHINESEDATE_H #define CHINESEDATE_H #include #include class ChineseDate { public: ChineseDate(); QString getDateLunar(); private: /** * @brief 根据农历年份获取该年天数 * @param year 农历年份 * @return */ int getYearDays(int year); /** * @brief 根据农历年份判断该年是否有闰月 * @param year 农历年份 * @return */ bool isLeapMonth(int year); /** * @brief 根据农历年份获取闰月的天数,如果存在闰月的话 * @param year 农历年份 * @return */ int getLeapMonthDays(int year); /** * @brief 根据农历年份获取闰月的月份 * @param year 农历年份 * @return */ int getLeapMonth(int year); /** * @brief 根据农历年份和月份获取当月的天数 * @param year 农历年份 * @param month 农历月份 * @return */ int getYearMonthDays(int year,int month); /** * @brief 获取农历日期 * @return */ QString getChineseDays(int month,int day,bool isleap); QStringList ChineseMonth; QStringList ChineseDay; QStringList ChineseDays; }; #endif // CHINESEDATE_H ukui-screensaver/screensaver/sleeptime.cpp0000644000175000017500000000532114205074704020010 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "sleeptime.h" #include #include #include SleepTime::SleepTime(QWidget *parent) : QWidget(parent), sleepTime(0) { init(); } SleepTime::~SleepTime() { } void SleepTime::init() { layout = new QHBoxLayout(this); layout->setDirection(QBoxLayout::RightToLeft); layout->setSpacing(4); for(int i=0;i<2;i++) { QLabel *label = new QLabel(this); label->setText("0"); label->setFixedSize(40,40); label->setObjectName("clockTime"); list.append(label); } QLabel *colon = new QLabel(this); colon->setText(":"); colon->setObjectName("colon"); list.append(colon); for(int i=0;i<2;i++) { QLabel *label = new QLabel(this); label->setText("0"); label->setFixedSize(40,40); label->setObjectName("clockTime"); list.append(label); } for(int i=0;iaddWidget(list.at(i)); } restTime = new QLabel(this); restTime->setText(tr("You have rested:")); restTime->setObjectName("restTime"); restTime->setAlignment(Qt::AlignBottom); restTime->adjustSize(); layout->addWidget(restTime); initTime = QDateTime::currentDateTime(); } int SleepTime::setTime(QDateTime time) { sleepTime = initTime.secsTo(time); if(sleepTime>5999 || sleepTime<0){ hide(); return false; } int sec = sleepTime % 60; int min = sleepTime/60; setSeconds(sec); setMinute(min); return true; } void SleepTime::setSeconds(int seconds) { int sec1 = seconds%10; int sec2 = seconds/10; list.at(0)->setText(QString::number(sec1)); list.at(1)->setText(QString::number(sec2)); } void SleepTime::setMinute(int minutes) { int min1 = minutes%10; int min2 = minutes/10; list.at(3)->setText(QString::number(min1)); list.at(4)->setText(QString::number(min2)); } void SleepTime::setSmallMode() { for(int i = 0;i<5;i++) list.at(i)->setFixedSize(8,8); adjustSize(); } ukui-screensaver/screensaver/weathermanager.h0000644000175000017500000000624014205074704020461 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * Authors: ZHAI Kang-ning **/ #ifndef WEATHERMANAGER_H #define WEATHERMANAGER_H #include #include #include #include #include "../src/networkwatcher.h" class QNetworkAccessManager; class QNetworkReply; class LocalWeatherInfo; class WeatherManager : public QObject { Q_OBJECT public: explicit WeatherManager(QObject *parent = nullptr); Q_SIGNALS: void onWeatherUpdate(QString city, QString cond, QString temperature); private Q_SLOTS: void replyFinished(QNetworkReply *); void onNetworkStateChanged(uint state); public: void getWeather(); QPixmap getWeatherIcon(); QPixmap getWeatherIcon(QString cond); QString getCityName(); QString getCond(); QString getTemperature(); private: bool updateLocation();//更新位置,从用户设置获取城市信息,如有多个,只取第一个,未对接 void weatherRequest(); bool getLogcalWeather(); QString getLogcalCityId(); private: QString m_city_id; // "101030100" 默认天津 QString m_city_name; QString m_cond_txt; //天气条件 晴、阴等 QString m_temperature;//温度 10、20等 QNetworkAccessManager *m_net_manager; QTimer *m_timer; QGSettings *m_settings; LocalWeatherInfo *m_local_weather_info; NetWorkWatcher *m_networkWatcher; int m_networkTryNum = 0; }; class LocalWeatherInfo : QObject { //"1920-08-27 10:17:42,101310204,澄迈,小雨,95%,25℃,北风,1级," 时间,城市编码,城市名称,天气,湿度,温度,风向,风力 Q_OBJECT public: explicit LocalWeatherInfo(QObject *parent = nullptr); private: QString m_update_time; QString m_city_id; QString m_city_name; QString m_cond_text; QString m_air_humidity; QString m_temperature; QString m_wind_direction; QString m_wind_force; public: bool isTimeValid(); void setTime(QString time); QString getTime(); void setCityId(QString cityId); QString getCityId(); void setCityName(QString cityName); QString getCityName(); void setCondText(QString condText); QString getCondText(); void setAirHumidity(QString airHumidity); QString getAirHumidity(); void setTemperature(QString temperature); QString getTemperature(); void setWindDirection(QString windDirection); QString getWindDirection(); void setWindForce(QString windForce); QString getWindForce(); }; #endif // WEATHERMANAGER_H ukui-screensaver/screensaver/CMakeLists.txt0000644000175000017500000000245214205074704020057 0ustar fengfengpkg_check_modules(X11 REQUIRED x11) pkg_check_modules(XTST REQUIRED xtst) pkg_check_modules(QGS REQUIRED gsettings-qt) include_directories(${PROJECT_BINARY_DIR}) include_directories(${PROJECT_SOURCE_DIR}/Common) include_directories( ${X11_INCLUDE_DIRS} ${XTST_INCLUDE_DIRS} ${QGS_INCLUDE_DIRS} ) set(EXTRA_LIBS ${EXTRA_LIBS} ${X11_LIBRARIES} ${XTST_LIBRARIES} ${QGS_LIBRARIES} Common ) qt5_add_resources(screensaver_SRC default.qrc ) qt5_wrap_cpp(screensaver_SRC chinesedate.h screensaver.h mbackground.h cyclelabel.h scconfiguration.h sleeptime.h weathermanager.h ../src/networkwatcher.h ) set(screensaver_SRC ${screensaver_SRC} main.cpp chinesedate.cpp mbackground.cpp screensaver.cpp cyclelabel.cpp scconfiguration.cpp sleeptime.cpp weathermanager.cpp ../src/networkwatcher.cpp ) add_executable(ukui-screensaver-default ${screensaver_SRC}) target_link_libraries(ukui-screensaver-default Qt5::Core Qt5::Widgets Qt5::X11Extras Qt5::Xml Qt5::Network ${EXTRA_LIBS}) install(TARGETS ukui-screensaver-default DESTINATION lib/ukui-screensaver) install(FILES language/screensaver-zh_CN.ini language/screensaver-en_US.ini language/screensaver-jd.ini DESTINATION share/ukui-screensaver/language) ukui-screensaver/screensaver/mbackground.cpp0000644000175000017500000000562314205074704020322 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include #include #include #include #include #include #include #include "mbackground.h" #include "commonfunc.h" MBackground::MBackground(): currentIndex(0) { getAllPixmap(); } QString MBackground::getCurrent() { if(list.count()<0) return ""; if(currentIndex>=0 && currentIndex=list.count() ||currentIndex<0) return ""; if(currentIndex == list.count() - 1) currentIndex = 0; else currentIndex++; return list.at(currentIndex); } QString MBackground::getPrev() { if(list.count() == 1) return list.at(0); if(list.count()<=0 || currentIndex>=list.count() || currentIndex<0) return ""; if(currentIndex == 0) currentIndex = list.count() - 1; else currentIndex--; return list.at(currentIndex); } QString MBackground::getRand() { if(list.count() <= 0) return ""; qsrand(time(NULL)); currentIndex = qrand() % list.count(); return list.at(currentIndex); } void MBackground::getAllPixmap() { QDomDocument doc; QFile *file; file = new QFile("/usr/share/ukui-background-properties/focal-ubuntukylin-wallpapers.xml"); if (!file->open(QIODevice::ReadOnly)) { qDebug()<fileName()<<" open failed"; return ; } if (!doc.setContent(file)) { file->close(); return ; } file->close(); file->deleteLater(); QDomElement root = doc.documentElement();//读取根节点 QDomNode node = root.firstChild();//读取第一个子节点 QDomNode 节点 while (!node.isNull()) { QDomElement node1 = node.firstChildElement("filename"); QString fileName = node1.text(); QMimeDatabase db; QMimeType mime = db.mimeTypeForFile(fileName); if(mime.name().startsWith("image/")){ list.append(fileName); } node = node.nextSibling();//读取下一个兄弟节点 } } ukui-screensaver/screensaver/chinesedate.cpp0000644000175000017500000001341014205074704020273 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "chinesedate.h" #include #include #include unsigned int chineseDays[201]={0x04bd8,0x04ae0,0x0a570,0x054d5,0x0d260,0x0d950,0x16554,0x056a0,0x09ad0,0x055d2,//1900-1909 0x04ae0,0x0a5b6,0x0a4d0,0x0d250,0x1d255,0x0b540,0x0d6a0,0x0ada2,0x095b0,0x14977,//1910-1919 0x04970,0x0a4b0,0x0b4b5,0x06a50,0x06d40,0x1ab54,0x02b60,0x09570,0x052f2,0x04970,//1920-1929 0x06566,0x0d4a0,0x0ea50,0x16a95,0x05ad0,0x02b60,0x186e3,0x092e0,0x1c8d7,0x0c950,//1930-1939 0x0d4a0,0x1d8a6,0x0b550,0x056a0,0x1a5b4,0x025d0,0x092d0,0x0d2b2,0x0a950,0x0b557,//1940-1949 0x06ca0,0x0b550,0x15355,0x04da0,0x0a5b0,0x14573,0x052b0,0x0a9a8,0x0e950,0x06aa0,//1950-1959 0x0aea6,0x0ab50,0x04b60,0x0aae4,0x0a570,0x05260,0x0f263,0x0d950,0x05b57,0x056a0,//1960-1969 0x096d0,0x04dd5,0x04ad0,0x0a4d0,0x0d4d4,0x0d250,0x0d558,0x0b540,0x0b6a0,0x195a6,//1970-1979 0x095b0,0x049b0,0x0a974,0x0a4b0,0x0b27a,0x06a50,0x06d40,0x0af46,0x0ab60,0x09570,//1980-1989 0x04af5,0x04970,0x064b0,0x074a3,0x0ea50,0x06b58,0x05ac0,0x0ab60,0x096d5,0x092e0,//1990-1999 0x0c960,0x0d954,0x0d4a0,0x0da50,0x07552,0x056a0,0x0abb7,0x025d0,0x092d0,0x0cab5,//2000-2009 0x0a950,0x0b4a0,0x0baa4,0x0ad50,0x055d9,0x04ba0,0x0a5b0,0x15176,0x052b0,0x0a930,//2010-2019 0x07954,0x06aa0,0x0ad50,0x05b52,0x04b60,0x0a6e6,0x0a4e0,0x0d260,0x0ea65,0x0d530,//2020-2029 0x05aa0,0x076a3,0x096d0,0x04afb,0x04ad0,0x0a4d0,0x1d0b6,0x0d250,0x0d520,0x0dd45,//2030-2039 0x0b5a0,0x056d0,0x055b2,0x049b0,0x0a577,0x0a4b0,0x0aa50,0x1b255,0x06d20,0x0ada0,//2040-2049 /**Add By JJonline@JJonline.Cn**/ 0x14b63,0x09370,0x049f8,0x04970,0x064b0,0x168a6,0x0ea50, 0x06b20,0x1a6c4,0x0aae0,//2050-2059 0x092e0,0x0d2e3,0x0c960,0x0d557,0x0d4a0,0x0da50,0x05d55,0x056a0,0x0a6d0,0x055d4,//2060-2069 0x052d0,0x0a9b8,0x0a950,0x0b4a0,0x0b6a6,0x0ad50,0x055a0,0x0aba4,0x0a5b0,0x052b0,//2070-2079 0x0b273,0x06930,0x07337,0x06aa0,0x0ad50,0x14b55,0x04b60,0x0a570,0x054e4,0x0d160,//2080-2089 0x0e968,0x0d520,0x0daa0,0x16aa6,0x056d0,0x04ae0,0x0a9d4,0x0a2d0,0x0d150,0x0f252,//2090-2099 0x0d520}; int Month[12] = {31,28,31,30,31,30,31,31,30,31,30,31}; ChineseDate::ChineseDate() { ChineseMonth<<""<<"正"<<"二"<<"三"<<"四"<<"五"<<"六"<<"七"<<"八"<<"九"<<"十"<<"冬"<<"腊"; ChineseDay<<""<<"一"<<"二"<<"三"<<"四"<<"五"<<"六"<<"七"<<"八"<<"九"; ChineseDays<<"初"<<"十"<<"廿"<<"三十"; } int ChineseDate::getYearDays(int year) { int sum = 12 * 29; for (unsigned int i = 0x8000; i > 0x8; i = i >> 1) { sum += chineseDays[year - 1900] & i ? 1 : 0; } sum += getLeapMonthDays(year); return sum; } bool ChineseDate::isLeapMonth(int year) { return chineseDays[year - 1900] & 0xf ? true : false; } int ChineseDate::getLeapMonthDays(int year) { if(isLeapMonth(year)) return chineseDays[year-1900]& 0x10000 ? 30 : 29; return 0; } int ChineseDate::getLeapMonth(int year) { if(isLeapMonth(year)) return chineseDays[year-1900] & 0xf; return 0; } int ChineseDate::getYearMonthDays(int year,int month) { return chineseDays[year-1900] & (0x10000 >> month) ? 30 : 29; } QString ChineseDate::getChineseDays(int month, int day, bool isleap) { QString res = ""; if(isleap) res = res + "闰"; res = res + ChineseMonth.at(month) + "月"; if(day == 10) res = res + "初十"; else if(day == 20) res = res + "二十"; else if(day == 30) res = res + "三十"; else res = res + ChineseDays.at(day/10) + ChineseDay.at(day%10); return res; } QString ChineseDate::getDateLunar() { int leapyear,leapmonth,leapday; QDateTime currentTime = QDateTime::currentDateTime(); QDate oldTile(1900, 1, 31); //获取当前日期到1900年1月31日的天数 int offset = oldTile.daysTo(currentTime.date()); //获取农历年 int i,yearlength; for (i = 1900; i < 2101 && offset > 0; i++) { yearlength = getYearDays(i); offset -= yearlength; } if (offset < 0) { offset += yearlength; i--; } leapyear = i; //获取农历月 bool isLeap = false; int temp; int leapMonth = getLeapMonth(leapyear); for (i = 1; i < 13 && offset >= 0; i++) { temp = getYearMonthDays(leapyear,i); offset -= temp; isLeap = false; if (i == leapMonth) { if (offset < 0) { i--; isLeap = true; } else { temp = getLeapMonthDays(leapyear); offset -= temp; } } } if (offset < 0) { if (i == leapMonth && isLeap) { offset += temp; isLeap = false; } else if (i == (leapMonth + 1)) { offset += temp; isLeap = true; i--; } else { offset += temp; i--; } } leapmonth = i; leapday = offset + 1; return getChineseDays(leapmonth,leapday,isLeap); } ukui-screensaver/screensaver/screensaver.cpp0000644000175000017500000012024214205074704020341 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "screensaver.h" #include #include #include #include #include "commonfunc.h" #include "config.h" #define TIME_TYPE_SCHEMA "org.ukui.control-center.panel.plugins" #define THEME_TYPE_SCHENA "org.ukui.style" #define GSETTINGS_SCHEMA_SCREENSAVER "org.ukui.screensaver" #define KEY_MESSAGE_NUMBER "message-number" #define KEY_MESSAGE_SHOW_ENABLED "show-message-enabled" #define KEY_HOURSYSTEM "hoursystem" #define KEY_DATE_FORMAT "date" QTime Screensaver::m_currentTime = QTime::currentTime(); extern bool bControlFlg; Screensaver::Screensaver(QWidget *parent): QWidget(parent), switchTimer(nullptr), backgroundPath(""), cycleTime(300), isCustom(false), isShowRestTime(true), myTextLabel(nullptr), myPreviewLabel(nullptr),//预览label标签 configuration(SCConfiguration::instance()), myTextWidget(nullptr), centerWidget(nullptr), sleepTime(nullptr), timer(nullptr), background(""), autoSwitch(nullptr), vboxFrame(nullptr), isAutoSwitch(false), flag(0), hasChanged(false), process(nullptr), screenLabel(nullptr), respondClick(false), m_weatherManager(new WeatherManager(this)) { installEventFilter(this); // setWindowFlags(Qt::X11BypassWindowManagerHint); setUpdateCenterWidget(); setMouseTracking(true); qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); isCustom = configuration->getIsCustom(); if(isCustom){ cycleTime = configuration->getCycleTime(); isAutoSwitch = configuration->getAutoSwitch(); backgroundPath = configuration->getBackgroundPath(); isShowRestTime = configuration->getShowRestTime(); textIsCenter = configuration->getTextIsCenter(); myText = configuration->getMyText(); } initUI(); m_background = new MBackground(); QString backgroundFile = configuration->getDefaultBackground(); background = QPixmap(backgroundFile); QList labelList = this->findChildren(); for(int i = 0;isetAlignment(Qt::AlignCenter); } #ifndef USE_INTEL updateBackgroundPath(); startSwitchImages(); connectSingles(); #endif QGSettings *themeSettings; if(QGSettings::isSchemaInstalled(TIME_TYPE_SCHEMA)) themeSettings = new QGSettings(TIME_TYPE_SCHEMA,"",this); connect(themeSettings, &QGSettings::changed, this, &Screensaver::themeChanged); screenLabel = new QLabel(this); screenLabel->setObjectName("screenLabel"); screenLabel->setText(tr("Picture does not exist")); screenLabel->adjustSize(); screenLabel->hide(); } Screensaver::~Screensaver() { } void Screensaver::themeChanged() { if(myTextLabel){ QColor highLightColor = palette().color(QPalette::Base); QString stringColor = QString("rgba(%1,%2,%3,82%)") .arg(highLightColor.red()) .arg(highLightColor.green()) .arg(highLightColor.blue()); QColor textColor = palette().color(QPalette::Text); QString textString = QString("rgb(%1,%2,%3)") .arg(textColor.red()) .arg(textColor.green()) .arg(textColor.blue()); QColor borderColor = palette().color(QPalette::BrightText); QString borderString = QString("rgba(%1,%2,%3,85%)") .arg(borderColor.red()) .arg(borderColor.green()) .arg(borderColor.blue()); if(width() < 600 || height()<400) myTextLabel->setStyleSheet(QString("font-size:5px;border-radius: 2px;background: %1;color: %2;padding: 4px 8px 4px 8px;border-width: 1px;border-style: solid;border-color:%3;") \ .arg(stringColor).arg(textString).arg(borderString)); else myTextLabel->setStyleSheet(QString("font-size:18px;border-radius: 6px;background: %1;color: %2;padding: 24px 48px 24px 48px;border-width: 1px;border-style: solid;border-color:%3;") \ .arg(stringColor).arg(textString).arg(borderString)); } } void Screensaver::connectSingles() { connect(configuration, &SCConfiguration::autoSwitchChanged, this, &Screensaver::autoSwitchChanged); connect(configuration, &SCConfiguration::backgroundPathChanged, this, &Screensaver::backgroundPathChanged); connect(configuration, &SCConfiguration::cycleTimeChanged, this, &Screensaver::cycleTimeChanged); connect(configuration, &SCConfiguration::myTextChanged, this, &Screensaver::myTextChanged); connect(configuration, &SCConfiguration::showRestTimeChanged, this, &Screensaver::showRestTimeChanged); connect(configuration, &SCConfiguration::textIsCenterChanged, this, &Screensaver::textIsCenterChanged); connect(configuration, &SCConfiguration::messageNumberChanged, this, &Screensaver::onMessageNumberChanged); connect(configuration, &SCConfiguration::messageShowEnableChanged, this, &Screensaver::onMessageShowEnabledChanged); connect(configuration, &SCConfiguration::timeTypeChanged, this, &Screensaver::onTimeFormatChanged); connect(configuration, &SCConfiguration::dateTypeChanged, this, &Screensaver::onDateFormatChanged); } void Screensaver::onTimeFormatChanged(int type){ timeType = type; } void Screensaver::onDateFormatChanged(QString type){ dateType = type; } void Screensaver::onMessageNumberChanged(int num) { int number = configuration->getMessageNumber(); (configuration->getMessageShowEnable() && number > 0) ? showNotice() : hideNotice(); } void Screensaver::onMessageShowEnabledChanged(bool enabled) { int number = configuration->getMessageNumber(); (configuration->getMessageShowEnable() && number > 0) ? showNotice() : hideNotice(); } void Screensaver::autoSwitchChanged(bool isSwitch) { if(!isCustom) return ; isAutoSwitch = isSwitch; if(!isSwitch){ stopSwitchImages(); } startSwitchImages(); } /* * 图片路径改变 */ void Screensaver::backgroundPathChanged(QString path) { backgroundPath = path; if(!isCustom) return ; updateBackgroundPath();//更新图片路径 stopSwitchImages(); startSwitchImages(); } void Screensaver::cycleTimeChanged(int cTime) { cycleTime = cTime; if(!isCustom || !autoSwitch) return ; stopSwitchImages(); startSwitchImages(); } void Screensaver::myTextChanged(QString text) { if(!isCustom) return ; myText = text; if(textIsCenter && centerWidget){ if(centerlabel1) centerlabel1->setText(myText); if(centerlabel2){ centerlabel2->setText(""); centerlabel2->hide(); } if(authorlabel){ authorlabel->setText(""); authorlabel->hide(); } centerWidget->adjustSize(); centerWidget->setGeometry((width()-centerWidget->width())/2,(height()-centerWidget->height())/2, centerWidget->width(),centerWidget->height()); if((height()-centerWidget->height())/2 < timeLayout->y() + timeLayout->height()) centerWidget->setGeometry((width()-centerWidget->width())/2,timeLayout->y() + timeLayout->height(), centerWidget->width(),centerWidget->height()); }else{ setRandomText(); setRandomPos(); if(centerWidget) centerWidget->hide(); } } void Screensaver::showRestTimeChanged(bool isShow) { isShowRestTime = isShow; if(!isCustom) return; setSleeptime(isShowRestTime); } void Screensaver::textIsCenterChanged(bool isCenter) { textIsCenter = isCenter; if(!isCustom) return ; if(isCenter){ if(myTextWidget) myTextWidget->hide(); if(!centerWidget){ setCenterWidget(); resize(width(),height()); } else{ centerWidget->show(); myTextChanged(myText); } }else{ if(centerWidget) centerWidget->hide(); setRandomText(); setRandomPos(); } } bool Screensaver::eventFilter(QObject *obj, QEvent *event) { #ifndef USE_INTEL if(obj == this){ if(event->type()==QEvent::MouseButtonPress){ if(respondClick){ if(!process){ process = new QProcess(this); } process->start("ukui-screensaver-command -s"); } } } #endif return false; } void Screensaver::paintEvent(QPaintEvent *event) { QPainter painter(this); /*时间未同步的时候重新刷新一次,主要是避免睡眠唤醒时的时间跳变*/ if (m_currentTime.hour() != QTime::currentTime().hour() || m_currentTime.minute() != QTime::currentTime().minute()) { updateTime(); } if(isCustom && imagePaths.count()==0){ painter.setBrush(QColor("#000000")); if(screenLabel->isHidden()){ screenLabel->show(); } }else{ painter.drawPixmap(0,0,this->width(),this->height(), getPaddingPixmap()); painter.setBrush(QColor(0,0,0,178)); if(screenLabel->isVisible()) screenLabel->hide(); } /*这里是为了不显示笔的线条*/ painter.drawRect(-1,-1,this->width()+1,this->height()+1); } QPixmap Screensaver::getPaddingPixmap() { if (background.width() == 0 || background.height() == 0) { return QPixmap(); } bool useHeight; float scaled = 0.0; QPixmap scaledPixmap; QPixmap paddingPixmap; qint64 rw = qint64(this->height()) * qint64(background.width()) / qint64(background.height()); useHeight = (rw >= this->width()); if (useHeight) { scaled = float(this->height()) / float(background.height()); scaledPixmap = background.scaled(background.width() * scaled, this->height()); paddingPixmap = scaledPixmap.copy((background.width() * scaled - this->width()) / 2 , 0, this->width(), this->height()); } else { scaled = float(this->width()) / float(background.width()); scaledPixmap = background.scaled(this->width(), background.height() * scaled); paddingPixmap = scaledPixmap.copy(0 , (background.height() * scaled - this->height()) / 2,this->width(), this->height()); } return paddingPixmap; } void Screensaver::addClickedEvent(){ respondClick = true; } void Screensaver::resizeEvent(QResizeEvent */*event*/) { float scale = 1.0; scale = (float)width()/1920; if(width() < 600 || height()<400){//当显示在控制面板上时,字体缩小三倍。 if(flag == 0) { QList labelList = this->findChildren(); for(int i = 0;ifont().pixelSize(); #ifdef USE_INTEL const QString SheetStyle = QString("font-size:%1px;").arg(fontsize/3); #else const QString SheetStyle = QString("font-size:%1px;").arg(fontsize/4); #endif labelList.at(i)->setStyleSheet(SheetStyle); } QList childList = timeLayout->findChildren(); for (int i = 0; i < childList.count(); ++i) { childList.at(i)->adjustSize(); } timeLayout->adjustSize(); if(centerWidget) centerWidget->adjustSize(); } flag = 1; #ifndef USE_INTEL if(myTextWidget){ QColor highLightColor = palette().color(QPalette::Base); QString stringColor = QString("rgba(%1,%2,%3,82%)") .arg(highLightColor.red()) .arg(highLightColor.green()) .arg(highLightColor.blue()); QColor textColor = palette().color(QPalette::Text); QString textString = QString("rgb(%1,%2,%3)") .arg(textColor.red()) .arg(textColor.green()) .arg(textColor.blue()); QColor borderColor = palette().color(QPalette::BrightText); QString borderString = QString("rgba(%1,%2,%3,85%)") .arg(borderColor.red()) .arg(borderColor.green()) .arg(borderColor.blue()); myTextLabel->setStyleSheet(QString("font-size:5px;border-radius: 2px;background: %1;color: %2;padding: 4px 8px 4px 8px;border-width: 1px;border-style: solid;border-color:%3;") \ .arg(stringColor).arg(textString).arg(borderString)); cycleLabel->setSize(QSize(5,5)); } if(screenLabel) screenLabel->adjustSize(); if(sleepTime) sleepTime->setSmallMode(); #endif scale = 0.1; } #ifdef USE_INTEL int x = 840*scale; int y = 96*scale; m_weatherLaout->setGeometry((this->width()-m_weatherLaout->width())/2, y, m_weatherLaout->geometry().width(), m_weatherLaout->geometry().height()); timeLayout->setGeometry((this->width()-timeLayout->width())/2,m_weatherLaout->geometry().bottom()+33, timeLayout->geometry().width(),timeLayout->geometry().height()); if(centerWidget){ centerWidget->adjustSize(); centerWidget->setGeometry((width()-centerWidget->width())/2,(height() * 85) / 100 - (centerWidget->height())/2, centerWidget->width(),centerWidget->height()); if((height()-centerWidget->height())/2 < timeLayout->y() + timeLayout->height()) centerWidget->setGeometry((width()-centerWidget->width())/2,timeLayout->y() + timeLayout->height(), centerWidget->width(),centerWidget->height()); } if (m_widgetNotice) { m_widgetNotice->setGeometry((this->width()-m_widgetNotice->width())/2, (centerWidget->y() + centerWidget->height() + 20), m_widgetNotice->geometry().width(), m_widgetNotice->geometry().height()); } #else int x = (this->width()-timeLayout->geometry().width())/2; int y = 59*scale; timeLayout->setGeometry(x,y,timeLayout->geometry().width(),timeLayout->geometry().height()); if(sleepTime){ x = 26*scale; y = this->height() - sleepTime->geometry().height() - 26*scale; sleepTime->setGeometry(x,y,sleepTime->geometry().width(),sleepTime->geometry().height()); } if(screenLabel){ screenLabel->setGeometry((width() - screenLabel->width())/2,y,screenLabel->width(),screenLabel->height()); } if(centerWidget){ centerWidget->adjustSize(); centerWidget->setGeometry((width()-centerWidget->width())/2,(height()-centerWidget->height())/2, centerWidget->width(),centerWidget->height()); if((height()-centerWidget->height())/2 < timeLayout->y() + timeLayout->height()) centerWidget->setGeometry((width()-centerWidget->width())/2,timeLayout->y() + timeLayout->height(), centerWidget->width(),centerWidget->height()); } if(myTextWidget) setRandomPos(); #endif } void Screensaver::setRandomPos() { myTextWidget->adjustSize(); int x1 = 10; int x2 = width() - 10 - myTextWidget->width(); int y1 = timeLayout->geometry().bottom() + 10; int y2; if(sleepTime) y2 = sleepTime->geometry().top() - myTextWidget->height() - 10; else y2 = geometry().bottom() - myTextWidget->height() - 10; int x = 0; int y = 0; if(x2 > x1) x = qrand()%(x2 - x1) + x1; if(y2 > y1) y = qrand()%(y2 - y1) + y1; myTextWidget->move(x,y); } void Screensaver::setUpdateCenterWidget() { //QString lang = qgetenv("LANG"); QString lang = QLocale::system().name(); QString homePath=qgetenv("HOME"); QString cwdPath="/usr/share/ukui-screensaver/"; QString languageDirPath=cwdPath+"language/"; QString defaultLanguageFilePath=languageDirPath+"screensaver-en_US.ini"; qDebug()<<"homePath="< formats = QImageReader::supportedImageFormats(); if(fileInfo.isDir()) { QDir dir(backgroundPath); QStringList files = dir.entryList(QDir::Files | QDir::Readable); for(QString file : files) { fileInfo.setFile(file); QString suffix = fileInfo.suffix(); if(formats.contains(suffix.toUtf8()) && file.right(4) != ".ico" && file.right(4) != ".tga"){ // qDebug() << "file:" <start(cycleTime * 1000); } repaint(); } } void Screensaver::stopSwitchImages() { if(switchTimer && switchTimer->isActive()) switchTimer->stop(); } void Screensaver::onBackgroundChanged() { opacity = 1.0; fadeTimer = new QTimer(this); connect(fadeTimer, &QTimer::timeout, this, [&]{ opacity -= 0.1; if(opacity <= 0) fadeTimer->stop(); else repaint(); }); fadeTimer->start(50); } void Screensaver::updateCenterWidget(int index) { if(!centerWidget ) return ; QStringList qlist = qsettings->childGroups(); if(qlist.count()<1) return; if(index<=1){ index = qrand() % qlist.count() + 1; } qsettings->beginGroup(QString::number(index)); if(qsettings->contains("OL")){ centerlabel1->setText(qsettings->value("OL").toString()); centerlabel2->hide(); #ifndef USE_INTEL authorlabel->setText(qsettings->value("author").toString()); #endif } else if(qsettings->contains("FL")) { centerlabel1->setText(qsettings->value("FL").toString()); centerlabel2->setText(qsettings->value("SL").toString()); centerlabel2->show(); #ifndef USE_INTEL authorlabel->setText(qsettings->value("author").toString()); #endif } #ifdef USE_INTEL if(qsettings->contains("author") && !qsettings->value("author").toString().isEmpty()) { authorlabel->setText(qsettings->value("author").toString()); authorlabel->show(); } else { authorlabel->setText(""); authorlabel->hide(); } #endif centerWidget->adjustSize(); #ifdef USE_INTEL centerWidget->setGeometry((width()-centerWidget->width())/2,(height() * 85) / 100 - (centerWidget->height())/2, centerWidget->width(),centerWidget->height()); if((height()-centerWidget->height())/2 < timeLayout->y() + timeLayout->height()) centerWidget->setGeometry((width()-centerWidget->width())/2,timeLayout->y() + timeLayout->height(), centerWidget->width(),centerWidget->height()); #else centerWidget->setGeometry((width()-centerWidget->width())/2,(height()-centerWidget->height())/2, centerWidget->width(),centerWidget->height()); if((height()-centerWidget->height())/2 < timeLayout->y() + timeLayout->height()) centerWidget->setGeometry((width()-centerWidget->width())/2,timeLayout->y() + timeLayout->height(), centerWidget->width(),centerWidget->height()); #endif qsettings->endGroup(); } void Screensaver::initUI() { QFile qssFile; #ifdef USE_INTEL qssFile.setFileName(":/qss/assets/default-intel.qss"); #else qssFile.setFileName(":/qss/assets/default.qss"); #endif if(qssFile.open(QIODevice::ReadOnly)) { setStyleSheet(qssFile.readAll()); } qssFile.close(); #ifdef USE_INTEL setWeatherLayout(); setDatelayout(); setCenterWidget(); setNoticeLaout(); m_weatherManager->getWeather(); connect(m_weatherManager, &WeatherManager::onWeatherUpdate, this, &Screensaver::getWeatherFinish); #else if(isCustom) setSleeptime(isShowRestTime); else setSleeptime(true); setDatelayout(); setCenterWidget(); setRandomText(); if(textIsCenter || myText == ""){ myTextWidget->hide(); centerWidget->show(); }else{ centerWidget->hide(); myTextWidget->show(); } #endif } void Screensaver::setDatelayout() { timeType = configuration->getTimeType(); dateType = configuration->getDateType(); #ifdef USE_INTEL timeLayout = new QWidget(this); timeLayout->setFixedSize(((timeType == 12) ? 397:326), 117); QHBoxLayout *htimeLayout = new QHBoxLayout(timeLayout); htimeLayout->setContentsMargins(0,0,0,0); QWidget *timeWidget = new QWidget(this); timeWidget->setFixedSize(235, 117); QGridLayout *gtimeLayout = new QGridLayout(timeWidget); gtimeLayout->setContentsMargins(0,0,0,12); this->dateOfLocaltimeHour = new QLabel(this); this->dateOfLocaltimeHour->setObjectName("dateOfLocaltime"); this->dateOfLocaltimeHour->setAlignment(Qt::AlignTop | Qt::AlignLeft); this->dateOfLocaltimeHour->setFixedSize(107, 96); this->dateofLocaltimeColon = new QLabel(this); this->dateofLocaltimeColon->setObjectName("dateOfLocaltime"); this->dateofLocaltimeColon->setAlignment(Qt::AlignCenter); this->dateofLocaltimeColon->setFixedSize(21, 96); this->dateofLocaltimeColon->setText(":"); this->dateOfLocaltimeMinute = new QLabel(this); this->dateOfLocaltimeMinute->setObjectName("dateOfLocaltime"); this->dateOfLocaltimeMinute->setAlignment(Qt::AlignTop | Qt::AlignLeft); this->dateOfLocaltimeMinute->setFixedSize(107, 96); gtimeLayout->setSpacing(0); gtimeLayout->setRowMinimumHeight(0, 9); gtimeLayout->setRowMinimumHeight(1, 87); gtimeLayout->setRowMinimumHeight(2, 9); gtimeLayout->setColumnMinimumWidth(0, 107); gtimeLayout->setColumnMinimumWidth(1, 21); gtimeLayout->setColumnMinimumWidth(2, 107); gtimeLayout->addWidget(dateOfLocaltimeHour, 1, 0, 2, 1); gtimeLayout->addWidget(dateofLocaltimeColon, 0, 1, 2, 1); gtimeLayout->addWidget(dateOfLocaltimeMinute, 1, 2, 2, 1); QWidget *dateWidget = new QWidget(this); dateWidget->setFixedSize(((timeType == 12) ? 154:83), 117); QVBoxLayout *vDateLaout = new QVBoxLayout(dateWidget); vDateLaout->setAlignment(Qt::AlignTop | Qt::AlignLeft); vDateLaout->setContentsMargins(0,18,0,12); this->dateOfWeek = new QLabel(this); this->dateOfWeek->setObjectName("dateOfWeek"); this->dateOfWeek->setAlignment(Qt::AlignTop | Qt::AlignLeft); this->dateOfWeek->setFixedWidth(83); this->dateOfDay = new QLabel(this); this->dateOfDay->setObjectName("dateOfDay"); this->dateOfDay->setAlignment(Qt::AlignTop | Qt::AlignLeft); this->dateOfDay->setFixedSize(((timeType == 12) ? 154:83),32); updateTime(); updateDate(); this->dateOfWeek->adjustSize(); vDateLaout->addWidget(dateOfWeek); vDateLaout->setSpacing(4); vDateLaout->addWidget(dateOfDay); htimeLayout->addWidget(timeWidget); htimeLayout->addSpacing(8); htimeLayout->addWidget(dateWidget); #else timeLayout = new QWidget(this); QVBoxLayout *vtimeLayout = new QVBoxLayout(timeLayout); this->dateOfLocaltime = new QLabel(this); if(timeType == 12) this->dateOfLocaltime->setText(QDateTime::currentDateTime().toString("A hh:mm")); else this->dateOfLocaltime->setText(QDateTime::currentDateTime().toString("hh:mm")); this->dateOfLocaltime->setObjectName("dateOfLocaltime"); this->dateOfLocaltime->setAlignment(Qt::AlignCenter); this->dateOfLocaltime->adjustSize(); vtimeLayout->addWidget(dateOfLocaltime); this->dateOfDay = new QLabel(this); if(dateType == "cn") this->dateOfDay->setText(QDate::currentDate().toString("yyyy/MM/dd ddd")); else this->dateOfDay->setText(QDate::currentDate().toString("yyyy-MM-dd ddd")); this->dateOfDay->setObjectName("dateOfDay"); this->dateOfDay->setAlignment(Qt::AlignCenter); this->dateOfDay->adjustSize(); vtimeLayout->addWidget(this->dateOfDay); timeLayout->adjustSize(); updateDate(); #endif } void Screensaver::setWeatherLayout() { m_weatherLaout = new QWidget(this); QHBoxLayout *hWeatherLayout = new QHBoxLayout(m_weatherLaout); hWeatherLayout->setContentsMargins(0, 0, 0, 0); this->m_weatherIcon = new QLabel(this); this->m_weatherArea = new QLabel(this); this->m_weatherCond = new QLabel(this); this->m_weatherTemperature = new QLabel(this); m_weatherIcon->setPixmap(m_weatherManager->getWeatherIcon()); m_weatherArea->setText(m_weatherManager->getCityName()); if (!m_weatherManager->getCond().isEmpty()) m_weatherCond->setText("·" + m_weatherManager->getCond()); m_weatherTemperature->setText(m_weatherManager->getTemperature()); m_weatherArea->setStyleSheet("font-size:26px;color:#ffffff"); m_weatherCond->setStyleSheet("font-size:26px;color:#ffffff"); m_weatherTemperature->setStyleSheet("font-size:26px;color:#ffffff"); hWeatherLayout->addWidget(m_weatherIcon); hWeatherLayout->addSpacing(8); hWeatherLayout->addWidget(m_weatherArea); hWeatherLayout->addWidget(m_weatherCond); hWeatherLayout->addSpacing(8); hWeatherLayout->addWidget(m_weatherTemperature); m_weatherLaout->adjustSize(); } void Screensaver::setSleeptime(bool Isshow) { if(!sleepTime) sleepTime = new SleepTime(this); sleepTime->adjustSize(); if(Isshow){ sleepTime->show(); } else{ sleepTime->hide(); if(timer){ timer->stop(); } } } void Screensaver::updateDate() { if(!timer){ timer = new QTimer(this); connect(timer, SIGNAL(timeout()), this, SLOT(updateTime())); } timer->start(1000); updateTime(); } void Screensaver::updateTime() { #ifdef USE_INTEL QLocale locale(QLocale::system().name()); QTimeZone timeZone(QString::fromLatin1(QTimeZone::systemTimeZoneId()).toLatin1()); QDateTime tzNow = QDateTime::currentDateTime().toTimeZone(timeZone); QString time; if (timeType == 12) { time = tzNow.toString("hh:mm AP").split(" ").at(0); this->dateOfWeek->setText(tzNow.toString("AP")); if(dateType == "en") { this->dateOfDay->setText(tzNow.toString("ddd MM-dd")); } else { this->dateOfDay->setText(tzNow.toString("ddd MM/dd")); } } else { time = tzNow.toString("hh:mm"); this->dateOfWeek->setText(tzNow.toString("ddd")); if(dateType == "en") { this->dateOfDay->setText(tzNow.toString("MM-dd")); } else { this->dateOfDay->setText(tzNow.toString("MM/dd")); } } this->dateOfLocaltimeHour->setText(time.split(":").at(0)); this->dateOfLocaltimeMinute->setText(time.split(":").at(1)); m_currentTime = QTime::currentTime(); #else if(timeType == 12) this->dateOfLocaltime->setText(QDateTime::currentDateTime().toString("A hh:mm")); else this->dateOfLocaltime->setText(QDateTime::currentDateTime().toString("hh:mm")); if(dateType == "cn") this->dateOfDay->setText(QDate::currentDate().toString("yyyy/MM/dd ddd")); else this->dateOfDay->setText(QDate::currentDate().toString("yyyy-MM-dd ddd")); if(sleepTime){ if(!sleepTime->setTime(QDateTime::currentDateTime())){ sleepTime->hide(); delete sleepTime; sleepTime=NULL; } } #endif } void Screensaver::setUpdateBackground() { } void Screensaver::updateBackground() { QString path = m_background->getRand(); if(!path.isEmpty() && ispicture(path)){ background = QPixmap(path); repaint(); hasChanged=true; } // updateCenterWidget(-1); } void Screensaver::setRandomText() { if(!myTextWidget){ myTextWidget = new QWidget(this); QHBoxLayout *layout = new QHBoxLayout(myTextWidget); cycleLabel = new CycleLabel(this); layout->addWidget(cycleLabel); layout->setSpacing(16); myTextLabel = new QLabel(myTextWidget); myTextLabel->setObjectName("myText"); myTextLabel->setBackgroundRole(QPalette::Base); myTextLabel->setAutoFillBackground(true); myTextLabel->setMaximumWidth(800); QColor highLightColor = palette().color(QPalette::Base); QString stringColor = QString("rgba(%1,%2,%3,82%)") .arg(highLightColor.red()) .arg(highLightColor.green()) .arg(highLightColor.blue()); QColor textColor = palette().color(QPalette::Text); QString textString = QString("rgb(%1,%2,%3)") .arg(textColor.red()) .arg(textColor.green()) .arg(textColor.blue()); QColor borderColor = palette().color(QPalette::BrightText); QString borderString = QString("rgba(%1,%2,%3,85%)") .arg(borderColor.red()) .arg(borderColor.green()) .arg(borderColor.blue()); myTextLabel->setStyleSheet(QString("font-size:18px;border-radius: 6px;background: %1;color: %2;padding: 24px 48px 24px 48px;border-width: 1px;border-style: solid;border-color:%3;") \ .arg(stringColor).arg(textString).arg(borderString)); layout->addWidget(myTextLabel); } myTextLabel->setText(myText); myTextWidget->adjustSize(); if(myText != "") myTextWidget->setVisible(true); else myTextWidget->setVisible(false); } void Screensaver::setPreviewText(bool bVisible) { if(!myPreviewLabel){ myPreviewLabel = new QLabel(this); myPreviewLabel->setFixedSize(58,30); //设置样式 myPreviewLabel->setStyleSheet("background-color: rgb(38,38,38); border-radius: 0px; color:white;"); //先采取固定大小方式 myPreviewLabel->move(120,142); myPreviewLabel->setAlignment(Qt::AlignCenter); } myPreviewLabel->setText(tr("View")); myPreviewLabel->adjustSize(); myPreviewLabel->setVisible(bVisible); } void Screensaver::setCenterWidget() { QStringList qlist = qsettings->childGroups(); if(qlist.count()<1) return; QDate date = QDate::currentDate(); int days = date.daysTo(QDate(2100,1,1)); int index = days%qlist.count()+1; QString configPath = QDir::homePath() + "/.ukui-screensaver-default.conf"; QSettings settings1(configPath, QSettings::IniFormat); if(settings1.value("FIRST").toString().isEmpty()){ settings1.setValue("FIRST",QDate::currentDate().toString("yy/MM/dd")); index = 1; } if(settings1.value("FIRST").toString() == QDate::currentDate().toString("yy/MM/dd")) index = 1; qsettings->beginGroup(QString::number(index)); if(isCustom){ centerlabel1 = new QLabel(myText); centerlabel2 = new QLabel(""); centerlabel2->hide(); authorlabel = new QLabel(""); } else if(qsettings->contains("OL")){ centerlabel1 = new QLabel(qsettings->value("OL").toString()); centerlabel2 = new QLabel(""); centerlabel2->hide(); #ifndef USE_INTEL authorlabel = new QLabel(qsettings->value("author").toString()); #endif } else if(qsettings->contains("FL")) { centerlabel1 = new QLabel(qsettings->value("FL").toString()); centerlabel2 = new QLabel(qsettings->value("SL").toString()); centerlabel2->show(); #ifndef USE_INTEL authorlabel = new QLabel(qsettings->value("author").toString()); #endif } #ifdef USE_INTEL if(qsettings->contains("author") && !qsettings->value("author").toString().isEmpty()) { authorlabel = new QLabel(qsettings->value("author").toString()); authorlabel->show(); } else { authorlabel = new QLabel(""); authorlabel->hide(); } #endif centerlabel1->setObjectName("centerLabel"); centerlabel2->setObjectName("centerLabel"); authorlabel->setObjectName("authorLabel"); qsettings->endGroup(); #ifdef USE_INTEL //设置背景透明,qss中更改为透明不生效 centerlabel1->setStyleSheet("QLabel{background-color: transparent;}"); centerlabel2->setStyleSheet("QLabel{background-color: transparent;}"); authorlabel->setStyleSheet("QLabel{background-color: transparent;}"); centerWidget = new QWidget(this); centerWidget->setStyleSheet("QWidget{background:rgb(0,0,0,64);border-radius:16px}"); QVBoxLayout *layout = new QVBoxLayout(centerWidget); // QPushButton *line =new QPushButton(this); // line->setWindowOpacity(0.08); // line->setFocusPolicy(Qt::NoFocus); // line->setMaximumHeight(1); layout->addWidget(centerlabel1); layout->addWidget(centerlabel2); // layout->addWidget(line); layout->addWidget(authorlabel); adjustSize(); centerWidget->setVisible(true); #else centerWidget = new QWidget(this); QVBoxLayout *layout = new QVBoxLayout(centerWidget); layout->addWidget(centerlabel1); layout->addWidget(centerlabel2); if(!isCustom){ QPushButton *line =new QPushButton(this); line->setWindowOpacity(0.08); line->setFocusPolicy(Qt::NoFocus); line->setMaximumHeight(1); layout->addWidget(line); } layout->addWidget(authorlabel); centerWidget->adjustSize(); centerWidget->setGeometry((width()-centerWidget->width())/2,(height()-centerWidget->height())/2, centerWidget->width(),centerWidget->height()); centerWidget->setVisible(true); #endif } void Screensaver::getWeatherFinish(QString city, QString cond, QString tmp) { qDebug() << "getWeatherFinish"; qDebug() << city << "," << cond << "," << tmp; this->m_weatherIcon->setPixmap(m_weatherManager->getWeatherIcon(cond)); this->m_weatherArea->setText(city); if(!cond.isEmpty()) { this->m_weatherCond->show(); this->m_weatherCond->setText("·" + cond); } else this->m_weatherCond->hide(); if(!tmp.isEmpty()) { this->m_weatherTemperature->show(); this->m_weatherTemperature->setText(tmp); } else this->m_weatherTemperature->hide(); m_weatherLaout->adjustSize(); m_weatherLaout->setGeometry((this->width()-m_weatherLaout->width())/2,96 * (float)width()/1920, m_weatherLaout->geometry().width(), m_weatherLaout->geometry().height()); } void Screensaver::setNoticeLaout() { m_widgetNotice = new QWidget(this); QHBoxLayout *hNoticeLayout = new QHBoxLayout(m_widgetNotice); hNoticeLayout->setContentsMargins(0, 0, 0, 0); m_labelNoticeIcon = new QLabel(this); m_labelNoticeMessage = new QLabel(this); m_labelNoticeMessage->setStyleSheet("font-size:16px;color:#ffffff"); m_labelNoticeIcon->setPixmap(QPixmap(":/assets/message.png")); m_labelNoticeMessage->setText(tr("You have new notification")); int num = configuration->getMessageNumber(); (configuration->getMessageShowEnable() && num > 0)? showNotice() : hideNotice(); hNoticeLayout->addWidget(m_labelNoticeIcon); hNoticeLayout->addWidget(m_labelNoticeMessage); m_widgetNotice->adjustSize(); } //显示新消息通知 void Screensaver::showNotice() { m_widgetNotice->show(); } void Screensaver::hideNotice() { m_widgetNotice->hide(); } /* void Screensaver::setDesktopBackground() { vboxFrame->hide(); QString mBackground; if(!hasChanged){ mBackground=defaultBackground; }else{ if(m_background->getCurrent().isEmpty()) return; mBackground=m_background->getCurrent(); } settings->set("picture-filename",QVariant(mBackground)); QDBusInterface * interface = new QDBusInterface("org.freedesktop.Accounts", "/org/freedesktop/Accounts", "org.freedesktop.Accounts", QDBusConnection::systemBus()); if (!interface->isValid()){ return; } QDBusReply reply = interface->call("FindUserByName", getenv("USER")); QString userPath; if (reply.isValid()){ userPath = reply.value().path(); } else { return; } QDBusInterface * useriFace = new QDBusInterface("org.freedesktop.Accounts", userPath, "org.freedesktop.Accounts.User", QDBusConnection::systemBus()); if (!useriFace->isValid()){ return; } QDBusMessage msg = useriFace->call("SetBackgroundFile", mBackground); if (!msg.errorMessage().isEmpty()) qDebug() << "update user background file error: " << msg.errorMessage(); }*/ ukui-screensaver/screensaver/assets/0000755000175000017500000000000014205074704016616 5ustar fengfengukui-screensaver/screensaver/assets/download.svg0000644000175000017500000000113414205074704021145 0ustar fengfeng下载ukui-screensaver/screensaver/assets/logo.svg0000644000175000017500000002762614205074704020314 0ustar fengfeng ukui-screensaver/screensaver/assets/weather-icon/0000755000175000017500000000000014205074704021203 5ustar fengfengukui-screensaver/screensaver/assets/weather-icon/100.svg0000644000175000017500000000300514205074704022222 0ustar fengfeng100-晴-SunnyClearukui-screensaver/screensaver/assets/weather-icon/510.svg0000644000175000017500000000116114205074704022230 0ustar fengfeng510-强浓雾-Strong fogukui-screensaver/screensaver/assets/weather-icon/213.svg0000644000175000017500000000161214205074704022231 0ustar fengfeng213-热带风暴Tropical Stormukui-screensaver/screensaver/assets/weather-icon/403.svg0000644000175000017500000000666214205074704022244 0ustar fengfeng403-暴雪-Snowstormukui-screensaver/screensaver/assets/weather-icon/202.svg0000644000175000017500000000077614205074704022241 0ustar fengfeng202-微风-Light Breezeukui-screensaver/screensaver/assets/weather-icon/._511-中度霾-Moderate haze.svg0000644000175000017500000001000014205074704030502 0ustar fengfengMac OS X  2ATTR;Xcom.apple.lastuseddate#PSHcom.apple.maclP^#IL Nn 1'This resource fork intentionally left blank ukui-screensaver/screensaver/assets/weather-icon/312.svg0000644000175000017500000000375214205074704022240 0ustar fengfeng312-特大暴雨-Severe Stormukui-screensaver/screensaver/assets/weather-icon/300.svg0000644000175000017500000000211514205074704022225 0ustar fengfeng300-阵雨-Shower Rainukui-screensaver/screensaver/assets/weather-icon/501.svg0000644000175000017500000000123514205074704022232 0ustar fengfeng501-雾-Foggyukui-screensaver/screensaver/assets/weather-icon/406.svg0000644000175000017500000000264214205074704022241 0ustar fengfeng406-阵雨夹雪-Shower Snowukui-screensaver/screensaver/assets/weather-icon/410.svg0000644000175000017500000000670614205074704022241 0ustar fengfeng410-大到暴雪-Heavy snow to snowstormukui-screensaver/screensaver/assets/weather-icon/204.svg0000644000175000017500000000077614205074704022243 0ustar fengfeng204-清风-Fresh Breezeukui-screensaver/screensaver/assets/weather-icon/900.svg0000644000175000017500000000403714205074704022240 0ustar fengfeng900-热-Hotukui-screensaver/screensaver/assets/weather-icon/404.svg0000644000175000017500000000244714205074704022242 0ustar fengfeng404-雨夹雪-Sleetukui-screensaver/screensaver/assets/weather-icon/203.svg0000644000175000017500000000101014205074704022220 0ustar fengfeng203-和风-Moderate Gentle Breezeukui-screensaver/screensaver/assets/weather-icon/102.svg0000644000175000017500000000113214205074704022223 0ustar fengfeng102-少云-Few Cloudsukui-screensaver/screensaver/assets/weather-icon/306.svg0000644000175000017500000000166114205074704022240 0ustar fengfeng306-中雨-Moderate Rainukui-screensaver/screensaver/assets/weather-icon/308.svg0000644000175000017500000000334314205074704022241 0ustar fengfeng308-极端降雨-Extreme Rainukui-screensaver/screensaver/assets/weather-icon/._.DS_Store0000644000175000017500000001000014205074704023072 0ustar fengfengMac OS X  2 @ATTR;xThis resource fork intentionally left blank ukui-screensaver/screensaver/assets/weather-icon/104.svg0000644000175000017500000000221514205074704022230 0ustar fengfeng104-阴-Overcastukui-screensaver/screensaver/assets/weather-icon/307.svg0000644000175000017500000000237714205074704022246 0ustar fengfeng307-大雨-Heavy Rainukui-screensaver/screensaver/assets/weather-icon/504.svg0000644000175000017500000000212214205074704022231 0ustar fengfeng504-浮尘-Dustukui-screensaver/screensaver/assets/weather-icon/405.svg0000644000175000017500000000355414205074704022243 0ustar fengfeng405-雨雪天气-Rain And Snowukui-screensaver/screensaver/assets/weather-icon/313.svg0000644000175000017500000000161514205074704022235 0ustar fengfeng313-冻雨-Freezing Rainukui-screensaver/screensaver/assets/weather-icon/509.svg0000644000175000017500000000137614205074704022250 0ustar fengfeng509-浓雾-Dense fogukui-screensaver/screensaver/assets/weather-icon/303.svg0000644000175000017500000000274714205074704022243 0ustar fengfeng303-强雷阵雨-Heavy Thunderstormukui-screensaver/screensaver/assets/weather-icon/305.svg0000644000175000017500000000143314205074704022234 0ustar fengfeng305-小雨-Light Rainukui-screensaver/screensaver/assets/weather-icon/515.svg0000644000175000017500000000134114205074704022235 0ustar fengfeng515-特强浓雾-Extra heavy fogukui-screensaver/screensaver/assets/weather-icon/208.svg0000644000175000017500000000114514205074704022236 0ustar fengfeng208-烈风Strong Galeukui-screensaver/screensaver/assets/weather-icon/304.svg0000644000175000017500000000213214205074704022230 0ustar fengfeng304-雷阵雨伴有冰雹-hailThundershower with hailukui-screensaver/screensaver/assets/weather-icon/407.svg0000644000175000017500000000340614205074704022241 0ustar fengfeng407-阵雪-Snow Flurryukui-screensaver/screensaver/assets/weather-icon/508.svg0000644000175000017500000000553114205074704022244 0ustar fengfeng508-强沙尘暴-Sandstormukui-screensaver/screensaver/assets/weather-icon/500.svg0000644000175000017500000000107114205074704022227 0ustar fengfeng500-薄雾-Mist ukui-screensaver/screensaver/assets/weather-icon/209.svg0000644000175000017500000000103314205074704022233 0ustar fengfeng209-风暴-Stormukui-screensaver/screensaver/assets/weather-icon/502.svg0000644000175000017500000000124514205074704022234 0ustar fengfeng502-霾-Hazeukui-screensaver/screensaver/assets/weather-icon/210.svg0000644000175000017500000000104614205074704022227 0ustar fengfeng210-狂爆风-Violent Stormukui-screensaver/screensaver/assets/weather-icon/211.svg0000644000175000017500000000103714205074704022230 0ustar fengfeng211-飓风-Hurricaneukui-screensaver/screensaver/assets/weather-icon/999.svg0000644000175000017500000000430214205074704022255 0ustar fengfeng 天气 ukui-screensaver/screensaver/assets/weather-icon/200.svg0000644000175000017500000000072514205074704022231 0ustar fengfeng200-有风-Windyukui-screensaver/screensaver/assets/weather-icon/310.svg0000644000175000017500000000332614205074704022233 0ustar fengfeng310-暴雨-Stormukui-screensaver/screensaver/assets/weather-icon/408.svg0000644000175000017500000000325214205074704022241 0ustar fengfeng408-小到中雪-Light to moderate snowukui-screensaver/screensaver/assets/weather-icon/400.svg0000644000175000017500000000232514205074704022231 0ustar fengfeng400-小雪-Light Snowukui-screensaver/screensaver/assets/weather-icon/499.svg0000644000175000017500000000245014205074704022252 0ustar fengfeng499-雪-snowukui-screensaver/screensaver/assets/weather-icon/206.svg0000644000175000017500000000115714205074704022237 0ustar fengfeng206-疾风-High Wind, Near Galeukui-screensaver/screensaver/assets/weather-icon/207.svg0000644000175000017500000000072414205074704022237 0ustar fengfeng207-大风-Galeukui-screensaver/screensaver/assets/weather-icon/401.svg0000644000175000017500000000323314205074704022231 0ustar fengfeng401-中雪-Moderate Snowukui-screensaver/screensaver/assets/weather-icon/311.svg0000644000175000017500000000374614205074704022242 0ustar fengfeng311-大暴雨-Heavy Stormukui-screensaver/screensaver/assets/weather-icon/301.svg0000644000175000017500000000240214205074704022225 0ustar fengfeng301-强阵雨-Heavy Shower Rainukui-screensaver/screensaver/assets/weather-icon/103.svg0000644000175000017500000000101414205074704022223 0ustar fengfeng103-晴间多云-Partly Cloudyukui-screensaver/screensaver/assets/weather-icon/507.svg0000644000175000017500000000164514205074704022245 0ustar fengfeng507-沙尘暴-Duststormukui-screensaver/screensaver/assets/weather-icon/315.svg0000644000175000017500000000242114205074704022233 0ustar fengfeng315-中到大雨-Moderate to heavy rainukui-screensaver/screensaver/assets/weather-icon/212.svg0000644000175000017500000000205314205074704022230 0ustar fengfeng212-龙卷风-Tornadoukui-screensaver/screensaver/assets/weather-icon/317.svg0000644000175000017500000000377014205074704022245 0ustar fengfeng317-暴雨到大暴雨-Storm to heavy stormukui-screensaver/screensaver/assets/weather-icon/402.svg0000644000175000017500000000471514205074704022240 0ustar fengfeng402-大雪-Heavy Snowukui-screensaver/screensaver/assets/weather-icon/513.svg0000644000175000017500000000134414205074704022236 0ustar fengfeng513-严重霾-Severe hazeukui-screensaver/screensaver/assets/weather-icon/318.svg0000644000175000017500000000377714205074704022255 0ustar fengfeng318-大暴雨到特大暴雨-Heavy to severe stormukui-screensaver/screensaver/assets/weather-icon/503.svg0000644000175000017500000000121214205074704022227 0ustar fengfeng503-扬沙-Sandukui-screensaver/screensaver/assets/weather-icon/514.svg0000644000175000017500000000116514205074704022240 0ustar fengfeng514-大雾-Heavy fogukui-screensaver/screensaver/assets/weather-icon/512.svg0000644000175000017500000000117114205074704022233 0ustar fengfeng512-重度霾-Heavy hazeukui-screensaver/screensaver/assets/weather-icon/316.svg0000644000175000017500000000335214205074704022240 0ustar fengfeng316-大到暴雨-Heavy rain to stormukui-screensaver/screensaver/assets/weather-icon/314.svg0000644000175000017500000000170014205074704022231 0ustar fengfeng314-小到中雨-Light to moderate rainukui-screensaver/screensaver/assets/weather-icon/201.svg0000644000175000017500000000074614205074704022235 0ustar fengfeng201-平静-Calmukui-screensaver/screensaver/assets/weather-icon/.DS_Store0000644000175000017500000003400414205074704022667 0ustar fengfengBud100 D7-Y'-H307-Y'-Heavy Rain.svgIlocblobax01-YN-Cloudy.svgIlocblob  @ @ @ @)308-gzM-Extreme Rain.svgIlocblobx309-kkۖ~Ɩ-Drizzle Rain.svgIlocblob;310-f-Storm.svgIlocblob311-Y'f-Heavy Storm.svgIlocblob312-ryY'f-Severe Storm.svgIlocblob313-Q-Freezing Rain.svgIlocblob#314-\R0N--Light to moderate rain.svgIlocbloba#315-N-R0Y'-Moderate to heavy rain.svgIlocblob 316-Y'R0f-Heavy rain to storm.svgIlocblob;X#317-fR0Y'f-Storm to heavy storm.svgIlocblobX&318-Y'fR0ryY'f-Heavy to severe storm.svgIlocblobX399--Rain.svgIlocblobX400-\-Light Snow.svgIlocblobX401-N--Moderate Snow.svgIlocblobaX402-Y'-Heavy Snow.svgIlocblobX403-f-Snowstorm.svgIlocblob;404-Y9-Sleet.svgIlocblob405-Y)l-Rain And Snow.svgIlocblob406-5Y9-Shower Snow.svgIlocblob407-5-Snow Flurry.svgIlocblob#408-\R0N--Light to moderate snow.svgIlocbloba#409-N-R0Y'-Moderate to heavy snow.svgIlocblob$410-Y'R0f-Heavy snow to snowstorm.svgIlocblob;8499--snow.svgIlocblob8500--Mist .svgIlocblob8501--Foggy.svgIlocblob8502->-Haze.svgIlocblob8503-bll-Sand.svgIlocbloba8504-mn\-Dust.svgIlocblob8507-l\f-Duststorm.svgIlocblob;508-_:l\f-Sandstorm.svgIlocblob509-mS-Dense fog.svgIlocblob510-_:mS-Strong fog.svgIlocblob511-N-^>-Moderate haze.svgIlocblob512-^>-Heavy haze.svgIlocbloba513-N%͗>-Severe haze.svgIlocblob514-Y'-Heavy fog.svgIlocblob;515-ry_:mS-Extra heavy fog.svgIlocblob 900-p-Hot.svgIlocblob901-Q-Cold.svgIlocblob999-g*w-Unknown.svgIlocblob100-ft-SunnyClear.svgIlocblob;(101-YN-Cloudy.svgIlocblob(102-\N-Few Clouds.svgIlocblob(103-ftYN-Partly Cloudy.svgIlocblob(104-4-Overcast.svgIlocblob(200-g -Windy.svgIlocbloba(201-^sY-Calm.svgIlocblob(202-_-Light Breeze.svgIlocblob;!203-T-Moderate Gentle Breeze.svgIlocblob204-n-Fresh Breeze.svgIlocblob205-_:R-Strong Breeze.svgIlocblob206-u-High Wind, Near Gale.svgIlocblob207-Y'-Gale.svgIlocbloba208-pȘStrong Gale.svgIlocblob209-f-Storm.svgIlocblob;210-rr-Violent Storm.svgIlocblob211-Ә-Hurricane.svgIlocblob212-Sw-Tornado.svgIlocblob213-p^&fTropical Storm.svgIlocblob300-5-Shower Rain.svgIlocbloba301-_:5-Heavy Shower Rain.svgIlocblob302-5-Thundershower.svgIlocblob;x303-_:5-Heavy Thunderstorm.svgIlocblobx+304-5O4g Q-hailThundershower with hail.svgIlocblobx305-\-Light Rain.svgIlocblobx306-N--Moderate Rain.svgIlocblobxsvgIlocblob8501--Foggy.svgIlocblob8502->-Haze.svgIlocblob8503-bll-Sand.svgIlocbloba8504-mn\-Dust.svgIlocblob8507-l\f-Duststorm.svgIlocblob;508-_:l\f-Sandstorm.svgIlocblob509-mS-Dense fog.svgIlocblob510-_:mS-Strong fog.svgIlocblob511-N-^>-Moderate haze.svgIlocblob512-^>-Heavy haze.svgIlocbloba513-N%͗>-Severe haze.svgIlocblob514-Y'-Heavy fog.svgIlocblob;515-ry_:mS-Extra heavy fog.svgIlocblob 900-p-Hot.svgIlocblob901-Q-Cold.svgIlocblob999-g*w-Unknown.svgIlocblob0 E DSDB `8@ @ @212-Sw-Tornado.svgIlocblob213-p^&fTropical Storm.svgIlocblob300-5-Shower Rain.svgIlocbloba301-_:5-Heavy Shower Rain.svgIlocblob302-5-Thundershower.svgIlocblob;x303-_:5-Heavy Thunderstorm.svgIlocblobx+304-5O4g Q-hailThundershower with hail.svgIlocblobx305-\-Light Rain.svgIlocblobx306-N--Moderate Rain.svgIlocblobxukui-screensaver/screensaver/assets/weather-icon/409.svg0000644000175000017500000000510714205074704022243 0ustar fengfeng409-中到大雪-Moderate to heavy snowukui-screensaver/screensaver/assets/weather-icon/101.svg0000644000175000017500000000152614205074704022231 0ustar fengfeng101-多云-Cloudyukui-screensaver/screensaver/assets/weather-icon/399.svg0000644000175000017500000000041514205074704022250 0ustar fengfeng399-雨-Rainukui-screensaver/screensaver/assets/weather-icon/302.svg0000644000175000017500000000222714205074704022233 0ustar fengfeng302-雷阵雨-Thundershowerukui-screensaver/screensaver/assets/weather-icon/205.svg0000644000175000017500000000115614205074704022235 0ustar fengfeng205-强风劲风-Strong Breezeukui-screensaver/screensaver/assets/weather-icon/511.svg0000644000175000017500000000142314205074704022232 0ustar fengfeng511-中度霾-Moderate hazeukui-screensaver/screensaver/assets/weather-icon/901.svg0000644000175000017500000000420014205074704022231 0ustar fengfeng901-冷-Coldukui-screensaver/screensaver/assets/weather-icon/309.svg0000644000175000017500000000160614205074704022242 0ustar fengfeng309-毛毛雨细雨-Drizzle Rainukui-screensaver/screensaver/assets/default.qss0000644000175000017500000000334314205074704020775 0ustar fengfengQLabel#dateOfWeek { font-size:16px; color: #ffffff; } QLabel#dateOfLocaltime { font-size:50px; color: #ffffff; } QLabel#dateOfDay { font-size:16px; color: #ffffff; } QLabel#dateOfLunar { font-size:16px; color: #ffffff; } QLabel#clockTime { background:rgba(255,255,255,0.15); border-radius: 6px; font-size:20px; color: #ffffff; } QLabel#colon { font-size:20px; color: #ffffff; } QLabel#restTime { font-size:20px; color: #ffffff; opacity:0.6; } QLabel#centerLabel { font-size:36px; color: #ffffff; } QLabel#authorLabel { font-size:28px; color: #ffffff; } QLabel#myText{ font-size:18px; border-radius: 6px; background: rgba(255, 255, 255, 82%); padding: 24px 48px 24px 48px; color: #000000; } QPushButton{ background:rgba(255,255,255,0.12); } #escButton,#prevButton,#nextButton,#settingsButton{ background: rgba(255, 255, 255, 12%); border-radius:24px; border-size:0px; color:white; icon-size:24px; } #escButton::hover,#prevButton::hover,#nextButton::hover,#settingsButton::hover { background: rgba(255, 255, 255, 30%); } #escButton::pressed,#prevButton::pressed,#nextButton::pressed,#settingsButton::pressed { background: rgba(255, 255, 255, 8%); } #vboxFrame{ background: rgba(255, 255, 255, 12%); border: 0px; border-radius:4px; } #WallpaperButton{ background: rgba(255, 255, 255, 0%); border-radius:4px; color:white; icon-size:24px; } #WallpaperButton::hover{ background: rgba(61, 107, 229, 255); } #autoSwitchLabel{ font-size:14px; color: #ffffff; } #screenLabel{ font-size:14px; color: #ffffff; } #autoSwitch{ background: rgba(255, 255, 255, 0%); border-radius:4px; } ukui-screensaver/screensaver/assets/message.png0000644000175000017500000000107514205074704020753 0ustar fengfengPNG  IHDRw=IDATHKMhAӤɶ&545ЃX*4O*͓ୠQPx&zQ]K JC!UJHlҏmMv99of[naࡀI)S`[kqMK\BuؗEWHcf-7e)VXM뢷eN\b='eH`9S [Hp6Z~edTͥ/Ըv))`9[Mt~FBn\;6d픦r336`G-ޤLWu՘:s6/KMS:"}b jp}-q|fOaNw/u.e=h==xPw3+̮,LUj\?7:v̶}e-NdIENDB`ukui-screensaver/screensaver/assets/logo-kylin.svg0000644000175000017500000001210614205074704021423 0ustar fengfeng ukui-screensaver/screensaver/assets/wallpaper.svg0000644000175000017500000000135314205074704021330 0ustar fengfeng设为壁纸ukui-screensaver/screensaver/assets/setBackground.svg0000644000175000017500000000135314205074704022134 0ustar fengfeng设为壁纸ukui-screensaver/screensaver/assets/settings.svg0000644000175000017500000000221414205074704021176 0ustar fengfeng设置ukui-screensaver/screensaver/assets/next.svg0000644000175000017500000000055014205074704020315 0ustar fengfeng下一张ukui-screensaver/screensaver/assets/default-intel.qss0000644000175000017500000000321614205074704022105 0ustar fengfengQLabel#m_weatherArea { font-size:26px; color: #ffffff; } QLabel#dateOfWeek { font-size:40px; color: #ffffff; text-align:left; } QLabel#dateOfLocaltime { font-size:96px; color: #ffffff; text-align:left; } QLabel#dateOfDay { font-size:32px; color: #ffffff; text-align:left; } QLabel#dateOfLunar { font-size:18px; color: #ffffff; } QLabel#clockTime { background:rgba(255,255,255,0.15); border-radius: 6px; font-size:20px; color: #ffffff; } QLabel#colon { font-size:20px; color: #ffffff; } QLabel#restTime { font-size:20px; color: #ffffff; opacity:0.6; } QLabel#centerLabel { font-size:18px; color: #ffffff; } QLabel#authorLabel { font-size:18px; color: #ffffff; } QPushButton{ background:rgba(255,255,255,0.12); } #escButton,#prevButton,#nextButton,#settingsButton{ background: rgba(255, 255, 255, 12%); border-radius:24px; border-size:0px; color:white; icon-size:24px; } #escButton::hover,#prevButton::hover,#nextButton::hover,#settingsButton::hover { background: rgba(255, 255, 255, 30%); } #escButton::pressed,#prevButton::pressed,#nextButton::pressed,#settingsButton::pressed { background: rgba(255, 255, 255, 8%); } #vboxFrame{ background: rgba(255, 255, 255, 12%); border: 0px; border-radius:4px; } #WallpaperButton{ background: rgba(255, 255, 255, 0%); border-radius:4px; color:white; icon-size:24px; } #WallpaperButton::hover{ background: rgba(61, 107, 229, 255); } #autoSwitchLabel{ font-size:14px; color: #ffffff; } #autoSwitch{ background: rgba(255, 255, 255, 0%); border-radius:4px; } ukui-screensaver/screensaver/assets/prev.svg0000644000175000017500000000055314205074704020316 0ustar fengfeng上一张ukui-screensaver/screensaver/default.qrc0000644000175000017500000000754114205074704017456 0ustar fengfeng assets/default.qss assets/default-intel.qss assets/logo.svg assets/download.svg assets/prev.svg assets/next.svg assets/setBackground.svg assets/settings.svg assets/wallpaper.svg assets/logo-kylin.svg assets/message.png assets/weather-icon/100.svg assets/weather-icon/101.svg assets/weather-icon/102.svg assets/weather-icon/103.svg assets/weather-icon/104.svg assets/weather-icon/200.svg assets/weather-icon/201.svg assets/weather-icon/202.svg assets/weather-icon/203.svg assets/weather-icon/204.svg assets/weather-icon/205.svg assets/weather-icon/206.svg assets/weather-icon/207.svg assets/weather-icon/208.svg assets/weather-icon/209.svg assets/weather-icon/210.svg assets/weather-icon/211.svg assets/weather-icon/212.svg assets/weather-icon/213.svg assets/weather-icon/300.svg assets/weather-icon/301.svg assets/weather-icon/302.svg assets/weather-icon/303.svg assets/weather-icon/304.svg assets/weather-icon/305.svg assets/weather-icon/306.svg assets/weather-icon/307.svg assets/weather-icon/308.svg assets/weather-icon/309.svg assets/weather-icon/310.svg assets/weather-icon/311.svg assets/weather-icon/312.svg assets/weather-icon/313.svg assets/weather-icon/314.svg assets/weather-icon/315.svg assets/weather-icon/316.svg assets/weather-icon/317.svg assets/weather-icon/318.svg assets/weather-icon/399.svg assets/weather-icon/400.svg assets/weather-icon/401.svg assets/weather-icon/402.svg assets/weather-icon/403.svg assets/weather-icon/404.svg assets/weather-icon/405.svg assets/weather-icon/406.svg assets/weather-icon/407.svg assets/weather-icon/408.svg assets/weather-icon/409.svg assets/weather-icon/410.svg assets/weather-icon/499.svg assets/weather-icon/500.svg assets/weather-icon/501.svg assets/weather-icon/502.svg assets/weather-icon/503.svg assets/weather-icon/504.svg assets/weather-icon/507.svg assets/weather-icon/508.svg assets/weather-icon/509.svg assets/weather-icon/510.svg assets/weather-icon/511.svg assets/weather-icon/512.svg assets/weather-icon/513.svg assets/weather-icon/514.svg assets/weather-icon/515.svg assets/weather-icon/900.svg assets/weather-icon/901.svg assets/weather-icon/999.svg ukui-screensaver/screensaver/language/0000755000175000017500000000000014205074704017077 5ustar fengfengukui-screensaver/screensaver/language/screensaver-zh_CN.ini0000644000175000017500000001041514205074704023120 0ustar fengfeng[1] FL=因为有悔,所以披星戴月 SL=因为有梦,所以奋不顾身 author= [2] OL=大直若屈,大巧若拙,大辩若讷。 author=《老子》 [3] OL=博学之,审问之,慎思之,明辨之,笃行之。 author=《礼记》 [4] OL=兼听则明,偏听则暗。 author=《资治通鉴》 [5] FL=一花一世界,一叶一追寻。 SL=一曲一场叹,一生为一人。 author=威廉·布莱克《天真的预言》 [6] FL=月光下,你带着笑地向我步来, SL=月色与雪色之间,你是第三种绝色。 author=余光中 [7] OL=不要问我心里有没有你,我余光中都是你。 author=余光中 [8] FL=你要是愿意,我就永远爱你, SL=你要是不愿意,我就永远相思。 author=王小波 [9] FL=草在结它的种子,风在摇它的叶子。 SL=我们站着,不说话,就十分美好。 author=顾城 [10] OL=见到你,我觉得多少适应了这个世界。 author=村上春树 [11] OL=不须耳鬓常厮伴,一笑低头意已倾。 author=朱生豪 [12] FL=君臣一梦,今古空名。 SL=但远山长,云山乱,晓山青。 author=苏轼 [13] FL=心如规矩,志如尺衡, SL=平静如水,正直如绳。 author=严遵 [14] OL=近水知鱼性,近山识鸟音。 author=周希陶 [15] OL=此处果有可乐,我即别无所思。 author=林语堂 [16] FL=心之所向,素履以往, SL=生如逆旅,一苇以航。 author=七堇年《尘曲》 [17] FL=你说,我们就山居于此吧, SL=胭脂用尽时,桃花就开了。 author=与谢野晶子 [18] OL=世间所有的相遇,都是久别重逢。 author=白落梅 [19] OL=浮云一别后,流水十年间。 author=韦应物《淮上喜会梁川故人》 [20] OL=最是人间留不住,朱颜辞镜花辞树。 author=王国维《蝶恋花》 [21] OL=行到水穷处,坐看云起时。 author=王维 [22] OL=我有一瓢酒,可以慰风尘。 author=韦应物 [23] OL=墙头马上遥相顾,一见知君即断肠。 author=白居易 [24] OL=人生到处知何似,应似飞鸿踏雪泥。 author=《和子由渑池怀旧》 [25] OL=粗缯大布裹生涯,腹有诗书气自华。 author=《和董传留别》 [26] OL=清风徐来,水波不兴。 author=《前赤壁赋》 [27] OL=我有斗酒,藏之久矣,以待子不时之须。 author=《后赤壁赋》 [28] FL=若是有缘,千山暮雪,万里层云,终会重逢。 SL=若是无缘,自此一去,天涯海角,再难相会。 author=白落梅《你若安好便是晴天》 [29] FL=愿你一生努力,一生被爱。 SL=想要的都拥有,得不到的都释怀。 author=八月长安 [30] OL=凌晨四点醒来,发现海棠花未眠。 author=川端康成 [31] OL=无路可走的时候,就不断回到原点。 author=东野圭吾 [32] OL=你要批评指点四周的风景,你首先要爬上屋顶。 author=歌德 [33] OL=只有流过血的手指,才能弹出世间的绝唱。 author=泰戈尔 [34] FL=幸亏时光不会倒流, SL=否则万物一定会朝旧岁月里疾步奔跑。 author=《迷楼》 [35] FL=我看到那些岁月如何奔驰, SL=挨过了冬季,便迎来了春天。 author=《瓦尔登湖》 [36] FL=整个世界展现在我们面前, SL=期待着我们去创造,而不是去重复。 author=毕加索 [37] FL=决定我们成为什么样的人, SL=不是我们的能力,而是我们的选择。 author=J·K·罗琳 [38] FL=不必太纠结于当下,也不必太忧虑未来, SL=当你经历过一些事情的时候,眼前的风景已经和从前不一样了。 author=村上春树 [39] OL=三更梦醒,你是檐上落下的星。 author=佚名 [40] OL=我将永远忠于自己,披星戴月的奔向理想与自由。 author=佚名 [41] OL=有一天,我看了43次日落! author=《小王子》 [42] OL=当太阳升到最高点的时候,影子就不见了。 author=佚名 [43] OL=拯救地球好累,虽然有些疲惫但我还是会。 author=《超人不会飞》 [44] OL=陌上花开,可缓缓归矣 author=佚名 [45] OL=别慌,月亮也正在大海某处迷茫 author=佚名 [46] OL=夏天到了,春天的不甘该统统放下了 author=佚名 [47] OL=保持热爱,奔赴山海 author=佚名 [48] FL=你好,是故事的开始, SL=你要好好的,是故事的结局。 author=佚名 [49] OL=工欲善其事,必先利其器。 author=《孔子》 ukui-screensaver/screensaver/language/screensaver-en_US.ini0000644000175000017500000000563414205074704023137 0ustar fengfeng[1] FL="May there be enough clouds in your life " SL="to make a beautiful sunset." author= [2] OL="And forever has no end." author= [3] FL="Just because someone doesn’t love you the way you want them to," SL="doesn’t mean they don’t love you with all they have." author= [4] OL="Happiness good health and a bad memory." author= [5] FL="The best and most beautiful things in the world can not be" SL="seen or even touched,they must be felt with heart." author= [6] FL="I am not afraid of tomorrow for I have seen" SL="yesterday and love today." author= [7] OL="Enjoy when you can,and endure when you must." author= [8] FL="A friend is one of the nicest things you can have," SL="and one of the best things you can be." author= [9] OL="Only you can control your future." author= [10] OL="Don’t let what you cannot do interfere with what you can do." author= [11] OL="Seeing is believing.But is it a truth?" author= [12] FL="You don’t have to see the whole staircase," SL="just take the first step." author= [13] FL="Start where you are.Use what you have." SL="Do what you can." author= [14] FL="If I had eight hours to chop down a tree," SL="I’d spend six hours sharpening my ax." author= [15] OL="Actions is the foundational key to all success." author= [16] OL="Refrain from excess." author= [17] FL="The longest way must have its close;" SL="the gloomiest night will wear on to a morning." author= [18] OL="Sometimes ever,sometimes never." author= [19] OL="My angel,flung out of space." author= [20] FL="Three thousand,see light is a cloud;" SL="Troubles are many,would like to open is a sunny day." author= [21] OL="Everything comes full circle." author= [22] FL="In delay there lies no plenty,Then come kiss me," SL="sweet and twenty,Youth’s a stuff that will not endure." author= [23] OL="There is always a better way." author= [24] OL="No act of kindness,no matter how small,is ever wasted." author= [25] FL="Laugh loudly,laugh often,and most important," SL="laugh at yourself." author= [26] FL="When you want something,at the universe conspires" SL="in helping you to achieve it." author= [27] FL="It’s the possibility of having a dream come true" SL="that makes life interesting." author= [28] FL="Some people don’t belong to you," SL="but it’s good to meet them." author= [29] OL="Miracles happen every day." author= [30] OL="You can’t change the past." author= [31] OL="To make each day count." author= [32] FL="If you reveal your secrets to the wind you should not" SL="blame the wind revealing them to the trees." author= [33] FL="I love three things in the world:the sun,the moon and you." SL="The sun for day,the moon for night and you forever." author= [34] OL="In me the tiger sniffs the rose." author= [35] OL="The longest day has an end." author= [36] FL="Sometimes accompanied,sometimes alone," SL="stay awesome all the time." author= [37] FL="There are no easy answer," SL="there’s only living through the questions." author= ukui-screensaver/screensaver/language/screensaver-jd.ini0000644000175000017500000001053614205074704022520 0ustar fengfeng[1] OL=没有共产党,就没有新中国! author= [2] OL=解放思想,实事求是! author= [3] OL=中国产生了共产党,这是开天辟地的大事变! author= [4] FL=一百年来,中国共产党团结带领中国人民 SL=书写了中华民族几千年历史上最恢宏的史诗! author= [5] FL=一百年来,中国共产党团结带领中国人民进行的一切奋斗、一切牺牲、 SL=一切创造,归结起来就是一个主题:实现中华民族伟大复兴! author= [6] OL=初心易得,始终难守! author= [7] FL=我们要用历史映照现实,远观未来。看清楚过去为什么能够成功, SL=弄明白未来怎样才能继续成功! author= [8] FL=中国共产党领导是党和国家的根本所在,命脉所在; SL=是全国各族人民的利益所系、命运所系! author= [9] OL=中国共产党根基在人民,血脉在人民、力量在人民! author= [10] FL=中国共产党始终代表最广大人民根本利益, SL=没有任何自己特殊的利益! author= [11] FL=用马克思主义观察时代、把握时代、引领时代, SL=继续发展当代中国马克思主义、21世纪马克思主义! author= [12] FL=走自己的路是党的全部理论和实践立足点, SL=更是党百年奋斗得出的历史结论! author= [13] OL=强国必须强军,军强才能国安! author= [14] OL=敢于斗争,敢于胜利,是中国共产党不可战胜的强大精神力量! author= [15] FL=新时代的中国青年,要以实现中华民族伟大复兴为己任, SL=增强做中国人的志气、骨气、底气! author= [16] FL=伟大、光荣、正确的中国共产党万岁! SL=伟大、光荣、英雄的中国人民万岁! author= [17] OL=发展才是硬道理! author= [18] OL=聚精会神搞建设,一心一意谋发展! author= [19] OL=看准了,就大胆地试,大胆地闯! author= [20] OL=人固有一死,或重于泰山,或轻于鸿毛! SL= author= [21] FL=理论联系实际,是马克思主义“活的灵魂”, SL=是共产党人从斗争中创造新局面的思想路线! author= [22] OL=用中国理论阐释中国实践,用中国实践升华中国理论! author= [23] FL=理论联系实际、和人民群众紧密联系在一起、 SL=批评与自我批评,是中国共产党的三大优良作风! author= [24] FL=坚持中国特色社会主义道路自信、 SL=理论自信、制度自信、文化自信! author= [25] OL=让初心薪火相传,把使命永担在肩! author= [26] OL=心有所信,方能行远! author= [27] FL=面向未来,走好新时代的长征路, SL=我们更需要坚定理想信念、矢志拼搏奋斗! author= [28] FL=牢记初心使命,坚定必胜信念, SL=发扬斗争精神,增强斗争本领! author= [29] OL=发扬优良传统,承担历史使命! author= [30] FL=实事求是、坚持真理,科学应变、主动求变,咬定目标、 SL=勇往直前,走好新时代的长征路! author= [31] FL=缅怀革命先烈,赓续共产党人精神血脉, SL=坚定理想信念,砥砺革命意志! author= [32] FL=革命理想高于天,理想信念之火 SL=一经点燃就会产生巨大的精神力量! author= [33] OL=信仰、信念、信心是最好的防腐剂! author= [34] OL=学史明理、学史增信、学史崇德、学史力行! author= [35] OL=时代是思想之母,实践是理论之源! author= [36] FL=实践发展永无止境,我们认识真理、 SL=进行理论创新就永无止境! author= [37] OL=理想因其远大而为理想,信念因其执着而为信念! author= [38] FL=在胜利和顺境时不骄傲不急躁, SL=在困难和逆境时不消沉不动摇! author= [39] OL=从群众中来、到群众中去! author= [40] FL=中国特色社会主义道路是实现社会主义现代化的必由之路, SL=是创造人民美好生活的必由之路! author= [41] FL=人民立场是中国共产党的根本政治立场, SL=是马克思主义政党区别于其他政党的显著标志! author= [42] OL=方向决定道路,道路决定命运! author= [43] OL=全党要坚定道路自信、理论自信、制度自信、文化自信! author= [44] OL=得众则得国,失众则失国! author= [45] OL=自信人生二百年,会当水击三千里! author= [46] FL=发展是党执政兴国的第一要务, SL=是解决中国所有问题的关键! author= ukui-screensaver/screensaver/main.cpp0000644000175000017500000001042314205074704016744 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "screensaver.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #define WORKING_DIRECTORY "/usr/share/ukui-screensaver" bool bControlFlg = false;//是否控制面板窗口 int main(int argc, char *argv[]) { #if(QT_VERSION>=QT_VERSION_CHECK(5,6,0)) QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); #endif QApplication a(argc, argv); prctl(PR_SET_PDEATHSIG, SIGHUP); //加载翻译文件 QString locale = QLocale::system().name(); QTranslator translator; QString qmFile = QString(WORKING_DIRECTORY"/i18n_qm/%1.qm").arg(locale); translator.load(qmFile); a.installTranslator(&translator); qDebug() << "load translation file " << qmFile; QCommandLineParser parser; QString windowId; Screensaver s; XWindowAttributes xwa; parser.setApplicationDescription("Test helper"); parser.addHelpOption(); parser.addVersionOption(); parser.addPositionalArgument("source", QCoreApplication::translate("main", "Screensaver for ukui-screensaver")); parser.setSingleDashWordOptionMode(QCommandLineParser::ParseAsLongOptions); parser.addOptions({ {{"r", "root"}, QCoreApplication::translate("main", "show on root window")}, {{"w", "window-id"}, QCoreApplication::translate("main", "show on window."), QCoreApplication::translate("main", "window id")}, }); parser.process(a); bool onWindow = parser.isSet("window-id"); bool onRoot = parser.isSet("root"); double scale = 1; QScreen *screen = QApplication::primaryScreen(); scale = screen->devicePixelRatio(); if(onWindow){ windowId = parser.value("window-id"); WId wid = windowId.toULong(); QWindow* window = QWindow::fromWinId(wid); window->setProperty("_q_embedded_native_parent_handle",QVariant(wid)); s.winId(); s.windowHandle()->setParent(window); XGetWindowAttributes (QX11Info::display(), wid, &xwa); #ifndef USE_INTEL XClassHint ch; ch.res_name = NULL; ch.res_class = NULL; XGetClassHint (QX11Info::display(), wid, &ch); if(ch.res_name && strcmp(ch.res_name,"ukui-control-center")==0){ bControlFlg = true; s.addClickedEvent(); } #endif //获取屏保所在屏幕对应的缩放比例。 for(auto screen : QGuiApplication::screens()) { QPoint pos(xwa.x,xwa.y); if(screen->geometry().contains(pos)){ scale = screen->devicePixelRatio(); } } s.resize(xwa.width/scale + 1,xwa.height/scale + 1); s.move(0,0); s.show(); } else if(onRoot){ bControlFlg = false; WId wid = QX11Info::appRootWindow(); QWindow* window = QWindow::fromWinId(wid); window->setProperty("_q_embedded_native_parent_handle",QVariant(wid)); s.winId(); s.windowHandle()->setParent(window); XGetWindowAttributes (QX11Info::display(), wid, &xwa); qDebug()<<"xwa.width = "< #include #include #include #include #include class CycleLabel : public QFrame { Q_OBJECT public: CycleLabel(QWidget *parent = 0); void setSize(QSize size); protected: void paintEvent(QPaintEvent *); private: bool checked; QColor borderColorOff; QColor bgColorOff; QColor bgColorOn; QColor sliderColorOff; QColor sliderColorOn; int space; //滑块离背景间隔 int rectRadius; //圆角角度 int step; //移动步长 int startX; int endX; QTimer * timer; void drawBg(QPainter *painter); void drawSlider(QPainter *painter); int m_width; int m_height; }; #endif // CHECKBUTTON_H ukui-screensaver/screensaver/screensaver.h0000644000175000017500000001135314205074704020010 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef SCREENSAVER_H #define SCREENSAVER_H #include #include #include #include #include #include #include #include #include #include #include #include #include "sleeptime.h" #include "chinesedate.h" #include "mbackground.h" #include "checkbutton.h" #include "scconfiguration.h" #include "cyclelabel.h" #include "weathermanager.h" class Screensaver : public QWidget { Q_OBJECT public: explicit Screensaver(QWidget *parent = 0); ~Screensaver(); void addClickedEvent(); private: void initUI(); void setDatelayout(); void setWeatherLayout(); void setNoticeLaout(); void setSleeptime(bool Isshow); void setCenterWidget(); void updateDate(); void setUpdateBackground(); void setUpdateCenterWidget(); void startSwitchImages(); void stopSwitchImages(); void onBackgroundChanged(); void setRandomText(); void setPreviewText(bool bVisible);//设置预览样式 void setRandomPos(); void connectSingles(); void updateBackgroundPath(); void enterEvent(QEvent*); void leaveEvent(QEvent*); QTimer *switchTimer; QTimer *fadeTimer; QStringList imagePaths; QString backgroundPath; int cycleTime; float opacity; bool isCustom; bool isShowRestTime; bool textIsCenter; QString myText; QLabel *myTextLabel; QLabel *myPreviewLabel; CycleLabel *cycleLabel; SCConfiguration *configuration; void showNotice(); void hideNotice(); QWidget *myTextWidget; QLabel *dateOfLocaltime; QLabel *dateOfWeek; QLabel *dateOfLocaltimeHour; QLabel *dateofLocaltimeColon; QLabel *dateOfLocaltimeMinute; QLabel *dateOfDay; QLabel *dateOfLunar; QWidget *centerWidget; QWidget *timeLayout; SleepTime *sleepTime; QTimer *timer; QPixmap background; QPushButton *settingsButton; QPushButton *WallpaperButton; QWidget *buttonWidget; QSettings *qsettings; MBackground *m_background; QLabel *centerlabel1; QLabel *centerlabel2; QLabel *authorlabel; checkButton *checkSwitch; QLabel *autoSwitchLabel; QFrame *autoSwitch; QFrame *vboxFrame; bool isAutoSwitch; int flag; bool hasChanged; int timeType; QString dateType; QProcess *process; QLabel *screenLabel; bool respondClick; static QTime m_currentTime; WeatherManager *m_weatherManager; QWidget *m_weatherLaout; QLabel *m_weatherIcon; QLabel *m_weatherArea; QLabel *m_weatherCond; QLabel *m_weatherTemperature; QWidget *m_widgetNotice; QLabel *m_labelNoticeIcon; QLabel *m_labelNoticeMessage; protected: void paintEvent(QPaintEvent *event); void resizeEvent(QResizeEvent *event); bool eventFilter(QObject *obj, QEvent *event); private Q_SLOTS: void updateTime(); void updateBackground(); void updateCenterWidget(int index); void autoSwitchChanged(bool iswitch); void backgroundPathChanged(QString path); void cycleTimeChanged(int cTime); void myTextChanged(QString text); void showRestTimeChanged(bool isShow); void textIsCenterChanged(bool isCenter); void themeChanged(); void getWeatherFinish(QString city, QString cond, QString tmp); void onMessageNumberChanged(int num); void onMessageShowEnabledChanged(bool enabled); void onTimeFormatChanged(int type); void onDateFormatChanged(QString type); QPixmap getPaddingPixmap(); }; #endif // MAINWINDOW_H ukui-screensaver/VirtualKeyboard/0000755000175000017500000000000014205074704016103 5ustar fengfengukui-screensaver/VirtualKeyboard/VirtualKeyboard.pri0000644000175000017500000000064214205074704021730 0ustar fengfengSOURCES += \ $$PWD/src/keyboardwidget.cpp \ $$PWD/src/x11keyboard.cpp \ $$PWD/src/cursormonitor.cpp \ $$PWD/src/virtualkeyboard.cpp HEADERS += \ $$PWD/src/keyboardwidget.h \ $$PWD/src/x11keyboard.h \ $$PWD/src/cursormonitor.h \ $$PWD/src/virtualkeyboard.h FORMS += \ $$PWD/src/keyboardwidget.ui RESOURCES += \ $$PWD/src/keyboard.qrc ukui-screensaver/VirtualKeyboard/CMakeLists.txt0000644000175000017500000000103314205074704020640 0ustar fengfengfind_package(Qt5 COMPONENTS Core Widgets REQUIRED) set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOUIC ON) set(CMAKE_AUTORCC ON) qt5_add_resources(VirtualKeyboard_SRC src/keyboard.qrc) set(VirtualKeyboard_SRC ${VirtualKeyboard_SRC} src/cursormonitor.cpp src/keyboardwidget.cpp src/virtualkeyboard.cpp src/x11keyboard.cpp src/keyboard.qrc) include_directories( ${Qt5Core_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ) add_library(VirtualKeyboard STATIC ${VirtualKeyboard_SRC}) target_link_libraries(VirtualKeyboard Qt5::Core Qt5::Widgets) ukui-screensaver/VirtualKeyboard/VirtualKeyboard.pro0000644000175000017500000000200314205074704021727 0ustar fengfeng#------------------------------------------------- # # Project created by QtCreator 2018-10-12T16:43:42 # #------------------------------------------------- QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = VirtualKeyboard TEMPLATE = app # The following define makes your compiler emit warnings if you use # any feature of Qt which has been marked as deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS # You can also make your code fail to compile if you use deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 CONFIG += link_pkgconfig debug PKGCONFIG += xtst x11 include(VirtualKeyboard.pri) SOURCES += \ $$PWD/src/main.cpp ukui-screensaver/VirtualKeyboard/src/0000755000175000017500000000000014205074704016672 5ustar fengfengukui-screensaver/VirtualKeyboard/src/x11keyboard.cpp0000644000175000017500000001237414205074704021537 0ustar fengfeng/** * Copyright (C) 2018 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, 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 "x11keyboard.h" #include #include #include #include struct CharMap { QChar name; KeySym code; }; struct CharMap XSpecialSymbolMap[] { {' ', XK_space}, {',', XK_comma}, {'.', XK_period}, {'\'', XK_quoteright}, {'@', XK_at}, {'#', XK_numbersign}, {'$', XK_dollar}, {'%', XK_percent}, {'&', XK_ampersand}, {'*', XK_asterisk}, {'(', XK_parenleft}, {')', XK_parenright}, {'-', XK_minus}, {'+', XK_plus}, {'!', XK_exclam}, {'"', XK_quotedbl}, {'<', XK_less}, {'>', XK_greater}, {':', XK_colon}, {';', XK_semicolon}, {'/', XK_slash}, {'?', XK_question}, {'=', XK_equal}, {'.', XK_kana_middledot}, {'~', XK_asciitilde}, {'`', XK_grave}, {'|', XK_bar}, {'^', XK_asciicircum}, {'{', XK_braceleft}, {'}', XK_braceright}, {'[', XK_bracketleft}, {']', XK_bracketright}, {'_', XK_underscore}, {'\\', XK_backslash}, }; QMap funckeyMap = { {FuncKey::SPACE, XK_space}, {FuncKey::BACKSPACE, XK_BackSpace}, {FuncKey::ENTER, XK_Return}, {FuncKey::HOME, XK_Home}, {FuncKey::END, XK_End}, {FuncKey::PGUP, XK_Page_Up}, {FuncKey::PGDN, XK_Page_Down}, {FuncKey::INSERT, XK_Insert}, {FuncKey::DELETE, XK_Delete}, {FuncKey::UP, XK_Up}, {FuncKey::DOWN, XK_Down}, {FuncKey::LEFT, XK_Left}, {FuncKey::RIGHT, XK_Right} }; QMap modifierMap = { {Modifier::CTRL, XK_Control_L}, {Modifier::ALT, XK_Alt_L}, {Modifier::SUPER, XK_Super_L}, {Modifier::SHIFT, XK_Shift_L} }; QVector shiftKeyVec = {'~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '{', '}', '|', ':', '"', '>', '?'}; static Display *display = XOpenDisplay(0); bool isShift = false; bool isLetter = false; unsigned int keyCodeOfChar(QChar c) { QString text(c); KeySym keysym = XStringToKeysym(text.toLocal8Bit().data()); if(keysym == NoSymbol) { int symbolCount = sizeof(XSpecialSymbolMap) / sizeof(struct CharMap); for(int i = 0; i < symbolCount; i++) { if(XSpecialSymbolMap[i].name == c) { keysym = XSpecialSymbolMap[i].code; break; } } } qDebug() << "keysym: " << keysym; isShift = shiftKeyVec.contains(c) || (c >= 'A' && c <= 'Z'); isLetter = c.isLetter(); KeyCode code = XKeysymToKeycode(display, keysym); return code; } X11Keyboard::X11Keyboard(QObject *parent) : QObject(parent) { } X11Keyboard::~X11Keyboard() { XCloseDisplay(display); } void X11Keyboard::addModifier(Modifier::MOD mod) { modList.push_back(mod); } void X11Keyboard::removeModifier(Modifier::MOD mod) { modList.removeOne(mod); } bool X11Keyboard::hasModifier(Modifier::MOD mod) { return modList.contains(mod); } QList X11Keyboard::getAllModifier() { return modList; } void X11Keyboard::clearModifier() { modList.clear(); } void X11Keyboard::onKeyPressed(QChar c) { unsigned int keyCode = keyCodeOfChar(c); sendKey(keyCode); } void X11Keyboard::onKeyPressed(FuncKey::FUNCKEY key) { KeyCode keyCode; KeySym keysym = funckeyMap[key]; if(keysym != NoSymbol) keyCode = XKeysymToKeycode(display, keysym); sendKey(keyCode); } void X11Keyboard::sendKey(unsigned int keyCode) { Window focusWindow; int revert; XGetInputFocus(display, &focusWindow, &revert); for(auto mod : modList){ KeyCode keyCode = XKeysymToKeycode(display, modifierMap[mod]); XTestFakeKeyEvent(display, keyCode, True, 2); } //如果使用了修饰键(如ctrl、alt)且字符键是字母,则不起用shift键,否则快捷键不起作用 if(!modList.isEmpty() && isLetter) isShift = false; if(isShift) XTestFakeKeyEvent(display, XKeysymToKeycode(display, XK_Shift_L), True, 2); XTestFakeKeyEvent(display, keyCode, True, CurrentTime); XTestFakeKeyEvent(display, keyCode, False, CurrentTime); if(isShift) XTestFakeKeyEvent(display, XKeysymToKeycode(display, XK_Shift_L), False, 2); for(auto mod : modList){ KeyCode keyCode = XKeysymToKeycode(display, modifierMap[mod]); XTestFakeKeyEvent(display, keyCode, False, 2); } XFlush(display); } ukui-screensaver/VirtualKeyboard/src/x11keyboard.h0000644000175000017500000000555614205074704021210 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef X11KEYBOARD_H #define X11KEYBOARD_H #include #include class Modifier : public QObject { Q_OBJECT public: Modifier(){} enum MOD{ UNKNOWN = -1, CTRL, SHIFT, ALT, SUPER }; Q_ENUM(MOD) static QString getModifierName(int mod) { QMetaEnum metaEnum = QMetaEnum::fromType(); const char* modName = metaEnum.valueToKey(mod); QString result = QString(modName).toLower(); return result; } static MOD getModifier(const QString &modName) { QMetaEnum metaEnum = QMetaEnum::fromType(); MOD mod = (MOD)metaEnum.keyToValue(modName.toUpper().toLocal8Bit().data()); return mod; } }; class FuncKey : public QObject { Q_OBJECT public: FuncKey(){} enum FUNCKEY { UNKNOWN = -1, SPACE = 0, BACKSPACE, ENTER, HOME, END, PGUP, PGDN, INSERT, DELETE, UP, DOWN, LEFT, RIGHT }; Q_ENUM(FUNCKEY) static QString getKeyName(int key) { QMetaEnum metaEnum = QMetaEnum::fromType(); const char* keyName = metaEnum.valueToKey(key); QString result = QString(keyName).toLower(); return result; } static FUNCKEY getKey(const QString &keyName) { QMetaEnum metaEnum = QMetaEnum::fromType(); FUNCKEY key = (FUNCKEY)metaEnum.keyToValue(keyName.toUpper().toLocal8Bit().data()); return key; } }; class X11Keyboard : public QObject { Q_OBJECT public: explicit X11Keyboard(QObject *parent = nullptr); ~X11Keyboard(); void addModifier(Modifier::MOD mod); void removeModifier(Modifier::MOD mod); bool hasModifier(Modifier::MOD mod); QList getAllModifier(); void clearModifier(); public Q_SLOTS: void onKeyPressed(QChar c); void onKeyPressed(FuncKey::FUNCKEY key); private: void sendKey(unsigned int keyCode); private: QList modList; }; #endif // X11KEYBOARD_H ukui-screensaver/VirtualKeyboard/src/keyboard.qss0000644000175000017500000000133414205074704021223 0ustar fengfengQPushButton { border: none; font: 24px; color: white; background: #35322f; border-radius: 5px; } QPushButton::pressed { color: gray; background: #2a2826; } #btn_backspace, #btn_enter, #btn_shift_l, #btn_shift_r, #btn_ctrl_l, #btn_ctrl_r, #btn_alt_l, #btn_alt_r, #btn_super { font: 16px; background: #1e1b18 } #btn_backspace::pressed, #btn_enter::pressed, #btn_shift_l::pressed, #btn_shift_r::pressed, #btn_ctrl_l::pressed, #btn_ctrl_r::pressed, #btn_alt_l::pressed, #btn_alt_r::pressed, #btn_super::pressed { background: #181613; color: gray; } #btn_letter, #btn_symbol, #btn_number, #btn_insert, #btn_delete, #btn_home, #btn_end, #btn_pgup, #btn_pgdn, #btn_close { font: 16px; } ukui-screensaver/VirtualKeyboard/src/keyboardwidget.cpp0000644000175000017500000004040314205074704022403 0ustar fengfeng/** * Copyright (C) 2018 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, 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 "keyboardwidget.h" #include "ui_keyboardwidget.h" #include #include #include #define SYMBOL_KEY_COUNT 29 #define SYMBOL_PAGE_COUNT 2 #define BUTTON_BG "QPushButton{background:#1E1B18}" #define BUTTON_BG_PRESSED "QPushButton{background: #181613;}" #define BUTTON_BG_HL "QPushButton{background:#80c342}" #define BUTTON_BG_HL_PRESSED "QPushButton{background:#486E25}" QChar symbols[SYMBOL_PAGE_COUNT][SYMBOL_KEY_COUNT] = { {'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/'}, {'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '`', '-', '=', '[', ']', '\\', '|', '{', '}', '~','<', '>', ':', ';', '\'', '"', '-', '+', '?'}}; KeyboardWidget::KeyboardWidget(QWidget *parent) : QWidget(parent), ui(new Ui::KeyboardWidget), capsLock(false), isShift(false), page(0) { vKeyboard = new X11Keyboard(this); connect(this, SIGNAL(keyPressed(QChar)), vKeyboard, SLOT(onKeyPressed(QChar))); connect(this, SIGNAL(keyPressed(FuncKey::FUNCKEY)), vKeyboard, SLOT(onKeyPressed(FuncKey::FUNCKEY))); ui->setupUi(this); bindSingal(); setDefaultIcon(); } KeyboardWidget::~KeyboardWidget() { delete ui; } void KeyboardWidget::resizeEvent(QResizeEvent */*event*/) { int w = width(); int h = height(); int mainLeftMargin = ui->hl_main->contentsMargins().left(); int mainRightMargin = ui->hl_main->contentsMargins().right(); int mainTopMargin = ui->hl_main->contentsMargins().left(); int mainBottomMargin = ui->hl_main->contentsMargins().right(); int mainSpacing = ui->hl_main->spacing(); int itemSpacing = ui->hl_1->spacing(); int btnWidthCount = w - 11 * itemSpacing - mainSpacing- mainLeftMargin - mainRightMargin; int btnHeightCount = h - 3 * itemSpacing - mainTopMargin - mainBottomMargin; double btnWidth = btnWidthCount / 12; double btnHeight = btnHeightCount / 4; for(int i = 0; i <= 28; i++) { QString btnObjName = "btn_" + QString::number(i); QPushButton *btn = ui->page_letter->findChild(btnObjName); btn->setFixedSize(btnWidth, btnHeight); } ui->btn_ctrl_l->setFixedSize(btnWidth * 1.3, btnHeight); ui->btn_ctrl_r->setFixedSize(btnWidth * 1.3, btnHeight); ui->btn_alt_l->setFixedSize(btnWidth, btnHeight); ui->btn_alt_r->setFixedSize(btnWidth, btnHeight); ui->btn_super->setFixedSize(btnWidth, btnHeight); ui->btn_shift_l->setFixedSize(btnWidth, btnHeight); ui->btn_shift_r->setFixedHeight(btnHeight); ui->spacer_2->changeSize(btnWidth / 2, 20); for(int i = 1; i <= 9; i++) { QString btnObjName = "btn_num_" + QString::number(i); QPushButton *btn = ui->page_number->findChild(btnObjName); btn->setFixedWidth(btnWidth); } ui->btn_backspace_num->setFixedSize(btnWidth,btnHeight); ui->btn_insert->setFixedWidth(btnWidth); ui->btn_delete->setFixedWidth(btnWidth); ui->btn_home->setFixedWidth(btnWidth); ui->btn_end->setFixedWidth(btnWidth); ui->btn_pgup->setFixedWidth(btnWidth); ui->btn_pgdn->setFixedWidth(btnWidth); ui->btn_up->setFixedSize(btnWidth,btnHeight); ui->btn_down->setFixedSize(btnWidth,btnHeight); ui->btn_left->setFixedSize(btnWidth,btnHeight); ui->btn_right->setFixedSize(btnWidth,btnHeight); ui->btn_close->setFixedHeight(btnHeight); ui->btn_letter->setFixedHeight(btnHeight); ui->btn_symbol->setFixedHeight(btnHeight); ui->btn_number->setFixedHeight(btnHeight); setIconSize(); } float hScale = 0.6; float wScale = hScale; #define SET_ICON_SIZE_SCALE(btn) \ ui->btn_##btn->setIconSize(QSize(ui->btn_##btn->width() * hScale, ui->btn_##btn->height() * wScale)); #define SET_ICON_SIZE(btn) \ ui->btn_##btn->setIconSize(QSize(ui->btn_##btn->width(), ui->btn_##btn->height())); #define SET_SHIFT_ICON_SIZE_SCALE(btn) \ ui->btn_##btn->setIconSize(QSize(ui->btn_##btn->height() * 0.4, ui->btn_##btn->height() * 0.4)); #define SET_ENTER_ICON_SIZE_SCALE(btn) \ ui->btn_##btn->setIconSize(QSize(ui->btn_##btn->width() * 0.4, ui->btn_##btn->height() * 0.4)); void KeyboardWidget::setIconSize() { SET_ICON_SIZE_SCALE(backspace); SET_ICON_SIZE_SCALE(backspace_num); SET_ENTER_ICON_SIZE_SCALE(enter); SET_ICON_SIZE_SCALE(enter_num); SET_ICON_SIZE_SCALE(close); SET_ICON_SIZE_SCALE(super); SET_SHIFT_ICON_SIZE_SCALE(shift_l); SET_SHIFT_ICON_SIZE_SCALE(shift_r); SET_ICON_SIZE(up); SET_ICON_SIZE(down); SET_ICON_SIZE(left); SET_ICON_SIZE(right); } void KeyboardWidget::bindSingal() { for(auto obj : ui->page_letter->children()) { if(obj->metaObject()->className() == QString("QPushButton")) { QPushButton *btn = static_cast(obj); btn->setFocusPolicy(Qt::NoFocus); connect(btn, &QPushButton::clicked, this, &KeyboardWidget::onButtonClicked); connect(btn, &QPushButton::pressed, this, &KeyboardWidget::onButtonPressed); connect(btn, &QPushButton::released, this, &KeyboardWidget::onButtonReleased); } } for(auto obj : ui->page_number->children()) { if(obj->metaObject()->className() == QString("QPushButton")) { QPushButton *btn = static_cast(obj); btn->setFocusPolicy(Qt::NoFocus); connect(btn, &QPushButton::clicked, this, &KeyboardWidget::onButtonClicked); connect(btn, &QPushButton::pressed, this, &KeyboardWidget::onButtonPressed); connect(btn, &QPushButton::released, this, &KeyboardWidget::onButtonReleased); } } ui->btn_close->setFocusPolicy(Qt::NoFocus); ui->btn_letter->setFocusPolicy(Qt::NoFocus); ui->btn_symbol->setFocusPolicy(Qt::NoFocus); ui->btn_number->setFocusPolicy(Qt::NoFocus); connect(ui->btn_letter, &QPushButton::clicked, this, [&] { ui->stackedWidget->setCurrentWidget(ui->page_letter); page = 0; switchPage(); }); connect(ui->btn_symbol, &QPushButton::clicked, this, [&] { ui->stackedWidget->setCurrentWidget(ui->page_letter); page = 1; switchPage(); }); connect(ui->btn_number, &QPushButton::clicked, this, [&] { ui->stackedWidget->setCurrentWidget(ui->page_number); }); connect(ui->btn_close, &QPushButton::clicked, this, &KeyboardWidget::aboutToClose); connect(ui->btn_close, &QPushButton::pressed, this, &KeyboardWidget::onButtonPressed); connect(ui->btn_close, &QPushButton::released, this, &KeyboardWidget::onButtonReleased); } void KeyboardWidget::setDefaultIcon() { ui->btn_backspace->setIcon(QIcon(":/images/images/backspace.svg")); ui->btn_backspace_num->setIcon(QIcon(":/images/images/backspace.svg")); ui->btn_enter->setIcon(QIcon(":/images/images/enter.svg")); ui->btn_enter_num->setIcon(QIcon(":/images/images/enter.svg")); ui->btn_shift_l->setIcon(QIcon(":/images/images/capslock.svg")); ui->btn_shift_r->setIcon(QIcon(":/images/images/capslock.svg")); ui->btn_close->setIcon(QIcon(":/images/images/close.svg")); //ui->btn_super->setIcon(QIcon(":/images/images/super.svg")); ui->btn_super->setText("Super"); ui->btn_up->setIcon(QIcon(":/images/images/up.svg")); ui->btn_down->setIcon(QIcon(":/images/images/down.svg")); ui->btn_left->setIcon(QIcon(":/images/images/left.svg")); ui->btn_right->setIcon(QIcon(":/images/images/right.svg")); } QString KeyboardWidget::getKeyName(QPushButton *btn) { QString objName = btn->objectName(); int lastUnderline = objName.lastIndexOf('_'); int start = strlen("btn_"); int keyLength = lastUnderline - start; QString keyName = objName.mid(start, keyLength); return keyName; } void KeyboardWidget::changeFuncKeyStyle(QPushButton *btn, bool isPressed) { QString modName = getKeyName(btn); Modifier::MOD mod = Modifier::getModifier(modName); if(vKeyboard->hasModifier(mod)) { if(isPressed) btn->setStyleSheet(BUTTON_BG_HL_PRESSED); else btn->setStyleSheet(BUTTON_BG_HL); } else { if(isPressed) btn->setStyleSheet(BUTTON_BG_PRESSED); else btn->setStyleSheet(BUTTON_BG); } } void KeyboardWidget::changeShitKeyStyle(QPushButton *btn, bool isPressed) { if(page == 0){ if(isShift) { if(capsLock){ if(isPressed) { btn->setStyleSheet(BUTTON_BG_HL_PRESSED); btn->setIcon(QIcon(":/images/images/capslock_click.svg")); } else { btn->setStyleSheet(BUTTON_BG_HL); btn->setIcon(QIcon(":/images/images/capslock.svg")); } } else { if(isPressed) btn->setIcon(QIcon(":/images/images/capslock_hl_click.svg")); else btn->setIcon(QIcon(":/images/images/capslock_hl.svg")); } } else { if(isPressed) btn->setIcon(QIcon(":/images/images/capslock_click.svg")); else btn->setIcon(QIcon(":/images/images/capslock.svg")); } } } void KeyboardWidget::changeDirectKeyStyle(QPushButton *btn, bool isPressed) { QString keyName = getKeyName(btn); FuncKey::FUNCKEY key = FuncKey::getKey(keyName); if(key == FuncKey::UNKNOWN) return; QString iconName = QString(":/images/images/%1.svg").arg(keyName); QString iconNamePressed = QString(":/images/images/%1_click.svg").arg(keyName); if(isPressed) btn->setIcon(QIcon(iconNamePressed)); else btn->setIcon(QIcon(iconName)); } /** * @brief 修改按键样式 * @param obj 按键 * @param isPressed 按下或者松开 */ void KeyboardWidget::changeKeyStyle(QPushButton *btn, bool isPressed) { if(btn == ui->btn_ctrl_l || btn == ui->btn_ctrl_r || btn == ui->btn_alt_l || btn == ui->btn_alt_r || btn == ui->btn_super) { changeFuncKeyStyle(btn, isPressed); } if(btn == ui->btn_shift_l) changeShitKeyStyle(ui->btn_shift_l, isPressed); if(btn == ui->btn_shift_r) changeShitKeyStyle(ui->btn_shift_r, isPressed); changeDirectKeyStyle(btn, isPressed); } void KeyboardWidget::onButtonPressed() { QPushButton *btn = static_cast(sender()); changeKeyStyle(btn, true); } void KeyboardWidget::onButtonReleased() { QPushButton *btn = static_cast(sender()); changeKeyStyle(btn, false); } void KeyboardWidget::onButtonClicked() { QObject *obj = sender(); if(obj->metaObject()->className() != QString("QPushButton")) return; QPushButton *btn = static_cast(obj); QString keyName = getKeyName(btn); qDebug() << "keyName: " << keyName; Modifier::MOD mod = Modifier::getModifier(keyName); FuncKey::FUNCKEY funcKey = FuncKey::getKey(keyName); if(keyName == "shift") { if(page == 0) { isShift = !isShift; if(isShift) { //第一次被按下 capsLock = false; shiftLastClicked = QTime::currentTime(); ui->btn_shift_l->setIcon(QIcon(":/images/images/capslock_hl.svg")); ui->btn_shift_r->setIcon(QIcon(":/images/images/capslock_hl.svg")); } else { int doubleClickInterval = QApplication::doubleClickInterval(); if(shiftLastClicked.msecsTo(QTime::currentTime()) <= doubleClickInterval) { //shift键双击,锁定大写 capsLock = true; isShift = true; ui->btn_shift_l->setIcon(QIcon(":/images/images/capslock.svg")); ui->btn_shift_r->setIcon(QIcon(":/images/images/capslock.svg")); ui->btn_shift_l->setStyleSheet("QPushButton{background:#80c342}"); ui->btn_shift_r->setStyleSheet("QPushButton{background:#80c342}"); } else { ui->btn_shift_l->setIcon(QIcon(":/images/images/capslock.svg")); ui->btn_shift_r->setIcon(QIcon(":/images/images/capslock.svg")); ui->btn_shift_l->setStyleSheet("QPushButton{background:#1e1b18}"); ui->btn_shift_r->setStyleSheet("QPushButton{background:#1e1b18}"); } } toggleCase(); } else { page = page % (SYMBOL_PAGE_COUNT - 1) + 1; switchPage(); } } else if(mod != Modifier::UNKNOWN) { if(vKeyboard->hasModifier(mod)) { vKeyboard->removeModifier(mod); btn->setStyleSheet(BUTTON_BG); btn->setStyleSheet(BUTTON_BG); } else { vKeyboard->addModifier(mod); btn->setStyleSheet(BUTTON_BG_HL); btn->setStyleSheet(BUTTON_BG_HL); } } else if(funcKey != FuncKey::UNKNOWN) { Q_EMIT keyPressed(funcKey); } else { //字符键 QChar c; QString text = btn->text(); qDebug() << "clicked button text: " << text; if(text == "&&") c = '&'; else if(text.length() == 1) c = text.at(0); Q_EMIT keyPressed(c); //如果shift键被单击,按一个键后就恢复为小写 if(isShift && !capsLock) { isShift = false; toggleCase(); changeShitKeyStyle(ui->btn_shift_l, false); changeShitKeyStyle(ui->btn_shift_r, false); } clearModifier(); } } void KeyboardWidget::clearModifier() { for(auto mod : vKeyboard->getAllModifier()) { QString modName = Modifier::getModifierName(mod); if(mod == Modifier::SUPER) { QString objName = QString("btn_%1").arg(modName); QPushButton *btn = ui->page_letter->findChild(objName); btn->setStyleSheet(BUTTON_BG); } else { QString objName = QString("btn_%1_l").arg(modName); QPushButton *btn = ui->page_letter->findChild(objName); btn->setStyleSheet(BUTTON_BG); objName = QString("btn_%1_r").arg(modName); btn = ui->page_letter->findChild(objName); btn->setStyleSheet(BUTTON_BG); } } vKeyboard->clearModifier(); } void KeyboardWidget::toggleCase() { for(int i = 0; i < 26; i++) { QString objName = "btn_" + QString::number(i); QPushButton *btn = findChild(objName); QChar ch; if(isShift) { //切换到大写 ch = symbols[0][i].toUpper(); } else { ch = symbols[0][i]; } btn->setText(ch); } } void KeyboardWidget::switchPage() { if(page == 0) { ui->btn_shift_l->setText(""); ui->btn_shift_r->setText(""); ui->btn_shift_l->setIcon(QIcon(":/images/images/capslock.svg")); ui->btn_shift_r->setIcon(QIcon(":/images/images/capslock.svg")); } else { ui->btn_shift_l->setText(""); ui->btn_shift_r->setText(""); ui->btn_shift_l->setIcon(QIcon(":/images/images/capslock.svg")); ui->btn_shift_r->setIcon(QIcon(":/images/images/capslock.svg")); } for(int i = 0; i < SYMBOL_KEY_COUNT; i++) { QString btnObjName = "btn_" + QString::number(i); QPushButton *btn = ui->page_letter->findChild(btnObjName); QChar c = symbols[page][i]; if(c == '&') btn->setText("&&"); else btn->setText(c); } } ukui-screensaver/VirtualKeyboard/src/virtualkeyboard.cpp0000644000175000017500000000522714205074704022613 0ustar fengfeng/** * Copyright (C) 2018 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, 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 "virtualkeyboard.h" #include #include #include #include VirtualKeyboard::VirtualKeyboard(QWidget *parent) : QWidget(parent) { Q_INIT_RESOURCE(keyboard); setAutoFillBackground(true); QPalette plt; plt.setBrush(QPalette::Background, Qt::black); setPalette(plt); setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::WindowDoesNotAcceptFocus); keyboardWidget = new KeyboardWidget(this); QHBoxLayout *hl_keyboard = new QHBoxLayout(this); QSpacerItem *spacer = new QSpacerItem(40, 20); hl_keyboard->addSpacerItem(spacer); hl_keyboard->addWidget(keyboardWidget); QSpacerItem *spacer2 = new QSpacerItem(40, 20); hl_keyboard->addSpacerItem(spacer2); QFile qssFile(":/qss/keyboard.qss"); qssFile.open(QIODevice::ReadOnly); setStyleSheet(qssFile.readAll()); qssFile.close(); QDesktopWidget *desktop = QApplication::desktop(); cursorMonitor = new CursorMonitor(this); //在多显示器情况下,监视鼠标指针的位置和主显示器变化信号 connect(cursorMonitor, &CursorMonitor::cursorPosChanged, this, [&](const QPoint &pos){ adjustGeometry(desktop->screenNumber(pos)); }); connect(desktop, &QDesktopWidget::primaryScreenChanged, this, [&]{ adjustGeometry(desktop->primaryScreen()); }); connect(keyboardWidget, &KeyboardWidget::aboutToClose, this, &VirtualKeyboard::aboutToClose); adjustGeometry(desktop->primaryScreen()); } void VirtualKeyboard::adjustGeometry(int screen) { QDesktopWidget *desktop = QApplication::desktop(); QWidget *activateScreen = desktop->screen(screen); setGeometry(0, activateScreen->height() - activateScreen->height() / 3, activateScreen->width(), activateScreen->height() / 3); } ukui-screensaver/VirtualKeyboard/src/keyboard.qrc0000644000175000017500000000172414205074704021205 0ustar fengfeng keyboard.qss images/backspace_click.svg images/backspace.svg images/capslock_click.svg images/capslock_hl.svg images/capslock.svg images/down_click.svg images/down.svg images/enter_click.svg images/enter.svg images/left_click.svg images/left.svg images/right_click.svg images/right.svg images/super_click.svg images/super.svg images/up.svg images/close_click.svg images/close.svg images/capslock_hl_click.svg images/up_click.svg ukui-screensaver/VirtualKeyboard/src/cursormonitor.h0000644000175000017500000000210114205074704021762 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef CURSORMONITOR_H #define CURSORMONITOR_H #include #include class CursorMonitor : public QThread { Q_OBJECT public: explicit CursorMonitor(QObject *parent = nullptr); void run(); Q_SIGNALS: void cursorPosChanged(const QPoint& pos); }; #endif // CURSORMONITOR_H ukui-screensaver/VirtualKeyboard/src/main.cpp0000644000175000017500000000224214205074704020322 0ustar fengfeng/** * Copyright (C) 2018 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, 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 "virtualkeyboard.h" #include int main(int argc, char *argv[]) { // qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard")); QApplication a(argc, argv); VirtualKeyboard *keyboard = new VirtualKeyboard; QObject::connect(keyboard, &VirtualKeyboard::aboutToClose, &a, &QApplication::quit); keyboard->resize(400,300); keyboard->show(); return a.exec(); } ukui-screensaver/VirtualKeyboard/src/cursormonitor.cpp0000644000175000017500000000420614205074704022325 0ustar fengfeng/** * Copyright (C) 2018 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, 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 "cursormonitor.h" #include #include #include CursorMonitor::CursorMonitor(QObject *parent) : QThread(parent) { } void CursorMonitor::run() { Display *display; XEvent xevent; Window window; display = XOpenDisplay(NULL); if (display == 0) { syslog(LOG_ERR, "CursorMonitor unable to open display"); return; } window = DefaultRootWindow(display); XAllowEvents(display, AsyncBoth, CurrentTime); XGrabPointer(display, window, 1, PointerMotionMask | ButtonPressMask | ButtonReleaseMask , GrabModeAsync, GrabModeAsync, None, None, CurrentTime); while(1) { XNextEvent(display, &xevent); switch (xevent.type) { case MotionNotify: //printf("Mouse move : [%d, %d]\n", xevent.xmotion.x_root, xevent.xmotion.y_root); Q_EMIT cursorPosChanged(QPoint(xevent.xmotion.x_root, xevent.xmotion.y_root)); break; case ButtonPress: // printf("Button pressed : %s\n", key_name[xevent.xbutton.button - 1]); break; case ButtonRelease: // printf("Button released : %s\n", key_name[xevent.xbutton.button - 1]); break; } } } ukui-screensaver/VirtualKeyboard/src/keyboardwidget.h0000644000175000017500000000423414205074704022052 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef KEYBOARDWIDGET_H #define KEYBOARDWIDGET_H #include #include #include #include "x11keyboard.h" namespace Ui { class KeyboardWidget; } class QPushButton; class KeyboardWidget : public QWidget { Q_OBJECT public: explicit KeyboardWidget(QWidget *parent = 0); ~KeyboardWidget(); protected: void resizeEvent(QResizeEvent *event); private: void bindSingal(); void toggleCase(); void switchPage(); void setDefaultIcon(); void setIconSize(); void changeKeyStyle(QPushButton *btn, bool isPressed); void changeFuncKeyStyle(QPushButton *btn, bool isPressed); void changeShitKeyStyle(QPushButton *btn, bool isPressed); void changeDirectKeyStyle(QPushButton *btn, bool isPressed); void clearModifier(); QString getKeyName(QPushButton *btn); private Q_SLOTS: void onButtonClicked(); void onButtonPressed(); void onButtonReleased(); Q_SIGNALS: void aboutToClose(); void keyPressed(QChar c); void keyPressed(FuncKey::FUNCKEY key); private: Ui::KeyboardWidget *ui; bool capsLock; //是否大写锁定 bool isShift; QTime shiftLastClicked; //shift键上次被点击的时间 int page; //当前是第几页的键盘 X11Keyboard *vKeyboard; }; #endif // KEYBOARDWIDGET_H ukui-screensaver/VirtualKeyboard/src/keyboardwidget.ui0000644000175000017500000012344514205074704022246 0ustar fengfeng KeyboardWidget Qt::NonModal 0 0 1132 293 0 0 0 0 KeyboardWidget 0 QLayout::SetMinAndMaxSize 0 0 0 0 20 QLayout::SetNoConstraint 10 10 10 10 1 0 QLayout::SetNoConstraint 0 0 0 0 5 QLayout::SetNoConstraint Qt::Vertical 20 40 10 QLayout::SetNoConstraint 0 0 q 0 0 w 0 0 e 0 0 r 0 0 t 0 0 y 0 0 u 0 0 i 0 0 o 0 0 p 0 0 10 QLayout::SetNoConstraint Qt::Horizontal QSizePolicy::Maximum 40 20 0 0 a 0 0 s 0 0 d 0 0 f 0 0 g 0 0 h 0 0 j 0 0 k 0 0 l 0 0 10 QLayout::SetNoConstraint 0 0 0 0 z 0 0 x 0 0 c 0 0 v 0 0 b 0 0 n 0 0 m 0 0 , 0 0 . 0 0 10 QLayout::SetNoConstraint 0 0 Ctrl 0 0 0 0 Alt 0 0 0 0 Alt 0 0 / 0 0 Ctrl Qt::Vertical 20 40 QLayout::SetNoConstraint Qt::Horizontal 40 20 10 QLayout::SetNoConstraint QLayout::SetNoConstraint 10 0 0 9 0 0 5 0 0 8 0 0 4 0 0 2 0 0 7 0 0 1 0 0 6 0 0 3 0 0 0 0 0 0 0 Qt::Horizontal 40 20 QLayout::SetNoConstraint 10 0 0 Delete 0 0 End 0 0 Insert 0 0 PgUp 0 0 0 0 0 0 Home 0 0 0 0 0 0 PgDn Qt::Horizontal 40 20 5 QLayout::SetNoConstraint 0 0 0 0 Qt::Vertical 20 40 0 0 100 16777215 0 0 100 16777215 Abc 0 0 100 16777215 @ 0 0 100 16777215 123 Qt::Vertical 20 40 ukui-screensaver/VirtualKeyboard/src/images/0000755000175000017500000000000014205074704020137 5ustar fengfengukui-screensaver/VirtualKeyboard/src/images/capslock.svg0000644000175000017500000000115514205074704022461 0ustar fengfeng ukui-screensaver/VirtualKeyboard/src/images/super.svg0000644000175000017500000000221314205074704022014 0ustar fengfeng画板 11ukui-screensaver/VirtualKeyboard/src/images/enter_click.svg0000644000175000017500000000143214205074704023142 0ustar fengfeng ukui-screensaver/VirtualKeyboard/src/images/capslock_click.svg0000644000175000017500000000112714205074704023625 0ustar fengfeng ukui-screensaver/VirtualKeyboard/src/images/close.svg0000644000175000017500000000226514205074704021772 0ustar fengfeng ukui-screensaver/VirtualKeyboard/src/images/up_click.svg0000644000175000017500000000071414205074704022453 0ustar fengfeng ukui-screensaver/VirtualKeyboard/src/images/right_click.svg0000644000175000017500000000071414205074704023144 0ustar fengfeng ukui-screensaver/VirtualKeyboard/src/images/capslock_hl_click.svg0000644000175000017500000000106014205074704024304 0ustar fengfeng ukui-screensaver/VirtualKeyboard/src/images/left.svg0000644000175000017500000000066714205074704021623 0ustar fengfeng 画板 19 ukui-screensaver/VirtualKeyboard/src/images/down_click.svg0000644000175000017500000000071414205074704022776 0ustar fengfeng ukui-screensaver/VirtualKeyboard/src/images/up.svg0000644000175000017500000000072214205074704021305 0ustar fengfeng 画板 13 ukui-screensaver/VirtualKeyboard/src/images/left_click.svg0000644000175000017500000000074114205074704022761 0ustar fengfeng 画板 20 ukui-screensaver/VirtualKeyboard/src/images/backspace.svg0000644000175000017500000000150514205074704022575 0ustar fengfeng ukui-screensaver/VirtualKeyboard/src/images/right.svg0000644000175000017500000000064214205074704021777 0ustar fengfeng ukui-screensaver/VirtualKeyboard/src/images/capslock_hl.svg0000644000175000017500000000106014205074704023137 0ustar fengfeng ukui-screensaver/VirtualKeyboard/src/images/backspace_click.svg0000644000175000017500000000152314205074704023742 0ustar fengfeng ukui-screensaver/VirtualKeyboard/src/images/close_click.svg0000644000175000017500000000235514205074704023137 0ustar fengfeng ukui-screensaver/VirtualKeyboard/src/images/down.svg0000644000175000017500000000072214205074704021630 0ustar fengfeng 画板 15 ukui-screensaver/VirtualKeyboard/src/images/super_click.svg0000644000175000017500000000222714205074704023166 0ustar fengfeng画板 12ukui-screensaver/VirtualKeyboard/src/images/enter.svg0000644000175000017500000000147414205074704022003 0ustar fengfeng ukui-screensaver/VirtualKeyboard/src/virtualkeyboard.h0000644000175000017500000000241614205074704022255 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef VIRTUALKEYBOARD_H #define VIRTUALKEYBOARD_H #include #include #include "keyboardwidget.h" #include "cursormonitor.h" class VirtualKeyboard : public QWidget { Q_OBJECT public: explicit VirtualKeyboard(QWidget *parent = 0); private: void adjustGeometry(int screen); Q_SIGNALS: void aboutToClose(); private: KeyboardWidget *keyboardWidget; CursorMonitor *cursorMonitor; bool isApplication; }; #endif // VIRTUALKEYBOARD_H ukui-screensaver/VirtualKeyboard/README.md0000644000175000017500000000004114205074704017355 0ustar fengfengA simple virtual keyboard in X11 ukui-screensaver/i18n_ts/0000755000175000017500000000000014205074760014263 5ustar fengfengukui-screensaver/i18n_ts/bo.ts0000644000175000017500000024655414205074760015253 0ustar fengfeng AuthDialog Please enter your password or enroll your fingerprint Password: Authentication failure, Please try again Please try again in %1 minutes. Please try again in %1 seconds. Account locked permanently. Password cannot be empty Login Biometric Authentication Password Authentication Other Devices Retry Too many unsuccessful attempts,please enter password. Fingerprint authentication failed, you still have %1 verification opportunities BiometricAuthWidget Current device: Identify failed, Please retry. BiometricDevicesWidget Please select the biometric device Device type: Device name: OK ConfForm edit network LAN name: Method: Address: Netmask: Gateway: DNS 1: DNS 2: Edit Conn Auto(DHCP) Manual Cancel Save Ok Can not create new wired network for without wired card New network already created New network settings already finished New settings already effective Edit Network Add Wired Network DeviceType FingerPrint FingerVein Iris Face VoicePrint DigitalAuthDialog LoginByUEdu ResetPWD? SetNewUEduPWD clear ConfirmNewUEduPWD The two password entries are inconsistent, please reset Password entered incorrectly, please try again DlgConnHidWifi Connect to Hidden Wi-Fi Network Add Hidden Wi-Fi Connection Wi-Fi name Wi-Fi security Cancel Connect C_reate… None WPA & WPA2 Personal DlgConnHidWifiLeap Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Username Password Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise DlgConnHidWifiSecFast Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Anonymous identity Allow automatic PAC pro_visioning PAC file Inner authentication Username Password Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Anonymous Authenticated Both DlgConnHidWifiSecLeap Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Username Password Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) DlgConnHidWifiSecPeap Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Anonymous identity Domain CA certificate CA certificate password No CA certificate is required PEAP version Inner authentication Username Password Cancel Connect None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Choose from file Automatic Version 0 Version 1 DlgConnHidWifiSecPwd Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Username Password Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) DlgConnHidWifiSecTls Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Identity Domain CA certificate CA certificate password No CA certificate is required User certificate User certificate password User private key User key password Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Choose from file DlgConnHidWifiSecTunnelTLS Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Anonymous identity Domain CA certificate CA certificate password No CA certificate is required Inner authentication Username Password Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Choose from file DlgConnHidWifiWep Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Key WEP index Authentication Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise 1(default) Open System Shared Key DlgConnHidWifiWpa Connect to Hidden Wi-Fi Network Add Hidden Wi-Fi Connection Wi-Fi name Wi-Fi security Password Cancel Connect C_reate… None WPA & WPA2 Personal DlgHotspotCreate Dialog Create Hotspot Network name Wi-Fi security Password Cancel Ok None WPA & WPA2 Personal InputInfos Get code Recapture(60s) Recapture(%1s) Service exception... Invaild parameters... Unknown fault:%1 KeyboardWidget KeyboardWidget KylinNM kylin-nm Ethernet Networks Wifi Networks No usable network in the list Ethernet Wifi HotSpot FlyMode Advanced Show KylinNM No wireless card detected Not connected Disconnected NetOn, No Other Wired Network Scheme No Other Wireless Network Scheme Wired net is disconnected Conn Ethernet Success Conn Ethernet Fail Conn Wifi Success Confirm your Wi-Fi password or usable of wireless card LockWidget Form Date Time SwitchUser Guest MyLineEdit Verification code OneConnForm Form Connect Disconnect Input Password... Automatically join the network Connect to Hidden Wi-Fi Network None WiFi Security: Signal: MAC: Conn Wifi Failed OneLancForm Form Connect Disconnect No Configuration IPv4: IPv6: BandWidth: MAC: PhoneAuthWidget Verification by phoneNum 「 Use bound Phone number to verification 」 commit 「 Use SMS to verification 」 Network not connected~ Verification Code invalid! Verification Code incorrect.Please retry! Failed time over limit!Retry after 1 hour! verifaction failed! Network unavailable~ PowerManager Switch User Log Out lock Restart Power Off Suspend Sleep QObject The screensaver is active. The screensaver is inactive. Screensaver Picture does not exist View You have new notification SleepTime You have rested: SwitchButtonGroup uEduPWD Wechat TabletLockWidget Cancel Back Skip New password is the same as old Reset password error:%1 Please scan by correct WeChat Utils kylin network applet desktop message VerificationWidget Please scan by bound WeChat VerticalVerificationWidget Please scan by bound WeChat WeChatAuthDialog Login by wechat 「 Use registered WeChat account to login 」 Verification by wechat 「 Use bound WeChat account to verification 」 Network not connected~ Scan code successfully Timeout!Try again! main Screensaver for ukui-screensaver show on root window show on window. window id Start command for the ukui ScreenSaver. lock the screen immediately query the status of the screen saver unlock the screen saver show the screensaver Dialog for the ukui ScreenSaver. activated by session idle signal lock the screen and show screensaver immediately show screensaver immediately ukui-screensaver/i18n_ts/fr.ts0000644000175000017500000014532014205074760015247 0ustar fengfeng AuthDialog Form Forme More Devices Plus d'appareils Biometric Biométrique Password Mot de passe Retry Réessayez UnLock Ouvrir LoggedIn Connecté Password Incorrect, Please try again Mot de passe incorrect, veuillez réessayer Password: Biometric Authentication Password Authentication Other Devices Authentication failure, Please try again Please enter your password or enroll your fingerprint Too many unsuccessful attempts,please enter password. Fingerprint authentication failed, you still have %1 verification opportunities Please try again in %1 minutes. Please try again in %1 seconds. Account locked permanently. Password cannot be empty Login BioAuthWidget Form Forme TextLabel TextLabel More Plus Retry Réessayez Password Mot de passe BioDevices FingerPrint Empreinte digitale FingerVein FingerVein Iris Iris Face Visage VoicePrint VoicePrint BioDevicesWidget Form Forme Please select other biometric devices Veuillez sélectionner d'autres appareils biométriques Device Type: Type d'appareil: Device Name: Nom de l'appareil: BiometricAuthWidget Current device: Identify failed, Please retry. BiometricDevicesWidget Please select the biometric device Device type: Device name: OK ConfForm edit network LAN name: Method: Address: Netmask: Gateway: DNS 1: DNS 2: Edit Conn Auto(DHCP) Manual Cancel Save Ok Can not create new wired network for without wired card New network already created New network settings already finished New settings already effective Edit Network Add Wired Network DeviceType FingerPrint Empreinte digitale FingerVein FingerVein Iris Iris Face Visage VoicePrint VoicePrint DigitalAuthDialog LoginByUEdu ResetPWD? SetNewUEduPWD clear ConfirmNewUEduPWD The two password entries are inconsistent, please reset Password entered incorrectly, please try again DlgConnHidWifi Connect to Hidden Wi-Fi Network Add Hidden Wi-Fi Connection Wi-Fi name Wi-Fi security Cancel Connect C_reate… None WPA & WPA2 Personal DlgConnHidWifiLeap Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Username Password Mot de passe Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise DlgConnHidWifiSecFast Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Anonymous identity Allow automatic PAC pro_visioning PAC file Inner authentication Username Password Mot de passe Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Anonymous Authenticated Both DlgConnHidWifiSecLeap Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Username Password Mot de passe Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) DlgConnHidWifiSecPeap Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Anonymous identity Domain CA certificate CA certificate password No CA certificate is required PEAP version Inner authentication Username Password Mot de passe Cancel Connect None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Choose from file Automatic Version 0 Version 1 DlgConnHidWifiSecPwd Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Username Password Mot de passe Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) DlgConnHidWifiSecTls Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Identity Domain CA certificate CA certificate password No CA certificate is required User certificate User certificate password User private key User key password Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Choose from file DlgConnHidWifiSecTunnelTLS Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Anonymous identity Domain CA certificate CA certificate password No CA certificate is required Inner authentication Username Password Mot de passe Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Choose from file DlgConnHidWifiWep Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Key WEP index Authentication Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise 1(default) Open System Shared Key DlgConnHidWifiWpa Connect to Hidden Wi-Fi Network Add Hidden Wi-Fi Connection Wi-Fi name Wi-Fi security Password Mot de passe Cancel Connect C_reate… None WPA & WPA2 Personal DlgHotspotCreate Dialog Create Hotspot Network name Wi-Fi security Password Mot de passe Cancel Ok None WPA & WPA2 Personal InputInfos Get code Recapture(60s) Recapture(%1s) Service exception... Invaild parameters... Unknown fault:%1 KeyboardWidget KeyboardWidget KeyboardWidget KylinNM kylin-nm Ethernet Networks Wifi Networks No usable network in the list Ethernet Wifi HotSpot FlyMode Advanced Show KylinNM No wireless card detected Not connected Disconnected NetOn, No Other Wired Network Scheme No Other Wireless Network Scheme Wired net is disconnected Conn Ethernet Success Conn Ethernet Fail Conn Wifi Success Confirm your Wi-Fi password or usable of wireless card LockWidget Form Forme Date Rendez-vous amoureux Time Temps Guest Client SwitchUser Changer d'utilisateur MyLineEdit Verification code OneConnForm Form Forme Connect Disconnect Input Password... Automatically join the network Connect to Hidden Wi-Fi Network None WiFi Security: Signal: MAC: Conn Wifi Failed OneLancForm Form Forme Connect Disconnect No Configuration IPv4: IPv6: BandWidth: MAC: PhoneAuthWidget Verification by phoneNum 「 Use bound Phone number to verification 」 commit 「 Use SMS to verification 」 Network not connected~ Verification Code invalid! Verification Code incorrect.Please retry! Failed time over limit!Retry after 1 hour! verifaction failed! Network unavailable~ PowerManager SwitchUser Changer d'utilisateur Switch User Log Out Restart Power Off Suspend Sleep lock QObject The screensaver is active. The screensaver is inactive. Screensaver Picture does not exist View You have new notification SleepTime You have rested: SwitchButtonGroup uEduPWD Wechat TabletLockWidget Cancel Back Skip New password is the same as old Reset password error:%1 Please scan by correct WeChat Utils kylin network applet desktop message VerificationWidget Please scan by bound WeChat VerticalVerificationWidget Please scan by bound WeChat WeChatAuthDialog Login by wechat 「 Use registered WeChat account to login 」 Verification by wechat 「 Use bound WeChat account to verification 」 Network not connected~ Scan code successfully Timeout!Try again! main Start command for the ukui ScreenSaver. Commande de démarrage pour l'ukui ScreenSaver. lock the screen immediately verrouiller l'écran immédiatement Dialog for the ukui ScreenSaver. Boîte de dialogue pour l'écran de veille ukui. activated by session idle signal activé par le signal d'inactivité de la session Screensaver for ukui-screensaver show on root window show on window. window id query the status of the screen saver lock the screen and show screensaver immediately unlock the screen saver show the screensaver show screensaver immediately ukui-screensaver/i18n_ts/pt.ts0000644000175000017500000014507614205074760015273 0ustar fengfeng AuthDialog Form Formato More Devices Mais dispositivos Biometric Biométrico Password Senha Retry Tente novamente UnLock Desbloquear LoggedIn Logado Password Incorrect, Please try again Senha incorreta, por favor tente novamente Password: Biometric Authentication Password Authentication Other Devices Authentication failure, Please try again Please enter your password or enroll your fingerprint Too many unsuccessful attempts,please enter password. Fingerprint authentication failed, you still have %1 verification opportunities Please try again in %1 minutes. Please try again in %1 seconds. Account locked permanently. Password cannot be empty Login BioAuthWidget Form Formato TextLabel TextLabel More Mais Retry Tente novamente Password Senha BioDevices FingerPrint Impressão digital FingerVein FingerVein Iris Íris Face Face VoicePrint VoicePrint BioDevicesWidget Form Formato Please select other biometric devices Por favor, selecione outros dispositivos biométricos Device Type: Tipo de dispositivo: Device Name: Nome do dispositivo: BiometricAuthWidget Current device: Identify failed, Please retry. BiometricDevicesWidget Please select the biometric device Device type: Device name: OK ConfForm edit network LAN name: Method: Address: Netmask: Gateway: DNS 1: DNS 2: Edit Conn Auto(DHCP) Manual Cancel Save Ok Can not create new wired network for without wired card New network already created New network settings already finished New settings already effective Edit Network Add Wired Network DeviceType FingerPrint Impressão digital FingerVein FingerVein Iris Íris Face Face VoicePrint VoicePrint DigitalAuthDialog LoginByUEdu ResetPWD? SetNewUEduPWD clear ConfirmNewUEduPWD The two password entries are inconsistent, please reset Password entered incorrectly, please try again DlgConnHidWifi Connect to Hidden Wi-Fi Network Add Hidden Wi-Fi Connection Wi-Fi name Wi-Fi security Cancel Connect C_reate… None WPA & WPA2 Personal DlgConnHidWifiLeap Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Username Password Senha Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise DlgConnHidWifiSecFast Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Anonymous identity Allow automatic PAC pro_visioning PAC file Inner authentication Username Password Senha Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Anonymous Authenticated Both DlgConnHidWifiSecLeap Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Username Password Senha Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) DlgConnHidWifiSecPeap Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Anonymous identity Domain CA certificate CA certificate password No CA certificate is required PEAP version Inner authentication Username Password Senha Cancel Connect None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Choose from file Automatic Version 0 Version 1 DlgConnHidWifiSecPwd Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Username Password Senha Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) DlgConnHidWifiSecTls Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Identity Domain CA certificate CA certificate password No CA certificate is required User certificate User certificate password User private key User key password Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Choose from file DlgConnHidWifiSecTunnelTLS Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Anonymous identity Domain CA certificate CA certificate password No CA certificate is required Inner authentication Username Password Senha Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Choose from file DlgConnHidWifiWep Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Key WEP index Authentication Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise 1(default) Open System Shared Key DlgConnHidWifiWpa Connect to Hidden Wi-Fi Network Add Hidden Wi-Fi Connection Wi-Fi name Wi-Fi security Password Senha Cancel Connect C_reate… None WPA & WPA2 Personal DlgHotspotCreate Dialog Create Hotspot Network name Wi-Fi security Password Senha Cancel Ok None WPA & WPA2 Personal InputInfos Get code Recapture(60s) Recapture(%1s) Service exception... Invaild parameters... Unknown fault:%1 KeyboardWidget KeyboardWidget KeyboardWidget KylinNM kylin-nm Ethernet Networks Wifi Networks No usable network in the list Ethernet Wifi HotSpot FlyMode Advanced Show KylinNM No wireless card detected Not connected Disconnected NetOn, No Other Wired Network Scheme No Other Wireless Network Scheme Wired net is disconnected Conn Ethernet Success Conn Ethernet Fail Conn Wifi Success Confirm your Wi-Fi password or usable of wireless card LockWidget Form Formato Date Encontro Time Tempo Guest Convidado SwitchUser Mudar de utilizador MyLineEdit Verification code OneConnForm Form Formato Connect Disconnect Input Password... Automatically join the network Connect to Hidden Wi-Fi Network None WiFi Security: Signal: MAC: Conn Wifi Failed OneLancForm Form Formato Connect Disconnect No Configuration IPv4: IPv6: BandWidth: MAC: PhoneAuthWidget Verification by phoneNum 「 Use bound Phone number to verification 」 commit 「 Use SMS to verification 」 Network not connected~ Verification Code invalid! Verification Code incorrect.Please retry! Failed time over limit!Retry after 1 hour! verifaction failed! Network unavailable~ PowerManager SwitchUser Mudar de utilizador Switch User Log Out Restart Power Off Suspend Sleep lock QObject The screensaver is active. The screensaver is inactive. Screensaver Picture does not exist View You have new notification SleepTime You have rested: SwitchButtonGroup uEduPWD Wechat TabletLockWidget Cancel Back Skip New password is the same as old Reset password error:%1 Please scan by correct WeChat Utils kylin network applet desktop message VerificationWidget Please scan by bound WeChat VerticalVerificationWidget Please scan by bound WeChat WeChatAuthDialog Login by wechat 「 Use registered WeChat account to login 」 Verification by wechat 「 Use bound WeChat account to verification 」 Network not connected~ Scan code successfully Timeout!Try again! main Start command for the ukui ScreenSaver. Inicie o comando para o ScreenSaver do ukui. lock the screen immediately bloquear a tela imediatamente Dialog for the ukui ScreenSaver. Diálogo para o ScreenSaver ukui. activated by session idle signal ativado por sinal ocioso de sessão Screensaver for ukui-screensaver show on root window show on window. window id query the status of the screen saver lock the screen and show screensaver immediately unlock the screen saver show the screensaver show screensaver immediately ukui-screensaver/i18n_ts/CMakeLists.txt0000644000175000017500000000054014205074704017020 0ustar fengfengfind_package(Qt5LinguistTools) file(GLOB ts_files *.ts) qt5_create_translation(qm_files ${ts_files}) add_custom_target(i18n DEPENDS ${qm_files} SOURCES ${ts_files} ) # 让主目标依赖翻译文件,这样才会执行i18n add_dependencies(ukui-screensaver-dialog i18n) install(FILES ${qm_files} DESTINATION /usr/share/ukui-screensaver/i18n_qm/) ukui-screensaver/i18n_ts/zh_CN.ts0000644000175000017500000030131014205074760015632 0ustar fengfeng AuthDialog More Devices 选择其他设备 Biometric 使用生物识别认证 Password 使用密码认证 Retry 重试 UnLock 解锁 Slide to unlock 向上滑动解锁 You have %1 unread message 您有%1条未读消息 LoggedIn 已登录 Password: 密码: Account locked %1 minutes due to %2 fail attempts 账户锁定%1分钟由于%2次错误尝试 Please try again in %1 minutes. 请%1分钟后再试 Please try again in %1 seconds. 请%1秒后再试 Account locked permanently. 账号已被永久锁定 Password cannot be empty 密码不能为空 Password Incorrect, Please try again 密码错误,请重试 Authentication failure,there are still %1 remaining opportunities 认证失败,还剩%1次尝试机会 Please enter your password or enroll your fingerprint 请输入密码或者录入指纹 Authentication failure, Please try again 认证失败,请重试 Password 密码 Login 登录 Biometric Authentication 生物识别认证 Password Authentication 密码认证 Other Devices 其他设备 Too many unsuccessful attempts,please enter password. 指纹验证失败达最大次数,请使用密码登录 Fingerprint authentication failed, you still have %1 verification opportunities 指纹验证失败,您还有%1次尝试机会 BioDevices FingerPrint 指纹 FingerVein 指静脉 Iris 虹膜 Face 人脸 VoicePrint 声纹 BioDevicesWidget Please select other biometric devices 请选择其他生物识别设备 Device Type: 设备类型: Device Name: 设备名称: BiometricAuthWidget Current device: 当前设备: Identify failed, Please retry. 识别失败,请重试 BiometricDevicesWidget Please select the biometric device 请选择生物设备 Device type: 设备类型: Device name: 设备型号: OK 确定 ConfForm edit network 网络属性 LAN name: 网络名称: Method: 编辑IP设置: Address: IP地址: Netmask: 子网掩码: Gateway: 默认网关: DNS 1: 首选DNS: DNS 2: 备选DNS: Edit Conn 网络设置 Auto(DHCP) 自动(DHCP) Manual 手动 Cancel 返回 Save 确定 Ok 确定 Can not create new wired network for without wired card 缺少有线网卡 无法新建网络 New network already created 已创建新的有线网络 New network settings already finished 新的网络配置已经完成 Edit Network 网络属性 Add Wired Network 新建有线网络 create wired network successfully 已创建新的有线网络 change configuration of wired network successfully 新的设置已经生效 New settings already effective 新的设置已经生效 There is a same named LAN exsits. 已有同名连接存在 DeviceType FingerPrint 指纹 FingerVein 指静脉 Iris 虹膜 Face 人脸 VoicePrint 声纹 DigitalAuthDialog LoginByUEdu 请输入锁屏密码 now is authing, wait a moment 认证中,请稍后 Password Incorrect, Please try again 密码错误,请重试 ResetPWD? 忘记密码? SetNewUEduPWD 设置新锁屏密码 ConfirmNewUEduPWD 确认新锁屏密码 The two password entries are inconsistent, please reset 两次密码输入不一致,请重设 Password entered incorrectly, please try again 密码输入错误,请重试 clear 清空 DlgConnHidWifi Add Hidden Wi-Fi 加入无线网络 Connection 连接设置: Wi-Fi name 网络名称: Wi-Fi security Wi-Fi 安全性: Cancel 返回 Connect 确定 C_reate… 新建... None WPA & WPA2 Personal WPA 及 WPA2 个人 WEP 40/128-bit Key (Hex or ASCII) WEP 40/128 位密钥(十六进制或ASCII) WEP 128-bit Passphrase WEP 128 位密码句 Dynamic WEP (802.1X) 动态 WEP (802.1x) WPA & WPA2 Enterprise WPA 及 WPA2 企业 Connect to Hidden Wi-Fi Network 连接到隐藏 Wi-Fi 网络 DlgConnHidWifiLeap Connect to Hidden Wi-Fi Network 连接到隐藏 Wi-Fi 网络 Add hidden Wi-Fi 加入无线网络 Connection 连接设置: Network name 网络名称: Wi-Fi security Wi-Fi 安全性: Username 用户名: Password 密码: Cancel 返回 Connect 连接 C_reate… 新建... None WPA & WPA2 Personal WPA 及 WPA2 个人 WEP 40/128-bit Key (Hex or ASCII) WEP 40/128 位密钥(十六进制或ASCII) WEP 128-bit Passphrase WEP 128 位密码句 Dynamic WEP (802.1X) 动态 WEP (802.1x) WPA & WPA2 Enterprise WPA 及 WPA2 企业 DlgConnHidWifiSecFast Connect to Hidden Wi-Fi Network 连接到隐藏 Wi-Fi 网络 Add hidden Wi-Fi 加入无线网络 Connection 连接设置: Network name 网络名称: Wi-Fi security Wi-Fi 安全性: Authentication 认证: Anonymous identity 匿名身份: Allow automatic PAC pro_visioning 自动PAC配置: PAC file PAC文件: Inner authentication 内部认证: Username 用户名: Password 密码: Cancel 返回 Connect 连接 C_reate… 新建... None WPA & WPA2 Personal WPA 及 WPA2 个人 WEP 40/128-bit Key (Hex or ASCII) WEP 40/128 位密钥(十六进制或ASCII) WEP 128-bit Passphrase WEP 128 位密码句 Dynamic WEP (802.1X) 动态 WEP (802.1x) WPA & WPA2 Enterprise WPA 及 WPA2 企业 Tunneled TLS 隧道 TLS Protected EAP (PEAP) 受保护的 EAP Anonymous 匿名 Authenticated 已认证 Both 两者兼用 DlgConnHidWifiSecLeap Connect to Hidden Wi-Fi Network 连接到隐藏 Wi-Fi 网络 Add hidden Wi-Fi 加入无线网络 Connection 连接设置: Network name 网络名称: Wi-Fi security Wi-Fi 安全性: Authentication 认证: Username 用户名: Password 密码: Cancel 返回 Connect 连接 C_reate… 新建... None WPA & WPA2 Personal WPA 及 WPA2 个人 WEP 40/128-bit Key (Hex or ASCII) WEP 40/128 位密钥(十六进制或ASCII) WEP 128-bit Passphrase WEP 128 位密码句 Dynamic WEP (802.1X) 动态 WEP (802.1x) WPA & WPA2 Enterprise WPA 及 WPA2 企业 Tunneled TLS 隧道 TLS Protected EAP (PEAP) 受保护的 EAP DlgConnHidWifiSecPeap Connect to Hidden Wi-Fi Network 连接到隐藏 Wi-Fi 网络 Add hidden Wi-Fi 加入无线网络 Connection 连接设置: Network name 网络名称: Wi-Fi security Wi-Fi 安全性: Authentication 认证: Anonymous identity 匿名身份: Domain 域名: CA certificate CA 证书: CA certificate password CA 证书密码: No CA certificate is required 不需要CA证书 PEAP version PEAP版本: Inner authentication 内部认证: Username 用户名: Password 密码: Cancel 返回 Connect 连接 None WPA & WPA2 Personal WPA 及 WPA2 个人 WEP 40/128-bit Key (Hex or ASCII) WEP 40/128 位密钥(十六进制或ASCII) WEP 128-bit Passphrase WEP 128 位密码句 Dynamic WEP (802.1X) 动态 WEP (802.1x) WPA & WPA2 Enterprise WPA 及 WPA2 企业 Tunneled TLS 隧道 TLS Protected EAP (PEAP) 受保护的 EAP Choose from file 从文件选择... Automatic 自动 Version 0 版本 0 Version 1 版本 1 DlgConnHidWifiSecPwd Connect to Hidden Wi-Fi Network 连接到隐藏 Wi-Fi 网络 Add hidden Wi-Fi 加入无线网络 Connection 连接设置: Network name 网络名称: Wi-Fi security Wi-Fi 安全性: Authentication 认证: Username 用户名: Password 密码: Cancel 返回 Connect 连接 C_reate… 新建... None WPA & WPA2 Personal WPA 及 WPA2 个人 WEP 40/128-bit Key (Hex or ASCII) WEP 40/128 位密钥(十六进制或ASCII) WEP 128-bit Passphrase WEP 128 位密码句 Dynamic WEP (802.1X) 动态 WEP (802.1x) WPA & WPA2 Enterprise WPA 及 WPA2 企业 Tunneled TLS 隧道 TLS Protected EAP (PEAP) 受保护的 EAP DlgConnHidWifiSecTls Connect to Hidden Wi-Fi Network 连接到隐藏 Wi-Fi 网络 Add hidden Wi-Fi 加入无线网络 Connection 连接设置: Network name 网络名称: Wi-Fi security Wi-Fi 安全性: Authentication 认证: Identity 身份: Domain 域名: CA certificate CA 证书: CA certificate password CA 证书密码: No CA certificate is required 不需要CA证书 User certificate 用户证书: User certificate password 用户证书密码: User private key 用户私钥: User key password 用户密钥密码: Cancel 返回 Connect 连接 C_reate… 新建... None WPA & WPA2 Personal WPA 及 WPA2 个人 WEP 40/128-bit Key (Hex or ASCII) WEP 40/128 位密钥(十六进制或ASCII) WEP 128-bit Passphrase WEP 128 位密码句 Dynamic WEP (802.1X) 动态 WEP (802.1x) WPA & WPA2 Enterprise WPA 及 WPA2 企业 Tunneled TLS 隧道 TLS Protected EAP (PEAP) 受保护的 EAP Choose from file 从文件选择... DlgConnHidWifiSecTunnelTLS Connect to Hidden Wi-Fi Network 连接到隐藏 Wi-Fi 网络 Add hidden Wi-Fi 加入无线网络 Connection 连接设置: Network name 网络名称: Wi-Fi security Wi-Fi 安全性: Authentication 认证: Anonymous identity 匿名身份: Domain 域名: CA certificate CA 证书: CA certificate password CA 证书密码: No CA certificate is required 不需要CA证书 Inner authentication 内部认证: Username 用户名: Password 密码: Cancel 返回 Connect 连接 C_reate… 新建... None WPA & WPA2 Personal WPA 及 WPA2 个人 WEP 40/128-bit Key (Hex or ASCII) WEP 40/128 位密钥(十六进制或ASCII) WEP 128-bit Passphrase WEP 128 位密码句 Dynamic WEP (802.1X) 动态 WEP (802.1x) WPA & WPA2 Enterprise WPA 及 WPA2 企业 Tunneled TLS 隧道 TLS Protected EAP (PEAP) 受保护的 EAP Choose from file 从文件选择... DlgConnHidWifiWep Connect to Hidden Wi-Fi Network 连接到隐藏 Wi-Fi 网络 Add hidden Wi-Fi 加入无线网络 Connection 连接设置: Network name 网络名称: Wi-Fi security Wi-Fi 安全性: Key 密钥 WEP index WEP 检索 Authentication 认证: Cancel 返回 Connect 连接 C_reate… 新建... None WPA & WPA2 Personal WPA 及 WPA2 个人 WEP 40/128-bit Key (Hex or ASCII) WEP 40/128 位密钥(十六进制或ASCII) WEP 128-bit Passphrase WEP 128 位密码句 Dynamic WEP (802.1X) 动态 WEP (802.1x) WPA & WPA2 Enterprise WPA 及 WPA2 企业 1(default) 1(默认) Open System 开放式系统 Shared Key 共享密钥 DlgConnHidWifiWpa Connect to Hidden Wi-Fi Network 连接到隐藏 Wi-Fi 网络 Add Hidden Wi-Fi 加入无线网络 Connection 连接设置: Wi-Fi name 网络名称: Wi-Fi security Wi-Fi 安全性: Password 密码: Cancel 返回 Connect 连接 C_reate… 新建... None WPA & WPA2 Personal WPA 及 WPA2 个人 WEP 40/128-bit Key (Hex or ASCII) WEP 40/128 位密钥(十六进制或ASCII) WEP 128-bit Passphrase WEP 128 位密码句 Dynamic WEP (802.1X) 动态 WEP (802.1x) WPA & WPA2 Enterprise WPA 及 WPA2 企业 DlgHotspotCreate Dialog Create Hotspot 创建个人热点 Network name 网络名称: Wi-Fi security Wi-Fi 安全性: Password 密码: Cancel 返回 Ok 确定 None WPA & WPA2 Personal WPA 及 WPA2 个人 InputInfos Service exception... 服务异常,重试中... Invaild parameters... 参数异常,重试中... Unknown fault:%1 未知错误:%1 Recapture(60s) 重新获取(60s) Recapture(%1s) 重新获取(%1s) Get code 获取验证码 KeyboardWidget KeyboardWidget KylinDBus kylin network applet desktop message 麒麟网络工具信息提示 KylinNM kylin-nm 网络工具 LAN 有线连接 Enabel LAN List 其他有线网络 WiFi 无线网络 Enabel WiFi List 其他无线网络 New WiFi 加入其他网络 Network 网络 Advanced 设置网络 Ethernet 有线网络 Connect Hide Network 加入网络 Wifi 无线网络 Enabled 已开启 Disabled 已关闭 HotSpot 个人热点 FlyMode 飞行模式 Show MainWindow 显示网络连接界面 Show KylinNM No wireless card detected 未检测到无线网卡 Not connected 未连接任何网络 Disconnected 未连接 No Other Wired Network Scheme 列表中无其他有线网络 Edit 编辑 Done 完成 No wifi connected. 未连接任何网络 No Other Wireless Network Scheme 未检测到其他无线网络 Wired net is disconnected 断开有线网络 Wi-Fi is disconnected 断开无线网络 Confirm your Wi-Fi password or usable of wireless card 请确认Wi-Fi密码或无线设备 Ethernet Networks 其他有线网络 New LAN 新建有线网络 Hide WiFi 加入网络 No usable network in the list 列表暂无可连接网络 NetOn, 已连接, Wifi Networks 其他无线网络 None keep wired network switch is on before turning on wireless switch 打开无线网开关前保持有线网开关打开 please insert the wireless network adapter 请先插入无线网卡 Abnormal connection exist, program will delete it 正在断开异常连接的网络 update Wi-Fi list now, click again 正在更新 Wi-Fi列表 请再次点击 update Wi-Fi list now 正在更新 Wi-Fi列表 Conn Ethernet Success 连接有线网络成功 Conn Ethernet Fail 连接有线网络失败 Conn Wifi Success 连接无线网络成功 LockWidget Form Date 日期 Time 时间 Guest 游客 SwitchUser 切换用户 MyLineEdit Verification code 短信验证码 OneConnForm Form -- Automatically join the network 自动加入该网络 Input password 输入密码 Config 设置 Connect 连接 Disconnect 断开连接 Input Password... 输入密码... Connect to Hidden Wi-Fi Network 连接到隐藏 Wi-Fi 网络 Signal: 信号强度: Public 开放 Safe 安全 Rate 速率 None WiFi Security: WiFi安全性: MAC: 物理地址: Conn Wifi Failed 连接无线网络失败 OneLancForm Form -- Config 设置 Connect 连接 Disconnect 断开连接 No Configuration 未配置 IPv4: IPv4地址: IPv6: IPv6地址: BandWidth: 带宽: MAC: 物理地址: Auto 自动 PhoneAuthWidget Verification by phoneNum 手机号验证 「 Use bound Phone number to verification 」 「 Use SMS to verification 」 「 请使用绑定该账户手机号验证 」 commit 提交 Network not connected~ 系统未联网,请检查网络连接~ Network unavailable~ 网络状态差,请检查网络连接~ Verification Code invalid! 验证码失效 Verification Code incorrect.Please retry! 验证码错误!请填写正确的验证码! Failed time over limit!Retry after 1 hour! 验证码错误次数超过10次,1小时后再试 verifaction failed! 手机验证失败 PowerManager lock 锁定 SwitchUser 切换用户 logout 注销 reboot 重启 shutdown 关机 Lock Screen 锁屏 Switch User 切换用户 Log Out 注销 Restart 重启 Power Off 关机 Suspend 睡眠 Sleep 休眠 QObject The screensaver is active. 屏幕保护程序已激活 The screensaver is inactive. 屏幕保护程序未激活 Screensaver exit(Esc) 退出(Esc) exit 退出 Picture does not exist 图片不存在 Set as desktop wallpaper 设置为桌面壁纸 Automatic switching 自动切换 You have %1 unread message 您有%1条未读消息 You have new notification 您有新的消息 View 预览 SleepTime You have rested: 您已休息: SwitchButton login by password 密码登录 login by qr code 微信登录 SwitchButtonGroup uEduPWD 密码登录 Wechat 微信登录 TabletLockWidget You have %1 unread message 您有%1条未读消息 Slide to unlock 向上滑动解锁 New password is the same as old 新密码与原密码相同 Reset password error:%1 重置密码失败:%1 Please scan by correct WeChat 请使用正确的微信扫码 Cancel 取消 Back 返回 Skip 跳过 Utils kylin network applet desktop message 麒麟网络工具信息提示 VerificationWidget Please scan by bound WeChat 请使用已绑定的微信扫码 VerticalVerificationWidget Please scan by bound WeChat 请使用已绑定的微信扫码 WeChatAuthDialog Login by wechat 微信登录 Verification by wechat 微信验证 「 Use registered WeChat account to login 」 「 使用已注册的微信号登录 」 「 Use bound WeChat account to verification 」 「 请使用绑定该账号的微信验证 」 Network not connected~ 系统未联网,请检查网络连接~ Scan code successfully 扫码成功 Timeout!Try again! 超时!请重新扫码! Login failed 登录失败 main Start command for the ukui ScreenSaver. 启动锁屏到命令 lock the screen immediately 马上锁定屏幕 query the status of the screen saver 获取锁屏状态 unlock the screen saver 解锁屏幕 show the screensaver Dialog for the ukui ScreenSaver. activated by session idle signal lock the screen and show screensaver immediately show screensaver immediately Screensaver for ukui-screensaver show on root window show on window. window id ukui-screensaver/i18n_ts/ru.ts0000644000175000017500000014561514205074760015275 0ustar fengfeng AuthDialog Form форма More Devices Дополнительные устройства Biometric Биометрические Password пароль Retry Retry UnLock отпереть LoggedIn LoggedIn Password Incorrect, Please try again Пароль неверен, повторите попытку Password: Biometric Authentication Password Authentication Other Devices Authentication failure, Please try again Please enter your password or enroll your fingerprint Too many unsuccessful attempts,please enter password. Fingerprint authentication failed, you still have %1 verification opportunities Please try again in %1 minutes. Please try again in %1 seconds. Account locked permanently. Password cannot be empty Login BioAuthWidget Form форма TextLabel TextLabel More Больше Retry Retry Password пароль BioDevices FingerPrint FingerPrint FingerVein FingerVein Iris Ирис Face Лицо VoicePrint Voiceprint BioDevicesWidget Form форма Please select other biometric devices Выберите другие биометрические устройства Device Type: Тип устройства: Device Name: Имя устройства: BiometricAuthWidget Current device: Identify failed, Please retry. BiometricDevicesWidget Please select the biometric device Device type: Device name: OK ConfForm edit network LAN name: Method: Address: Netmask: Gateway: DNS 1: DNS 2: Edit Conn Auto(DHCP) Manual Cancel Save Ok Can not create new wired network for without wired card New network already created New network settings already finished New settings already effective Edit Network Add Wired Network DeviceType FingerPrint FingerPrint FingerVein FingerVein Iris Ирис Face Лицо VoicePrint Voiceprint DigitalAuthDialog LoginByUEdu ResetPWD? SetNewUEduPWD clear ConfirmNewUEduPWD The two password entries are inconsistent, please reset Password entered incorrectly, please try again DlgConnHidWifi Connect to Hidden Wi-Fi Network Add Hidden Wi-Fi Connection Wi-Fi name Wi-Fi security Cancel Connect C_reate… None WPA & WPA2 Personal DlgConnHidWifiLeap Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Username Password пароль Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise DlgConnHidWifiSecFast Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Anonymous identity Allow automatic PAC pro_visioning PAC file Inner authentication Username Password пароль Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Anonymous Authenticated Both DlgConnHidWifiSecLeap Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Username Password пароль Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) DlgConnHidWifiSecPeap Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Anonymous identity Domain CA certificate CA certificate password No CA certificate is required PEAP version Inner authentication Username Password пароль Cancel Connect None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Choose from file Automatic Version 0 Version 1 DlgConnHidWifiSecPwd Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Username Password пароль Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) DlgConnHidWifiSecTls Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Identity Domain CA certificate CA certificate password No CA certificate is required User certificate User certificate password User private key User key password Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Choose from file DlgConnHidWifiSecTunnelTLS Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Anonymous identity Domain CA certificate CA certificate password No CA certificate is required Inner authentication Username Password пароль Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Choose from file DlgConnHidWifiWep Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Key WEP index Authentication Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise 1(default) Open System Shared Key DlgConnHidWifiWpa Connect to Hidden Wi-Fi Network Add Hidden Wi-Fi Connection Wi-Fi name Wi-Fi security Password пароль Cancel Connect C_reate… None WPA & WPA2 Personal DlgHotspotCreate Dialog Create Hotspot Network name Wi-Fi security Password пароль Cancel Ok None WPA & WPA2 Personal InputInfos Get code Recapture(60s) Recapture(%1s) Service exception... Invaild parameters... Unknown fault:%1 KeyboardWidget KeyboardWidget KeyboardWidget KylinNM kylin-nm Ethernet Networks Wifi Networks No usable network in the list Ethernet Wifi HotSpot FlyMode Advanced Show KylinNM No wireless card detected Not connected Disconnected NetOn, No Other Wired Network Scheme No Other Wireless Network Scheme Wired net is disconnected Conn Ethernet Success Conn Ethernet Fail Conn Wifi Success Confirm your Wi-Fi password or usable of wireless card LockWidget Form форма Date Дата Time Время Guest гость SwitchUser Сменить пользователя MyLineEdit Verification code OneConnForm Form форма Connect Disconnect Input Password... Automatically join the network Connect to Hidden Wi-Fi Network None WiFi Security: Signal: MAC: Conn Wifi Failed OneLancForm Form форма Connect Disconnect No Configuration IPv4: IPv6: BandWidth: MAC: PhoneAuthWidget Verification by phoneNum 「 Use bound Phone number to verification 」 commit 「 Use SMS to verification 」 Network not connected~ Verification Code invalid! Verification Code incorrect.Please retry! Failed time over limit!Retry after 1 hour! verifaction failed! Network unavailable~ PowerManager SwitchUser Сменить пользователя Switch User Log Out Restart Power Off Suspend Sleep lock QObject The screensaver is active. The screensaver is inactive. Screensaver Picture does not exist View You have new notification SleepTime You have rested: SwitchButtonGroup uEduPWD Wechat TabletLockWidget Cancel Back Skip New password is the same as old Reset password error:%1 Please scan by correct WeChat Utils kylin network applet desktop message VerificationWidget Please scan by bound WeChat VerticalVerificationWidget Please scan by bound WeChat WeChatAuthDialog Login by wechat 「 Use registered WeChat account to login 」 Verification by wechat 「 Use bound WeChat account to verification 」 Network not connected~ Scan code successfully Timeout!Try again! main Start command for the ukui ScreenSaver. Начните команду для ukui ScreenSaver. lock the screen immediately немедленно заблокируйте экран Dialog for the ukui ScreenSaver. Диалог для экранного экрана ukui. activated by session idle signal активируется сигналом холостого хода Screensaver for ukui-screensaver show on root window show on window. window id query the status of the screen saver lock the screen and show screensaver immediately unlock the screen saver show the screensaver show screensaver immediately ukui-screensaver/i18n_ts/tr.ts0000644000175000017500000025627514205074760015301 0ustar fengfeng AuthDialog More Devices Diğer Cihazlar Biometric Biometrik Password Parola Retry Yeniden Dene UnLock Kilidi Aç Password: Parola Account locked %1 minutes due to %2 fail attempts %2 başarısız denemeden dolayı hesap %1 dakika kilitlendi Password Incorrect, Please try again Parola yanlış, Lütfen tekrar deneyin Authentication failure,there are still %1 remaining opportunities Kimlik doğrulama hatası, hala %1 kalan denemen var Please enter your password or enroll your fingerprint Authentication failure, Please try again Please try again in %1 minutes. Please try again in %1 seconds. Account locked permanently. Password cannot be empty Login Biometric Authentication Biyometrik Kimlik Doğrulama Password Authentication Parola Doğrulama Other Devices Diğer Ayıtlar Too many unsuccessful attempts,please enter password. Fingerprint authentication failed, you still have %1 verification opportunities BioDevices FingerPrint Parmak İzi FingerVein Damar İzi Iris Göz Face Yüz VoicePrint Ses İzi BioDevicesWidget Please select other biometric devices Lütfen diğer biyometrik cihazları seçin Device Type: Aygıt Türü: Device Name: Aygıt Adı: BiometricAuthWidget Current device: Şuanki aygıt: Identify failed, Please retry. Tanımlama başarısız, Lütfen tekrar deneyin. BiometricDevicesWidget Please select the biometric device Lütfen biyometrik aygıtı seçin Device type: Aygıt türü: Device name: Aygıt adı: OK Tamam ConfForm edit network LAN name: Method: Address: Netmask: Gateway: DNS 1: DNS 2: Edit Conn Auto(DHCP) Manual Cancel Save Ok Can not create new wired network for without wired card New network already created New network settings already finished New settings already effective Edit Network Add Wired Network DeviceType FingerPrint Parmak İzi FingerVein Parmak Damarı Iris Göz Face Yüz VoicePrint Ses İzi DigitalAuthDialog LoginByUEdu ResetPWD? SetNewUEduPWD clear ConfirmNewUEduPWD The two password entries are inconsistent, please reset Password entered incorrectly, please try again DlgConnHidWifi Connect to Hidden Wi-Fi Network Add Hidden Wi-Fi Connection Wi-Fi name Wi-Fi security Cancel Connect C_reate… None WPA & WPA2 Personal DlgConnHidWifiLeap Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Username Password Parola Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise DlgConnHidWifiSecFast Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Anonymous identity Allow automatic PAC pro_visioning PAC file Inner authentication Username Password Parola Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Anonymous Authenticated Both DlgConnHidWifiSecLeap Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Username Password Parola Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) DlgConnHidWifiSecPeap Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Anonymous identity Domain CA certificate CA certificate password No CA certificate is required PEAP version Inner authentication Username Password Parola Cancel Connect None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Choose from file Automatic Version 0 Version 1 DlgConnHidWifiSecPwd Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Username Password Parola Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) DlgConnHidWifiSecTls Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Identity Domain CA certificate CA certificate password No CA certificate is required User certificate User certificate password User private key User key password Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Choose from file DlgConnHidWifiSecTunnelTLS Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Anonymous identity Domain CA certificate CA certificate password No CA certificate is required Inner authentication Username Password Parola Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Choose from file DlgConnHidWifiWep Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Key WEP index Authentication Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise 1(default) Open System Shared Key DlgConnHidWifiWpa Connect to Hidden Wi-Fi Network Add Hidden Wi-Fi Connection Wi-Fi name Wi-Fi security Password Parola Cancel Connect C_reate… None WPA & WPA2 Personal DlgHotspotCreate Dialog Create Hotspot Network name Wi-Fi security Password Parola Cancel Ok None WPA & WPA2 Personal InputInfos Get code Recapture(60s) Recapture(%1s) Service exception... Invaild parameters... Unknown fault:%1 KeyboardWidget KeyboardWidget KylinNM kylin-nm Ethernet Networks Wifi Networks No usable network in the list Ethernet Wifi HotSpot FlyMode Advanced Show KylinNM No wireless card detected Not connected Disconnected NetOn, No Other Wired Network Scheme No Other Wireless Network Scheme Wired net is disconnected Conn Ethernet Success Conn Ethernet Fail Conn Wifi Success Confirm your Wi-Fi password or usable of wireless card LockWidget Form Date Tarih Time Zaman Guest Misafir SwitchUser Kullanıcı Değiştir MyLineEdit Verification code OneConnForm Form Connect Disconnect Input Password... Automatically join the network Connect to Hidden Wi-Fi Network None WiFi Security: Signal: MAC: Conn Wifi Failed OneLancForm Form Connect Disconnect No Configuration IPv4: IPv6: BandWidth: MAC: PhoneAuthWidget Verification by phoneNum 「 Use bound Phone number to verification 」 commit 「 Use SMS to verification 」 Network not connected~ Verification Code invalid! Verification Code incorrect.Please retry! Failed time over limit!Retry after 1 hour! verifaction failed! Network unavailable~ PowerManager lock kilit SwitchUser Kullanıcı Değiştir logout Çıkış reboot yeniden başlat shutdown kapat Lock Screen Ekranı Kilitle Switch User Kullanıcı Değiştir Log Out Çıkış Restart Yeniden Başlat Power Off Bilgisayarı Kapat Suspend Sleep QObject The screensaver is active. The screensaver is inactive. Screensaver exit(Esc) çıkış(Esc) exit çıkış Picture does not exist View You have new notification Set as desktop wallpaper Masaüstü arkaplanı olarak ayarla Automatic switching Otomatik değiştir SleepTime You have rested: SwitchButtonGroup uEduPWD Wechat TabletLockWidget Cancel Back Skip New password is the same as old Reset password error:%1 Please scan by correct WeChat Utils kylin network applet desktop message VerificationWidget Please scan by bound WeChat VerticalVerificationWidget Please scan by bound WeChat WeChatAuthDialog Login by wechat 「 Use registered WeChat account to login 」 Verification by wechat 「 Use bound WeChat account to verification 」 Network not connected~ Scan code successfully Timeout!Try again! main Start command for the ukui ScreenSaver. Ukui Ekran Koruyucu için başlatma komutu. lock the screen immediately Ekranı hemen kilitle query the status of the screen saver unlock the screen saver show the screensaver Dialog for the ukui ScreenSaver. activated by session idle signal lock the screen and show screensaver immediately show screensaver immediately Screensaver for ukui-screensaver show on root window show on window. window id ukui-screensaver/i18n_ts/es.ts0000644000175000017500000014526114205074760015253 0ustar fengfeng AuthDialog Form Formar More Devices Más dispositivos Biometric Biometrico Password Contraseña Retry Procesar de nuevo UnLock Desbloquear LoggedIn Conectado Password Incorrect, Please try again Contraseña incorrecta, por favor intente de nuevo Password: Biometric Authentication Password Authentication Other Devices Authentication failure, Please try again Please enter your password or enroll your fingerprint Too many unsuccessful attempts,please enter password. Fingerprint authentication failed, you still have %1 verification opportunities Please try again in %1 minutes. Please try again in %1 seconds. Account locked permanently. Password cannot be empty Login BioAuthWidget Form Formar TextLabel TextLabel More Más Retry Procesar de nuevo Password Contraseña BioDevices FingerPrint Huella dactilar FingerVein FingerVein Iris Iris Face Cara VoicePrint Impresión de voz BioDevicesWidget Form Formar Please select other biometric devices Por favor seleccione otros dispositivos biométricos Device Type: Tipo de dispositivo: Device Name: Nombre del dispositivo: BiometricAuthWidget Current device: Identify failed, Please retry. BiometricDevicesWidget Please select the biometric device Device type: Device name: OK ConfForm edit network LAN name: Method: Address: Netmask: Gateway: DNS 1: DNS 2: Edit Conn Auto(DHCP) Manual Cancel Save Ok Can not create new wired network for without wired card New network already created New network settings already finished New settings already effective Edit Network Add Wired Network DeviceType FingerPrint Huella dactilar FingerVein FingerVein Iris Iris Face Cara VoicePrint Impresión de voz DigitalAuthDialog LoginByUEdu ResetPWD? SetNewUEduPWD clear ConfirmNewUEduPWD The two password entries are inconsistent, please reset Password entered incorrectly, please try again DlgConnHidWifi Connect to Hidden Wi-Fi Network Add Hidden Wi-Fi Connection Wi-Fi name Wi-Fi security Cancel Connect C_reate… None WPA & WPA2 Personal DlgConnHidWifiLeap Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Username Password Contraseña Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise DlgConnHidWifiSecFast Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Anonymous identity Allow automatic PAC pro_visioning PAC file Inner authentication Username Password Contraseña Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Anonymous Authenticated Both DlgConnHidWifiSecLeap Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Username Password Contraseña Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) DlgConnHidWifiSecPeap Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Anonymous identity Domain CA certificate CA certificate password No CA certificate is required PEAP version Inner authentication Username Password Contraseña Cancel Connect None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Choose from file Automatic Version 0 Version 1 DlgConnHidWifiSecPwd Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Username Password Contraseña Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) DlgConnHidWifiSecTls Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Identity Domain CA certificate CA certificate password No CA certificate is required User certificate User certificate password User private key User key password Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Choose from file DlgConnHidWifiSecTunnelTLS Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Authentication Anonymous identity Domain CA certificate CA certificate password No CA certificate is required Inner authentication Username Password Contraseña Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise Tunneled TLS Protected EAP (PEAP) Choose from file DlgConnHidWifiWep Connect to Hidden Wi-Fi Network Add hidden Wi-Fi Connection Network name Wi-Fi security Key WEP index Authentication Cancel Connect C_reate… None WPA & WPA2 Personal WEP 40/128-bit Key (Hex or ASCII) WEP 128-bit Passphrase Dynamic WEP (802.1X) WPA & WPA2 Enterprise 1(default) Open System Shared Key DlgConnHidWifiWpa Connect to Hidden Wi-Fi Network Add Hidden Wi-Fi Connection Wi-Fi name Wi-Fi security Password Contraseña Cancel Connect C_reate… None WPA & WPA2 Personal DlgHotspotCreate Dialog Create Hotspot Network name Wi-Fi security Password Contraseña Cancel Ok None WPA & WPA2 Personal InputInfos Get code Recapture(60s) Recapture(%1s) Service exception... Invaild parameters... Unknown fault:%1 KeyboardWidget KeyboardWidget TecladoWidget KylinNM kylin-nm Ethernet Networks Wifi Networks No usable network in the list Ethernet Wifi HotSpot FlyMode Advanced Show KylinNM No wireless card detected Not connected Disconnected NetOn, No Other Wired Network Scheme No Other Wireless Network Scheme Wired net is disconnected Conn Ethernet Success Conn Ethernet Fail Conn Wifi Success Confirm your Wi-Fi password or usable of wireless card LockWidget Form Formar Date Fecha Time Hora Guest Huésped SwitchUser Cambiar de usuario MyLineEdit Verification code OneConnForm Form Formar Connect Disconnect Input Password... Automatically join the network Connect to Hidden Wi-Fi Network None WiFi Security: Signal: MAC: Conn Wifi Failed OneLancForm Form Formar Connect Disconnect No Configuration IPv4: IPv6: BandWidth: MAC: PhoneAuthWidget Verification by phoneNum 「 Use bound Phone number to verification 」 commit 「 Use SMS to verification 」 Network not connected~ Verification Code invalid! Verification Code incorrect.Please retry! Failed time over limit!Retry after 1 hour! verifaction failed! Network unavailable~ PowerManager SwitchUser Cambiar de usuario Switch User Log Out Restart Power Off Suspend Sleep lock QObject The screensaver is active. The screensaver is inactive. Screensaver Picture does not exist View You have new notification SleepTime You have rested: SwitchButtonGroup uEduPWD Wechat TabletLockWidget Cancel Back Skip New password is the same as old Reset password error:%1 Please scan by correct WeChat Utils kylin network applet desktop message VerificationWidget Please scan by bound WeChat VerticalVerificationWidget Please scan by bound WeChat WeChatAuthDialog Login by wechat 「 Use registered WeChat account to login 」 Verification by wechat 「 Use bound WeChat account to verification 」 Network not connected~ Scan code successfully Timeout!Try again! main Start command for the ukui ScreenSaver. Comando de inicio para el protector de pantalla de ukui. lock the screen immediately bloquea la pantalla inmediatamente Dialog for the ukui ScreenSaver. Diálogo para el protector de pantalla de ukui. activated by session idle signal activado por la señal de inactividad de la sesión Screensaver for ukui-screensaver show on root window show on window. window id query the status of the screen saver lock the screen and show screensaver immediately unlock the screen saver show the screensaver show screensaver immediately ukui-screensaver/CMakeLists.txt0000644000175000017500000000356714205076742015553 0ustar fengfengcmake_minimum_required(VERSION 2.6) project(ukui-screensaver) find_package(Qt5 COMPONENTS Core Widgets DBus X11Extras Xml Network Svg) find_package(PkgConfig REQUIRED) find_package(OpenCV REQUIRED) find_package(PkgConfig) find_package(X11 REQUIRED) pkg_check_modules(GIOUNIX2 REQUIRED gio-unix-2.0) pkg_check_modules(GLIB2 REQUIRED glib-2.0 gio-2.0) # 是否是intel项目 option (USE_INTEL "intel项目" OFF) # 用于测试替换用的变量 set(TEST_ON 1) set(TEST_OF 0) set(VAR "VAR_NEW") # 加入一个配置头文件,用于处理 CMake 对源码的设置 configure_file ( "${CMAKE_CURRENT_SOURCE_DIR}/config.h.in" "${CMAKE_CURRENT_BINARY_DIR}/config.h" ) set(TS_FILES ${CMAKE_CURRENT_SOURCE_DIR}/i18n_ts/zh_CN.ts ${CMAKE_CURRENT_SOURCE_DIR}/i18n_ts/es.ts ${CMAKE_CURRENT_SOURCE_DIR}/i18n_ts/fr.ts ${CMAKE_CURRENT_SOURCE_DIR}/i18n_ts/pt.ts ${CMAKE_CURRENT_SOURCE_DIR}/i18n_ts/ru.ts ${CMAKE_CURRENT_SOURCE_DIR}/i18n_ts/tr.ts ) add_custom_command( OUTPUT ${TS_FILES} COMMAND lupdate src/ screensaver/ -ts ${TS_FILES} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) add_custom_target( i18n_ts DEPENDS ${TS_FILES} ) add_compile_options(-fPIC) #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror") set(CMAKE_CXX_STANDARD 11) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_INSTALL_PREFIX /usr) set(Debug ON) if(Debug) set(CMAKE_BUILD_TYPE "Debug") endif() #add_subdirectory(BioAuth) add_subdirectory(BiometricAuth) add_subdirectory(VirtualKeyboard) add_subdirectory(src) add_subdirectory(i18n_ts) add_subdirectory(data) add_subdirectory(screensaver) add_subdirectory(screensaver-focus-helper) add_subdirectory(Common) add_subdirectory(KylinNM) add_dependencies(ukui-screensaver-dialog BiometricAuth VirtualKeyboard Common) add_dependencies(ukui-screensaver-default Common) ukui-screensaver/screensaver-focus-helper/0000755000175000017500000000000014205074760017710 5ustar fengfengukui-screensaver/screensaver-focus-helper/CMakeLists.txt0000644000175000017500000000050214205074704022443 0ustar fengfengproject(screensaver-capslock-helper) set(CMAKE_AUTOMOC ON) set(bin_SRCS ${bin_SRCS} main.cpp ) add_executable(screensaver-focus-helper ${bin_SRCS}) target_link_libraries(screensaver-focus-helper Qt5::Core Qt5::Widgets) install(TARGETS screensaver-focus-helper DESTINATION lib/ukui-screensaver) ukui-screensaver/screensaver-focus-helper/main.cpp0000644000175000017500000000260214205074760021340 0ustar fengfeng/** * Copyright (C) 2018 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, 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 #include #include #include #include #include #include #include #include int main(int argc, char *argv[]) { QApplication a(argc, argv); QWidget w; w.resize(QApplication::desktop()->size()); w.setWindowFlags(Qt::X11BypassWindowManagerHint); QPalette pal(w.palette()); pal.setColor(QPalette::Background, Qt::black); //设置背景黑色 w.setAutoFillBackground(true); w.setPalette(pal); w.setCursor(Qt::BlankCursor); w.showFullScreen(); a.exec(); return 0; } ukui-screensaver/Common/0000755000175000017500000000000014205074704014224 5ustar fengfengukui-screensaver/Common/autoresize.h0000644000175000017500000000202014205074704016561 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef AUTORESIZE_H #define AUTORESIZE_H #include struct AutoResizeOriginalData { QRect data_rect; QFont data_font; }; class AutoResize { public: AutoResize(QWidget* obj,int baseWidth,int baseHeight); ~AutoResize(void); private: QWidget *obj; int baseWidth; int baseHeight; }; #endif ukui-screensaver/Common/commonfunc.h0000644000175000017500000000225614205074704016546 0ustar fengfeng/* -*- 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. * */ #ifndef COMMONFUNC_H #define COMMONFUNC_H #include #include bool ispicture(QString filepath); QString getSystemVersion(); QString getSystemDistrib(); bool getUseFirstDevice(); QString ElideText(QFont font,int width,QString strInfo); class commonFunc { public: commonFunc(); }; #endif // COMMONFUNC_H ukui-screensaver/Common/checkbutton.cpp0000644000175000017500000001024014205074704017236 0ustar fengfeng/* -*- 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 "checkbutton.h" checkButton::checkButton(QWidget *parent) :QFrame(parent) { this->setFixedSize(QSize(52, 24)); checked = false; borderColorOff = QColor("#cccccc"); bgColorOff = QColor("#ffffff"); bgColorOn = QColor("#0078d7"); sliderColorOff = QColor("#cccccc"); sliderColorOn = QColor("#ffffff"); space = 4; step = width() / 50; startX = 0; endX= 0; timer = new QTimer(this); timer->setInterval(5); connect(timer, SIGNAL(timeout()), this, SLOT(updatevalue())); setWindowFlags(Qt::FramelessWindowHint); setAttribute(Qt::WA_TranslucentBackground, true); } void checkButton::paintEvent(QPaintEvent *){ //启用反锯齿 QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing, true); drawBg(&painter); drawSlider(&painter); } void checkButton::drawBg(QPainter *painter){ painter->save(); if (!checked){ painter->setPen(QColor(255,255,255,30)); painter->setBrush(QColor(255,255,255,30)); } else{ painter->setPen(Qt::NoPen); painter->setBrush(bgColorOn); } //circle in QRect rect(0, 0, width(), height()); //半径为高度的一半 int radius = rect.height() / 2; //圆的宽度为高度 int circleWidth = rect.height(); QPainterPath path; path.moveTo(radius, rect.left()); path.arcTo(QRectF(rect.left(), rect.top(), circleWidth, circleWidth), 90, 180); path.lineTo(rect.width() - radius, rect.height()); path.arcTo(QRectF(rect.width() - rect.height(), rect.top(), circleWidth, circleWidth), 270, 180); path.lineTo(radius, rect.top()); painter->drawPath(path); painter->restore(); } void checkButton::drawSlider(QPainter *painter){ painter->save(); painter->setPen(Qt::NoPen); if (!checked){ painter->setBrush(sliderColorOff); } else painter->setBrush(sliderColorOn); //circle in QRect rect(0, 0, width(), height()); int sliderWidth = rect.height() - space * 2; QRect sliderRect(startX + space, space, sliderWidth, sliderWidth); painter->drawEllipse(sliderRect); painter->restore(); } void checkButton::mousePressEvent(QMouseEvent *){ checked = !checked; emit checkedChanged(checked); step = width() / 50; if (checked){ endX = width() - height(); } else{ endX = 0; } timer->start(); } void checkButton::resizeEvent(QResizeEvent *){ step = width() / 50; if (checked){ startX = width() - height(); } else startX = 0; update(); } void checkButton::updatevalue(){ if (checked) if (startX < endX){ startX = startX + step; } else{ startX = endX; timer->stop(); } else{ if (startX > endX){ startX = startX - step; } else{ startX = endX; timer->stop(); } } update(); } void checkButton::setChecked(bool checked){ if (this->checked != checked){ this->checked = checked; emit checkedChanged(checked); update(); } step = width() / 50; if (checked){ endX = width() - height(); } else{ endX = 0; } timer->start(); } bool checkButton::isChecked(){ return this->checked; } ukui-screensaver/Common/commonfunc.cpp0000644000175000017500000000434614205074704017103 0ustar fengfeng/* -*- 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 #include #include #include #include #include "commonfunc.h" bool ispicture(QString filepath) { QFileInfo file(filepath); if(file.exists() == false) return false; QMimeDatabase db; QMimeType mime = db.mimeTypeForFile(filepath); return mime.name().startsWith("image/"); } QString getSystemVersion() { QSettings settings("/etc/lsb-release", QSettings::IniFormat); QString release = settings.value("DISTRIB_RELEASE").toString(); QString description = settings.value("DISTRIB_DESCRIPTION").toString(); if(description.right(3) == "LTS") release = release + " LTS"; return release; } QString getSystemDistrib() { QSettings settings("/etc/lsb-release", QSettings::IniFormat); QString distribId = settings.value("DISTRIB_ID").toString(); return distribId; } bool getUseFirstDevice() { QSettings settings("/etc/biometric-auth/ukui-biometric.conf", QSettings::IniFormat); return settings.value("UseFirstDevice").toBool(); } commonFunc::commonFunc() { } QString ElideText(QFont font,int width,QString strInfo) { QFontMetrics fontMetrics(font); //如果当前字体下,字符串长度大于指定宽度 if(fontMetrics.width(strInfo) > width) { strInfo= QFontMetrics(font).elidedText(strInfo, Qt::ElideRight, width); } return strInfo; } ukui-screensaver/Common/autoresize.cpp0000644000175000017500000000161014205074704017120 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "autoresize.h" AutoResize::AutoResize(QWidget* obj,int baseWidth,int baseHeight): obj(obj), baseWidth(baseWidth), baseHeight(baseHeight) { } AutoResize::~AutoResize(void) { } ukui-screensaver/Common/CMakeLists.txt0000644000175000017500000000060614205074704016766 0ustar fengfengqt5_wrap_cpp(Common_SRC autoresize.h checkbutton.h commonfunc.h ) set(Common_SRC ${Common_SRC} autoresize.cpp checkbutton.cpp commonfunc.cpp ) include_directories( ${Qt5Core_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5DBus_INCLUDE_DIRS} ) add_library(Common STATIC ${Common_SRC}) target_link_libraries(Common Qt5::Core Qt5::DBus Qt5::Widgets) ukui-screensaver/Common/checkbutton.h0000644000175000017500000000343514205074704016713 0ustar fengfeng/* -*- 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. * */ #ifndef CHECKBUTTON_H #define CHECKBUTTON_H #include #include #include #include #include #include class checkButton : public QFrame { Q_OBJECT public: checkButton(QWidget *parent = 0); void setChecked(bool checked); bool isChecked(); protected: void mousePressEvent(QMouseEvent *); void resizeEvent(QResizeEvent *); void paintEvent(QPaintEvent *); private: bool checked; QColor borderColorOff; QColor bgColorOff; QColor bgColorOn; QColor sliderColorOff; QColor sliderColorOn; int space; //滑块离背景间隔 int rectRadius; //圆角角度 int step; //移动步长 int startX; int endX; QTimer * timer; void drawBg(QPainter *painter); void drawSlider(QPainter *painter); private slots: void updatevalue(); Q_SIGNALS: void checkedChanged(bool checked); }; #endif // CHECKBUTTON_H ukui-screensaver/man/0000755000175000017500000000000014205074760013551 5ustar fengfengukui-screensaver/man/ukui-screensaver-backend.10000644000175000017500000000423514205074704020515 0ustar fengfeng.\" ukui-screensaver manual page .\" .\" This is free software; you may 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, .\" or (at your option) any later version. .\" .\" This 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. .\" .TH UKUI-SCREENSAVER 1 "03 May 2018" "UKUI Desktop Environment" .\" Please adjust this date whenever revising the manpage. .\" .SH "NAME" ukui-screensaver \- The UKUI Desktop Screensaver and Locker .SH "SYNOPSIS" .B ukui-screensaver [OPTIONS] .SH "DESCRIPTION" UKUI Screensaver is the default screen saver and locker for the UKUI Desktop. It is designed with simplicity and security in mind. \fBukui-screensaver\fP integrates well with the UKUI desktop, and it supports User Switching and the ability to lock down configuration settings. .SH "OPTIONS" .TP \fB\-\-display=DISPLAY\fR X display to use. .TP \fB\-\-no\-daemon\fR Don't start as a daemon .TP \fB\-\-debug\fR Enable debugging messages for \fBukui-screensaver\fP .TP \fB\-\-version\fR Output version information and exit. .TP \fB\-h, \-\-help\fR Print standard command line options. .TP \fB\-\-help\-all\fR Print all command line options. .P This program also accepts the standard GTK options. .SH "BUGS" .SS Should you encounter any bugs, they may be reported at: http://github.com/ukui-desktop/ukui-screensaver/issues .SH "AUTHORS" .SS ukui-screensaver is maintained by: .nf Hao Lee .fi .SS This Man Page has been updated for the UKUI Desktop Environment by: Hao Lee (2018) .SH "SEE ALSO" .SS Further information may also be available at: http://wiki.ukui-desktop.org/docs .P .BR ukui-screensaver-command (1), .BR ukui-screensaver-preferences (1), .BR gtk-options (7) ukui-screensaver/man/ukui-screensaver-command.10000644000175000017500000000415714205074704020547 0ustar fengfeng.\" ukui-screensaver manual page .\" .\" This is free software; you may 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, .\" or (at your option) any later version. .\" .\" This 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. .\" .TH UKUI-SCREENSAVER 1 "03 May 2018" "UKUI Desktop Environment" .\" Please adjust this date whenever revising the manpage. .\" .SH "NAME" ukui-screensaver \- The UKUI Desktop Screensaver and Locker .SH "SYNOPSIS" .B ukui-screensaver [OPTIONS] .SH "DESCRIPTION" UKUI Screensaver is the default screen saver and locker for the UKUI Desktop. It is designed with simplicity and security in mind. \fBukui-screensaver\fP integrates well with the UKUI desktop, and it supports User Switching and the ability to lock down configuration settings. .SH "OPTIONS" .TP \fB\-\-display=DISPLAY\fR X display to use. .TP \fB\-\-no\-daemon\fR Don't start as a daemon .TP \fB \-\-debug\fR Enable debugging messages for \fBukui-screensaver\fP .TP \fB\-\-version\fR Output version information and exit. .TP \fB\-h, \-\-help\fR Print standard command line options. .TP \fB\-\-help\-all\fR Print all command line options. .P This program also accepts the standard GTK options. .SH "BUGS" .SS Should you encounter any bugs, they may be reported at: http://github.com/ukui-desktop/ukui-screensaver/issues .SH "AUTHORS" .SS ukui-screensaver is maintained by: .nf Hao Lee .fi .SS This Man Page has been updated/re-written for the UKUI Desktop Environment by: Hao Lee (2018) .SH "SEE ALSO" .SS Further information may also be available at: http://wiki.ukui-desktop.org/docs .P .BR ukui-screensaver-command (1), ukui-screensaver/man/ukui-screensaver-checkpass.10000644000175000017500000000415714205074760021077 0ustar fengfeng.\" ukui-screensaver manual page .\" .\" This is free software; you may 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, .\" or (at your option) any later version. .\" .\" This 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. .\" .TH UKUI-SCREENSAVER 1 "03 May 2018" "UKUI Desktop Environment" .\" Please adjust this date whenever revising the manpage. .\" .SH "NAME" ukui-screensaver \- The UKUI Desktop Screensaver and Locker .SH "SYNOPSIS" .B ukui-screensaver [OPTIONS] .SH "DESCRIPTION" UKUI Screensaver is the default screen saver and locker for the UKUI Desktop. It is designed with simplicity and security in mind. \fBukui-screensaver\fP integrates well with the UKUI desktop, and it supports User Switching and the ability to lock down configuration settings. .SH "OPTIONS" .TP \fB\-\-display=DISPLAY\fR X display to use. .TP \fB\-\-no\-daemon\fR Don't start as a daemon .TP \fB \-\-debug\fR Enable debugging messages for \fBukui-screensaver\fP .TP \fB\-\-version\fR Output version information and exit. .TP \fB\-h, \-\-help\fR Print standard command line options. .TP \fB\-\-help\-all\fR Print all command line options. .P This program also accepts the standard GTK options. .SH "BUGS" .SS Should you encounter any bugs, they may be reported at: http://github.com/ukui-desktop/ukui-screensaver/issues .SH "AUTHORS" .SS ukui-screensaver is maintained by: .nf Hao Lee .fi .SS This Man Page has been updated/re-written for the UKUI Desktop Environment by: Hao Lee (2018) .SH "SEE ALSO" .SS Further information may also be available at: http://wiki.ukui-desktop.org/docs .P .BR ukui-screensaver-command (1), ukui-screensaver/man/ukui-screensaver-dialog.10000644000175000017500000000423514205074704020365 0ustar fengfeng.\" ukui-screensaver manual page .\" .\" This is free software; you may 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, .\" or (at your option) any later version. .\" .\" This 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 Street, Fifth Floor, Boston, MA 02110-1301 USA. .\" .TH UKUI-SCREENSAVER 1 "03 May 2018" "UKUI Desktop Environment" .\" Please adjust this date whenever revising the manpage. .\" .SH "NAME" ukui-screensaver \- The UKUI Desktop Screensaver and Locker .SH "SYNOPSIS" .B ukui-screensaver [OPTIONS] .SH "DESCRIPTION" UKUI Screensaver is the default screen saver and locker for the UKUI Desktop. It is designed with simplicity and security in mind. \fBukui-screensaver\fP integrates well with the UKUI desktop, and it supports User Switching and the ability to lock down configuration settings. .SH "OPTIONS" .TP \fB\-\-display=DISPLAY\fR X display to use. .TP \fB\-\-no\-daemon\fR Don't start as a daemon .TP \fB\-\-debug\fR Enable debugging messages for \fBukui-screensaver\fP .TP \fB\-\-version\fR Output version information and exit. .TP \fB\-h, \-\-help\fR Print standard command line options. .TP \fB\-\-help\-all\fR Print all command line options. .P This program also accepts the standard GTK options. .SH "BUGS" .SS Should you encounter any bugs, they may be reported at: http://github.com/ukui-desktop/ukui-screensaver/issues .SH "AUTHORS" .SS ukui-screensaver is maintained by: .nf Hao Lee .fi .SS This Man Page has been updated for the UKUI Desktop Environment by: Hao Lee (2018) .SH "SEE ALSO" .SS Further information may also be available at: http://wiki.ukui-desktop.org/docs .P .BR ukui-screensaver-command (1), .BR ukui-screensaver-preferences (1), .BR gtk-options (7) ukui-screensaver/src/0000755000175000017500000000000014205075527013567 5ustar fengfengukui-screensaver/src/digitalkeyboard.h0000644000175000017500000000247614205074760017105 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef DIGITALKEYBOARD_H #define DIGITALKEYBOARD_H #include #include #include class DigitalKeyBoard : public QWidget { Q_OBJECT public: explicit DigitalKeyBoard(QWidget *parent = nullptr); public Q_SLOTS: void onKeyReleaseEvent(QKeyEvent *event); Q_SIGNALS: void numbersButtonPress(int btn_id); private: void initUI(); void initConnect(); void setQSS(); private: QPushButton *m_pNumerPressBT[12]; // 0~9 是数字按键 10是删除键 11是清空键 }; #endif // DIGITALKEYBOARD_H ukui-screensaver/src/types.h0000644000175000017500000000431414205074704015102 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef TYPES_H #define TYPES_H /* https://www.narf.ssji.net/~shtrom/wiki/projets/gnomescreensavernosession */ enum SessionStatus { SESSION_AVAILABLE = 0, SESSION_INVISIBLE = 1, SESSION_BUSY = 2, SESSION_IDLE = 3 }; enum ScreenStatus { UNDEFINED = 0x00, SCREEN_SAVER = 0x01, SCREEN_LOCK = 0x02, SCREEN_LOCK_AND_SAVER = 0x03, SCREEN_BLACK = 0x04, }; #define SM_DBUS_SERVICE "org.gnome.SessionManager" #define SM_DBUS_PATH "/org/gnome/SessionManager/Presence" #define SM_DBUS_INTERFACE "org.gnome.SessionManager.Presence" #define DM_DBUS_SERVICE "org.freedesktop.DisplayManager" #define DM_DBUS_PATH "/org/freedesktop/DisplayManager" #define DM_DBUS_INTERFACE "org.freedesktop.DisplayManager" #define DM_SEAT_INTERFACE "org.freedesktop.DisplayManager.Seat" #define ACT_DBUS_SERVICE "org.freedesktop.Accounts" #define ACT_DBUS_PATH "/org/freedesktop/Accounts" #define ACT_DBUS_INTERFACE "org.freedesktop.Accounts" #define ACT_USER_INTERFACE "org.freedesktop.Accounts.User" #define DBUS_PROP_INTERFACE "org.freedesktop.DBus.Properties" #define SS_DBUS_SERVICE "org.ukui.ScreenSaver" #define SS_DBUS_PATH "/" #define SS_DBUS_INTERFACE "org.ukui.ScreenSaver" #define BIO_ERROR -1 #define BIO_FAILED 0 #define BIO_SUCCESS 1 #define BIO_IGNORE 2 #define BIOMETRIC_PAM "BIOMETRIC_PAM" #define BIOMETRIC_IGNORE "BIOMETRIC_IGNORE" #define BIOMETRIC_SUCCESS "BIOMETRIC_SUCCESS" #define BIOMETRIC_FAILED "BIOMETRIC_FAILED" #endif // TYPES_H ukui-screensaver/src/users.h0000644000175000017500000000325214205074704015077 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef USERS_H #define USERS_H #include struct UserItem { QString name; QString realName; QString icon; quint64 uid; QString path; //accounts service path friend QDebug operator<<(QDebug stream, const UserItem &user); }; class QDBusInterface; class QDBusObjectPath; class Users : public QObject { Q_OBJECT public: explicit Users(QObject *parent = nullptr); QList getUsers(); UserItem getUserByName(const QString &name); QString getDefaultIcon(); private: void loadUsers(); UserItem getUser(const QString &path); int findUserByPath(const QString &path); private Q_SLOTS: void onUserAdded(const QDBusObjectPath& path); void onUserDeleted(const QDBusObjectPath& path); Q_SIGNALS: void userAdded(const UserItem &user); void userDeleted(const UserItem &user); private: QDBusInterface *actService; QList users; QString defaultIcon; }; #endif // USERS_H ukui-screensaver/src/powermanager.h0000644000175000017500000000450514205074760016431 0ustar fengfeng /* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef POWERMANAGER_H #define POWERMANAGER_H #include #include #include #include "config.h" #ifdef USE_INTEL #define ITEM_WIDTH 128 #define ITEM_HEIGHT (ITEM_WIDTH + 40) #define ITEM_SPACING 72 class QWidget; class PowerManager:public QWidget #else #define ITEM_WIDTH 168 #define ITEM_HEIGHT ITEM_WIDTH #define ITEM_SPACING (ITEM_WIDTH/8) class QListWidget; class QListWidgetItem; class QDBusInterface; class PowerManager:public QListWidget #endif { Q_OBJECT public: PowerManager(QWidget *parent = 0); #ifdef USE_INTEL bool hibernate(); #else void showNormalSize(); void showSmallSize(); #endif private: void initUI(); #ifdef USE_INTEL void setQSS(); QWidget *list; #else QListWidget *list; QWidget *suspendWidget; QWidget *hibernateWidget; QDBusInterface *sessionInterface; QDBusInterface *loginInterface; QDBusInterface *actService; bool canSuspend; bool canHibernate; int m_count; #endif QWidget *lockWidget; QWidget *switchWidget; QWidget *logoutWidget; QWidget *rebootWidget; QWidget *shutdownWidget; QTime lasttime; private: void lockWidgetClicked(); void switchWidgetClicked(); void logoutWidgetCliced(); void rebootWidgetClicked(); void shutdownWidgetClicked(); #ifdef USE_INTEL bool reboot(); bool powerOff(); #else void suspendWidgetClicked(); void hibernateWidgetClicked(); #endif private Q_SLOTS: #ifndef USE_INTEL void powerClicked(QListWidgetItem *item); #endif Q_SIGNALS: void switchToUser(); void lock(); }; #endif // POWERMANAGER_H ukui-screensaver/src/eduplatforminterface.h0000644000175000017500000000550214205074760020143 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef EDUPLATFORMINTERFACE_H #define EDUPLATFORMINTERFACE_H #include #include #include #include "common.h" #include #include #include #include #include #include class EduPlatformInterface: public QDBusAbstractInterface { Q_OBJECT public: static inline const char* getInterfaceName() {return "cn.kylinos.SSOBackend.eduplatform";} public: EduPlatformInterface(const QString &strService,const QString &strPath,\ const QDBusConnection &connection, QObject *parent = 0); static EduPlatformInterface* getInstance(); // 得到登录二维码地址 DBusMsgCode GetLoginQRUrl(QString &url); // 绑定手机号 DBusMsgCode BindPhoneNum(const QString &username, const QString &phonenum, const QString &vcode); // 得到登录二维码 DBusMsgCode GetLoginQR(QPixmap &qrcode); // 得到验证码 DBusMsgCode GetVerifyCode(const QString &phonenum); // 设置Pin码 DBusMsgCode SetPinCode(const QString &username, const QString &pincode); // 检查手机号绑定 DBusMsgCode CheckPhoneNumBind(const QString &username, bool &isBind); // 检查Pin码设置 DBusMsgCode CheckPincodeSet(const QString &username, bool &isBind); // 验证手机号正确性 DBusMsgCode CheckUserByPhone(const QString &username, const QString &phonenum, const QString &vcode); // 通过二维码检查用户身份 DBusMsgCode CheckUserByQR(QPixmap &qrcode); // 通过二维码检查用户身份:获取二维码地址 DBusMsgCode CheckUserByQR(QString &url); // 通过url获取二维码图片数据 DBusMsgCode getQRCodeFromURL(const QString &url, QPixmap &qrcode); // 获取用户登录状态 DBusMsgCode CheckToken(const QString &username); private: void initConnect(); QPixmap beautifyQRCode(QPixmap &); static EduPlatformInterface *m_instance; Q_SIGNALS: void QRStatusChange(QString,QString,int); private: }; #endif // EDUPLATFORMINTERFACE_H ukui-screensaver/src/wechatauthdialog.h0000644000175000017500000000573514205074704017263 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * Authors: ZHAI Kang-ning **/ #ifndef WECHATAUTHDIALOG_H #define WECHATAUTHDIALOG_H #include #include #include #include #include #include #include "networkwatcher.h" class QRLabel; class RequestQRThread; /** * @brief The WeChatAuthDialog class * 微信登录、校验界面 * 一、标题状态改变: * 成功 事例: 1、微信登录->扫描成功->正在登录··· * 微信不相符: 2、微信登录->登录失败 */ class WeChatAuthDialog : public QWidget { Q_OBJECT public: explicit WeChatAuthDialog(QWidget *parent = nullptr); explicit WeChatAuthDialog(int type, QWidget *parent = nullptr); enum authType{ login = 0, check, }; void reloadQR(); void showErrorMessage(QString message, bool isLong = false); // void updateStatus(int status); void onReset(); protected: void closeEvent(QCloseEvent *event) override; void hideEvent(QHideEvent *event) override; void showEvent(QShowEvent *event) override; Q_SIGNALS: void authenticateCompete(bool result); void qRStatusChange(QString loginname, QString loginpwd, int curstatus); private: void initUI(); void initConnect(); int m_authType = 0; QNetworkAccessManager *m_networkManager; QRLabel *m_loginQR; QLabel *m_title; //标题 QLabel *m_guide; //提示 QLabel *m_errorMsg; //错误信息 RequestQRThread *m_requestQRThread = nullptr; bool m_isThreadWorking = false; NetWorkWatcher *m_networkWatcher; QTimer *m_timer; void getLoginQR(); private Q_SLOTS: void replyFinished(QNetworkReply *); void qRStatusChangeSolt(QString loginname, QString loginpwd, int curstatus); void onQRUrlReady(int errorCode, const QString url); void onNetworkStateChanged(uint state); }; class QRLabel : public QLabel { Q_OBJECT public: explicit QRLabel(QWidget *parent = nullptr); Q_SIGNALS: void clicked(); protected: void mousePressEvent(QMouseEvent *event) override; }; class RequestQRThread : public QThread { Q_OBJECT public: RequestQRThread(QObject *parent); protected: void run() override; Q_SIGNALS: void resultReady(int errorCode, const QString url); }; #endif // WECHATAUTHDIALOG_H ukui-screensaver/src/digitalauthdialog.h0000644000175000017500000001211214205074704017410 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * Authors: ZHAI Kang-ning **/ #ifndef DIGITALAUTHDIALOG_H #define DIGITALAUTHDIALOG_H #include #include #include #include #include #include #include "auth.h" #include "digitalkeyboard.h" #include class Auth; class MyLabel; class DigitalAuthDialog : public QWidget { Q_OBJECT public: struct PosInCircle { int i; //行 int j; //列 bool isIn; //是否在范围内 }; enum LoginType{ AUTHENTICATE = 0, RESET, SECONDCONFIRMATION, }; explicit DigitalAuthDialog(QWidget *parent = nullptr); ~DigitalAuthDialog(); void setPassword(const QString password); QString getPassword(); bool checkPassword(); void reset(); void showResetPasswordPage(); int getStatus(); void showErrorMessage(QString message); // void RecieveKey(int key); protected: void paintEvent(QPaintEvent *event) override; void mouseMoveEvent(QMouseEvent *event) override; void mousePressEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void keyPressEvent(QKeyEvent *event) override; void closeEvent(QCloseEvent *evert) override; void drawBg(QPainter *painter); void drawOutCircle(QPainter *painter); void drawFilledCircle(QPainter *painter); void drawTipLine(QPainter *painter); void drawInCircle(QPainter *painter); void drawJoinLine(QPainter *painter); void drawStatusCircle(QPainter *painter); void drawHoverCircle(QPainter *painter); private: /** * 圆形按钮,测量距离中心的距离 * @brief distance * @param x1 * @param y1 * @param x2 圆心x坐标 * @param y2 圆心y坐标 * @return */ double distance(int x1, int y1, int x2, int y2); bool isInButtonArea(int x1, int y1, int x2, int y2); int posToNumber(int i, int j); // void onShowMessage(const QString &message); void cleanMessage(); void startWaiting(); void stopWaiting(); Q_SIGNALS: void correctPassword(bool isCorrect, QString password); void authenticateCompete(bool result); void requestPasswordReset(); void setPinCode(QString pinCode); void switchToReset(bool isReset); private Q_SLOTS: void onShowMessage(const QString &message, Auth::MessageType type); void onShowPrompt(const QString &prompt, Auth::PromptType type); void onAuthComplete(); public Q_SLOTS: void startAuth(); void stopAuth(); void onNumerPress(int btn_id); private: QColor m_bgColor; //背景色 QColor m_outCircleColor; //外圆颜色 QColor m_tipLineColor; //提示线颜色 QColor m_circleRingColor; //圆环颜色 QColor m_circleColor; //实心圆颜色 int m_margin; //外边距 int m_radius; //圆相对半径 int m_buttonRadius; //按钮圆角半径 int m_buttonWidth; //按钮宽度 int m_buttonHeight; //按钮高度 int m_buttonStep; //按钮间距 PosInCircle m_posInCircle; //判断点是否在圆内 bool m_pressed; //鼠标按下 bool m_showText; //是否显示文字 QVector m_vecInputPoints; //鼠标移动选点 QPoint m_followPoint; //鼠标跟随点 QString m_password; //原密码 QString m_inputPassword; //鼠标移动选点转换为密码 //label QLabel *m_title; MyLabel *m_labelReset; //密码状态更新布局 int m_statusRadius; //认证中? bool m_isAuthing; //数字键盘 DigitalKeyBoard *m_digitalKeyBoard; /** * 二次认证相关成员变量 */ int m_loginType = LoginType::AUTHENTICATE; QString m_resetPassword; QLabel *m_resetOrAuthFailure; QLabel *m_authMessage; //pam auth Auth *m_auth; // QTimer *m_timer; }; class MyLabel : public QLabel{ Q_OBJECT public: MyLabel(const QString & text, QWidget *parent); MyLabel(QWidget *parent); Q_SIGNALS: void onClick(); protected: void mouseReleaseEvent(QMouseEvent *event) override; void mousePressEvent(QMouseEvent *event) override; }; #endif // DIGITALAUTHDIALOG_H ukui-screensaver/src/ukui-screensaver-checkpass.cpp0000644000175000017500000001053514205074760021532 0ustar fengfeng/** * Copyright (C) 2018 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, 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 #include #include #include #include #include #include #include #include static int toParent = 0; static int fromChild = 0; typedef struct pam_message PAM_MESSAGE; typedef struct pam_response PAM_RESPONSE; static void writeData(int fd, const void *buf, ssize_t count) { if(write(fd, buf, count) != count) printf("write to parent failed: %s\n",strerror(errno)); } static void writeString(int fd, const char *data) { int length = data ? strlen(data) : -1; writeData(fd, &length, sizeof(length)); if(data) writeData(fd, data, sizeof(char) * length); } static int readData(int fd, void *buf, size_t count) { ssize_t nRead = read(fd, buf, count); if(nRead < 0) printf("read data failed: %s\n",strerror(errno)); return nRead; } static char * readString(int fd) { int length; if(readData(fd, &length, sizeof(length)) <= 0) return NULL; if(length <= 0) length = 0; char *value = (char *)malloc(sizeof(char) * (length + 1)); readData(fd, value, length); value[length] = '\0'; return value; } static int pam_conversation(int msgLength, const struct pam_message **msg, PAM_RESPONSE **resp, void */*appData*/) { PAM_RESPONSE *response = (PAM_RESPONSE*)calloc(msgLength,sizeof(PAM_RESPONSE)); int authComplete = 0; writeData(toParent, (const void*)&authComplete, sizeof(authComplete)); writeData(toParent, (const void*)&msgLength, sizeof(msgLength)); //发送pam消息 for(int i = 0; i < msgLength; i++) { const struct pam_message *m = msg[i]; writeData(toParent, (const void *)&m->msg_style, sizeof(m->msg_style)); writeString(toParent, m->msg); } //读取响应 for(int i = 0; i < msgLength; i++) { PAM_RESPONSE *r = &response[i]; readData(fromChild, &r->resp_retcode, sizeof(r->resp_retcode)); r->resp = readString(fromChild); } *resp = response; return PAM_SUCCESS; } static void _authenticate(const char *userName) { printf("authenticate %s\n",userName); pam_handle_t *pamh = NULL; char *newUser; int ret; int authRet; struct pam_conv conv; conv.conv = pam_conversation; conv.appdata_ptr = NULL; ret = pam_start("ukui-screensaver-qt", userName, &conv, &pamh); if(ret != PAM_SUCCESS) { printf("failed to start PAM: = %s\n", pam_strerror(NULL, ret)); } authRet = pam_authenticate(pamh, 0); ret = pam_get_item(pamh, PAM_USER, (const void **)&newUser); if(ret != PAM_SUCCESS) { pam_end(pamh, 0); printf("failed to get username\n"); } if(authRet == PAM_SUCCESS) ret = pam_acct_mgmt(pamh, 0); if(ret != PAM_SUCCESS) { } free(newUser); fprintf(stderr, "authentication result: %d\n", authRet); // 发送认证结果 int authComplete = 1; writeData(toParent, (const void*)&authComplete, sizeof(authComplete)); writeData(toParent, (const void *)&authRet, sizeof(authRet)); printf("--- 认证完成\n"); _exit(EXIT_SUCCESS); } int main(int argc, char **argv) { if (argc != 4) { return EXIT_FAILURE; } toParent = atoi (argv[1]); fromChild = atoi (argv[2]); if (toParent == 0 || fromChild == 0) { printf ("Invalid file descriptors %s %s\n", argv[2], argv[3]); return EXIT_FAILURE; } mlockall (MCL_CURRENT | MCL_FUTURE); fcntl (toParent, F_SETFD, FD_CLOEXEC); fcntl (fromChild, F_SETFD, FD_CLOEXEC); _authenticate(argv[3]); } ukui-screensaver/src/generalauthwidget.h0000644000175000017500000000171214205074704017440 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef GENERALAUTHWIDGET_H #define GENERALAUTHWIDGET_H #include class GeneralAuthWidget : public QWidget { Q_OBJECT public: explicit GeneralAuthWidget(QWidget *parent = nullptr); signals: public slots: }; #endif // GENERALAUTHWIDGET_Hukui-screensaver/src/fullbackgroundwidget.cpp0000644000175000017500000007365714205074760020521 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "fullbackgroundwidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "lockwidget.h" #include "xeventmonitor.h" #include "monitorwatcher.h" #include "configuration.h" #include "screensaver.h" #include "screensaverwidget.h" #include "grab-x11.h" #include "tabletlockwidget.h" // 实现键盘f1 - f2 的功能键 #include "PhysicalDeviceSet/sounddeviceset.h" #include "PhysicalDeviceSet/brightnessdeviceset.h" #include "config.h" enum { SWITCH_TO_LINUX = 0, SWITCH_TO_ANDROID = 1, BACK_TO_DESKTOP = 2, TEST_CONNECTION = 3, }; QT_BEGIN_NAMESPACE extern void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0); QT_END_NAMESPACE #define BLUR_RADIUS 300 QPixmap scaledPixmap(int width, int height, QString url) { QFile imgFile(url); if(!imgFile.exists()){ qDebug()<< "not find the pixmap file"; return QPixmap(); } QImage image(url); QPixmap pixmap = QPixmap::fromImage(image); if(pixmap.isNull()) { qDebug() << "pixmap is null"; QProcess exec; QString program("file " + url); exec.start(program); exec.waitForFinished(1000); QString output = exec.readAllStandardOutput(); qDebug() << output; if(output.contains("SVG")){ qDebug() << "image format is SVG"; QSvgRenderer render(url); QImage image(width, height, QImage::Format_ARGB32); image.fill(Qt::transparent); QPainter painter(&image); render.render(&painter, image.rect()); pixmap.convertFromImage(image); } else if(output.contains("TIFF")) { qDebug() << "image format is TIFF"; } } return pixmap.scaled(width, height, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); } int connect_to_switch(const char* path) { int ret; int connect_fd; struct sockaddr_un srv_addr; connect_fd = socket(PF_UNIX,SOCK_STREAM,0); if(connect_fd < 0) { return -1; } srv_addr.sun_family=AF_UNIX; strcpy(srv_addr.sun_path, path); ret = connect(connect_fd, (struct sockaddr*)&srv_addr, sizeof(srv_addr)); if(ret < 0) { perror("cannot connect to the server"); close(connect_fd); return -1; } return connect_fd; } int switch_to_linux(const char* container) { int connect_fd; int32_t switch_to = BACK_TO_DESKTOP; char path[1024] = {0}; sprintf(path, "/var/lib/kydroid/%s/sockets/%s", container, "desktop-switch"); printf("path = %s\n",path); connect_fd = connect_to_switch(path); if(connect_fd < 0) return -1; write(connect_fd, &switch_to, sizeof(switch_to)); close(connect_fd); return 0; } void x11_get_screen_size(int *width,int *height) { Display* display; display = XOpenDisplay(NULL); if (display == NULL) { fprintf(stderr, "Cannot connect to X server %s/n", "simey:0"); exit (-1); } int screen_num; screen_num = DefaultScreen(display); *width = DisplayWidth(display, screen_num); *height = DisplayHeight(display, screen_num); XCloseDisplay(display); } QPixmap blurPixmap(QPixmap pixmap) { QPainter painter(&pixmap); QImage srcImg = pixmap.toImage(); qt_blurImage(&painter, srcImg, BLUR_RADIUS, false, false); painter.end(); return pixmap; } FullBackgroundWidget::FullBackgroundWidget(QWidget *parent) : QWidget(parent), lockWidget(nullptr), xEventMonitor(new XEventMonitor(this)), monitorWatcher(new MonitorWatcher(this)), configuration(Configuration::instance()), isLocked(false), isPassed(false), lockState(false), screenStatus(UNDEFINED), isBlank(false), m_delay(false) { qDebug() << "init - screenStatus: " << screenStatus; setMouseTracking(true); connect(monitorWatcher, &MonitorWatcher::monitorCountChanged, this, &FullBackgroundWidget::onScreenCountChanged); QDesktopWidget *desktop = QApplication::desktop(); connect(desktop, &QDesktopWidget::resized, this, &FullBackgroundWidget::onDesktopResized); connect(desktop, &QDesktopWidget::workAreaResized, this, &FullBackgroundWidget::onDesktopResized); connect(desktop, &QDesktopWidget::primaryScreenChanged, this, &FullBackgroundWidget::onDesktopResized); connect(desktop, &QDesktopWidget::screenCountChanged, this, &FullBackgroundWidget::onDesktopResized); QDBusInterface *iface = new QDBusInterface("org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", QDBusConnection::systemBus(), this); connect(iface, SIGNAL(PrepareForSleep(bool)), this, SLOT(onPrepareForSleep(bool))); #ifdef USE_INTEL QDBusConnection::systemBus().connect("org.freedesktop.UPower", "/org/freedesktop/UPower", "org.freedesktop.DBus.Properties", "PropertiesChanged", this, SLOT(propertiesChangedSlot(QString, QMap, QStringList))); #endif init(); qApp->installNativeEventFilter(this); installEventFilter(this); QTimer::singleShot(500,this,SLOT(switchToLinux())); LogindIntegration *m_logind = new LogindIntegration(this); connect(m_logind, &LogindIntegration::requestUnlock, this, [this]() { closeScreensaver(); }); } #ifdef USE_INTEL void FullBackgroundWidget::propertiesChangedSlot(QString property, QMap propertyMap, QStringList propertyList) { Q_UNUSED(property); Q_UNUSED(propertyList); if (propertyMap.keys().contains("LidIsClosed")) { qDebug() <<"LidIsClosed" << propertyMap.value("LidIsClosed").toBool(); // if(!(propertyMap.value("LidIsClosed").toBool())) // { // m_isSuspend = true; // } } } #endif void FullBackgroundWidget::switchToLinux() { struct passwd *pwd; pwd = getpwuid(getuid()); char *username = pwd->pw_name; int uid = pwd->pw_uid; char container[100]= {0}; sprintf(container,"kydroid2-%d-%s",uid,username); switch_to_linux(container); } void FullBackgroundWidget::laterActivate() { activateWindow(); raise(); setFocus(); if(lockWidget && lockWidget->isVisible()) lockWidget->setFocus(); } void FullBackgroundWidget::setLockState() { if(lockState == true) return ; lockState = true; QDBusInterface *interface = new QDBusInterface(SS_DBUS_SERVICE, SS_DBUS_PATH, SS_DBUS_INTERFACE); QDBusMessage msg = interface->call("SetLockState"); if(msg.type() == QDBusMessage::ErrorMessage) qDebug() << msg.errorMessage(); } bool FullBackgroundWidget::eventFilter(QObject *obj, QEvent *event) { if(event->type() == QEvent::WindowDeactivate){ QTimer::singleShot(50,this,SLOT(laterActivate())); }else if(event->type() == QEvent::WindowActivate){ QTimer::singleShot(500,this,SLOT(setLockState())); } return false; } void FullBackgroundWidget::setIsStartup(bool val) { isStartup = val; } void FullBackgroundWidget::paintEvent(QPaintEvent *event) { for(auto screen : QGuiApplication::screens()) { QPainter painter(this); if(background.isNull()){ QColor cor = "#035290"; painter.setBrush(cor); painter.drawRect(screen->geometry()); } else{ painter.drawPixmap(screen->geometry(), background); } } return QWidget::paintEvent(event); } void FullBackgroundWidget::closeEvent(QCloseEvent *event) { qDebug() << "FullBackgroundWidget::closeEvent"; #ifdef USE_INTEL //蓝牙连接后 唤醒信号会有延迟 以防退出时未收到信号导致kwin compositor未resume QDBusInterface *interface = new QDBusInterface("org.ukui.KWin", "/Compositor", "org.ukui.kwin.Compositing", QDBusConnection::sessionBus(), this); if (!interface->isValid()){ syslog(LOG_DEBUG, "interface error"); return; } QDBusMessage msg = interface->call("resume"); syslog(LOG_DEBUG, "after close resume kwin "); #endif for(auto obj: children()) { QWidget *widget = dynamic_cast(obj); if(widget) widget->close(); } closeGrab(); if(isStartup){ QProcess process; process.start("killall screensaver-focus-helper"); process.waitForFinished(1000); } return QWidget::closeEvent(event); } void FullBackgroundWidget::showEvent(QShowEvent *event) { // XSetWindowAttributes top_attrs; // top_attrs.override_redirect = False; // XChangeWindowAttributes(QX11Info::display(), this->winId(), CWOverrideRedirect, &top_attrs); // XRaiseWindow(QX11Info::display(), this->winId()); // raise(); return QWidget::showEvent(event); } bool FullBackgroundWidget::nativeEventFilter(const QByteArray &eventType, void *message, long *result) { if (qstrcmp(eventType, "xcb_generic_event_t") != 0) { return false; } xcb_generic_event_t *event = reinterpret_cast(message); const uint8_t responseType = event->response_type & ~0x80; if (responseType == XCB_CONFIGURE_NOTIFY) { xcb_configure_notify_event_t *xc = reinterpret_cast(event); if(xc->window == winId()) return false; XWindowAttributes window_attributes; XGetWindowAttributes (QX11Info::display(), xc->window,&window_attributes); XClassHint ch; ch.res_name = NULL; ch.res_class = NULL; XGetClassHint (QX11Info::display(), xc->window, &ch); if(QString(ch.res_name) == "ukui-screensaver-dialog") return false; laterActivate(); }else if(responseType == XCB_MAP_NOTIFY){ xcb_map_notify_event_t *xm = reinterpret_cast(event); if(xm->window == winId()) return false; XWindowAttributes window_attributes; XGetWindowAttributes (QX11Info::display(), xm->window,&window_attributes); XClassHint ch; ch.res_name = NULL; ch.res_class = NULL; XGetClassHint (QX11Info::display(), xm->window, &ch); if(QString(ch.res_name) == "ukui-screensaver-dialog") return false; laterActivate(); } return false; } void FullBackgroundWidget::mouseMoveEvent(QMouseEvent *e) { onCursorMoved(QCursor::pos()); return QWidget::mouseMoveEvent(e); } void FullBackgroundWidget::mousePressEvent(QMouseEvent *e) { #ifdef USE_INTEL if(screenStatus == SCREEN_LOCK_AND_SAVER) { ScreenSaver *saver = configuration->getScreensaver(); if(saver->path == "/usr/lib/ukui-screensaver/ukui-screensaver-default") return ; clearScreensavers(); } #endif } void FullBackgroundWidget::init() { setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint); XWindowAttributes rootAttr; XGetWindowAttributes(QX11Info::display(), QX11Info::appRootWindow(), &rootAttr); XSelectInput( QX11Info::display(), QX11Info::appRootWindow(), SubstructureNotifyMask|rootAttr.your_event_mask ); // setAttribute(Qt::WA_DeleteOnClose); /*捕获键盘,如果捕获失败,则可能是由于弹出菜单项已经捕获,那么模拟一次esc按键来退出菜单,如果仍捕获失败,则放弃锁屏,避免密码无法输入*/ if(establishGrab()) qDebug()<<"establishGrab : true"; else { qDebug()<<"establishGrab : false"; XTestFakeKeyEvent(QX11Info::display(), XKeysymToKeycode(QX11Info::display(),XK_Escape), True, 1); XTestFakeKeyEvent(QX11Info::display(), XKeysymToKeycode(QX11Info::display(),XK_Escape), False, 1); XFlush(QX11Info::display()); sleep(1); if(!establishGrab()) { exit(1); } } // 监听session信号 smInterface = new QDBusInterface(SM_DBUS_SERVICE, SM_DBUS_PATH, SM_DBUS_INTERFACE, QDBusConnection::sessionBus()); connect(smInterface, SIGNAL(StatusChanged(uint)), this, SLOT(onSessionStatusChanged(uint))); connect(xEventMonitor, SIGNAL(keyPress(const QString &)), this, SLOT(onGlobalKeyPress(const QString &))); connect(xEventMonitor, SIGNAL(keyRelease(const QString &)), this, SLOT(onGlobalKeyRelease(const QString &))); connect(xEventMonitor, SIGNAL(buttonDrag(int, int)), this, SLOT(onGlobalButtonDrag(int, int))); connect(xEventMonitor, SIGNAL(buttonPress(int, int)), this, SLOT(onGlobalButtonPressed(int, int))); // int totalWidth = 0; // int totalHeight = 0; // for(auto screen : QGuiApplication::screens()) // { // totalWidth += screen->geometry().width(); // totalHeight += screen->geometry().height(); // } // setGeometry(0, 0, totalWidth, totalHeight); QDesktopWidget *desktop = QApplication::desktop(); setGeometry(desktop->geometry()); QImageReader reader; reader.setFileName(configuration->getBackground()); reader.setAutoTransform(true); reader.setScaledSize(QApplication::primaryScreen()->size()); background = QPixmap::fromImageReader(&reader); // background.load(configuration->getBackground()); // background = scaledPixmap(QApplication::primaryScreen()->geometry().width(), QApplication::primaryScreen()->geometry().height(), configuration->getBackground()); if(!background.isNull()){ background = blurPixmap(background); } xEventMonitor->start(); #ifdef USE_INTEL SoundDeviceSet::instance(); #endif } void FullBackgroundWidget::onCursorMoved(const QPoint &pos) { if(!lockWidget) { return; } for(auto screen : QGuiApplication::screens()) { #ifdef USE_INTEL if(screen == qApp->primaryScreen()){ lockWidget->setGeometry(screen->geometry()); break; } #else if(screen->geometry().contains(pos)) { if(lockWidget->geometry() == screen->geometry()) return ; /*避免切换时闪烁*/ qDebug()<geometry()<geometry(); lockWidget->hide(); lockWidget->setGeometry(screen->geometry()); lockWidget->show(); break; } #endif } } void FullBackgroundWidget::lock() { showLockWidget(); if(lockWidget){ lockWidget->show(); lockWidget->startAuth(); } #ifndef USE_INTEL inhibit(); #endif } void FullBackgroundWidget::showLockWidget() { #ifdef USE_INTEL screenStatus = /*(ScreenStatus)(screenStatus | SCREEN_LOCK)*/SCREEN_LOCK; #else screenStatus = (ScreenStatus)(screenStatus | SCREEN_LOCK); #endif qDebug() << "showLockWidget - screenStatus: " << screenStatus; if(!lockWidget) { #ifdef USE_INTEL lockWidget = new TabletLockWidget(this); connect(lockWidget, &TabletLockWidget::closed, this, &FullBackgroundWidget::close); connect(lockWidget, &TabletLockWidget::screenSaver, this, [=] { showScreensaver(); }); connect(lockWidget, &TabletLockWidget::blackSaver, this, [=] { onShowBlackBackGround(); }); #else lockWidget = new LockWidget(this); connect(lockWidget, &LockWidget::closed, this, &FullBackgroundWidget::close); #endif } onCursorMoved(QCursor::pos()); lockWidget->setFocus(); XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); activateWindow(); repaint(); } void FullBackgroundWidget::showScreensaver() { #ifdef USE_INTEL screenStatus = /*(ScreenStatus)(screenStatus | SCREEN_SAVER)*/SCREEN_LOCK_AND_SAVER; #else screenStatus = (ScreenStatus)(screenStatus | SCREEN_SAVER); #endif qDebug() << "showScreensaver - screenStatus: " << screenStatus; for(auto screen : QGuiApplication::screens()) { ScreenSaver *saver = configuration->getScreensaver(); ScreenSaverWidget *saverWidget = new ScreenSaverWidget(saver, this); qDebug() << " new ScreenSaverWidget"; widgetXScreensaverList.push_back(saverWidget); //深色模式有一像素的白边,所以主屏幕向左,向右移一个像素点;这种操作后,外显上方仍旧会有一个像素的白边,暂时不对外显做偏移处理 if(screen == qApp->primaryScreen()) { saverWidget->setGeometry(screen->geometry().x()-1, screen->geometry().y()-1, screen->geometry().width()+1, screen->geometry().height()+1); } else { saverWidget->setGeometry(screen->geometry()); } } setCursor(Qt::BlankCursor); //显示屏保时,停止认证(主要针对生物识别) if(lockWidget) { lockWidget->stopAuth(); lockWidget->hide(); } } void FullBackgroundWidget::clearScreensavers() { #ifdef USE_INTEL screenStatus = /*(ScreenStatus)(screenStatus & ~SCREEN_SAVER)*/SCREEN_LOCK; #else screenStatus = (ScreenStatus)(screenStatus & ~SCREEN_SAVER); #endif for(auto widget : widgetXScreensaverList) { widget->close(); } widgetXScreensaverList.clear(); qDebug() << "clearScreensavers - screenStatus: " << screenStatus; unsetCursor(); if(screenStatus == UNDEFINED) { close(); } else { lock(); } } int FullBackgroundWidget::onSessionStatusChanged(uint status) { qDebug() << "session status changed: " << status; if(status != SESSION_IDLE) { //当前session没有处于空闲状态 return -1; } qDebug() << "onSessionStatusChanged - screenStatus: " << screenStatus; if(!configuration->xscreensaverActivatedWhenIdle()) { return -1; } #ifdef USE_INTEL if(screenStatus == SCREEN_LOCK_AND_SAVER) #else if(screenStatus & SCREEN_SAVER) #endif { return -1; } #ifdef USE_INTEL else if(screenStatus == SCREEN_LOCK) #else else if(screenStatus & SCREEN_LOCK) #endif { showScreensaver(); } else if(screenStatus == UNDEFINED) { #ifdef USE_INTEL //显示锁屏和屏保 showLockWidget(); showScreensaver(); #else if(configuration->xscreensaverActivatedWhenIdle() && configuration->lockWhenXScreensaverActivated()) { //显示锁屏和屏保 showLockWidget(); showScreensaver(); } else if(configuration->xscreensaverActivatedWhenIdle()) { //只显示屏保 showScreensaver(); } #endif } return 0; } void FullBackgroundWidget::onBlankScreensaver() { showLockWidget(); screenStatus = (ScreenStatus)(screenStatus | SCREEN_SAVER | SCREEN_LOCK); qDebug() << "showScreensaver - screenStatus: " << screenStatus; for(auto screen : QGuiApplication::screens()) { ScreenSaver *saver = configuration->getScreensaver(); saver->mode = SaverMode(SAVER_BLANK_ONLY); ScreenSaverWidget *saverWidget = new ScreenSaverWidget(saver, this); widgetXScreensaverList.push_back(saverWidget); saverWidget->setGeometry(screen->geometry()); } setCursor(Qt::BlankCursor); isBlank = true; } void FullBackgroundWidget::onScreensaver() { showLockWidget(); showScreensaver(); } void FullBackgroundWidget::onGlobalKeyPress(const QString &key) { #ifdef USE_INTEL qDebug() << "onGlobalKeyPress " << key << "screenStatus " << screenStatus; if(m_delay) { qDebug() << "it is delay time ,ignore"; return; } if(!key.isEmpty() && (screenStatus == SCREEN_LOCK_AND_SAVER)) { clearScreensavers(); }/*else{ lockWidget->startAuth(); inhibit(); }*/ // if(screenStatus == SCREEN_LOCK) // { // checkNumLock(); // int keyValue = numberMatch(key);; // if (keyValue >= 0 && keyValue <= 10 ) // { // lockWidget->RecieveKey(keyValue); // } // } #endif } void FullBackgroundWidget::onGlobalKeyRelease(const QString &key) { if(key == "Caps_Lock") { lockWidget->capsLockChanged(); } #ifdef USE_INTEL // 声音、亮度等调整 // 取消声音快捷键设置,由settings-deamon控制 有一个bug,音量为零时再按静音键,静音指示灯会熄灭,可解决,但是不用锁屏做了 // if(key == "XF86AudioRaiseVolume") // { // SoundDeviceSet::instance()->setValue(SoundDeviceSet::instance()->getValue() + 5); // } // else if(key == "XF86AudioLowerVolume") // { // SoundDeviceSet::instance()->setValue(SoundDeviceSet::instance()->getValue() - 5); // } // else if(key == "XF86AudioMute") // { // SoundDeviceSet::instance()->setMute(!(SoundDeviceSet::instance()->getIsMute())); // } // else if (key == "XF86MonBrightnessUp") // 亮度调整 { //qDebug() << "up"; BrightnessDeviceSet* pBrightness = BrightnessDeviceSet::instance(); pBrightness->setValue(pBrightness->getValue() + 5); } else if (key == "XF86MonBrightnessDown") { //qDebug() << "down"; BrightnessDeviceSet* pBrightness = BrightnessDeviceSet::instance(); pBrightness->setValue(pBrightness->getValue() - 5); } else if (key == "XF86RFKill") // 飞行模式 { // 键盘上的飞行模式实体键 生效,不需要在登录界面进行设置 } else if (key == "") // num_lock { // 键盘上的num_lock生效、不需要登录界面进行管理 } #else if(key == "Escape" && screenStatus == SCREEN_LOCK) { showScreensaver(); } else if(screenStatus & SCREEN_SAVER && !isBlank) { clearScreensavers(); } #endif } void FullBackgroundWidget::onGlobalButtonDrag(int xPos, int yPos) { #ifdef USE_INTEL if(screenStatus == SCREEN_LOCK_AND_SAVER) { ScreenSaver *saver = configuration->getScreensaver(); if(saver->path == "/usr/lib/ukui-screensaver/ukui-screensaver-default") return ; clearScreensavers(); } #else if(screenStatus & SCREEN_SAVER && !isBlank) { ScreenSaver *saver = configuration->getScreensaver(); if(isPassed || saver->path != "/usr/lib/ukui-screensaver/ukui-screensaver-default"){ clearScreensavers(); } isPassed = true; } #endif } void FullBackgroundWidget::onGlobalButtonPressed(int xPos, int yPos) { #ifndef USE_INTEL if(screenStatus & SCREEN_SAVER) { clearScreensavers(); } #endif } void FullBackgroundWidget::closeScreensaver() { if(screenStatus & SCREEN_SAVER){ clearScreensavers(); } if(screenStatus & SCREEN_LOCK){ if(lockWidget){ lockWidget->stopAuth(); lockWidget->close(); } } close(); } void FullBackgroundWidget::onScreenCountChanged(int) { #ifdef USE_INTEL QSize newSize = monitorWatcher->getVirtualSize(); setGeometry(0, 0, newSize.width(), newSize.height()); //repaint(); update(); clearScreensavers(); #else QDesktopWidget *desktop = QApplication::desktop(); setGeometry(desktop->geometry()); //repaint(); if(screenStatus & SCREEN_SAVER) { clearScreensavers(); } update(); #endif } void FullBackgroundWidget::onDesktopResized() { #ifdef USE_INTEL qDebug() << "[FullBackgroundWidget] [onDesktopResized]"; QDesktopWidget *desktop = QApplication::desktop(); if(NULL == desktop) { qWarning() << " get desktop size failed"; return; } setGeometry(desktop->geometry()); if(lockWidget) onCursorMoved(cursor().pos()); // clearScreensavers(); //repaint(); update(); if(screenStatus == SCREEN_LOCK_AND_SAVER) { clearScreensavers(); showScreensaver(); } #else QDesktopWidget *desktop = QApplication::desktop(); setGeometry(desktop->geometry()); if(lockWidget) onCursorMoved(QCursor::pos()); if(screenStatus & SCREEN_SAVER) { clearScreensavers(); } //repaint(); update(); #endif } void FullBackgroundWidget::laterInhibit(bool val) { if(val){ inhibit(); }else{ uninhibit(); } } void FullBackgroundWidget::laterStartAuth() { lockWidget->startAuth(); inhibit(); } void FullBackgroundWidget::onPrepareForSleep(bool sleep) { ///系统休眠时,会关闭总线,导致设备不可用,发生错误 ///在系统休眠之前停止认证,在系统唤醒后重新开始认证 if(sleep) { lockWidget->stopAuth(); uninhibit(); } else { if(screenStatus & SCREEN_SAVER) { isBlank = false; clearScreensavers(); }else{ lockWidget->startAuth(); inhibit(); } } } void FullBackgroundWidget::inhibit() { if (m_inhibitFileDescriptor.isValid()) { return; } QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", QStringLiteral("Inhibit")); message.setArguments(QVariantList({QStringLiteral("sleep"), "Screen Locker", "Ensuring that the screen gets locked before going to sleep", QStringLiteral("delay")})); QDBusPendingReply reply = QDBusConnection::systemBus().call(message); if (!reply.isValid()) { return; } reply.value().swap(m_inhibitFileDescriptor); } void FullBackgroundWidget::uninhibit() { if (!m_inhibitFileDescriptor.isValid()) { return; } m_inhibitFileDescriptor = QDBusUnixFileDescriptor(); } /** * @brief FullBackgroundWidget::getPaddingPixmap * @param pixmap 需要填充的图像 * @param width 容器宽度 * @param height 容器高度 * @return */ QPixmap FullBackgroundWidget::getPaddingPixmap(QPixmap pixmap, int width, int height) { if (pixmap.isNull() || pixmap.width() == 0 || pixmap.height() == 0) { return QPixmap(); } bool useHeight; float scaled = 0.0; QPixmap scaledPixmap; QPixmap paddingPixmap; qint64 rw = qint64(height) * qint64(pixmap.width()) / qint64(pixmap.height()); useHeight = (rw >= width); if (useHeight) { scaled = float(height) / float(pixmap.height()); scaledPixmap = pixmap.scaled(pixmap.width() * scaled, height); paddingPixmap = scaledPixmap.copy((pixmap.width() * scaled - width) / 2 , 0, width, height); } else { scaled = float(width) / float(pixmap.width()); scaledPixmap = pixmap.scaled(width, pixmap.height() * scaled); paddingPixmap = scaledPixmap.copy(0 , (pixmap.height() * scaled - height) / 2,width, height); } return paddingPixmap; } #ifdef USE_INTEL void FullBackgroundWidget::onShowBlackBackGround() { screenStatus = SCREEN_BLACK; qDebug() << "showBlackBackGround - screenStatus: " << screenStatus; for(auto screen : QGuiApplication::screens()) { // BlackWidget *blackWidget = new BlackWidget(this); // qDebug() << " new BlackWidget"; // widgetBlackList.push_back(blackWidget); ScreenSaver *saver = configuration->getScreensaver(); saver->mode = SaverMode(SAVER_BLANK_ONLY); ScreenSaverWidget *saverWidget = new ScreenSaverWidget(saver, this); widgetBlackList.push_back(saverWidget); saverWidget->setGeometry(screen->geometry()); //深色模式有一像素的白边,所以主屏幕向左,向右移一个像素点;这种操作后,外显上方仍旧会有一个像素的白边,暂时不对外显做偏移处理 if(screen == qApp->primaryScreen()) { saverWidget->setGeometry(screen->geometry().x()-1, screen->geometry().y()-1, screen->geometry().width()+1, screen->geometry().height()+1); } else { saverWidget->setGeometry(screen->geometry()); } } setCursor(Qt::BlankCursor); } #endif ukui-screensaver/src/image.qrc0000644000175000017500000000026714205074704015361 0ustar fengfeng image/hide-password.png image/show-password.png image/warn.png ukui-screensaver/src/accountsinterface.h0000644000175000017500000000356514205074760017447 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef ACCOUNTSINTERFACE_H #define ACCOUNTSINTERFACE_H #include #include #include #include #include #include #include #include #include #include "common.h" class AccountsInterface: public QDBusAbstractInterface { Q_OBJECT public: static inline const char* getInterfaceName() {return "cn.kylinos.SSOBackend.accounts";} public: static AccountsInterface* getInstance(); AccountsInterface(const QString &strService,const QString &strPath,\ const QDBusConnection &connection, QObject *parent = 0); DBusMsgCode SetAccountPincode(const QString &username, const QString &pincode); DBusMsgCode GetAccountPincode(const QString &username, QString &pincode); // 检查用户是不是新用户 DBusMsgCode CheckUserIsNew(const QString &username, bool &isNewUser); // 获得用户的手机号 DBusMsgCode GetUserPhone(const QString &username, QString &phone); private: static AccountsInterface *m_instance; }; #endif // ACCOUNTSINTERFACE_H ukui-screensaver/src/weathermanager.cpp0000644000175000017500000002105414205074704017263 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * Authors: ZHAI Kang-ning **/ #include "weathermanager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include const QString weatherServerAddr = "http://service.ubuntukylin.com:8001/weather/api/3.0/heweather_data_s6/"; const QString defaultCityId = "101030100"; //"101030100" 默认天津 const int weatherReqInterval = 1000 * 60 * 20; //定时更新天气,和麒麟天气保持一致 const QByteArray schemaWeather = "org.china-weather-data.settings"; static const QMap weatherMap { {"NA", "55"}, {"晴", "0"}, {"多云", "1"}, {"阴", "2"}, {"阵雨", "3"}, {"雷阵雨", "4"}, {"小雨", "7"}, {"中雨", "8"}, {"大雨", "9"}, {"中到大雨", "9"}, {"雪", "13"}, }; WeatherManager::WeatherManager(QObject *parent) : QObject(parent) { //初始化m_net_manager请求天气 m_net_manager = new QNetworkAccessManager(this); QObject::connect(m_net_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*))); m_timer = new QTimer(this); m_timer->setInterval(weatherReqInterval); m_local_weather_info = new LocalWeatherInfo(this); connect(m_timer, &QTimer::timeout, this, &WeatherManager::weatherRequest); } void WeatherManager::getWeather() { weatherRequest(); if (m_timer != NULL) { m_timer->start(); } return; } void WeatherManager::weatherRequest() { if (updateLocation()) return; QNetworkRequest request(QUrl(weatherServerAddr + m_city_id + "/")); m_net_manager->get(request); } bool WeatherManager::updateLocation() { //更新城市信息 未实现 麒麟天气提供gsettings,完成后对接 if (QGSettings::isSchemaInstalled(schemaWeather)) { m_settings = new QGSettings(schemaWeather,"",this); //org/ukui/indicator-china-weather path if(getLogcalWeather()) { emit onWeatherUpdate(m_local_weather_info->getCityName(), m_local_weather_info->getCondText(), m_local_weather_info->getTemperature()); return true; } m_city_id = getLogcalCityId(); } if (m_city_id.isEmpty()) m_city_id = defaultCityId; return false; } bool WeatherManager::getLogcalWeather() { if (m_settings != nullptr) { //"1920-08-27 10:17:42,101310204,澄迈,小雨,95%,25℃,北风,1级," 时间,城市编码,城市名称,天气,湿度,温度,风向,风力 QString weather = m_settings->get("weather").toString(); QStringList weatherInfoList = weather.split(","); if (weatherInfoList.size() < 9) return false; m_local_weather_info->setTime(weatherInfoList.at(0)); if(!m_local_weather_info->isTimeValid()) return false; m_local_weather_info->setCityId(weatherInfoList.at(1)); m_local_weather_info->setCityName(weatherInfoList.at(2)); m_local_weather_info->setCondText(weatherInfoList.at(3)); m_local_weather_info->setAirHumidity(weatherInfoList.at(4)); m_local_weather_info->setTemperature(weatherInfoList.at(5)); m_local_weather_info->setWindDirection(weatherInfoList.at(6)); m_local_weather_info->setWindForce(weatherInfoList.at(7)); return true; } return false; } QString WeatherManager::getLogcalCityId() { if (m_settings != nullptr) { QString citys = m_settings->get("citylist").toString();//"101010100," if (citys.isEmpty()) return ""; QStringList cityList = citys.split(","); if (cityList.size() >= 1) { QString s = cityList.at(0); qDebug() << "local city id = " << s; return s; } } return ""; } void WeatherManager::replyFinished(QNetworkReply *reply) { //注:天气信息只解析了锁屏需要展示的部分 QByteArray BA; QJsonDocument JD; QJsonParseError JPE; BA = reply->readAll(); // QTextCodec *codec = QTextCodec::codecForName("UTF-8"); // QString all = codec->toUnicode(BA); // qDebug() << "reply is:" << all; JD = QJsonDocument::fromJson(BA, &JPE); if (JPE.error == QJsonParseError::NoError) { if (JD.isObject()) { QJsonObject kylinWeatherObj = JD.object().value("KylinWeather").toObject(); QString nowWeather = kylinWeatherObj.value("weather").toObject().value("now").toString(); m_city_name = kylinWeatherObj.value("weather").toObject().value("location").toString(); QStringList nowList = nowWeather.split(","); for(QString now : nowList) { if(now.contains("cond_txt")) { m_cond_txt = now.mid(9); } if (now.contains("tmp")){ m_temperature = now.mid(4); } } emit onWeatherUpdate(m_city_name, m_cond_txt, m_temperature); } } else { qWarning() << "get weather info error : " << JPE.errorString(); } reply->deleteLater(); } QPixmap WeatherManager::getWeatherIcon() { return getWeatherIcon(m_cond_txt); } QPixmap WeatherManager::getWeatherIcon(QString cond) { if (cond.isEmpty()) { qWarning() << "cond info is unknown"; return QPixmap(":/image/assets/weather/55.png").scaled(32,32); } //根据m_cond_txt QString numStr = weatherMap.value(cond); if (!numStr.isEmpty()) { qDebug() << "----------------numStr=" + numStr; return QPixmap(":/image/assets/weather/" + numStr +".png").scaled(32,32); } return QPixmap(":/image/assets/weather/55.png").scaled(32,32); } LocalWeatherInfo::LocalWeatherInfo(QObject *parent) { } bool LocalWeatherInfo::isTimeValid() { if (m_update_time != nullptr && !m_update_time.isEmpty()) { QString strBuffer; QDateTime time = QDateTime::fromString(m_update_time, "yyyy-MM-dd hh:mm:ss"); QDateTime currentTime = QDateTime::currentDateTime(); if (!time.isValid()) return false; uint timeInterval = currentTime.toTime_t() - time.toTime_t(); if((timeInterval <= 21 * 60) && (timeInterval > 0)) { //麒麟天气更新时间为20分钟,加入1分钟容错机制 return true; } } return false; } void LocalWeatherInfo::setTime(QString time) { m_update_time = time; } QString LocalWeatherInfo::getTime() { return m_update_time; } void LocalWeatherInfo::setCityId(QString cityId) { m_city_id = cityId; } QString LocalWeatherInfo::getCityId() { return m_city_id; } void LocalWeatherInfo::setCityName(QString cityName) { m_city_name = cityName; } QString LocalWeatherInfo::getCityName() { return m_city_name; } void LocalWeatherInfo::setCondText(QString condText) { m_cond_text = condText; } QString LocalWeatherInfo::getCondText() { return m_cond_text; } void LocalWeatherInfo::setAirHumidity(QString airHumidity) { m_air_humidity = airHumidity; } QString LocalWeatherInfo::getAirHumidity() { return m_air_humidity; } void LocalWeatherInfo::setTemperature(QString temperature) { m_temperature = temperature; } QString LocalWeatherInfo::getTemperature() { return m_temperature; } void LocalWeatherInfo::setWindDirection(QString windDirection) { m_wind_direction = windDirection; } QString LocalWeatherInfo::getWindDirection() { return m_wind_direction; } void LocalWeatherInfo::setWindForce(QString windForce) { m_wind_force = windForce; } QString LocalWeatherInfo::getWindForce() { return m_wind_force; } ukui-screensaver/src/pam.h0000644000175000017500000000242714205074704014516 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef PAM_H #define PAM_H #include #include #include void authenticate(int toParent[2], int toAuthChild[2]); int pam_conversation(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr); #define MAX_MSG_LENGTH 1024 struct pam_message_object { int msg_style; char msg[MAX_MSG_LENGTH + 1]; } __attribute__((packed)); #define PIPE_OPS_SAFE(statement) do { \ int return_value = statement; \ if (return_value == -1)\ qWarning("PIPE write/read error: %s", strerror(errno)); \ } while (0) #endif // PAM_H ukui-screensaver/src/auth.h0000644000175000017500000000307214205074704014677 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef AUTH_H #define AUTH_H #ifndef QT_NO_KEYWORDS #define QT_NO_KEYWORDS #endif #include class Auth : public QObject { Q_OBJECT Q_ENUMS(PromptType MessageType) public: explicit Auth(QObject *parent = nullptr) : QObject(parent) { } enum PromptType { PromptTypeQuestion, PromptTypeSecret }; enum MessageType { MessageTypeInfo, MessageTypeError }; Q_SIGNALS: void showPrompt(const QString &prompt, Auth::PromptType type); void showMessage(const QString &message, Auth::MessageType type); void authenticateComplete(); public: virtual void authenticate(const QString &userName) = 0; virtual void stopAuth() = 0; virtual void respond(const QString &response) = 0; virtual bool isAuthenticating() = 0; virtual bool isAuthenticated() = 0; }; #endif // AUTH_H ukui-screensaver/src/authdialog.cpp0000644000175000017500000007164314205074760016425 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "authdialog.h" #include #include #include #include #include #include #include #include #include "users.h" #include "iconedit.h" #include "biometricproxy.h" #include "biometricauthwidget.h" #include "biometricdeviceswidget.h" #include "pam-tally.h" #include "commonfunc.h" AuthDialog::AuthDialog(const UserItem &user, QWidget *parent) : QWidget(parent), user(user), auth(new AuthPAM(this)), authMode(UNKNOWN), m_deviceCount(-1), m_biometricProxy(nullptr), m_biometricAuthWidget(nullptr), m_biometricDevicesWidget(nullptr), m_buttonsWidget(nullptr), m_retryButton(nullptr), usebind(false), usebindstarted(false), isBioPassed(false), failedTimes(0), m_bioTimer(nullptr), m_timer(nullptr), isLockingFlg(false), useFirstDevice(false) { initUI(); pam_tally_init(); //这里写函数声明 connect(auth, &Auth::showMessage, this, &AuthDialog::onShowMessage); connect(auth, &Auth::showPrompt, this, &AuthDialog::onShowPrompt); connect(auth, &Auth::authenticateComplete, this, &AuthDialog::onAuthComplete); useFirstDevice = getUseFirstDevice(); } void AuthDialog::startAuth() { prompted = false; unacknowledged_messages = false; auth->authenticate(user.name); //showPasswordAuthWidget(); m_passwordEdit->clear(); m_passwordEdit->setEnabled(false); } void AuthDialog::stopAuth() { if(m_biometricAuthWidget) { usebind = false; usebindstarted = false; if(m_bioTimer && m_bioTimer->isActive()) m_bioTimer->stop(); m_biometricAuthWidget->stopAuth(); m_biometricAuthWidget->hide(); } clearMessage(); // auth->stopAuth(); // if(m_passwdWidget) // m_passwdWidget->hide(); } QPixmap AuthDialog::PixmapToRound(const QPixmap &src, int radius) { if (src.isNull()) { return QPixmap(); } QPixmap pixmapa(src); QPixmap pixmap(radius*2,radius*2); pixmap.fill(Qt::transparent); QPainter painter(&pixmap); painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform); QPainterPath path; path.addEllipse(0, 0, radius*2, radius*2); painter.setClipPath(path); painter.drawPixmap(0, 0, radius*2, radius*2, pixmapa); return pixmap; } void AuthDialog::initUI() { setFixedWidth(500); m_userWidget = new QWidget(this); m_userWidget->setObjectName(QStringLiteral("userWidget")); /* 头像 */ m_faceLabel = new QLabel(m_userWidget); m_faceLabel->setObjectName(QStringLiteral("faceLabel")); m_faceLabel->setFocusPolicy(Qt::NoFocus); const QString SheetStyle = QString("border-radius: %1px; border:0px solid white;").arg(90*scale); m_faceLabel->setStyleSheet(SheetStyle); m_faceLabel->setAlignment(Qt::AlignCenter); QPixmap facePixmap(user.icon); facePixmap = facePixmap.scaled(180*scale,180*scale, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); facePixmap = PixmapToRound(facePixmap, 90*scale); m_faceLabel->setAlignment(Qt::AlignCenter); m_faceLabel->setPixmap(facePixmap); /* 用户名 */ m_nameLabel = new QLabel(m_userWidget); m_nameLabel->setObjectName(QStringLiteral("login_nameLabel")); m_nameLabel->setFocusPolicy(Qt::NoFocus); m_nameLabel->setAlignment(Qt::AlignCenter); //m_nameLabel->setText(user.realName.isEmpty() ? user.name : user.realName); QString text = user.realName.isEmpty() ? user.name : user.realName; QFont font; font.setPixelSize(24); QString str = ElideText(font,500,text); if(text != str) m_nameLabel->setToolTip(text); m_nameLabel->setText(str); /* 密码框所在窗口 */ m_passwdWidget = new QWidget(this); m_passwdWidget->setObjectName(QStringLiteral("passwordWidget")); /* 密码框 */ m_passwordEdit = new IconEdit(m_passwdWidget); m_passwdWidget->setInputMethodHints(Qt::ImhNone); m_passwordEdit->setObjectName(QStringLiteral("passwordEdit")); m_passwordEdit->setIcon(QIcon(":/image/assets/unlock-button.png")); m_passwordEdit->setFocusPolicy(Qt::StrongFocus); m_passwordEdit->installEventFilter(this); m_passwordEdit->setEnabled(false); m_passwordEdit->setType(QLineEdit::Password); setFocusProxy(m_passwordEdit); connect(m_passwordEdit, SIGNAL(clicked(const QString&)), this, SLOT(onRespond(const QString&))); m_passwdWidget->hide(); /* 密码认证信息显示列表 */ m_messageLabel = new QLabel(m_passwdWidget); m_messageLabel->setObjectName(QStringLiteral("messageLabel")); m_messageLabel->setAlignment(Qt::AlignCenter); m_messageButton = new QPushButton(m_passwdWidget); m_messageButton->setObjectName(QStringLiteral("messageButton")); m_messageButton->hide(); } void AuthDialog::unlock_countdown() { int failed_count = 0; int time_left = 0; int deny = 0; int fail_time =0; int unlock_time = 0; pam_tally_unlock_time_left(&failed_count, &time_left, &deny,&fail_time,&unlock_time); // qDebug() << "failed_count:" << failed_count << "time_left:" < 1)//请多少分钟后重试 { char ch[100]={0}; int nMinute = nMinuteleft; if (nMinuteleft > 1 ) { nMinute = nMinuteleft + 1; } m_messageLabel->setText(tr("Please try again in %1 minutes.").arg(nMinute)); m_messageLabel->setToolTip(tr("Please try again in %1 minutes.").arg(nMinute)); m_passwordEdit->clearText(); m_passwordEdit->setDisabled(true); isLockingFlg = true; return ; } else if(time_left > 0)//请多少秒后重试 { char ch[100]={0}; m_messageLabel->setText(tr("Please try again in %1 seconds.").arg(time_left%60)); m_messageLabel->setToolTip(tr("Please try again in %1 seconds.").arg(time_left%60)); m_passwordEdit->clearText(); m_passwordEdit->setDisabled(true); isLockingFlg = true; return ; } else if (failed_count == 0xFFFF)//账号被永久锁定 { m_messageLabel->setText(tr("Account locked permanently.")); m_messageLabel->setToolTip(tr("Account locked permanently.")); m_passwordEdit->clearText(); m_passwordEdit->setDisabled(true); isLockingFlg = true; return ; } else { if(m_passwordEdit){ m_passwordEdit->setDisabled(false); m_passwordEdit->setFocus(); } if (isLockingFlg) { onShowMessage(tr("Authentication failure, Please try again"), Auth::MessageTypeError); isLockingFlg = false; } m_timer->stop(); } return ; } void AuthDialog::root_unlock_countdown() { int failed_count = 0; int time_left = 0; int deny = 0; pam_tally_root_unlock_time_left(&failed_count, &time_left, &deny); int nMinuteleft = time_left/60; if(nMinuteleft > 1)//请多少分钟后重试 { char ch[100]={0}; int nMinute = nMinuteleft; if (nMinuteleft > 1 ) { nMinute = nMinuteleft + 1; } m_messageLabel->setText(tr("Please try again in %1 minutes.").arg(nMinute)); m_messageLabel->setToolTip(tr("Please try again in %1 minutes.").arg(nMinute)); m_passwordEdit->clearText(); m_passwordEdit->setDisabled(true); isLockingFlg = true; return ; } else if(time_left > 0)//请多少秒后重试 { char ch[100]={0}; m_messageLabel->setText(tr("Please try again in %1 seconds.").arg(time_left%60)); m_messageLabel->setToolTip(tr("Please try again in %1 seconds.").arg(time_left%60)); m_passwordEdit->clearText(); m_passwordEdit->setDisabled(true); isLockingFlg = true; return ; } else if (failed_count == 0xFFFF)//账号被永久锁定 { m_messageLabel->setText(tr("Account locked permanently.")); m_messageLabel->setToolTip(tr("Account locked permanently.")); m_passwordEdit->clearText(); m_passwordEdit->setDisabled(true); isLockingFlg = true; return ; } else { if(m_passwordEdit){ m_passwordEdit->setDisabled(false); m_passwordEdit->setFocus(); } if (isLockingFlg) { // m_messageLabel->setText(""); onShowMessage(tr("Authentication failure, Please try again"), Auth::MessageTypeError); isLockingFlg = false; } m_timer->stop(); } return ; } void AuthDialog::resizeEvent(QResizeEvent *) { setChildrenGeometry(); } void AuthDialog::setChildrenGeometry() { if(scale < 0.5) setFixedWidth(500); // 用户信息显示位置 m_userWidget->setGeometry(0, 0, width(), 292*scale); const QString SheetStyle = QString("border-radius: %1px; border:0px solid white;").arg(90*scale); m_faceLabel->setStyleSheet(SheetStyle); QPixmap facePixmap(user.icon); facePixmap = facePixmap.scaled(180*scale,180*scale, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); facePixmap = PixmapToRound(facePixmap, 90*scale); m_faceLabel->setAlignment(Qt::AlignCenter); m_faceLabel->setPixmap(facePixmap); m_faceLabel->setGeometry((width() - 180*scale) / 2, 0, 180*scale, 180*scale); m_nameLabel->setGeometry(0, m_faceLabel->geometry().bottom() + 25*scale, width(), 40); // 密码框和提示信息显示位置 m_passwdWidget->setGeometry(0, m_nameLabel->geometry().bottom() + 45*scale, width(), 150); m_passwordEdit->setGeometry((m_passwdWidget->width() - 300)/2, 0, 300, 34); m_messageLabel->setGeometry((m_passwdWidget->width() - 600)/2, m_passwordEdit->geometry().bottom() + 25, 600, 25); m_messageButton->setGeometry((m_passwdWidget->width() - 200)/2 ,0, 200, 40); setBiometricWidgetGeometry(); setBiometricButtonWidgetGeometry(); } void AuthDialog::closeEvent(QCloseEvent *event) { qDebug() << "AuthDialog::closeEvent"; if(auth && auth->isAuthenticating()) { auth->stopAuth(); } return QWidget::closeEvent(event); } void AuthDialog::onShowMessage(const QString &message, Auth::MessageType type) { qDebug()<setInterval(800); connect(m_timer, &QTimer::timeout, this, &AuthDialog::unlock_countdown); } m_timer->start(); }else if (message.indexOf("No password received, please input password") != -1){ m_messageLabel->setText(tr("Password cannot be empty")); m_messageLabel->setToolTip(tr("Password cannot be empty")); } else{ m_messageLabel->setText(message); m_messageLabel->setToolTip(message); } unacknowledged_messages = true; //stopWaiting(); } void AuthDialog::pamBioSuccess() { m_biometricAuthWidget->startAuth(m_deviceInfo, user.uid); onShowMessage(tr("Please enter your password or enroll your fingerprint "), Auth::MessageTypeInfo); m_bioTimer->stop(); } void AuthDialog::startBioAuth() { if(!m_bioTimer){ m_bioTimer = new QTimer(this); connect(m_bioTimer, SIGNAL(timeout()), this, SLOT(pamBioSuccess())); } m_bioTimer->start(1000); } void AuthDialog::setX11Focus() { if(m_passwordEdit && m_passwordEdit->isVisible()){ m_passwordEdit->setX11Focus(); } } void AuthDialog::onShowPrompt(const QString &prompt, Auth::PromptType type) { qDebug() << "prompt: " << prompt; QString text = prompt; if(text == BIOMETRIC_PAM) { if(authMode == PASSWORD) { skipBiometricAuth(); } else { performBiometricAuth(); } } else if(text == BIOMETRIC_PAM_DOUBLE) { if(failedTimes >= maxFailedTimes){ skipBiometricAuth(); return ; } usebind = true; if(authMode == PASSWORD) { skipBiometricAuth(); } else { if(isBioPassed){ onRespond(BIOMETRIC_SUCCESS); } else performBiometricAuth(); } } else { stopWaiting(); if(!text.isEmpty()) m_passwordEdit->setEnabled(true); m_passwordEdit->setFocus(); prompted = true; unacknowledged_messages = false; if(text == "Password: " || text == "密码:"){ if(usebindstarted){ if(m_messageLabel->text().isEmpty()){ onShowMessage(tr("Please enter your password or enroll your fingerprint "), Auth::MessageTypeInfo); } else{ QTimer::singleShot(1000, [&]{ onShowMessage(tr("Please enter your password or enroll your fingerprint "), Auth::MessageTypeInfo); }); } } text = tr("Password "); } m_passwordEdit->clear(); m_passwordEdit->setPrompt(text); showPasswordAuthWidget(); if(!m_timer){ m_timer = new QTimer(this); m_timer->setInterval(200); connect(m_timer, &QTimer::timeout, this, &AuthDialog::unlock_countdown); } m_timer->start(); } } void AuthDialog::onAuthComplete() { stopWaiting(); if(auth->isAuthenticated()) { if(usebindstarted){ m_biometricAuthWidget->stopAuth(); } if((prompted && !unacknowledged_messages )||direct_login){ direct_login = false; Q_EMIT authenticateCompete(true); } else { qDebug()<<"prompted = "<show(); m_passwordEdit->hide(); m_messageButton->show(); m_messageButton->setFocus(); m_messageButton->setDefault(true); connect(m_messageButton, &QPushButton::clicked, this, &AuthDialog::onMessageButtonClicked); if(successful) { isretry = false; m_messageButton->setText(tr("Login")); } else { isretry = true; m_messageButton->setText(tr("Retry")); } } void AuthDialog::onMessageButtonClicked() { m_messageButton->setDefault(false); if(!isretry) { Q_EMIT authenticateCompete(true); } else { m_messageButton->hide(); authMode = PASSWORD; m_messageLabel->setText(""); startAuth(); } } void AuthDialog::onRespond(const QString &text) { unacknowledged_messages=false; clearMessage(); startWaiting(); m_passwordEdit->setEnabled(false); auth->respond(text); } void AuthDialog::onCapsLockChanged() { m_passwordEdit->onCapsStateChanged(); } void AuthDialog::startWaiting() { if(m_buttonsWidget) { m_buttonsWidget->setEnabled(false); } } void AuthDialog::stopWaiting() { m_passwordEdit->stopWaiting(); if(m_buttonsWidget) { m_buttonsWidget->setEnabled(true); } } void AuthDialog::clearMessage() { m_messageLabel->clear(); } void AuthDialog::performBiometricAuth() { if(!m_biometricProxy) { m_biometricProxy = new BiometricProxy(this); isHiddenSwitchButton = GetHiddenSwitchButton(); } //服务没启动,或者打开DBus连接出错 if(!m_biometricProxy->isValid()) { qWarning() << "An error occurs when connect to the biometric DBus"; skipBiometricAuth(); return; } //初始化enableBiometriAuth if(m_deviceCount < 0) { m_deviceCount = m_biometricProxy->GetUserDevCount(user.uid); } //没有可用设备,不启用生物识别认证 if(m_deviceCount < 1) { qWarning() << "No available devices"; skipBiometricAuth(); return; } //初始化生物识别认证UI if(!usebind) initBiometricButtonWidget(); initBiometricWidget(); //获取默认设备 if(m_deviceName.isEmpty()) { m_deviceName = GetDefaultDevice(user.name); } qDebug() << m_deviceName; // qDebug() << (m_deviceInfo ? m_deviceInfo->shortName : ""); //如果默认设备为空的话,第一次不启动生物识别认证 if(m_deviceName.isEmpty() && !m_deviceInfo) { if(m_deviceCount == 1 && useFirstDevice == true){ DeviceList deviceList = m_biometricProxy->GetDevList(); m_deviceInfo = deviceList.at(0); }else{ skipBiometricAuth(); return; } } //clearMessage(); if(!m_deviceInfo) { m_deviceInfo = m_biometricDevicesWidget->findDeviceByName(m_deviceName); } if(!m_deviceInfo) { skipBiometricAuth(); return; } if(usebind){ if(!usebindstarted){ startBioAuth(); usebindstarted = true; } skipBiometricAuth(); return ; } authMode = BIOMETRIC; m_biometricAuthWidget->startAuth(m_deviceInfo, user.uid); showBiometricAuthWidget(); } void AuthDialog::skipBiometricAuth() { auth->respond(BIOMETRIC_IGNORE); showPasswordAuthWidget(); } void AuthDialog::initBiometricWidget() { if(m_biometricAuthWidget) { m_biometricDevicesWidget->setUser(user.uid); return; } maxFailedTimes = GetFailedTimes(); m_biometricAuthWidget = new BiometricAuthWidget(m_biometricProxy, this); connect(m_biometricAuthWidget, &BiometricAuthWidget::authComplete, this, &AuthDialog::onBiometricAuthComplete); m_biometricDevicesWidget = new BiometricDevicesWidget(m_biometricProxy,user.uid, this); connect(m_biometricDevicesWidget, &BiometricDevicesWidget::deviceChanged, this, &AuthDialog::onDeviceChanged); setBiometricWidgetGeometry(); } void AuthDialog::initBiometricButtonWidget() { if(m_buttonsWidget) { return; } m_buttonsWidget = new QWidget(this); m_buttonsWidget->setObjectName(QStringLiteral("buttonsWidget")); m_buttonsWidget->setFixedHeight(38); QSizePolicy sizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding); sizePolicy.setHorizontalStretch(0); sizePolicy.setVerticalStretch(0); m_biometricButton = new QPushButton(m_buttonsWidget); m_biometricButton->setObjectName(QStringLiteral("biometricButton")); m_biometricButton->setIcon(QIcon(":/image/assets/bio-login.png")); m_biometricButton->setText(tr("Biometric Authentication")); m_biometricButton->setSizePolicy(sizePolicy); m_biometricButton->setVisible(false); m_biometricButton->setCursor(Qt::PointingHandCursor); QFontMetrics fm(m_biometricButton->font(), m_biometricButton); int width = fm.width(m_biometricButton->text()); m_biometricButton->setMaximumWidth(std::max(width + 120, 190)); connect(m_biometricButton, &QPushButton::clicked, this, &AuthDialog::onBiometricButtonClicked); m_passwordButton = new QPushButton(m_buttonsWidget); m_passwordButton->setObjectName(QStringLiteral("passwordButton")); m_passwordButton->setIcon(QIcon(":/image/assets/password-login.png")); m_passwordButton->setText(tr("Password Authentication")); fm = QFontMetrics(m_passwordButton->font(), m_passwordButton); width = fm.width(m_passwordButton->text()); m_passwordButton->setMaximumWidth(std::max(width + 120, 140)); m_passwordButton->adjustSize(); m_passwordButton->setSizePolicy(sizePolicy); m_passwordButton->setVisible(false); m_passwordButton->setCursor(Qt::PointingHandCursor); connect(m_passwordButton, &QPushButton::clicked, this, &AuthDialog::onPasswordButtonClicked); m_otherDeviceButton = new QPushButton(m_buttonsWidget); m_otherDeviceButton->setObjectName(QStringLiteral("otherDeviceButton")); m_otherDeviceButton->setText(tr("Other Devices")); m_otherDeviceButton->setSizePolicy(sizePolicy); m_otherDeviceButton->setMaximumWidth(std::max(width + 50, 140)); m_otherDeviceButton->setVisible(false); m_otherDeviceButton->setCursor(Qt::PointingHandCursor); connect(m_otherDeviceButton, &QPushButton::clicked, this, &AuthDialog::onOtherDevicesButtonClicked); m_retryButton = new QPushButton(m_buttonsWidget); m_retryButton->setObjectName(QStringLiteral("retryButton")); m_retryButton->setText(tr("Retry")); m_retryButton->setSizePolicy(sizePolicy); m_retryButton->setMaximumWidth(110); m_retryButton->setVisible(false); m_retryButton->setCursor(Qt::PointingHandCursor); connect(m_retryButton, &QPushButton::clicked, this, &AuthDialog::onRetryButtonClicked); QGridLayout *layout = new QGridLayout(); layout->setContentsMargins(0, 0, 0, 0); layout->addWidget(m_biometricButton, 0, 0); layout->addWidget(m_passwordButton, 0, 1); layout->addWidget(m_otherDeviceButton, 0, 2); layout->addWidget(m_retryButton, 0, 3); m_buttonsWidget->setLayout(layout); m_buttonsWidget->show(); setBiometricButtonWidgetGeometry(); } void AuthDialog::setBiometricWidgetGeometry() { //生物识别 if(m_biometricAuthWidget) { if(scale > 0 && scale < 1) m_biometricAuthWidget->setMinImage(scale); m_biometricAuthWidget->setGeometry(0, m_userWidget->geometry().bottom(), width(), m_biometricAuthWidget->height()); } if(m_biometricDevicesWidget) { m_biometricDevicesWidget->setGeometry((width() - m_biometricDevicesWidget->width()) / 2, 0, m_biometricDevicesWidget->width(), m_biometricDevicesWidget->height()); } } void AuthDialog::setBiometricButtonWidgetGeometry() { if(m_buttonsWidget) { if(scale > 0.5) m_buttonsWidget->setGeometry(0, height() - m_buttonsWidget->height() - y() - 100*scale, width(), m_buttonsWidget->height()); else m_buttonsWidget->setGeometry(0, height() - m_buttonsWidget->height() - y() - 20, width(), m_buttonsWidget->height()); } } void AuthDialog::onDeviceChanged(const DeviceInfoPtr &deviceInfo) { qDebug() << "device changed: " << *deviceInfo; m_deviceInfo = deviceInfo; if(authMode != BIOMETRIC) { authMode = BIOMETRIC; startAuth(); } else { m_biometricAuthWidget->startAuth(m_deviceInfo, user.uid); } m_userWidget->show(); m_passwdWidget->hide(); m_biometricAuthWidget->show(); m_buttonsWidget->show(); m_biometricDevicesWidget->hide(); m_biometricButton->hide(); m_passwordButton->show(); m_otherDeviceButton->show(); if(m_retryButton) m_retryButton->hide(); } void AuthDialog::onBiometricAuthComplete(bool result) { if(!result) { if(usebind){ authMode = UNKNOWN; failedTimes++; if(failedTimes >= maxFailedTimes){ onShowMessage(tr("Too many unsuccessful attempts,please enter password."),Auth::MessageTypeError); usebindstarted = false; return ; } onShowMessage(tr("Fingerprint authentication failed, you still have %1 verification opportunities")\ .arg(maxFailedTimes - failedTimes),Auth::MessageTypeError); if(!isBioPassed) startBioAuth(); }else{ if(m_retryButton) m_retryButton->setVisible(!m_biometricAuthWidget->isHidden()); } } else { if(usebind){ isBioPassed = true; authMode = UNKNOWN; startAuth(); //onShowMessage("验证成功!",Auth::MessageTypeInfo); }else{ auth->respond(BIOMETRIC_SUCCESS); } direct_login = true; } } void AuthDialog::onBiometricButtonClicked() { //当前没有设备,让用户选择设备 if(!m_deviceInfo) { if(m_deviceCount == 1) { if(m_biometricDevicesWidget) m_biometricDevicesWidget->onOKButtonClicked(); } else { m_otherDeviceButton->click(); } } else { qDebug() << "restart the PAM process"; authMode = BIOMETRIC; startAuth(); } } void AuthDialog::onPasswordButtonClicked() { skipBiometricAuth(); } void AuthDialog::onOtherDevicesButtonClicked() { m_biometricAuthWidget->stopAuth(); showBiometricDeviceWidget(); } void AuthDialog::onRetryButtonClicked() { m_biometricAuthWidget->startAuth(m_deviceInfo, user.uid); m_retryButton->setVisible(false); } void AuthDialog::showPasswordAuthWidget() { qDebug() << "show password authentication widget"; m_userWidget->setVisible(true); m_passwdWidget->setVisible(true); m_passwordEdit->setVisible(true); if(m_biometricAuthWidget) { m_biometricAuthWidget->setVisible(false); m_biometricDevicesWidget->setVisible(false); if(!usebindstarted) m_biometricAuthWidget->stopAuth(); } if(m_buttonsWidget) { if(m_deviceCount > 0) { m_buttonsWidget->setVisible(true); if(!isHiddenSwitchButton){ m_biometricButton->setVisible(true); } m_passwordButton->setVisible(false); m_otherDeviceButton->setVisible(false); if(m_retryButton) m_retryButton->setVisible(false); } else { qDebug() << "hide buttons widget"; m_buttonsWidget->setVisible(false); } } } void AuthDialog::showBiometricAuthWidget() { qDebug() << "show biometric authentication widget"; m_userWidget->setVisible(true); m_passwdWidget->setVisible(false); if(m_biometricAuthWidget) { m_biometricAuthWidget->setVisible(true); m_biometricDevicesWidget->setVisible(false); } if(m_buttonsWidget && m_deviceCount > 0) { m_buttonsWidget->setVisible(true); m_biometricButton->setVisible(false); if(!isHiddenSwitchButton){ m_passwordButton->setVisible(true); } m_otherDeviceButton->setVisible(m_deviceCount > 1); if(m_retryButton) m_retryButton->setVisible(!m_biometricAuthWidget->isAuthenticating()); } else { m_buttonsWidget->setVisible(false); } } void AuthDialog::showBiometricDeviceWidget() { qDebug() << "show biometric devices widget"; m_userWidget->setVisible(false); m_passwdWidget->setVisible(false); if(m_biometricAuthWidget) { m_biometricAuthWidget->setVisible(false); m_biometricDevicesWidget->setVisible(true); } if(m_buttonsWidget) { m_buttonsWidget->setVisible(false); m_biometricButton->setVisible(false); m_passwordButton->setVisible(false); m_otherDeviceButton->setVisible(false); if(m_retryButton) m_retryButton->setVisible(false); } } ukui-screensaver/src/unixsignallistener.cpp0000644000175000017500000000355614205074704020227 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "unixsignallistener.h" #include #include #include #include #include int UnixSignalListener::sigusr1Fd[2]; UnixSignalListener::UnixSignalListener(QObject *parent) : QObject(parent) { if (::socketpair(AF_UNIX, SOCK_STREAM, 0, sigusr1Fd)) qFatal("Couldn't create SIGUSR1 socketpair"); snUsr1 = new QSocketNotifier(sigusr1Fd[1], QSocketNotifier::Read, this); connect(snUsr1, &QSocketNotifier::activated, this, &UnixSignalListener::handleSigUsr1); } void UnixSignalListener::usr1SignalAction(int sig, siginfo_t *siginfo, void *ucontext) { (void)sig; (void)ucontext; char buffer[16]; sprintf(buffer, "%d", siginfo->si_pid); int ignore = ::write(sigusr1Fd[0], buffer, strlen(buffer) + 1); (void)ignore; } void UnixSignalListener::chldSignalAction(int /*sig*/, siginfo_t */*siginfo*/, void */*ucontext*/) { ::waitpid(-1, NULL, 0); } void UnixSignalListener::handleSigUsr1() { snUsr1->setEnabled(false); char buffer[16]; int pid; int ignore = ::read(sigusr1Fd[1], buffer, sizeof(buffer)); sscanf(buffer, "%d", &pid); (void)ignore; /* Do Qt stuff */ Q_EMIT transition(pid); snUsr1->setEnabled(true); } ukui-screensaver/src/screensaverwidget.cpp0000644000175000017500000001136414205074704020020 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "screensaverwidget.h" #include #include #include #include #include #include #include #include #include #include ScreenSaverWidget::ScreenSaverWidget(ScreenSaver *screensaver, QWidget *parent) : QWidget(parent), timer(nullptr), screensaver(screensaver), closing(false) { qDebug() << "ScreenSaverWidget::ScreenSaverWidget"; setMouseTracking(true); setFocus(); this->installEventFilter(this); QPalette pal(palette()); pal.setColor(QPalette::Background, Qt::black); //设置背景黑色 setAutoFillBackground(true); setPalette(pal); switch(screensaver->mode) { case SAVER_RANDOM: case SAVER_SINGLE: embedXScreensaver(screensaver->path); break; case SAVER_BLANK_ONLY: break; case SAVER_IMAGE: { setAutoFillBackground(true); screensaver->startSwitchImages(); QPalette plt; plt.setBrush(QPalette::Background, Qt::black); setPalette(plt); connect(screensaver, &ScreenSaver::imagePathChanged, this, &ScreenSaverWidget::onBackgroundChanged); break; } case SAVER_DEFAULT: embedXScreensaver(screensaver->path); break; case SAVER_DEFAULT_CUSTOM: embedXScreensaver(screensaver->path); break; default: break; } show(); } ScreenSaverWidget::~ScreenSaverWidget() { } void ScreenSaverWidget::closeEvent(QCloseEvent *event) { qDebug() << "ScreenSaverWidget::closeEvent---beginStop"; if(process.state() != QProcess::NotRunning) process.kill(); if(!closing){ closing = true; screensaver->stopSwitchImages(); delete screensaver; if(timer && timer->isActive()) timer->stop(); } qDebug() << "ScreenSaverWidget::closeEvent---endStop"; return QWidget::closeEvent(event); } void ScreenSaverWidget::paintEvent(QPaintEvent *event) { if(!screensaver->exists()) { QPainter painter(this); painter.fillRect(geometry(), Qt::black); } if(screensaver->mode == SAVER_IMAGE) { switch(screensaver->effect) { case TRANSITION_NONE: { QPixmap pixmap(screensaver->path); pixmap.scaled(size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); QPainter painter(this); painter.drawPixmap(geometry(), pixmap); break; } case TRANSITION_FADE_IN_OUT: { QPainter painter(this); QPixmap pixmap1(screensaver->lastPath); pixmap1.scaled(size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); painter.setOpacity(opacity); painter.drawPixmap(geometry(), pixmap1); QPixmap pixmap(screensaver->path); pixmap.scaled(size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); painter.setOpacity(1 - opacity); painter.drawPixmap(geometry(), pixmap); break; } } } return QWidget::paintEvent(event); } bool ScreenSaverWidget::eventFilter(QObject *obj, QEvent *event) { if(event->type() == 23) { XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); } return false; } /* Embed xscreensavers */ void ScreenSaverWidget::embedXScreensaver(const QString &path) { QString cmd = path + " -window-id " + QString::number(winId()); if(process.state() == QProcess::NotRunning) process.start(cmd); } void ScreenSaverWidget::onBackgroundChanged(const QString &/*path*/) { switch(screensaver->effect) { case TRANSITION_NONE: repaint(); break; case TRANSITION_FADE_IN_OUT: opacity = 1.0; timer = new QTimer(this); connect(timer, &QTimer::timeout, this, [&]{ opacity -= 0.1; if(opacity <= 0) timer->stop(); else repaint(); }); timer->start(50); break; } } ukui-screensaver/src/switchbuttongroup.h0000644000175000017500000000252714205074704017554 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * Authors: ZHAI Kang-ning **/ #ifndef SWITCHBUTTONGROUP_H #define SWITCHBUTTONGROUP_H #include #include #include class SwitchButtonGroup : public QWidget { Q_OBJECT public: explicit SwitchButtonGroup(QWidget *parent = nullptr); Q_SIGNALS: void onSwitch(int id); private Q_SLOTS: void parseButtonStatus(); private: void initUI(); int m_checkedId;//上一次选中的按钮id QButtonGroup *m_bg_switch; QPushButton *m_pb_password; QPushButton *m_pb_qrCode; protected: void paintEvent(QPaintEvent *event) override; }; #endif // SWITCHBUTTONGROUP_H ukui-screensaver/src/auth-pam.cpp0000644000175000017500000002301614205074704016005 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "auth-pam.h" #include #include #include #include #define PAM_SERVICE_NAME "ukui-screensaver-qt" //通信管道的文件描述符 int toParent[2], toChild[2]; void sigchld_handler(int signo); static void writeData(int fd, const void *buf, ssize_t count); static void writeString(int fd, const char *data); static int readData(int fd, void *buf, size_t count); static char * readString(int fd); static int pam_conversation(int msgLength, const struct pam_message **msg, PAM_RESPONSE **resp, void *appData); void sigchld_handler(int signo); AuthPAM::AuthPAM(QObject *parent) : Auth(parent), pid(0), nPrompts(0), _isAuthenticated(false), _isAuthenticating(false) { // signal(SIGCHLD, sigchld_handler); } void AuthPAM::authenticate(const QString &userName) { stopAuth(); if(pipe(toParent) || pipe(toChild)) qDebug()<< "create pipe failed: " << strerror(errno); if((pid = fork()) < 0) { qDebug() << "fork error: " << strerror(errno); } else if(pid == 0) { prctl(PR_SET_PDEATHSIG, SIGHUP); close(toParent[0]); close(toChild[1]); int arg1_int = toParent[1]; int arg2_int = toChild[0]; char arg1[128]; char arg2[128]; sprintf(arg1,"%d",arg1_int); sprintf(arg2,"%d",arg2_int); execlp ("ukui-screensaver-checkpass", "ukui-screensaver-checkpass", arg1, arg2,userName.toLocal8Bit().data(), NULL); _exit (EXIT_FAILURE); } else { close(toParent[1]); close(toChild[0]); _isAuthenticating = true; notifier = new QSocketNotifier(toParent[0], QSocketNotifier::Read); connect(notifier, &QSocketNotifier::activated, this, &AuthPAM::onSockRead); } } void AuthPAM::stopAuth() { if(pid != 0) { messageList.clear(); responseList.clear(); _isAuthenticating = false; _isAuthenticated = false; nPrompts = 0; ::kill(pid, SIGKILL); close(toParent[0]); close(toChild[1]); if(notifier){ notifier->deleteLater(); notifier = nullptr; } pid = 0; } } void AuthPAM::respond(const QString &response) { nPrompts--; responseList.push_back(response); // for(auto msg : messageList) // qDebug() << msg.msg; // qDebug() << responseList; // qDebug() << nPrompts; if(nPrompts == 0) { //发送响应到子进程 int j = 0; PAM_RESPONSE *resp = (PAM_RESPONSE*)calloc(messageList.size(), sizeof(PAM_RESPONSE)); //响应的数量和消息的数量一致,如果消息类型不是PROMPT,则响应是空的 for(int i = 0; i < messageList.size(); i++) { struct pam_message message = messageList[i]; PAM_RESPONSE *r = &resp[i]; if(message.msg_style == PAM_PROMPT_ECHO_OFF || message.msg_style == PAM_PROMPT_ECHO_ON) { int respLength = responseList[j].length() + 1; r->resp = (char *)malloc(sizeof(char) * respLength); memcpy(r->resp, responseList[j].toLocal8Bit().data(), respLength); j++; } } _respond(resp); free(resp); messageList.clear(); responseList.clear(); } } bool AuthPAM::isAuthenticated() { return _isAuthenticated; } bool AuthPAM::isAuthenticating() { return _isAuthenticating; } void AuthPAM::onSockRead() { // qDebug() << "has message"; int msgLength; int authComplete = 0; readData(toParent[0], &authComplete, sizeof(authComplete)); if(authComplete) { int authRet = -1; if(readData(toParent[0], (void*)&authRet, sizeof(authRet)) <= 0) qDebug() << "get authentication result failed: " << strerror(errno); qDebug() << "result: " << authRet; _isAuthenticated = (authRet == PAM_SUCCESS); _isAuthenticating = false; if(notifier){ notifier->deleteLater(); notifier = nullptr; } Q_EMIT authenticateComplete(); } else { readData(toParent[0], &msgLength, sizeof(msgLength)); // qDebug() << "message length: " << msgLength; for(int i = 0; i < msgLength; i++) { //读取message struct pam_message message; readData(toParent[0], &message.msg_style, sizeof(message.msg_style)); message.msg = readString(toParent[0]); qDebug() << message.msg; messageList.push_back(message); switch (message.msg_style) { case PAM_PROMPT_ECHO_OFF: nPrompts++; Q_EMIT showPrompt(message.msg, Auth::PromptTypeSecret); break; case PAM_PROMPT_ECHO_ON: nPrompts++; Q_EMIT showPrompt(message.msg, Auth::PromptTypeQuestion); break; case PAM_ERROR_MSG: Q_EMIT showMessage(message.msg, Auth::MessageTypeInfo); break; case PAM_TEXT_INFO: Q_EMIT showMessage(message.msg, Auth::MessageTypeError); break; } } if(nPrompts == 0) { //不需要响应,发送一个空的 PAM_RESPONSE *response = (PAM_RESPONSE*)calloc(messageList.size(), sizeof(PAM_RESPONSE)); _respond(response); free(response); messageList.clear(); } } } static void writeData(int fd, const void *buf, ssize_t count) { if(write(fd, buf, count) != count) qDebug() << "write to parent failed: " << strerror(errno); } static void writeString(int fd, const char *data) { int length = data ? strlen(data) : -1; writeData(fd, &length, sizeof(length)); if(data) writeData(fd, data, sizeof(char) * length); } static int readData(int fd, void *buf, size_t count) { ssize_t nRead = read(fd, buf, count); if(nRead < 0) qDebug() << "read data failed: " << strerror(errno); return nRead; } static char * readString(int fd) { int length; if(readData(fd, &length, sizeof(length)) <= 0) return NULL; if(length <= 0) length = 0; char *value = (char *)malloc(sizeof(char) * (length + 1)); readData(fd, value, length); value[length] = '\0'; return value; } void AuthPAM::_authenticate(const char *userName) { qDebug() << "authenticate " << userName; pam_handle_t *pamh = NULL; char *newUser; int ret; int authRet; struct pam_conv conv; conv.conv = pam_conversation; conv.appdata_ptr = NULL; ret = pam_start(PAM_SERVICE_NAME, userName, &conv, &pamh); if(ret != PAM_SUCCESS) { qDebug() << "failed to start PAM: " << pam_strerror(NULL, ret); } authRet = pam_authenticate(pamh, 0); ret = pam_get_item(pamh, PAM_USER, (const void **)&newUser); if(ret != PAM_SUCCESS) { pam_end(pamh, 0); qDebug() << "failed to get username"; } if(authRet == PAM_SUCCESS) ret = pam_acct_mgmt(pamh, 0); if(ret != PAM_SUCCESS) { qDebug() << "failed to acct mgmt " << pam_strerror(NULL, ret); } free(newUser); fprintf(stderr, "authentication result: %d\n", authRet); // 发送认证结果 int authComplete = 1; writeData(toParent[1], (const void*)&authComplete, sizeof(authComplete)); writeData(toParent[1], (const void *)&authRet, sizeof(authRet)); qDebug() << "--- 认证完成"; _exit(EXIT_SUCCESS); } void AuthPAM::_respond(const PAM_RESPONSE *response) { for(int i = 0; i < messageList.size(); i++) { const PAM_RESPONSE *resp = &response[i]; writeData(toChild[1], (const void *)&resp->resp_retcode, sizeof(resp->resp_retcode)); writeString(toChild[1], resp->resp); } } static int pam_conversation(int msgLength, const struct pam_message **msg, PAM_RESPONSE **resp, void */*appData*/) { PAM_RESPONSE *response = (PAM_RESPONSE*)calloc(msgLength,sizeof(PAM_RESPONSE)); int authComplete = 0; writeData(toParent[1], (const void*)&authComplete, sizeof(authComplete)); writeData(toParent[1], (const void*)&msgLength, sizeof(msgLength)); //发送pam消息 for(int i = 0; i < msgLength; i++) { const struct pam_message *m = msg[i]; writeData(toParent[1], (const void *)&m->msg_style, sizeof(m->msg_style)); writeString(toParent[1], m->msg); } //读取响应 for(int i = 0; i < msgLength; i++) { PAM_RESPONSE *r = &response[i]; readData(toChild[0], &r->resp_retcode, sizeof(r->resp_retcode)); r->resp = readString(toChild[0]); } *resp = response; return PAM_SUCCESS; } void sigchld_handler(int signo) { if(signo == SIGCHLD) { ::waitpid(-1, NULL, WNOHANG); } } ukui-screensaver/src/lockwidget.cpp0000644000175000017500000003407514205074760016436 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "lockwidget.h" #include "powermanager.h" #include "ui_lockwidget.h" #include #include #include #include #include #include #include #include #include #include #include #include "authdialog.h" #include "virtualkeyboard.h" #include "users.h" #include "displaymanager.h" #include "config.h" #include "commonfunc.h" #define TIME_TYPE_SCHEMA "org.ukui.control-center.panel.plugins" #define CONFIG_FILE "/etc/lightdm/ukui-greeter.conf" float scale; LockWidget::LockWidget(QWidget *parent) : QWidget(parent), ui(new Ui::LockWidget), usersMenu(nullptr), scrollArea(nullptr), users(new Users(this)), displayManager(new DisplayManager(this)), timeType(24) { scale = 1.0; ui->setupUi(this); UserItem user = users->getUserByName(getenv("USER")); QString recodfile = QDir::homePath() + "/.cache/ukui-greeter.conf"; qDebug() << recodfile; configSettings = new QSettings(CONFIG_FILE, QSettings::IniFormat, this); authDialog = new AuthDialog(user, this); authDialog->installEventFilter(this); connect(authDialog, &AuthDialog::authenticateCompete, this, &LockWidget::closed); connect(this, &LockWidget::capsLockChanged, authDialog, &AuthDialog::onCapsLockChanged); this->installEventFilter(this); initUI(); if(users->getUsers().count() < 2){ ui->btnSwitchUser->hide(); } } LockWidget::~LockWidget() { delete ui; } QVariant LockWidget::getValue(const QString &key) { configSettings->beginGroup("Greeter"); QVariant value = configSettings->value(key); configSettings->endGroup(); return value; } void LockWidget::closeEvent(QCloseEvent *event) { qDebug() << "LockWidget::closeEvent"; authDialog->close(); return QWidget::closeEvent(event); } bool LockWidget::eventFilter(QObject *obj, QEvent *event) { if(event->type() == 2){ if(obj == ui->btnPowerManager || obj == ui->btnSwitchUser) return false; if(scrollArea && scrollArea->isVisible()){ scrollArea->hide(); } if(powermanager->isVisible()){ authDialog->setFocus(); authDialog->show(); powermanager->hide(); } } return false; } void LockWidget::startAuth() { if(authDialog) { authDialog->startAuth(); } } void LockWidget::stopAuth() { if(authDialog) { authDialog->stopAuth(); } } void LockWidget::setX11Focus() { if(authDialog){ authDialog->setX11Focus(); } } void LockWidget::initUI() { setFocusProxy(authDialog); if(QGSettings::isSchemaInstalled(TIME_TYPE_SCHEMA)){ QGSettings *time_type = new QGSettings(TIME_TYPE_SCHEMA); QStringList keys = time_type->keys(); if (keys.contains("hoursystem")) { timeType = time_type->get("hoursystem").toInt(); } if (keys.contains("date")) { dateType = time_type->get("date").toString(); } } //显示系统时间 timer = new QTimer(this); connect(timer, &QTimer::timeout, this, [&]{ if(timeType == 12) ui->lblTime->setText(QDateTime::currentDateTime().toString("A hh:mm")); else ui->lblTime->setText(QDateTime::currentDateTime().toString("hh:mm")); if(dateType == "cn") ui->lblDate->setText(QDate::currentDate().toString("yyyy/MM/dd ddd")); else ui->lblDate->setText(QDate::currentDate().toString("yyyy-MM-dd ddd")); }); if(timeType == 12) ui->lblTime->setText(QDateTime::currentDateTime().toString("A hh:mm")); else ui->lblTime->setText(QDateTime::currentDateTime().toString("hh:mm")); ui->lblTime->setStyleSheet("QLabel{color:white; font-size: 50px;}"); ui->lblTime->setAlignment(Qt::AlignCenter); ui->lblTime->adjustSize(); timer->start(1000); // QString date = QDate::currentDate().toString("yyyy/MM/dd ddd"); // qDebug() << "current date: " << date; // ui->lblDate->setText(date); if(dateType == "cn") ui->lblDate->setText(QDate::currentDate().toString("yyyy/MM/dd ddd")); else ui->lblDate->setText(QDate::currentDate().toString("yyyy-MM-dd ddd")); ui->lblDate->setStyleSheet("QLabel{color:white; font-size: 16px;}"); ui->lblDate->setAlignment(Qt::AlignCenter); ui->lblDate->adjustSize(); ui->widgetTime->adjustSize(); //电源管理 ui->btnPowerManager->setIcon(QIcon(":/image/assets/powerManager.png")); ui->btnPowerManager->setFixedSize(52,48); ui->btnPowerManager->setIconSize(QSize(30,30)); ui->btnPowerManager->setFocusPolicy(Qt::NoFocus); ui->btnPowerManager->installEventFilter(this); connect(ui->btnPowerManager,&QPushButton::clicked ,this,&LockWidget::showPowerManager); powermanager = new PowerManager(this); powermanager->hide(); connect(powermanager,SIGNAL(lock()) ,this,SLOT(showPowerManager())); connect(powermanager,SIGNAL(switchToUser()) ,this,SLOT(switchToGreeter())); //虚拟键盘 vKeyboard = new VirtualKeyboard(this); vKeyboard->hide(); connect(vKeyboard, &VirtualKeyboard::aboutToClose, vKeyboard, &VirtualKeyboard::hide); ui->btnKeyboard->setIcon(QIcon(":/image/assets/keyboard.png")); ui->btnKeyboard->setFixedSize(52, 48); ui->btnKeyboard->setIconSize(QSize(30, 30)); ui->btnKeyboard->setFocusPolicy(Qt::NoFocus); ui->btnKeyboard->installEventFilter(this); /* connect(ui->btnKeyboard, &QPushButton::clicked, this, [&]{ qDebug() << vKeyboard->isHidden(); vKeyboard->setVisible(vKeyboard->isHidden()); }); */ connect(ui->btnKeyboard, &QPushButton::clicked, this, &LockWidget::showVirtualKeyboard); //用户切换 if(displayManager->canSwitch()) { initUserMenu(); } } void LockWidget::showVirtualKeyboard() { vKeyboard->setVisible(vKeyboard->isHidden()); setVirkeyboardPos(); } void LockWidget::showPowerManager() { if(powermanager->isVisible()){ authDialog->setFocus(); authDialog->show(); powermanager->hide(); } else{ authDialog->hide(); powermanager->show(); #ifndef USE_INTEL if(width() < 1280) powermanager->showSmallSize(); else powermanager->showNormalSize(); #endif powermanager->setGeometry((width()-powermanager->width())/2, (height()-powermanager->height())/2, powermanager->width(),powermanager->height()); } } void LockWidget::switchToGreeter() { if(authDialog) { authDialog->stopAuth(); } displayManager->switchToGreeter();; } void LockWidget::setVirkeyboardPos() { if(vKeyboard) { vKeyboard->setGeometry(0, height() - height()/3, width(), height()/3); } } void LockWidget::initUserMenu() { ui->btnSwitchUser->setIcon(QIcon(":/image/assets/switchUser.png")); ui->btnSwitchUser->setIconSize(QSize(36, 24)); ui->btnSwitchUser->setFixedSize(52, 48); ui->btnSwitchUser->setFocusPolicy(Qt::NoFocus); bool isHideUser = getValue("hide-switchuser-button").toBool(); if(isHideUser) { ui->btnSwitchUser->hide(); } scrollArea = new QScrollArea(this); // scrollArea->setAttribute(Qt::WA_TranslucentBackground); //设置背景透明 // scrollArea->viewport()->setAttribute(Qt::WA_TranslucentBackground); //设置背景透明 scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); //屏蔽水平滚动条 scrollArea->setStyleSheet("QScrollArea {background-color:transparent;}"); scrollArea->viewport()->setStyleSheet("background-color:transparent;"); scrollArea->verticalScrollBar()->setProperty("drawScrollBarGroove", false); scrollArea->verticalScrollBar()->setContextMenuPolicy(Qt::NoContextMenu); scrollContents = new QWidget(scrollArea); scrollArea->setWidget(scrollContents); scrollArea->hide(); if(!usersMenu) { usersMenu = new QMenu(scrollContents); usersMenu->setObjectName("usersMenu"); usersMenu->setToolTipsVisible(true); usersMenu->setStyleSheet("background-color: rgba(255,255,255,20%);\ color: white; \ border-radius: 4px; \ padding: 5px 5px 5px 5px;"); //如果没有设置x11属性,则由于弹出菜单受窗口管理器管理,而主窗口不受,在点击菜单又点回主窗口会闪屏。 usersMenu->setWindowFlags(Qt::X11BypassWindowManagerHint); //usersMenu->hide(); connect(usersMenu, &QMenu::triggered, this, &LockWidget::onUserMenuTrigged); connect(ui->btnSwitchUser, &QPushButton::clicked, this, [&]{ if(scrollArea->isVisible()){ scrollArea->hide(); } else{ scrollArea->show(); // usersMenu->setActiveAction(nullptr); scrollArea->setFocus(); } }); } if(displayManager->getDisplayType() == "gdm"){ QAction *action = new QAction(QIcon(users->getDefaultIcon()), tr("SwitchUser"), this); action->setToolTip("SwitchUser"); action->setData("SwitchUser"); usersMenu->addAction(action); } else if(displayManager->getDisplayType() == "lightdm"){ connect(users, &Users::userAdded, this, &LockWidget::onUserAdded); connect(users, &Users::userDeleted, this, &LockWidget::onUserDeleted); for(auto user : users->getUsers()) { onUserAdded(user); } if(displayManager->hasGuestAccount()) { QAction *action = new QAction(QIcon(users->getDefaultIcon()), tr("Guest"), this); action->setData("Guest"); action->setToolTip("Guest"); usersMenu->addAction(action); } } scrollContents->setFixedSize(usersMenu->size()); //scrollArea->setFixedSize(scrollContents->width(),scrollContents->height()+20); } void LockWidget::keyReleaseEvent(QKeyEvent *e) { if(e->key() == Qt::Key_K){ if(e->modifiers() & Qt::ControlModifier) showVirtualKeyboard(); } } /* lockscreen follows cursor */ void LockWidget::resizeEvent(QResizeEvent *event) { QSize size = event->size(); //重新计算缩放比例 scale = QString::number(size.width() / 1920.0, 'f', 1).toFloat(); if(scale > 1) scale = 1; //系统时间 ui->widgetTime->move((width()-ui->widgetTime->geometry().width())/2, 59*scale); //认证窗口 //设置认证窗口左右居中 authDialog->setGeometry((width()-authDialog->geometry().width())/2,height()/3, \ authDialog->width(), height()); //右下角按钮,x,y的初始值代表距离右下角的距离。 int x=19,y=86; x = x + ui->btnPowerManager->width(); ui->btnPowerManager->move(width() - x,height() - y); x = x+ui->btnKeyboard->width(); ui->btnKeyboard->move(width() - x, height() - y); x = x + ui->btnSwitchUser->width(); ui->btnSwitchUser->move(width() - x, height() - y); setVirkeyboardPos(); //设置弹出菜单,设置弹出菜单的坐标为切换用户按钮的上方,中间保持一定间隔。 if(scrollArea){ if(scrollContents->height() < height()/2){ scrollArea->setFixedSize(scrollContents->width(),scrollContents->height()+10); }else{ scrollArea->setFixedSize(scrollContents->width(),height()/2); } scrollArea->move(width() - x, \ height() - y - scrollArea->height() - 5); } if(powermanager){ #ifndef USE_INTEL if(width() < 1280) powermanager->showSmallSize(); else powermanager->showNormalSize(); #endif powermanager->setGeometry((width()- powermanager->width())/2, (height()-powermanager->height())/2, powermanager->width(),powermanager->height()); } XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); } void LockWidget::onUserAdded(const UserItem &user) { QAction *action = new QAction(QIcon(user.icon), user.realName, this); QFont font; font.setPixelSize(16); QString str = ElideText(font,120,user.realName); if(user.realName != str) action->setToolTip(user.realName); action->setData(user.realName); action->setText(str); usersMenu->addAction(action); usersMenu->adjustSize(); } void LockWidget::onUserDeleted(const UserItem &user) { for(auto action : usersMenu->actions()) { if(action->data() == user.name) usersMenu->removeAction(action); } } void LockWidget::onUserMenuTrigged(QAction *action) { qDebug() << action->data().toString() << "selected"; if(authDialog) { authDialog->stopAuth(); } QString userName = action->data().toString(); if(userName == "Guest") { displayManager->switchToGuest(); } else if(userName == "SwitchUser") { displayManager->switchToGreeter(); } else { displayManager->switchToUser(userName); } } ukui-screensaver/src/accountsinterface.cpp0000644000175000017500000001131614205074760017773 0ustar fengfeng/** * Copyright (C) 2018 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, 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 "accountsinterface.h" const QString STR_EDU_SERVICE = "cn.kylinos.SSOBackend"; const QString STR_EDU_PATH = "/cn/kylinos/SSOBackend"; AccountsInterface* AccountsInterface::m_instance = nullptr; AccountsInterface::AccountsInterface(const QString &strService,const QString &strPath,\ const QDBusConnection &connection, QObject *parent)\ :QDBusAbstractInterface(strService,strPath,getInterfaceName(),connection,parent) { } AccountsInterface* AccountsInterface::getInstance() { static QMutex mutex; mutex.lock(); if(m_instance == nullptr) m_instance = new AccountsInterface(STR_EDU_SERVICE, STR_EDU_PATH, QDBusConnection::systemBus()); mutex.unlock(); return m_instance; } DBusMsgCode AccountsInterface::SetAccountPincode(const QString &username, const QString &pincode) { QDBusReply reply = call("SetAccountPincode", username, pincode); if(!reply.isValid()) { qDebug() << "error: [AccountsInterface][SetAccountPincode]: DBus Connect Failed!"; return DBusMsgCode::Error_NoReply; } if(reply.value() != 0) { qDebug() << "error: [AccountsInterface][SetAccountPincode]: DBus request failed!"; //return static_cast(reply.value()); return DBusMsgCode::Error_NoReply; } return DBusMsgCode::No_Error; } DBusMsgCode AccountsInterface::GetAccountPincode(const QString &username, QString &pincode) { QDBusMessage message = call("GetAccountPincode", username); if(QDBusMessage::ErrorMessage == message.type()) { qDebug() << "error: [AccountsInterface][GetAccountPincode]: DBus Connect Failed!"; return DBusMsgCode::Error_NoReply; } QList argvs = message.arguments(); if(argvs.size() != 2) { qDebug() << "error: [AccountsInterface][GetAccountPincode]: DBus arguments error!"; return DBusMsgCode::Error_ArgCnt; } int state = argvs.at(1).value(); if(state != 0) { qDebug() << "error: [AccountsInterface][GetAccountPincode]: DBus request failed!"; //return static_cast(state); return DBusMsgCode::Error_ArgCnt; } pincode = argvs.at(0).value(); qDebug() << "pincode:" << pincode; return DBusMsgCode::No_Error; } DBusMsgCode AccountsInterface::CheckUserIsNew(const QString &username, bool &isNewUser) { QDBusReply reply = call("CheckUserIsNew", username); if(!reply.isValid()) { qDebug() << "info: [AccountsInterface][CheckUserIsNew]: DBus connect failed!"; return DBusMsgCode::Error_NoReply; } if(reply.value()) { qDebug() << "info: [AccountsInterface][CheckUserIsNew]: DBus request failed!"; return DBusMsgCode::Error_UnknownReason; } isNewUser = static_cast(reply.value()); return DBusMsgCode::No_Error; } DBusMsgCode AccountsInterface::GetUserPhone(const QString &username, QString &phonenum) { QDBusMessage message = call("GetAccountBasicInfo", username); if(QDBusMessage::ErrorMessage == message.type()) { qDebug() << "info: [AccountsInterface][GetUserPhone]: DBus Connect Failed!"; return DBusMsgCode::Error_NoReply; } QList argvs = message.arguments(); if(argvs.size() != 7) { qDebug() << "info: [AccountsInterface][GetUserPhone]: DBus arguments =" << argvs.size() << "error!"; return DBusMsgCode::Error_ArgCnt; } int role = argvs.at(0).value(); Q_UNUSED(role); QString school = argvs.at(1).value(); Q_UNUSED(school); QString province = argvs.at(2).value(); Q_UNUSED(province); QString city = argvs.at(3).value(); Q_UNUSED(city); QString county = argvs.at(4).value(); Q_UNUSED(county); phonenum = argvs.at(5).value(); int state = argvs.at(6).value(); Q_UNUSED(state); return state ? DBusMsgCode::Error_UnknownReason : DBusMsgCode::No_Error; } ukui-screensaver/src/users.cpp0000644000175000017500000001237414205074704015437 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "users.h" #include #include #include #include #include #include "types.h" #include #include QDebug operator<<(QDebug stream, const UserItem &user) { stream << user.name << user.realName << user.uid << user.icon << user.path; return stream; } Users::Users(QObject *parent) : QObject(parent) { defaultIcon = ":/image/assets/iconFace.png"; loadUsers(); } QList Users::getUsers() { return users; } UserItem Users::getUserByName(const QString &name) { for(int i = 0 ; i < users.size() ; i++) { if(users.at(i).name == name) { return users.at(i); } } UserItem user; if(name == "root") { user.icon = "/root/.face"; if(!QFile(user.icon).exists()) { user.icon = defaultIcon; } } else { user.icon = qgetenv("HOME")+"/.face"; if(!QFile(user.icon).exists()) { user.icon = defaultIcon; } } user.name = name; user.path = ""; user.realName = name; user.uid = getuid(); return user; } QString Users::getDefaultIcon() { return defaultIcon; } bool compareBarData(const UserItem &user1, const UserItem &user2) { if (user1.realName < user2.realName) { return true; } return false; } //https://stackoverflow.com/questions/20206376/ //how-do-i-extract-the-returned-data-from-qdbusmessage-in-a-qt-dbus-call void Users::loadUsers() { qDebug() << "loadUsers"; actService = new QDBusInterface(ACT_DBUS_SERVICE, ACT_DBUS_PATH, ACT_DBUS_INTERFACE, QDBusConnection::systemBus()); connect(actService, SIGNAL(UserAdded(const QDBusObjectPath&)), this, SLOT(onUserAdded(const QDBusObjectPath&))); connect(actService, SIGNAL(UserDeleted(const QDBusObjectPath&)), this, SLOT(onUserDeleted(const QDBusObjectPath&))); QDBusMessage ret = actService->call("ListCachedUsers"); QList outArgs = ret.arguments(); //(QVariant(QDBusArgument,)) QVariant first = outArgs.at(0); //QVariant(QDBusArgument,) const QDBusArgument &dbusArgs = first.value(); QDBusObjectPath path; dbusArgs.beginArray(); while (!dbusArgs.atEnd()) { dbusArgs >> path; getUser(path.path()); } dbusArgs.endArray(); qSort(users.begin(), users.end(), compareBarData); } UserItem Users::getUser(const QString &path) { QDBusInterface iface(ACT_DBUS_SERVICE, path, DBUS_PROP_INTERFACE, QDBusConnection::systemBus()); QDBusMessage ret = iface.call("GetAll", ACT_USER_INTERFACE); QList outArgs = ret.arguments(); QVariant first = outArgs.at(0); const QDBusArgument &dbusArgs = first.value(); UserItem user; user.path = path; dbusArgs.beginMap(); while(!dbusArgs.atEnd()) { QString key; QVariant value; dbusArgs.beginMapEntry(); dbusArgs >> key >> value; if(key == "UserName") { user.name = value.toString(); } else if(key == "RealName") { user.realName = value.toString(); } else if(key == "IconFile") { user.icon = value.toString(); if(!QFile(user.icon).exists()) { user.icon = defaultIcon; } } else if(key == "Uid") { user.uid = value.toUInt(); } dbusArgs.endMapEntry(); } dbusArgs.endMap(); if(user.realName.isEmpty()) { user.realName = user.name; } users.push_back(user); return user; } void Users::onUserAdded(const QDBusObjectPath& path) { int index = findUserByPath(path.path()); if(index >=0 &&index= 0 && index. * * Authors: ZHAI Kang-ning **/ #include "wechatauthdialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "eduplatforminterface.h" WeChatAuthDialog::WeChatAuthDialog(QWidget *parent) : QWidget(parent), m_networkManager(new QNetworkAccessManager(this)), m_loginQR(new QRLabel(this)), m_title(new QLabel(this)), m_guide(new QLabel(this)), m_errorMsg(new QLabel(this)), m_networkWatcher(new NetWorkWatcher(this)), m_timer(new QTimer(this)) { initUI(); } WeChatAuthDialog::WeChatAuthDialog(int type, QWidget *parent) : QWidget(parent), m_networkManager(new QNetworkAccessManager(this)), m_loginQR(new QRLabel(this)), m_title(new QLabel(this)), m_guide(new QLabel(this)), m_errorMsg(new QLabel(this)), m_networkWatcher(new NetWorkWatcher(this)), m_timer(new QTimer(this)) { m_authType = type; initUI(); } void WeChatAuthDialog::initUI() { /** * ************标题*************** * **********提示信息************** * **********二维码**************** * **********错误信息*************** */ this->setContentsMargins(0, 0, 0, 0); QVBoxLayout *vbLayout = new QVBoxLayout(this); vbLayout->setContentsMargins(0, 0, 0, 0); if (m_authType == authType::login) { m_title->setText(tr("Login by wechat")); m_guide->setText(tr("「 Use registered WeChat account to login 」")); } else if (m_authType == authType::check) { m_title->setText(tr("Verification by wechat")); m_guide->setText(tr("「 Use bound WeChat account to verification 」")); } m_errorMsg->setText(""); m_title->setStyleSheet("font-size:32px;color:#ffffff"); m_guide->setStyleSheet("font-size:24px;color: rgba(255,255,255,192);"); m_errorMsg->setStyleSheet("font-size:14px;color:#FD625E;"); m_guide->setWordWrap(true); m_title->adjustSize(); m_guide->adjustSize(); QPixmap pixmap(":/image/assets/intel/icon-wechat-noqrcode.png"); m_loginQR->setPixmap(pixmap.scaled(188, 188, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); m_loginQR->setStyleSheet("QLabel{border-radius: 16px;background:rgb(255,255,255);color:white}"); //m_loginQR->resize(208,208); vbLayout->addWidget(m_title, 0, Qt::AlignCenter); vbLayout->addSpacerItem(new QSpacerItem(0,16,QSizePolicy::Fixed,QSizePolicy::Preferred)); vbLayout->addWidget(m_guide, 0, Qt::AlignCenter); vbLayout->addSpacerItem(new QSpacerItem(0,30,QSizePolicy::Fixed,QSizePolicy::Preferred)); vbLayout->addWidget(m_loginQR, 0, Qt::AlignCenter); vbLayout->addWidget(m_errorMsg, 0 ,Qt::AlignCenter); vbLayout->addStretch(1); this->adjustSize(); // //监听网络状态变化 // QDBusConnection::systemBus().connect(QString("org.freedesktop.NetworkManager"), // QString("/org/freedesktop/NetworkManager"), // QString("org.freedesktop.NetworkManager"), // QString("StateChanged"), this, SLOT(onNetworkStateChanged(uint))); connect(m_networkWatcher, &NetWorkWatcher::NetworkStateChanged, this, &WeChatAuthDialog::onNetworkStateChanged); connect(m_timer, &QTimer::timeout, this, [=]{ m_errorMsg->clear(); }); } void WeChatAuthDialog::onNetworkStateChanged(uint state) { if(isHidden()) return; if(NM_STATE_CONNECTED_GLOBAL == state) showErrorMessage(" ", true); else showErrorMessage(tr("Network not connected~"), true); } void WeChatAuthDialog::onReset() { if (m_authType == authType::login) { m_title->setText(tr("Login by wechat")); m_guide->setText(tr("「 Use registered WeChat account to login 」")); } else if (m_authType == authType::check) { m_title->setText(tr("Verification by wechat")); m_guide->setText(tr("「 Use bound WeChat account to verification 」")); } m_guide->show(); QPixmap pixmap(":/image/assets/intel/icon-wechat-noqrcode.png"); m_loginQR->setPixmap(pixmap.scaled(188, 188, Qt::IgnoreAspectRatio, Qt::SmoothTransformation)); m_loginQR->setStyleSheet("QLabel{border-radius: 16px;background:rgb(255,255,255);color:white}"); //m_loginQR->resize(208,208); reloadQR(); } void WeChatAuthDialog::initConnect() { QObject::connect(m_networkManager, &QNetworkAccessManager::finished, this, &WeChatAuthDialog::replyFinished); } void WeChatAuthDialog::getLoginQR() { if(!m_requestQRThread) { qDebug() << "[WeChatAuthDialog] getLoginQR create new requestQRThread"; m_requestQRThread = new RequestQRThread(this); connect(m_requestQRThread, &RequestQRThread::resultReady, this, &WeChatAuthDialog::onQRUrlReady); } if(!m_isThreadWorking){ qDebug() << "[WeChatAuthDialog] getLoginQR requestQRThread is not running"; m_requestQRThread->start(); m_isThreadWorking = true; } else { qDebug() << "[WeChatAuthDialog] getLoginQR requestQRThread is running"; } } void WeChatAuthDialog::replyFinished(QNetworkReply *reply) { if(!reply->isFinished()) { //超时 reply->abort(); qWarning() << "error: [WeChatAuthDialog][replyFinished]: network timeout"; showErrorMessage(tr("Network not connected~")); reloadQR(); return; } if (reply->error() == QNetworkReply::NoError) { QByteArray bytes = reply->readAll(); QSize size(188, 188); QBitmap mask(size); QPainter painter(&mask); painter.setRenderHint(QPainter::Antialiasing); painter.setRenderHint(QPainter::SmoothPixmapTransform); painter.fillRect(0, 0, size.width(), size.height(), Qt::white); painter.setBrush(QColor(0, 0, 0)); painter.drawRoundedRect(0, 0, size.width(), size.height(), 16, 16); QPixmap pixmap; pixmap.loadFromData(bytes); QPixmap pixmap_ = pixmap.scaled(188, 188, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); pixmap_.setMask(mask); m_loginQR->setPixmap(pixmap_); //m_loginQR->resize(208,208); } else { qWarning() << "网络错误" << reply->error(); reloadQR(); // 错误处理-显示错误信息,或显示上一次缓存的图片或叉图。 } } void WeChatAuthDialog::qRStatusChangeSolt(QString loginname, QString loginpwd, int curstatus) { qDebug() << "---loginname:" << loginname << "---loginpwd:" << loginpwd << "---curstatus:" << curstatus; QRCodeSwepState state = static_cast(curstatus); switch (state) { case QRCodeSwepState::WaitingSwep: qDebug() << "info: [WeChatAuthDialog][qRStatusChangeSolt]: waiting user swep qrcode!"; break; case QRCodeSwepState::HaveSwep: qDebug() << "info: [WeChatAuthDialog][qRStatusChangeSolt]: user has swep code!"; m_title->setText(tr("Scan code successfully")); m_guide->setText(" "); m_errorMsg->setText(""); break; case QRCodeSwepState::CancelSwep: qDebug() << "info: [WeChatAuthDialog][qRStatusChangeSolt]: user cancel swep code!"; onReset(); m_errorMsg->setText(""); break; case QRCodeSwepState::ConfirmSuccess: { //Todo 判断是否是该用户 qDebug() << "info: [WeChatAuthDialog][qRStatusChangeSolt]: user = [" << loginname << "] confirm success!"; Q_EMIT qRStatusChange(loginname, loginpwd, curstatus); } case QRCodeSwepState::QRCodeInvalid: { qDebug() << "info: [WeChatAuthDialog][onQRCodeStateChanged]: qrcode invalid!"; onReset(); break; }case QRCodeSwepState::QRCodeTimeout: { qDebug() << "info: [UserSecondQRCodeLogin][onQRCodeState]: qrcode timeout!"; onReset(); // 更新错误信息 showErrorMessage(tr("Timeout!Try again!")); break; } default: break; } } void WeChatAuthDialog::reloadQR() { if(this->parentWidget()->isHidden() || isHidden()) return; qDebug() << "info: [WeChatAuthDialog] [reloadQR] reloadQR"; getLoginQR(); } void WeChatAuthDialog::showErrorMessage(QString message, bool isLong) { if (m_timer->isActive()) m_timer->stop(); onReset(); m_errorMsg->setText(message); m_errorMsg->adjustSize(); m_errorMsg->setGeometry((this->width() - m_errorMsg->width())/2, this->height() - m_errorMsg->height(), m_errorMsg->width(), m_errorMsg->height()); // if(isLong) // return; // QTimer *timer = new QTimer(this); // connect(timer, &QTimer::timeout, this, [=]{ // m_errorMsg->setText(" "); // }); // timer->start(3000); m_timer->setSingleShot(true); m_timer->start(10000); } void WeChatAuthDialog::onQRUrlReady(int errorCode, const QString url) { m_isThreadWorking = false; if (DBusMsgCode(errorCode) == DBusMsgCode::No_Error) { // 从网络上下载二维码 并加载到qrcode QNetworkRequest request; request.setUrl(url); QNetworkReply *reply = m_networkManager->get(request); QTimer::singleShot(2*1000, this, [=](){ replyFinished(reply); }); } else if(DBusMsgCode(errorCode) == DBusMsgCode::Error_NetWork) { qWarning() << "[error] [WeChatAuthDialog] DBus(cn.kylinos.SSOBackend.eduplatform) get url network error"; QTimer::singleShot(2 * 1000, this, [=]{ if(this->isVisible() && !m_requestQRThread->isRunning()) reloadQR(); }); } else { qWarning() << "[error] connect form DBus(cn.kylinos.SSOBackend.eduplatform)"; QTimer::singleShot(2 * 1000, this, [=](){ reloadQR(); }); } } void WeChatAuthDialog::closeEvent(QCloseEvent *event) { if(m_requestQRThread) { qDebug() << "[WeChatAuthDialog] requestQRThread delete"; m_requestQRThread->quit(); m_requestQRThread->wait(); m_requestQRThread->deleteLater(); } } void WeChatAuthDialog::showEvent(QShowEvent *event) { m_networkWatcher->checkOnline(); onReset(); connect(EduPlatformInterface::getInstance(),&EduPlatformInterface::QRStatusChange, this, &WeChatAuthDialog::qRStatusChangeSolt); } void WeChatAuthDialog::hideEvent(QHideEvent *event) { disconnect(EduPlatformInterface::getInstance(),&EduPlatformInterface::QRStatusChange, this, &WeChatAuthDialog::qRStatusChangeSolt); } QRLabel::QRLabel(QWidget *parent) : QLabel(parent) { } void QRLabel::mousePressEvent(QMouseEvent *event) { if(event->button()== Qt::LeftButton) { Q_EMIT clicked(); } } RequestQRThread::RequestQRThread(QObject *parent) : QThread(parent) { // } void RequestQRThread::run() { QString url; DBusMsgCode ret = EduPlatformInterface::getInstance()->CheckUserByQR(url); Q_EMIT resultReady(ret, url.toLocal8Bit()); } ukui-screensaver/src/PhysicalDeviceSet/0000755000175000017500000000000014205074760017135 5ustar fengfengukui-screensaver/src/PhysicalDeviceSet/sounddeviceset.cpp0000644000175000017500000001626014205074760022672 0ustar fengfeng/** * Copyright (C) 2018 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, 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 "sounddeviceset.h" int SoundDeviceSet::m_value = -1; SoundDeviceSet* SoundDeviceSet::instance(QObject *parent) { static SoundDeviceSet* _instance = nullptr; QMutex mutex; mutex.lock(); if(!_instance) _instance = new SoundDeviceSet(parent); mutex.unlock(); return _instance; } SoundDeviceSet::SoundDeviceSet(QObject *parent): QObject(parent) { init(); } void SoundDeviceSet::init(){ if (mate_mixer_init () == FALSE){ qDebug()<<"matemixer init false"; return ; } context = mate_mixer_context_new (); if (mate_mixer_context_open (context) == FALSE) { qDebug()<<"matemixer context open context false."; return ; } MateMixerState state = mate_mixer_context_get_state (context); switch (state) { case MATE_MIXER_STATE_READY: connected (context); break; case MATE_MIXER_STATE_CONNECTING: g_print ("Waiting for connection...\n"); /* The state will change asynchronously to either MATE_MIXER_STATE_READY * or MATE_MIXER_STATE_FAILED, wait for the change in a main loop */ g_signal_connect (G_OBJECT (context), "notify::state", G_CALLBACK (on_context_state_notify), NULL); break; default: qDebug()<<"it's can not reached"; break; } } void SoundDeviceSet::emitSignal(bool val){ emit muteChanged(val); } void SoundDeviceSet::setValue(int val){ if(!context) return ; if(val > 100) val = 100; else if(val < 0) val = 0; if(val == m_value) return; m_value = val; emit valueChanged(m_value); MateMixerStream *m_pOutputStream = mate_mixer_context_get_default_output_stream(context); if(m_pOutputStream == NULL) return; MateMixerStreamControl *control = mate_mixer_stream_get_default_control(m_pOutputStream); bool status = false; int volume = val*65536/100; mate_mixer_stream_control_set_volume(control,guint(volume)); if (val <= 0) { status = true; mate_mixer_stream_control_set_mute(control,status); mate_mixer_stream_control_set_volume(control,0); } else { mate_mixer_stream_control_set_mute(control,status); } } void SoundDeviceSet::onStreamControlMuteNotify(MateMixerStreamControl *m_pControl,GParamSpec *pspec,gpointer point){ if(!m_pControl) return ; bool state = mate_mixer_stream_control_get_mute (m_pControl); SoundDeviceSet::instance()->emitSignal(state); } void SoundDeviceSet::onStreamControlVolumeNotify(MateMixerStreamControl *m_pControl,GParamSpec *pspec,gpointer point){ MateMixerStreamControlFlags flags; guint volume = 0; if (m_pControl != nullptr) flags = mate_mixer_stream_control_get_flags(m_pControl); if (flags&MATE_MIXER_STREAM_CONTROL_VOLUME_READABLE) { volume = mate_mixer_stream_control_get_volume(m_pControl); } MateMixerDirection direction; MateMixerStream *m_pStream = mate_mixer_stream_control_get_stream(m_pControl); direction = mate_mixer_stream_get_direction(m_pStream); //设置输出滑动条的值 int value = volume*100/65536.0 + 0.5; if (direction == MATE_MIXER_DIRECTION_OUTPUT) { SoundDeviceSet::instance()->setValue(value); } } void SoundDeviceSet::connected (MateMixerContext *context) { MateMixerStream *m_pOutputStream = mate_mixer_context_get_default_output_stream(context); if(m_pOutputStream == NULL) return; MateMixerStreamControl *control = mate_mixer_stream_get_default_control(m_pOutputStream); g_signal_connect ( G_OBJECT (control), "notify::volume", G_CALLBACK (onStreamControlVolumeNotify), NULL); g_signal_connect (control, "notify::mute", G_CALLBACK (onStreamControlMuteNotify), NULL); SoundDeviceSet::instance()->setDefaultVal(); } void SoundDeviceSet::setDefaultVal() { if(!context) return ; MateMixerStream *m_pOutputStream = mate_mixer_context_get_default_output_stream(context); if(m_pOutputStream == NULL) return; MateMixerStreamControl *control = mate_mixer_stream_get_default_control(m_pOutputStream); // int volume = mate_mixer_stream_control_get_volume(control); // int value = volume *100 /65536.0+0.5; // setValue(value); } void SoundDeviceSet::on_context_state_notify (MateMixerContext *context,GParamSpec *pspec,gpointer point ) { MateMixerState state; state = mate_mixer_context_get_state (context); switch (state) { case MATE_MIXER_STATE_READY: /* This state can be reached repeatedly if the context is connected * to a sound server, the connection is dropped and then reestablished */ connected (context); break; case MATE_MIXER_STATE_FAILED: qDebug()<<"matemixser state failed"; break; default: break; } } bool SoundDeviceSet::getIsMute(){ if(!context) return false; MateMixerState state; state = mate_mixer_context_get_state (context); if(state != MATE_MIXER_STATE_READY) return false; MateMixerStream *m_pOutputStream = mate_mixer_context_get_default_output_stream(context); if(m_pOutputStream == NULL) return false; MateMixerStreamControl *control = mate_mixer_stream_get_default_control(m_pOutputStream); return mate_mixer_stream_control_get_mute(control); } void SoundDeviceSet::setMute(bool val){ if(!context) return; MateMixerState state; state = mate_mixer_context_get_state (context); if(state != MATE_MIXER_STATE_READY) return; MateMixerStream *m_pOutputStream = mate_mixer_context_get_default_output_stream(context); if(m_pOutputStream == NULL) return; MateMixerStreamControl *control = mate_mixer_stream_get_default_control(m_pOutputStream); mate_mixer_stream_control_set_mute(control,val); } bool SoundDeviceSet::getIsReady(){ MateMixerState state; state = mate_mixer_context_get_state (context); return state == MATE_MIXER_STATE_READY; } ukui-screensaver/src/PhysicalDeviceSet/sounddeviceset.h0000644000175000017500000000374414205074760022342 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef SOUNDDEVICESET_H #define SOUNDDEVICESET_H #include #include #include #include #include #include class SoundDeviceSet : public QObject { Q_OBJECT public: static SoundDeviceSet* instance(QObject *parent = nullptr); void setMute(bool val); bool getIsMute(); void setDefaultVal(); int getValue(){ return m_value; } Q_SIGNALS: void muteChanged(bool mute); // val from 0 to 100 change void valueChanged(int val); public Q_SLOTS: // val from 0 to 100 change void setValue(int val); private: SoundDeviceSet(QObject *parent = nullptr); private: MateMixerContext *context; static void onStreamControlMuteNotify(MateMixerStreamControl *m_pControl,GParamSpec *pspec,gpointer point); static void onStreamControlVolumeNotify(MateMixerStreamControl *m_pControl,GParamSpec *pspec,gpointer point); static void on_context_state_notify (MateMixerContext *context,GParamSpec *pspec,gpointer point ); static void connected (MateMixerContext *context); void init(); void emitSignal(bool val); bool getIsReady(); static int m_value; // 当前的音量值 }; #endif // SOUNDDEVICESET_H ukui-screensaver/src/PhysicalDeviceSet/touchscreenset.cpp0000644000175000017500000000234314205074760022701 0ustar fengfeng/** * Copyright (C) 2018 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, 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 "touchscreenset.h" #include TouchScreenSet* TouchScreenSet::instance(QObject *parent) { static TouchScreenSet* _instance = nullptr; QMutex mutex; mutex.lock(); if(!_instance) _instance = new TouchScreenSet(parent); mutex.unlock(); return _instance; } TouchScreenSet::TouchScreenSet(QObject *parent): QObject(parent) { init(); } void TouchScreenSet::init() { } int TouchScreenSet::getTouchScreenID() { } ukui-screensaver/src/PhysicalDeviceSet/brightnessdeviceset.cpp0000644000175000017500000000704514205074760023713 0ustar fengfeng/** * Copyright (C) 2018 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, 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 "brightnessdeviceset.h" int BrightnessDeviceSet::m_value = -1; int BrightnessDeviceSet::m_maxBrightnessValue = -1; bool BrightnessDeviceSet::m_isPowerSupply = false; int BrightnessDeviceSet::m_curBrightnessValue = -1; BrightnessDeviceSet* BrightnessDeviceSet::instance(QObject *parent) { static BrightnessDeviceSet* _instance = nullptr; QMutex mutex; mutex.lock(); if(_instance == nullptr) _instance = new BrightnessDeviceSet(parent); mutex.unlock(); return _instance; } BrightnessDeviceSet::BrightnessDeviceSet(QObject *parent): QObject(parent) { init(); } void BrightnessDeviceSet::init() { //m_isPowerSupply = true; m_isPowerSupply = isPowerSupply(); if(!m_isPowerSupply){ qWarning() << "info: [BrightnessDeviceSet][init]: current device not support brightness-change!"; } m_curBrightnessValue = getCurBrightness(); m_maxBrightnessValue = getMaxBrightness(); //m_maxBrightnessValue = 19200; m_value = m_curBrightnessValue * 1.0 / m_maxBrightnessValue * 100; } int BrightnessDeviceSet::getValue() { return m_value; } void BrightnessDeviceSet::setValue(int value) { if(!m_isPowerSupply) return; if(value == m_value) return; if(value > 100) value = 100; else if(value < 0) value = 0; m_value = value; //emit valueChanged(m_value); // 调整亮度 int val = value * 1.0 / 100 * m_maxBrightnessValue; setBrightness(val); } bool BrightnessDeviceSet::isPowerSupply() { QProcess process; QString command = "/usr/lib/ukui-greeter/greeter-backlight-helper --get-support-brightness"; process.start(command); process.waitForFinished(3000); QString result = process.readAll(); return result == "true"; } int BrightnessDeviceSet::getMaxBrightness() { if(!m_isPowerSupply) return 0; QProcess process; QString command = "/usr/lib/ukui-greeter/greeter-backlight-helper --get-max-brightness"; process.start(command); process.waitForFinished(3000); QString result = process.readAll(); return result.toInt(); } int BrightnessDeviceSet::getCurBrightness() { if(!m_isPowerSupply) return 0; QProcess process; QString command = "/usr/lib/ukui-greeter/greeter-backlight-helper --get-brightness"; process.start(command); process.waitForFinished(3000); QString result = process.readAll(); return result.toInt(); } void BrightnessDeviceSet::setBrightness(int val) { if(!m_isPowerSupply) return; if(val > m_maxBrightnessValue) val = m_maxBrightnessValue; else if(val < 100) val = 100; QString command = "/usr/lib/ukui-greeter/greeter-backlight-helper --set-brightness " + QString::number(val); QProcess process; process.start(command); process.waitForFinished(3000); //QString result = process.readAll(); } ukui-screensaver/src/PhysicalDeviceSet/physical-device-set.pri0000644000175000017500000000041714205074704023513 0ustar fengfengHEADERS += \ $$PWD/brightnessdeviceset.h \ $$PWD/flightmodeset.h \ $$PWD/sounddeviceset.h \ $$PWD/touchscreenset.h SOURCES += \ $$PWD/brightnessdeviceset.cpp \ $$PWD/flightmodeset.cpp \ $$PWD/sounddeviceset.cpp \ $$PWD/touchscreenset.cpp ukui-screensaver/src/PhysicalDeviceSet/touchscreenset.h0000644000175000017500000000212114205074760022340 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef TOUCHSCREENSET_H #define TOUCHSCREENSET_H #include class TouchScreenSet : public QObject { Q_OBJECT public: TouchScreenSet *instance(QObject* parent = nullptr); void init(); int getTouchScreenID(); private: TouchScreenSet(QObject *parent = nullptr); }; #endif // TOUCHSCREENSET_H ukui-screensaver/src/PhysicalDeviceSet/flightmodeset.cpp0000644000175000017500000000225214205074760022500 0ustar fengfeng/** * Copyright (C) 2018 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, 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 "flightmodeset.h" bool FlightModeSet::m_isFlightModeOpen = false; FlightModeSet* FlightModeSet::instance(QObject *parent) { static FlightModeSet* _instance = nullptr; QMutex mutex; mutex.lock(); if(_instance == nullptr) _instance = new FlightModeSet(parent); mutex.unlock(); return _instance; } FlightModeSet::FlightModeSet(QObject *parent): QObject(parent) { } ukui-screensaver/src/PhysicalDeviceSet/brightnessdeviceset.h0000644000175000017500000000315414205074760023355 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef BRIGHTNESSDEVICESET_H #define BRIGHTNESSDEVICESET_H #include #include #include #include class BrightnessDeviceSet : public QObject { Q_OBJECT public: static BrightnessDeviceSet* instance(QObject *parent = nullptr); public Q_SLOTS: // val from 0 to 100 change void setValue(int value); int getValue(); private: BrightnessDeviceSet(QObject *parent = nullptr); void init(); bool isPowerSupply(); int getMaxBrightness(); int getCurBrightness(); // val from 0 to MaxBrightness change void setBrightness(int val); Q_SIGNALS: // val form to 100 change //void valueChanged(int val); private: static int m_value; static int m_maxBrightnessValue; static int m_curBrightnessValue; static bool m_isPowerSupply; }; #endif // BRIGHTNESSDEVICESET_H ukui-screensaver/src/PhysicalDeviceSet/flightmodeset.h0000644000175000017500000000260214205074760022144 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef FLIGHTMODESET_H #define FLIGHTMODESET_H /*! *@brief 设置飞行模式 * 本想在登录界面加载时 提供实体键 飞行模式的功能 * 后来发现有效。但是飞行模式具体设置是谁负责管理的 还未知。 * 最初实现的策略是通过 nmcli networking off 的方式设置飞行模式。 */ #include #include class FlightModeSet : public QObject { Q_OBJECT public: static FlightModeSet* instance(QObject *parent = nullptr); private: FlightModeSet(QObject *parent = nullptr); private: static bool m_isFlightModeOpen; }; #endif // FLIGHTMODESET_H ukui-screensaver/src/generalauthwidget.cpp0000644000175000017500000000146514205074704020000 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "generalauthwidget.h" GeneralAuthWidget::GeneralAuthWidget(QWidget *parent) : QWidget(parent) { } ukui-screensaver/src/digitalauthdialog.cpp0000644000175000017500000006340214205074704017753 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * Authors: ZHAI Kang-ning **/ #include "digitalauthdialog.h" #include #include #include #include #include #include #include "auth-pam.h" #include "permissioncheck.h" #include "eduplatforminterface.h" DigitalAuthDialog::DigitalAuthDialog(QWidget *parent) : QWidget(parent), m_bgColor("#000000"), //整个wigidt背景颜色 m_outCircleColor("#000000"), m_tipLineColor("#ff0000"), m_circleRingColor("#ddffff"), m_radius(40), m_margin(5), m_pressed(false), m_showText(true), m_inputPassword(""), m_circleColor("#ffffff"),//按钮的颜色 m_statusRadius(8), m_auth(new AuthPAM(this)), m_isAuthing(false), m_buttonWidth(96), m_buttonHeight(64), m_buttonRadius(16), m_buttonStep(16), m_resetPassword(""), m_resetOrAuthFailure(new QLabel(this)), m_digitalKeyBoard(new DigitalKeyBoard(this)) { //获取键盘事件 此操作会使得其他控件无法获取键盘事件,使用releaseKeyboard可释放 // grabKeyboard(); m_posInCircle.isIn = false; // qDebug() <<"-----------init width=" << width() << ",height=" << height(); m_title = new QLabel(tr("LoginByUEdu"), this); m_title->setStyleSheet("font-size:30px;color:#ffffff"); m_title->adjustSize(); m_labelReset = new MyLabel(tr("ResetPWD?"), this); m_labelReset->setStyleSheet("QLabel{font-size:16px;color:rgba(255, 255, 255, 45);}" "QLabel:hover{color:rgba(255, 255, 255, 100);}"); m_labelReset->adjustSize(); m_authMessage = new QLabel(this); m_authMessage->setStyleSheet("font-size:14px;color:#ffffff"); //设置字体大小 QFont f; f.setPixelSize(m_radius * 24/40); setFont(f); //调整适当的大小 resize(350,600); m_title->setGeometry((this->width() - m_title->width())/2, 6, m_title->width(), m_title->height()); m_labelReset->setGeometry((this->width()- m_labelReset->width())/2, this->height() - 120, m_labelReset->width(),m_labelReset->height()); setMouseTracking(true); connect(m_digitalKeyBoard, &DigitalKeyBoard::numbersButtonPress, this, &DigitalAuthDialog::onNumerPress); connect(m_auth, &Auth::showMessage, this, &DigitalAuthDialog::onShowMessage); connect(m_auth, &Auth::showPrompt, this, &DigitalAuthDialog::onShowPrompt); connect(m_auth, &Auth::authenticateComplete, this, &DigitalAuthDialog::onAuthComplete); connect(m_labelReset, &MyLabel::onClick, this, [=]{ // qDebug() << "-------------------onClick"; m_title->setText(tr("SetNewUEduPWD")); m_title->adjustSize(); m_resetOrAuthFailure->clear(); m_title->setGeometry((this->width() - m_title->width())/2, 5, m_title->width(), m_title->height()); m_inputPassword.clear(); m_loginType = LoginType::RESET; m_labelReset->hide(); // PermissionCheck *check = new PermissionCheck(this); // QVBoxLayout *v = new QVBoxLayout(this); // v->addWidget(check); // this->hide(); Q_EMIT requestPasswordReset(); }); // m_timer = new QTimer(this); // connect(m_timer,&QTimer::timeout,this,[=]{ // if(m_isAuthing) // { // qDebug() << "Auth respond timeout , restart"; // startAuth(); // } // }); m_digitalKeyBoard->move(9,143); } DigitalAuthDialog::~DigitalAuthDialog() { } void DigitalAuthDialog::onNumerPress(int btn_id) { qDebug() << btn_id; //nothing if(m_authMessage) cleanMessage(); if(m_resetOrAuthFailure) m_resetOrAuthFailure->clear(); m_pressed = true; if(m_isAuthing) { qWarning() << "authenticating"; return; } if(btn_id == 11) { //点击了清空按钮 m_inputPassword.clear(); } else if (btn_id == 10) { if (!m_inputPassword.isEmpty()) m_inputPassword.remove(m_inputPassword.size() -1, 1); } else { int num = btn_id; m_inputPassword.append(QString::number(num == 11 ? 0 : num)); if (m_inputPassword.size() >= 6) { checkPassword(); } } repaint(); } void DigitalAuthDialog::paintEvent(QPaintEvent *event) { int width = this->width(); int height = this->height(); int side = qMin(width, height); // qDebug() <<"-----------width=" << width << ",height=" << height << ",side=" << side; QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); painter.translate(width / 2, height / 2); painter.scale(side / 200, side / 200); // drawBg(&painter); drawStatusCircle(&painter); //// drawOutCircle(&painter); // drawFilledCircle(&painter); //// drawTipLine(&painter); // drawInCircle(&painter); //// drawJoinLine(&painter); // drawHoverCircle(&painter); } //画背景颜色 void DigitalAuthDialog::drawBg(QPainter *painter) { painter->save(); int width = this->width(); int height = this->height(); painter->setPen(Qt::NoPen); m_bgColor.setAlpha(0); painter->setBrush(m_bgColor); painter->drawRect(-width / 2, -height / 2, width, height); painter->restore(); } //绘制按钮的颜色 void DigitalAuthDialog::drawFilledCircle(QPainter *painter) { painter->save(); m_circleColor.setAlphaF(0.15); QPen pen(m_circleColor); painter->setPen(pen); painter->setBrush(m_circleColor); for (int i = 0; i < 4; i++) { for (int j = 0; j < 3; j++) { int x = -3 * (m_buttonWidth / 2) + j * m_buttonWidth + (j - 1) * m_buttonStep; int y = -2 * m_buttonHeight + i * m_buttonHeight + m_buttonStep * i - 3 * (m_buttonStep / 2); QRect rect(x, y, m_buttonWidth, m_buttonHeight); // painter->drawEllipse(rect); painter->drawRoundedRect(rect, m_buttonRadius, m_buttonRadius); if (m_showText) { painter->save(); painter->setPen(QColor("#ffffff")); painter->setBrush(QColor("#ffffff")); int number = posToNumber(i, j); if (number == 11) { number = 0; } else if(number == 10) { // 数字10的地方是清空按钮 x = (j - 1) * m_buttonWidth + (j - 1) * m_buttonStep;; y = -3 * (m_buttonHeight / 2) + i * m_buttonHeight + m_buttonStep * i - 3 * (m_buttonStep / 2); QString text = tr("clear"); int textWidth = fontMetrics().width(text); QFont font = painter->font(); font.setPixelSize(m_radius * 20/40); painter->setFont(font); painter->drawText(x - textWidth / 2 + 3, y + textWidth / 2 - 18, text); painter->restore(); continue; } else if (number == 12) { // 画删除符号(3,2) x = m_buttonWidth / 2 + m_buttonStep; y = m_buttonHeight + 3 * (m_buttonStep / 2); painter->drawPixmap(x + m_buttonWidth/2 - 15,y + m_buttonHeight/2 - 15, QPixmap(":/image/assets/intel/delete.svg")); painter->restore(); continue; } QString text = QString::number(number); x = (j - 1) * m_buttonWidth + (j - 1) * m_buttonStep;; y = -3 * (m_buttonHeight / 2) + i * m_buttonHeight + m_buttonStep * i - 3 * (m_buttonStep / 2); int textWidth = fontMetrics().width(text); int textHeight = fontMetrics().height(); painter->drawText(x - textWidth / 2, y + textWidth / 2 + 4, text); painter->restore(); } } } painter->restore(); } //画外圆 void DigitalAuthDialog::drawOutCircle(QPainter *painter) { painter->save(); QPen pen(m_outCircleColor, 2); painter->setPen(pen); painter->setBrush(Qt::NoBrush); for (int i = 0; i < 4; i++) { for (int j = 0; j < 3; j++) { int x = -3 * (m_buttonWidth / 2) + j * m_buttonWidth + (j - 1) * m_buttonStep; int y = -2 * m_buttonHeight + i * m_buttonHeight + m_buttonStep * i - 3 * (m_buttonStep / 2); QRect rect(x, y, m_buttonWidth, m_buttonHeight); // painter->drawEllipse(rect); painter->drawRoundedRect(rect, m_buttonRadius, m_buttonRadius); // painter->drawEllipse(x, y, m_radius * 2, m_radius * 2); if (m_showText) { int number = posToNumber(i, j); QString text = QString::number(number); x = -2 * m_radius + j * 2 * m_radius + (j - 1) * 16; y = -3 * m_radius + i * 2 * m_radius + 16 * i - 24; int textWidth = fontMetrics().width(text); int textHeight = fontMetrics().height(); painter->drawText(x - textWidth / 2, y + textWidth / 2, text); } } } painter->restore(); } void DigitalAuthDialog::drawTipLine(QPainter *painter) { painter->save(); int offset = 3; if (m_posInCircle.isIn) { if (!m_pressed) { painter->setPen(m_tipLineColor); painter->setBrush(Qt::NoBrush); int x = -3 * (m_buttonWidth / 2) + m_posInCircle.j * m_buttonWidth + (m_posInCircle.j - 1) * m_buttonStep - offset; int y = -2 * m_buttonHeight + m_posInCircle.i * m_buttonHeight + m_buttonStep * m_posInCircle.i - 3 * (m_buttonStep / 2) - offset; QRect rect(x, y, m_buttonWidth, m_buttonHeight); painter->drawRoundedRect(rect, m_buttonRadius, m_buttonRadius); } } painter->restore(); } //绘制点击时的颜色 void DigitalAuthDialog::drawInCircle(QPainter *painter) { painter->save(); if (m_pressed) { if (m_posInCircle.isIn) { m_circleColor.setAlphaF(0.05); painter->setPen(m_circleColor); painter->setBrush(m_circleColor); int x = -3 * (m_buttonWidth / 2) + m_posInCircle.j * m_buttonWidth + (m_posInCircle.j - 1) * m_buttonStep; int y = -2 * m_buttonHeight + m_posInCircle.i * m_buttonHeight + m_buttonStep * m_posInCircle.i - 3 * (m_buttonStep / 2); int w = m_buttonWidth; int h = m_buttonHeight; QRect rect = QRect(x, y, w, h); painter->drawRoundedRect(rect, m_buttonRadius, m_buttonRadius); } } painter->restore(); } //绘制悬浮时的颜色 void DigitalAuthDialog::drawHoverCircle(QPainter *painter) { painter->save(); if (!m_pressed) { if (m_posInCircle.isIn) { m_circleColor.setAlphaF(0.35); painter->setPen(m_circleColor); painter->setBrush(m_circleColor); int x = -3 * (m_buttonWidth / 2) + m_posInCircle.j * m_buttonWidth + (m_posInCircle.j - 1) * m_buttonStep; int y = -2 * m_buttonHeight + m_posInCircle.i * m_buttonHeight + m_buttonStep * m_posInCircle.i - 3 * (m_buttonStep / 2); int w = m_buttonWidth; int h = m_buttonHeight; QRect rect = QRect(x, y, w, h); painter->drawRoundedRect(rect, m_buttonRadius, m_buttonRadius); } } painter->restore(); } void DigitalAuthDialog::drawJoinLine(QPainter *painter) { painter->save(); QPen pen(m_outCircleColor, 3); painter->setPen(pen); //绘制连接线段 for (int i = 0; i < m_vecInputPoints.count() - 1; i++) { painter->drawLine(m_vecInputPoints[i], m_vecInputPoints[i + 1]); } int offset1 = 1;//圆环偏移量 int offset2 = 3;//内圆偏移量 //绘制连接圆 for (int i = 0; i < m_vecInputPoints.count(); i++) { int x = m_vecInputPoints[i].x() - m_radius + offset1; int y = m_vecInputPoints[i].y() - m_radius + offset1; int w = 2 * (m_radius - offset1); int h = 2 * (m_radius - offset1); painter->setPen(m_circleRingColor); painter->setBrush(m_circleRingColor); painter->drawEllipse(x, y, w, h); x = m_vecInputPoints[i].x() - m_radius + offset2; y = m_vecInputPoints[i].y() - m_radius + offset2; w = 2 * (m_radius - offset2); h = 2 * (m_radius - offset2); painter->setPen(m_outCircleColor); painter->setBrush(m_outCircleColor); painter->drawEllipse(x, y, w, h); } //绘制跟随线 if (m_pressed && m_vecInputPoints.count() < 9) { int width = this->width(); int height = this->height(); int side = qMin(width, height); int gestureScale = side / 200; int x = (m_followPoint.x() - width / 2) / gestureScale; int y = (m_followPoint.y() - height / 2) / gestureScale; if (m_vecInputPoints.count() > 0) { painter->setPen(pen); painter->drawLine(m_vecInputPoints.last(), QPoint(x, y)); } } painter->restore(); } void DigitalAuthDialog::mouseMoveEvent(QMouseEvent *event) { // bool temp = false; // //nothing // int x = (event->x() - this->width()/2) / (qMin(width(), height())/200); // int y = (event->y() - this->height()/2) / (qMin(width(), height())/200); // for (int i = 0; i < 4; i++) // { // for (int j = 0; j < 3; j++) // { // int x1 = -3 * (m_buttonWidth / 2) + j * m_buttonWidth + (j - 1) * m_buttonStep; // int y1 = -2 * m_buttonHeight + i * m_buttonHeight + m_buttonStep * i - 3 * (m_buttonStep / 2); // if (isInButtonArea(x, y, x1, y1)) // { // m_posInCircle.i = i; // m_posInCircle.j = j; // m_posInCircle.isIn = true; // temp = true; // repaint(); // } // } // } // if (!temp) // { // m_posInCircle.isIn = false; // repaint(); // } } void DigitalAuthDialog::mousePressEvent(QMouseEvent *event) { //nothing // if(m_authMessage) // cleanMessage(); // if(m_resetOrAuthFailure) // m_resetOrAuthFailure->clear(); // m_pressed = true; // int x = (event->x() - this->width()/2) / (qMin(width(), height())/200); // int y = (event->y() - this->height()/2) / (qMin(width(), height())/200); // for (int i = 0; i < 4; i++) // { // for (int j = 0; j < 3; j++) // { // int x1 = -3 * (m_buttonWidth / 2) + j * m_buttonWidth + (j - 1) * m_buttonStep; // int y1 = -2 * m_buttonHeight + i * m_buttonHeight + m_buttonStep * i - 3 * (m_buttonStep / 2); // if (isInButtonArea(x, y, x1, y1)) // { // if(m_isAuthing) // { // qWarning() << "authenticating"; // return; // } // m_posInCircle.i = i; // m_posInCircle.j = j; // m_posInCircle.isIn = true; // if(posToNumber(i, j) == 10) // { // //点击了清空按钮 // m_inputPassword.clear(); // } else if (posToNumber(i, j) == 12) // { // if (!m_inputPassword.isEmpty()) // m_inputPassword.remove(m_inputPassword.size() -1, 1); // } else { // int num = posToNumber(i,j); // m_inputPassword.append(QString::number(num == 11 ? 0 : num)); // if (m_inputPassword.size() >= 6) // { // checkPassword(); // } //// qDebug() << "---------------选中了"<< posToNumber(i,j); // } // repaint(); // } // } // } } void DigitalAuthDialog::mouseReleaseEvent(QMouseEvent *event) { // //nothing // m_pressed = false; // //m_posInCircle.isIn = false; // repaint(); } ////监听键盘输入 void DigitalAuthDialog::keyPressEvent(QKeyEvent *event) { qDebug() << "keyPressEvent " << event->key(); if (m_isAuthing) { qWarning() << "authenticating"; return; } if(event->key() == Qt::Key_Backspace) { if (!m_inputPassword.isEmpty()) m_inputPassword.remove(m_inputPassword.size() -1, 1); } else if (event->key() >= Qt::Key_0 && event->key() <= Qt::Key_9 ) { if(m_resetOrAuthFailure) m_resetOrAuthFailure->clear(); m_inputPassword.append(event->text()); if (m_inputPassword.size() >= 6) { checkPassword(); m_inputPassword.clear(); } } else { return; } repaint(); } ////监听键盘输入 //void DigitalAuthDialog::RecieveKey(int key) //{ // qDebug() << "keyPressEvent " << key; // if (m_isAuthing) // { // qWarning() << "authenticating"; // return; // } // if(key == 10) // { // if (!m_inputPassword.isEmpty()) // m_inputPassword.remove(m_inputPassword.size() -1, 1); // } else if (key >= 0 && key <= 9 ) // { // if(m_resetOrAuthFailure) // m_resetOrAuthFailure->clear(); // m_inputPassword.append(QString::number(key)); // if (m_inputPassword.size() >= 6) // { // checkPassword(); // m_inputPassword.clear(); // } // } else { // return; // } // repaint(); //} double DigitalAuthDialog::distance(int x1, int y1, int x2, int y2) { //nothing double x = x1 - x2; double y = y1 - y2; return sqrt(x*x + y*y); } int DigitalAuthDialog::posToNumber(int i, int j) { //nothing return ((3*i) + j +1); } void DigitalAuthDialog::setPassword(const QString password) { //ToDo Q_EMIT setPinCode(password); } QString DigitalAuthDialog::getPassword() { //nothing } bool DigitalAuthDialog::checkPassword() { if(m_loginType == LoginType::AUTHENTICATE) { m_password = m_inputPassword; qDebug() << "Input finished" << m_password; m_auth->respond(m_password); m_isAuthing = true; // m_timer->start(5000); // onShowMessage(tr("now is authing, wait a moment"), Auth::MessageTypeInfo); } else if (m_loginType == LoginType::RESET) { m_resetPassword = m_inputPassword; m_title->setText(tr("ConfirmNewUEduPWD")); m_title->adjustSize(); m_title->setGeometry((this->width() - m_title->width())/2, 5, m_title->width(), m_title->height()); m_inputPassword.clear(); m_loginType = LoginType::SECONDCONFIRMATION; Q_EMIT switchToReset(false); } else if (m_loginType == LoginType::SECONDCONFIRMATION) { if (m_resetPassword == m_inputPassword) { setPassword(m_resetPassword); } else { m_resetOrAuthFailure->setText(tr("The two password entries are inconsistent, please reset")); m_resetOrAuthFailure->setStyleSheet("font-size:14px;color:rgba(255, 255, 255, 255)"); m_resetOrAuthFailure->adjustSize(); m_resetOrAuthFailure->setGeometry((this->width()- m_resetOrAuthFailure->width())/2, 120, m_resetOrAuthFailure->width(),m_resetOrAuthFailure->height()); showResetPasswordPage(); Q_EMIT switchToReset(true); } } return false; } //画密码状态的圆圈 void DigitalAuthDialog::drawStatusCircle(QPainter *painter) { painter->save(); m_circleColor.setAlphaF(0.45); QPen pen(m_circleColor, 2); painter->setPen(pen); painter->setBrush(Qt::NoBrush); for(int i = 0; i < 6; i++) { int x = -11 * m_statusRadius + i * 4 * m_statusRadius; int y = -2 * m_buttonHeight - (11 * m_buttonStep) / 2; if (i < m_inputPassword.size()) { painter->save(); painter->setBrush(QColor("#ffffff")); QRect rect(x, y, 2 * m_statusRadius, 2 * m_statusRadius); painter->drawEllipse(rect); painter->restore(); } else { painter->drawEllipse(x, y, 2 * m_statusRadius, 2 * m_statusRadius); } } painter->restore(); } void DigitalAuthDialog::onShowMessage(const QString &message, Auth::MessageType type) { m_authMessage->setText(message); m_authMessage->adjustSize(); m_authMessage->setGeometry((this->width()-m_authMessage->width())/2, this->height() -20, m_authMessage->width(),m_authMessage->height()); } void DigitalAuthDialog::cleanMessage() { m_authMessage->clear(); } void DigitalAuthDialog::onShowPrompt(const QString &prompt, Auth::PromptType type) { qDebug() << "prompt: " << prompt; } void DigitalAuthDialog::onAuthComplete() { qDebug() << "Auth Complete"; // m_timer->stop(); DBusMsgCode errcode = EduPlatformInterface::getInstance()->CheckToken(getenv("USER")); if(m_auth->isAuthenticated()) { /* DBusMsgCode errcode = EduPlatformInterface::getInstance()->CheckToken(getenv("USER")); if(DBusMsgCode::Error_AccessTokenInvalid == errcode){ m_resetOrAuthFailure->setText(tr("登录状态已过期,请重新扫码登录")); m_resetOrAuthFailure->setStyleSheet("font-size:14px;color:rgba(255, 255, 255, 255)"); m_resetOrAuthFailure->adjustSize(); m_resetOrAuthFailure->setGeometry((this->width()- m_resetOrAuthFailure->width())/2, 120, m_resetOrAuthFailure->width(),m_resetOrAuthFailure->height()); startAuth(); m_inputPassword.clear(); m_password.clear(); m_isAuthing = false; repaint(); return; } */ Q_EMIT authenticateCompete(true); m_isAuthing = false; } else { qWarning() << "auth failed"; if(m_loginType == LoginType::AUTHENTICATE) { m_resetOrAuthFailure->setText(tr("Password entered incorrectly, please try again")); m_resetOrAuthFailure->setStyleSheet("font-size:14px;color:rgba(255, 255, 255, 255)"); m_resetOrAuthFailure->adjustSize(); m_resetOrAuthFailure->setGeometry((this->width()- m_resetOrAuthFailure->width())/2, 120, m_resetOrAuthFailure->width(),m_resetOrAuthFailure->height()); } //认证失败,重新认证 startAuth(); } m_inputPassword.clear(); m_password.clear(); m_isAuthing = false; repaint(); } void DigitalAuthDialog::startAuth() { m_inputPassword.clear(); m_password.clear(); m_auth->authenticate(getenv("USER")); m_isAuthing = false; repaint(); } void DigitalAuthDialog::stopAuth() { m_isAuthing = false; } void DigitalAuthDialog::startWaiting() { } void DigitalAuthDialog::stopWaiting() { } void DigitalAuthDialog::closeEvent(QCloseEvent *event) { qDebug() << "DigitalAuthDialog::closeEvent"; if(m_auth && m_auth->isAuthenticating()) { m_auth->stopAuth(); } return QWidget::closeEvent(event); } bool DigitalAuthDialog::isInButtonArea(int x1, int y1, int x2, int y2) { if (x1 >= x2 && x1 <= (x2 + m_buttonWidth) && y1 >= y2 && y1 <= (y2 + m_buttonHeight)) return true; return false; } void DigitalAuthDialog::reset() { m_title->setText(tr("LoginByUEdu")); m_title->adjustSize(); m_title->setGeometry((this->width() - m_title->width())/2, 5, m_title->width(), m_title->height()); m_labelReset->show(); m_inputPassword.clear(); m_resetPassword.clear(); m_loginType = LoginType::AUTHENTICATE; repaint(); } /** * @brief DigitalAuthDialog::showResetPasswordPage * 重新展示重置密码页 */ void DigitalAuthDialog::showResetPasswordPage() { m_title->setText(tr("SetNewUEduPWD")); m_title->adjustSize(); m_title->setGeometry((this->width() - m_title->width())/2, 5, m_title->width(), m_title->height()); m_loginType = LoginType::RESET; m_resetPassword.clear(); m_inputPassword.clear(); repaint(); Q_EMIT switchToReset(true); } int DigitalAuthDialog::getStatus() { return m_loginType; } void DigitalAuthDialog::showErrorMessage(QString message) { m_resetOrAuthFailure->setText(message); m_resetOrAuthFailure->setStyleSheet("font-size:14px;color:rgba(255, 255, 255, 255)"); m_resetOrAuthFailure->adjustSize(); m_resetOrAuthFailure->setGeometry((this->width()- m_resetOrAuthFailure->width())/2, 120, m_resetOrAuthFailure->width(),m_resetOrAuthFailure->height()); QTimer::singleShot(3000,[=](){ m_resetOrAuthFailure->clear(); }); } MyLabel::MyLabel(const QString & text,QWidget *parent) : QLabel(parent) { setText(text); } MyLabel::MyLabel(QWidget *parent) : QLabel(parent) { } void MyLabel::mousePressEvent(QMouseEvent *event) { //Qt::LeftButton //Qt::RightButton if(event->button()== Qt::LeftButton) { this->setStyleSheet("QLabel{font-size:16px;color:rgba(255, 255, 255, 0.45);}"); } } void MyLabel::mouseReleaseEvent(QMouseEvent *event) { //Qt::LeftButton //Qt::RightButton if(event->button()== Qt::LeftButton) { this->setStyleSheet("QLabel{font-size:16px;color:rgba(255, 255, 255, 0.35);}" "QLabel:hover{color:rgba(255, 255, 255, 1);}"); Q_EMIT onClick(); } } ukui-screensaver/src/iconedit.cpp0000644000175000017500000001554114205074704016073 0ustar fengfeng/* iconedit.cpp * Copyright (C) 2018 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, 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 "iconedit.h" #include #include #include #include #include #include #include #include #include #include /** * @brief 判断大写键状态 * @return true: 大写锁定 */ bool checkCapsLockState() { bool capsState = false; unsigned int n; XkbGetIndicatorState(QX11Info::display(), XkbUseCoreKbd, &n); capsState = (n & 0x01) == 1; return capsState; } IconEdit::IconEdit(QWidget *parent) : QWidget(parent), m_timer(nullptr) { m_edit = new QLineEdit(this); m_edit->setObjectName(QStringLiteral("passwdEdit")); m_edit->setAttribute(Qt::WA_InputMethodEnabled, false); //禁用输入法 m_edit->setContextMenuPolicy(Qt::NoContextMenu); //禁用右键菜单 m_edit->installEventFilter(this); m_capsIcon = new QLabel(this); m_capsIcon->setObjectName(QStringLiteral("capsIconLabel")); m_capsIcon->setVisible(checkCapsLockState()); m_iconButton = new QPushButton(this); m_iconButton->setObjectName(QStringLiteral("loginButton")); m_iconButton->setFocusPolicy(Qt::NoFocus); m_iconButton->setCursor(QCursor(Qt::PointingHandCursor)); m_iconButton->installEventFilter(this); m_modeButton = new QPushButton(this); m_modeButton->setObjectName(QStringLiteral("echoModeButton")); m_modeButton->setCheckable(true); m_modeButton->setFocusPolicy(Qt::NoFocus); m_modeButton->setCursor(Qt::PointingHandCursor); connect(m_modeButton, &QPushButton::clicked, this, [&](bool checked){ setType(checked ? QLineEdit::Normal : QLineEdit::Password); }); QHBoxLayout *layout = new QHBoxLayout(this); layout->setContentsMargins(1, 1, 1, 1); layout->setSpacing(0); layout->addStretch(); layout->addWidget(m_capsIcon); layout->addWidget(m_modeButton); layout->addWidget(m_iconButton); connect(m_edit, &QLineEdit::returnPressed, this, &IconEdit::clicked_cb); connect(m_iconButton, &QPushButton::clicked, this, &IconEdit::clicked_cb); setFocusProxy(m_edit); } void IconEdit::setType(QLineEdit::EchoMode type) { m_edit->setEchoMode(type); if(type == 0) m_modeButton->setChecked(true); else m_modeButton->setChecked(false); } void IconEdit::resizeEvent(QResizeEvent *) { // 设置输入框中文件输入区,不让输入的文字在被隐藏在按钮下 m_edit->setTextMargins(1, 1, m_iconButton->width() + m_modeButton->width(), 1); m_edit->setFixedSize(size()); } bool IconEdit::eventFilter(QObject *obj, QEvent *event) { if(obj == m_edit){ if(event->type() == 6){ //禁止复制粘贴功能。 QKeyEvent *keyEvent = static_cast(event); if(keyEvent->matches(QKeySequence::Copy) || keyEvent->matches(QKeySequence::Cut) || keyEvent->matches(QKeySequence::Paste)){ event->ignore(); return true; }else if((keyEvent->modifiers() & Qt::MetaModifier) || (keyEvent->modifiers() & Qt::AltModifier)){//当meta或者alt键被按下时,忽略按键事件 event->ignore(); return true; } } if(event->type() == 23) { XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); update(); }else if(event->type() == QEvent::MouseButtonPress){ XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); update(); } } if(obj == m_iconButton){ if(m_timer && m_timer->isActive()) { return false; } if(event->type() == QEvent::HoverEnter){ setIcon(QIcon(":/image/assets/unlock-button-hover.png")); } else if(event->type() == QEvent::HoverLeave){ setIcon(QIcon(":/image/assets/unlock-button.png")); } } return false; } void IconEdit::setX11Focus() { XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); update(); } void IconEdit::clicked_cb() { startWaiting(); emit clicked(m_edit->text()); } void IconEdit::onCapsStateChanged() { bool capsState = m_capsIcon->isHidden(); m_capsIcon->setVisible(capsState); int w = m_iconButton->width() + m_modeButton->width(); m_edit->setTextMargins(1, 1, capsState ? w + m_capsIcon->width() : w, 1); } void IconEdit::setIcon(const QString &text) { m_iconButton->setIcon(QIcon()); m_iconButton->setText(text); m_iconText = text; m_icon = QIcon(); } void IconEdit::setIcon(const QIcon &icon) { m_iconButton->setIcon(icon); m_iconButton->setText(""); m_icon = icon; m_iconText = ""; } void IconEdit::clear() { m_edit->setText(""); setPrompt(""); } void IconEdit::clearText() { m_edit->setText(""); } void IconEdit::setPrompt(const QString &prompt) { m_edit->setPlaceholderText(prompt); } const QString IconEdit::text() { return m_edit->text(); } void IconEdit::startWaiting() { m_edit->setReadOnly(true); m_iconButton->setEnabled(false); if(!m_timer) { m_timer = new QTimer(this); m_timer->setInterval(120); connect(m_timer, &QTimer::timeout, this, &IconEdit::updatePixmap); } m_waitingPixmap.load(":/image/assets/waiting.png"); m_iconButton->setIconSize(m_iconButton->size()); m_iconButton->setIcon(QIcon(m_waitingPixmap)); m_timer->start(); } void IconEdit::stopWaiting() { if(m_timer && m_timer->isActive()) { m_timer->stop(); } m_edit->setReadOnly(false); m_iconButton->setEnabled(true); if(!m_icon.isNull()) m_iconButton->setIcon(m_icon); else m_iconButton->setText(m_iconText); } void IconEdit::updatePixmap() { QMatrix matrix; matrix.rotate(90.0); m_waitingPixmap = m_waitingPixmap.transformed(matrix, Qt::FastTransformation); m_iconButton->setIcon(QIcon(m_waitingPixmap)); } /* void IconEdit::setEnabled(bool enabled) { m_edit->setAttribute(Qt::WA_InputMethodEnabled, false); m_edit->setEnabled(enabled); m_iconButton->setEnabled(enabled); } */ ukui-screensaver/src/permissioncheck.h0000644000175000017500000000611114205074760017123 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef PERMISSIONCHECK_H #define PERMISSIONCHECK_H #include #include #include #include #include "wechatauthdialog.h" #include "common.h" class InputInfos; class PhoneAuthWidget; class InputInfos : public QWidget { Q_OBJECT public: enum InputState{ InputWaiting , InputFinish }; InputInfos(QWidget *parent = nullptr); QString getPhoneNumer(); QString getVerificationCode(); void clearInfos(); Q_SIGNALS: void getVerCode(); void InputStateChanged(InputState input_state); protected: void paintEvent(QPaintEvent *); private Q_SLOTS: void onPhoneTextChanged(const QString &text); void onVerCodeTextChanged(const QString &text); void onGetVerCode(); void onNextGetVerCodeTimer(); private: void initUI(); void initConnect(); void setQSS(); private: QLabel *m_pPhoneIconLB; QLineEdit *m_pPhoneLE; QLabel *m_pVerCodeIconLB; QLineEdit *m_pVerCodeLE; QPushButton *m_pGetVerCodeBT; QTimer *m_pNextGetVerCodeQTimer; int m_nextGetVerCodeTime; InputState m_curInputState; }; class VerificationWidget : public QWidget { Q_OBJECT public: explicit VerificationWidget(QWidget *parent = nullptr); Q_SIGNALS: void pageMessage(SwitchPage id, QList argvs); private: QLabel *m_titleLB; QLabel *m_phonePromptMsgLB; WeChatAuthDialog *m_weChatWidget; //public: PhoneAuthWidget *m_phoneAuthWidget; protected: void paintEvent(QPaintEvent *); }; class PhoneAuthWidget : public QWidget { Q_OBJECT public: PhoneAuthWidget(QWidget* parent = nullptr); QSize sizeHint() const; private: void initUI(); void initConnect(); void setQSS(); void showPhoneErrorMsg(); void hidePhoneErrorMsg(); Q_SIGNALS: void pageMessage(SwitchPage id, QList argvs); private Q_SLOTS: void onInputStateChanged(InputInfos::InputState input_state); void onSubmitBTClick(); void onGetVerCode(); void onQRCodeStateChanged(QString username, QString password, int nState); private: // 手机号验证 QLabel *m_pPhoTitleLB; QLabel *m_pPhoPromptMsgLB; QLabel *m_pPhoErrorMsgLB; QLabel *m_pPhoErrorMsgCloneLB; // 控制格式 QPushButton *m_pPhoSubmitBT; InputInfos *m_pPhoInputInfos; }; #endif // PERMISSIONCHECK_H ukui-screensaver/src/ukui-screensaver-dialog.cpp0000644000175000017500000002460314205074704021024 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "fullbackgroundwidget.h" #include "configuration.h" #define CACHE_DIR "/.cache/ukui-screensaver/" #define DOUBLE 2 #define MAX_FILE_SIZE 1024 * 1024 #define LOG_FILE0 "screensaver_0.log" #define LOG_FILE1 "screensaver_1.log" #define GSETTINGS_SCHEMA_SCREENSAVER "org.ukui.screensaver" #define KEY_LOCK_ENABLED "lock-enabled" FullBackgroundWidget *window = NULL; static void messageOutput(QtMsgType type, const QMessageLogContext &context,const QString &msg); void checkIslivecd() { char cmd[128] = {0}; char str[1024]; FILE *fp; int n = sprintf(cmd, "cat /proc/cmdline"); Q_UNUSED(n) fp = popen(cmd, "r"); while(fgets(str, sizeof(str)-1, fp)) { if(strstr(str,"boot=casper")) { printf("is livecd\n"); exit(0); } } pclose(fp); QString filepath = QDir::homePath() + "/Desktop" + "/kylin-os-installer.desktop"; QFileInfo file(filepath); if(!file.exists()) return; if(getuid() != 999) return; exit(0); } void checkIsRunning() { int fd, len; char buf[32]; struct flock lock; const QString PID_DIR = QString("/var/run/user/%1").arg(QString::number(getuid())); QString env = qgetenv("DISPLAY"); const QString PID_FILE = PID_DIR + QString("/ukui-screensaver%1.pid").arg(env); qDebug() << PID_DIR; QDir dir(PID_DIR); if(!dir.exists()) { if(!dir.mkdir(PID_DIR.toLocal8Bit().data())) { perror("create pid directory failed"); exit(1); } } if( (fd = open(PID_FILE.toLocal8Bit().data(), O_RDWR | O_CREAT, 0666)) == -1){ perror("open pid file failed"); exit(1); } memset(&lock, 0, sizeof(struct flock)); lock.l_type = F_WRLCK; lock.l_whence = SEEK_SET; if(fcntl(fd, F_SETLK, &lock) < 0) { // perror("fcntl F_SETLK failed"); printf("There is already an instance running\n"); exit(1); } len = snprintf(buf, sizeof(buf), "%d", getpid()); ftruncate(fd, 0); if(write(fd, buf, len) != len) { perror("write pid to lock file failed"); exit(1); } } void handler(int signum) { window->closeScreensaver(); } #define WORKING_DIRECTORY "/usr/share/ukui-screensaver" int main(int argc, char *argv[]) { if(argc < 2) return 0; checkIsRunning(); checkIslivecd(); if(QString(argv[1]) == "--lock-startup"){ Configuration::instance(); QDBusInterface *checkInterface = new QDBusInterface("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", QDBusConnection::sessionBus()); for(int i = 0;i<20;i++){ QDBusReply ret = checkInterface->call("NameHasOwner", "org.gnome.SessionManager"); if(ret.value()) { break; } usleep(100000); } } #if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0)) QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); #endif #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)) QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); #endif qunsetenv("QT_IM_MODULE"); //signal(SIGTERM,handler); QApplication a(argc, argv); QApplication::setSetuidAllowed(true); QDesktopWidget *desktop = QApplication::desktop(); if(desktop->geometry().width()<=0 || desktop->geometry().height()<=0) return 0; //命令行参数解析 QCommandLineParser parser; parser.setApplicationDescription(QCoreApplication::translate("main", "Dialog for the ukui ScreenSaver.")); parser.addHelpOption(); parser.addVersionOption(); QCommandLineOption lockOption(QStringLiteral("lock"), QCoreApplication::translate("main", "lock the screen immediately")); QCommandLineOption lstOption(QStringLiteral("lock-startup"), QCoreApplication::translate("main", "lock the screen immediately")); QCommandLineOption sessionIdleOption(QStringLiteral("session-idle"), QCoreApplication::translate("main", "activated by session idle signal")); QCommandLineOption lscreensaverOption(QStringLiteral("lock-screensaver"), QCoreApplication::translate("main", "lock the screen and show screensaver immediately")); QCommandLineOption screensaverOption(QStringLiteral("screensaver"), QCoreApplication::translate("main", "show screensaver immediately")); QCommandLineOption blankOption(QStringLiteral("blank"), QCoreApplication::translate("main", "lock the screen and show screensaver immediately")); parser.addOptions({lockOption, lstOption,sessionIdleOption , screensaverOption,blankOption,lscreensaverOption}); parser.process(a); if(!parser.isSet(sessionIdleOption) && !parser.isSet(lockOption) && !parser.isSet(lstOption) && !parser.isSet(screensaverOption) && !parser.isSet(lscreensaverOption) && !parser.isSet(blankOption)) { return 0; } qInstallMessageHandler(messageOutput); //加载翻译文件 QString locale = QLocale::system().name(); QTranslator translator; QString qmFile = QString(WORKING_DIRECTORY"/i18n_qm/%1.qm").arg(locale); translator.load(qmFile); a.installTranslator(&translator); qDebug() << "load translation file " << qmFile; window = new FullBackgroundWidget(); QFile qssFile(":/qss/assets/authdialog.qss"); if(qssFile.open(QIODevice::ReadOnly)) { a.setStyleSheet(qssFile.readAll()); } qssFile.close(); if(parser.isSet(blankOption)) { window->onBlankScreensaver(); } #ifndef USE_INTEL window->show(); window->activateWindow(); #endif if(parser.isSet(lockOption)) { window->lock(); } if(parser.isSet(lstOption)) { window->lock(); window->setIsStartup(true); } if(parser.isSet(sessionIdleOption)) { if(window->onSessionStatusChanged(SESSION_IDLE) == -1) return 0; } if(parser.isSet(lscreensaverOption)) { window->onScreensaver(); } /* if(parser.isSet(blankOption)) { window->onBlankScreensaver(); } */ if(parser.isSet(screensaverOption)) { window->showScreensaver(); } #ifdef USE_INTEL window->show(); window->activateWindow(); #endif QString username = getenv("USER"); int uid = getuid(); QDBusInterface *interface = new QDBusInterface("cn.kylinos.Kydroid2", "/cn/kylinos/Kydroid2", "cn.kylinos.Kydroid2", QDBusConnection::systemBus(), window); QDBusMessage msg = interface->call(QStringLiteral("SetPropOfContainer"),username, uid, "is_kydroid_on_focus", "0"); return a.exec(); } static void messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) { Q_UNUSED(context) QDateTime dateTime = QDateTime::currentDateTime(); QByteArray time = QString("[%1] ").arg(dateTime.toString("MM-dd hh:mm:ss.zzz")).toLocal8Bit(); QByteArray localMsg = msg.toLocal8Bit(); QString name[DOUBLE] = {LOG_FILE0, LOG_FILE1}; FILE *log_file = nullptr; QString logFilePath; int fileSize; static int i = 0; QDir dir; if (dir.mkpath(QDir::homePath() + CACHE_DIR)) { logFilePath = QDir::homePath() + CACHE_DIR + "/" + name[i]; log_file = fopen(logFilePath.toLocal8Bit().constData(), "a+"); } QString filePath(context.file); int separator = filePath.lastIndexOf('/'); QString fileName = filePath.right(filePath.length() - separator - 1); const char *file = fileName.toLocal8Bit().data(); switch(type) { case QtDebugMsg: fprintf(log_file? log_file:stderr, "%s Debug: %s:%u: %s\n", time.constData(), file, context.line, localMsg.constData()); break; case QtInfoMsg: fprintf(log_file? log_file:stderr, "%s Info: %s:%u: %s\n", time.constData(), file, context.line, localMsg.constData()); break; case QtWarningMsg: fprintf(log_file? log_file:stderr, "%s Warnning: %s:%u: %s\n", time.constData(), file, context.line, localMsg.constData()); break; case QtCriticalMsg: fprintf(log_file? log_file:stderr, "%s Critical: %s:%u: %s\n", time.constData(), file, context.line, localMsg.constData()); break; case QtFatalMsg: fprintf(log_file? log_file:stderr, "%s Fatal: %s:%u: %s\n", time.constData(), file, context.line, localMsg.constData()); abort(); } fflush(stderr); if (log_file) { fileSize = ftell(log_file); if (fileSize >= MAX_FILE_SIZE) { i = (i + 1) % DOUBLE; logFilePath = QDir::homePath() + logFilePath + "/" + name[i]; if (QFile::exists(logFilePath)) { QFile temp(logFilePath); temp.remove(); } } fclose(log_file); } } ukui-screensaver/src/gestureauthdialog.cpp0000644000175000017500000003053614205074704020016 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * Authors: ZHAI Kang-ning **/ #include "gestureauthdialog.h" #include #include #include #include #include #include int gestureScale = 1; /** * @author zhaikangning * @date 2020/09/15 * 手势密码页 * 功能未完善 未对接pam * 未来进化 所有登录均继承认证父类 该父类含有密码校验等基本功能 */ GestureAuthDialog::GestureAuthDialog(QWidget *parent) : QWidget(parent), m_bgColor("#000000"), m_outCircleColor("#fff333"), m_tipLineColor("#ff0000"), m_circleRingColor("#ddffff"), m_radius(20), m_margin(5), m_pressed(false), m_showText(true), m_inputPassword(""), m_is_set_password(false), m_is_check_password(false) { m_posInCircle.isIn = false; qDebug() <<"-----------init width=" << width() << ",height=" << height(); m_set_password = new QPushButton(this); m_set_password->setGeometry(0,0,m_set_password->width(),m_set_password->height()); m_set_password->setText("设置密码"); connect(m_set_password, &QPushButton::clicked,this, [=] { m_chech_result->setText("请输入密码"); m_is_set_password = true; }); m_unlock = new QPushButton(this); m_unlock->setText("解锁"); m_unlock->setGeometry(0,m_set_password->height() + 2,m_unlock->width(),m_unlock->height()); connect(m_unlock,&QPushButton::clicked, this, [=] { m_chech_result->setText("密码校验"); m_is_check_password = true; }); m_chech_result = new QLabel("校验结果", this); m_chech_result->setStyleSheet("color:#ffeeff;"); m_chech_result->setGeometry(0,m_set_password->height() + m_unlock->height() +2, m_chech_result->width(), m_chech_result->height()); resize(640,480); } GestureAuthDialog::~GestureAuthDialog() { } void GestureAuthDialog::paintEvent(QPaintEvent *event) { int width = this->width(); int height = this->height(); int side = qMin(width, height); qDebug() <<"-----------width=" << width << ",height=" << height << ",side=" << side; QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); painter.translate(width / 2, height / 2); painter.scale(side / 200, side / 200); gestureScale = side/200; drawBg(&painter); drawOutCircle(&painter); drawTipLine(&painter); drawInCircle(&painter); drawJoinLine(&painter); } void GestureAuthDialog::drawBg(QPainter *painter) { painter->save(); int width = this->width(); int height = this->height(); painter->setPen(Qt::NoPen); m_bgColor.setAlpha(100); painter->setBrush(m_bgColor); painter->drawRect(-width / 2, -height / 2, width, height); painter->restore(); } void GestureAuthDialog::drawOutCircle(QPainter *painter) { painter->save(); QPen pen(m_outCircleColor, 2); painter->setPen(pen); painter->setBrush(Qt::NoBrush); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { int x = -5 * m_radius + j * 4 * m_radius; int y = -5 * m_radius + i * 4 * m_radius; painter->drawEllipse(x, y, m_radius * 2, m_radius * 2); //qDebug() << "-------------x,y=" << x << ","<< y; if (m_showText) { int number = posToNumber(i, j); QString text = QString::number(number); x = -4 * m_radius + j * 4 * m_radius; y = -4 * m_radius + i * 4 * m_radius; int textWidth = fontMetrics().width(text); int textHeight = fontMetrics().height(); painter->drawText(x - textWidth / 2, y + textWidth / 2, text); } } } painter->restore(); } void GestureAuthDialog::drawTipLine(QPainter *painter) { painter->save(); int offset = 3; if (m_posInCircle.isIn) { if (!m_pressed) { painter->setPen(m_tipLineColor); painter->setBrush(Qt::NoBrush); int x = -m_radius * 5 + m_posInCircle.j * 4 * m_radius - offset; int y = -m_radius * 5 + m_posInCircle.i * 4 * m_radius - offset; int w = (m_radius + offset) * 2; int h = (m_radius + offset) * 2; QRect rect(x, y, w, h); painter->drawEllipse(rect); } } painter->restore(); } void GestureAuthDialog::drawInCircle(QPainter *painter) { painter->save(); if (m_pressed) { int offset1 = 1;//圆环偏移量 int offset2 = 3;//内圆偏移量 if (m_posInCircle.isIn) { //绘制圆环 painter->setPen(m_circleRingColor); painter->setBrush(m_circleRingColor); int x = -m_radius * 5 + m_posInCircle.j * 4 * m_radius + offset1; int y = -m_radius * 5 + m_posInCircle.i * 4 * m_radius + offset1; int w = (m_radius - offset1) * 2; int h = (m_radius - offset1) * 2; QRect rect(x, y, w, h); painter->drawEllipse(rect); painter->setPen(m_outCircleColor); painter->setBrush(m_outCircleColor); x = -m_radius * 5 + m_posInCircle.j * 4 * m_radius + offset2; y = -m_radius * 5 + m_posInCircle.i * 4 * m_radius + offset2; w = (m_radius - offset2) * 2; h = (m_radius - offset2) * 2; rect = QRect(x, y, w, h); painter->drawEllipse(rect); x = -m_radius * 4 + m_posInCircle.j * 4 * m_radius; y = -m_radius * 4 + m_posInCircle.i * 4 * m_radius; if (!m_vecInputPoints.contains(QPoint(x, y))) { m_vecInputPoints.push_back(QPoint(x, y)); int number = posToNumber(m_posInCircle.i, m_posInCircle.j); m_inputPassword += QString::number(number); } } } painter->restore(); } void GestureAuthDialog::drawJoinLine(QPainter *painter) { painter->save(); QPen pen(m_outCircleColor, 3); painter->setPen(pen); //绘制连接线段 for (int i = 0; i < m_vecInputPoints.count() - 1; i++) { painter->drawLine(m_vecInputPoints[i], m_vecInputPoints[i + 1]); } int offset1 = 1;//圆环偏移量 int offset2 = 3;//内圆偏移量 //绘制连接圆 for (int i = 0; i < m_vecInputPoints.count(); i++) { int x = m_vecInputPoints[i].x() - m_radius + offset1; int y = m_vecInputPoints[i].y() - m_radius + offset1; int w = 2 * (m_radius - offset1); int h = 2 * (m_radius - offset1); painter->setPen(m_circleRingColor); painter->setBrush(m_circleRingColor); painter->drawEllipse(x, y, w, h); x = m_vecInputPoints[i].x() - m_radius + offset2; y = m_vecInputPoints[i].y() - m_radius + offset2; w = 2 * (m_radius - offset2); h = 2 * (m_radius - offset2); painter->setPen(m_outCircleColor); painter->setBrush(m_outCircleColor); painter->drawEllipse(x, y, w, h); } //绘制跟随线 if (m_pressed && m_vecInputPoints.count() < 9) { int width = this->width(); int height = this->height(); int side = qMin(width, height); int gestureScale = side / 200; int x = (m_followPoint.x() - width / 2) / gestureScale; int y = (m_followPoint.y() - height / 2) / gestureScale; if (m_vecInputPoints.count() > 0) { painter->setPen(pen); painter->drawLine(m_vecInputPoints.last(), QPoint(x, y)); } } painter->restore(); } void GestureAuthDialog::mouseMoveEvent(QMouseEvent *event) { //nothing qDebug() << "--------mouseMoveEvent(" << event->x() << "," << event->y() << ")"; // qDebug() << "-------------gestureScale=" << gestureScale; int x = (event->x() - this->width()/2) / gestureScale; int y = (event->y() - this->height()/2) / gestureScale; // qDebug() << "--------mousePressEvent转化后 x,y(" << x << "," << y << ")"; int jMax = 0; if (x >=0) jMax = 1; for (int i = 0; i < 3; i++) { for (int j = jMax; j < 3; j++) { int x1 = -4 * m_radius + j * 4 * m_radius; int y1 = -4 * m_radius + i * 4 * m_radius; // qDebug() << "--------每个圆心的位置 x1,y1(" << x1 << "," << y1 << ")"; if (distance(x , y, x1, y1) <= m_radius) { QString numStr = QString::number(posToNumber(i,j), 10); if (m_inputPassword.contains(numStr)) { qWarning() << "已选过该区域"; return; } m_inputPassword.append(numStr); m_posInCircle.i = i; m_posInCircle.j = j; // m_posInCircle.isIn = true; qDebug() << "---------------选中了"<< posToNumber(i,j); m_vecInputPoints.append(QPoint(x1, y1)); //鼠标移动选点 m_followPoint = QPoint(x, y); repaint(); } } } } void GestureAuthDialog::mousePressEvent(QMouseEvent *event) { //nothing qDebug() << "--------mousePressEvent(" << event->x() << "," << event->y() << ")"; // qDebug() << "-------------gestureScale=" << gestureScale; int x = (event->x() - this->width()/2) / gestureScale; int y = (event->y() - this->height()/2) / gestureScale; // qDebug() << "--------mousePressEvent转化后 x,y(" << x << "," << y << ")"; for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { int x1 = -4 * m_radius + j * 4 * m_radius; int y1 = -4 * m_radius + i * 4 * m_radius; // qDebug() << "--------每个圆心的位置 x1,y1(" << x1 << "," << y1 << ")"; if (distance(x , y, x1, y1) <= m_radius) { m_posInCircle.i = i; m_posInCircle.j = j; m_posInCircle.isIn = true; m_vecInputPoints.append(QPoint(x1, y1)); //鼠标移动选点 m_followPoint = QPoint(x1, y1); qDebug() << "---------------选中了"<< posToNumber(i,j); repaint(); } } } } void GestureAuthDialog::mouseReleaseEvent(QMouseEvent *event) { //nothing qDebug() << "--------mouseReleaseEvent(" << event->x() << "," << event->y() << ")"; m_posInCircle.isIn = false; if (m_is_set_password && !m_inputPassword.isEmpty()) { m_password = m_inputPassword; m_chech_result->setText("密码设置成功"); qDebug() << "---------密码:" << m_password; m_is_set_password = false; } if (m_is_check_password) { if (m_inputPassword == m_password) { m_chech_result->setText("密码正确"); qDebug() << "---------密码:" << m_password << " 输入的是:" << m_inputPassword; emit authenticateCompete(true); // m_is_check_password = false; } else { m_chech_result->setText("密码错误"); qDebug() << "---------密码:" << m_password << " 输入的是:" << m_inputPassword; } } m_vecInputPoints.clear(); m_inputPassword.clear(); repaint(); } double GestureAuthDialog::distance(int x1, int y1, int x2, int y2) { //nothing double x = x1 - x2; double y = y1 - y2; return sqrt(x*x + y*y); } int GestureAuthDialog::posToNumber(int i, int j) { //nothing return ((3*i) + j +1); } void GestureAuthDialog::setPassword(const QString password) { //nothing } QString GestureAuthDialog::getPassword() { //nothing } bool GestureAuthDialog::checkPassword() { //nothing } ukui-screensaver/src/auth-pam.h0000644000175000017500000000307514205074704015455 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef AUTHPAM_H #define AUTHPAM_H #include "auth.h" #include #include #include typedef struct pam_message PAM_MESSAGE; typedef struct pam_response PAM_RESPONSE; class AuthPAM : public Auth { Q_OBJECT public: AuthPAM(QObject *parent = nullptr); void authenticate(const QString &userName); void stopAuth(); void respond(const QString &response); bool isAuthenticated(); bool isAuthenticating(); private: void _authenticate(const char *userName); void _respond(const struct pam_response *response); private Q_SLOTS: void onSockRead(); private: QString userName; pid_t pid; QSocketNotifier *notifier; int nPrompts; QStringList responseList; QList messageList; bool _isAuthenticated; //认证结果 bool _isAuthenticating; }; #endif // AUTHPAM_H ukui-screensaver/src/pam.cpp0000644000175000017500000000721314205074704015047 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "pam.h" extern "C" { #include #include #include } #define TO_AUTHCHILD_RD_SHIFT 16 #define TO_PARENT_WR_SHIFT 0 #define PIPE_FD_MASK ((1 << TO_AUTHCHILD_RD_SHIFT) - 1) void authenticate(int toParent[2], int toAuthChild[2]) { pam_handle_t *pamh = NULL; char *username; int retval; int auth_status; struct pam_conv conv; unsigned long fd = 0; fd = fd | toAuthChild[0] << TO_AUTHCHILD_RD_SHIFT | toParent[1] << TO_PARENT_WR_SHIFT; /* authentication child process */ username=getenv("USER"); conv.conv = pam_conversation; conv.appdata_ptr = (void *)fd; retval = pam_start("ukui-screensaver-qt", username, &conv, &pamh); if(retval == PAM_SUCCESS) qDebug("PAM started successfully."); else qDebug("PAM started unsuccessfully."); qDebug("Invoke pam authentication."); auth_status = pam_authenticate(pamh, 0); qDebug("Complete pam authentication."); if(pam_end(pamh, retval) != PAM_SUCCESS){ qDebug("Failed to terminate PAM."); _exit(1); } qDebug("PAM ended successfully."); kill(getppid(), SIGUSR1); char buffer[16]; sprintf(buffer, "%d", auth_status); PIPE_OPS_SAFE( write(toParent[1], buffer, strlen(buffer) + 1) ); qDebug("Auth status has been written to pipe."); ::close(toParent[1]); ::close(toAuthChild[0]); qDebug("Authenticate child process now exits."); _exit(0); } #define MAX_PASSWORD_LENGTH 1024 int pam_conversation(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) { unsigned long fd; int read_from_parent; int write_to_parent; int count; char *password; struct pam_response *tmp_save; qDebug("Into pam_conversation"); fd = (unsigned long)appdata_ptr; read_from_parent = (fd >> TO_AUTHCHILD_RD_SHIFT) & PIPE_FD_MASK; write_to_parent = (fd >> TO_PARENT_WR_SHIFT) & PIPE_FD_MASK; count = num_msg; password = (char *)malloc(MAX_PASSWORD_LENGTH); *resp = (struct pam_response *)malloc(num_msg * sizeof(struct pam_response)); tmp_save = (struct pam_response *)(*resp); memset(*resp, 0, num_msg * sizeof(struct pam_response)); qDebug("Resolve PAM messages."); while(count-- >= 1){ struct pam_message_object pam_msg_obj; pam_msg_obj.msg_style = (*msg)->msg_style; strncpy(pam_msg_obj.msg, (*msg)->msg, MAX_MSG_LENGTH); PIPE_OPS_SAFE( write(write_to_parent, &pam_msg_obj, sizeof(pam_msg_obj)); ); qDebug("PAM message has been written to pipe."); kill(getppid(), SIGUSR1); if ((*msg)->msg_style == PAM_PROMPT_ECHO_OFF || (*msg)->msg_style == PAM_PROMPT_ECHO_ON){ int n; PIPE_OPS_SAFE( n = read(read_from_parent, password, MAX_PASSWORD_LENGTH); ); qDebug("%d bytes response received from pipe.", n); (*resp)->resp = password; (*resp)->resp_retcode = 0; } else { ; } if(count != 0){ msg++; (*resp)++; } } (*resp) = tmp_save; qDebug("Out pam_conversation."); return PAM_SUCCESS; } ukui-screensaver/src/unixsignallistener.h0000644000175000017500000000271514205074704017670 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef UNIXSIGNALLISTENER_H #define UNIXSIGNALLISTENER_H #ifndef QT_NO_KEYWORDS #define QT_NO_KEYWORDS #endif #include #include #include class UnixSignalListener : public QObject { Q_OBJECT public: explicit UnixSignalListener(QObject *parent = nullptr); public: /* Unix signal handlers. */ static void usr1SignalAction(int sig, siginfo_t *siginfo, void *ucontext); static void chldSignalAction(int sig, siginfo_t *siginfo, void *ucontext); Q_SIGNALS: /* pid is the sending process id */ void transition(int pid); /* Finite State Machine Driven Signal */ public Q_SLOTS: /* Qt signal handlers. */ void handleSigUsr1(); private: static int sigusr1Fd[2]; QSocketNotifier *snUsr1; }; #endif // UNIXSIGNALLISTENER_H ukui-screensaver/src/lockwidget.h0000644000175000017500000000451214205074704016072 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef LOCKWIDGET_H #define LOCKWIDGET_H #ifndef QT_NO_KEYWORDS #define QT_NO_KEYWORDS #endif #include #include #include namespace Ui { class LockWidget; } class VirtualKeyboard; class PowerManager; class AuthDialog; class Users; class UserItem; class DisplayManager; class QMenu; class QScrollArea; class LockWidget : public QWidget { Q_OBJECT public: explicit LockWidget(QWidget *parent = 0); ~LockWidget(); void closeEvent(QCloseEvent *event); void startAuth(); void stopAuth(); void setX11Focus(); QVariant getValue(const QString &); Q_SIGNALS: void closed(); void capsLockChanged(); private: void initUI(); void initUserMenu(); void setVirkeyboardPos(); private Q_SLOTS: void onUserAdded(const UserItem &user); void onUserDeleted(const UserItem &user); void onUserMenuTrigged(QAction *action); void showVirtualKeyboard(); void showPowerManager(); void switchToGreeter(); protected: bool eventFilter(QObject *obj, QEvent *event); void resizeEvent(QResizeEvent *event); void keyReleaseEvent(QKeyEvent *e); private: Ui::LockWidget *ui; AuthDialog *authDialog; VirtualKeyboard *vKeyboard; PowerManager *powermanager; QTimer *timer; QMenu *usersMenu; Users *users; DisplayManager *displayManager; int timeType; QString dateType; QScrollArea *scrollArea; QWidget *scrollContents; QSettings *configSettings; }; #endif // LOCKWIDGET_H ukui-screensaver/src/authdialog.h0000644000175000017500000001133614205074760016063 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef AUTHDIALOG_H #define AUTHDIALOG_H #ifndef QT_NO_KEYWORDS #define QT_NO_KEYWORDS #endif #include #include #include "auth-pam.h" #include "types.h" #include "users.h" #include "biometricdeviceinfo.h" #include "pam-tally.h" namespace Ui { class AuthDialog; } class QLabel; class QPushButton; class IconEdit; class Auth; class BiometricProxy; class BiometricAuthWidget; class BiometricDevicesWidget; class PamTally; extern float scale; class AuthDialog : public QWidget { Q_OBJECT public: explicit AuthDialog(const UserItem &user, QWidget *parent = 0); void resizeEvent(QResizeEvent *event); void closeEvent(QCloseEvent *event); void setUserOfAuth(); void setX11Focus(); private: void initUI(); void startWaiting(); void stopWaiting(); void clearMessage(); void performBiometricAuth(); void skipBiometricAuth(); void initBiometricWidget(); void initBiometricButtonWidget(); void setChildrenGeometry(); void setBiometricWidgetGeometry(); void setBiometricButtonWidgetGeometry(); void showPasswordAuthWidget(); void showBiometricAuthWidget(); void showBiometricDeviceWidget(); QPixmap PixmapToRound(const QPixmap &src, int radius); void startBioAuth(); void show_authenticated (bool successful = true); private Q_SLOTS: void onShowMessage(const QString &message, Auth::MessageType type); void onShowPrompt(const QString &prompt, Auth::PromptType type); void onAuthComplete(); void onRespond(const QString &text); // void onBioAuthStart(); // void onBioAuthStop(); // void setBioMovieImage(); // void updateIcon(); void onDeviceChanged(const DeviceInfoPtr &deviceInfo); void onBiometricAuthComplete(bool result); void onBiometricButtonClicked(); void onPasswordButtonClicked(); void onOtherDevicesButtonClicked(); void onRetryButtonClicked(); void pamBioSuccess(); void onMessageButtonClicked(); public Q_SLOTS: // void switchToBiometric(); // void switchToPassword(); // void switchToDevices(); void onCapsLockChanged(); void startAuth(); void stopAuth(); Q_SIGNALS: void authenticateCompete(bool result); private: UserItem user; Auth *auth; enum AuthMode { PASSWORD, BIOMETRIC, UNKNOWN }; AuthMode authMode; // biometric auth int m_deviceCount; int m_featureCount; QString m_deviceName; DeviceInfoPtr m_deviceInfo; BiometricProxy *m_biometricProxy; BiometricAuthWidget *m_biometricAuthWidget; BiometricDevicesWidget *m_biometricDevicesWidget; QWidget *m_buttonsWidget; QPushButton *m_biometricButton; QPushButton *m_passwordButton; QPushButton *m_otherDeviceButton; QPushButton *m_retryButton; // UI // QPushButton *m_backButton; //返回用户列表 QWidget *m_userWidget; //放置用户信息Label QLabel *m_faceLabel; //头像 QLabel *m_nameLabel; //用户名 // QLabel *m_isLoginLabel; //提示是否已登录 QWidget *m_passwdWidget; //放置密码输入框和信息列表 IconEdit *m_passwordEdit; //密码输入框 QLabel *m_messageLabel; //PAM消息显示 QPushButton *m_messageButton; bool usebind; bool usebindstarted; bool isBioPassed; int maxFailedTimes; bool isHiddenSwitchButton; int failedTimes; QTimer *m_bioTimer; bool useFirstDevice; bool isLockingFlg; //判断当前是否正在锁定倒计时 bool prompted = false; bool unacknowledged_messages = false; bool direct_login = false; bool isretry = true; void root_unlock_countdown(); void unlock_countdown(); QTimer *m_timer; }; #endif // AUTHDIALOG_H ukui-screensaver/src/lockwidget.ui0000644000175000017500000000425114205074704016260 0ustar fengfeng LockWidget 0 0 748 433 Form 550 10 80 26 PointingHandCursor Qt::NoFocus 10 280 54 70 Time Date 460 10 80 26 PointingHandCursor Qt::NoFocus 650 10 80 26 PointingHandCursor ukui-screensaver/src/org.ukui.ScreenSaver.xml0000644000175000017500000000113114205074704020263 0ustar fengfeng ukui-screensaver/src/xeventmonitor.h0000644000175000017500000000313214205074704016654 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2011 ~ 2017 Deepin, Inc. * 2011 ~ 2017 Wang Yong * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. * * Author: Wang Yong * Maintainer: Wang Yong * * 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 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef XEVENTMONITOR_H #define XEVENTMONITOR_H #include #include #include class XEventMonitorPrivate; class XEventMonitor : public QThread { Q_OBJECT public: XEventMonitor(QObject *parent = 0); ~XEventMonitor(); Q_SIGNALS: void buttonPress(int x, int y); void buttonDrag(int x, int y); void buttonRelease(int x, int y); void keyPress(int keyCode); void keyRelease(int keyCode); void keyPress(const QString &key); void keyRelease(const QString &key); protected: void run(); private: XEventMonitorPrivate *d_ptr; Q_DECLARE_PRIVATE(XEventMonitor) }; #endif ukui-screensaver/src/gestureauthdialog.h0000644000175000017500000000552414205074704017462 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * Authors: ZHAI Kang-ning **/ #ifndef GESTUREAUTHDIALOG_H #define GESTUREAUTHDIALOG_H #include #include #include #include #include #include class GestureAuthDialog : public QWidget { Q_OBJECT public: struct PosInCircle { int i; //行 int j; //列 bool isIn; //是否在范围内 }; explicit GestureAuthDialog(QWidget *parent = nullptr); ~GestureAuthDialog(); void setPassword(const QString password); QString getPassword(); bool checkPassword(); protected: void paintEvent(QPaintEvent *event); void mouseMoveEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void drawBg(QPainter *painter); void drawOutCircle(QPainter *painter); void drawTipLine(QPainter *painter); void drawInCircle(QPainter *painter); void drawJoinLine(QPainter *painter); private: double distance(int x1, int y1, int x2, int y2); int posToNumber(int i, int j); Q_SIGNALS: void correctPassword(bool isCorrect, QString password); void authenticateCompete(bool result); public Q_SLOTS: private: QColor m_bgColor; //背景色 QColor m_outCircleColor; //外圆颜色 QColor m_tipLineColor; //提示线颜色 QColor m_circleRingColor; //圆环颜色 int m_margin; //外边距 int m_radius; //圆相对半径 PosInCircle m_posInCircle; //判断点是否在圆内 bool m_pressed; //鼠标按下 bool m_showText; //是否显示文字 QVector m_vecInputPoints; //鼠标移动选点 QPoint m_followPoint; //鼠标跟随点 QString m_password; //原密码 QString m_inputPassword; //鼠标移动选点转换为密码 QPushButton *m_set_password; bool m_is_set_password; QPushButton *m_unlock; bool m_is_check_password; QLabel *m_chech_result; }; #endif // GESTUREAUTHDIALOG_H ukui-screensaver/src/monitorwatcher.cpp0000644000175000017500000000715314205074704017342 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "monitorwatcher.h" #include #include #include #include #define DRM_DIR "/sys/class/drm/" MonitorWatcher::MonitorWatcher(QObject *parent) : QThread(parent), virtualSize(0, 0), monitorCount(0), firstDetect(true) { } MonitorWatcher::~MonitorWatcher() { requestInterruption(); terminate(); wait(); } void MonitorWatcher::run() { QDir drmDir(DRM_DIR); QStringList drms = drmDir.entryList(QDir::Dirs); for(auto iter = drms.begin(); iter != drms.end(); ) { if((*iter).indexOf("card") == 0 || iter->length() > 5) iter++; else iter = drms.erase(iter); } FILE * fp = popen("xrandr", "r"); Q_UNUSED(fp) /* 每隔3秒遍历一次显卡接口的连接状态 */ while(!isInterruptionRequested()) { int width = 0; int height = 0; QMap tmpStatus; for(const QString & drm : drms) { QFile drmStatusFile(DRM_DIR + drm + "/status"); if(drmStatusFile.open(QIODevice::ReadOnly | QIODevice::Text)) { QTextStream in(&drmStatusFile); QString status = in.readLine(); tmpStatus[drm] = status; if(status == "connected") { QSize maxMode = getMonitorMaxSize(drm); width += maxMode.width(); height = height > maxMode.height() ? height : maxMode.height(); } } } if(drmStatus != tmpStatus) { drmStatus = tmpStatus; int count = 0; for(auto &pair : tmpStatus) if(pair == "connected") count++; qDebug() << "monitor count changed ---" << count; if(monitorCount != count) { monitorCount = count; if(!firstDetect) { firstDetect = false; Q_EMIT monitorCountChanged(count); } } FILE *fp = popen("xrandr", "r"); Q_UNUSED(fp) } virtualSize = QSize(width, height); sleep(3); } } /** * 获取显示器的最大分辨率 */ QSize MonitorWatcher::getMonitorMaxSize(const QString &drm) { int width = 0, height = 0; QFile drmModeFile(DRM_DIR + drm + "/modes"); if(drmModeFile.open(QIODevice::ReadOnly | QIODevice::Text)) { QTextStream in2(&drmModeFile); QString maxMode = in2.readLine(); int xpos = maxMode.indexOf('x', 0); width = maxMode.left(xpos).toInt(); int ipos = maxMode.indexOf('i', 0); if(ipos != -1) height = maxMode.mid(xpos+1, ipos-xpos-1).toInt(); else height = maxMode.mid(xpos+1).toInt(); } return QSize(width, height); } QSize MonitorWatcher::getVirtualSize() { return virtualSize; } int MonitorWatcher::getMonitorCount() { return monitorCount; } ukui-screensaver/src/verticalVerificationwidget.h0000644000175000017500000000274214205074760021323 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef VERTICALVERIFICATIONWIDGET_H #define VERTICALVERIFICATIONWIDGET_H #include #include #include #include #include #include "common.h" class VerticalVerificationWidget : public QWidget { Q_OBJECT public: explicit VerticalVerificationWidget(QWidget *parent = nullptr); ~VerticalVerificationWidget(); void reloadQR(); Q_SIGNALS: void pageMessage(SwitchPage id, QList argvs); private: QLabel *m_titleLB; QLabel *m_phonePromptMsgLB; WeChatAuthDialog *m_weChatWidget; //public: PhoneAuthWidget *m_phoneAuthWidget; protected: void paintEvent(QPaintEvent *); }; #endif // VERTICALVERIFICATIONWIDGET_H ukui-screensaver/src/interface.h0000644000175000017500000000345514205074704015703 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef INTERFACE_H #define INTERFACE_H #include #include #include #include #include #include "types.h" #include "logind.h" class QGSettings; class Interface : public QObject, protected QDBusContext { Q_OBJECT Q_CLASSINFO("D-Bus Interface", SS_DBUS_SERVICE) public: explicit Interface(QObject *parent = nullptr); LogindIntegration *m_logind; Q_SIGNALS: void SessionIdle(); public Q_SLOTS: /** * Lock the screen */ void Lock(); void UnLock(); void ShowScreensaver(); bool GetLockState(); void SetLockState(); void onSessionIdleReceived(); void onShowScreensaver(); void onShowBlankScreensaver(); void onNameLost(const QString&); void onPrepareForSleep(bool sleep); private: bool checkExistChild(); void inhibit(); void uninhibit(); bool lockState; void emitLockState(bool); int m_timerCount; QGSettings *settings; QTimer *m_timer; QDBusUnixFileDescriptor m_inhibitFileDescriptor; private: QProcess process; }; #endif // INTERFACE_H ukui-screensaver/src/verificationwidget.cpp0000644000175000017500000005363114205074760020167 0ustar fengfeng/** * Copyright (C) 2018 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, 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 "verificationwidget.h" #include #include #include #include #include #include #include #include #include "common.h" #include "wechatauthdialog.h" #include "eduplatforminterface.h" #include "accountsinterface.h" /** * 忘记密码后,校验页面:分为二维码校验和手机号校验 */ bool isDigitalString(QString s);//判断字符串是否全为数字 VerificationWidget::VerificationWidget(QWidget *parent) : QWidget(parent) { qDebug() << "PermissionCheck"; resize(1000,400); QHBoxLayout *mainLayout = new QHBoxLayout(this); setLayout(mainLayout); m_weChatWidget = new WeChatAuthDialog(1,this); mainLayout->addWidget(m_weChatWidget, 1, Qt::AlignLeft); m_weChatWidget->setFixedWidth(400); mainLayout->addSpacerItem(new QSpacerItem(0,200,QSizePolicy::Fixed,QSizePolicy::Expanding)); m_phoneAuthWidget = new PhoneAuthWidget(this); mainLayout->addWidget(m_phoneAuthWidget, 1, Qt::AlignRight); m_phoneAuthWidget->setFixedWidth(400); connect(m_phoneAuthWidget, &PhoneAuthWidget::pageMessage, this, [=](SwitchPage s, QList list){ Q_EMIT pageMessage(s, list); }); connect(m_weChatWidget, &WeChatAuthDialog::qRStatusChange, this, [=] (QString loginname, QString loginpwd, int curstatus){ //QString loginname, QString loginpwd, int curstatus if (loginname.isEmpty()) { // Todo?正在登陆???? qDebug() << "wechar name is null"; } else if(getenv("USER") == loginname) { Q_EMIT pageMessage(SwitchPage::SwitchToResetPWD, QList());; } else { qWarning() << "[error] Username does not match wechat<" << loginname << ">" << " local<" << getenv("USER")<<">"; m_weChatWidget->showErrorMessage(tr("Please scan by bound WeChat")); m_weChatWidget->onReset(); } }); } VerificationWidget::~VerificationWidget() { m_phoneAuthWidget->close(); m_weChatWidget->close(); } void VerificationWidget::paintEvent(QPaintEvent *) { int x1 = width() / 2; int y1 = height() / 4; int x2 = x1; int y2 = height() / 3 * 2 + y1; QLinearGradient linearGra(QPoint(x1, y1), QPoint(x2, y2)); linearGra.setColorAt(0, QColor(238, 238, 238, 0)); linearGra.setColorAt(0.5, QColor(255, 255, 255, 138)); linearGra.setColorAt(1, QColor(216, 216, 216, 0)); QPainter painter(this); QBrush brush(linearGra); painter.setPen(Qt::transparent); painter.setBrush(brush); painter.drawRoundedRect(QRect(x1, y1, 4, height() / 3 * 2), 16, 16); } void VerificationWidget::reloadQR() { m_weChatWidget->reloadQR(); } InputInfos::InputInfos(QWidget *parent): QWidget(parent) { initUI(); initConnect(); setQSS(); } void InputInfos::initUI() { setFixedSize(316, 129); QGridLayout *mainLayout = new QGridLayout(this); setLayout(mainLayout); mainLayout->setColumnStretch(1, 0); mainLayout->setColumnStretch(2, 1); mainLayout->setColumnStretch(3, 0); m_pPhoneIconLB = new QLabel(this); m_pPhoneIconLB->setPixmap(QPixmap(":/image/assets/intel/phone.png")); mainLayout->addWidget(m_pPhoneIconLB, 0, 1, 1, 1, Qt::AlignLeft); m_pPhoneLE = new QLineEdit(this); m_pPhoneLE->setReadOnly(true); //限制以下特殊符号在lineEdit中的输入 /*需求变更,不需要用户输入手机号,直接获取已绑定的手机号显示给用户 QRegExp phoneNumrx = QRegExp("^1([358][0-9]|4[579]|66|7[0135678]|9[89])[0-9]{8}$"); QRegExpValidator *phoneNumValidator = new QRegExpValidator(phoneNumrx); m_pPhoneLE->setValidator(phoneNumValidator); */ m_pPhoneLE->setText("正在获取手机号..."); GetPhoneNumThread *workerThread = new GetPhoneNumThread(this); connect(workerThread, &GetPhoneNumThread::resultReady, this, &InputInfos::onGetPhoneNum); connect(workerThread, &GetPhoneNumThread::finished, workerThread, &QObject::deleteLater); workerThread->start(); m_pPhoneLE->setPlaceholderText("手机号"); m_pPhoneLE->setProperty("class", "InputLine"); mainLayout->addWidget(m_pPhoneLE, 0, 2, 1, 2, Qt::AlignLeft); m_pVerCodeIconLB = new QLabel(this); m_pVerCodeIconLB->setPixmap(QPixmap(":/image/assets/sms.png")); mainLayout->addWidget(m_pVerCodeIconLB, 1, 1, 1, 1, Qt::AlignLeft); //限制以下特殊符号在lineEdit中的输入 QRegExp verCoderx = QRegExp("^[0-9]{6}$"); QRegExpValidator *verCodeValidator = new QRegExpValidator(verCoderx); m_pVerCodeLE = new MyLineEdit(this); m_pVerCodeLE->setValidator(verCodeValidator); mainLayout->addWidget(m_pVerCodeLE, 1, 2, 1, 1, Qt::AlignLeft); m_pGetVerCodeBT = new QPushButton(this); m_pGetVerCodeBT->setText(tr("Get code")); m_pGetVerCodeBT->setEnabled(false); m_pGetVerCodeBT->setFocusPolicy(Qt::NoFocus); m_pGetVerCodeBT->setProperty("class", "GetCodeBT"); m_pGetVerCodeBT->setCursor(QCursor(Qt::PointingHandCursor)); mainLayout->addWidget(m_pGetVerCodeBT, 1, 3, 1, 1, Qt::AlignLeft); m_pNextGetVerCodeQTimer = new QTimer(this); m_curInputState = InputState::InputWaiting; m_networkWatcher = new NetWorkWatcher(this); } void InputInfos::initConnect() { connect(m_pPhoneLE, &QLineEdit::textChanged, this, &InputInfos::onPhoneTextChanged); connect(m_pVerCodeLE, &QLineEdit::textChanged, this, &InputInfos::onVerCodeTextChanged); connect(m_pNextGetVerCodeQTimer, &QTimer::timeout, this, &InputInfos::onNextGetVerCodeTimer); connect(m_pGetVerCodeBT, &QPushButton::clicked, this, &InputInfos::onGetVerCode); connect(m_networkWatcher, &NetWorkWatcher::NetworkStateChanged, this, &InputInfos::onNetworkStateChanged); } void InputInfos::setQSS() { QString style_sheet = ".InputLine{" "padding:10px 2px 10px 2px;" "background-color:rgb(255,255,255,0);" "color:black;" "}" ".GetCodeBT{" "background:rgba(0,0,0,0);" "color:rgba(38,38,38,115);" "font-size:16px;" "}"; setStyleSheet(style_sheet); //adjustSize(); } void InputInfos::paintEvent(QPaintEvent *) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); painter.setPen(Qt::white); painter.setBrush(Qt::white); painter.drawRoundedRect(rect(), 16, 16); painter.setPen(QColor(226, 226, 226)); painter.drawLine(QLineF(0, m_pPhoneIconLB->y() + m_pPhoneIconLB->height() + 1, width(), m_pPhoneIconLB->y() + m_pPhoneIconLB->height() + 1)); } void InputInfos::onPhoneTextChanged(const QString &text) { if(text.length() == 11 && isDigitalString(text)){ m_pGetVerCodeBT->setEnabled(true); m_pGetVerCodeBT->setFocusPolicy(Qt::NoFocus); m_pGetVerCodeBT->setStyleSheet("color:#2FB3E8;"); if(m_pVerCodeLE->text().length() == 6){ Q_EMIT InputStateChanged(InputState::InputFinish); m_curInputState = InputState::InputFinish; } } else { m_pGetVerCodeBT->setEnabled(false); m_pGetVerCodeBT->setStyleSheet("color:rgba(38, 38, 38, 115);"); if(InputState::InputFinish == m_curInputState) { m_curInputState = InputState::InputWaiting; Q_EMIT InputStateChanged(InputState::InputWaiting); } } } void InputInfos::onNetworkStateChanged(uint state) { if(NM_STATE_CONNECTED_LIMIT == state) { m_nextGetVerCodeTime = 0; emit notGlobal(); } else if(NM_STATE_CONNECTED_GLOBAL != state) { m_nextGetVerCodeTime = 0; emit offlineState(); } else emit online(); } void InputInfos::onVerCodeTextChanged(const QString &text) { if(text.length() == 6 && m_pPhoneLE->text().length() == 11 && isDigitalString(m_pPhoneLE->text())) { Q_EMIT InputStateChanged(InputState::InputFinish); m_curInputState = InputState::InputFinish; } else if(m_curInputState == InputState::InputFinish && text.length() > 0 && text.length() < 6) { Q_EMIT InputStateChanged(InputState::InputWaiting); m_curInputState = InputState::InputWaiting; } } void InputInfos::clearInfos() { m_pPhoneLE->clear(); m_pVerCodeLE->clear(); if(m_curInputState == InputState::InputFinish) { m_curInputState = InputState::InputWaiting; Q_EMIT InputStateChanged(m_curInputState); } } QString InputInfos::getVerificationCode() { return m_pVerCodeLE->text(); } QString InputInfos::getPhoneNumer() { return m_phoneNum; } /** * @brief InputInfos::onGetVerCode * 获取手机验证码 */ void InputInfos::onGetVerCode() { if(!m_networkWatcher->isConnect()) { emit offlineState(); return; } m_networkWatcher->checkOnline(); m_pGetVerCodeBT->setEnabled(false); m_pGetVerCodeBT->setStyleSheet("color:rgba(38, 38, 38, 115);"); m_nextGetVerCodeTime = 60; m_pGetVerCodeBT->setText(tr("Recapture(60s)")); m_pNextGetVerCodeQTimer->start(1000); QDBusReply reply = EduPlatformInterface::getInstance()->call("GetVerifyCode", getPhoneNumer()); if(!reply.isValid()) { qDebug() << "info: [InputInfos][onGetVerCode]: DBus Connect Failed!"; return; } // if(reply.value() != 0) // 默认0为成功 { qDebug() << "info: [InputInfos][onGetVerCode]: DBus request failed!"; return; } } void InputInfos::onNextGetVerCodeTimer() { if(m_nextGetVerCodeTime > 0) --m_nextGetVerCodeTime; if(m_nextGetVerCodeTime == 20 || m_nextGetVerCodeTime == 40) m_networkWatcher->checkOnline(); m_pGetVerCodeBT->setText(tr("Recapture(%1s)").arg(QString::number(m_nextGetVerCodeTime))); if(m_nextGetVerCodeTime == 0) { m_pNextGetVerCodeQTimer->stop(); m_pGetVerCodeBT->setEnabled(true); m_pGetVerCodeBT->setFocusPolicy(Qt::NoFocus); m_pGetVerCodeBT->setText(tr("Get code")); m_pGetVerCodeBT->setStyleSheet("color:#2FB3E8;"); return; } } void InputInfos::onGetPhoneNum(int errorCode, const QString phoneNum) { switch (errorCode) { case DBusMsgCode::No_Error: if(phoneNum != nullptr && phoneNum.size() == 11) { m_phoneNum = phoneNum; m_pPhoneLE->setText(QString(phoneNum).replace(3,4,"****")); } else { qWarning() << "error: [InputInfos] onGetPhoneNum 获取到的手机号格式错误:" << phoneNum; } break; case DBusMsgCode::Error_NoReply: m_pPhoneLE->setText(tr("Service exception...")); break; case DBusMsgCode::Error_ArgCnt: m_pPhoneLE->setText(tr("Invaild parameters...")); break; default: m_pPhoneLE->setText(tr("Unknown fault:%1").arg(errorCode)); break; } if(DBusMsgCode::No_Error == errorCode && phoneNum != nullptr && phoneNum.size() == 11 && isDigitalString(phoneNum)) { } else { qWarning() << "error: [InputInfos] onGetPhoneNum errorcode" << errorCode; } } void InputInfos::onClearInfo() { m_pVerCodeLE->clear(); } PhoneAuthWidget::PhoneAuthWidget(QWidget *parent) { initUI(); initConnect(); setQSS(); } void PhoneAuthWidget::initUI() { QVBoxLayout *phoLayout = new QVBoxLayout(this); phoLayout->setMargin(0); m_pPhoTitleLB = new QLabel(this); m_pPhoTitleLB->setText(tr("Verification by phoneNum")); m_pPhoTitleLB->setProperty("class", "titleLB"); phoLayout->addWidget(m_pPhoTitleLB, 0, Qt::AlignHCenter); phoLayout->addSpacing(16); m_pPhoPromptMsgLB = new QLabel(this); m_pPhoPromptMsgLB->setText(tr("「 Use SMS to verification 」")); m_pPhoPromptMsgLB->setProperty("class", "PromptText"); phoLayout->addWidget(m_pPhoPromptMsgLB, 0, Qt::AlignHCenter); m_pPhoErrorMsgLB = new QLabel(this); m_pPhoErrorMsgCloneLB = new QLabel(this); m_pPhoErrorMsgLB->setProperty("class", "ErrorMsg"); m_pPhoErrorMsgCloneLB->setProperty("class", "ErrorMsg"); hidePhoneErrorMsg(); phoLayout->addWidget(m_pPhoErrorMsgLB, 0, Qt::AlignHCenter); phoLayout->addWidget(m_pPhoErrorMsgCloneLB, 0, Qt::AlignHCenter); m_pPhoInputInfos = new InputInfos(this); phoLayout->addWidget(m_pPhoInputInfos, 0, Qt::AlignHCenter); m_pPhoSubmitBT = new QPushButton(this); m_pPhoSubmitBT->setFocusPolicy(Qt::NoFocus); m_pPhoSubmitBT->setText(tr("commit")); m_pPhoSubmitBT->setProperty("class", "BindBT"); m_pPhoSubmitBT->setCursor(QCursor(Qt::PointingHandCursor)); m_pPhoSubmitBT->setEnabled(false); phoLayout->addSpacing(8); phoLayout->addWidget(m_pPhoSubmitBT, 0, Qt::AlignHCenter); phoLayout->addStretch(1); m_pPhoPromptMsgLB->setWordWrap(true); m_hideTimer = new QTimer(this); } void PhoneAuthWidget::initConnect() { connect(m_pPhoInputInfos, &InputInfos::InputStateChanged, this, &PhoneAuthWidget::onInputStateChanged); connect(m_pPhoSubmitBT, &QPushButton::clicked, this, &PhoneAuthWidget::onSubmitBTClick); connect(m_pPhoInputInfos, &InputInfos::getVerCode, this, &PhoneAuthWidget::onGetVerCode); connect(m_pPhoInputInfos, &InputInfos::offlineState, this, &PhoneAuthWidget::onOfflineState); connect(m_pPhoInputInfos, &InputInfos::notGlobal, this, &PhoneAuthWidget::onNotGlobal); connect(m_pPhoInputInfos, &InputInfos::online, this, &PhoneAuthWidget::hidePhoneErrorMsg); connect(m_hideTimer, &QTimer::timeout, this, &PhoneAuthWidget::hidePhoneErrorMsg); connect(this, &PhoneAuthWidget::clearInfo, m_pPhoInputInfos, &InputInfos::onClearInfo); } QSize PhoneAuthWidget::sizeHint() const{ return QWidget::sizeHint(); } void PhoneAuthWidget::hidePhoneErrorMsg() { m_pPhoErrorMsgCloneLB->setFixedHeight(m_pPhoErrorMsgLB->height()); m_pPhoErrorMsgCloneLB->show(); m_pPhoErrorMsgLB->hide(); } void PhoneAuthWidget::showPhoneErrorMsg() { if(m_hideTimer->isActive()) m_hideTimer->stop(); m_pPhoErrorMsgLB->show(); m_pPhoErrorMsgCloneLB->hide(); //QTimer::singleShot(5*1000, this,&PhoneAuthWidget::hidePhoneErrorMsg); m_hideTimer->setSingleShot(true); m_hideTimer->start(5*1000); } void PhoneAuthWidget::onInputStateChanged(InputInfos::InputState input_state) { if(m_pPhoErrorMsgLB->isVisible()) hidePhoneErrorMsg(); if(input_state == InputInfos::InputState::InputFinish) { m_pPhoSubmitBT->setEnabled(true); m_pPhoSubmitBT->setFocusPolicy(Qt::NoFocus); m_pPhoSubmitBT->setStyleSheet("background:#2FB3E8;"); } else { m_pPhoSubmitBT->setEnabled(false); m_pPhoSubmitBT->setStyleSheet("background:rgba(255,255,255,115);"); } } void PhoneAuthWidget::onSubmitBTClick() { QString tel = m_pPhoInputInfos->getPhoneNumer(); QString verCode = m_pPhoInputInfos->getVerificationCode(); DBusMsgCode code = EduPlatformInterface::getInstance()->CheckUserByPhone(getenv("USER"), tel, verCode); switch (code) { case DBusMsgCode::No_Error: Q_EMIT pageMessage(SwitchPage::SwitchToResetPWD, QList()); break; case DBusMsgCode::Error_NetWork: m_pPhoErrorMsgLB->setText(tr("Network not connected~")); break; case DBusMsgCode::Error_VerifyCode_Timeout: m_pPhoErrorMsgLB->setText(tr("Verification Code invalid!")); break; case DBusMsgCode::Error_VerifyCodeDiff: m_pPhoErrorMsgLB->setText(tr("Verification Code incorrect.Please retry!")); break; case Error_ErrTimesOverMax: m_pPhoErrorMsgLB->setText(tr("Failed time over limit!Retry after 1 hour!")); break; default: qWarning() << "[ERROR] verification error code is" << code; m_pPhoErrorMsgLB->setText(tr("verifaction failed!")); break; } if( code != DBusMsgCode::No_Error) { showPhoneErrorMsg(); emit clearInfo(); m_pPhoSubmitBT->setEnabled(false); m_pPhoSubmitBT->setStyleSheet("background:rgba(255,255,255,115);"); } } void PhoneAuthWidget::onGetVerCode() { // DBusMsgCode msgCode = SSOP->m_pRetrievePwdInterface->GetVerificationCode(Cfg->getUsername(), m_pPhoInputInfos->getPhoneNumer()); // switch (msgCode) { // case DBusMsgCode::No_Error: // // 验证码获取无错误 // break; // // TODO 更新错误状态 // default: // break; // } } void PhoneAuthWidget::onOfflineState() { m_pPhoErrorMsgLB->setText(tr("Network not connected~")); showPhoneErrorMsg(); } void PhoneAuthWidget::onNotGlobal() { m_pPhoErrorMsgLB->setText(tr("Network unavailable~")); showPhoneErrorMsg(); } void PhoneAuthWidget::onQRCodeStateChanged(QString username, QString password, int nState) { QRCodeSwepState state = static_cast(nState); switch (state) { case QRCodeSwepState::WaitingSwep: qDebug() << "info: [QRCodePhoneAuthWidget][onQRCodeStateChanged]: waiting user swep qrcode!"; break; case QRCodeSwepState::HaveSwep: qDebug() << "info: [QRCodePhoneAuthWidget][onQRCodeStateChanged]: user has swep code!"; break; case QRCodeSwepState::CancelSwep: qDebug() << "info: [QRCodePhoneAuthWidget][onQRCodeStateChanged]: user cancel swep code!"; break; case QRCodeSwepState::ConfirmSuccess: { qDebug() << "info: [QRCodePhoneAuthWidget][onQRCodeStateChanged]: user = [" << username << "] confirm success!"; // if(username != Cfg->getUsername()) // { // resetQRCService(); // // TODO 更新错误信息 // } // else // emit pageMessage(PageMessage::JumpToNewPswSet, QList()); // break; } case QRCodeSwepState::QRCodeInvalid: { qDebug() << "info: [QRCodePhoneAuthWidget][onQRCodeStateChanged]: qrcode invalid!"; // resetQRCService(); break; } default: break; } } void PhoneAuthWidget::setQSS() { QString style_sheet =".PromptText{" "font-size:24px;" "color: rgba(255,255,255,192);" "}" ".BindBT{" "background:rgba(255,255,255,115);" "width:316px;" "height:64px;" "border-radius:16px;" "}" ".ErrorMsg{" "color:#FD625E;" "font-size:14px;" "}" ".titleLB{" "color:#FFFFFF;" "font-size:32px;" "}"; setStyleSheet(style_sheet); } MyLineEdit::MyLineEdit(QWidget *parent) { this->setStyleSheet("padding:10px 2px 10px 2px;" "background-color:rgb(255,255,255,0);" "color:grey;" "font-size:16px"); setText(tr("Verification code")); } void MyLineEdit::focusInEvent(QFocusEvent *e) { QLineEdit::focusInEvent(e); if(text() == tr("Verification code")) this->clear(); this->setStyleSheet("padding:10px 2px 10px 2px;" "background-color:rgb(255,255,255,0);" "color:black;" "font-size:16px"); } void MyLineEdit::focusOutEvent(QFocusEvent *e) { QLineEdit::focusOutEvent(e); if(text().isEmpty()) { this->setStyleSheet("padding:10px 2px 10px 2px;" "background-color:rgb(255,255,255,0);" "color:grey;" "font-size:16px"); setText(tr("Verification code")); } } GetPhoneNumThread::GetPhoneNumThread(QObject *parent) : QThread(parent) { //获取手机号的dbus理论上也是耗时操作,故放到线程里面去请求 } void GetPhoneNumThread::run() { QString phoneNum = ""; DBusMsgCode ret = DBusMsgCode::Error_UnknownReason; /**极其不良的重试策略,如果没有服务或者网络问题,会导致不停地重试,应该做优化 * 1、需要后台服务支持,如果不存在dbus服务,应该直接报错,当前绑定失败不意味着服务不存在,判断逻辑需要研究 * 2、监听网络变化,网络状态变化时,断网时及时提醒用户网络未连接;联网时,如未获取到已绑定的手机号,需要重新获取; * 网络异常时,固定次数的重试,都失败后提示用户网络请求异常,并提供可手动刷新的策略 * */ while (DBusMsgCode::No_Error != ret) { ret = AccountsInterface::getInstance()->GetUserPhone(getenv("USER"), phoneNum); Q_EMIT resultReady(ret, phoneNum); sleep(5); } } bool isDigitalString(QString s) { for(int i = 0; i< s.length(); i++) { if(s.at(i) > '9' || s.at(i) < '0') { qDebug() << "phoneNum error at" << i+1 << "position"; return false; } if(i == 2) i += 4; } for(int i = 3; i< 7; i++) { if(s.at(i) != '*') { qDebug() << "phoneNum error at" << i+1 << "position unencrypted"; return false; } } return true; } ukui-screensaver/src/configuration.h0000644000175000017500000000317714205074704016613 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef CONFIGURATION_H #define CONFIGURATION_H #ifndef QT_NO_KEYWORDS #define QT_NO_KEYWORDS #endif //#include "gsettings.h" #include #include "screensaver.h" class QGSettings; class Configuration : public QObject { Q_OBJECT public: explicit Configuration(QObject *parent = nullptr); public: ScreenSaver *getScreensaver(); static Configuration *instance(QObject *parent = nullptr); QString getBackground(); bool xscreensaverActivatedWhenIdle(); bool lockWhenXScreensaverActivated(); public Q_SLOTS: void onConfigurationChanged(QString key); private: QString getXScreensaverPath(const QString &theme); private: QGSettings *gsettings; QGSettings *bgGsettings; QString mode; QList themes; QString background; bool idleActivationEnabled; bool lockEnabled; int imageTSEffect; int imageSwitchInterval; static Configuration *instance_; }; #endif // CONFIGURATION_H ukui-screensaver/src/logind.h0000644000175000017500000000210514205074704015206 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef LOGIND_H #define LOGIND_H #include #include class QDBusServiceWatcher; class LogindIntegration : public QObject { Q_OBJECT public: explicit LogindIntegration(QObject *parent = nullptr); ~LogindIntegration() override; Q_SIGNALS: void requestLock(); void requestUnlock(); void connectedChanged(); private: }; #endif ukui-screensaver/src/eduplatforminterface.cpp0000644000175000017500000003163114205074760020500 0ustar fengfeng/** * Copyright (C) 2018 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, 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 "eduplatforminterface.h" const QString STR_EDU_SERVICE = "cn.kylinos.SSOBackend"; const QString STR_EDU_PATH = "/cn/kylinos/SSOBackend"; EduPlatformInterface* EduPlatformInterface::m_instance = nullptr; EduPlatformInterface::EduPlatformInterface(const QString &strService,const QString &strPath,\ const QDBusConnection &connection, QObject *parent)\ :QDBusAbstractInterface(strService,strPath,getInterfaceName(),connection,parent) { initConnect(); } EduPlatformInterface* EduPlatformInterface::getInstance() { static QMutex mutex; mutex.lock(); if(m_instance == nullptr || !m_instance->isValid()) m_instance = new EduPlatformInterface(STR_EDU_SERVICE, STR_EDU_PATH, QDBusConnection::systemBus()); mutex.unlock(); return m_instance; } void EduPlatformInterface::initConnect() { } DBusMsgCode EduPlatformInterface::GetLoginQR(QPixmap &qrcode) { QDBusMessage message = call("GetLoginQR"); if(QDBusMessage::ErrorMessage == message.type()) { qDebug() << "info: [EduPlatformInterface][GetLoginQR]: DBus Connect Failed!"; return DBusMsgCode::Error_NoReply; } QList argvs = message.arguments(); if(argvs.size() != 2) { qDebug() << "info: [EduPlatformInterface][GetLoginQR]: DBus arguments error!"; return DBusMsgCode::Error_ArgCnt; } int state = argvs.at(1).value(); if(state != 0) { qDebug() << "info: [EduPlatformInterface][GetLoginQR]: DBus request failed!"; //return static_cast(state); return DBusMsgCode::Error_ArgCnt; } const QString url = argvs.at(0).value(); DBusMsgCode download_errcode = getQRCodeFromURL(url, qrcode); if(download_errcode != DBusMsgCode::No_Error) return download_errcode; qrcode = beautifyQRCode(qrcode); return DBusMsgCode::No_Error; } DBusMsgCode EduPlatformInterface::GetLoginQRUrl(QString &url) { QDBusMessage message = call("GetLoginQR"); if(QDBusMessage::ErrorMessage == message.type()) { qDebug() << "info: [EduPlatformInterface][GetLoginQR]: DBus Connect Failed!"; return DBusMsgCode::Error_NoReply; } QList argvs = message.arguments(); if(argvs.size() != 2) { qDebug() << "info: [EduPlatformInterface][GetLoginQR]: DBus arguments error!"; return DBusMsgCode::Error_ArgCnt; } int state = argvs.at(1).value(); if(state != 0) { qDebug() << "info: [EduPlatformInterface][GetLoginQR]: DBus request failed!"; //return static_cast(state); return DBusMsgCode::Error_ArgCnt; } url = argvs.at(0).value(); return DBusMsgCode::No_Error; } DBusMsgCode EduPlatformInterface::BindPhoneNum(const QString &username, const QString &phonenum, const QString &vcode) { QDBusReply reply = call("BindPhoneNum", username, phonenum, vcode); if(!reply.isValid()) { qDebug() << "info: [EduPlatformInterface][BindPhoneNum]: DBus Connect Failed!"; return DBusMsgCode::Error_NoReply; } if(reply.value() != 0) { qDebug() << "info: [EduPlatformInterface][BindPhoneNum]: DBus request failed!"; //return static_cast(reply.value()); return DBusMsgCode::Error_NoReply; } return DBusMsgCode::No_Error; } DBusMsgCode EduPlatformInterface::GetVerifyCode(const QString &phonenum) { QDBusReply reply = call("GetVerifyCode", phonenum); if(!reply.isValid()) { qDebug() << "info: [EduPlatformInterface][GetVerifyCode]: DBus Connect Failed!"; return DBusMsgCode::Error_NoReply; } // if(reply.value() != 0) // 默认0为成功 { qDebug() << "info: [EduPlatformInterface][GetVerifyCode]: DBus request failed!"; //return static_cast(reply.value()); return DBusMsgCode::Error_NoReply; } return DBusMsgCode::No_Error; } DBusMsgCode EduPlatformInterface::SetPinCode(const QString &username, const QString &pincode) { QDBusReply reply = call("SetPinCode", username, pincode); if(!reply.isValid()) { qDebug() << "info: [][]: DBus connect failed!"; return DBusMsgCode::Error_NoReply; } if(!reply.value()) { return DBusMsgCode::No_Error; } return DBusMsgCode::Error_NoReply; } DBusMsgCode EduPlatformInterface::CheckToken(const QString &username) { QDBusReply reply = call("CheckToken", username); if(!reply.isValid()) { qDebug() << "info: [EduPlatformInterface][RefreshToken]: DBus connect failed!"; return DBusMsgCode::Error_NoReply; } // if(reply.value()) // { // qDebug() << "info: [EduPlatformInterface][RefreshToken]: DBus return-result failed!"; // } switch (reply.value()) { case 0: return DBusMsgCode::No_Error; default: return static_cast(reply.value()); } } DBusMsgCode EduPlatformInterface::CheckPhoneNumBind(const QString &username, bool &isBind) { QDBusReply reply = call("CheckPhoneNumBind", username); if(!reply.isValid()) { qDebug() << "info: [EduPlatformInterface][CheckPhoneNumBind]: DBus connect failed!"; return DBusMsgCode::Error_NoReply; } // TODO 需要改接口 接口有问题 if(reply.value() == 0) { isBind = false; return DBusMsgCode::No_Error; } if(reply.value() == 1) { isBind = true; return DBusMsgCode::No_Error; } isBind = true; return DBusMsgCode::Error_NoReply; } DBusMsgCode EduPlatformInterface::CheckPincodeSet(const QString &username, bool &isBind) { QDBusReply reply = call("CheckPincodeSet", username); if(!reply.isValid()) { qDebug() << "info: [EduPlatformInterface][CheckPincodeSet]: DBus connect failed!"; return DBusMsgCode::Error_NoReply; } if(reply.value() == 0) { isBind = true; return DBusMsgCode::No_Error; } if(reply.value() == 1) { isBind = false; return DBusMsgCode::No_Error; } return DBusMsgCode::Error_NoReply; } DBusMsgCode EduPlatformInterface::CheckUserByPhone(const QString &username, const QString &phonenum, const QString &vcode) { QDBusReply reply = call("CheckUserByPhone", username, phonenum, vcode); if(!reply.isValid()) { qDebug() << "info: [EduPlatformInterface][CheckUserByPhone]: DBus connect failed!"; return DBusMsgCode::Error_NoReply; } return static_cast(reply.value()); } DBusMsgCode EduPlatformInterface::CheckUserByQR(QPixmap &qrcode) { QDBusMessage message = call("CheckUserByQR"); if(QDBusMessage::ErrorMessage == message.type()) { qDebug() << "info: [EduPlatformInterface][CheckUserByQR]: DBus Connect Failed!"; return DBusMsgCode::Error_NoReply; } QList argvs = message.arguments(); if(argvs.size() != 2) { qDebug() << "info: [EduPlatformInterface][CheckUserByQR]: DBus arguments error!"; return DBusMsgCode::Error_ArgCnt; } int state = argvs.at(1).value(); if(state != 0) { qDebug() << "info: [EduPlatformInterface][CheckUserByQR]: DBus request failed!"; //return static_cast(state); return static_cast(state); } const QString url = argvs.at(0).value(); DBusMsgCode download_errcode = getQRCodeFromURL(url, qrcode); if(download_errcode != DBusMsgCode::No_Error) return download_errcode; qrcode = beautifyQRCode(qrcode); return DBusMsgCode::No_Error; } DBusMsgCode EduPlatformInterface::CheckUserByQR(QString &url) { QDBusMessage message = call("CheckUserByQR"); if(QDBusMessage::ErrorMessage == message.type()) { qDebug() << "info: [EduPlatformInterface][CheckUserByQR]: DBus Connect Failed!"; return DBusMsgCode::Error_NoReply; } QList argvs = message.arguments(); if(argvs.size() != 2) { qDebug() << "info: [EduPlatformInterface][CheckUserByQR]: DBus arguments error!"; return DBusMsgCode::Error_ArgCnt; } int state = argvs.at(1).value(); if(state != 0) { qDebug() << "info: [EduPlatformInterface][CheckUserByQR]: DBus request failed!"; //return static_cast(state); return static_cast(state); } url = argvs.at(0).value(); return DBusMsgCode::No_Error; } DBusMsgCode EduPlatformInterface::getQRCodeFromURL(const QString &url, QPixmap &qrcode) { // 从网络上下载二维码 并加载到qrcode QNetworkRequest request; QNetworkAccessManager networkManager; request.setUrl(url); QNetworkReply *reply = networkManager.get(request); // 超时 \ 同步处理 QEventLoop loop; QTimer timer; connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit); connect(&timer, &QTimer::timeout, &timer, &QTimer::stop); connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit); timer.start(3000); loop.exec(); if(!timer.isActive()) { reply->abort(); qDebug() << "info: [EduPlatformInterface][GetLoginQR]: Get QRCode timeout!"; return DBusMsgCode::Error_QR_Get_Timeout; } timer.stop(); // 生成二维码 if(reply->error() != QNetworkReply::NoError) { qDebug() << "info: [EduPlatformInterface][GetLoginQR]: Network error!" << reply->errorString(); return DBusMsgCode::Error_NetWork; } QByteArray bytes = reply->readAll(); qrcode.loadFromData(bytes); return DBusMsgCode::No_Error; } // 美化图片 QPixmap EduPlatformInterface::beautifyQRCode(QPixmap &pixImg) { // 去除白边 QImage img = pixImg.toImage(); int rect_x, rect_y, rect_width, rect_height; for(int i = 0;i < img.size().width();i++) { bool isEnd = false; for(int j = 0;j < img.size().height();j++) { if(img.pixel(i, j) != qRgb(255, 255, 255)) { rect_x = i - 1; rect_y = j - 1; rect_width = img.size().width() - 2 * rect_x; rect_height = img.size().height() - 2 * rect_y; isEnd = true; break; } } if(isEnd) break; } QPixmap dealImg = QPixmap::fromImage(img.copy(rect_x, rect_y, rect_width, rect_height)).scaledToWidth(150); img = dealImg.toImage(); // 添加微信log // QPixmap piximg_wechat(WECHAT_LOG_PATH); // QImage img_wechat = piximg_wechat.scaledToWidth(150).toImage(); // for(int i = 0;i < img.size().width();++i) // { // for(int j = 0;j < img.size().height(); ++j) // { // if(img.pixel(i, j) > qRgb(125, 125, 125)) // { // int r = qRed(img_wechat.pixel(i, j)); // int g = qGreen(img_wechat.pixel(i, j)); // int b = qBlue(img_wechat.pixel(i, j)); // int alpha = qAlpha(img_wechat.pixel(i, j)); // if(alpha == 0) r = 255, b = 255, g = 255; // else r = 0x25, g = 0xAC, b = 0x36; // img.setPixelColor(i, j, QColor(r, g, b, alpha)); // //img.setPixel(i, j, qRgb(0, 255, 0)); // } // } // } dealImg = QPixmap::fromImage(img); return dealImg; } //void EduPlatformInterface::onScanState(QString username, QString password, int state) //{ // switch(state) // { // case 4: // 扫码并确认完成 // qDebug() << "=================扫码并确认完成" << username << password; // emit qrcodeScanState(QRCodeSwepState::ConfirmSuccess, username, password); // break; // case 2: // 用户扫码 // qDebug() << "=================用户扫码" << username << password; // emit qrcodeScanState(QRCodeSwepState::HaveSwep, "", ""); // break; // case 3: // 用户取消扫码 // qDebug() << "=================用户取消扫码" << username << password; // emit qrcodeScanState(QRCodeSwepState::CancelSwep, "", ""); // break; // case 5: // 二维码超时 // qDebug() << "=================二维码超时" << username << password; // emit qrcodeScanState(QRCodeSwepState::QRCodeInvalid, "", ""); // break; // default: // break; // } //} ukui-screensaver/src/assets.qrc0000644000175000017500000001115414205074704015576 0ustar fengfeng assets/authdialog.qss assets/show-password.png assets/hide-password.png assets/keyboard.png assets/switchGreeter.png assets/switchUser.png assets/waiting.png assets/capslock.png assets/combobox_down.png assets/scrollbar_down.png assets/scrollbar_down_clicked.png assets/scrollbar_down_hover.png assets/scrollbar_up.png assets/scrollbar_up_clicked.png assets/scrollbar_up_hover.png assets/unlock-button.png assets/unlock-button-hover.png assets/unlock-button-pressed.png assets/iconFace.png assets/iconFace.svg assets/powerManager.png assets/lock.png assets/logout.png assets/shutdown.png assets/suspend.png assets/hibernate.png assets/reboot.png assets/bio-login.png assets/password-login.png assets/weather/68.png assets/weather/67.png assets/weather/66.png assets/weather/63.png assets/weather/62.png assets/weather/60.png assets/weather/59.png assets/weather/58.png assets/weather/56.png assets/weather/55.png assets/weather/53.png assets/weather/52.png assets/weather/51.png assets/weather/49.png assets/weather/48.png assets/weather/47.png assets/weather/45.png assets/weather/43.png assets/weather/41.png assets/weather/40.png assets/weather/39.png assets/weather/38.png assets/weather/36.png assets/weather/35.png assets/weather/33.png assets/weather/31.png assets/weather/30.png assets/weather/29.png assets/weather/28.png assets/weather/27.png assets/weather/24.png assets/weather/22.png assets/weather/21.png assets/weather/20.png assets/weather/19.png assets/weather/18.png assets/weather/17.png assets/weather/16.png assets/weather/15.png assets/weather/14.png assets/weather/13.png assets/weather/11.png assets/weather/10.png assets/weather/9.png assets/weather/8.png assets/weather/7.png assets/weather/6.png assets/weather/5.png assets/weather/4.png assets/weather/3.png assets/weather/2.png assets/weather/1.png assets/weather/0.png assets/intel/message.png assets/intel/more.png assets/intel/slide_unlock.png assets/intel/qr-code.png assets/intel/wifi.png assets/intel/delete.svg assets/intel/pin.png assets/intel/wechat.png assets/intel/back.png assets/intel/cancel.png assets/intel/qr-reload.png assets/intel/icon-wechat-noqrcode.png assets/intel/icon-no-signal.png assets/intel/icon-wired.png assets/intel/icon-wifi.png assets/intel/sms.png assets/intel/phone.png assets/intel/icon-backspace.png assets/intel/lock.png assets/intel/logout.png assets/intel/shutdown.png assets/intel/reboot.png assets/intel/powerManager.png assets/intel/keyboard.png ukui-screensaver/src/logind.cpp0000644000175000017500000000452514205074704015551 0ustar fengfeng/* * Copyright (C) 2020 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "logind.h" #include #include #include #include #include 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"); const static QString login1SessionInterface = QStringLiteral("org.freedesktop.login1.Session"); LogindIntegration::LogindIntegration(QObject *parent) : QObject(parent) { QDBusInterface loginInterface(login1Service, login1Path, login1ManagerInterface, QDBusConnection::systemBus()); QDBusReply sessionPath = loginInterface.call("GetSessionByPID",(quint32) QCoreApplication::applicationPid()); if(!sessionPath.isValid()){ qWarning()<< "Get session error:" << sessionPath.error(); } else{ QString session = sessionPath.value().path(); QDBusConnection::systemBus().connect(login1Service, session, login1SessionInterface, QStringLiteral("Lock"), this, SIGNAL(requestLock())); QDBusConnection::systemBus().connect(login1Service, session, login1SessionInterface, QStringLiteral("Unlock"), this, SIGNAL(requestUnlock())); } return; } LogindIntegration::~LogindIntegration() = default; ukui-screensaver/src/pam-tally.c0000644000175000017500000002312514205074760015634 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "pam-tally.h" #include #include #include #include #include #include #include #include #include #include char shm_tally_real[128]; #define FILE_MODE (S_IRUSR | S_IWUSR) #define CONFIG_FILE "/usr/share/lightdm/lightdm.conf.d/96-kylin-setting.conf" struct tallylog { char fail_line[52]; /* rhost or tty of last failure */ uint16_t reserved; /* reserved for future use */ uint16_t fail_cnt; /* failures since last success */ uint64_t fail_time; /* time of last failure */ }; static int get_is_open_other_authentication() { char buf[128]; FILE *config_file; if( (config_file = fopen(CONFIG_FILE, "r")) == NULL) { //gs_debug("open %s failed", CONFIG_FILE); return 0; } int open_other_authentication = 0; while(fgets(buf, sizeof(buf), config_file)) { if(strlen(buf) == 0 || buf[0] == '#') { memset(buf, sizeof(buf), 0); continue; } if(buf[strlen(buf)-1] == '\n') buf[strlen(buf)-1] = '\0'; char *p = strchr(buf, '='); if(!p) continue; *p = '\0'; size_t len = strlen(buf); if(len == 0) continue; //去掉=之前的空格 while(len--) if(buf[len] == ' ' || buf[len] == '\t') buf[len] = '\0'; if(strcmp(buf, "open-other-authentication") != 0) continue; p++; len = strlen(p); if(len == 0) break; //去掉等号之后的空格 while(*p == ' ' || *p == '\t') { p++; len--; } //去掉尾部空格 while(len--) if(*(p+len) == ' ' || *(p+len) == '\t') *(p+len) = '\0'; if(*p == '0') break; if(*p == '1') { open_other_authentication = 1; break; } } fclose(config_file); return open_other_authentication; } static int get_pam_tally(int *deny, int *unlock_time , int *root_unlock_time) { char buf[128]; FILE *auth_file; if( (auth_file = fopen("/etc/pam.d/common-auth", "r")) == NULL) return -1; while(fgets(buf, sizeof(buf), auth_file)) { if(strlen(buf) == 0 || buf[0] == '#') continue; if(!strstr(buf, "deny")) continue; char *ptr = strtok(buf, " \t"); while(ptr) { if(strncmp(ptr, "deny=", 5)==0){ sscanf(ptr, "deny=%d", deny); // fprintf(stderr, "-------------------- deny=%d\n", *deny); } if(strncmp(ptr, "unlock_time=", 12)==0){ sscanf(ptr, "unlock_time=%d", unlock_time); // fprintf(stderr, "-------------------- unlock_time=%d\n", *unlock_time); } if(strncmp(ptr, "root_unlock_time=", 17)==0){ sscanf(ptr, "root_unlock_time=%d", root_unlock_time); // fprintf(stderr, "-------------------- root_unlock_time=%d\n", *root_unlock_time); } ptr = strtok(NULL, " \t"); } return 1; } return 0; } static void set_shm_tally_real() { sprintf(shm_tally_real, "%s_%d", SHM_TALLY, getuid()); } int pam_tally_init() { int fd; int deny = 0, unlock_time = 0 , root_unlock_time = 0; pam_tally *tally_ptr; set_shm_tally_real(); printf("shm path =========== : %s\n", shm_tally_real); shm_unlink(shm_tally_real); if(get_is_open_other_authentication()) { return 0; } if(!get_pam_tally(&deny, &unlock_time,&root_unlock_time)) { return 0; } if(deny <= 0) deny = 0; if(unlock_time <= 0) unlock_time = 0; if( (fd = shm_open(shm_tally_real, O_RDWR | O_CREAT, FILE_MODE)) == -1) { printf("shm_open error: %s\n", strerror(errno)); return -1; } ftruncate(fd, sizeof(pam_tally)); if( (tally_ptr = mmap(NULL, sizeof(pam_tally), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { close(fd); return -1; } close(fd); tally_ptr->deny = deny; tally_ptr->unlock_time = unlock_time; tally_ptr->failed = 0; tally_ptr->lock_start_time = 0; tally_ptr->root_unlock_time = root_unlock_time; return 1; } static pam_tally* pam_tally_memory() { int fd; pam_tally *tally_ptr; set_shm_tally_real(); if( (fd = shm_open(shm_tally_real, O_RDWR, FILE_MODE)) == -1) { return NULL; } if( (tally_ptr = mmap(NULL, sizeof(pam_tally), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { close(fd); return NULL; } close(fd); return tally_ptr; } int pam_tally_is_enbled() { int fd; set_shm_tally_real(); if( (fd = shm_open(shm_tally_real, O_RDONLY, FILE_MODE)) == -1) { printf("shm_open error: %s\n", strerror(errno)); close(fd); return 0; } pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL){ close(fd); return -1; } if(tally_ptr->deny == 0 || tally_ptr->unlock_time == 0){ close(fd); return 0; } close(fd); return 1; } int pam_tally_add_failed() { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return -1; tally_ptr->failed++; //如果失败次数达到上限,开始计时 if(tally_ptr->failed >= tally_ptr->deny) tally_ptr->lock_start_time = time(NULL); return 0; } int pam_tally_clear_failed() { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return -1; tally_ptr->failed = 0; tally_ptr->lock_start_time = 0; return 0; } int pam_tally_failure_is_out() { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return -1; return (tally_ptr->failed >= tally_ptr->deny ? 1 : 0); } int pam_tally_deny() { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return -1; return tally_ptr->deny; } int pam_tally_failed_count() { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return -1; return tally_ptr->failed; } int pam_tally_unlock_time() { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return -1; printf("########################### unlock time = %d\n", tally_ptr->unlock_time); return tally_ptr->unlock_time; } int pam_tally_is_canUnlock() { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return -1; if(tally_ptr->failed >= tally_ptr->deny && time(NULL) - tally_ptr->lock_start_time < tally_ptr->unlock_time) return 0; return 1; } int pam_modutil_read(int fd, char *buffer, int count) { int block, offset = 0; while (count > 0) { block = read(fd, &buffer[offset], count); if (block < 0) { if (errno == EINTR) continue; return block; } if (block == 0) return offset; offset += block; count -= block; } return offset; } void get_tally(uid_t uid, int *tfile, struct tallylog *tally) { char filename[50]={0}; sprintf(filename,"%s","/tmp/.tallylog"); void *void_tally = tally; if ((*tfile = open(filename, O_RDONLY)) == -1){ fprintf(stderr, "open tallylog failed \n"); return ; } if (lseek(*tfile, (off_t)uid*(off_t)sizeof(*tally), SEEK_SET) == (off_t)-1) { fprintf(stderr, "lseek tallylog failed \n"); close(*tfile); return ; } if (pam_modutil_read(*tfile, void_tally, sizeof(*tally)) != sizeof(*tally)) { fprintf(stderr, "read tallylog failed \n"); memset(tally, 0, sizeof(*tally)); } close(*tfile); tally->fail_line[sizeof(tally->fail_line)-1] = '\0'; } int pam_tally_unlock_time_left(int *fail_cnt,int *left_time, int *deny, int *fail_time, int *unlock_time1) { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL) return 0; int unlock_time = tally_ptr->unlock_time; *deny = tally_ptr->deny; if(unlock_time == 0) return 0; int tfile = -1; uid_t uid = getuid(); struct tallylog tally; tally.reserved = 0; tally.fail_cnt = 0; tally.fail_time = 0; get_tally(uid,&tfile,&tally); if(tally.fail_cnt<*deny) return 0; //连续输错,时间累加 if (tally.fail_cnt >= (*deny)*2 && tally.fail_cnt < (*deny)*3){ unlock_time = unlock_time*2; } else if(tally.fail_cnt >= (*deny)*3 && tally.fail_cnt < (*deny)*4){ unlock_time = unlock_time*8; } else if (tally.fail_cnt >= (*deny)*4){ *fail_cnt = 0xFFFF;//永久锁定 return 0; } int unlock_time_left = unlock_time - ((long)time(NULL) - tally.fail_time); *fail_time = tally.fail_time; *unlock_time1 = unlock_time; *left_time = unlock_time_left > 0 ? unlock_time_left : 0; *fail_cnt = tally.fail_cnt; return *left_time; } int pam_tally_root_unlock_time_left(int *fail_cnt,int *left_time, int *deny1) { pam_tally *tally_ptr; if((tally_ptr = pam_tally_memory()) == NULL){ return 0; } int root_unlock_time = tally_ptr->root_unlock_time; int deny = tally_ptr->deny; if(root_unlock_time == 0) return 0; int tfile = -1; uid_t uid = getuid(); struct tallylog tally; tally.reserved = 0; tally.fail_cnt = 0; tally.fail_time = 0; get_tally(uid,&tfile,&tally); if(tally.fail_cnt= (deny)*2 && tally.fail_cnt < (deny)*3){ root_unlock_time = root_unlock_time*2; } else if(tally.fail_cnt >= (deny)*3 && tally.fail_cnt < (deny)*4){ root_unlock_time = root_unlock_time*8; } else if (tally.fail_cnt >= (deny)*4){ *fail_cnt = 0xFFFF;//永久锁定 return 0; } int root_unlock_time_left = root_unlock_time - ((long)time(NULL) - tally.fail_time); *left_time = root_unlock_time_left > 0 ? root_unlock_time_left : 0; *fail_cnt = tally.fail_cnt; return *left_time; } ukui-screensaver/src/weathermanager.h0000644000175000017500000000567314205074704016741 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * Authors: ZHAI Kang-ning **/ #ifndef WEATHERMANAGER_H #define WEATHERMANAGER_H #include #include #include #include class QNetworkAccessManager; class QNetworkReply; class LocalWeatherInfo; class WeatherManager : public QObject { Q_OBJECT public: explicit WeatherManager(QObject *parent = nullptr); Q_SIGNALS: void onWeatherUpdate(QString city, QString cond, QString temperature); private Q_SLOTS: void replyFinished(QNetworkReply *); public: void getWeather(); QPixmap getWeatherIcon(); QPixmap getWeatherIcon(QString cond); private: bool updateLocation();//更新位置,从用户设置获取城市信息,如有多个,只取第一个,未对接 void weatherRequest(); bool getLogcalWeather(); QString getLogcalCityId(); private: QString m_city_id; // "101030100" 默认天津 QString m_city_name; QString m_cond_txt; //天气条件 晴、阴等 QString m_temperature;//温度 10、20等 QNetworkAccessManager *m_net_manager; QTimer *m_timer; QGSettings *m_settings; LocalWeatherInfo *m_local_weather_info; }; class LocalWeatherInfo : QObject { //"1920-08-27 10:17:42,101310204,澄迈,小雨,95%,25℃,北风,1级," 时间,城市编码,城市名称,天气,湿度,温度,风向,风力 Q_OBJECT public: explicit LocalWeatherInfo(QObject *parent = nullptr); private: QString m_update_time; QString m_city_id; QString m_city_name; QString m_cond_text; QString m_air_humidity; QString m_temperature; QString m_wind_direction; QString m_wind_force; public: bool isTimeValid(); void setTime(QString time); QString getTime(); void setCityId(QString cityId); QString getCityId(); void setCityName(QString cityName); QString getCityName(); void setCondText(QString condText); QString getCondText(); void setAirHumidity(QString airHumidity); QString getAirHumidity(); void setTemperature(QString temperature); QString getTemperature(); void setWindDirection(QString windDirection); QString getWindDirection(); void setWindForce(QString windForce); QString getWindForce(); }; #endif // WEATHERMANAGER_H ukui-screensaver/src/networkwatcher.h0000644000175000017500000000311214205074760017002 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef NETWORKWATCHER_H #define NETWORKWATCHER_H #include #include #include enum NMState{ NM_STATE_UNKNOWN = 0, NM_STATE_ASLEEP = 10, NM_STATE_DISCONNECTED = 20, NM_STATE_DISCONNECTING = 30, NM_STATE_CONNECTING = 40, NM_STATE_CONNECTED_LOCAL = 50, NM_STATE_CONNECTED_SITE = 60, NM_STATE_CONNECTED_GLOBAL = 70, NM_STATE_CONNECTED_LIMIT = 80 }; class NetWorkWatcher : public QObject { Q_OBJECT public: NetWorkWatcher(QObject *parent=nullptr); Q_SIGNALS: void NetworkStateChanged(uint state); private Q_SLOTS: void onNetworkStateChanged(uint state); void getIp(QHostInfo info); public: void checkOnline(); bool isConnect(); private: QDBusInterface *network; }; #endif ukui-screensaver/src/pam-tally.h0000644000175000017500000000334414205074760015642 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef PAM_TALLY_H #define PAM_TALLY_H #include #ifdef __cplusplus extern "C" { #endif #define SHM_TALLY "/shm_tally" struct _pam_tally { int deny; //失败次数上限 int unlock_time; //普通用户失败次数达到上限后,多少秒之后才能解锁 int root_unlock_time; //root用户失败次数达到上限后,多少秒之后才能解锁 int failed; //当前失败的次数 time_t lock_start_time; //失败次数达到上限后,开始计时 }; typedef struct _pam_tally pam_tally; int pam_tally_init(); int pam_tally_add_failed(); int pam_tally_clear_failed(); int pam_tally_falure_is_out(); int pam_tally_deny(); int pam_tally_failed_count(); int pam_tally_unlock_time(); int pam_tally_is_enbled(); int pam_tally_is_canUnlock(); int pam_tally_unlock_time_left(int *fail_cnt, int *left_time, int *deny, int *fail_time, int *unlock_time); int pam_tally_root_unlock_time_left(int *fail_cnt, int *left_time, int *deny); #ifdef __cplusplus } #endif #endif // PAM_TALLY_H ukui-screensaver/src/displaymanager.cpp0000644000175000017500000001021614205074704017267 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "displaymanager.h" #include #include #include #include #include #include "types.h" DisplayManager::DisplayManager(QObject *parent) : QObject(parent), _canSwitch(false), _displayType(""), process(nullptr) { if(getenv("XDG_SEAT_PATH")){ _displayType = "lightdm"; } else if(process_is_running ("gdm") || process_is_running("gdm3") || process_is_running("gdm-binary")){ _displayType = "gdm"; process = new QProcess(this); } if(_displayType == "lightdm"){ char *seatPath = getenv("XDG_SEAT_PATH"); qDebug() << seatPath; dmService = new QDBusInterface(DM_DBUS_SERVICE, seatPath, DBUS_PROP_INTERFACE, QDBusConnection::systemBus()); dmSeatService = new QDBusInterface(DM_DBUS_SERVICE, seatPath, DM_SEAT_INTERFACE, QDBusConnection::systemBus()); getProperties(); }else if(_displayType == "gdm"){ _canSwitch = true; } } bool DisplayManager::canSwitch() { return _canSwitch; } bool DisplayManager::hasGuestAccount() { return _hasGuestAccount; } QString DisplayManager::getDisplayType() { return _displayType; } void DisplayManager::switchToGreeter() { qDebug()<<"111111111111111111111111111111111111111111111111111111"; if(_displayType == "lightdm"){ QDBusMessage ret = dmSeatService->call("SwitchToGreeter"); handleDBusError(ret); } else if(_displayType == "gdm"){ QString cmd = "gdmflexiserver"; if(QFile("/usr/bin/gdmflexiserver").exists()){ process->waitForFinished(3000); process->start(cmd); } } } void DisplayManager::switchToUser(const QString &userName) { if(_displayType != "lightdm") return ; QDBusMessage ret = dmSeatService->call("SwitchToUser", userName, ""); handleDBusError(ret); } void DisplayManager::switchToGuest() { if(_displayType != "lightdm") return ; QDBusMessage ret = dmSeatService->call("SwitchToGuest", ""); handleDBusError(ret); } void DisplayManager::getProperties() { QDBusMessage ret = dmService->call("GetAll", DM_SEAT_INTERFACE); handleDBusError(ret); const QDBusArgument &arg = ret.arguments().at(0).value(); qDebug() << arg.currentType(); arg.beginMap(); while(!arg.atEnd()) { QString key; QVariant value; arg.beginMapEntry(); arg >> key >> value; arg.endMapEntry(); if(key == "CanSwitch") { _canSwitch = value.toBool(); } else if(key == "HasGuestAccount") { _hasGuestAccount = value.toBool(); } } arg.endMap(); } bool DisplayManager::process_is_running(QString name) { int num_processes; QString command = "pidof " + name + " | wc -l"; FILE *fp = popen(command.toLatin1().data(), "r"); if (fscanf(fp, "%d", &num_processes) != 1) num_processes = 0; pclose(fp); if (num_processes > 0) { return true; } else { return false; } } void DisplayManager::handleDBusError(const QDBusMessage &msg) { if(msg.type() == QDBusMessage::ErrorMessage) { qWarning() << msg.errorMessage(); } } ukui-screensaver/src/interface.cpp0000644000175000017500000001541314205074704016233 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "interface.h" #include #include #include #include #include #include #include #include #include Interface::Interface(QObject *parent) : QObject(parent), m_timerCount(0), settings(nullptr), m_timer(nullptr) { lockState = false; m_logind = new LogindIntegration(this); connect(m_logind, &LogindIntegration::requestLock, this, [this]() { this->onShowScreensaver(); } ); connect(m_logind, &LogindIntegration::requestUnlock, this, [this]() { // process.terminate(); process.kill(); } ); connect(&process, static_cast(&QProcess::finished), [=](int exitCode, QProcess::ExitStatus exitStatus){ emitLockState(false); }); settings = new QGSettings("org.ukui.screensaver","",this); QDBusInterface *iface = new QDBusInterface("org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", QDBusConnection::systemBus(), this); connect(iface, SIGNAL(PrepareForSleep(bool)), this, SLOT(onPrepareForSleep(bool))); inhibit(); } bool Interface::GetLockState() { return ((process.state() != QProcess::NotRunning) && lockState); } void Interface::SetLockState() { lockState = true; } void Interface::emitLockState(bool val) { QDBusMessage message; if(val){ message = QDBusMessage::createSignal(SS_DBUS_PATH, SS_DBUS_INTERFACE, "lock"); }else{ message = QDBusMessage::createSignal(SS_DBUS_PATH, SS_DBUS_INTERFACE, "unlock"); } QDBusConnection::sessionBus().send(message); } void Interface::UnLock() { if(process.state() != QProcess::NotRunning) process.kill(); } void Interface::Lock() { if(process.state() != QProcess::NotRunning) return ; qDebug() << "Lock requested"; lockState = false; QString cmd = QString("/usr/bin/ukui-screensaver-dialog --lock"); qDebug() << cmd; process.start(cmd); emitLockState(true); } void Interface::onSessionIdleReceived() { if(process.state() != QProcess::NotRunning) return ; qDebug() << "emit SessionIdle"; lockState = false; QString cmd = QString("/usr/bin/ukui-screensaver-dialog --session-idle"); qDebug() << cmd; process.start(cmd); emitLockState(true); } void Interface::onShowBlankScreensaver() { if(process.state() != QProcess::NotRunning) return ; qDebug() << "lock and show screensaver"; lockState = false; QString cmd = QString("/usr/bin/ukui-screensaver-dialog --blank"); qDebug() << cmd; process.start(cmd); emitLockState(true); } void Interface::onShowScreensaver() { if(process.state() != QProcess::NotRunning) return ; qDebug() << "lock and show screensaver"; lockState = false; QString cmd = QString("/usr/bin/ukui-screensaver-dialog --lock-screensaver"); qDebug() << cmd; process.start(cmd); emitLockState(true); } bool Interface::checkExistChild() { char cmd[128] = {0}; char str[4]; FILE *fp; int num; sprintf(cmd, "ps -aux | grep ukui-screensaver-dialog | grep %s | grep -v grep | wc -l", getenv("USER")); fp = popen(cmd, "r"); if(fgets(str, sizeof(str)-1, fp) == NULL) qDebug() << "fgets: " << strerror(errno); pclose(fp); num = atoi(str); qDebug() << (num > 0 ? "exist dialog running" : ""); return num > 0; } void Interface::onNameLost(const QString &serviceName) { if(serviceName == "cn.kylinos.ScreenSaver") exit(0); } void Interface::onPrepareForSleep(bool sleep) { if(!settings->get("sleep-activation-enabled").toBool()){ uninhibit(); return; } if(sleep) { if(GetLockState()){ uninhibit(); return; } this->onShowBlankScreensaver(); if(!m_timer){ m_timer = new QTimer(this); connect(m_timer, &QTimer::timeout, this, [&]{ m_timerCount+=1; if(GetLockState() || m_timerCount>20){ m_timer->stop(); m_timerCount = 0; uninhibit(); } }); } m_timer->start(200); } else { inhibit(); } } void Interface::ShowScreensaver() { if(process.state() != QProcess::NotRunning) return ; qDebug() << "lock and show screensaver"; lockState = false; QString cmd = QString("/usr/bin/ukui-screensaver-dialog --screensaver"); qDebug() << cmd; process.start(cmd); emitLockState(true); } void Interface::inhibit() { if (m_inhibitFileDescriptor.isValid()) { return; } QDBusMessage message = QDBusMessage::createMethodCall("org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", QStringLiteral("Inhibit")); message.setArguments(QVariantList({QStringLiteral("sleep"), "Screen Locker Backend", "Ensuring that the screen gets locked before going to sleep", QStringLiteral("delay")})); QDBusPendingReply reply = QDBusConnection::systemBus().call(message); if (!reply.isValid()) { return; } reply.value().swap(m_inhibitFileDescriptor); } void Interface::uninhibit() { if (!m_inhibitFileDescriptor.isValid()) { return; } m_inhibitFileDescriptor = QDBusUnixFileDescriptor(); } ukui-screensaver/src/CMakeLists.txt0000644000175000017500000001062714205075527016335 0ustar fengfengpkg_check_modules(X11 REQUIRED x11) pkg_check_modules(XTST REQUIRED xtst) pkg_check_modules(XCB REQUIRED xcb) pkg_check_modules(QGS REQUIRED gsettings-qt) pkg_check_modules(GLIB REQUIRED glib-2.0) pkg_check_modules(MMIX REQUIRED libmatemixer) find_library(PAM_LIBRARIES pam) include_directories(${PROJECT_BINARY_DIR}) include_directories(${PROJECT_SOURCE_DIR}/VirtualKeyboard/src) include_directories(${PROJECT_SOURCE_DIR}/BiometricAuth) include_directories(${PROJECT_SOURCE_DIR}/Common) include_directories(${PROJECT_SOURCE_DIR}/KylinNM) include_directories(${PROJECT_SOURCE_DIR}/KylinNM/src) include_directories(${PROJECT_SOURCE_DIR}/KylinNM/hot-spot) include_directories(${PROJECT_SOURCE_DIR}/KylinNM/wireless-security) include_directories( ${X11_INCLUDE_DIRS} ${XTST_INCLUDE_DIRS} ${XCB_INCLUDE_DIRS} ${QGS_INCLUDE_DIRS} ${GLIB_INCLUDE_DIRS} ${MMIX_INCLUDE_DIRS} ) set(EXTRA_LIBS ${EXTRA_LIBS} ${PAM_LIBRARIES} ${X11_LIBRARIES} ${XTST_LIBRARIES} ${XCB_LIBRARIES} ${QGS_LIBRARIES} ${GLIB_LIBRARIES} ${MMIX_LIBRARIES} -lrt ) qt5_wrap_ui(dialog_SRC lockwidget.ui ) qt5_add_resources(dialog_SRC assets.qrc ../KylinNM/nmqrc.qrc #暂时将麒麟网络的资源文件放到这里,否则显示不出来,暂时不知道原因 ) # 头文件中包含了Xlib.h,需要单独拿出来处理,不知道原因 qt5_wrap_cpp(dialog_SRC pam-tally.h fullbackgroundwidget.h lockwidget.h authdialog.h screensaverwidget.h auth.h auth-pam.h screensaver.h xeventmonitor.h monitorwatcher.h configuration.h users.h displaymanager.h iconedit.h powermanager.h logind.h weathermanager.h tabletlockwidget.h gestureauthdialog.h digitalauthdialog.h switchbuttongroup.h wechatauthdialog.h verificationwidget.h verticalVerificationwidget.h common.h eduplatforminterface.h accountsinterface.h networkwatcher.h digitalkeyboard.h PhysicalDeviceSet/brightnessdeviceset.h PhysicalDeviceSet/flightmodeset.h PhysicalDeviceSet/sounddeviceset.h PhysicalDeviceSet/touchscreenset.h ) set(dialog_SRC ${dialog_SRC} pam-tally.c ukui-screensaver-dialog.cpp fullbackgroundwidget.cpp lockwidget.cpp authdialog.cpp screensaverwidget.cpp auth-pam.cpp xeventmonitor.cpp monitorwatcher.cpp grab-x11.cpp configuration.cpp screensaver.cpp powermanager.cpp users.cpp displaymanager.cpp iconedit.cpp logind.cpp weathermanager.cpp tabletlockwidget.cpp gestureauthdialog.cpp digitalauthdialog.cpp switchbuttongroup.cpp wechatauthdialog.cpp verificationwidget.cpp verticalVerificationwidget.cpp eduplatforminterface.cpp accountsinterface.cpp networkwatcher.cpp digitalkeyboard.cpp PhysicalDeviceSet/brightnessdeviceset.cpp PhysicalDeviceSet/flightmodeset.cpp PhysicalDeviceSet/sounddeviceset.cpp PhysicalDeviceSet/touchscreenset.cpp ) add_executable(ukui-screensaver-dialog ${dialog_SRC}) target_link_libraries(ukui-screensaver-dialog Qt5::Core Qt5::Widgets Qt5::DBus Qt5::Svg Qt5::X11Extras Qt5::Network ${EXTRA_LIBS} BiometricAuth VirtualKeyboard Common Kylin-nm ) link_libraries(libmatemixer.so glib-2.0.so) qt5_add_dbus_adaptor(backend_SRC org.ukui.ScreenSaver.xml interface.h Interface ) qt5_wrap_cpp(backend_SRC interface.h sessionwatcher.h logind.h ) set(backend_SRC ${backend_SRC} ukui-screensaver-backend.cpp interface.cpp sessionwatcher.cpp logind.cpp ) add_executable(ukui-screensaver-backend ${backend_SRC}) target_link_libraries(ukui-screensaver-backend Qt5::Core Qt5::DBus ${QGS_LIBRARIES}) set(command_SRC ukui-screensaver-command.cpp ) add_executable(ukui-screensaver-command ${command_SRC}) target_link_libraries(ukui-screensaver-command Qt5::Core Qt5::DBus) set(checkpass_SRC ukui-screensaver-checkpass.cpp ) add_executable(ukui-screensaver-checkpass ${checkpass_SRC}) target_link_libraries(ukui-screensaver-checkpass ${PAM_LIBRARIES}) install(TARGETS ukui-screensaver-dialog ukui-screensaver-backend ukui-screensaver-command ukui-screensaver-checkpass DESTINATION bin) #set(test-act_SRC # users.cpp # test-accounts.cpp # ) #add_executable(test-accounts ${test-act_SRC}) #target_link_libraries(test-accounts Qt5::Core Qt5::DBus) ukui-screensaver/src/verificationwidget.h0000644000175000017500000001007614205074760017630 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef VERIFICATIONWIDGET_H #define VERIFICATIONWIDGET_H #include #include #include #include #include #include "wechatauthdialog.h" #include "common.h" #include "networkwatcher.h" class InputInfos; class PhoneAuthWidget; class MyLineEdit; class InputInfos : public QWidget { Q_OBJECT public: enum InputState{ InputWaiting , InputFinish }; InputInfos(QWidget *parent = nullptr); QString getPhoneNumer(); QString getVerificationCode(); void clearInfos(); Q_SIGNALS: void getVerCode(); void InputStateChanged(InputState input_state); void offlineState(); void notGlobal(); void online(); protected: void paintEvent(QPaintEvent *); private Q_SLOTS: void onPhoneTextChanged(const QString &text); void onVerCodeTextChanged(const QString &text); void onGetVerCode(); void onNextGetVerCodeTimer(); void onGetPhoneNum(int errorCode, const QString phoneNum); void onNetworkStateChanged(uint state); public Q_SLOTS: void onClearInfo(); private: void initUI(); void initConnect(); void setQSS(); private: QLabel *m_pPhoneIconLB; QLineEdit *m_pPhoneLE; QLabel *m_pVerCodeIconLB; MyLineEdit *m_pVerCodeLE; QPushButton *m_pGetVerCodeBT; QTimer *m_pNextGetVerCodeQTimer; int m_nextGetVerCodeTime; QString m_phoneNum = nullptr; InputState m_curInputState; NetWorkWatcher *m_networkWatcher; }; class VerificationWidget : public QWidget { Q_OBJECT public: explicit VerificationWidget(QWidget *parent = nullptr); ~VerificationWidget(); void reloadQR(); Q_SIGNALS: void pageMessage(SwitchPage id, QList argvs); private: QLabel *m_titleLB; QLabel *m_phonePromptMsgLB; WeChatAuthDialog *m_weChatWidget; //public: PhoneAuthWidget *m_phoneAuthWidget; protected: void paintEvent(QPaintEvent *); }; class PhoneAuthWidget : public QWidget { Q_OBJECT public: PhoneAuthWidget(QWidget* parent = nullptr); QSize sizeHint() const; private: void initUI(); void initConnect(); void setQSS(); void showPhoneErrorMsg(); void hidePhoneErrorMsg(); Q_SIGNALS: void pageMessage(SwitchPage id, QList argvs); void clearInfo(); private Q_SLOTS: void onInputStateChanged(InputInfos::InputState input_state); void onSubmitBTClick(); void onGetVerCode(); void onQRCodeStateChanged(QString username, QString password, int nState); void onOfflineState(); void onNotGlobal(); private: // 手机号验证 QLabel *m_pPhoTitleLB; QLabel *m_pPhoPromptMsgLB; QLabel *m_pPhoErrorMsgLB; QLabel *m_pPhoErrorMsgCloneLB; // 控制格式 QPushButton *m_pPhoSubmitBT; InputInfos *m_pPhoInputInfos; QTimer *m_hideTimer; }; class MyLineEdit : public QLineEdit { Q_OBJECT public: explicit MyLineEdit(QWidget *parent = nullptr); /*public Q_SLOTS: void onTextChanged(const QString &text);*/ protected: void focusInEvent(QFocusEvent *) override; void focusOutEvent(QFocusEvent *) override; }; class GetPhoneNumThread : public QThread { Q_OBJECT public: GetPhoneNumThread(QObject *parent); protected: void run() override; Q_SIGNALS: void resultReady(int errorCode, const QString phoneNum); }; #endif // VERIFICATIONWIDGET_H ukui-screensaver/src/xeventmonitor.cpp0000644000175000017500000001345014205074704017213 0ustar fengfeng/* -*- Mode: C++; indent-tabs-mode: nil; tab-width: 4 -*- * -*- coding: utf-8 -*- * * Copyright (C) 2011 ~ 2017 Deepin, Inc. * 2011 ~ 2017 Wang Yong * Copyright (C) 2018 Tianjin KYLIN Information Technology Co., Ltd. * * Author: Wang Yong * Maintainer: Wang Yong * * 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 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include "xeventmonitor.h" #include #include #include #include #include // Virtual button codes that are not defined by X11. #define Button1 1 #define Button2 2 #define Button3 3 #define WheelUp 4 #define WheelDown 5 #define WheelLeft 6 #define WheelRight 7 #define XButton1 8 #define XButton2 9 class XEventMonitorPrivate { public: XEventMonitorPrivate(XEventMonitor *parent); virtual ~XEventMonitorPrivate(); void run(); protected: XEventMonitor *q_ptr; bool filterWheelEvent(int detail); static void callback(XPointer trash, XRecordInterceptData* data); void handleRecordEvent(XRecordInterceptData *); void emitButtonSignal(const char *member, xEvent *event); void emitKeySignal(const char *member, xEvent *event); private: Q_DECLARE_PUBLIC(XEventMonitor) }; XEventMonitorPrivate::XEventMonitorPrivate(XEventMonitor *parent) : q_ptr(parent) { } XEventMonitorPrivate::~XEventMonitorPrivate() { } void XEventMonitorPrivate::emitButtonSignal(const char *member, xEvent *event) { int x = event->u.keyButtonPointer.rootX; int y = event->u.keyButtonPointer.rootY; QMetaObject::invokeMethod(q_ptr, member, Qt::DirectConnection, Q_ARG(int, x), Q_ARG(int, y)); } void XEventMonitorPrivate::emitKeySignal(const char *member, xEvent *event) { if(QX11Info::display()){ int keyCode = event->u.u.detail; KeySym keySym = XkbKeycodeToKeysym(QX11Info::display(), event->u.u.detail, 0, 0); char *keyStr = XKeysymToString(keySym); QMetaObject::invokeMethod(q_ptr, member, Qt::AutoConnection, Q_ARG(int, keyCode)); QMetaObject::invokeMethod(q_ptr, member, Qt::AutoConnection, Q_ARG(QString, keyStr)); } } void XEventMonitorPrivate::run() { Display* display = XOpenDisplay(0); if (display == 0) { fprintf(stderr, "unable to open display\n"); return; } // Receive from ALL clients, including future clients. XRecordClientSpec clients = XRecordAllClients; XRecordRange* range = XRecordAllocRange(); if (range == 0) { fprintf(stderr, "unable to allocate XRecordRange\n"); return; } // Receive KeyPress, KeyRelease, ButtonPress, ButtonRelease and MotionNotify events. memset(range, 0, sizeof(XRecordRange)); range->device_events.first = KeyPress; range->device_events.last = MotionNotify; // And create the XRECORD context. XRecordContext context = XRecordCreateContext(display, 0, &clients, 1, &range, 1); if (context == 0) { fprintf(stderr, "XRecordCreateContext failed\n"); return; } XFree(range); XSync(display, True); Display* display_datalink = XOpenDisplay(0); if (display_datalink == 0) { fprintf(stderr, "unable to open second display\n"); return; } if (!XRecordEnableContext(display_datalink, context, callback, (XPointer) this)) { fprintf(stderr, "XRecordEnableContext() failed\n"); return; } } void XEventMonitorPrivate::callback(XPointer ptr, XRecordInterceptData* data) { ((XEventMonitorPrivate *) ptr)->handleRecordEvent(data); } void XEventMonitorPrivate::handleRecordEvent(XRecordInterceptData* data) { if (data->category == XRecordFromServer) { xEvent * event = (xEvent *)data->data; switch (event->u.u.type) { case ButtonPress: if (filterWheelEvent(event->u.u.detail)) { emitButtonSignal("buttonPress", event); } break; case MotionNotify: emitButtonSignal("buttonDrag", event); break; case ButtonRelease: if (filterWheelEvent(event->u.u.detail)) { emitButtonSignal("buttonRelease", event); } break; case KeyPress: emitKeySignal("keyPress", event); break; case KeyRelease: emitKeySignal("keyRelease", event); break; default: break; } } fflush(stdout); XRecordFreeData(data); } bool XEventMonitorPrivate::filterWheelEvent(int detail) { return detail != WheelUp && detail != WheelDown && detail != WheelLeft && detail != WheelRight; } XEventMonitor::XEventMonitor(QObject *parent) : QThread(parent), d_ptr(new XEventMonitorPrivate(this)) { Q_D(XEventMonitor); } XEventMonitor::~XEventMonitor() { requestInterruption(); quit(); wait(); } void XEventMonitor::run() { if(!isInterruptionRequested()) { d_ptr->run(); } } ukui-screensaver/src/tabletlockwidget.cpp0000644000175000017500000005466414205074704017636 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * Authors: ZHAI Kang-ning **/ #include #include #include #include //#include //#include //#include #include #include #include #include #include #include #include #include #include #include "tabletlockwidget.h" #include "authdialog.h" #include "virtualkeyboard.h" #include "users.h" #include "displaymanager.h" #include "weathermanager.h" #include "powermanager.h" #include "digitalauthdialog.h" #include "switchbuttongroup.h" #include "wechatauthdialog.h" #include "verificationwidget.h" #include "verticalVerificationwidget.h" #include "common.h" #include "eduplatforminterface.h" #include "accountsinterface.h" #include "kylinnm.h" #include float tablescale; TabletLockWidget::TabletLockWidget(QWidget *parent) : QWidget(parent), displayManager(new DisplayManager(this)), m_switchButtonGroup(new SwitchButtonGroup(this)), m_digitalAuthDialog(new DigitalAuthDialog(this)), m_weChatAuthDialog(new WeChatAuthDialog(this)), m_pb_powerManager(new QPushButton(this)), m_pb_networkManager(new QPushButton(this)), m_vKeyboardPB(new QPushButton(this)), m_vKeyboard(new VirtualKeyboard(this)), m_cancelOrBack(new QPushButton(this)), m_pb_skip(new QPushButton(this)), m_verificationWidget(new VerificationWidget(this)), m_verticalVerificationWidget(new VerticalVerificationWidget(this)), m_authType(0), m_eduPlatformInterface(nullptr), m_kylinNM(new KylinNM(this)) { tablescale = 1.0; m_kylinNM->installEventFilter(this); m_digitalAuthDialog->installEventFilter(this); m_switchButtonGroup->installEventFilter(this); m_vKeyboard->installEventFilter(this); this->installEventFilter(this); powermanager = new PowerManager(this); powermanager->hide(); initUI(); initConnect(); onSwitchPage(); } TabletLockWidget::~TabletLockWidget() { } void TabletLockWidget::closeEvent(QCloseEvent *event) { qDebug() << "TabletLockWidget::closeEvent"; m_digitalAuthDialog->close(); m_weChatAuthDialog->close(); m_switchButtonGroup->close(); m_verificationWidget->close(); m_verticalVerificationWidget->close(); m_kylinNM->close(); return QWidget::closeEvent(event); } bool TabletLockWidget::eventFilter(QObject *obj, QEvent *event) { if (obj == m_vKeyboard || obj == m_kylinNM) return true; if (event->type() == QEvent::MouseButtonPress && m_kylinNM->isVisible()) { m_kylinNM->hide(); if(powermanager->isHidden()) //非电源会话界面则刷新,否则只网络弹窗 onSwitchPage(); } return QWidget::eventFilter(obj, event); } void TabletLockWidget::startAuth() { m_digitalAuthDialog->startAuth(); } void TabletLockWidget::stopAuth() { } void TabletLockWidget::initUI() { //电源管理 m_pb_powerManager->setIcon(QIcon(":/image/assets/intel/powerManager.png")); m_pb_powerManager->setFixedSize(48,48); m_pb_powerManager->setIconSize(QSize(24,24)); m_pb_powerManager->setFocusPolicy(Qt::NoFocus); m_pb_powerManager->setStyleSheet("QPushButton:Hover{border-radius:24px;background-color:rgba(255, 255, 255, 0.15);}" "QPushButton:Pressed{border-radius:24px;background-color:rgba(255, 255, 255, 0.05);}"); m_pb_powerManager->installEventFilter(this); connect(m_pb_powerManager,&QPushButton::clicked ,this,&TabletLockWidget::showPowerManager); //网络设置 updateNetIcon(m_kylinNM->getConnectStatus()); m_pb_networkManager->setFixedSize(48,48); m_pb_networkManager->setIconSize(QSize(24,24)); m_pb_networkManager->setFocusPolicy(Qt::NoFocus); m_pb_networkManager->setStyleSheet("QPushButton:Hover{border-radius:24px;background-color:rgba(255, 255, 255, 0.15);}" "QPushButton:Pressed{border-radius:24px;background-color:rgba(255, 255, 255, 0.05);}"); m_pb_networkManager->installEventFilter(this); connect(m_pb_networkManager,&QPushButton::clicked ,this,&TabletLockWidget::showNetManager); //虚拟键盘 m_vKeyboard->hide(); connect(m_vKeyboard, &VirtualKeyboard::aboutToClose, m_vKeyboard, &VirtualKeyboard::hide); m_vKeyboardPB->setIcon(QIcon(":/image/assets/intel/keyboard.png")); m_vKeyboardPB->setFixedSize(48,48); m_vKeyboardPB->setIconSize(QSize(24,24)); m_vKeyboardPB->setFocusPolicy(Qt::NoFocus); m_vKeyboardPB->installEventFilter(this); m_vKeyboardPB->setStyleSheet("QPushButton:Hover{border-radius:24px;background-color:rgba(255, 255, 255, 0.15);}" "QPushButton:Pressed{border-radius:24px;background-color:rgba(255, 255, 255, 0.05);}"); connect(m_vKeyboardPB,&QPushButton::clicked ,this,&TabletLockWidget::showVirtualKeyboard); //取消或返回 m_cancelOrBack->resize(88, 48); m_cancelOrBack->setIcon(QIcon(":/image/assets/intel/cancel.png")); m_cancelOrBack->setStyleSheet("QPushButton{font-size:16px;color:#ffffff;}" "QPushButton:Hover{border-radius:24px;background-color:rgba(255, 255, 255, 0.15);}" "QPushButton:Pressed{border-radius:24px;background-color:rgba(255, 255, 255, 0.05);}"); m_cancelOrBack->setText(tr("Cancel")); m_cancelOrBack->setIconSize(QSize(24,24)); m_cancelOrBack->setFocusPolicy(Qt::NoFocus); m_cancelOrBack->installEventFilter(this); connect(m_digitalAuthDialog, &DigitalAuthDialog::requestPasswordReset, this, [=]{ m_cancelOrBack->setIcon(QIcon(":/image/assets/intel/back.png")); m_cancelOrBack->setText(tr("Back")); m_pageType = pageType::check; m_pb_skip->hide(); onSwitchPage(); }); connect(m_cancelOrBack, &QPushButton::clicked, this, [=]{ if(powermanager->isVisible()) { powermanager->hide(); onSwitchPage(); // m_digitalAuthDialog->reset(); if(m_pageType != pageType::check) { m_cancelOrBack->setIcon(QIcon(":/image/assets/intel/cancel.png")); m_cancelOrBack->setText(tr("Cancel")); } return; } if(m_pageType == pageType::pinLogin && m_digitalAuthDialog->getStatus() == DigitalAuthDialog::LoginType::SECONDCONFIRMATION) { // 二次确认页返回,则显示重置密码页 m_digitalAuthDialog->showResetPasswordPage(); return; } if(m_pageType == pageType::check) { m_pageType = pageType::pinLogin; m_digitalAuthDialog->reset(); onSwitchPage(); m_cancelOrBack->setIcon(QIcon(":/image/assets/intel/cancel.png")); m_cancelOrBack->setText(tr("Cancel")); return; } if(m_digitalAuthDialog->getStatus() == 0) { //Todo 1、锁屏 -》息屏 m_digitalAuthDialog->reset(); Q_EMIT blackSaver(); #ifdef USE_INTEL powermanager->hibernate(); #endif } else { m_digitalAuthDialog->reset(); m_cancelOrBack->setIcon(QIcon(":/image/assets/intel/cancel.png")); m_cancelOrBack->setText(tr("Cancel")); } }); // 重置密码时跳过按钮 m_pb_skip->setText(tr("Skip")); m_pb_skip->resize(88, 48); m_pb_skip->setStyleSheet("QPushButton{font-size:16px;color:#ffffff;}" "QPushButton:Hover{border-radius:24px;background-color:rgba(255, 255, 255, 0.15);}" "QPushButton:Pressed{border-radius:24px;background-color:rgba(255, 255, 255, 0.05);}"); m_pb_skip->hide(); //网络模块 m_kylinNM->hide(); } /** * @brief TabletLockWidget::initConnect * 建立信号与槽的绑定 */ void TabletLockWidget::initConnect() { connect(m_digitalAuthDialog, &DigitalAuthDialog::authenticateCompete, this, &TabletLockWidget::closed); connect(m_digitalAuthDialog, &DigitalAuthDialog::setPinCode, this, [=](QString pinCode){ //Todo QString currentPinCode; AccountsInterface::getInstance()->GetAccountPincode(getenv("USER"), currentPinCode); qDebug() << "currentPinCode:" << currentPinCode << "--old pinCode:" << pinCode; if(!currentPinCode.isEmpty() && currentPinCode == pinCode) { //与原密码相同 m_digitalAuthDialog->showErrorMessage(tr("New password is the same as old")); m_digitalAuthDialog->showResetPasswordPage(); return; } DBusMsgCode code = AccountsInterface::getInstance()->SetAccountPincode(getenv("USER"), pinCode); if (code == DBusMsgCode::No_Error) { qDebug() << "set pincode success"; Q_EMIT closed(); } else { qWarning() << "设置失败" << code; m_digitalAuthDialog->showErrorMessage(tr("Reset password error:%1").arg(code)); } }); connect(m_weChatAuthDialog, &WeChatAuthDialog::authenticateCompete, this, &TabletLockWidget::closed); connect(m_weChatAuthDialog, &WeChatAuthDialog::qRStatusChange, this, [=] (QString loginname, QString loginpwd, int curstatus){ //QString loginname, QString loginpwd, int curstatus if(getenv("USER") == loginname && m_pageType == pageType::wecharLogin) { Q_EMIT closed(); } else { qWarning() << "[error] Username does not match wechat<" << loginname << ">" << " local<" << getenv("USER")<<">"; if (!loginname.isEmpty()){ m_weChatAuthDialog->showErrorMessage(tr("Please scan by correct WeChat")); m_weChatAuthDialog->onReset(); } } }); connect(m_switchButtonGroup, &SwitchButtonGroup::onSwitch, this, &TabletLockWidget::switchLoginType); connect(m_verificationWidget, &VerificationWidget::pageMessage, this, [=](SwitchPage type, QList args) { m_pageType = pageType::pinLogin; onSwitchPage(); m_pb_skip->show(); }); connect(m_verticalVerificationWidget, &VerticalVerificationWidget::pageMessage, this, [=](SwitchPage type, QList args) { m_pageType = pageType::pinLogin; onSwitchPage(); m_pb_skip->show(); }); connect(powermanager,SIGNAL(lock()) ,this,SLOT(showPowerManager())); if(QGSettings::isSchemaInstalled("org.ukui.SettingsDaemon.plugins.tablet-mode")) { QGSettings *tm = new QGSettings("org.ukui.SettingsDaemon.plugins.tablet-mode", "", this); //判断是否是平板模式 if(tm->get("tablet-mode").toBool()){ connect(m_kylinNM, &KylinNM::onLineEditClicked, this, [=](){ //点击了输入密码的框框,需要弹出软键盘 showVirtualKeyboard(true); m_kylinNM->move(m_kylinNM->x(), height() - m_vKeyboard->height() - m_kylinNM->height() - 20); }); } //监听平板模式变化 connect(tm, &QGSettings::changed, this, [=](QString key){ if(key == "tablet-mode" || key == "tabletMode") { disconnect(m_kylinNM, &KylinNM::onLineEditClicked, this, nullptr); if(tm->get("tablet-mode").toBool()){ connect(m_kylinNM, &KylinNM::onLineEditClicked, this, [=](){ //点击了输入密码的框框,需要弹出软键盘 showVirtualKeyboard(true); m_kylinNM->move(m_kylinNM->x(), height() - m_vKeyboard->height() - m_kylinNM->height()); }); } } }); } connect(m_kylinNM, &KylinNM::onConnectChanged, this,[=](){ updateNetIcon(m_kylinNM->getConnectStatus()); }); connect(m_vKeyboard, &VirtualKeyboard::aboutToClose, m_vKeyboard, [=](){ if(m_vKeyboard->isHidden() && m_kylinNM->isVisible()) { m_kylinNM->setGeometry(this->width() - m_kylinNM->width() - 20, this->height() - m_kylinNM->height() - 100, m_kylinNM->width(), m_kylinNM->height()); } }); connect(m_pb_skip, &QPushButton::clicked, this, &TabletLockWidget::closed); connect(m_digitalAuthDialog, &DigitalAuthDialog::switchToReset, this, [=](bool isReset){ if(isReset){ m_pb_skip->show(); } else { m_pb_skip->hide(); } }); } void TabletLockWidget::switchLoginType(int position) { if(position == 0) { //锁屏密码登录 m_pageType = pageType::pinLogin; } else if (position == 1) { m_pageType = pageType::wecharLogin; //微信登录 m_digitalAuthDialog->reset(); m_cancelOrBack->setIcon(QIcon(":/image/assets/intel/cancel.png")); m_cancelOrBack->setText(tr("Cancel")); } onSwitchPage(); } void TabletLockWidget::showPowerManager() { if (powermanager->isVisible()) { powermanager->hide(); onSwitchPage(); if(m_pageType != pageType::check) { m_cancelOrBack->setIcon(QIcon(":/image/assets/intel/cancel.png")); m_cancelOrBack->setText(tr("Cancel")); } Q_EMIT screenSaver(); } else { m_digitalAuthDialog->hide(); m_weChatAuthDialog->hide(); m_switchButtonGroup->hide(); m_verificationWidget->hide(); m_verticalVerificationWidget->hide(); m_cancelOrBack->setIcon(QIcon(":/image/assets/intel/back.png")); m_cancelOrBack->setText(tr("Back")); m_pb_networkManager->hide(); m_pb_powerManager->hide(); m_vKeyboardPB->hide(); m_vKeyboard->hide(); powermanager->show(); powermanager->setGeometry((width()-ITEM_WIDTH*4 - ITEM_SPACING*3)/2, (height()-ITEM_HEIGHT)/2, (ITEM_WIDTH*4 + ITEM_SPACING*3),ITEM_HEIGHT); } } void TabletLockWidget::showNetManager() { if(m_kylinNM->isVisible()) { m_kylinNM->hide(); } else { m_digitalAuthDialog->releaseKeyboard(); m_kylinNM->show(); m_kylinNM->setGeometry(this->width() - m_kylinNM->width() - 20, this->height() - m_kylinNM->height() - 100, m_kylinNM->width(), m_kylinNM->height()); m_kylinNM->updateWifiList(); } } /* lockscreen follows cursor */ void TabletLockWidget::resizeEvent(QResizeEvent *event) { QSize size = event->size(); //重新计算缩放比例 tablescale = QString::number(size.width() / 1920.0, 'f', 1).toFloat(); if(tablescale > 1) tablescale = 1; m_cancelOrBack->setGeometry(32, 40, m_cancelOrBack->width(), m_cancelOrBack->height()); m_pb_skip->setGeometry(this->width() - m_pb_skip->width() - 32, 40, m_pb_skip->width(), m_pb_skip->height()); m_digitalAuthDialog->setGeometry((this->width()-m_digitalAuthDialog->width())/2, (this->height()-m_digitalAuthDialog->height())/2 + 40, m_digitalAuthDialog->width(), m_digitalAuthDialog->height()); m_weChatAuthDialog->setGeometry((this->width()-m_weChatAuthDialog->width())/2, (this->height()-m_digitalAuthDialog->height())/2 + 40, m_weChatAuthDialog->width(), m_weChatAuthDialog->height()); m_switchButtonGroup->setGeometry((this->width()-m_switchButtonGroup->width())/2, this->height()-80, m_switchButtonGroup->width(), m_switchButtonGroup->height()); if(isOrientation()) m_verticalVerificationWidget->setGeometry((this->width()-m_verticalVerificationWidget->width())/2, (this->height()-m_verticalVerificationWidget->height())/2, m_verticalVerificationWidget->width(), m_verticalVerificationWidget->height()); else m_verificationWidget->setGeometry((this->width()-m_verificationWidget->width())/2, (this->height()-m_verificationWidget->height())/2 - 65, m_verificationWidget->width(), m_verificationWidget->height()); if(m_verificationWidget->isVisible() || m_verticalVerificationWidget->isVisible()) showVerificationPage(); // XSetInputFocus(QX11Info::display(),this->winId(),RevertToParent,CurrentTime); //右下角按钮,x,y的初始值代表距离右下角的距离。 int x=19,y=76; x = x + m_pb_powerManager->width(); m_pb_powerManager->setGeometry(this->width() - x,this->height() - y, m_pb_powerManager->width(), m_pb_powerManager->height()); m_pb_networkManager->setGeometry(this->width() - x - 64 * tablescale, this->height() - y, m_pb_networkManager->width(),m_pb_networkManager->height()); m_vKeyboardPB->setGeometry(this->width() - x - 128 * tablescale, this->height() - y, m_vKeyboardPB->width(), m_vKeyboardPB->height()); m_kylinNM->setGeometry(this->width() - m_kylinNM->width() - 20, this->height() - m_kylinNM->height() - 100, m_kylinNM->width(), m_kylinNM->height()); //更新软键盘位置 setVirkeyboardPos(); if(powermanager && powermanager->isVisible()) { powermanager->setGeometry((width()-ITEM_WIDTH*4 - ITEM_SPACING*3)/2, (height()-ITEM_HEIGHT)/2, (ITEM_WIDTH*4 + ITEM_SPACING*3),ITEM_HEIGHT); } } //重写重绘事件,比如动态更新文本位置等 void TabletLockWidget::paintEvent(QPaintEvent *event) { } void TabletLockWidget::onSwitchPage() { bool isOnlyWeChatLogin = false; EduPlatformInterface::getInstance()->CheckPincodeSet(getenv("USER"), isOnlyWeChatLogin); if(isOnlyWeChatLogin && m_pageType == pageType::pinLogin) { m_pageType = pageType::wecharLogin; } if(!m_pb_networkManager->isVisible()) m_pb_networkManager->show(); if(!m_pb_powerManager->isVisible()) m_pb_powerManager->show(); switch (m_pageType) { case pageType::pinLogin: m_digitalAuthDialog->show(); m_digitalAuthDialog->grabKeyboard(); m_switchButtonGroup->show(); m_weChatAuthDialog->hide(); m_verificationWidget->hide(); m_verticalVerificationWidget->hide(); m_vKeyboardPB->hide(); m_vKeyboard->hide(); break; case pageType::wecharLogin: m_digitalAuthDialog->hide(); m_digitalAuthDialog->releaseKeyboard(); m_weChatAuthDialog->show(); if(isOnlyWeChatLogin) { m_switchButtonGroup->hide(); } else { m_switchButtonGroup->show(); } m_verificationWidget->hide(); m_verticalVerificationWidget->hide(); m_vKeyboardPB->hide(); m_vKeyboard->hide(); break; case pageType::check: m_digitalAuthDialog->hide(); m_digitalAuthDialog->releaseKeyboard(); m_weChatAuthDialog->hide(); m_switchButtonGroup->hide(); showVerificationPage(); m_vKeyboardPB->show(); break; default: break; } } QWidget* TabletLockWidget::getCurrentWidget() { switch (m_pageType) { case pageType::pinLogin: return m_digitalAuthDialog; case pageType::wecharLogin: return m_weChatAuthDialog; case pageType::check: return m_verificationWidget; default: return m_digitalAuthDialog; } } void TabletLockWidget::showVirtualKeyboard(bool isShow) { m_vKeyboard->setVisible(isShow || m_vKeyboard->isHidden()); setVirkeyboardPos(); } void TabletLockWidget::setVirkeyboardPos() { if(m_vKeyboard) { m_vKeyboard->setGeometry(0 + 20, height() - height()/3 + 10, width() - 40 , height()/3 - 20); m_vKeyboard->raise(); m_vKeyboard->repaint(); } } bool TabletLockWidget::isOrientation() { QRect wRect = QApplication::primaryScreen()->geometry(); if(wRect.height() > wRect.width()) return true; return false; } void TabletLockWidget::showVerificationPage() { if(isOrientation()) { m_verificationWidget->hide(); m_verticalVerificationWidget->show(); } else { m_verificationWidget->show(); m_verticalVerificationWidget->hide(); } } //void TabletLockWidget::RecieveKey(int key) //{ // if(m_pageType == pageType::pinLogin ||m_pageType == pageType::check) // m_digitalAuthDialog->RecieveKey(key); //} void TabletLockWidget::updateNetIcon(int status) { switch(status) { case 0: //有线 m_pb_networkManager->setIcon(QIcon(":/image/assets/intel/icon-wired.png")); break; case 1: //无线 m_pb_networkManager->setIcon(QIcon(":/image/assets/intel/icon-wifi.png")); break; case 2: //有线+无线 m_pb_networkManager->setIcon(QIcon(":/image/assets/intel/icon-wired.png")); break; default: //无连接 m_pb_networkManager->setIcon(QIcon(":/image/assets/intel/icon-no-signal.png")); } } /** * @Destoryed * @brief TabletLockWidget::getEduPlatformInterface * @return */ EduPlatformInterface* TabletLockWidget::getEduPlatformInterface() { if(m_eduPlatformInterface == nullptr) { m_eduPlatformInterface = new EduPlatformInterface("cn.kylinos.SSOBackend", "/cn/kylinos/SSOBackend", QDBusConnection::systemBus(), this); } return m_eduPlatformInterface; } ukui-screensaver/src/ukui-screensaver.pro0000644000175000017500000000377314205074704017612 0ustar fengfeng#------------------------------------------------- # # Project created by QtCreator 2018-04-09T11:40:40 # #------------------------------------------------- QT += core gui dbus x11extras greaterThan(QT_MAJOR_VERSION, 4): QT += widgets include(BioAuth/bioauth.pri) include(VirtualKeyboard/VirtualKeyboard.pri) TARGET = ukui-screensaver-dialog TEMPLATE = app # The following define makes your compiler emit warnings if you use # any feature of Qt which has been marked as deprecated (the exact warnings # depend on your compiler). Please consult the documentation of the # deprecated API in order to know how to port your code away from it. DEFINES += QT_DEPRECATED_WARNINGS \ QT_MESSAGELOGCONTEXT LIBS += -lpam -lpam_misc -lX11 -lXext -lXtst CONFIG += link_pkgconfig PKGCONFIG += gio-2.0 x11 xcb xtst # You can also make your code fail to compile if you use deprecated APIs. # In order to do so, uncomment the following line. # You can also select to disable deprecated APIs only up to a certain version of Qt. #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 INCLUDEPATH += \ VirtualKeyboard/src/ BioAuth/include/ SOURCES += \ ukui-screensaver-dialog.cpp \ mainwindow.cpp \ unixsignallistener.cpp \ auth-pam.cpp \ authdialog.cpp \ gsettings.cpp \ auxiliary.cpp \ configuration.cpp \ screensaverwidget.cpp \ screensaver.cpp \ event_monitor.cpp \ monitorwatcher.cpp HEADERS += \ mainwindow.h \ unixsignallistener.h \ auth-pam.h \ auth.h \ authdialog.h \ gsettings.h \ auxiliary.h \ configuration.h \ screensaverwidget.h \ screensaver.h \ event_monitor.h \ monitorwatcher.h FORMS += \ mainwindow.ui \ authdialog.ui RESOURCES += \ assets.qrc TRANSLATIONS = ../i18n_ts/zh_CN.ts \ ../i18n_ts/ru.ts \ ../i18n_ts/fr.ts \ ../i18n_ts/pt.ts \ ../i18n_ts/es.ts target.path = /usr/bin/ INSTALLS += target ukui-screensaver/src/screensaverwidget.h0000644000175000017500000000271314205074704017463 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef SCREENSAVERWIDGET_H #define SCREENSAVERWIDGET_H #include #include #include "screensaver.h" class ScreenSaverWidget : public QWidget { Q_OBJECT public: ScreenSaverWidget(ScreenSaver *screensaver, QWidget *parent = nullptr); ~ScreenSaverWidget() ; protected: void closeEvent(QCloseEvent *); void paintEvent(QPaintEvent *event); bool eventFilter(QObject *obj, QEvent *event); private: void embedXScreensaver(const QString &path); private Q_SLOTS: void onBackgroundChanged(const QString &path); private: QTimer *timer; ScreenSaver *screensaver; bool closing; float opacity; QProcess process; }; #endif // SCREENSAVERWIDGET_H ukui-screensaver/src/configuration.cpp0000644000175000017500000001576514205074704017154 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "configuration.h" #include #include #include #include #include #include #include #include #include #include "commonfunc.h" #define GSETTINGS_SCHEMA_SCREENSAVER "org.ukui.screensaver" #define KEY_MODE "mode" #define KEY_THEMES "themes" #define KEY_IDLE_ACTIVATION_ENABLED "idle-activation-enabled" #define KEY_LOCK_ENABLED "lock-enabled" #define KEY_IMAGE_TRANSITION_EFFECT "image-transition-effect" #define KEY_IMAGE_SWITCH_INTERVAL "image-switch-interval" #define KEY_BACKGROUND "background" #define XSCREENSAVER_DIRNAME "/usr/lib/xscreensaver" Configuration* Configuration::instance_ = nullptr; Configuration::Configuration(QObject *parent) : QObject(parent) { /* QGSettings for screensaver */ gsettings = new QGSettings(GSETTINGS_SCHEMA_SCREENSAVER, "", this); connect(gsettings, &QGSettings::changed, this, &Configuration::onConfigurationChanged); /* Initiailization */ mode = gsettings->get(KEY_MODE).toString(); themes = gsettings->get(KEY_THEMES).toStringList(); idleActivationEnabled = gsettings->get( KEY_IDLE_ACTIVATION_ENABLED).toBool(); lockEnabled = gsettings->get(KEY_LOCK_ENABLED).toBool(); imageSwitchInterval = gsettings->get(KEY_IMAGE_SWITCH_INTERVAL).toInt(); imageTSEffect = gsettings->get(KEY_IMAGE_TRANSITION_EFFECT).toInt(); background = gsettings->get(KEY_BACKGROUND).toString(); qDebug() << mode << themes; qDebug() << imageSwitchInterval << imageTSEffect; int FileisExist = 0; if(!background.isEmpty()) { QFileInfo file(background); if(file.exists()==false) FileisExist = 0; else FileisExist = 1; } //如果org.ukui.screensaver background中的背景图片为空,则设为桌面背景 if(background.isEmpty()||0==FileisExist) { QString currentDesktop = qgetenv("XDG_CURRENT_DESKTOP"); if(currentDesktop == "UKUI" || currentDesktop == "MATE") { bgGsettings = new QGSettings("org.mate.background"); background = bgGsettings->get("picture-filename").toString(); } else if(currentDesktop == "ubuntu:GNOME") { bgGsettings = new QGSettings("org.gnome.desktop.background"); background = bgGsettings->get("picture-uri").toString(); //去除前缀:file:///usr/share/background/xxx.png background.remove(0, 7); } } qDebug() << "background: " << background; if(themes.count() == 1 && themes[0] == "kyccss-personal-slideshow") mode ="image"; } Configuration* Configuration::instance(QObject *parent) { if(instance_ == nullptr) instance_ = new Configuration(parent); return instance_; } /* Update member value when GSettings changed */ void Configuration::onConfigurationChanged(QString key) { qDebug() << "GSettings value changed, key = " << key; if (key == KEY_MODE) mode = gsettings->get(KEY_MODE).toString(); else if (key == KEY_THEMES) themes = gsettings->get(KEY_THEMES).toStringList(); else if (key == KEY_IDLE_ACTIVATION_ENABLED) idleActivationEnabled = gsettings->get(KEY_IDLE_ACTIVATION_ENABLED).toBool(); else if (key == KEY_LOCK_ENABLED) lockEnabled = gsettings->get(KEY_LOCK_ENABLED).toBool(); else if(key == KEY_IMAGE_TRANSITION_EFFECT) imageTSEffect = gsettings->get(KEY_IMAGE_TRANSITION_EFFECT).toInt(); else if(key == KEY_IMAGE_SWITCH_INTERVAL) imageSwitchInterval = gsettings->get(KEY_IMAGE_SWITCH_INTERVAL).toInt(); } /* * Getter */ /* Get the executable path of xscreensaver */ ScreenSaver *Configuration::getScreensaver() { QStringList modeStr{"blank-only", "random", "single", "image","default-ukui","default-ukui-custom"}; ScreenSaver *saver = new ScreenSaver; int index = modeStr.indexOf(mode); saver->mode = SaverMode(index); saver->interval = imageSwitchInterval; saver->effect = TransitionEffect(imageTSEffect); switch(index){ case SAVER_BLANK_ONLY: break; case SAVER_RANDOM: { if(themes.count()==0){ saver->path = "/usr/lib/ukui-screensaver/ukui-screensaver-default"; break; } qsrand((unsigned)time(0)); int index = qrand() % themes.count(); while(QString::compare(themes[index], "kyccss-personal-slideshow")==0) { index = qrand() % themes.count(); } saver->path = getXScreensaverPath(themes[index]); break; } case SAVER_SINGLE: if(themes.count()==0){ saver->path = "/usr/lib/ukui-screensaver/ukui-screensaver-default"; break; } saver->path = getXScreensaverPath(themes[0]); break; case SAVER_IMAGE: { QString lang = qgetenv("LANG"); if (!lang.isEmpty()){ qDebug()<<"lang = "<path = QDir::homePath() + "/图片"; break; } } saver->path = QDir::homePath() + "/" + QStandardPaths::displayName(QStandardPaths::PicturesLocation); break; } case SAVER_DEFAULT: saver->path = "/usr/lib/ukui-screensaver/ukui-screensaver-default"; break; case SAVER_DEFAULT_CUSTOM: saver->path = "/usr/lib/ukui-screensaver/ukui-screensaver-default"; break; default: break; } return saver; } QString Configuration::getXScreensaverPath(const QString &theme) { /* screensavers-ukui-binaryring => binaryring */ QStringList strs = theme.split("-"); QString str = strs.at(strs.size() - 1); QString filePath = QString("%1/%2").arg(XSCREENSAVER_DIRNAME, str); //除了判断gsetting值是否为空,还需要判断屏保文件是否存在,不存在就使用默认屏保。 if(QFile(filePath).exists()) return filePath; else return "/usr/lib/ukui-screensaver/ukui-screensaver-default"; } QString Configuration::getBackground() { if(ispicture(background)) return background; return "/usr/share/backgrounds/warty-final-ubuntukylin.jpg"; } bool Configuration::xscreensaverActivatedWhenIdle() { return idleActivationEnabled; } bool Configuration::lockWhenXScreensaverActivated() { return lockEnabled; } ukui-screensaver/src/networkwatcher.cpp0000644000175000017500000000676214205074760017353 0ustar fengfeng/** * Copyright (C) 2018 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, 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 #include #include #include #include "networkwatcher.h" const int port = 80; NetWorkWatcher::NetWorkWatcher(QObject *parent) { QDBusConnection::systemBus().connect(QString("org.freedesktop.NetworkManager"), QString("/org/freedesktop/NetworkManager"), QString("org.freedesktop.NetworkManager"), QString("StateChanged"), this, SLOT(onNetworkStateChanged(uint))); network = new QDBusInterface("org.freedesktop.NetworkManager", "/org/freedesktop/NetworkManager", "org.freedesktop.NetworkManager", QDBusConnection::systemBus()); } void NetWorkWatcher::onNetworkStateChanged(uint state) { qDebug() << "NetWork state already changed to" << state; emit NetworkStateChanged(state); } //网络是否可以连接 void NetWorkWatcher::checkOnline() { QHostInfo::lookupHost("www.baidu.com", this, SLOT(getIp(QHostInfo))); //异步非阻塞 /*QHostInfo info = QHostInfo::fromName("www.baidu.com"); //阻塞 if(info.error() != QHostInfo::NoError) return false; QString ipAddress = info.addresses().first().toString(); QTcpSocket tcpClient; tcpClient.abort(); tcpClient.connectToHost(ipAddress, port); //150毫秒没有连接上则判断不在线 return tcpClient.waitForConnected(150);*/ } //是否连接网络 bool NetWorkWatcher::isConnect() { QDBusMessage message = network->call("state"); if(QDBusMessage::ErrorMessage == message.type()) { qDebug() << "error: NetWorkManager DBus Connect Failed!"; return false; } QList argvs = message.arguments(); uint state = argvs.at(0).value(); qDebug() << "NetWorkManager state:" << state; if(state == NM_STATE_CONNECTED_SITE || state == NM_STATE_CONNECTED_LOCAL || state == NM_STATE_CONNECTED_GLOBAL) return true; return false; } void NetWorkWatcher::getIp(QHostInfo info) { if(!isConnect()) { emit NetworkStateChanged(NM_STATE_DISCONNECTED); return; } if(info.error() != QHostInfo::NoError) { emit NetworkStateChanged(NM_STATE_CONNECTED_LIMIT); return; } QString ipAddress = info.addresses().first().toString(); QTcpSocket tcpClient; tcpClient.abort(); tcpClient.connectToHost(ipAddress, port); //150毫秒没有连接上则判断不在线 if(!tcpClient.waitForConnected(150)) { emit NetworkStateChanged(NM_STATE_CONNECTED_LIMIT); return; } emit NetworkStateChanged(NM_STATE_CONNECTED_GLOBAL); } ukui-screensaver/src/displaymanager.h0000644000175000017500000000271414205074704016740 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef DISPLAYMANAGER_H #define DISPLAYMANAGER_H #include #include class QDBusInterface; class QDBusMessage; class DisplayManager : public QObject { Q_OBJECT public: explicit DisplayManager(QObject *parent = nullptr); void switchToGreeter(); void switchToUser(const QString &userName); void switchToGuest(); bool canSwitch(); bool hasGuestAccount(); QString getDisplayType(); private: void getProperties(); void handleDBusError(const QDBusMessage &msg); bool process_is_running(QString name); private: bool _canSwitch; bool _hasGuestAccount; QString _displayType; QDBusInterface *dmService; QDBusInterface *dmSeatService; QProcess *process; }; #endif // DISPLAYMANAGER_H ukui-screensaver/src/tabletlockwidget.h0000644000175000017500000000635314205074704017273 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * Authors: ZHAI Kang-ning **/ #ifndef TABLETLOCKWIDGET_H #define TABLETLOCKWIDGET_H #ifndef QT_NO_KEYWORDS #define QT_NO_KEYWORDS #endif #include #include #include #include #include #include class VirtualKeyboard; class PowerManager; class AuthDialog; class Users; class UserItem; class DisplayManager; class QMenu; class DigitalAuthDialog; class SwitchButtonGroup; class WeChatAuthDialog; class VerificationWidget; class VerticalVerificationWidget; class EduPlatformInterface; class KylinNM; class TabletLockWidget : public QWidget { Q_OBJECT public: explicit TabletLockWidget(QWidget *parent = nullptr); ~TabletLockWidget(); enum pageType{ pinLogin = 0, wecharLogin, check }; void closeEvent(QCloseEvent *event); void startAuth(); void stopAuth(); // void RecieveKey(int key); Q_SIGNALS: void closed(); void capsLockChanged(); void screenSaver(); void blackSaver(); private: void initUI(); void initConnect(); void onSwitchPage(); QWidget* getCurrentWidget(); EduPlatformInterface* getEduPlatformInterface(); void updateNetIcon(int status); void paintEvent(QPaintEvent *event) override; bool isOrientation(); void showVerificationPage(); private Q_SLOTS: void showPowerManager(); void showNetManager(); void showVirtualKeyboard(bool isShow = false); void setVirkeyboardPos(); void switchLoginType(int position); protected: bool eventFilter(QObject *obj, QEvent *event); void resizeEvent(QResizeEvent *event); private: AuthDialog *authDialog; VirtualKeyboard *m_vKeyboard; PowerManager *powermanager; QTimer *timer; QMenu *usersMenu; Users *users; DisplayManager *displayManager; DigitalAuthDialog *m_digitalAuthDialog; WeChatAuthDialog *m_weChatAuthDialog; SwitchButtonGroup *m_switchButtonGroup; QPushButton *m_pb_powerManager; QPushButton *m_pb_networkManager; QPushButton *m_cancelOrBack; QPushButton *m_pb_skip; QPushButton *m_vKeyboardPB; VerificationWidget *m_verificationWidget; VerticalVerificationWidget *m_verticalVerificationWidget; EduPlatformInterface *m_eduPlatformInterface; KylinNM *m_kylinNM; QWidget *m_NetManagerWidget; int m_authType; int m_pageType = 0; }; #endif // TABLETLOCKWIDGET_H ukui-screensaver/src/ukui-screensaver-backend.cpp0000644000175000017500000000774114205074704021160 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include #include #include #include "interface.h" #include "sessionwatcher.h" #include "screensaveradaptor.h" #include "types.h" #include #include #include #include #define POWER_TYPE_SCHENA "org.ukui.power-manager" void sig_chld(int /*signo*/) { pid_t pid; while( (pid = waitpid(-1, NULL, WNOHANG)) > 0) qDebug() << "child" << pid << "terminated"; return; } int main(int argc, char *argv[]) { // if(signal(SIGCHLD, sig_chld) == SIG_ERR) { // perror("signal error"); // exit(EXIT_FAILURE); // } QCoreApplication a(argc, argv); // 检查该程序是否已经有实例在运行 QDBusInterface *checkInterface = new QDBusInterface("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", QDBusConnection::sessionBus()); QDBusReply ret = checkInterface->call("NameHasOwner", "cn.kylinos.ScreenSaver"); if(ret.value()) { qDebug() << "There is an instance running"; exit(EXIT_FAILURE); } FILE *fp; // for PowerManager fp = popen("xset s 0 0", "r"); fclose(fp); // Q_UNUSED(fp) QGSettings *powerSettings; if(QGSettings::isSchemaInstalled(POWER_TYPE_SCHENA)){ powerSettings = new QGSettings(POWER_TYPE_SCHENA,"",NULL); QStringList keys = powerSettings->keys(); if (keys.contains("lockSuspend")) { bool ret = powerSettings->get("lockSuspend").toBool(); if(ret){ powerSettings->set("lock-suspend",false); } } if (keys.contains("lockHibernate")) { bool ret = powerSettings->get("lockHibernate").toBool(); if(ret){ powerSettings->set("lock-hibernate",false); } } } // 注册DBus Interface *interface = new Interface(); ScreenSaverAdaptor adaptor(interface); QDBusConnection service = QDBusConnection::sessionBus(); if(!service.registerService(SS_DBUS_SERVICE)) { qDebug() << service.lastError().message(); exit(EXIT_FAILURE); } if(!service.registerObject(SS_DBUS_PATH, SS_DBUS_SERVICE, &adaptor, QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals)) { qDebug() << service.lastError().message(); exit(EXIT_FAILURE); } qDebug() << service.baseService(); // 发送DBus信号 SessionWatcher *watcher = new SessionWatcher; QObject::connect(watcher, &SessionWatcher::sessionIdle, interface, &Interface::onSessionIdleReceived); QObject::connect(watcher, &SessionWatcher::sessionIdle, &a, [&]{ QDBusMessage message = QDBusMessage::createSignal(SS_DBUS_PATH, SS_DBUS_INTERFACE, "SessionIdle"); service.send(message); }); QObject::connect(checkInterface, SIGNAL(NameLost(QString)), interface, SLOT(onNameLost(QString))); return a.exec(); } ukui-screensaver/src/verticalVerificationwidget.cpp0000644000175000017500000000667214205074760021664 0ustar fengfeng/** * Copyright (C) 2018 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, 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 "verticalVerificationwidget.h" #include #include #include #include #include #include #include #include #include #include "common.h" #include "wechatauthdialog.h" #include "eduplatforminterface.h" #include "accountsinterface.h" /** * 忘记密码后,校验页面:分为二维码校验和手机号校验 */ VerticalVerificationWidget::VerticalVerificationWidget(QWidget *parent) : QWidget(parent) { qDebug() << "PermissionCheck"; resize(600,1000); QVBoxLayout *mainLayout = new QVBoxLayout(this); setLayout(mainLayout); m_weChatWidget = new WeChatAuthDialog(1,this); mainLayout->addWidget(m_weChatWidget, 1, Qt::AlignCenter); mainLayout->addSpacerItem(new QSpacerItem(0, 250, QSizePolicy::Fixed, QSizePolicy::Expanding)); m_phoneAuthWidget = new PhoneAuthWidget(this); mainLayout->addWidget(m_phoneAuthWidget, 1, Qt::AlignCenter); connect(m_phoneAuthWidget, &PhoneAuthWidget::pageMessage, this, [=](SwitchPage s, QList list){ Q_EMIT pageMessage(s, list); }); connect(m_weChatWidget, &WeChatAuthDialog::qRStatusChange, this, [=] (QString loginname, QString loginpwd, int curstatus){ //QString loginname, QString loginpwd, int curstatus if (loginname.isEmpty()) { // Todo?正在登陆???? qDebug() << "wechar name is null"; } else if(getenv("USER") == loginname) { Q_EMIT pageMessage(SwitchPage::SwitchToResetPWD, QList());; } else { qWarning() << "[error] Username does not match wechat<" << loginname << ">" << " local<" << getenv("USER")<<">"; m_weChatWidget->showErrorMessage(tr("Please scan by bound WeChat")); m_weChatWidget->onReset(); } }); } VerticalVerificationWidget::~VerticalVerificationWidget() { m_phoneAuthWidget->close(); m_weChatWidget->close(); } void VerticalVerificationWidget::paintEvent(QPaintEvent *) { int x1 = width() / 3; int y1 = height() / 2; int x2 = width() / 3 * 2 ; int y2 = y1; QLinearGradient linearGra(QPoint(x1, y1), QPoint(x2, y2)); linearGra.setColorAt(0, QColor(238, 238, 238, 0)); linearGra.setColorAt(0.5, QColor(255, 255, 255, 138)); linearGra.setColorAt(1, QColor(216, 216, 216, 0)); QPainter painter(this); QBrush brush(linearGra); painter.setPen(Qt::transparent); painter.setBrush(brush); painter.drawRoundedRect(QRect(x1, y1, width() / 3 * 2, 4), 16, 16); } void VerticalVerificationWidget::reloadQR() { m_weChatWidget->reloadQR(); } ukui-screensaver/src/switchbuttongroup.cpp0000644000175000017500000001156314205074704020107 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * * Authors: ZHAI Kang-ning **/ #include "switchbuttongroup.h" #include #include #include #include #include #include #include #include SwitchButtonGroup::SwitchButtonGroup(QWidget *parent) : QWidget(parent), m_checkedId(0) { this->resize(264, 48); m_bg_switch = new QButtonGroup(this); m_pb_password = new QPushButton(tr("uEduPWD"), this); m_pb_qrCode = new QPushButton(tr("Wechat"), this); m_pb_password->setIcon(QIcon(":/image/assets/intel/pin.png")); m_pb_qrCode->setIcon(QIcon(":/image/assets/intel/wechat.png")); m_pb_password->setCheckable(true); m_pb_qrCode->setCheckable(true); m_pb_password->setStyleSheet("font-size:16px;color:#ffffff"); m_pb_qrCode->setStyleSheet("font-size:16px;color:#ffffff"); m_bg_switch->addButton(m_pb_password, 0); m_bg_switch->addButton(m_pb_qrCode, 1); QObject::connect(m_pb_password, &QPushButton::clicked, this, &SwitchButtonGroup::parseButtonStatus); QObject::connect(m_pb_qrCode, &QPushButton::clicked, this, &SwitchButtonGroup::parseButtonStatus); initUI(); } void SwitchButtonGroup::initUI() { QHBoxLayout *hbLayout = new QHBoxLayout(this); hbLayout->setContentsMargins(0, 0, 0, 0); hbLayout->addSpacerItem(new QSpacerItem(40,20,QSizePolicy::Expanding, QSizePolicy::Maximum)); hbLayout->addWidget(m_pb_password); hbLayout->addSpacerItem(new QSpacerItem(64,20,QSizePolicy::Expanding, QSizePolicy::Maximum)); QLine *s = new QLine(this->width()/2, 0, this->width(), this->height()/2); // hbLayout->addChildWidget(s); hbLayout->addWidget(m_pb_qrCode); hbLayout->addSpacerItem(new QSpacerItem(40,20,QSizePolicy::Expanding, QSizePolicy::Maximum)); } void SwitchButtonGroup::parseButtonStatus() { // qDebug() << "---------------------------parseButtonStatus check id=" << m_bg_switch->checkedId(); if (m_checkedId == m_bg_switch->checkedId()) return; m_checkedId = m_bg_switch->checkedId(); // switch (m_checkedId) { // case 0: // m_pb_password->setStyleSheet("font-size:16px;color:#2fb4e8"); // m_pb_qrCode->setStyleSheet("font-size:16px;color:#ffffff"); // break; // case 1: // m_pb_qrCode->setStyleSheet("font-size:16px;color:#2fb4e8"); // m_pb_password->setStyleSheet("font-size:16px;color:#ffffff"); // break; // default: // break; // } repaint(); emit onSwitch(m_checkedId); } void SwitchButtonGroup::paintEvent(QPaintEvent *event) { // Q_UNUSED(event); // QPainter painter(this); //QWidget为绘图设备,创建一个画刷对象,主要用到设置颜色和填充模式,brush,setBrush // int width=this->width(); //获取QWidget 窗口的宽度 // int height=this->height();//获取QWidget 窗口的高度 // painter.setPen(QColor("#ffffff")); // painter.drawLine(this->width()/2, 0, this->width()/2, this->height()/2); // QPainterPath drawtriangle; //单独画三角形 // QPushButton *checkedButton; // if (m_checkedId == 0) // { // checkedButton = m_pb_password; // } else { // checkedButton = m_pb_qrCode; // } // drawtriangle.moveTo(checkedButton->x() + checkedButton->geometry().width()/2 -6, height);//左下角,第一点坐标为(0,height); // drawtriangle.lineTo(checkedButton->x() + checkedButton->geometry().width()/2, height -12);//第二点坐标为(width/4,height/2) // drawtriangle.lineTo(checkedButton->x() + checkedButton->geometry().width()/2 + 6, height);//第三点坐标为(width/2,height) // painter.setPen(Qt::NoPen); // painter.setBrush(QColor("#2fb4e8")); //填充绿色 // painter.drawPath(drawtriangle); //绘制出图形 //设计稿变化重新做界面 QPainter painter(this); QColor color("#ffffff"); color.setAlphaF(0.15); painter.setRenderHint(QPainter::Antialiasing); QPen pen(color); painter.setPen(pen); painter.setBrush(color); if(m_checkedId == 0) { QRect rect1(4, 0, 120, 48); painter.drawRoundedRect(rect1, 24, 24); } else { QRect rect2(140, 0, 120, 48); painter.drawRoundedRect(rect2, 24, 24); } } ukui-screensaver/src/digitalkeyboard.cpp0000644000175000017500000001245714205074760017440 0ustar fengfeng/** * Copyright (C) 2018 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, 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 "digitalkeyboard.h" #include #include #include DigitalKeyBoard::DigitalKeyBoard(QWidget *parent): QWidget(parent) { initUI(); initConnect(); setQSS(); } void DigitalKeyBoard::initUI() { setFocusPolicy(Qt::NoFocus); QGridLayout* mainLayout = new QGridLayout(this); setLayout(mainLayout); for(int i = 1;i <= 9;i++) { m_pNumerPressBT[i] = new QPushButton(this); m_pNumerPressBT[i]->setText(QString(QChar(i + '0'))); m_pNumerPressBT[i]->setProperty("class", "numberPressBT"); m_pNumerPressBT[i]->setFocusPolicy(Qt::NoFocus); mainLayout->addWidget(m_pNumerPressBT[i], (i - 1) / 3, (i - 1) % 3); } m_pNumerPressBT[0] = new QPushButton(this); m_pNumerPressBT[0]->setText(QString(QChar('0'))); m_pNumerPressBT[0]->setFocusPolicy(Qt::NoFocus); m_pNumerPressBT[0]->setProperty("class", "numberPressBT"); mainLayout->addWidget(m_pNumerPressBT[0], 3, 1); m_pNumerPressBT[10] = new QPushButton(this); m_pNumerPressBT[10]->setIcon(QPixmap(":/image/assets/intel/icon-backspace.png")); m_pNumerPressBT[10]->setIconSize(QSize(30, 30)); m_pNumerPressBT[10]->setFocusPolicy(Qt::NoFocus); m_pNumerPressBT[10]->setProperty("class", "numberPressBT"); mainLayout->addWidget(m_pNumerPressBT[10], 3, 2); m_pNumerPressBT[11] = new QPushButton(this); m_pNumerPressBT[11]->setText("清空"); m_pNumerPressBT[11]->setFocusPolicy(Qt::NoFocus); m_pNumerPressBT[11]->setProperty("class", "numberPressBT"); mainLayout->addWidget(m_pNumerPressBT[11], 3, 0); mainLayout->setSpacing(16); mainLayout->setVerticalSpacing(16); } void DigitalKeyBoard::initConnect() { connect(m_pNumerPressBT[0], &QPushButton::clicked, this, [=](){ qDebug() << "DigitalKeyBoard press";emit numbersButtonPress(0); }); connect(m_pNumerPressBT[1], &QPushButton::clicked, this, [=](){ emit numbersButtonPress(1); }); connect(m_pNumerPressBT[2], &QPushButton::clicked, this, [=](){ emit numbersButtonPress(2); }); connect(m_pNumerPressBT[3], &QPushButton::clicked, this, [=](){ emit numbersButtonPress(3); }); connect(m_pNumerPressBT[4], &QPushButton::clicked, this, [=](){ emit numbersButtonPress(4); }); connect(m_pNumerPressBT[5], &QPushButton::clicked, this, [=](){ emit numbersButtonPress(5); }); connect(m_pNumerPressBT[6], &QPushButton::clicked, this, [=](){ emit numbersButtonPress(6); }); connect(m_pNumerPressBT[7], &QPushButton::clicked, this, [=](){ emit numbersButtonPress(7); }); connect(m_pNumerPressBT[8], &QPushButton::clicked, this, [=](){ emit numbersButtonPress(8); }); connect(m_pNumerPressBT[9], &QPushButton::clicked, this, [=](){ emit numbersButtonPress(9); }); connect(m_pNumerPressBT[10], &QPushButton::clicked, this, [=](){ emit numbersButtonPress(10); }); connect(m_pNumerPressBT[11], &QPushButton::clicked, this, [=](){ emit numbersButtonPress(11); }); } void DigitalKeyBoard::setQSS() { setStyleSheet(".numberPressBT{" "font-size:20px;" "min-width:96px;" "min-height:64px;" "max-width:96px;" "max-height:64px;" "background:rgba(255, 255, 255, 15);" "border-radius:16px;" "}" ".numberPressBT:hover{" "background:rgba(255, 255, 255, 35);" "}" ".numberPressBT:pressed{" "background:rgba(255, 255, 255, 5);" "}"); } void DigitalKeyBoard::onKeyReleaseEvent(QKeyEvent *event) { // switch(event->key()) // { // case Qt::Key_0: // emit numbersButtonPress(0); // break; // case Qt::Key_1: // emit numbersButtonPress(1); // break; // case Qt::Key_2: // emit numbersButtonPress(2); // break; // case Qt::Key_3: // emit numbersButtonPress(3); // break; // case Qt::Key_4: // emit numbersButtonPress(4); // break; // case Qt::Key_5: // emit numbersButtonPress(5); // break; // case Qt::Key_6: // emit numbersButtonPress(6); // break; // case Qt::Key_7: // emit numbersButtonPress(7); // break; // case Qt::Key_8: // emit numbersButtonPress(8); // break; // case Qt::Key_9: // emit numbersButtonPress(9); // break; // case Qt::Key_Backspace: // emit numbersButtonPress(10); // break; // default: // break; // } } ukui-screensaver/src/screensaver.cpp0000644000175000017500000001025214205074704016607 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "screensaver.h" #include #include #include ScreenSaver::ScreenSaver(QObject *parent) : QObject(parent), imageIndex(0), timer(nullptr) { } ScreenSaver::ScreenSaver(const ScreenSaver &screensaver) : mode(screensaver.mode), path(screensaver.path), effect(screensaver.effect), interval(screensaver.interval), imageIndex(screensaver.imageIndex), timer(screensaver.timer), imagePaths(screensaver.imagePaths) { } ScreenSaver::ScreenSaver(ScreenSaver &&screensaver) noexcept : mode(screensaver.mode), path(screensaver.path), effect(screensaver.effect), interval(screensaver.interval), imageIndex(screensaver.imageIndex), timer(screensaver.timer), imagePaths(screensaver.imagePaths) { } bool ScreenSaver::exists() { switch(mode) { case SAVER_BLANK_ONLY: return true; case SAVER_RANDOM: case SAVER_SINGLE: return QFile(path).exists(); case SAVER_IMAGE: return QDir(path).exists(); case SAVER_DEFAULT: return QDir(path).exists(); case SAVER_DEFAULT_CUSTOM: return QDir(path).exists(); default: return false; } return false; } void ScreenSaver::startSwitchImages() { qDebug() << "ScreenSaver::startSwitchImages"; if(mode != SAVER_IMAGE) return; QFileInfo fileInfo(path); if(fileInfo.isFile()) return; QList formats = QImageReader::supportedImageFormats(); if(fileInfo.isDir()) { QDir dir(path); QStringList files = dir.entryList(QDir::Files | QDir::Readable); for(QString file : files) { fileInfo.setFile(file); QString suffix = fileInfo.suffix(); if(formats.contains(suffix.toUtf8())) imagePaths.push_back(path + "/" + file); } if(!imagePaths.empty()) { path = imagePaths[0]; timer = new QTimer(this); connect(timer, &QTimer::timeout, this, [&]{ imageIndex = (imageIndex + 1) % imagePaths.size(); path = imagePaths[imageIndex]; lastPath = imagePaths[imageIndex - 1 < 0 ? imagePaths.size() - 1 : imageIndex - 1]; Q_EMIT imagePathChanged(path); }); timer->start(interval * 1000); Q_EMIT imagePathChanged(path); } } } void ScreenSaver::stopSwitchImages() { if(timer && timer->isActive()) timer->stop(); } bool ScreenSaver::timerStatus() { return timer->isActive(); } QDebug &operator<<(QDebug debug, const ScreenSaver &screensaver) { QString modes[] = {"blank-only", "random", "single", "image","default-ukui","default-ukui-custom"}; QString effects[] = {"none", "fade-in-out"}; debug.nospace()<< "screensaver: "<< modes[screensaver.mode]; switch(screensaver.mode) { case SAVER_BLANK_ONLY: break; case SAVER_RANDOM: case SAVER_SINGLE: debug.nospace() << screensaver.path; break; case SAVER_IMAGE: debug.nospace() << screensaver.path << effects[screensaver.effect] << screensaver.interval; case SAVER_DEFAULT: debug.nospace() << screensaver.path << effects[screensaver.effect] << screensaver.interval; case SAVER_DEFAULT_CUSTOM: debug.nospace() << screensaver.path << effects[screensaver.effect] << screensaver.interval; default: debug.nospace() <<"screensaver path not exists"; } return debug.maybeSpace(); } ukui-screensaver/src/pam-tally.cpp0000644000175000017500000000525314205074704016174 0ustar fengfeng/* * Copyright (C) 2018 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, 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 "pam-tally.h" #include #include #include #include #include #define PAM_CONFIG_FILE "/etc/pam.d/common-auth" PamTally* PamTally::instance_ = nullptr; PamTally::PamTally(QObject *parent) : QObject(parent) { parsePamConfig(); } PamTally* PamTally::instance(QObject *parent) { if(instance_ == nullptr) instance_ = new PamTally(parent); return instance_; } int PamTally::parsePamConfig() { deny = 0; unlock_time = 0; root_unlock_time = 0; QFile file(PAM_CONFIG_FILE); if(!file.open(QIODevice::ReadOnly|QIODevice::Text)){ qDebug()<<"open /etc/pam.d/common-auth failed"; return -1; } QStringList list; list.clear(); while(!file.atEnd()){ QString line = (QString)file.readLine(); line = line.trimmed(); if(line.startsWith("#") || !line.contains("unix",Qt::CaseSensitive)) continue; list << line; } file.close(); if(list.size() > 0) { QString line = list.at(0); QStringList strs = line.split(" "); foreach (QString str, strs) { if(str.contains("deny",Qt::CaseSensitive)) { deny = str.split("=").at(1).toUInt(); } if(str.contains("unlock_time",Qt::CaseSensitive)) { unlock_time = str.split("=").at(1).toULongLong(); } if(str.contains("root_unlock_time",Qt::CaseSensitive)) { root_unlock_time = str.split("=").at(1).toULongLong(); } } } qDebug()<<"deny = "< #include #include "types.h" #define GSETTINGS_SCHEMA_SCREENSAVER "org.ukui.screensaver" #define KEY_IDLE_DELAY "idleDelay" SessionWatcher::SessionWatcher(QObject *parent) : QObject(parent) { sessionPath = qgetenv("XDG_SESSION_PATH"); QDBusInterface *interface = new QDBusInterface( SM_DBUS_SERVICE, SM_DBUS_PATH, SM_DBUS_INTERFACE, QDBusConnection::sessionBus()); connect(interface, SIGNAL(StatusChanged(unsigned int)), this, SLOT(onStatusChanged(unsigned int))); QDBusInterface *displayManagerInterface = new QDBusInterface( DM_DBUS_SERVICE, DM_DBUS_PATH, DM_DBUS_INTERFACE, QDBusConnection::systemBus()); connect(displayManagerInterface, SIGNAL(SessionRemoved(QDBusObjectPath)), this, SLOT(onSessionRemoved(QDBusObjectPath))); settings = new QGSettings(GSETTINGS_SCHEMA_SCREENSAVER, "", this); connect(settings, &QGSettings::changed, this, &SessionWatcher::onConfigurationChanged); idleDelay = settings->get("idle-delay").toInt(); } void SessionWatcher::onConfigurationChanged(QString key) { if(key == KEY_IDLE_DELAY){ idleDelay = settings->get("idle-delay").toInt(); } } void SessionWatcher::onStatusChanged(unsigned int status) { qDebug() << "Session Status: " << status; if(status == SESSION_IDLE) { if(!m_timer){ m_timer = new QTimer(this); connect(m_timer, &QTimer::timeout, this, [&]{ Q_EMIT sessionIdle(); m_timer->stop(); }); } int time = (idleDelay - 1)*60000; if(time<0) time = 0; m_timer->start(time); }else if(status == SESSION_AVAILABLE){ if(m_timer && m_timer->isActive()){ m_timer->stop(); } } } void SessionWatcher::onSessionRemoved(const QDBusObjectPath &objectPath) { //如果session注销了,则结束进程 if(objectPath.path() == sessionPath) exit(0); } ukui-screensaver/src/grab-x11.h0000644000175000017500000000145314205074704015261 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef GRABX11_H #define GRABX11_H bool establishGrab(); bool closeGrab(); #endif // GRABX11_H ukui-screensaver/src/assets/0000755000175000017500000000000014205074704015065 5ustar fengfengukui-screensaver/src/assets/iconFace.png0000644000175000017500000002657314205074704017317 0ustar fengfengPNG  IHDRx pHYs%%IR$ IDATxOl׹sL0vb% T\v"H\)"R,Ra RVmz+!7)TfU4VFj+ed N`Ǯ\s xΟG&ywyR)%KJ]vqB6u!D{LfEuݒhZY(JŘ@HH)Kv I+OJIA$ KJ ғ{J bY%aE) "P̟F򦊰Rku$@ Ô呌R`YPJ{~$@ ɾ '|>VJJF."S̓~ l &2z Xl#_//΁t2p  "-t`-H:9_ P@Hg(cUi؀RADH)Mgmn$FX2?J, "g^gCh^3Mx1"EȘ~sv@tJg'e~ Q$ f6sH4X%o*$h FF"`SfpNnG!@UlfAD 9?LGޢ6 ZA0 ٟBt>@@ BN  Pf_A[0D )e?0ˀ /@W@8H@@X 礔}fw?~*sH<%0{YV3e|C H<&?1bgH<`KG NsfǑ8~)GTF v'EƗl3K;a8tO]kM5. p2c?خhfn$cAr$bAb$R !(L+LXFJ{CޙWJdZA` '%K9%` v;)@$N @h P4J @Jll` HRz?<$̜z?<+/ Y$ 2w17H)M)fČ~06& F&f4`Ą &fl @ @LH"ƛ rQ0$Ċc"Rza^3J9u$yM5S5h @ 4# h{d]N]8+/k`cH@k_@`u`@'4ABP'hs9?8vv{8"X @'  *H!wH* (c^Kx$ײ>x>sCP /@JϋXp)d `wYzl3m"w Hk1 A~\ !7 g&,@Je,zMlJP 9A#z} &0=9fGH'Hf61{'4 !Ev)e?;M51[&Rn!דU%^208vZp)uS6wARJɦ?@:LlW T''@"z}M`7B@"|E`6`6.؋XKg_;H)3>{&R^9?p\.kL&a۶m{]...N-,,LݺukjjjEXSB\UJ:' ]\ 95,--Mܽ{O?K/tGJo\&G3~SN冇z'=cg/w/~W}v) . HʬRjv200Xp)@t?z3O<đ[+_|'$^ (QKǏ nt6z/ą~ RGt1Ȳ>OǏc=vؖ~T27.;w]ԜRjƥT`^˸˂K"7󍌌fCՙ yZtc9ҿ^G/gΜyep lO.vگrOMMM~׮]vs HU[?KR>?\wQtX1cgB0:L,^ s/㡗yh X`[Y*cuѽ8:K.w 1 J]u gǾ8Ⱥ6&+ߠ_:tWCpҊRjҦ j]JO+c 1SM5 G8o8:+TȲ. ۅ$1Κ*lc?GIkb^lyZp @Mz?^zn>p1/@JK?N稟 }`Rj`^kծH`=&?s,qM LM^ /=g;K[jL泗~ Mgg䞥V *qi?l7ݥM\H%Fo=Ħ?9s8ji5J p?63=zNCX- &/077>?n߾ǾCXmR)Qؑ¿.甥X.@&aWN^L[`L-]R&\rrppɳ{}+qJo%V6McsL X+*@ba3 >VbUD*ւRz{'Jq9獁X&I,9섉b&X{`wX?ev=Cca񶶶&*\b-[>VQ(SJ8s?B@Vm&"kXý˹H){y/D lLL\\AѣGavP{%F70O拇pOrqh L 9h'X"&톇bP ,y{+$k{4F<?Too/Qi,lFT Ez$0ʀ?O󄇚Gbm$ ٘? K?Ow{j3`T6z===&8"U@?6=GDs[Npl"pr%ԃ{h9ؾ};m^Q8΀VpB&Gu^CZ&QG]W4H);x/0)R)(eVǼJ/(KJ 1iR[Y`t5J(`fPMml6j p .9uǺ4| pNA hI?vi867+5| @˯h(F7PN AةW7RκwEf^$#@J] pzpq]&fo @7w\:½M(inGu^&ᴩk 7},;}'* >J=ᅥ fp#zݻw/3{4vS@0fggqGM#Hk)ew 駟 5q#m&@)e;X]]okkaB^Xe˖ <2q6{󄇊7࡚1|fpW_} J7࡚1j`XW>cFQ !D;󣝝CL,JQJUX9/}2(=U>^<{kl @J.䎀߶m!&ݻd^~ IW?611q^@*j>)h@)fjN ƍ<{ӫ%Ν;.6bL߰`@f\x5q@0* R {vΞ=Vcl*lDP8!@6VA9s e0І^]^а #PE?Ct$#8Ag6x B@\rrppɳ{%@)K~>W^y~s8q@G-'=zCnۏ>过>>}^}R sرWf1z.>@%P2G}Ӣ'\R+8<ڵkr?aX555]v:q<8 PYF V>bHܳ458(ĺ=4y_f?{ } ]/p?K/t9q*xp<ëǏ8pu~.]? }* Jb]ٟTPMA_Kл';a?R/ ~,I}x/А_Ju" hC؁4e-4$ ]5qǜ4m-SZwc2Xh])c 4O=h=z9l-^ H}FKhh1cK{_ k1rc DW GWSJ}&d 1^`Iyz&@ &###>n߾GƸ1z1tHs`gttг>[d[^^Z]xdrr,]=F [h/(w۶mΜ9GD`I/HЩSr?ضmۡ޽{Ϝ9ӧ, 4: !z ϟ?22r,a ٳg" n!DKW?{p[[[Oӡݸq¹s%Vȓ?244t]柘@^:$tUѣ<G:;;\,ݶ믿>}Z$+t20<<ԓO>Loo![ ty~~W_}g} k /ܣ7>ӇOB޽{yvv~zNZ /<;r]۷oe2\wwwNF{ԭ[Ѥ e@ D@H " @$ D@H " @$ &9A'K ,1eI'EY @TZK)x¡c?TJx# aX7*%l k1 t3FGGr]۷o յYD܊|>Yk/޺ukjjjEXR)%B]lsԩS?CLl4q/}v)& ]f 6Ol6֭[w2)pO.]"SJMJAZΟ?;BЇJ_zL4ҢR`AǏ|?Fi!K_;xL<VPJ]N$axxʕ+'WWW8:w@w y+B~fq?ro={c>-}ի+34ѬRjVKYFq|}$D/|k1LɌRjN["w ? MGwEgwB 7"2?==3cC@K~ryh^裏^P:(*$uWUFͺvگrO@ ZSSSߵkׯV hnٛG @$ÆNukNL@ f#ݣ쥿l D'J)TNҗna]fW1WLR+p~@w ֊T )Ȅ>r!mA)u>r!NVC' MP֭[w>owttTȅD%~mZXf4@ &} }8R3o,>zx7>w\י`Ԍ% ^ lÏ] 1&)[G]r ٽ{t{M'VWW)(wlr)Z%<c ,;L6T1zM+{6y f8, } lo '`]M`۷s68XO500@68l0brS qM /i XpoP t,n%)j:7CSeвBb@P 5-V8W~WZR)`H)Ƒ R_>*R+CV. @Z-'JyZ-a8U?B !IDATHD$17vDP[$17@)k]ܖEU,bmd U$J&uf@i40h @Wu@P rԢ",8*,w*%ƒp$HDz\\m.6!-ƝP9E'T#4mXYliXӴ xl>?]ThX3d0=x"򶿕$QT["-IL CԖo%IUU6XL, @M=+*U%#MPQO" v3'&T%Ok!~򻜞ػUF@ =o&EF%5TyP?;nݺ5b.b@6:F>coC*iVĥR*O.Bv* ںu}zspGGǿ1UJY!8w! X1105&JT? } |߄T̚TJ{_H@VWWzB tb-[> +(}i/qqƅ)"Y \J0Ν;nc߂,$+ev!ޛ~#}P\x 1zjZ׳&ؚIuGdhΞ=Vc߀ĥk*%RA!DW?@xO܊RjҦ  ! @}*/_>o߾mmm=` _Stƥ vծ.X{wF?aA.$?U:W4ƩSr'N8I y:7>}zO q24N?{0K@|tƍΝ;.7@Ov !,}yGںuNh;w|>R߸z'6b20<: HZ@!E$8)e"Ň{VhDHJ7]n>D$,@diHb B& ME && )h@V +~H}cF3 56o 1"HR @R3_H1Ac~ "H'`v RvsB́BW0;WB́f4LJ/z)#, /L -B`) x &?KX Ls[b`?-8H刟H ̘jKlW4O ̔HaN $+` w chR?七Al`69Ql`69q!C kH<@5@x GO!qR@9B)N ;=F9)e@A*u9F_$0]BLc`S G6 M~!i'DzSoxHŲ!ļY e,:?`ל`?5biK3<@ L"0 eti?#@Uf`?$6&l$pXF> fN Vʛ'~v.$h`?BDQ Х~4-c (6!$LY"y'#2$ !@h1 4 A.lCbH(O@'<ѥ;&𳾏Đ 5fy PH RGUi ULU ^xF/J*1ͅ:%8`,zRd8N˭yTɂH m)8KJ1' i'RjчH S0C(_| f^L] P@-+eAg$Y*6@7  $ txh/>"ʬtdy!j0 ;LBɦB@d,qhA*J%g{1$@LA;ՂM)C'{u$@Rt=P#tObD(\t?DizY KAXNJ]v J D8@^d({r_ZO`!jH{{IENDB`ukui-screensaver/src/assets/scrollbar_down_clicked.png0000644000175000017500000000017714205074704022270 0ustar fengfengPNG  IHDR;֕JFIDAT(c 2p(05DRYfl`ՈK3604ӌFBj$F3^0D5 NIENDB`ukui-screensaver/src/assets/scrollbar_down_hover.png0000644000175000017500000000017614205074704022014 0ustar fengfengPNG  IHDR;֕JEIDAT(c-\HscrkDǪX5Ҍ 4#kfь Q ٪IENDB`ukui-screensaver/src/assets/hide-password.png0000644000175000017500000000051714205074704020347 0ustar fengfengPNG  IHDRĴl;IDAT8ұJQ߷X|@|-TLl%4V2[[JHa'hHk%#R.; cƌMDD\۶^{"b>" 3kf ؃m[9|FUݼpKUi{NmAU=c{|Uqf.V 1ՎqQU3s 3X:.[U=XjU R|yf'`xUkQ݌G{+"6~+bϏ>G`GՎ?(-IENDB`ukui-screensaver/src/assets/password-login.png0000644000175000017500000000027414205074704020546 0ustar fengfengPNG  IHDRw=IDATHA 0 'VO(N~1>4$6)?@ j=3PYq%8SVz%Kr;uEzE߯yC]g{ 0wkjkr/mcU;IENDB`ukui-screensaver/src/assets/lock.png0000644000175000017500000000147614205074704016533 0ustar fengfengPNG  IHDR::J(IDAThMk@jֺV*[7**~TPW](v%__Ѻ֕J *ڂmm.*]Jy%rrIbs`yL#j؝TY|Mp 8ց ЋQ013[XRK;i4%*L3g` W*p&|Q5zTfvzѵ*s\ʲF4:lfM }lf)8UulFOن>t|)R[ 63d^qo: .r5lj2tw $0 lZrNlJӤ4ƢS=Ep XML5l$$4 M8gf;vF'D`f%2ؚ|m_u"Y) Hlg4#]ߩb/M5Z"zzjUCm4 OjxE/πk-ԖD^4L@uCTh+_. Amjofյ'vhx z<1ڢ}|]c(itx{E0T Ѫ6Z5V> Ef:lI팴֨Q)oPWXIENDB`ukui-screensaver/src/assets/logout.png0000644000175000017500000000106214205074704017103 0ustar fengfengPNG  IHDR00W pHYs  ~IDAThZq0 }M7#AG`Fvlܑ3ϲ,04#q}hQh"QO虆Vvt;!:]cvTEh̵m+fٔлǬV6HR |"Wy^2T;tyWB[sI/f4@ь}/-+OS,XS;l?Xt3P7a'}Ǐ)<,;f@Q3# {܉]wv=RĿ?6|24zGG 6p gl 6g%T=ކ$|Œ`Y=W#3]hu_ mtqc !vS XHA㻤Kh{c Kh-{s7u{]|C{$= &~cW (bqmmb5Z?]nEIÔ WIENDB`ukui-screensaver/src/assets/show-password.png0000644000175000017500000000110614205074704020411 0ustar fengfengPNG  IHDRĴl; IDAT8ˋq#a( Q.)?@԰U{\"epye1&e!. Pr f=Nӹ|y~K]Zֈh4Zj Ef"bBD\?z]l~l׸V;xTIhF<Wф \F<8TG1X4h6Eb̓0'U?3_nC\́~ޣRx ډYE~38x<]q3Vefoŷ#b"F|O2/GمKW籪X?-⫑* "b/7Ef.̥ލ؇򽃲3QHJX/J.X.sqg3TujjeDOf +2 .a&VgAߐ4=؁~ ba8_Âk}#+Pf满j/ gIENDB`ukui-screensaver/src/assets/suspend.png0000644000175000017500000000146114205074704017256 0ustar fengfengPNG  IHDR00W pHYs  ~IDAThYq0 { #lPFH'(otǛ &(6H7;r*$w%dY1kD"Oxݨ ` ]o4OH"+(B7@čx-@/ b|s-*OBF˄a> b+[ 3]·p,v}d>+:>E XA -`P 8KReSnvi>jg^Q yҧC1]&w#iP {,y4Ɣs+pG+*{QpBno"h.`9gY{O?"y]~"!.ܥODڌU/}9`P ^(읦F˄{c["!kMHi<|OJ&V%+h_E <-Hb{]ر_*KI vQ7,wvň% Y$gQhq#c̯J ZR8Lw6_Ry1Uy~xpvӻlY1^eKv ZQ+G3+ e3׍0KɮOxcYG+:vѽX3;سң)={fL+ ൒&-1T[Zp.y=x4cG-ֲ}.-b2o(og}OIENDB`ukui-screensaver/src/assets/hibernate.png0000644000175000017500000000160614205074704017537 0ustar fengfengPNG  IHDR00W pHYs  ~8IDAThYq0 s#hx@ A@v&77@)xAJLrH97C/ؕ,)mF~@ ש@gvXXDf|]A]!b[l%"=! " px^ k v3mk  ݦYd2fvA|.I9=@9OawZzsHoÃ\ͫKH J/QgYHiU|q[UuK8. #|&"'zi)Oe-(3*Ƚz[Oljfr!*v *ާ:ތo{ Ldm6t['ߟ b0t2:bx2)tB8?+2 Ј}WG79DsP*{x18MMEgZT4VIPbf`+-Ie4Z4Xh)PAX*$:(l=R^'g5x rP9|p5ET;fs*C~fqMDLDn$ 'wa͸Oa*\<$8uoE$Wt!EχȚI7#o(=J~)7J{:玩F UzI(pgL7 ?~-h"vlm͜WQMIENDB`ukui-screensaver/src/assets/unlock-button-pressed.png0000644000175000017500000000104214205074704022037 0ustar fengfengPNG  IHDRJLIDATHka? AB:@ɟ !D%ВJ]3. TtRt? .vH,I -AA]"<x/|{{߻sJrlM`4e!p1NT>eZ%@;mko2Z-yW1m 2 R.És6ztsiV{zd{&O^}bDwV@0j<vI@g~e%~G+6-N5Us$y45 Mco_%҅  :~eQA.#_?5g uvQC@} p"}C+046B:u'*Mz-|gՁz4'XOF&a%=[QLAm~ZHI\f K"p4a:+~TIENDB`ukui-screensaver/src/assets/weather/0000755000175000017500000000000014205074704016524 5ustar fengfengukui-screensaver/src/assets/weather/35.png0000644000175000017500000003327014205074704017466 0ustar fengfengPNG  IHDR>a IDATx}]$q^9s?W{wErER #)cҢ-H$[$~!   =yH ~1`{e˲@e+ҎHJL2Hrww ֥>}z[v""!"a撈?&y^.KuTǎqԩϜ9s˙3g늢5RYpٺVD9SKKK'vzdϞ=?ܿ>! +~R`C ==z?ԩS?w7ESDZLAHpαPUU:(zEϭ|߾}_{x{oQPW)n+_?wcǎx<~]Zpn+kCDda) 31DVUUUQYT%%I7|A qU'3#Fk-qLas9RE(c P]T5EAySQREg 13آ(Le9%IM7x;o?>oW[Mcǎs.A%"✳Z44M9MSd*Qsn YQe2N)sr3;"r"b,Ʉ8xw|}{w.J \Ԓ~=z?QFF#˲fN&L&?gh67񚶫 뮻~]"Zjs6Iڵkٳ448}kkmUDY.kkk4NYD<σtz;?j@?qį.,,6 á-ш"D$ܤv ʩz#Gt:}ke]ז^:Y]]0 97#X|LD33E n}Qg=+!"4ܹsԺ.˲ I~cWvYzAZ {s_z=qu]I 7 wfL&d~ Z`cL]F|A[>%eI"BΞ=+ш"D$̲챏~zCzykKDɟ{ ~? ð:XZZ7 )k"Ah3jZ}am zd|w,K2̀l2P]6( pႬS]LDed2y~~~WDT}ݿr}`0Z'"v޽r3L-Wk `C57w^%tT[ k')MS꺦*V^/8;W>5KD#Gcȍ70ZM4L x鬟&`Rx!EQԍ)Rף$I(W)pRUUw޽r/~&WZ{GG3 Bk=t萬244QZ E܉^DA@DTm[CհtȑLӴg=t8peY,XpAt:0h>W 5iXD!z= "K-..RVDp뮻FWDY`"GKԧrν! 9eYRe%ǒe;tVU/| wR./|+q~YUUxu 7D4\Fɞ^{h>׏  (A `˲<.*OApY""<ϯ_ַJ}meUUΝ; ox>BM4͘u}`Ҵم;.PUDƘkVtuC54@(T,"Z[~xv]eiW LDO}}{4~onf ÐkZ@8JSh+Z:GkuT%EэA %i\5z=yꩧG?w]F}`(޵k_/--1Ç`0`hX`*Aph[S *ǔeY{4tܯ[S[(ϲ, D*o 0eY`O|.D~?ܹG~ٻw/aHD5DMb`v]G[mʲxLɄs]QN{~ M_{TMӮnGCV<4MgN8+!ҪIPE _ 6Vm-’&~+ VA. ^ר0&6ٳ-Y͹s瞡W. v8㜓(ÇͱvH M<&'0Hh⧐hj|vC:WuS~1hKǥ&;瘚{lO8q rKD_y<WDd'qӋ/KF^h Ck"ғؙd]/0"? qM[< n\AABH_4EQtM~kkk+pywa9G~߼gmĉ6ڤ̼ND&/m7ѝ`i Ws95E.I,"cSO=yzdrXCDnΝ޵k۳,ٳG$aF_`/׼x_ObC-k0m4yze.c֮Hsqm{]15a֊E!|_$x:~^l;offviC1&Pgȴ$jBkxD~Z˵ibtNÏk ~д4POh.JBsSA۹ẮkfO?zyaZ{xuu!ٽ{ I!jm4@WD^(Τ{h&{bfNk.x}A:}JdfaH;h+_Z1ImMyAyn@p"%IrQzKץ8(;t?2J^)ÇJ]CYXX`B@g%]\74h$A" " (OMV=!t׀[Ĺ$I:kC|s}?p=ʍ17V?%W .//EYZZ6b(fXW<hN '$fuNS14D/Ej; Nk``cvNkj]'^_ o]2sDZ]\\dA$JO٢Mm4(0y$=ڪh%i9Ƣ$@6PMp8LEopma.qرA./V/27ncz=t5&P  /4QUC^Aں!u[c|-GvOmH׿~&(NyFʢD,͠duu]-^R{10ys.`ѣo-رC$atTʆѓ gMڴ@B ~.żM'`0\<¨Řfrssm6WɈxee6"拐i.Dsu.L;4(xqqt/l'.Ldp8_y$p.4O>Vگ# $l\2#ZAJ3DAp]ג Gѷ^'"="(3(9Wu8): Mә2+L4VО5k`%OOC2Pz}7J.XX/=.m((hL PA q_TNU%aD䬵={nm𢳂> #"J(&>3'sjMᐒ$4MΊi0̄Bp_u Q>ihsgTN!`:݅J4(,ЏT}Kr9cYYYyhp'"V:"cV!q @ELܼ8Z:}hz }:^i[g_JYkk+&:JD %I2$\w>rUUś[ y> ڿ}"9uEu]/A2 Z+:M>O@&~YZhK~[G A_i!tm-4)oD280ScDQeYA"Z  %ju}" e'I"@o11Z0:{VW`b'}@=83P @'z4k@5EU6I~X =0 )I9z,"wرcemmDYYd澈sI$4ƈM;`rH־yo70i:/g\kd63wh)- ,$IT1c"`О{Բ~fZ"gZ<1ƀ؏_ӵ:l}5ӱ6d-,_k@<}^>lZ~"\ xLAB&""----r|QDE$Fj?DXD"2s?~Lgn7y@_]H&Ng&I'  >K׼C Juﵐ} ڏyѹ24M/roKk1Lq-?k q>F8礪*njYұ6Akïeq' uLtQkvQz #AS4'Ajk]g*57 =~18tJKKKf0 7jWt8އVrcCͪ`eh<ciK r"|yp&7w4Q:v5h7zUh䇒A )$ZǼvܹcǎ4.+9SH)yVBH!$"#"%yRuZ urůo'я5VNx7Z}@`2s=OVע>:$!= m86\3siqDDq]׹"KwWRcCN AF959fATDT; 3KQ SIBL[ R h˲)B`A->a#MuAݜoY?uI1 ? _M{^$ %I4̜Sc͉ŞI+a&Wez5Ӛ5\ӡvbI}q|mN:I C}Wɮ>K ÷H>`0OZ1tΩ@iJ`!><ιjI^TXQZOh;7 ̬?72 ñs.afaf oZӵ ~])+E1z bԣjy1}|=:$n(d4ݺ_뚃 j-Z/5Jq aC@ BM*km-,rg)U}/h[!Æ u MBZڇk>kD4C~E[@@ 1ۤDQE 0F,AZ+]dm~^Zdz& h4aaĘ 훱'm]bӺ@"r]>H8\/@<Ҫ>'>з^MsvwuK(i.$IRDQRă;u%k &4 SUU5RUթI\Ue@*.V5CaQc5С mBTU1|Yu@PVZ#fZ ]m}`CtjA `"(4M(0Lq p @MGED3s{Dt(#u]w!dO{YO_m~uӓoWV@cZ0/Z~Pk|C`h^\A̜(J @1OZourj$o ڮ"y3&AYgX=A4W\AN U>>.c)`˂.$C }M/,8|7}5p:B 1[aVAj:ZxdOPO6ʪLӪDGD*uNWBzR43ד mk)>ւzuf.HkZd4Ȥ i786 sIDAT4[ʉ1FD@h{H?"gfnՎMDZcʲJs̷IS<Mg]8ZXm˶AtqXmιE !ת-)d=&%\hZTiEQ89Su̅1f3"RH)h;7@a -YyK,;̛UU 1Z,@Whc2< ,f6>ᡮ~Z'|"=|7_A}7 +q$yoXk9 "c&̜) 4?Vvg n7" ".˲7Ls=c~gHF&y62qmUD4S}R}"Rz}]`0#$M7}S:RKG>DgL5(d:<ϟzEQu][k'\8*"*y@u ""Ƙ: z<kkk@Do߾qα1FQ;p-At tdP~)^18`eY(:Xի GhOM ҂8*c̩:Aڑl2.^x⊚z( 777o'4ND1IBY4Im6u)8L. QkL&&TƍO&di-־][ (c,kn \zyCan͙.y-@@D)ICtٳgq-|\!jL2*4 BZ 'Xki8v Za' mZAaqhg5|vQeYJ*gZSk1&ky[-"u m!V!"M~׻ޕsطo{9'i]m1t)ຮme`ޮeTE u]S{CG`q4&Wߍ!$ }qBmʣ0 8˲Z[DQ$QUƘJDJ15?A3/eH^>w={nllϟDQp뽇tٗ&XDԙ~OQu5Djw@!Orצ\Gim4["NDmazYp8i:6"SDp$JFSk-"{-3I5kF si_}&2p0Zpf"jBEQtQ-ÂBWehcp- Z1eq|6^a(*k&Y}V0sFt:=#ok-2ࢴo֏bgg DSO8I%ȧOucl:4 zYk4Eⷦ)M&TS뚝s'0ZhG "b[0@gJ^^M"jV kkkk_?q6 ?ۅ 5PY8@0Ngfֹ8W@>OЦa=ZsRUO&qQ?N8GIlvKD2f3Qc5c&u]h~+y{e]u 1Ym>  f=LD]@3xԦ_kB1>k ev9rktƓAA0fMczƘ-ј9]/^kkkgv}Ν;wu0L\ Ws- = H"X ھ_o<--'fzsK2q-4mϬh!Q:S \@UUf}}TQc& Q]Ht=M0 f Q 5 / VȔ"2&[Q٪Zi3~~:v[֡( L&i4u]w+"oA! (ft%4FY[wD8;sw$4ƌ$0Ƭa:3sc,OhM69n\@vI,ۨzt:u^ۉb}v}\fzFxܙtn rE4?o.Y`Ѡ,[ EQǏ}eLjhZ$ qoшq̴ּ~=܏wqxyyy'91HBDnqcW G D?XyYdBL&{:_>oڱJ[>SO>}!"czsٕ Al`{Q }SNEQLDeN2Af|#3wu^20aD7n:lȡ,q^nzI NMe!`e|ֽt:d"u]'NwWeYneVUթ N:W RS&|yWg.\ܹsN>}ѣGשasۮ]Ko- 9ygzK?Pe&bUJWD",CI{At+Zs5G1v 3*2脟ecf{ȑ{omZUU犢0NG$x^v% .WQ, ޏ{]YlS#u]3G4[!SB+K׾+)`?o4 (" 3i^h!HL  <l,6Dۻj;wLbIt`0vE =2`u׫hZWLSN2N( L&( C=t.P+|fh3ҕQ}kދ3<8p&cQ[qdc # -_`! ,Î#. -Q+-G f'd2t*ys{/ wuy䑯sSED}M2}ݮ4 3gΜӧOڿ~?v͎ئ"Bxރm@D C/3GQDItnBgt8Zx<һ^G=O~GىuDD }=fI}ݮ4fAqz|iii]v]DĄa(`CL.ЋFR`}X}&BpD]CD !ھ2J "{wn4n5?G/P#)%\ MR<'?w{ EQᢴaB@POD]↙>=˲i[ _oǢ^w0!iIe gΜ~~_vܔݏ1_jhvB (8yǏ?6w////5u+xԾB.+{}^֋53$߾wDd2_~vG9FkͿl^x+۰HF=hC)*fn֟}]v pҚnJ%.@8h"ak u-m03=cg/裏~mX-m|J h@Jo{~[o}BN lizQ~D  E__–I6L>|fӮpE}^+5 HZa25=Z ' {7/--m`q~  +yP*,mJ9:gYo|yQȔ' Ƙ ܘQAbcL9HJI$ͭNU;o喷tMoٻwnuNG #4+c錠*Bl҆F٘ꩧzw,ujXDrj4{L]cZ;jjsޥk  WUR#xaH#zlfYc7|ͷ޸<Щ[kC8&eKnFEQb:Qu<}G}}{<ǨdMnh·ADAlUU}UbkmjU X 6DDQ-߿quu~o}/<# ~VHF@='|O<'~\ڽ¾Q{lR[m^?+/ծ&4$"5,$3<($" @ ///ؽ{u{ٿs+ z= ~>QL>Μ9sϝyg=y󴽱vM=d ~B[̼ծ&Z"kmb 7lcj@۾4&I`!IA'IZkCk״r:'d<FdҒOjjVP#x-1Ƙ*KD[-RIi yBm59eL61[-5)k7Z-`'1f1f[v5 摵6sN  efC-3MK6Wm |Sc̘W~=ڞ*>pQc. ڶp' jɌ1"wzS$ 'ZkcjIS ´ͽ@̹1 .\ݒn? 1&2ye "4}E`9W:f6bx@~ @t1@_ZPSsӋvzÅKys&MxT Uf<_{S#kZ֮kZ֮kZ֮}mdIENDB`ukui-screensaver/src/assets/weather/48.png0000644000175000017500000004764514205074704017505 0ustar fengfengPNG  IHDR>a IDATxwř?ӓvvgV+r$$[p s>1ωg|` M!@JBZVff'O1ֶfWpyٝz U-o `>5_1D=7o<1O&UKT9sVl&òx$F{kjj:&Ly}@rhmm]gϞ]]]bl#\EpyQcmsض ˲9c NTUc 1LaY DlˢU$I̶m9#mj1't3ӦMr0*?C688# Be))ɲ̈ PU*RdLӄafP(P(@uXƘ ۶dYi|ޙ3g>|gwǷ9]+?D1s~eݺufA4i,rD" IpslKt$vk-˂id2<ɠP(00i6뺮iض5kw ,Vd?4?syW3JDL۶%IX(BUUX(,.AyD/2i"<]KH۶]( H;UmC$z0dx<G:fmsιiH$(?.i<#W?UU.i2ι\QQF(KP`jRnY Կxx6ra&$O$d2Lu1fY aٿ替 ?IDȿ닕eٴm[ 8q"eEŠ*|{jDHBsX~]CǕq+R)>00d2XsJ$UU߿+:37O #ٟիWUt:}v4I3X4et8?ӵ}_I I(u;|̶m^($]י(ik׮k_ތ#, P"{+'|w/P(d)B!i̙4޼R/kQ}U9to71 iѝ4~: 9|>oǎ~s^ x;%@r0xCDZ W՗WXX4 ɲlZbΜ9D"L$"(^7Pd̉ ˲.b(q\ ,˂(L4fYu]m~申>{ ^p31Ҿ}&rYBD|EEEBiӦu0~ 9\$yĉ|ҤIL%K߉Ċ"&0 %E m$P(2yt]$I( .#D"c3M|>Su5<\ @Ds0(o۶mΝ;O>p)dra4yc~~ݻwlIi4i$D-qQUY8")$2i^Ta,7AP( 0 4dx,ca`0h|/׿0jd޽qƍooo$J-TUU)++C P-I^P9lۖu]䊝L&0ӧOgމ/yվؼ-HEIS(FK1=8M01@:F,C&A.H&$ fr@ЂT句 0& qz0s ¨1G(,˂ $(|>reҲ{:\&~ۦM~8i$=(I&Lsah€H|a D\a8aQDFJ1ȐԷWҞf]s$jb&K.7M%>1IjD+iUTT;;;Hq!ۑ ׾M^lnnv§NHO3 b٬;1A8@;4 :s K\.'mRȟF"dh@ ѝ%f[xLϧܹ?4G9ϟ_䖖>e&NR4Dab1>Ef$Nɲ MQ^^EQshd{1t ԉf(MGL|+M,f0 feY|b߾}Goڴy<)xM`r;ϟ_(i[ZZ%+&6/Z$JoVTD|H꺎>!eeeuLD|)D/ƛ("f!s,p(e1\e4M* p0'y晗rέ`0(WUUS+/' ")+VYF] 5M ffGi]ב UUQ^^۶]#b!e"*C<CFfͶm#ϣx8̉FʆaXsνX,G|R /xi< `0ZZZ(Ti%LtGORO#YDPWWSNiɤSã\L˲PVV`0L&3*'FEw(UC0ts+!DHI>bU$˲:;ny饗NH0vcc[ZZN4z^^^>J+ "EBiWDI;|>աڝo.!_]]\.D"xSn={`0hF"yLD`&Fa>w+>h_L(Ar|B(++.kt'&k dYa@]GĤA35EńdYfm3ι9guuuvWXU*4MF<O=jJA K4|> ġ~&JXH*! bppe$٬;|̩eYHR DO(eYCmmmOa h^WW@ Ƙ@ pP;߼ I0766$؇1ͫD-~;il624>J@Q?$H䢦!35 T$$0xiS <:I䪪y4A>; 5\ jb(W꣦Ub-aD{Qc^( "A&4NL&uPUp1Ljcbtι+0B1'aR@}$I ϙ3͛7%\jMqƉ`0(w$K)xB!DQWC#y%M8?Mz>(s@I/1I:}&E#( n9ISfxNiڹs^]((.4MHg2hvP Y}.D DH$>e0'=G/AhRJ(Q;<1RT^`F@D,# tbbzn\Ѿ ^I 8`m[,rܮ ٥#1 .++;K/}ӟѨP(>0IHLB"P$FSBc|/A[)#"=/i,ᙱ\W:,aznWPq[QzI.0o'?4J4e <3x}L N{ĉDO:=s׎~7DX0 Qu}BTf۶k󁢇@($baGA%dfA*rur1&"ȱ$5ض#ϡ@`>7\FiӦf GSޠH ԈBu'KC\:\ ]BRl4  2[T F@:FPpu}Sj<1(8);WYŃ`cMMͬ.x ;Ŀ^ &@@WϟkkkWY(%`DzczJ1K)F@ SA Ld3P}o߾O?=*˲YYYuQ<"~)&N$M*1VZࠉ|[-% *V (jGM IKdZ`-Pڶl6j2,G,*е^姟r)epX>}:F iBD`ex 6Í ",HzC/ HR@:FMM{?nͅP4B@ re15Mf.%M^]l„ \b#'u%w½i"t{{gEI(+ Fj;#!hll9%s \ \O,hT HG4 |2IiAf-2`|PHnjj>у"5Q&^bp<7>RHs爫o1f@`xݨAee%1G$44`F1N1j23p g! `U"=F19sHD4͈D"jee%E|ƘkƲcOpEo<`<"׊cϧ})35kH"< m ߏ.0PQQJ-HeyԊ"1OE`I#i ̲,cAPN4i+//~E,U.5c&;yux;Rۇ"QF LRI9:H@0D8v5y,_UUפP!#J&B B!Z?pƘ1Y2"Xk1c5ČG/EFBފcpEGͩiԩSGͣ񁸿a@ I{мQL AS=\P(4JUU%\pvI%H$>=R848PyAM\#;ahhh3F@ mp=m D!a8/dGiS&E}>#t,'V>֤xD-&cJuI3_cil744-:- i^Rm$a:O,p2䪪Rͤ+SŠpEQ0*pR!b.PLb$/×zVK AB!TWW# #jW`$'MOaezG#b.2$qM%KP|R Zea^Q:kD)M@FU@RTXc"&.2Xt<Ѩ9b@Y SjqdYf\. @ŗ[ șiI$K΂ХRvӋ D nNq_/K1xׄDQ>zGD"HR(++sK|f`DRb9]KX4M bYLN3t:-IRsέӒ6n-|oK(3)!OA;J ++q0,K2M (&06cL6 Æ ̙sv6٬( 0u.N8QCz^~*J?1[$.R x5[^.u",A p5#I4^`L)B9R.K t0$ιg }}}>h4*;c $p-w8&b yXJ_n<HX!/5s( tHBRL7A5ma|>-bm7o~Zes`ӾC|t:^`۶-IP\k?jDHtvnT,NH|Za]\R*^hx@vJC+.Ӓ IDAT=+Hs@HIE8*D5a\.g3Ƥ͛7ܿ:Y ۶Q|'H wvv3g̘Q[(,㜻 KI:FxQ꽫yE/MU޿cEټ륌@"iMA.C.C&AOO`0J=QBCv_hHzIu['vIrdgA`86x 9& Z|^ ,pNc1#"aTt{#|c!q^<*D RJ]tS["S2D<҄=/$!#{D3 B,˲c`OOO.\wzE@`(8P(J?b?smL R zUEQ^jDyDt,r鳗𥀚7N=_S/y̢eY0z?l@}È9cسg&˲)IA 9a@жO?~|3Ϙ14MdY[UUX L'PXz'5;$1-Ds#R${%V^<5O)$e2D50jzbh  HB;t][[[ף (%̭$I9P>}o===9I"~?d63   x>w38Rɜ*KDχ"7$,&." 5*&"N.9Jaq_V,rZ;v@ `0Ү4wM&hy-R9g{W^$/뺮)9P$4%]יb*GJK|W*]!eN'{&ϳ<0сݻw*HÊ1zvu;UȜ1&kneys> V 4茱<\eg۶9m.HTn۶յkǛoȲ*++HYYYc~9s,cIx0QiDJO 2sHD.2,bޥ~R/ZX'އL DPb^q|4_4~rB`zzzb۷o<{{˲Ι3gmہ;wcPX1˲ D/Ht;E\4i3fT'I˶mTU`2J1NFμ@dRHXIy75;`R.؆sO(.$IJ0c#ģCKP( /$F#~w>W_}uiyM Sc*cL$9/8p{ dY#K̉*O^ʯ/%'fD[ʏՏ7D-졵ΡC<z={w߅eYݧŚ]TH#XE3]m۶3ڰw^tuu-p.I}:F<Goo/۱c84 eeen{[)Kyfi޽{qγH]OP u͛[[[[ߟa`lkks '|JӴp@o__~X1sb ~۶e555u,s,XtP$U2J9GUU*ض~C>c * D G{,gF*rs ^ fMdl'=PQVkp)Sb$I$Ib`!RU|ڴi8ꨣP[[j̚5 ۶ms{r9TVV '3#&t]t:m{zzl Eoc,hc 0BAιeY|s>܀?nN 6㏿2mڴ-nݺ~7͋.]{V8FȌ`hhhYYYҶm;c9% e]6555uU$䒉VUU\wuؽ{) PU---xW188JAeaƍ8QQQQy~LEW"O=N?'d(y+|j .\s?8p8O;e̙Q7o^}WWW_( $0 8>00F+kkk矏͛7B̘1ͰsXaLMܮŲ,TWW}X"ի]0(ȗ'i1ydߔn$G]]_Xǝ@d2$I=󀃛,y!$I ۶8v͢Im08\l\p'N1cF5k^pSZ[[wzWr) Q[[œ '¶ 袋.mܸ. hnnf@fزe ordo%Ir_~z+D"1>L<}}}`)_O8#ɸ&&heYEee3(u]gBg2){t3Ɔm΢HЇuر+w0ɓN2e?Xr厚G/첓O?<p](ƭ3 F ~|nҥ J2pB̞=luuuAuL0Guz{{]NTwwoχs9< ^}U$Ipeee8^fYTTT`x1qD׼DQtvv عs'0Ny"i}D"$E¿%_Y;v,-pLm۶9s̛7 Soڴ 'OvCTe$;GV(l4z͏=M:j$@\UՔacFjiDbRwwo%/xGmjjjy}ݭiU{{{z]'tߝzǨOc=쩧={_J&Hq'(I΋N>o޼Zkkkc)>}:Z[[b |_Eyy9=XȲF%z,.s5|=EBE"b1u]8ꨣd'{H=2 O,_mbL$x`v7;cƌa淾[s8UNµDBYwvvEO:97n~;1`;uٶ-~[А\sI'5>{yvgΜ)GQ_xh"^SSFҫbvk*%Ĕm*ªU~\r%G__T gy&dYFee:, |;I%l]יݻ}:::0T'?,HiduӦMUVm}@7zzƌUׯ߽vۮ纺F1}Ce^eY4zɒ%c{ b헍]ck׮};ECCCIoY[lɲ`'N-['I/ƪUx{{;[p!wk7A}"8أ$E2bɔ~Cu`֬Yxgyf{. T]ĝ\sҹ(k_~4+ޥJ߲M|t2hT=Sp*@ R/-?/Th2XIFLCumۃ<(J3cYEQR!C<&˲/ U˲xuLӴ CCCoq+O~rӥnmcuuu y:`FP(barok|4~zڵˍx'֧R),/gu֬xVrBTGH1C5 @Ν;eY6~x֬Y;D":k}zM7={}fl eYW B۶|>Ϩ T*\.?3gD{{;9lݺ|-sh;6KpR(bIt:{mg/_dS9sx Ipcx P$\Z4}L&F#]v٧>kϾ{os~8>4 @^tg^Q]]9sfN]| gq[ne(!˲x<޵nݺ}7n\5iҤ)ӦM<\QV(pB466rY]edY477cԩ;òe1W\H$©# J@Q5O2,|>;vsrs(F>Αe9eY aymYIzH:{>SotM v,R2x-iZ\uͫSNsWݽW_]Ͼ{a0rN510 }Ϟ=ٳ}ihh2qĖoͱXL/G4mO>ݻ0[4y N5ٹw}1gTƘ>"Α0,IR@In#Cy%\D1v0/˲)IRaz=ז{~BS 05k 0:ں4F%Q %>mڴ-z>wP6p47rΑu :dBɌJYeYN͙CZ(>˥xz۶m_<餓nPvڎ>}ݝ^1eʔ58|m QI"$缏s^,$ݒoqK1~'p¢˗[o^y}_җ/^|׮]y/M4]w]e]O}*k׮r뭷W[sYQ$IYI2iR1TIDATT@OD(rX`D`۷ᛏ>W\qŜ.{ӧO?6?-m>o޼fwF0H(mضM>AEQ&~׿p@ RgoyGuuu 7p>_]|r/78暚o3NRߢPIgm&g#<R xK/w{}޽;2o>}w-Zh/>mmh2)RqwTp|g?,~۶s~4d]]݉K,kpk׮Lggg_?B{kjjqox)'|rӵ^t:ztdY.psNHXc"7o~nZj|0gϞŋ/{wr9cǎg}vN:7xC۶>$/muQi*42&TVVC9<s9뮻vx[8shhZ|yw{{{s-[ WXq@|Kt,˳eY*IDڗc'|u]v5 ~ĦMy2;v޷o_>oٳg>wP\,Q'"|8%j&(5 p \hp o eo޼99睝ٳپ}O>_ӓ?dY*I4QP+~]hCwկz{<y:惃vWW͛b袋\vXIl5k<{k?ɘo馓lW\qQ$K,  >s̻W^}7;7y9+V8} 9ȠFVLնkUW]7n%\rk/Ydi$Iryy9bJMM ׮]?s@?+++_ß}޽U]]] &Lx9p&www} uE|'wO6|ƍ ͛76444MBl*dɒ/ݻ7u֤w\}wɓ;::pԟA̟g]v0Lo544Dgkjj$IFGGGۏ;MLʁbDݱcLJ^{mS-[{ws%,x^c(W88@/ gfň9z_zmݺn_}$Ie7n0k֬םȕ|>w҉s#`q{%MMM~_۶mX|Oti++(f0X- FW_}fϞ=q֭ݫW~ϲ{"!)>V&PȌ5h۷oA^~568t|{EۑT[aL4 ]]]W^yώ=czꩫo׷㏟$I~%1\{hH$UUU  s׮]X]]݇񙃣x_mgz7Q c>UU(F IRifgWڑ ( _s5vtttK~m6 (>Ī%IE1wV$uYՅb"H$&>X[[{lsߡrU>o>$I~)'Gq˛s>Uf*ۑd seYc5ZU$\Q h(_{WFϝn)])HSHɃiJ HK(B% !- ybiy(5BgUh46ۇ4Yfoz&(iE e  YBx03$euuuuHʲ\Cu]BT*{QAw}9"s)ndžaaKm,>w^D"sΝaǖ’Duu)Yws)8''紴ؙ6dCN>rRK޳%yGӴg˓TUmbXcdH"@cc7'Ν;D)5HdSJ9rҥxb#(.Dsuuuҕ+W'UUwOLLx<fgg?~ʬEni?~. 2&EQT !!dBG. l/ ^X̝k 9 z|+WY0zPX%}zG<-S~ !L'VٺqnR<(̐o'^D!A[a%-#EuVmQ%*,QK[5Dob/C*^IIENDB`ukui-screensaver/src/assets/weather/0.png0000644000175000017500000004047714205074704017405 0ustar fengfengPNG  IHDR>a IDATxy%Gu';'rkRTUZ@b!L23v6^n@nnh<4"  VTUg̼yUTԟeyFD$|{=ߞoϷ|{=ߞoϷ|{zLv?:y?`fjޗvܷ<xK xxN;pMLC-_/|v>{@σ3W?`RI.y 뜵 }O;|N5GkoIϪ|z"3SԵ*ޞD*?3NX@m-pfīYxϧW̡}ekg{{`mn_?j?P_Wlx zo7E!/ϷV~ N q/?n3Gϩ1}tV`;fTEqFԺ~F썿-l#OX {^5p*H%#x:߬>;ob/~c@{>?s G|`&lԈ>]</+tw.Ѝ[gf.Rz 7mpj=VD.l4Kw|+5.Ӫ±Zu{G>+׮ş:K` Rzϐ?N%_o|?QomS$<*Txl؞#&}yVP"f"XϯoLs75oȧ+;18k_OGw} Lh7TMMn߄אP8Uzҽ+wnzvzCz7i\ ~0C@C<۳p\ȁObO?ޤʌ/AsQU6|_yO|k>W8bcWh* T~D]u:TϿBf*O߽wKO~K4~nTeBRJ*o߳>Q7&2ܖ5^z~+$!L\?Wco+bÉ'5!H#zhi1:OU=?xy0iQRa J-w]C  X73?k8IӷsL5|&UĪP<\5_K;1lmbpХC}ʺ.3U .5z\)(X}N_`HC`{_޼j5v=7o~y/5TEH%95DXSw]u۱˟^x $"2!)po&Em .yqc+]GL1@AAjb)yLD*@eS]**;]`dk`Mv8^fxb)<#c*YoJ>[x3߄F&PNx]gڲn&UImqD-.+!֫H]z-Ae:~(_:֬ 6Ugb `H_j\O6mPy.O֭ . 黟fL26߼joy g4߽k5ڟ+xcK`4"k <]y ^5R L  PX6jkm|<$'?A, [uϢ>~77A HƠ+'7%Ut} խÓ߇ TѢ}߹ҾUSo( 1C瑍Ώ zjj߫_߫~mK/[wD ϋt}c˯]e+RWInjb;ҿ E,b"V1{,Dĝb|}zGk T/YyGNtHp#)gX17@i ũ5a>$D,/@:PgINZ <(NKJA%_.ؓH.Dv0*T~,iԓH GN@)6ր;/G}^d`@"Cg;(\>6u}|T0a @ ,hГN?uQn>%Hh,7-%D$`[5SKqWP9IC3}M#.ݞ8̄}^w<~[ʒ23'((q,I4-- Pf0&YN @'FKhN+&!@J 9)SAF@b96F6@̤ٝCJrA򨣈MI %`{j;?NpsQb?$̜0DIoA VEOCdJ2"]+ F^dHWFT8{Bby HY(1L0?g}0 X,@B,{p9Y+`(I d Q>(J9͂E)S1:hB}GTX'`X0o^oQC#v&40{yzwl;/xebšĀl~(JܖftB"Y"AJZdF/C/_DO7kə@DT6|+{V^kP=/C #lx(?F_h#@*ܷ!#%rmf]wN ʎ3̧d!6I)PuW囃x7+~ڛEYR S,yJM.H 5LgqG|zn=z}C޸Uc͘q x1y fzs.] 7YIWXjR#;CY̜#1Ht^t ]@/$JeEт'IY>鶠wQcj;6-՝/hqr3ܶSyX DmGػf˃`G j 5Cxu6$V1 ` [JHu7 i>s?^"(2}>b` .R"g3r 8f7MEFyPgmT8);FA Aw тdI!i+>t iVzP?t'[ȁÝ12U{Ǐ#Wն*"Y"T7V? /7BpmC*9#B8~u?f"Vg} GW@d} Ɓl+HZ IJLa1l"D {[Aw\is6km@#{~ߑd%Ml z"~AjbMv@MU_<ΠJ#|˝.gTՒ/?H }ЇM%O1 :>ۗ9| Ab}azQ}0LD1CHt)^8 >WW6/anfl6orū yְoK%!TAD`¥_b 햙7^#r4$>(l+{#)gFV3NS2o #,(u  U@ &"@w>mzyŷ]`0:mu1@@O\֖=~ =B|8g.2s}!Ri9%0䭬 ʜ_Š ]G ΑJ-~8? ?#y ǫ. TdT<"lԀ*-%gց{y%@EuZ V*GT}-a\7C1[W_e^'D{&U_︟SnO#2ϭF|) <ď9A* 2^?@\s=cB):8'a wyNQOR@{i8EZ\@ 3P=(:};$6f1$yDG5pJ^Bڥq z(}/lȈ[N=QD7v3`6~M)Ul1*mG+Ce$A3ܶpDZl"GAb#)p8Ju\1h m9̹+!^F2\^jRώi&gmY׾E4D- u)׿C%%&$R%}r2#9=gG9V#$AY ?/zp!2O%zpe:s57],T{YtKb[0pSϬn3F,D`,%[JH|j%7WOr}[j[ 6tyYy«0D:U G,GX5Y;Sd2-zӯ}g/2Ycd+ 7MHF`VrI W| FKS9= cU1˜\O?V @AF@C`  Ē@\L+ʥM.3ZٟxEC_=yz n(ᅿH\HbG *jyF G'ߥo'Ju>E}% sr*bK# `kM*tN,tK!"X39T?szhn }5t"7_-pyuOMux~`E^+ @p=t`6P%̸7)'GV )#K/m﹚N'v`ulڰqym͒6i{6KhΠvk~-k~曧KS@˷7?{ojq.~WKl؈ʮ7?s`_(͉_YDL;n!et {Зသ|H|m703j2%->,ECE% @=opk9$b#TJ>"iN!Q2Œ,P0"2R2߽z|l`yl+kBe1l.C E9fԟW{2 ǾnYMG3yn,` h@!'}x@&${n$e!T;:`bݜ @t 3P|e@$ gRa50#wC_bIܤ"nLFjSo wS#v0 Q&v?J"X > ARA1_4PIL +F }O5'p#/T(5xb-zpxm.Rj=zL?p ,JQ#[cz*T) l wLW^|o_SBB>H \4S\$0 $p9˜] + 3\"E "1-s/W#wA%W ँ(kBQ]M*^D@b}"`%D2GڈH_OM%  Ii /bV.g>P܌3B : )1˰[+4z>#E1?F]CK^Bk[<2Ϯ.EDݏ`m5 NX8[{-"Ko޴sO 7wA SXA3QAu1* saW$Nvb ? َd ٿՀP(ŭF>?DL@ī6Ѧw6*XbDZpvW580#[Wrᆘ)~sy/'ol=HE`E08/n>=ny{g%EWE F]8ŭd|$XN5.m2dc&pkhؘa":U/M[X#ᳶV Pn jLM5*7U @2I@Cl ʠg,$3Ez|䪨(RXQ$jQߖgYp2}'!%qJS@"fo_}'M$fN=;~OOoV5fC&("ֶIrtydά^hn"YIl b_L.r-mR>Οv1n2$ɡbɫx Q41m_JGL%u.cxuTh[FD 1DRd( lǥEWv. ì+q}=ʞb-m`rN|񃟯7&Q6f}&gbb ۛqb_@>`v0KYe|<%._Ê:j-@1M;f.BJ:t I@ٶ!Q~CrE qzŦH"E01tuwzhr\ r,~o_ObBW>PBZV`r+ QX(h0nX}\M?Z2=L=6alr"o2gݶGĊ'0L]IMB}ep9 @딪c^r4#]FŽMB/KI &G@@6KyNX$AEi]v5~`TpL`L`$N7]@Wic CL襥J<|d%O>gk3f @[HwCkc|rTU#'0`| YͰ p(N@9eLzgG!D,&rQP#(߫,J , ]̐٬ڿzH y 쐻qޯг" po] $X6:&L%p` נ*r{K 5 ,AZ3 \'7Aϻ;<ի<=a@9 `dKqI˽ưI2IM+BD,nlӉq ]9QYF3I;Ci > PTU :[Tl-ḭ̄ATX\_@nݿ 'bhwQLd4r Ղj>TV\eU 1"ggF53Y,ڊP3'y%ChV1p*ćXrf J  l$","*{c(fVQujED1A^ 3]05g#x6$bF = mew8]oؾi ֩0#@IXlNfkt[ NL!"+q  H`@V `w/6PF^2#ٷziZ@7F,,E|V  T% 3 CTn1 _W|M`߁!x˙,Ȭ6}dY>\Iw҂ei $ nr+Bnh!b7iD,R ZXk,EZE ?9=HԂ9Ud Ub f‹> ``TizO(xVQ@O4axX DgI'S%׬C7v ] @,\I%Ag{- TY%%|.mO1%.Rb`ۂ[ac&Erk3Һ#٩)^GL+]Ŗ8i3lBb=,xGZڦ)^5U^3޸!Nd]\5*Ȃ_YHQkPI9zE:ɒGт_T~I?+botsܟ8S{῝{rM7U6ɓD 3i& :"đ@z:DAz{ +WݴVRýp%~(UT[+0Lv"],| (@]|~/xc>-GB48(*T BWq`!J l(1jնMk099jo*1CZ'擃s vr7QlF$@Ȼu3Uۨe РŞŌ[xY;@ā[N/l>ˤdɜQ-)GX[s[;`šqZQnj23o WPeM׿8c0 ~<ě7/sСc_X"q_/UAZ ٴ!bGSTP.BAȹ|yj%>]IR<[Η%6*`H*CE-6OX;_؁ݞH;=@Tju6W^nw\!| fOùgA\I ޽o<HH:@5F <XQYw*LC(rA3k Np1 $B(1$I$})yؔg8L{nb:J>uYAq ܼb/96w yΌ3h\s0;9@Ym@,t;Ly!al)pHPfͱ6oK3VU 5."&DI۽9p&b;alf X[uB`"@R{c,W<_c $2 9S "[c-4Xj;W>[  .Kf^~'xwl6޳W٬{dM<h.S"LH:l%夊M#j} "@H#u6̀%i=C MW;tmaqoNOF=ؾc+.+tHLDëBc.KK;,BֳxE} yvoË-zM#~MX,Z!1qIR:c׹d]@)d׈gC$xv@XJ1,* b{׵Kc 3 Y'HQ%I:lhAa螇-ݼK[_ŕ=cjf!$_2f.Tng ?4ҝv/74ԅU}D3 z2 1vEzxz3bmvm1s%G-C%XK"R#@n.$ʼn3{ǃwx1zj@|=_f޵E[X K`AY{^ $ud/=~ ~|ʶA3aį &+GI]"nBGea!]^xz&ipisLDZMH2+) ql٘luKYzX~HK'.'VX5w~[8㭤(^V6Y9[Jly@H:w>£&Җ},Qo`jK,Z3Ɛ{&b/ %dcMySm pvbbm<6QY ~?"H(3Yt}?ɭw-՞>P Ł>r_W͉w@Y!@fDK,f1Pw޳=}42#MIT?3u-I%N;@Gv3vy zR*!imBDZ9HHKu _:֎U\N]dS4k Ᾱ[\zxEE=Qؠ}:"iH2m*@rƛ>L -ŊHC+J*7KkM=\zk3WTtbL1%d(hd[wBC8n88芜;i<@Xƭ[]8J%tGQ4OGZ7DRÍ\m/nl?:]Vvktጿڬi'~df@ZSm}mmT "g@fT]z^vb=Pۯj\o?MVZ|VfXW)-˝ oWtJϊs 86jE*U7a IDATxwՕ6{h4J(# ˮ]kwiql &gH&+!$HUuVM{4`穧u{ %& 轸 w"zPJR5k'ض$PZ &bm---[OuM #zW_M6Nf2IJ@kajjj61mڴ͛ٳ7Km`Xx /p͚5a !,H)&"BkMmP( @fO}ѷ}ُToo%'@xѢE\Kx<4emm-{qʱ=3?L$>prdF8^dPaXkM43 uaYVmmp}}}o,ܼS.?Znf /\Ҳ LHH&|Rcc#lۆv^}T*.Ų37)Am*&. ,lqF| !t}}W9'ϟɓi$uQGבGh4q#裏]`TVZkd2lݺmuRBaa$`?b J)ömyضX,c̙p ;餓^?Db'?d2L&4MqAa(v+1?l mۆ|>qP,avD!0 \O}}=ڐH$ ,l4xffT(d&mۘ6mSgu5'|3࣊} @wq7{W !x祔?̐R"byD$"+'>q /@; _pA'գ$Ւ=5l[|R34M$ ̝;"1 F1MRJX&L:Z[[)L"h---ڵk/+^蘂ؗ}dòq/:O$I`v,\-;A''YX fB2#8,z;B8H$I}}}P ̿꫟8 `_බ,)+$,K;0+%l3:0ʪٗV41sL$ ?/3ޏs(q'v%0"$Rj8>|_ʯtN bfZ 2MsRjێ;^ε +Z`OO:_Դq²,  v6 mem#8'̯95y>h4zիoG|cz/ 5kLZ?Z__Rb1Dss3Ϙ1mmm܌z(`%I 'm*1+`owGk65JjM{UCCCSGGǪL&C׎zٲe\s5j444ؑHlhhyi(`bBbXV R}5FUl}ЖWag{0Y5 L?\u֭[}衇Hgpq ~7f?~JJ91 Ú2e qૼ D |b|mpxQI]λ7XA秐#auE>ǔ)SN4 u%>&pwwwW_) a9scX,FZO8D4- ƜpTl~5UgO}0-?*~k0L)b'x"~뭷Q S̤{ɯ&@P_WޱcG)9{l># @l"3 umӱ4IaFa΅r4G3y셉d2a=drC[[3f3| ɩ~Zao O?s-2LN8| KO\>/OݮĀp^ ߞNbt8Rٶd21}?[;ATm.Fɓ'7NBMM f<ySª vr pU|ݝ_&i^㺮f,b(4l۶Nzٳgo{d>蠃{X,f.Xg͚EJ3@{ 2P(j_^|jl_0䛅J[=p@kڶm#JP( s1?}@ Pw嗯Fnnn'p$N!'P(t<(,aA0g#~0 ^!`2UP0zzz0a„;o]{ zΜ9ga(˲ĤIF˒]fJ&U;UsKD >JRayKٸP(ȪmW]uG #1cyap$xZZZ^ކ3N#J94;+,]Ntj|JaAݲ,Xh4xIc|%W S*E4e,A%FB%-|Ȳ,D"R)'pG=@4NlvHQy}!'A.T#*|atoT *)dw;mv }A8-2wwD4@&d2g۶96j'܁jIRnJ8TAJuV Ga ߻ 0Q !ز,={ nT "2R鞞"b5;C2*hL(Y8p% >i˫䄎೎ET|y;f @D$-[PJuJ&έRIR*I}L_^8^fժiJeVsT\ u}$DDBbf$ɉi=5B6nRJ uf9ˍya0TcPCc#>[~9 ;!Jj 0SXM=?AFW*Ͽ&pbd$0*ƚbׯ_nSSӼbmۖeJüaϻZ UG E<T\}ವJ>@t}0]$>F% 4&"5yמ<$"DQ6 XT~%543>+2+]͞Pwt5t.r^ e)X4&%b^`p,`n޼yWs12l4^0:5,aOJh_Xò`'V(}&%AoT&8'wA*WJRʈR*7sǪ2 @?looVkkd4l6YFyP ; GNK~:*wNQD89;XnX"Rʊ9pU0UL'g;XR3GPzSX,wؑ3g"bQΨLJ Om)XDUZp>>PMX,=s.eX B  n-L>@""۶.q'[ѕ_~?ⓠ6OA2sTsA=J#XF .0]]===?7:3DD3;(@im "Z|>?s/0aBq9eYP `'U;h~ Y Œ]Bi4 T6{\NO?o}(I}6W%ȝ4@ɤ֮];֭[{3vj 3?|PT*'T2i9l~\((jXz= T@@rnC'H]TI;5 P6X4yNWXѽbŊW H556666d2,+ -'NlhF0ژ0 vQ\/#8PɎæ%|xn|X,R&QRww?V۶PNݬ!& 9>Fq<1s;#J&߿ƍ}ũ_,Kz(e)I>󽶳8K1RJ~{zzVERn&%$F[}w[ ۽4{`1<-aBDmۘ>}BA1?YjG!1%|Ue$7Z۶MbC߃G,~yuooݺ ""fAg_5&t7?w9*tnDmf =ԋ< r& 8GK(l%ѷz/uuu ,8*+W;̃# -iպZAw7 Kh_Z/ L4{ဿ hѢ .|,u{B<zq`w'_D7ra]c x!2#uމba̰Q+HX 2qLj$^'S5z4g,AIC.C>|>oʠٹ|>Rqz'+Ks`樔2" ! ]!]TzzzK,Ys}=tgɕ(:`TԤ9} 4R 75Ȃy%?r4 f0xg8i0/^PwwOVpطba)}'VX2~[U8nƍ76a̬mv2pOOOoggggGG\.׋ ̜Ci ,Qio[nzްAEKi 2bP# b  3: 7뙾q=hH$\U6Q͛7/<9䐣k|* 4rtEc 2Lcu}}}ۈR(f$a˲(`FQ6z` <~wy? m%8͟luwwo^,/s9t5?}{LOs}SW3Fuִas>)2/tDLkeGNݯ W̘"/>ZܩY(av^{wY2k֬s̙?a„Ix\6X6 R6,wض===6lذbݺuo"M9s&M:45"؟;>hR^v%Ky敥PsR\zV;z-bԧ#{ ҄ǘkJH$vm!-}@CF2֪SliuyG̓K}  %3,"˟_|gN8qZKKKk"D"wFK{{]]];;;nGy(z֭kniɖImmo IDATmS[[['5555b14MCFqL&ݼyׯ1Di>EN@k84?$O\rpw8s(1;c'w+e>JM9O^mV- Mज़?~q?M aZYu~32xS r7}QIoy?t`z1hW0DmmmC}}}C2lL&H$R^ʚ]׵b.ɤ`*r]7u$YD%3H!D,%bX0JՑQJeDdPJ`xb3v tَ*#@{JN/9(iJiO55|e; 5;|qţ-fD1>]\U#q&f;wK{/1GmEx5x>dUTV񙿋 po jWXQeK fMqgE`IwA"@JF!6ac/aDC̈Nfӗ"-vf0ZK1ss b 0a*־uwt-똕(d޲jisH %z8Y ^NeP#ZvSj/n]ʽE@g|) :Z(چ (28΃n;@PB. }_8tu,BH"s&~\ta2ko_K\UE Ojk=^iopᯢ1şK=.h!K@pVC?j6 \/ 7?0D=ßKepY%$3ifs#757^ wpdL0"вUsa-s-͜1ԍ?<DF(%Z jG˅gThk6Z% ܂!$㖵b7KxfbW_Ɍaz/j5bAE.% \6?w:cXѬN<Ȓ2gڌ7̌fP (9g`*FwMNUF$m* HC[vK!#QU\fB̒d*C= Vǰj R'IC(F E/FЌ @.9{ aeO:ˤ qyC+M 0 ! }}X6;\Q9E iZwAr&>n#:H%]o_ 4Jt^A)&J1!yK"ao?% {񄣘iB>de`,̱'D"%e?2σ A fa@QN,ȥi~R#{6 C[@/@&9iW݈E(e5]åDžK5YȏlӲ̠ i } ` 8 ~ԁG@Aq mDNP}=8O֢^ djor/`f" }DpDJ)5QO{$bďqe_?``e⮇[kC1('13WͅZC'ZX4Lf5̐Bih|>Mř"`_2Z) i % -UhT W%"Б #`du$`\ 0}0D%.,B)y3D$R(iҨOɔ>" ɨFB&q1(pXFfp?kw/[xti0-oJJ1GBOCBA4dz_}u0 w0~enxe5K1z aj1dUY ZaFJ`w8mv!T׃+X8!bDV#6| A N@ wF|Uo>Hetle<6ih$e+ Q&ѻk~W`h !# x{^8B?vpSm1g;n}x) gۧOUۭD K{)?^OzэR')1뷯|n9P"F㽹+ _pz|f˄MML   e$ } _YP,53\q/\ɓ? ">P`YA(e1tB`ժ ]}nB#?'bX2~Vr;m\mǣ/b=XjDzp56gfDQ A0 *'~EM$)rOO&cw)xvaģfvz&|?ԕ٫:2}*`[:8)qKֵ6v|hO8>59٬#<&HLva xO>Ab)BP4I .nNe"2R eFsimS0E1k0eaփ-LqDZTo|%vS7sGwXHV\ݛ,8de.CjMV ߿calT#NgY"N=9=ZFOb_?io@#v Kj)L@3-!%'isKG$zҽ(eF%KFԚN*FpXLEe/J4b͸ӑ lzdỳϙs瞻i(Xfĉ9";w/%R&gC@ mw+.n,ؗRy1k>tkJZfCuJqˁųIHBͪ֋>"`2zm 6\Y|kn!FɜG;):82):TCSd󄓭y)vv>Xb~>bAHu/;aRԨa4+YeWo󺇞 }`7Kìt7uS9un1ݼt,"cZNP]Bg;ԍ`A4co~p?1`jfvH:Ȁ)͠!H1bsy\w# ED9a1@c*ÜNp+icM+2̔P?/c/ӏť *\_C@wFiߝ^R`ߝ[{),z:6{WB D۽z/Xon]FDxR O0 ;d@H{49gG~a6l's-d-4,5[{13ίt:[Q.zv?[ Ar[zXҵ@4{0Z;j|[ԽnoqL.-+SJ} ?$'y8=:eej4H3s?JkޫSz6_qʌ(g?#t [lq1Z?L .e؛ק5Js{nSq.p—&qI !zR؏ۊ62)u!i90&MQܨ`oP8a_sTpBuFiKkg|mL`f=_~R"Z6CJܹG;voگh^\ԷPD/JS-?no<ϗ5b[ Pq7J4Nefun-ngҷסCl'ƒ!C8+Q|C_{Sȁa)e]?@51M8{r8rdW}oO[êaXթ)~05u:GڙBG7e[5<^POɜEWO1K%4ZBDֻ]> Oopr=RʽgKp[ w?6&Qך|({|W1 id{:wa槹C D~$w =ŴC}Tڗ3Լ/sRʈ]kruR5˟$̢DʭMصQ(uڥ;@fysWJr!jC57VpOz]?gF_jZ7oǛhErfslؐD45G`XjE| %%:te;nEjxhu60"IZ 1)ٴb;sB *a.U7fՕ/" 'پB@iFHf9zt_qDE[M"Nf Yt]@2<4#|dC( 1BG^VX&2v+?>_ؽv&`6ڽyaءQdzLsMgHWuh<(2"̱)hS!3-q ][8aDžךt Z\V^fo}7ŋ9dFڅ?z֘PD.en|u3bPܷ_4K){R]´lCNL.(̤f f2@ŕL y !~xf) 1q0TNh>}֎h}&!+cڔl|c"{\55W@3fT^ W!DRN3MZ&y-dmZ'@)Rc7qk݋RS5Oc أRPJ<8SpQ;qLEIENDB`ukui-screensaver/src/assets/weather/8.png0000644000175000017500000003126614205074704017411 0ustar fengfengPNG  IHDR>a`tEXtSoftwareStardock IconDeveloper - Professional ver 1.0.0, Build 839 - http://www.skinstudio.net0lt IDATx}y]Uo3֜RI2$'"- ݡ[inۧ>DmҶ!Thb#DM3B%Cus^{]'֐"|w:w}p B,>2l9Yz# _۷kd2===uiPVr󼁳:+onnv$῞C@NO?}}.=|l6PJ9l˲@DB`fH)y۲t:ܜ9s\dɯڎke BEN5te?/Mǎ{ x3\.l\B]ו늁qL>;x;>֍ ַ۷өֵm"mtT[[X,(JCJ ry1)"gƌh4jb1J&pBjooeYz|T3`fytuu pRJRdfl<>Pf^PjR䵸 |xӦMߜ7oDX,Ft.\HtRJ|&aRJ T*UCu8S9\e󈙥Rd2;y^ϲvO>}… ;a7 82 ׯ_iF"X,&4/Zc{%a?H㠧l㜠xuO\ 33JJ"Hg}} mmmO.YɥKҪ)Pfוjt7fժU#LdL$za0򕲂/(z7 d@9A9a&EJI*fRkjj~dɒW\YU61d2׼d2i#cܹ ٽ^u(  BE@Yنa$Rx<^2krQ*1,؜9s_z7/_ۯ4L%@KN$2L---hoo?`aӧ(}``}}}(J*b*mDhllD* #UٙLLS'P(}}}d2˖--exd 3gǾDZϧH$R>r`P)y z{{UBUѶm444iqT 3`TxRy.O^s5?4 觜oӧ&I$ BuuuRz !D&sXx`Y"H$Z[[QWWWap(SBXxOG?zӌ344 Slٲk鴰,˵m۬mEt)ѕvYH$˲PWW)__-)D"Eoo/!psss;W^y if`̜924d2IpNma?(ReYbY è|AdR>a5zk}^z2Ϙ6mRv-˂ DW 8M6LIAG~z&R3`wpp` \[[;/J3dfRHyPl$P4h4h4Zy8o'0@ :A1,d2ID$GQĐSxe%ٖe`dj8eC5f6^n0N&D" (&G0 :Ϫx\wI)<]9J:砇b}5ΠSK?CѾ C7A~ Ð}}}+; ]8IrW]uխW\qſϜ9sf2tH$H$LJ1==ذ"tM3Lޟ WM4F`T*y~+СC)J~߯pMM LRF]]jjjJ@ k`vр"2^{~| 6t!'Vj"8hjjuJ0!9YBIRF:f Pcc#JJֲ We* %*A}$ 8tbbIVKR[vD1Ms=36mZ)Xlɶ".NiEFj@#6k`c~d dfdkqb8N)(Ny?篙6mZ1EsESS ^5dh6WAEJ%aT4͇>x֬[.zw0)Tʟ2v|@}};[[[KhjhhKtBm|XC,L~n0C)#sT9au9YPմFfæ RlV !'WZZZ={W^C0!x@C|q^3gŨFs9Pr0Z>L՘ㄛEcPuR@A& y .O&~@)hl|mo5k_|wg͚OZqKnBT\p!ʂ<ԕ"z* Qd(t @ em k Zy.!穯|جYv7 IbpKKʿm"T*%qgW2}awsƢ`33JaVGu:_}qVVHuX,GE&rK/} cM^bGSmۉƌ3*C՜=^ F6ȠCDOece0aUcQB}3cZR,EPBXd2g?O]k֬ X sϽ0 Fmm-Qi_5jZ!ZqB 0YAQQY_4E*OzLt.]Jw]y͚5 `,0x-ζm7\[zckz1Ancc՜ }_m\"88ADP*ȟ\d2hѢݻnڵ5k>.F@̙sy"H$¾B%Wk  :YaLh_5 GnmeYlY Z/m߾|pM78 p&jll<۲,m[b1bfVWޡLu~06l]ZaNcI5G ЇIB7/^m޼M6 /܆qfGH$R___?ݟGX)ۦBj}TTAUAq넱z?lRvkTaYRJ "/ "m^  DFQm'8}Vʩ0TS( fGpgXun0 VvwA)s<7S[[ꮻ {2ifDH5Dyar, A?k뻅珵cQ`0 aTDm#"Q" ˲D{{, " MDWv X0/;0P} @WH%v߃ )袋f,Z= dzRJRp0ۦ7F Ao^o2! Քj V02aJ& _)mH&|ݘX`4q]fu%zH Q ,)R5L:Xv^Pz0^SAm6<+WGDK5(#@063 Vb$֨#j~PTO1#A/LFhyj~ٶMaȺ:sŊk:QFe"2x-SNh+v>8k Hl”\'樆68z?yɒ%t]Fv{ّfbyE9p#hJiFr0hd((uRnNz צylQ;۷oǑ#G R6EPL5Pa*QCީA)_XKAW Z;;V#uB$&I6 +P(ںuE[(T*|>_UxxUj=Gf}u}+Ta4[@dLBF3aPo13x4& B "~% 6+80 y'}VSkX@)jPeNT=00fa'x^PiV_Sg0"8"BPp(#.E _Hj޽mڴiUW]5+H˲ "b"&l`7TsFlpHPjyzfNW^o]a#oJeacÜj?2Lο X`$Hy̬?#X---0M>yGjb/Ha T9z3d‚Qu10  <})iYJGH0lFh)0s@@jpp+7._|"T`VY]3fװ]5b*#}qVu :zaj>@ FUh~AXoד]Lc* ^Tׯ)0 )e#L iF6ٳ;̛7o^STdynR9j5Aו`%-< $jv<st Q PMFr4- uww|;{>!Q6 z"Qֶmvض=u]ZQz _3#5x3f l1,lԯ+.{w݌f19YJI?{>%!Dq3zF[l288okkk,2Wf:C~OLFJ)饗^ʬ]kePު'?a@>L|IDѾ#>=cXmۂu]RH- \(8ϳ.K-^B0z0Ň9 &ǀ^*a&EY5&$k8!B`s=۷),9 8YR "tuu{^|g_޽{w_OO,2"yBJ)ï?/ ' pRy%#(zp004^`Quww0 #USSS[WWW_[[[JD"aIDb ZZZl"H$BRJ&"5QQn0E6nzܯ@1C50Τh}#,ndǯ&< ֮]m"rqb!czWB9@)!l, zzz*Csv͚5oq<`f _5x;SAZ J)CQAf gP{) ^T8&`lڴ)swܗ_ CDt~J $Aو0 $EC@"{/^tŊ)R{P:m{YqLEL6̕Cp!P zeY3P#*X,Jf&'x=ܳ6&"} eyި[Ҏg@   pQ :xo<{ץR[j=f6X аAb8`*2 KDa,e*CBA>6[E/5T038p=}oe.(Qو1 xUss(<>8;v455ill@ٿPʥ`"$%yUf+d26br?gi "zPP al۶->k׮>q"Ba'+SLqr9(>#އ_|ŧ1 AR*6u`( skGQ#]p\ Ҁs|u( H\ve׮^z<O}& }:ணdN*tRQJ7 CJe!X Xw:Ukשl_G<̡}{?oa[fΜؘN&H$bX%\ ;cvڻk׮|> me@^B)ee6N4̏{W;wD}/fx*{0ZS&oƌ/+.]:;L*Jm䰵rAIѧ2eGȺ+\X,9sf,?vb"sP^`f߿}G6 FD?D#\ϭ"b?OB3XJa"^PGsDT`f\#x@W\|p{fsGi~~txץ ?2 `N=UUTʏ)e(OG>z.(S"p&*TR#f\'u!1 F{U1<ڡ 3u-k?O޴> gPAekq`V1/uuݻ^f_ 9~CLz֮022DJzOQQA31!AKuL @8k_/ۡ^37Gn,ݔ-bv"5ۿ闀/!|dM@/n·0?&ܳ1b*U2#K,a_(T0 zj4W'LIT竲TW^cd8o[?]x+IBvYK (OR :n7noSNd>qjί W|)WSDb0Sg0EieS @0? G*(?Yh 3T. FYJt]&in%2+$%Gr?Է^5Kd>YBP>" `E' R9c BT#B` @"H^ֲ7/I=B8s=E< ,`&$"59ƽd0IX8S.9~cf(bb[&嘍m\޲瀜wFV_ßm A++.R͖A<}DeO<_)QYv:T%t (0sDJixC,5I5P'"* !*0ʏ}5= ctv.ۿTm^Ѹ臰Feu]vߚt\u0cQ ̆~II>5l糫V_(`:ɗ^z`O2(PEI)gjy?:C )p%{!QT !* ̎af2Jf0fiU%b[vmUDs˙8^ƪ(-ۗ66[ϵW*;Lc~G(n(>rF"oKڽ zޯ&x^ybČ.j`jϯ/S*W~eh>T6mSQ=h}>bAOx%lj8'2m99';^G!)q<KX ˊ 3cF&& eoN2Bˢb) =̙@,ndHm IV}|KNq\O5L'SOWλl'Enm Lɜ9 QNZKN!d0 Ơ7aٻ#g*[@dgy 2|lJ`¡1JծLWck\eu|0)'}nz܊LֳTvsvk歌œMDkO3ppW~،ݹ??W1wo{ ?6~y*)ӝvO v]ֺ}#>}﯁Lӳ(QM9@J/:@ a=&MHJ"]Ckﳉ+g %8!Qfd4sRdH;Lx߹GFi+SLzLc D55%e'SD&bW'h>Rx'Ê3St6<-^[yTy%|a,=G~ xwyEqYt;G8?8 +h%W0udڟQ?8Qb%#|ǽ o Pd@}= I  }3_5lܶ|.95c_ǵk 52Q wf# \%;/2 + >|c=$R$호Kssgᕈ1lz*d + x Jr^O_m]F\swcn;P#`-SOVO|Z[EO'H\u=YNv!dis~wJ 8iY ycB-y5y'[oyΥ|o?1bex_s;hc N).׉&ZR7QH\dULI5-7y/\"]sR6NA594Q(LpzXW_Lб|-cQi㞵uQ}'s@9^-x_^ moyvݿ f1_1}?hEa玧;.M;/Ձ1f#sfg$}JdQ@iw/~wciuk:YGX?)wQɬx~Z /=~uw|iw~E ݢ':`.Ox26x~GκQZ&u2I0,d04󴒉 &K?=;pϳ?ݴL#۽a'Wݝҷߜ6(l^ x#s&.aDR[n`ӴDC?ޓ(xБ6I2lO}|[5DÒtm{`3ZBإٳ;4*S !_c:0a 'k_x$'la QS'ed-(BH]M?yfmnov|#6kRykI'Urn>nS)̥~IwֶEw`B[6OīiGۓj^pt穮NnY5hwIiPʞ9et7$[?oZޝe812Q#i3"U$Dͻ|Oo"Q@ϱX;{E] 4IOJaI=. ^;y q37.(5Ͳ:%=(O8#opI7k8x,^sנT{xDx͚gw| 4$a IDATxw%E?}:t;3wrN0 bZӮaװ]}u"A0 wxs8CU=?ܾgΝ;0o}tWWzOh"D76N&Ka)c:F aQ.&AlKi}}-Y3g36h'Lxb cB3%3 yuSƀbO |$#S ̈h`3!z4"\11#“"Jh0%00fk8"P3 !r AE' hm!" Ar$r36Fah Zs`@qD~ $̡1& ! +&dáa#6JmW MwD "|y34gŠр&2߲,BRUA0A`68U+* &D2$"Cl&`˲@( #ga@kDEb3:D00!q %+M=ڐlXfQQh+2]"UJR Ce30Z)&~ R=Y1v6c)c 9llt,1Z)V*Qy 92PX0wu!c *м+8%wABFc&Ma@RR8[_ A#E*4Ogar  e\L> J+ֵMMYh1R&?f9,ۆR NH_H2L֥0[.60ʳ#;s.=BhF +elds]s-S:~E{1LDt+w+<&.d MQ,hm೟]0䓛pgqI Ų Аq>NZ9~dg)?wГ{~/ğ^Ɔ7}O olR{mA #dYD dljh wPp.r.gsggs.x13|y0_΋f-}Xlvl-Ƭ4ٺcf&F+ͻ^^;?iZZ :u6}E1oƋF 0W j)~|_ !$@V;յ?X`  }`,fRB/w qCtNk%fiϞ>jjBS3bQ,ز 6m+ᵭ>xcWzJ-k7__p2,oG& =;2y W}KJ" )nO~*!H$ , ]B䁈P(ل{vAXtigT4Ɋ3QAaά&, "† {2 ضs}#%lt>7cOB`bΨm[OٸgW[>dhFN&Z. Q g%_ggmZqE_g3nX Px9aA~;cWMOn1BqιKB>K/?AJ+J'43Je iwTߨ o@ $LArؼ@-BBww/Z[̐R`Lւ MMT%S14T~0#6+GjaI%FcB\Sq^n"[@EL4b$0Έ8Bdގ)hnhi@O=ػwϝo<;C^t?}E&cKp98XnټF"lh٧ +$i QW%A{o5ID<[Wgx4h}`N?̌kW?V!c5ogQ^BpG݄g]IǡA% S, ~˵hj+GʫVu-|ڛbva8*OqR@R1w&u!}h0J_?(}efgm _Тw,yyu_'?&Rʈt{*-gZM;7k{;~6eѬu~(,"? P[K5@[Iul֎)ض}X 47g1sV ^u=J?3ޮ`.^҉~_kPP(d@DXe V,uN F3,Kkǟ؂|ENo(c ؋|Sxn)?!˶ -1DMX7 ϡBCSssmG#Ы4 4OcD="G NH/ (5L]]{jbSWvXh;?}7̟? ҮW?-6>bP`Iboh B\x_G.\p˱O;F61Q4\C kCTq%pۖ$ڀR% Ur]t̖]?,KB)MaW^ٍn9NYAbU=1j c@@lR Hf+Z:a]U.9P‚]ӟ>}`ꗪe`~ɭ݃eJ !r> `c*.ת x׹Kq=Ƌ<QcJ`9VTnDBDR@XҒрŀ"LF}۶8L|'Vmw<χCCꪛL8$ =]rƍBF4-Ě?lRpK}[I--9KB_q,z-#;<; +u._qݯ qY5e tLtn!qs6hoWEDkS&8$E-mrJW˒-a .=|s~P&r8j%@U `OQ` D`4ظ-Chmo_y&p]/qeco-o}2$}| VL_ڄV<[$H WK{뮗E6I+λ:0U2.FUg' -`,[r$Ɩ<xWq'T%=Gsk d2 iY nشl Ft̟cԍvbֈҡb]Xb)q'`Hoփz;N\];ᮻᤓq,̛7 coFoL{Z;;W* oC0N%A(K83`9կ W_}|?ą.BP DuǪ CG*.! aTJ>`ݣq9 pNF*ض{Y[dd.,[RZKz!XX°6 "N@E*\KՈXP"Aߺ  D`O0X"!qǟz<ɣAsKq,WX\,z1x;PCJke N8vƆ@V<8/E%J"GJ8=B\_NE틸;֛x^fFSSSNŦ'_Ƨ,ӛW_s20= ً&`HKBZlUFΜ̤&h2]Pd3!^hZ93487IP8.yhw5T;\G f/'xṭ8m xz`DlɪTPuys3AR 8%,K0GN+8LVDARړѐK)9! <𗟻{Ƥ)1wi'?0lۂm[Jy8bS01xZvb-SaY@bI ƄmvFG, J%8~{я?p]Nd1@b`B!, 1DZ02㓟7Q.V] @iEKפ%`Ydݎ# u+2LHY"bA\vb7"IxH270vBD9p){uRn9h=8 MM( !9u>n{Ƃw,^xhtaJK(}}yFDvR*c9+`Q* 1UC5C;w׿^[v8qձ8ELGF#I $a}O)aJBL\Id b5p*(ZB& Xख़1iz-Ċ_m@c!,B|L_0/4v`/q( jŬo Aiis _ApaFs[Oy_ xR'n'$* ]$[_-P*`z[@R K_]hWpZ@@² x+p5+hQ Qd09?crz (m267*{[S&X#03i-"z8"9IF 8:&n:g3a5An#&L[<fNV"th:reOCTVt(W<=@q\$.ܸp KXwhҶ m ! iJ;J2*B /+07뢥-iy'>quF%RAN~2T"@5Y$v&Ӥ$HĔ{P|k+xR-Dn[׷"#ּ%S\I|j T0C2)YgLdVJ˵d3&<7Rm-2/Wb2h89-&YA,$Et6NFeՀL&`ztR%5B(ZF(?) dBR_U*0Z# ^ _# a3+f Z Vl2CM(R^ | D|d\a“QL&hiq h D,3 ER GX@a/Vg&V 0M"r%[lX*R@V522,KYP~DQuq< \T0DCχ͠)\*Z 0FA6|_PTr)p>:e`Xh%3+K™Y̬lذ1Dgm kcB?;EsgAFس^-0!ј035H!TDQk".L8P%]bT A"oT&rbRP-QdCJlZ%`I{+$H}QW*eJ\ю)v>uIEH8tQj]UA!oIX'^2VN=o4\#" a68 gtCxra?!n̵ )Q'רY&k #JKG.Rķb$߂k&L8h"}T V54 baQ.P.\p/ohmm_bI&? 7 C% Pei.>")Pu lǝ `ZSP?)JԖU .ܶ#rNl. xb T%J<85I4a J"* * GAX{!7 vv>5gΜ/>zuppl]3$c&F7ƄLcd2¶mv]WL:lEmw25-UCr(1d10ߑJK1,D 9 t2`I?4SF;AaRJaH*(<묟5k/<̟ϛ7@<8G(Ӭ" `3Ik/Yc3fX*Ԯvnm{'^;*ďD[߇4.ܔrj)eI1ĕsn8>zԗVEdߵ=?iVKt R}qq\bao3eʔo^wu_CļjI ,qzܹlnnl6k)SP(iJuN?0Vu貯Q5Hzy}JVWz6MmJnYְmqmmۦ{… z>?x |ؓ&MZn69#2 g2@$+#@:ob\pz=ԻUUD&*i,!kɒ%z?Zv 'tkx@u֖N)%lۦL&C㌫g#!~2H'c ]VҖf"b?`NP^mJVgV ,pz衟8 oR#x.m|ɲ,ضL&˲E;Us=M&~ɴsrH)׵FW>ԂZUpj/]x꽓N>QTp4!8ꥻk׮<赶ar2¥6?=xiNMiG#IP%B8NkApHȯt$t"IΓp*="ްC_G0p<յhѢ< D\H:Z[x^P"=w&>1_JyHp; 7?N""JDrL&S< "ϽC?3ZRJT*O|:鳄x83~N鎧9?$-=$*N }%j= ԪZ2]g,6!Y(2eY1Ar۷oߖdϛ7}m!dzFX-"Ibm@k4N58AkASKzi1_ms<\.#~lB R |xCP< ]]];3k*V5i9Tobf<7o<4(= 0F U5peSI}V#$hT*TTC/ҁ{&DLBdM1 "_~}X͚5kmy a&ӔÐAHV&i/{I )Hk͈?(p-'~U%g8ZPX=8a$e&"k[߄+( !ʱxKqj̅}vv}6\" dDBsI)eCSSSsKKKkSSSsccc>,˲H,_|ԩS""uEKu\20]FI=7i{j< 1z9-j4j%ZDZ*a zgo喟03uH͝|cymMZz'laݽXDd'RAkߝj !.ٳ뮻a*h/!dkzI}iz1LJxF-lۮko$AaRB5v*ʁ DcGes/sҔO6thWܤv`q#s.E!mfad49֭{bɒ%VX1mxxX Z^KܴخÈϪAyޘ-kfMbz@Lh18 C 0D%\o(jG\ 3Z>Co_mD$bq 2a aDL>_*# lٙmKctOa.qɁ^zm 9sfȈff$6TvN8@VT*(U$ Ju$2 ǩ0RcBB)EDAfb p#܂iϞ=Xzk֬x|ˈD-@\?<3w@b]`MQO*v\HJ"R_W\qu-,JZkMƘj`) CGjh2JBHN?>s"0d"88NBD l Dt`&ZuGڶmU뮻:uj13I U 813<Þ={g}vC=tOOVA2oTT#$2dz׼s0=# B *<7*X+f8bzU.>Nvbb2 @`MZܦR RJaA\6m>o޼E ,7smmm l$)8$c?<<]vٺu;vl-J}+޲e[ly%ϷΜ9sΜ9s͜9sɓ[|>_(Fc``߹sW_}u뻆C Љ}y%Qkt"YWX'6AÈ?qRRl#NYv\s>^>p KߏSfbIDH>4Q!ʓuN ÔJun]Ϟ~ #F05q1eYmmm퓧Mjoiijs\.m[ !1AV*X, D`1&;gu,ADB0dz&5677 BmZP&"+(D{~Ii> Qί "HH צ B~Η?Z@ W$ pf`H&F?0˧^vπ GvV L ќhQ<:"e1VPMIiQb]%"BCM\/˽%`:VLXT0OL8$aXIdT$1 XQǛJD(lvi8&4pdhY۶m[{0'+z_ Ps9~(X e#Cb4`%$$)ΌWK5dca*8xC@*@XFn奵krf&ďactS+xKu~b(OdPA׺̥T'x*E̯|jp42{e 2xjj@d*̧L{Ꮬ9O/\|u@8Ih#F%8\$|tC~|̝^#@ F%IRwy<"s%W*J:ZWCgᨤ#nXyښJ٫Q;E"Jܿl.l~Ɵ*tWK==IV֊I ["A$t`>Tp`V .tw^{Uy̼%=Ȕy^J)O@0e]|>q΅ھq3ևdyuS!@!eKϧN=׈==R)YR { "p'_~{ˏ\x]ߺD!fNNo3qGM7}@8 [<ռڵ ]uͼtJZTxe9ET,o$\E5@oO jh }C(:qs^fBrBWB/P-5j0*a4No֩EV*PBifѪ>C&҆yyYuvw6:EG2S3sN?{S=&O?ƚ/kͷsbk>{7= /Wz~ Hđ$" =.]lAY؜$MI `Ӵ|gV<˒&K4̞`d,Cm @0E`Y˩Lmv씢d4;(4Ns\ QqsÁ =IDH;sL{Xyp=`z[қxw簴{N+e7lxudA ۞-֞5;8+Wc[R/!_1߷L{ʤC[2$m@z)cEضs:h޾]6v@d[(q$0`}q^|g4H͑K@oDҒ@]|ǻ0z6)V.'cv7 $/fK&r[%ݺ61$ }k ȲRMbZk$:a1xtKk@6Bk1CDF)KDS PKlV.K̚Rhh_u|a1&1 ܿ9((atrTnGe^-R6 rsRQit0 x0;vATjum23lټW^mYs)528uڲ~b>cfb ӴVCBXa"(1z4S^E$&:Mˌ1Fp!"|`a7 >ADt_k~+aN7"Č0S -ïCFUgj>bV` :Xsb{ bffP(LE (ˍqj㻺n^[҃F(UyaҤ~z4g?k B76Zgiݱ TFޝ=@iM?3f0ѐi:acK#CBte<]֙4}W7k޸<(ʗb/;C۞θ'~yuO/CI;_t@ٓfn4NenJ]%L=t;O'6hJbht)⯷w*~ߋ6Ϳ\ ؎uw@o b7l?ջ/\y:H!6w.3|% .+_?5'5O;طo_> *%T^PͿ.Ml{۳{nzۿE`\ض עl{_X_O#Xl&:6#rÇ}ԥՐ5xYe9Y-[W׿̜f! lbn~;QK [/9eӷRy<lȼMn=;c`!{6޽va^MG4yw-sVf܌a@9W,pwYNO:/#vmwg۷oJ@GdA}DK;+oFtɗ1{ˀE-$'5O9~ȇ}RXNLOKK'`|pvI-> ~mR(:X?ѽ`#Yfٹjݧ(x1vﺫ}GhVgIDATԤޕGU]Y2[2 aъu)ZVS~c+jJKԥV)VjAqb+ZDP)dL2wdtH}Lιsϣn!ѿ*,RB^wy:-QCd­bڒcScQ5:V+wm>a;wV`8c`v7f 9v?p >mbx`V;^$U˯ak# /-\ށ'LTNY2T/CFsSL͝I,*+[|eN2NOx=Ӧw(0i;(fyT@Wɫf" fLei`ǧv?JyVYL,# 2ͦX]g-c DO _y|[+xݥTc&4;"DBmwE|G˂Y]F&LÕw&, +!Ti,VCBVwYS67߹)Z {!hsa# hSq'$)i7܂νznJ"`W%Ϟ:&:-Ld45x{ᡲu_lPٜ+UDZ(#.{ΟAw^8)8%}*G2 w›x'`dd=xp|:w ˃^g1}K6/%6@xmы-ŀoJ%wyԙ3NKu-W<PSs]Ƃ_fš S4go٣אb0%wJn׮Ӧ!`Q0lou5eP%1K"@Nܯl 0,^"L+ɑBoZʍϙxiʁJ6,x0ʘXI6{ cPO`?-;wK}XiϼB%bF %'y^osvǣd8t?s$2v5'&u9Ē #@$2f%Y4S9dԐ;ILnѓv .efYX5 (с⍳g?V x]v&`+)'a1 T AO-):d-oĝwdע4,@x5Vn寰WefYcM0ÙGB%^q"023ߔl.$TOaV:l6JTU)DK#G;<"o<܃ŋmnwgʌ,XDhɎLMgā]7P[Gض\PCQ54*qs|NNh_l1ۜR0ƃgI|syʵ}_$'}}AWm^چgZͩ*-媲mE@I#{n;8JpeO,S;fCPWo9]u r:8lG9sE9evh PRaoiLt0vڗL6ʺl>+DgH3f 2|D̕MlBEٶ,)XUaac N4$q .2sXdG1]ﲤ egd.R&2yyKXq=6ynl45{G1@^]֖GLhY)@.B;tpMiC,<#B#É&0 y%e,Z :w9K[\Ջ4%Զ(lp›nu2GK TUm"?ޗz0%5ӞZ\fД N2g=. X餴 rFsfʼnLCJXW$zS˭\9<֯;'h=>[S_<PnWBm #Fx+*)=D8=x;f=ܢV~jQ Feŧk֙x~9dpf"7Ȑ!U*:}q8C2nvFQfnf;oʚ7okK.w$b_ C1.7]QҬRUTж!ÉzZ qY:C[.] ym8*G?>:siB-UesW?w/~*|@ dD7Ef}{KvNXRn,wZpɍUI eG+3>n")tnrE#1fMp 9NXXx}+9n Z€fX-Z?Kx%`p/п sdJ#ӞbGu^}3Y >Qaqó;;NZ.ikVUOS0ϹڵTq9D]1';xۗ 78P-eiZP`bp~?sqYS\h(th hSNe5(}$sGJ=ة~۶pQ.R-6t6-Z&!씝iLz| &~fkUx?=b*pRpnuj0c q|C^ h2A tW<]EJX̙dr8 DW*n@N=NPBz4吲ro.1I`mQ~9g_4XKol"[\|WAQJyr,(+@s0mksG>qJ_U?YT.>ln`(9Plqhv;7hUkX^0 jgR4w',@(4,* Fvᅑ*Mf#Ăiv&'T9֭|`c3{h#S,}/?ZB[z8+ŧd0Q!b.>WO;"ho`D92g.9R'L9d0t(C%yxxEH D,W˟ԑzIUU Y^ vzL3dfaܒ- M'h3 _NkѽN-o|E]6ժم,Z6Etվ[`6=Wg]Dff(cd ГS7t1m! ݃@L_<, GkT5Tt"*yj#P`Cx:?~ٕ zkXQ M[5{,+f\زz}E@zp{/~mԴ/̣op ǯ[owɒƲ7Im6;X ^7xp9RQFZ$:v(ZrCbx܎@طNܛ| \&~2 am XWw  Koߚ̶8dX1@08}H]\5hCH,V[4l)0j=Bo9,$Qʺ J6cMV}X̑#%*RW_K>dL"..V v0]\z_0@~p&zy&41/sLug"Zq_bEНBjm-Ҭ'C5ϘMrua8YI3Xp,}>}x /Y̮%;3YB@wADFԦ+)0T* X`vgwHgc@UG[J>_AEd2gUQjvϿ#Mw&~60IaUEeG%)}ukoY8zU;QASKXPM{:z/w:Ž0WTCQpl .n> ($%7O,XW`O0ˆv* R >2+]Vfԃ$f!X]ɼY0 PY~T6t ̵w0\-`[0)$x(Lj>0!a!*`9- ڥ h( #6Ҫ@ PUK0l}p2.!Z&4 `vղ /P?_0L$isIENDB`ukui-screensaver/src/assets/weather/9.png0000644000175000017500000004240714205074704017411 0ustar fengfengPNG  IHDR>a IDATx}yU{nmξ$d%@ j ,"!j@DQ?WTD \Y%,l&aM$!$!{f2I&gꪺGwu* I@?y[޺=uK'-w:t y:ܧ;Z~X,6zpppLoooAdRvڶݾEG.P7K^ycZ[[ܹx<>ն:"UUA/`f8!DaMeee+'M.Oyzesϝ~w}8 0 t](LDRQ$Rqi"L"qgϞyXjz/Jr}]z+GQ HEQ$(BQUUiȕ|mem82Kdߏp8xܹ??S_ gҥs|YuLuu5u]N`H^_J q`YLD*B"x@T b$R !۶˲L&L&fyy?9s<2nܸ\*?J) ,B:xEQ*%;@DB4- W 4[mۜ3,KM$sp 7Μ99p(@_N:uB(pXɓRC^?dNJd8^4-D èFii)} / 8{ڐms:VcR̙3/Wi}z7c`@B;HEQ8hrt!K x% %z~ wR~*T ? n+mmVl۶#Ho~k|q`%=s]pG~8 ɒ%P(au= Uu )\xb{RJHQŎ<\jU7$с /~U'tƌSDd4U0yu%L5o9W41mo|_!4r_VP+|5=|PHF"ǎ1cPyy9JJJk>Ih2Kx%X\\ܒu, UUU[L&?>Snjj*tV$QѨ0aO:jjj0|v͂6`,m$ v*?_:9Dкub*d}w]  !ӎ̭A3gĄ 0}M:ToN%8^} K\GHUUcڵ o8] k/HYSScgϞ"BBv(]*\!S1RI׿?(fx3*$ ;:{7pM7'S2i] țnk֬1c2ahUUU={6Z|1ܠx{x+F&  Qs(4M$ $ 7ɦi5HH!ĮH$ &{A4Lx̙_FBu+ )yoN;@Pj\x9B}T;!r^mh a&`ЎG,Zh 5?A0RH"5kY"M)//犊 P/4lDJbB:_ B> D7tXH+q)Nsw4M0555﮽ HpMvJIIIaJeee>Bӫ̜_]h!HA[%z wޫ}7-mAuL&x<ӧO455]`{?Fֆ@p&Lpr(b08 ?]{_(S_R 1X0Tsn(p 1{q|Lu45MAmʔ)_;p Gj#rKD0`0H`SDL&PpW xsMH@ʄ wAP`:)BWO]˗~Ǯ~f 0*r r2fe#d ޵L(?8ƼGءBYd֔;0c…/07&!De8.uW +(ITzC{z ;.PBB!*++;J#n_(n&T '~ ) QFɠ?B!_#__E!Sn1~xs};^CBD3DD9D>?T?ý ċ_ rj +&{(oۯ i?H)ܹsN6vB^ΒRu}o '4#Ux à`0Ȇa 'F  ˲2Db`bk$Q,f罡{xҬTl!7KjoQOEJs̙MDcBgf+`ffOF1D)cL3Эbu&koZ$|?R ϐ]ܝS5M#EQdyyzG<[TN{{{s|?0Jg IWܕ~cޔB`*Lw1c8RHƽwcB3f8vECE9 dcPa4)#q.c >x&2?hz1л,wU 7YrC=o:guudpװ]۷oё0rd(8t{|y%͇{ވĭ @ ~u.<`pK{w{8M-s(  !@80jvht}ݺuN:+Ns&dr?/_bύs{3~~o5 atzAWC1ί_76[~8JDB@ I) 370,H:,]tI'4[QR)1p~3y$ӷbv/xտƽns#yɯ~tJo.x@DHӶeY0~Gчdf$Ҳrʕ-vڸx<.5MS܉ w_RȆ*߿|ʫOx̀ W;F&($oQt|@~[_`Q鞃 'smB  !"yK'x3g֨Q*Sl6y#?p7vrWBݔB. igRJff @*;#0U!@tpp;NW͜9sp6޻^߯Cx3;Co!3ŀ0_P1Htd2駟^(2! EUU]J# B۶mk'MTm#$ 9a~{Ur@{se_,;XPŜb BTDnm&'Id2<-YSȚ  Bumu}U㐓{ M {5ޛA %J03^Mq~[w!s)AsP*b)%曻zd̬bKu ڵkиq4Mt:-s@Ӕ,;wHp/d 9{nRt/6xf|߿2(_~2X KMT*ED±,K{lmm}!盥9 S͑dBaf PjyݺuvQ]VVVJDtwt7\N^{n\pKw5Lkjo$L/d .XJ(K)%^:`?:Gvk *34"V1@v vX⭦^qB`LuADd۶ -oT*ũTs %r_OgB/=Z6z+^5^H\1MP(kvw:2N+7|#۷o9WER̜8Y!\}\%ҳ"2{UZbXoo4MSRRJ@8#BJ)Tro!q٨0KM$yg8 }? SCB .)'IpH}G>!%$ɜxGy|d) E>gy(7JA~}l2ؚ(0 c?(vt:-۶(98g#7.3ӎ;'|_sD6`QYSp>|pirb {g*K8IL48F@%<  D"ywry͟:uj]<w>:ĒeY3il~'W\xUOv5eYLDut]wHL&Wxob&46Mr;8)֭K=ËG]}O3fLeII0 zgNcsٲe.\k+0ö FpAb\9Bv 2r( -U2=HI vlfx{N:kܹx<.sj{@d?YU):Eim)%ɤ4 tQArw5jO;7qrKy뮇bX ' UVVՍS[[[UUUUDBa( ۶t:m unٲe˖-MTȩdH߅:P_,kgLI ڶHZ))t\7ȢU@p Rve}f|kq̢Eڴi;qdn4McLL~m ft:[`}}}!Y`0}]m' fV'xŋ/!RzOOO[OOOڵk]k9va۶d,pvm]bD[Q&&c%c >d'c(̺{x1B*u3NnmnWWt;vl{ƍ7c3cƌIUUU7c"bw-Bl6s.=-r͛[+ڶ(O8q3fN8qbuuuPQ IDAT|h&kƊ=ʁP&Ν;%K{^mIc$ND"Ϝi4S9ƹ" `)&^:1 IDif ,x`]ʌA5"@`sϭʹ q2kSQ@*''Wl(,e. Z[[7n|'M402 9\Gp? "6LD$d:UAZֺkP090>0"9";#(ѱc bo3C>S# +*d*+l" d7Lv[Ej9U-,@;gGsP62vVc { ,]B@RfsgJ"5?~¸#mXWgL.E($`aR`hYM` gF@9ӣ8W:c(DnD*8 c'6T[31&WNn PlR/_>,xs9wh2<Lү|K|wwdPOq̰8>ĒW7(\̤(88qX V%$MؽԻ;HsǞ.>q[d&~ t7O{4@)& ;|}\|' -zcأI:sH-Ci"?[y¼芺5lYpJl?N?I$j9z;أDnF66/bXr{ߥjՌzd*H):s.F&;(&X` \Wz}) 4dy/.=@u֧S>l6sϜZNl](.|;>5MIbJKmPRq Et$級(.>{?~.O>! #3B 3qkonq/"xÏ#FN m׶k8{*zTPou!(pGb+P`s?PTZ=8 )G}𶯟zvǐ p|v]:n 參ؓ(=sG_.gh`٤ƒmcB#r$̪y~1ںS96R U.6r{]3tz+W^ h3O|Z_[sKXW]{ͧv̚T3V5~}=XY; dymA@vr?(hZIYM@Ow$^c~}G.TN"@t|T{a49? 58U 鰮2^kyS%5fG>VZ!-pxzY(A@[p+(~櫳m^rقNz[D M J)3&ҹRғǧbGN BSMR4 B 3E6qcϼoۦ#HD= ׊h!Q:}izGlUT#DzzdMZ:w=:YƴYj֬(Lc@0b"1c; "XX H@gOTUHUN{_iR .D0^/9,@qY#ޗ}ؓ2uC'4f"˲h,Au~ﻻniݹzs}s7{_7/ VZum#]pha2VUY/dP2t4$'0|_sNK,P6ܷsPx~`ȩa`ӟn|oh]/E"8Rm ^ﯼC AE6rѺP'?QѮNz[]pl٘1,^nI4fޝҼlg7Y]}t %V;R@3n֏L "}ӟ{߿)QV?g2)@HV!Abz캷omo|vNEݻb~M9}w|j>3BQ@=޻PH.X_?MaO3t5/ٱ酟?$8>Ұ׽ؼqn)@ܑvZׁ?ɍ5\^ .pJeVu7>V颴4=00SWhPZ;wo75UUF[ӎ\{Y%GmbUWoilрa&Du7ۺtB ͝B H 4X+>Qר=Բn}ؼ8H']䍆Q?G(R`!Lojk[sK]A36QnTT0H X[1фFzHKj> B ۷Du}{#iU⦔4jCdD֚ aN7SI*egW/unߏl {( LyNE iF*竟NoR<{ *2S핗}_h+?ģ>"ZG3$BLv~ƍo~(M(uZ}耝@f[UiegS(J4bV;쿇R^+hocI@`/rq&ۯȕW^d#%'?\Pz,>Â"ȱEmA? Cݨiz<2iiVSfbhjXˬ@(lms׌o]ů>#|︡wvӎ^Z>wpx.Y>±Ǔ Vѱ{{0wMRMMnغך݀wA'F^)-5?#ii!q QdgFBE ~خ1=wgGUW49KoLzPK&3T(c.M$6= ^?>ycֺ?zkȲg=?fr&xB*`4?TO^kq;wCbW:Vu+)ph/s19 hPI=l-o%O8cȑ7\"g2rÿ^?%Os}ղ?yw>9$Xtd'TX!SAЀDƮrCօ/xAE DTs"6 wJA _} k@I`2 L$2!*Ջ];;W>XO=ͦueuεv7ߺP~ /ٞ/f¨Ddڋ30uH`j'_=s>N@$KQZz{\0ȶ~;AY '.cUTVK.*HSwVC+^z_tSǦ$3'ZOB=6U%^|"tC~1k3({P T?$1i-M2Oq̙pv,:fkFyWF;/۹su,k&;l[Bl{}k;ڏOGJkh2G)K.< OaHpjmggc$]h=c -rO :2>賩fV Uyr[G7+HHr þc+yS;WS5Oo~闏v3\AYʶz ,tX|:m'H0D N0R~r-!F?-MbRh*Y&t$;9zW@M͸[nfJi`zpqnU-3A7%!ڱG2]K٬aM5=`258}DB׎ Gu)@aMUWˣ¥cHAM(,.]4vk #AQEKnh^Q +zI(n{͊ 3jQg5♃N#zP"kV=~Zuk-ĆW:*YiGR2Gj U]uu_T`ڴqt J'Ŏ;;7{ qdæQ?Yi5k$WS?;bcAvB.V/z_ċQXP:;YSIG&c[֪5zkS'3'%Y1Eytj?LW#B$ym>cSV˪ s9}$OoR!3 ׬yh<ٯ~oHG yy@-~nK'7!yW@ycՏ^ :~oM-׸!;]N32^)5>t&@7J2Olxe`0 t%6t:,FWL:vŚ=cMиDоfT`Y2el sTJ+k@Q͢v_K7%n!TSSӆ <5Ԁ+̆c*C id*/ .iu 0vxM"ql[ؖI}[YYؿ1hq`aQe OޔMK@h;SNƄ|E(yXoXrRQ.RMu>o|>;Mp'rZ>!tfׯ=; 4DsGAQ<U:̶ ) Od^ʖHʹ1\-2=eq"̵X |9$M±%[CA{EP@Cg*kmYZ\9vD5 )E $VL7:^C.jE|GƳϖG?~SPUDH oہɃ]=̻͡ b<01:4o͒%6jhA!Q]k~M'W*z~[<^}/;;(PrE(ul0kkS糟Oj߿5OMWep 1~tX']R׶mc6cIDATP^VΔ#+Y/ǞU [xm|>A:yoϬ||U6em" Z ]*|зw_r1`ח[nSw~~Y1SA?J<:(yOW,:Sϖ6[TV֮y#%a[S-?|%l l".- Ni,@Ҕw\l ~nz5Cҭ~qU"шGºQ]ܿ3[cP@>}d>*{3` ]Q@XqGo4ZnleSV/emǽuU›#?̢%MW +h۶c'$/e Lw̘;WWVySPy]3S7mT Ap.8>3|n3{]][G:Bb4.8әyTPO`e:] O^BvS @g!ݵݤC@.YçO0EAVB6K+6SD)^H{CQrGoY%(Dd@Hݒ*@L),F3dspj`WLU3r ňЗBkVެRNY5@sޝ?@dS;^[vh<d;0Vzc)HYN;V\__x#UX]c<ѡ@vsU?\Y]4i86yl;?ZhKXhJ (l7 gOᅤ*$.׋µF^sǬ PDw"t^UPB[P#3ϥŻ*z#}PyCėRUs{UAr7y `.ȏ?(Jt̬#a'whhxQ_| ,dA@P5@j#z4^q~1&1BT(M}\=/ QjpHLeJ׃K'<B9׮IENDB`ukui-screensaver/src/assets/weather/icon.htm0000644000175000017500000000145314205074704020171 0ustar fengfeng
文件名网络图标本地图标
ukui-screensaver/src/assets/weather/21.png0000644000175000017500000004626514205074704017471 0ustar fengfengPNG  IHDR>a IDATxYmQ.Zcιo%BwCHA4:59:rBB OHHvPb8 i\ 8Aذ9FU݇Qs66tϐV71jԨ꫚W@/^ff`mbן79svOun|zZxM7u=qS6}GwF3C*o6 7?'F{6']{ұk;OɎ=7osۓO}xaTqO6>)L'5 IO- ؆@'뼟$z={0>!@}Co۶EUq`E8^'7ƶjfwl}㞨uw( zwDܾlʱsnV6εmgQŷټ>/431"3`۶BUDؘn((>8 bnfm*+.q-9efqķUUQDTD""RB1k=(URU`{ofs_dfEDNnH@EUDoxK_  9K53CJB&"s6еR, tsY8al1FsFFlmmeU|N}b0lgU-9""YDJ9jV\J3ÔW9ٽ~m.;ǖ6sW_LDlO3Uն-/"D/| ]a=?@oϝ;g.<<4ϱm[Woa Tccg?vgg %m_m[r 3@1k#(X=V+._=}_>w뵻5 VoKbf=<<~cm a pV:gUu=!s#sox^f~VJCx衇/~WhT23],==>я>9U"2U5D4U#, |K_?gxG~sҹs0C=Ї~GkBޗk!{g>֯ޞ mۂkMbxcSU "?o~zի^}G_6mޏ޶Ϥ3D\03 5mm`2M7d'u{"b~`6 "ZJrii>˫_93?e׽NUzo| ~'~⫾뿞Fugԙ3g$OO'𸰜Ѷ^Dd=_}.]fp);D^rDfR ٯEDWV+],: .KmF:dc lˀ˗/MUa˿KX,vgk^١oo5Uz衇S13kkpgg/??h$*03<̥vIodЯ7OYq0Q8ƛ@D;?YvyٳXJC ^335y ?4MSFї5 Y]t:E"a~GEfDV~loobQ?n3˗c o@wٳg!缾" 1Fmqmp#j|sgSl,,gJ/zы)R 6M<\@nRJxCDY.ܶҸf4h'wA0<O 4#"#"[.4 {ー\.x!@)>;No~~F"ʛƤqx;TjϚp= <YVJYE0r|B=cd]d2/nBOh;t$ ?ya\^7|7-Bo_WҦ> }c>w}^8nYYh |[oN:fl}J.\gΜY˃8<<[n0xgokh}+__7j۳ 9~730ڃ>x曾雾Ox{vΗfjj>shQtkkT?OگDz/| p%'m];f:HB0+UW;`s\p ' q3#<?#?roŢ=g6govF8F5Fhk_5|7|575 3CU??77a|cSUgYPXJrXJYڸtb46Un47vm?O|w~^h۶{3A#.8;pCUѷ}Zz#?*:YN|2Au5j{wwΜ9׳0M7ߌ+v圑ŋxy;U7bş9s#H:… 7y] GGG׾w(??Ύ}K_ځ=\Ӥ-!j"dBqT$ I<^ϴMPU888D71om"13v]?zEo[LD0!MɟI TxJ F߇Rzif裏b4l]`)9q52lm||zKō B#27b1wH)ٕ+Wg~g(?^hJ o'?ɷ~: Rz]gmj_??).] gΜU:u? /~G U â_mNjpB0hM p\pJ)OwX)ࡇ_N>*zV+TU{;ߩ뿎vmmmSETawu|͸Urt)y_?g~g^1!}B33>¯ZuwDD cT… x53888FMi>9~2;4tڸq 0U^//;ja\./׽umm: Rp{{[/ӯt:5"^*}¶/~qU)K)7oo7Ν'C9L&>w~W~êʰvNJ)_o۵m[23XV?9>s#Fɑ^9@DxJmw _p5D{0YX>Mӌ8RU+0 OL:\. sbp޽IRʕ+kv5b+8E|$](C Z]?3oRK]%t^C RmB*xM=Nk]Ϝ9祔)3_җGyޱ\s'mlI|8~WfǏn{D&)ɮ6zҬ}p>y O[+{ !bNxY8儎Xoo !bP7Q|,*Ǿ0 $|l?!i`\^NOcv\hp>/| #>O7nf?g8O>ƙs7f~_<4.OUi÷;.I6fJ)EK_5yu9$y\;^5^zI{y~G 7O??j#:3}>s ~+ȥ dBPJmFf1Ʀ{\VZ6=sQGx޶@4mڶڶn4͎N`t,V)S ""fUBDa .#⡈,EDqD#!1SRRTuYA\a򖷌fx^`po{{;&<%61Ʃ&!z[f63DD@ϙD#C}ӈؖRRa4bfkٺk(jm:^VE)Ec˜sC4[RrOHI?kSJ[؆ҔP])$f "jp;s\+pT55qjknRj9!bRRJNwSI)eKUTJnv>03|kiBhC-3oQ4͞P>l ÀRRJRNdUxof[ccSBdf+D,)s"Q4f53M)%fRJj.R? !лn;NўO@ڶmC[f037MZDlTuw(4fmf' RU !rST3[lmmM1wC f֖RZX{?o49DEe "LDxww9eoXR1C[Xf6q$Ш23}#f3f:{^!]\+R̼KD!ڶ=Bgn4 @:%"-[DtO6vc[1ƛDdO1YD!lgQzz9h H)il:5!VU;" 9g"c(Z1@fDԨꑗ›!"*q0 їvgff D" N> xR Tly+3mv}",$}w=ycb] L[t)OӦmqfRʖ'8A+WL}faТ]8kC4)%܀+#: Dg!yV5s Sf.0y{[ׂF'q5ûc,^A D4U՞Tu`f %dVP40 ɘ%݊Ȁ7R$01þTD̂i"0`4b+E{0 YUEUo}&csڞk$p3 ={v6NO1&3aU望lv(8$\QTuBR!̡ڤHD3pv"ts{yf67˪]!̎<qq!" "RU~P< 5#FxhOm!3l6fnJtaܸ:]qbf{jw"FI=:Y:KXk5n42s4RJ3K)&IPg8"zU=rySEU{ d#z23gD<D"x4sDasGj__HϺ<0*fMJ!4TUySJ)x''6MӦ({Xw&̼ahU9w}߷031ڶ`i[̸9ga-"/2pЦ@לsdAg "H#ۥRgf="f9AfvBXF䒈\AD0 b8ry}1;5Eg=0Z}oL&d2b!-Umi9Z3.TxKD3[g0Q՛ͬ+suz,5 b !w D wK=Rzշf]{D"tQaH-%|v IDATeZQ9HUq"Z0 ͌s*"}y_U/~)@DŢ!l1')My̶hMH]"WS'ةjSJD V4 Cdf"DTQU5jB0 i "Di:p(WDXWYyu[U3q*ضgdLFUPu@^[‡u-C 37!Bą ÖWEi=8xĪDĆNيkBD}JIEdW f)1,ݻ3uC]!3clB½JJM~|o٤߰qliӘY}CD3"9' ?LB_8rFeB}9X""bjcftK+z聜;u׋Atk[{gPDB9RXO!QblfKHB-;J)+f"A\@(1(";Bi3H1~%ϧ-oPuij&~䃗d!ô8up!3QιGYN)%fJ)YNDSG8"">KF c.@}cyAK)˔""pdf~5s{.]u$rxÞ!b˵M9_rAi-r"rj%Mؽ;,\J;cN  u]3DnfS1=3;B t)+Tb ޅq4@po`u]DW[2ƘawC$VBhp0 ӷIQUwlWnu> a%0 ,%!eTuNDi ւg.󜳨ꬔ᱔RgfR.13.˹)yja4,}0J)jʪZ18A J%h}V\9ZI< #mf6GDqaM4x>_K3"3_H)5,"#SJI("n0#- XqSJ೻)4f̬&$ *Dl9?#bQ'"-Շ_*S9 `fPԣu9khifCw=Hq| R8n)egA< p M2amFd2z(hc-aXu]xw{ {ZeV43f\fq^7313o}  !H4l*OTuԧp,9Vv *—},V+3K)GfB6V.uT_bFf$X[(̡jp%3RJBij6Z.pSQK-D X.C%?츍RTԸ2d[J9p-glf{'v] N)tTMqvciIa1LJu">c\Ddz|;rB| 3ߒs^B}*$3XUvG5 >bǰr)e|43"3DJkL=@`[a )Gf̬.HbfADlkA!Rʾ(%(Rj 0,rWqsZe_JɈ\'ڶm Mڶ3KmM!4s.E""Da8e3G:Yd=78jf)K)!Ti#sgZ4E{ttxawYJ)R<){tQ L23a7&`v`Z ̄*m}je9PM90EgO`),i@jÝw޹fݨlBocf̼e6BS[+''DE$%816"r4McDDR!$ͅOYUID&hf%:԰,"R)eRJo1Άa8p߾sm=l u}.AfxY*qbP9S|_[)d_J)Ed7M"NcJ$;CPŅ;QƐu{キmvB谲ivKstvP ѲiN1Ƹ +Dtc !lDR}̝̍50i-M0"6k!DD;zU"%"Ú7`;SGn|QU[U%ѿNĊQ?l( ~΅[SJ{c#}cTD\&5EUţ7>Jl7 {d2I!RHWJ;Ǖ3R,@E4MyRjb_u޵3'UrKD!r4 np#p "]"Zt"~= a T>6K3v/~lce,C-B"pFݴX'֨咈BE]DDV7k45M.!عfnM\H|$ pcKZׇ?cl]MOBSDt jPdBi̍R9q% T?5̼jsB@'"=ֈb? PJ9dt:=B,"U5SKZҵ.$"RZ-j*'Tf>ڻskgybB!d;sQ ZefF5 Ts'5EUtZ\w P|o=w} X1I#v9g !3gx<жm:mi)3c}4VT)e5 0L&q_QmjB1r+|xSYOW|F*AE M3)9 7hf;R ^$qHV:^OcC`$PF1N1z 8cUwAb[,~>RՐs^AzmPꞙBIU۾R+H)enfW s΍P{ !HQUay -3UuQ3f朏fVjZBUuR9L&#U"µ*W9)V;Hy*XWu܆fNܨ{$xf4HP0T%U~!V+9)̬rlc\j%l:wZ~FJXq,#lf 1FJ)vtl}Z),hOUiZ@]wNs[3;(ZAjZ΍.!8{9TsqꚆl)e0"B,"hkf 03Y‘Unzv \RMi3b23r߯gG7+0` =6s4 I%Mk(yY,\0-Lp۶ 9ƘRJLDּ("invIO̼I<]uDɜƝs.IZ6 6qc {Q>+YjpttEj J(ZYADDqju~~v$?߬ҋt\.RJ3(M43fRY@\JrΧDdUBFUڍPaRW2geC3[@qf0~71ٮ3YΙR GZ9 E9/b}+1%QRczT8gRҦi &!h^`IQ@DcN`C\ %pD4Ra+|Uh F3A<Bj5Yp4RɈmvX̪ YU}AJ]Wz5@E u9DUeoHA+V} WT`D-~[RSe{D< 5RMPVr(+-(򣙍ݝpkp;'P%0 5B&"bf6+fALJD튈jdT0T/f=%"s'Ṫx%p )jDt1p8 z6 &|M&Ib-iyLlDZBZmODLkvD!ъDξ2g0rc.2Pj:\y5 C X1暥UUoTg/XJ}<> #{fvsפUAM/fjA[+)l^>TO_RʑV;ON\F Ʒ29`ٖsRc~F+勪= .V4,Zû"NTuj5GJ):ɭm t0,RJ])eY#mǵًˎ5>s+@& XYc %@3^8tuCw!!LD17\DzR@7Bmr5QU-\v-ZYPsGcEdpf tqy`B4-"j`Mgf[>gB1܏<~*׸uj%\diᦪ ETI#C)%vK)byRy<HZa-Y̪Ji6BF^;F*l>Sr/J2aɣ+9|7C/r69N&AjQ%R(Rv"l;<[]Mk1}h4Vs,u=k>4ZgL EDE$ReLK)LDaVC>H y5ָ@fE`&eJsTc c/Z Y?ڸ\%U6FA+cfqY->+@j2mR\R %>Xl' e5e\EGyay̮hE,祔]-2qs/ᮻ "0LTM)u9=%Bݤj)̼_Z)TG;.*+GEݢ5k!UgǕч -r2RՀ5`2@5@{qRV2g'_ khwn %!bQ2xfol偧c pW/5m#pjk1ƜcnEfRJdRkd}s̆mef/Y-VۮfT뷠>3G!yӣg0VpjנrgЫ꿵mbeݎQ f6Պa ;`/ѣVZuȵ<ظ0#3@-a#T;Êѣ,$q#bI4!")G0:,UEnSJ "o)%4D4n}G9U)eUJ<;h]cV]&<8LNwm;r5"/U=C = _DIԏ7Xky[D!NR]etDSL232ĉ5z﹔qQD Tj{W^ICbz1XY23Bs=ѿ k|O@n|8眢ұep}E&`4zJ<-MgWS>"¿{׳|{9pE"ٰ:"RzR+9d M,)5Tr.gxLs5QL))^Z4mJ){;?MV} Î}FjٝFzn! ɸFvSC8U}B -"̳ZAf¢2-!*,HS+㻡xT}x{;'5殔~9Zf~u&s9콟3T6[׵jN)ɺھTyyf5>} Lݺxw"e#ͣg8X-+Tm/+ōل֚~5gf! dIDAT2fU5Zo09##wQorHц[ffgh"+])]snBw]bV"2t8l\Jids>6S7[((윣Rvc)*"֚DJzE1EMOD} bqj&3ߔRNn`H Y9[,d1!afqqոN J"2;vĆAsܭ61sEy]~vΝ꭭"m8 >ιmQHөSJ)RV5U ` EClR5"}v`ϊO?nG x%P`g833)%P}Q&fΈ'pRMoר90H7^dAb~^ ovb:Mp΅s/M1"-`f7MS8""1 ^BD6]7;^x7T~Z[K)71ƛRZ0Oߨ[>t""[(W=Y9j O@D_Tv@G'zRbt,yJsC!I(ʭ-$WG7㼍[uTݦ ȸ{`۟|+*3S!2 D)Ã7:;>F=N"4Mc,jXWTk=j9{g~ƒ4M1|.vni R$zԆ>>ᅲF4U;#T 0MS,<,@wj"N4ޏZinj30'6ꜻELqGg4LD⍱k~1N""K7u@1 dYpM#}_?L4{@+׏XEzaѱF*y km5aG\#.Y7Sxn7Kx[Wѱ)9cƕW2rS+=3cj)L'Vd(%DƝC8!`aAy4ly/DtnyU]j33kkS5ElPu[k"r+ZZ Z+Rb#jF ^J`3=7C,r<nZ ^ٷ [5KBkZ2gBxZ;7[W64a;2b@o;sQCA6:mDg#6@봙F@UU/XVغhƬ75sx1λaXM!AZ:D9\ZkSyJD+`Kq|Bׯ]{w  ٘< iιsgIYMh d|C3q6C%zxĬl%|P+)?gSĘI<)ZUo{l,Fجd\tz3֌E+{ C Sl z`8r|\k4X 4fRk= 喴IGl@%(c )KtOGP݈;2EeݑQMj!U_ G83sW+SV2ncڱcCG(vl:A RMYԱ.bZ}?Vrpʶ'2sxCDV95(9=c7fbljìN#cFZ5Ͻ=31?y=l[g x<V%YQ(Tݼ'륟izjxݝpH6_{Ϫo(|TULb7Dl(!!ADi:*RD< YDe@ZJWU=W u'[p9v HTS*]ٙp8eބ ι4؛ cM1FKn=!d/Ԝ %.$l`֎DTZkC3wbQ7]{pGjWsoY 9":kFHK"ժ,Zk m̟r0O٥FD̝I"59c!Ľ&뺶/rחZ|o7~k޼y3[qv"=k $\NüMyA`Srx#*"9_our~,;3sy"yVR먻֚RW_})Xod~OBȿyf}aoݖ#. 8ض1{"*d@8^ D5K||,#8rVwDLBEZ}l?ODl(@D~;˒}<>.3m=s!Ӎ-q$ miѶ ](_^Ϳmi`kŹ\˿3^Wծv]jWծv]jWծv]jWծv]jWծvߙ}M2lSIENDB`ukui-screensaver/src/assets/weather/6.png0000644000175000017500000004431714205074704017410 0ustar fengfengPNG  IHDR>a IDATx}w|Uoz3PB &,XaGwUY +Ql A]AB( &77O9?L2 7P}39sSspm`P`І@:H8U}o=p@LnkkKmnnyނ,l6[eRRRe^t~+p<#nznEEńn{()# R~2c 1HJd2FGGԯ_ﳲ67jڦ@h_Zf֭z9uuu$IJX,lX,08BdJi8@dY$IB $IF 6i5J=bŊ[ eyhDD"##a6edB8ra0!U((B$&t6墋.^y ZH;vf͚ pnBBl6l4ebn#**l6f<e$A|>x<vz((rц_W^yczrD~ lɒ%O۷﯉$::Z4Lh4RшH$&&8X,pncj?k_EQD dN Ȣ(JƍAh^{d, g4YTTHBBL&S;CC%=WUH xv eMMMhkk 28< M7B``Za0ځj@ @ 퉢AxJiCffG\p?˔.L/ 2o޼ZfRRRy z-Z[[҂`0χ`0Ic`hO"l6$$$ ** Ұdjj ni!~?t:\ً\d)Pr߾}o뮻F1::!Cdc,_kү2paD1<ǃJڪo&  R048(@NKKc%%%>9 _qȐ!3v;5 `࣢`4}z+Ҫ`0xo$W9EJJJGGe8 b2Hss3N'R͒MMM^{/0`@~cpiiiygEDD'0>wlT2@FUHNNnoWe>\?6_k mq !D-QJrBSS%KfRJJJ#~C % [ִ,8Fb2 IH$Qeh!ݷ8VIIIQs ڄ:sp`SEatt40X!Cllp8.\$~#ݟrR`љv=1&3ƈpZ3&}mxg4a6aX`6a6.ZUf|>qQn8P!8'n3l ,Xt8: ><Ƙ$ jSkUuUUuj5cEtR9FІH}kYaXI+&I!111xСV^K/@R>QQѿ4pZt Xiii4Z[[v}a$d2lg,j;ls?@i5>d Ý/jUBDI֢RәuƵD)N񉉉AbEvv6CL& k391CPX-cgJ~w G KTGȲ,B81p"S@~Vx<lJHH`#F@bb"!ⅳ@xZU*H3={}'LmQB"%z̙Q#S2'[@o{=555h2 1b!EY[Z`DW8~A_x<x<5QY=L))))[~;С~d@{6Z,IGu ^8kc.HN#׆zng@IOߞfA@jJ `@8TYT / ##C]eO\p3f\F)v;?h ַo_һjz چ-=lbO%dGimѪ(LU&IS󑖖>}y7.Ϥ z %''wZVfYglYvOͶO\mH9YOSūZӦAA h;lhh-4iҽ&L؂A4L{#""hV+mމSH1q ԇU*iΜ[8U*T|C}ģwEh h42"7n;w8M2!$i3ia@XO?+k׿gkU&j+:'k?P*iE=4#L Al?0oz4hРɑ1FQ4L\\\\{Wc A vUҪWО@EL&90˻n6x`iiS˗/Ν,B/[z @ӧ$L&X,D'eWއK#p5zu!tu+pu1tx$II2H 3 0`̙VJbaݙ'  0ߕ՝kzS,2!]U)W'1J)imm,gϞ;"d;d2Ĥ( 1Duʘ pko'Y`FYĞ0TE=`jg'$3.K߿iÆ (J)lQj5Zo٠Rn_WGg3*\gOU:tqпH;jʬV+)DGG~7nEH{\o؝xƘy 'I^B:SQFɠq2p!^#I^g9pxeڻwoyݺuXa;pcH! "ZhW霌%Upp!>ݩꮜp߅Xzܕk_[ iudYǏ6hРk{nO"kf! (`T'n6\;Z~I7 {kOU~gy o]?&X,f2`ؤI)/8ƘIi;X3U(@vf絡zhåYO/)ܹ̋,i-vu F8(,lԨQ#!Y2(RjdG`c)pLnX;* TW 6zvg} pe©ΐ0.Ωp'Æ v{AH555,3 j>_OztRYpd*W_[r?9@xӷѝf 'zM޻1gRF6dȐqU@4W^^~ζZD$f;ATƄ3|@82^;Me~дv@?LINW{Ѓ@-ҟו^G:kBBB&zX-X.Mǎ;X__5)E l68tIJ2P=v&ձZxAOz8|i4]i(XPJ lvVwc ~~ =./wڰF:s{3~zoY5éatjAW]1ί+mL*!0`Zf}fn[BdҎ;6N8qq|La>lЙ=SN2u@7|P'Y9-5Up@Л.S;Y} P.w1&+DO?O:5vS'&=~K8׫|}V_mKњ5T@= Eڋ]v1]s0p^ZF~t @"H,[YYg H˱H\g^YGm@נv)kN+虧X8NhCIfɲcp93JDyJ1f`㳳H!BQ.~xmnT^7п3J;]o83; \?cH~ w}b q,~tQ(8獲,b=zhlׯ_B dY&׽sתx=ՁµveYv0:s;cLG>az ᠟}ٿC>!!d3ke2 ƌ޽{'U$Iy~,$Lga^g 2E+ZkpfP]I?L dzgն]kFiPe,$77o}@R8]1ƣ!FtLv[322z ee:M Avnu~ p6?Õkz3 zB~8K7ciȨoW-# }Gk***~P|3c 5{-R1hՙL(BQ:&x.~R7d^ AO>P5]'LgÅ*u^gmj #n[e/_$InB۠*BNn޽͒$Y-Kh" 73|>SJD} ;xԳ^1^{赐6lJVjN8te8BSz!U|"yx)^ER@%@) HC0(JyJ1G(ߵkq\DTTTtLLLlttttDDf6b4;;{@rrBL&e^}\:(Z:@?iméfVwfז5Wc)%.Kرõ| ! lD"cLD7!=- %I "UR5,lEI`"T IR[UU5sܹA%I Duy8^|,wܽ3k}>Cvyz @*^p>NqB$+ ?1`0PAv}ŋjii >裋r1N90Q#PrӄO?eYÆ Ku\vSWzjն^JPv1W9ۺ.s3/L"x\UОG`j@@fI 6-^x.#PEr$u%("M|7O~G}v;Vq"iHc*xwҪU>W^mmmcSSuԴ*zf^ekd2PG2L.(D( dL9P@7e*\5k|U_/B @ *<'E zꩿ|[&L0e̙+++222$IKKKK5GP9g v }㣂Ka. N*N֮W'xvWzg (1=aAoYCD9㊊|K,YWRRD)pG9|"J2Xu8x^RZZ9dɒU[o,ڠKۢAQ)S<3cAem& {-E1z;QBM>R#!x{8ĉg?~ݫ, *AdVk¦I,Ze:qTal0<ViU:O0W#+۷oYlN\_k\\\bJJJrzzzjRRR||||nL&`0PQ%/*++JJJKJJJ}>_(ZB+f-Z(.Y=i"""*999Uyyc}POU<eB,IRpƍ_>|x &geey^}L43 % 1S&"~(R8rHbBvۓYZ}B8Q~*++ŜmABHp8*Gyaa!1RJ;EQ BB̌1QaW@BZ '˲mM? hѢuuu7pjjj}ZDDD\FFF"T jݻw>uJ)NUA*̷)bFhMB"##7zaX-QrRQQQUZZZR^^~8fիO>}+5)))&::hM~0Dsss~߾}wܙ+I# +b5V[M Y9~tH!)yszLd``=}|p޽{l_4J ˲ y@e|$BE1ZdYVG|d\\\BBBBR\\\|LLLf[V`(Te9 >/v]1DNI@(<5!) *Vkdtttn`$It\ކ٢0 0jԨc(Y8Q9TFkCب4(ޢPH!MZ"##333ssscD(zz(CtU  MPI ME\<^om‰O 233SJKK[^|̙3䥗^ZbŊ5RNB!@i2=9B[0ƘS:@|Ir>X/YoEQ4,[B\ZCZ C ٳg;p@REEE={oY)@Ѵ 1jI[2OFh$͡OdM|w///ov\5k>|x} :vPwRCSaP:u̘1+++KË{ !~1mܯ`+*((8RE|ydYVmRWQ,˵C???߿cee3\lommm۾}>Q= Z8gѡT5$)~Ƙj3U RUnU39lذo>l6ƌ;22:v቉%%% x5@0ZéwO[wf͚/wBԾm@?'rFBR1V.r5fJiO{a+]9LNX,UM'!oYs(ΖKmR}v^G|$I|,h=hIQ?2eʔ>_1~1PBMak `\vo /pGlli^ ǎ FEEK/tܲe}ǙdYv̞=cǎTرsQݻ `0::k;IuJ'DF:O ]L&Ҵ45Y7nX @7oc(tʔ)7y<BDw4=SsW>O>Ye˖1ҥKL6mop9kw;vҲe˞{W{'GDD"%&&Z֬Y{뭷^M) ʲDH#S+|0hРni 4Nur3tA Бog}٥[o{уʡw}ESL9yrM.uUW]֫Bd2M6d2c-o}ܹ -JKK3SJZX}U6c_WvvvRSStm6KKK:묳.y[e OUSô[瑟D rrr>޼y /𢌌߿9駟~n|ѣGq!kF|Wm6y{?cmۊsss/\c=6t2q 8SBY9J˗/po_ g͚5xƍMgO:'0={4l6KbbK.O kkk[SSSc?IyZ9w\U\\|~9..zSknnڵkbG8ŋ;Nlsrr>C(1"h5gس>QMJJI&\r%/]GyII .+E\/!Tp P&&2ݵkׁ{>(^z_~&zO@~衇r_~}5LKIIv\R^,|~~~7x5\3~+JOetZp81NrXDffUUU)_',0~Ag(5p; 6|=/qV׻7mT߿/rߦTYh5V jjj?)y嗏7n… ϯz7bOũ۷o8pׯ_?Oiǧ:sDQc>wqqq޽{+8#GTSJ`/{W̚5krddɵzjСC}F`P>}z5QK,K.sNA3G8 FBH5qU%Ij$BFWcc' iWA!r˒º]v-8NjhhCH;i3N싾555l׮]-۷oo޷o_ۆ +_`[} BRn0  pJ xsE[*Q?|[]]jժJŋo۹sg cy^6iҤFs=:0O>Wggg_5!d a;mrxJi&\OJYYxȑ?en9묳b{ط.T@ 4hҥKW}WE0x*rrW]]{r8 3~!:kgFʲ압$O@.@ИDAx*;3##'qe[e<,bz ZV. ~YoCCC岲ԗM#^}eY"}J;TT B(0,Vꪫw K\ti#L0To0< ITk׮u?s@3f~ "pj+zh3лwosnnnjxڵӯVTT(immmZ dtw]gQ52"RBfz7uҫ9sʔ>D9j2bJPi6R1&\`2| 5 L0s/N|xՔ)Sƍ;ꝙ޽{r p8ލn;Aj1$Ct-6Z'D14 ۶m+N`0vu,22>lذ>e@_|6mZ &j㴊rS Ԅi&ʻRSuuu+c~ҤIont?~Q޽clgϞ=k h0|}y7>ON𿋂`tii 7o8v옷>ۑ:^t\rIIIu ~ecǎO|\WW4s\ Ͽvǎ?m}aaawy^^1&~}>RVQe>r<'#d6k+tMkغuk={~UUU瓷o^i6ر TVVJo֝J[@8s#GSMMM}ݷGY]VV$y<k׮F1rss[bccgϞ7OZc?IIIWD) e8 v͛&2)uuu޽{>ϯݸqcWjWDX:th;|i?-PyJ!ıc|1v=|ۿ;X]XXXWW'1؆ z뭝^0XSB(YҼ=3@SN뮻?|7z  F d2x0Ƹ>;>==3 P2t۶m{O?o輚'$0s7bЫaÆ]}ߴiӣ Gm{&XbayyywIJJˆ#21555.e pp@h)--]vmُ?XlٲbQQZjkk}>vZ[[jѣ:?-ZYiѣGg+ܻwouNN|+/++{cLII믯Rg1wߕ^q|>Y}/˲OЧO瞜`0Ȗ,YjUq83&@w޽yذa9r㑇I!>vȲL!Le477GLDDDDUUU-rqQVVfڹsjnnnwCCgm۶_}>?%{2?ٶf͚]v?CڵGvfAꫯ8rȔ2 7kSr䧟~zzNNζmE#gtLp8W\[oMYcSS?**va0o01d̘1^~/Gw*u9+6qľ{e2"9={ >IÇOK(,,,(+++ideYf<(S,!ӟth4_ȲeݺueW_}_rss W\J>׷\r%C¦+.B?HEhkiӦYeOYb>+? d4!T4U: !әJ9l^7:ӧr8XMR&N8h…ʲH+"tUSMAu˼^V(IVu={RnWM6m@`8.QXJizb3ka";aHV*ɬ<#<€(9IGhV>}OJ(!?} $7lӷPJގeZΝ;~sKqF*Iq%Apczm8(:( !Y Ji q&)V9=I (ĂtҤI;w+++snV[[ˊ};w,ٿJ{iMBk&BG1ov~L5y͵1óV}K$jkk!`0SKį'|FB`2]{Odqfff\^^^sLLnSj8p3f\VQQ#BɣNw=o6G9BI:uSIIIźu3#G8_tE322~4dȐȆ^W.HJJ^zHv Hxw[aÆM2dHVdddF[[g̙=:#77ͱcǎ[nM,..ފO֯_SVVݽ{wb\vmh4/eK|W*I6wC1(--=xiii ֭;}CK.]$]d07mڴ}ĉ._|OQQQՈ#R>m|Lrrr֢cNpd ,XVO>?Su߾}SRRGn*..މoq\A$`~ta IDATx}w|Uoz3j0HPbņ{/k]We-,VD-(ui H0JBBBzS; Mu綹gΜ3~D)aN7;#Nyt[8t:S[ZZbx ,ˮfVTQ?U^?tkߏTSS3vE1byPJ;Nf1I@)uLmvv&MK@ ~80~$I6 F1BL) g,˜$Izpݐ$ɑȑ#ߝ4i0?M$TV\yKaa},@dd$fqL!Q`4< !J>E @EH@ 9Nf};qĿ\x*}?_ iǎ׮]wAF'$$fFQVN, v;flǩY!IA@ an^@(H].mllDFFƿG3228_[tkbb"M&1h4"22$..uyd9$WQvt: (/ &a"W^yִ4l63F4PPIU$u|/<YKK Ax<:W\1okgSOx<פFbIFFfs~2_ W׋vx<x^|>I0A/w^x@^X?62N-3/;999`4fv6p@T|3zۍ`0A:^ DEIev뭷1bġ^ Eh+q&V\yѯ_?l6&DEEC(ȲxRC+$A DQ<hIDc,5d%I:FcUtttmlllyJJJA* B?7nݺ/rOff&gZlQQQ,;;vȲ JqR8 ,C8C$C4_$@7-`DQ4h6+3336;;TM ?7(rWl9r8&vjlIq\Z/W*"vjAD'dLeEcf( zz`bbbv61cƬlT 䬬7xVUf3 Dmk=tH,mnnF{{;Aǁyp\h  UmOE {<\.PJ>8St7a~N  4jm6~wk}ֆVA~|>AHt CGf!!!QQQ- SSpLs YEy Y|w@ ;sh :L&0J&@/*~?~!@C~00L HHH@||<8H(ԕQj~` AҩS>:k֬5qUSN_fbbbnb$66KTr @ p!y& fHOOGlllu8RpqVfPJ9J)X,!$1??o1믿ވP_?CKLL>h4Ll6#t멫ď:y^}C CAtt4RRR`4;t*T`0f(8v䴴4VZZ?>ڄ_I9:nS  >** F#W#ZF)=NrՙXtN}}Tj Y &t2J)u,)))_:_~j v{_ cLKժ֪p`ЇW1ԊPB^Z)tܜV#hpRھ5,˰X,ڤ$ɐb*GFFrvXVL&-Oh=t կ %H&G &-xmtuhӿ*,D#d9|ԨQ7L.:DcƌOM{О@EL&90˻n6dȐ`YYٓ+Vϟ'x_#Էo)VL&fXZSN G@/)j *B']w.b<I:dF f0H{{a<'T̛7oN1 0ǟvQ, Q+OA0uU= vrK{uj%VYV.22Rk݂ް' @1;&5i5N*z~t:pA=d2BTFߓrJ=1&O>`%O؎B 1#!($k]s2ҦT=õÅċ^ sj}NcMsw]m6PeY8qb%o{< W(tSWޞpjվ '4*U])uwNNL&bXdfcSLYW@Oc&A]`WwIpٕ׆~Cf=@ߧp3/z]z+@r,1cƌ$dkxx8J1p8M cl+D)cL3Pm#\1J^5]5Iz {@C; q>|J/ ! VȲ̔|=НJg IV\~nmUp` LsWLFO%5zǜQJa4СC톯QwQ\EEA;jIX  6SD$Gx4AӶ0%;]A&K^wfO{ ꜫ YeW`4;v`CC?66֤1  |ҩ'zkO+j>\@F$j[:Wje:T^k{sTpvcA)%`XmX:0 Y0^>/eÚeҩ^vg'B{2j5f@H;vv#9c fʼp=Zqkm8hzmwiIztJ5ݕϢ!~_"w'Ȍ1Yi$b?X1}L- NP:/l^SZ~-}rDkP~`kpL]NC(vU z`ttv{kэ2"2o/77wUNNguxg$K&".#Y?p]{gm2[ _Rڥp8g`'M&uM&2c1Q@8(IE7S)&Ƙ @D{{{+`F!Dxd=|SzB[n@^(v{\vpԎ?"R0|ʭq,MHOx7ʲlDFBѣf9 @@eX 3_ WZ .7o7۝M|WpY슡z39u;nE0$~'joȯ J (``(..>h43铠VJD$=,p3]y]@k5Au'K03ZMqzWv8sw Anc,mAJit·89A"m0 u  l~8gÓ+E2\ogݩpkƺːQ߮ZZ#GVVV~f>Ƙ@k&[D)cL! +///...7L QtLVwT7\Z{nvKwփ@w7L}Uk^oF AUꪽ_ Gn,2),,tXuIm;m AU4'Ng޽{ Z$IZ,hH !DEL)of>|>$pe?w©gck!mب~kx8͢7s]ipZj~?S~?dɒǎ۪4!c^\QB2C* ! {",&Y)*IeʲL%I>(o!$1(^ 6U gv%|p ,q%BիW/F(RJ8_A)hIVxb` 8v%K<|G+cr>` F !q!Cr$@ժmv>;R9Pchmsu]8Rg^ Du/T +, #v#$q7n_d ]N"%IqKړ'PDț=͜9>`;v2====555ѣ U2TիWq{FFFt{{㔁ej>Ai(5JAzY}vq0L$ԽQG8h S 2*"Q52YS*zN;1PMcVaڵ_hS׋B Ϻn'|/~I&M={ت4I2MTY=$堂 >>>n[M&g0(Z[[]UUUe> ! @ VR,Of]&<۽1CCCC]bbb}h *jԲ !Ue$)iӦ>ҤIS<>JV&``ϙے)EimYQ)c~9rbX !p,Qz>RJ!Lu(^?eqUUUbnnov# !$ Vw8U)FCh(AAab!a !fƘ0߫!-eYն=OFXxv믿w~9nHNN ,x~͚5(љ/LE9lcLgff=zC7@P]e4)jWRRRZPPcUUU)q~ :thI^ IDATN~%$$XVvkf0qLs=BP__/mݺuw}EqduRLi:PŁf,K4~N$ V-̙3gDDDeff&RJerqq궽{n^x !QeԬ|+r !f$ 222 ?###-...bPI[>rq(1#d/f۷oIII1Faz ZZZ ;s-)))F^SBQPr#РzrCA"!(7iLJ;΍͢(ju: uU3B,BO4QC%54scLz-^'>5J*++k}n7o~ʕ+RJ9A`mcNwzG]'Kvbc,Gz7hX|W %cuJ" 8Asνw~ʦ={ _RiK`-cܓJIe@IC{ZTC)Ÿ[o]WQQr\qqqk׮?bĈ{)tڡ.5 tn۸qVUUUԔ*!BsʷǸ_O'0(^/_\XXx!8Ȳڤ:Y 6~ܿ*$99־}}(zp6U}6Sj8H RJ1fXDm.f"...r_}UC=tl67Oddu##KKK Ahj:N`)S?/oqGJJYk׮ 9~7!DI|,ph")jc,hUl6fϞ}ksIOOO{뮻.v駻^|ſsw}^5贕.&'cNjbfBRچ7ݢ9ZÉNg˥E) 8p ϪnbX ݻw=Ss9}c56Ji+B)u?u-[z_|y]vƍ7jԨ>HBWzϧaT/81f8N$IdDQTU$~:vI_a˖-[`wݻ{ĈgΜ97###~ԨQi<7Kd7h͂փ#iӦM%cQ(Fehw6<쳷~fdd;\rɄ˗{(383ɲ;wǎܱcǧ(ݻw`tt4_WWW1~|N6 P"d{u@AzM_eiiiknڴ `1Qinx<." h~'׬Yg}G}x֭;ce˖-1cƬ^{mu0Ks?~˗?/}=L0555 EJLL]6[nReىFRC/^zo_m6l2>>>&22$|uuu.rrr4xওZ:gͨj%Bg׿z駗 4hrzzzoc+u]N6ɪU6\.וW^y!B[;!NNKK1cd۷nO׿8--L)u0c aPٌ1AA{_999I>l,--6lx%"jx@L}чR ~Nw477f3`ଳκ1㢺?oh{R~B\v_{433s;Ɣ[ZZť|voX&oQQёdɒNc6OJ!_?1cƌNJJ)S&]|/[~ I ?+>ꫯ~^wu#Tp P&&2ݵkׁ~> &Å~O@~rm]yWHIIv\RFF/((h.%B4ɳN #t^z: QE&/ FnѴqO?o͛ gp8Z[ Fj@@mm?/‘ &XhկX,?[l曟+.kjjx≫{ッh{{{ܹs-_|{tȢH|F #Rڤ j(***nztwBLV 9⍈,YuΝ@MM͏,,zξ}egg..//g{۲eKmAAA?mQSSӿ̄L !{6lȞ}?~K~a8 pD`„ geeMrEo^+rt_y~Φ&;|} `J88n8qL&SBݵapd9s|R]]c}]ull\tEGtN`nٲ% %$$ĘL&ӨQݲeKDCCCWa1yB<_͛w9sMLL8sF?ӯA!DE.0eʔ˾O:fY|ɫgΜyhD0fΜٿzEEҥK?]pt3AmRq\5I%Iro}%hhjj`0Y}* !o^ZTTTk׮9Nڰ9''opmm-۵kW[׾q.^|7R `!@(ŔY8.TL~zyUUUaK,ٶsZzlʔ)/{ws} }^sy)+ OhӷQJ)Y&Ϝ9rȑ#zhK|Yg9oҩ8!<@cbbAV|bn޶m[s=?jÆ Żw.^zcTX~|ˌHROyzb,F[Eaݺuk,YСCo9$___R*Եw؎ q^zǏO>NΎ$ ѣgqEftQf)IR,&?9#PJ' &^dɲQF]|Wεcƌw 7{7~G>rGG};/~Ŋ/IԆ^l[:tд}qqqM)sv,BHoP܏̟ە4M<8RSSN6mb1l6kLLn"""L .\VUUkfGYE9ritfO=)Ҿ!e e bF#oISny>@,Q_?_?c„ JCUT)Ng#gbb7xog}vVff)gWii&L),,YvBZ6\0<ˇ eggOm8(F!ʲEHv<˩Щ@&DQleYV^ŕW^9a{`0lٲU˖-kP9 GvIvZ3<}}=sss6k֬ێ=ZPYYp:{Z[[]N-tE@v>}Smc˲Z[nrzz|.JiZ{{;Vk :sŝ@Y_|l p-*.y2e~JL&g!TtC){#G B B. 8n`q\O_‹!F&PJB&, B(B8B衿Pֿ91v? @G}̙Ȏ;_ڻwoc566z>KcǎJ>LI" $Cq7!ώp8p\8ǥ" Χ HQJ t,Z2ōO{矂 n[d1IJs{hmm M6-"FDDw=&&&:++k( $.^>}T\wuYUUU(?U@MxmFK]A-5Դ1L2fȐ!q~ƪ*ĉ'v֭nyܹXYYY(I#F~y#<$:( F}[PPиe˖cǎy >D%_z?U9فQ]S ^cǎCo4??~>Cv@iii(Gydt25D`ʕo^y|%{q~V[[,))VWW>O޾}{lcǎ7n|[l)*:ƜN\WW'׋{m:|nӦM_S`xС;vXVXXxÇg@ 775+eee]Pv\TTǎ1wo}MQQQS}}c7nx7v644x tL0'IfEN>fk>7tӫ@Ff0dD>t c̜kۛ2@m۶?FFFҶ644jސ q\B~mݶp͏ =z駟rW޽6))644#G̼{ֺ)`qULLtݺu?CJJJŮ]|%kkkkjjģG<|~h_xsG۷|޽5;{!+Wiޏ1%%e䫯Z~17|Sv~d,wߝ ҥKZ㕲xAΌIݻwo>|yFxaÆEBn',Be---c>Q]]]7qytvܹsĉsZZZn:uꟳl۶m_|Oɞ Es]|׮]%>+vj~g\pY`?5*ܵp/?-={\.mFəp4Zj-r  fTTv`0e`b4ɸq&''G 9TvVl3d2Erg2dHƅ^8z7mEuuu;WZ C!$`rkkk7o^{?e?q˯꪿ZjYg8dȐxQŢ?JL@ȑ#&$$ `)S_={ׯoZ~}ömfV~}͚55!TJE*'T f)h40dĈZjM7}mpW^;S"Bȹ4D|*LכLL 8B%zOS!_fZ/p6B&S"T2 BH?f"8nZdc7 &A*S}[|_~}RRRZƘL)mP;ltE6"$I&} RQC F g577X/߿H8.UEuaR**5~3J/"%Iwƫ|DL8Ji,c,A8Ll63߯yu:Nt'xKB:R  Bii^OV(IVu={RnwWΘ1cݞ@`8.QXJizb ke!;aHV*ɬ<v#<€(9IGhV>}OJ(!?cI$7n̙3RJތcZΝ;w^K/KqF*Iq%Apszlo8(:(!لALJi q&)V9I (Ătʔ)?///wnVWWJJJ| ;w,ݿ}J{=iMBk&Bg1v~L5y͵1ӳV}O$!`0SK/ɓ'|&B`2]s5M:uUW]uab;Xz щT$S2a@^^>}l[---8ObbbUuEKIIIy?>|xNkk-;;,"""СCb~o|_5ӵK@Oz@0h4^xݻw1c\{֯_Ə6B޽%-^xi N6mG}$+++.??%&&l۩j54hԬY.Q;}WktD FUWWhjjj%$O>ɤ}lYcȨQf}C.ə~_:thdcc?##þf͚¤$5k*dBɚߌDv>|ԡCfGFFf{fϞ}رc3j;vX'|O6lؐ[^^ݽ{wb\n]y睗a4… ˲]r%⋏&_ XdʴʖHHHJIIݾ}e˖-g d2 7o >y VXzȑ)޶zkl&й _& 8Y2^|ڤ<5KOII1=zGd'zezqYc/9=|YG}>066]YYt@(_Wk'#Ç_4{p;!CA$`~t>uLe٥I8uEQ"7F0C % 0@ga`UwJ q 9䛸]< F,4NIENDB`ukui-screensaver/src/assets/weather/11.png0000644000175000017500000004213014205074704017453 0ustar fengfengPNG  IHDR>a IDATxyU?9{g&3I2 D4DE("/(&!HBBȾdf2Kf鵺]J̄$K,Y C`}w_OH""gϞz ðm-`Nr~mH&hooGoo/yAeYLF.s=d7oۯ||ޑT.⏜{PC6Û|/ﭭ !H$".\SL!^&!~*Bww7$H'Y^^{„ /s1O.X`ĉ{ux-7… hѢt]7ѨzꩧbܸqC3&pL&!DQmD !$m{\hU \3oP @ѫ@83gݧrmGjjj&}ٛDXu:Ĵi&>0<|}7ضCJ 0`̕R (PUurb1EQ@DC 9"˱# mҶmrJ2i:u3K,i\qHo{H3 -Z/Ҷms֬YϖeR3;{{{3-!!|1 "B<G}}=*++T6z 4J088Ad١cѸ-dRdYL:o_|ہm o ?Yx"JhY F̌L&zp]1qDL8 3R{I& `V0M6M)%K}ZmrVF/rHuq3g/g͚L4,:@ܻa$} 3L B@ EQPVVYfv G%c8j[FUUa!BQbfr(XB__s_x0[xۀ @={Gc&N8dxyg_hl6 0r!iPU՘?>lhǩ7C8L*8&Mz$ F `0jsǎg>󯦦IEI4Gn<|3ZD"!'zKlF.63]?4!"> =/8O/!ݍRƭVQQa-ojj:sMxGv]]݉`0 f.Gsq{f(BQUUӧqUߐ0tWt]GUUEAK @+//7f?\Դxx0eD"qu#yw>$iFR!⻉D0uԡzL 8 J#1[V^^}7?(-wh4:Ӷm  ;K?)`hvsOz(2<0D^Uf&J-oDRJ@ p8 .d(YJWTT䛛O[n <#@SU5ZZZ1TUN دߎ^0rt0Lf(F~N]c ]׽-K)*s_[lgyxH0 eʆaP{{;04M ?g&yLu!mPUCMRfCfR= I)ٶmm[q ]8XLN;q DIt}Ct"k0[ 8̛Fd2@.z{c~@~f*\.W[WWײk׮ؿwM%1-XE}EAPu]6vZO.Mߏl6;$];0pP$!~ =(8@D⣊p(PHaBˏ Ew5>7WSOc)%a7is*ڄ(Jx ȵk~l&9&H$QG3gΤ:A"@<힍~O{ &c#w~Fφ(e :Hpَ;75MPTQ7x㳊///7~QGܹs9H0npvn1&ZWf7qK- T麎@ alӦM;EQ:۶[ٜ<#F%ny)xڮ,]Ed2WU#H쮯_5s/~ @օÚF@`_xᅟ br3@" ۶pyhhI0_xد>7DwwGU縸ዩ0MSڶ-FqömDɓ'?r'ANOӉ'Nu8 eߍ8OD,k(ʲ 1? E?]ޫG3м .uߏIx&nI0eYxbHr9J)SϿa֬YM8Lăe@Κ5s9z0̅ jG}4[E xOTۦid28 "^EΡkXCawܶ{{w(-%5ز,b`N%\rJx# OzuN:1~!' 3t$(e?ubL6>RRV.:;;Q[[{w`@@N>h4:AJiϜ9S>don "R)$ɡg#=Ws#ב*~21RʔWEuTЏi\aq*s.4M` \sQ` O:oVVVH$+_h WΧ;鎌{Ŵ_RUy"G-Ydu|"XAVVV.""֊`0F$

G?z;P O @ hPO 0 cXⅻw;u`n7˛M#"`ft~1Y˽XUB#t]G0D0Ҫ뺘0ajժ/_U( ǩ`P꺮z^!$rܰR"V9PJ{ E'KǛK+pʍ /^9aq:ff۶˲'naU4"c( 9:=ukwΛF%hR@àr"FD(.,Q0`0ns1-\X<* bR4 R7X7¼)^۫ 2Cl-%RV +""9a% ~EQa, P0ŕ,b(d2vq~"oF^O8ϻv+LP*7@I) HueY|ꩧ^ cFdi3 @!+ˍ-S\γ~֑Dw]{#ݞ_g,W)|w HUUB؉Dbԩ)65*}*@:KӽmiEa%CcA*R 1G0dիW/7oNq`f2Msҽq`4'ִCp=x^wݥwupC)%=]$F>(1%?XƲz$(X0YYYytMMMi2)%r9v= Y%{Gh ~Oܖy7~"}~r^8w\L0{֭[wB2s#JbE6goʔ)*D.cUUIJ99-{n);[{Er378Nwtɘle/JIpggg[^Ē0cMd\n37gΜ|Md)m/ދ #{YANc}\Rۏ 7 XXc!MT/_pWW!I)R+(hEBGqaǜ1ckZY<ׯ~/und!{@nCo?pnvu?;Iܹز,i,]i9` ,Vg7mڴ4o/R_O2Jv?,l%绛E㏜l衇-N$A%R!z.BawZccc2+4͡≞ P,wfK|#[xzgdd? %|J~>;d2Ϯ\~(t28 6@0 ;̠*j۷y-mmm=L-ҋn$q8*BE@a&K 7"nsKKYvތJ+]}\.GtZJ)Ŷm|[lNHQͦp0@-K2b" 6lhݰaKEDeYYYEEEEe8F""W]ׁ0ZwG[y?$pL*`$qh׆{#SmYuuux.0M9{I8@(R6$v`,(x *if;;;:;;_jǯ4M !DޠN3 @Q\FR &RjϮ7z-e\.g۶twwwuן_'" `J)-2V 3Wwww 8[;PT"҅"r\IEr|^L6mF6 t!&p_rd$lrv$;+PFrc*2U/~P\}cŭlА뮻ijjZCD̃R(TQ狴H†W[s[xۖq`g?@6 BA P^̧"b @hϗW{d26_t1 kznB,nڭpUUCӴf gz_Lٲ, R\9e"⢪a'#e%}Q:ƪU,]T*V7y۶&Jh @>ŦU㧲I"\Ձ1 b'_DH|F`ߴ| wqolY9'9PM>}G0iuݙdSr zqw Ð\He˖l5k֜p0$oe  v֭[w\ressԤRiF00؞~w%J`$;B(Yfp$@ -XoM/@eeeY.eY4M8b1Dn鄂CW a,E!۶fY4ʾuG} 5v1Ɋ'\aÆ׿ *++kjjƍWSQQQ@@4Mefd2niii޳gOc*DAj fN94Qζ eӗ`Z/j5Y ;xlbM_2UU-)e^Jin fD@mmm ,8y Dѧ\N_$=#\4H !Yt:Ҳ-WWWW'"mal6`)b©%\.7\l&" d.KnuBBB[3ǫD,^)f6ό<HbwJ2$z#r:kRYgf @* l"*P(2Vzrƍf͚`ԅB!!$ "e l&) w޴cǎ BIM>'NO$eEOΧ,`!M6ٶd2;wlXjʆ~Fl%`b,4Ξ`,"6w l # 揯1 Py5e59\-y˲r(u!FD* ARmpBᇐvvqbB:N[uֽ\SS3~ &7n|8N0 tIWO&]]]mmm{ݻk߾}` "MMM[6xuu &L?~X, ÚQ IDAT[RtWWW={wܹYb cF!(Brq5dEf?? '#OpLmLI恖*YψgDAz0 ekKK&(p8 BUUuEQiaT*4M3]DR\0#8^XG;R#1}2T/A DׁK-:n Ğ/_`6 N?*+\H2QP GNDs-{a{ٰ"‰(@Dfl X#t@m;L&d2)FD#k8sy!xt3@EEɸҝ׮xMUyL<lymWHc`>qwJEW퐠Hٱ3I gK`fg ,Pr+3ň,H73;1 0JQGTQzu9,֋mb78/%.;(5 D8bZkEE"JeO~0B ;@G,'C= { @: mfi`DjNqp(n]궰b#Y|>OZC ;Ϝpźl̕?:|;O׷򔫮M^<N8cC+sp-3_"Hظ x_Y*Wu`ּ%`m"˶^)e3#>}Bo}KKi'U?d[^$#J7BKA["$[7H10ͷv&9WPhv:.b5{ל:%2.j ;i_ȕw%{3AvR dakuwA(qX(\C(78n`povPzSVK*ك[]vqIjP*j+&{aCa}B{٨X+, 3xP7oKQJ?+k]]U{tp}loߦDdˮiK6RX24ՌibRVl!sW\b ~p/zv̜";tmߺa/ۤh 򢪲x ^\V 2D@sC~o`S?RD ffsφ-/(GmB lS"w?6}x@U WW,AyO{8w՗+PD TU\'p|yGmwr jR=m}=},^E%_nxeDZTTFo4lvv@  H+&R@ 0 mj@!zWJSFq_rM_tgtxu^jb;8@OSF_ز+꧌h߷O/j9}[nyƧ~#EY(Q`om(@VPfAO?}ۯ_z?l5lݷ}2)᷆ 2`mgëNwNiZf0ko \7VX({zsǶ7nj.=@YQc!in:4TU-gaDg> '>TsW DHڶ ([q6-Mm׊ܻkr :@1l?<{{tcGݩl!U/-[y&A Hg]ݒښĸB6`z↔ SMsw m@(@֔d#VXжw}(J,jYfF8eVGwkW_}yo[)/K?ʷX&"\*b7W_n %䅗-I&A%*>z t.Q&۶=oӧ_0H+c6v^Ӏ7҇!ko#(s dY{L>X!\/C7ϴdgN "0%>貉''jC:c_GsH'od6{[wzhݏnśFcN;(/>ZV},GmϞG:Fx İ?c4P.\^8W#1KQՕm, ,aQgqe<3>)^E"Qǜ%ȶ; W9//V2~p*CѼ F,K<ďݹ>TT.eG?w4J@~K|>UnE&l+V w"#6QǒM @yK0_z16ù䗔W3xڛhҴ8_Y8P,; N_\\xi0t *D,|ż shPg(}o[EH"=]>k'E_:,2IW=Rŗ@羆 M+m.0|V yx|q\=nV) ?y~G )`giD6`!{k;`;FK eJ۵+N|Yb֍wu7e@ n} ipzv|Q8b%S_8R,F KQVߴeN73؏_>4ʡ,{>~k.gUTVM\6TV.KڲKwVcCkV\qǺ/m= dF t Ur|<0D?|o~[V79wG x3s=ݐm(ĤUvn)~*:ӺvbͬoxhoW;(cY=f]m@F7$fi9#m<+[ǎ_DWdO'?9S*'ojMVWHY@=@&X揝v𥧜Be3MV nWt;79ϑ?Mwő?N\IhX2!Q "ll<[Ƨ1Y$BQf^&wz} D_]_VE".DR2r8 ~ƍBhn 6`>Ƌ*D L lwr'nė0yDޔk/Y/VD:pTuU|O-Du4jl/TT &;Zƨl)UK1g`P mi(DJ$w'5a"?|Cxom_oÁw@Sl;QoD=H q 3ߍK*aufTb%¡e˞כ"|~4cDlW Om\H$ɑJMk`W[L@]B;qCPT-*m[٧}ŏR.׽9dF$av= =uǟw]=UݪU[9i+si@RD5^zSMY8*@ǼK0eq)-Op'\9u]ܾ^d W95ӿϷ.;7? lsq@klmD?=߷:svowwcs=h-Da#w 8m7[q9VM+mڼg߶߿|A7=d(Sao ?USa6%HnivREս{~_/`\'3DnY-b!L}kvx¾ĜE"VD7`wu=O`v^ ?# Az8=,D4fy64 g  8G9m;w(0-6T^P;[MCU 6n)8x-۶U5Jgxm/ެat %e~hZ4@ XU6sL 8daT8 ; &WL{_jZaš⹉#<VM4=izETr552eDT?˲QgCcGK9pwk4'U ]$,l*$9x;KIǘ5 U/$}M{;m[')͐l[Wg B%|Y4k|͵o~#xsV1!;"eB=?_,#YiΑIWLs޲O>sk]'Hֵt+ӵc\_瞣ᓼ֯%}GT/oDq"m B@ %>Bp(6x5զW=7Fu˗.O~;|.ɐiU*z;ǣܾ?j۳&aDSLzFCD ݶlN{!}\3n?h;yw,KRY.DERlmh[Զ#bL'cӫZ7LeFΘ1w]+J fuO}|uuE+wEpW'Y*Ѧzp^]Df׮ܸL)|FU?bkwܾUVrݣ20(X6Qx @w{,6e fWJu` hq8dU'nxtv&$s@WЬ@:o8|`*l,Sѿ i*&;TB4e-^c_W|p[oVwt5RݫvHk>U-s; p/M3Qf:9 ɗ8(wH!GM3,DV5_ՒHc?>/ȫ滋/N?րɚr=Q8@жVe26|sLJ3>Fɱ|U91RL^uۛ:QuuY p=>8=2 |W-?Xw %)p w-Rf۲e7^mj`xn5sКR@ aVe?u3xSݽBHJ4ˮes_T=B2@4ZmJEB(eHٳ{=rGj5Lkq]}/׌PVaZ ܲ3>۔DWck N> uYP9T[Xn{ P;dUIus믯({K>bvHd:=8PyvE!w(iUC3P+,@&v6E]a[~ۻQ8f$)5޺N]!Q+*mf`VڃL{G~qgz\r cfVI$Uq{t9^a&V_ Q-ÎHؖ0)wķnp3Je9΃%UXre!ɮnAL*jD%up]/3S4DjG~d_ ?m+C͛tEJ;o6xb5u'e[,+ ` .`k_[|Dgh5Oyҧ>I{0볟a>˨r,@Pg_3 lAKIDATG%|IY=8۰өs#]=y{O,XZDUk{߻O/З%z׬=o#uY#EjzP  ݹ2Ho~5rևat(}X=fV$4]+j PQƜoy-uF!jwN%nvJK ~f˓\ό7m;M T4=hD+gh_wH2x}C;$΋'ŗf~ kѲuܸ/az(_?s,H >a-{G z!ot,3-f3oVY9Yxw#շ/N"޾JF%T7{%/5hU#lmaQgFwR!zvfәc` ( Hl?vp@/g>bH5+aY r #Q ~n_z%Dd@7l dQщ,kՅXٜlWh:xB)`SgƖW;v("1Qʚ,VҲhÛ[BD!Tۺimb"`t&Ѳ^FFṞ-{I=zJJMMpp8ʇ3.;mɪbKw5r&C[-U ۄ賀AT:YQHJ]'/iPZ+7rkٌH @>z+XJR:!Bjk䭷tGY_(l@IO?}g"XXd7DLl ofTx!%l$Hw0@b op%#W)~=h`ÇXX^0\1a&DvNNK_ec 9pqG>'W IENDB`ukui-screensaver/src/assets/weather/40.png0000644000175000017500000003536414205074704017470 0ustar fengfengPNG  IHDR>a IDATxyU7}Ω^,=! !Pq0:.踼#qW}ygUP@E&P%D@ $$dY{ᄋo[y~TMuNDϧ>ު:ϾS?A4w{#rOXNF|nii)(p31DT#(^zi޽{[?Ϸ%Id2銈HJIRJ!HZCkJ),BCCCH&]˖-5k;k֬}A?aip ԭ]_{IDZd2²,Fmm-jjjNɲ,H Zk(8" !#ömv]l۶0V^]vٷ#i8`x≋~_\444 NB)uuuڊVeYf9~R X,"rOOȶmbŴi~s݆?Q"8Y 7|kkkEmmk!;w.!J9p''}_~L2MR!Z[[sΡL&uA+8ȏr>3cppk!CBVJ)۶eCCŋ?}=WJu644:ue˖ WṀ?R0Y@ݻ 4R)6 CKe<!ʈp+CGGG9G|Jh!@2쬯} _hSӦM<!9p[zۅn*2ydYR}zc3tuuE0AHHG&<WJ)d29sϞ}O7O MLFR)cŊhnn.8f]na{2D{{;m'JѾqwy^P,u]yrm}2h#9- s9W$IJs%|c9>ѕ?Ru]sB"?LBJZ,ZBJQD14MTWWS: ED$ PBϾGyny' zҥ7oŖed2)f͚Euuue$0f  8ʜoprX9np=/$ fiH$ DT*ڵk%\ro_r$ >nllgYg2~ '<esD)eYWWWc,( 6EhHD{40¾uC@ZkJW^yeλ߭)"'mNRMKIT*ʼnD<ݯhQ,kg&H5Mgφi{CPN!;SDs*5:ZUU50ٚ:uji˖-+~/}8EF'J2ee˖eY4M444sT֚AKKˊM6kxRx:4eYF*ҩTJVWWsCCjjj(N#L4aFT1 ~P}T:/VJy:{'866o|旿_13LTd2rܹ<{l)WG*y~w4>$]̱`] -*zD"A8Zc;v')aj @Л6m:=׻i|gpss3UprLVۃ0(RH ǓF)\~7M3\žI766hhhX,KIA|5*}f_HJiΟ?;D p LDDo4S5DCwڵkٲesŢ,KRQ=V@xHs=x Xo#_t1kVN#>Ţ`[S*x@&w}Νyff˲uuuTIGWJHP%3lpҢZajJqDVqDm?J(U}G*(=Jm;8NIZzqK!DDT=00iYVۜ9s]U2 =X"9.pE%APѵ*qm)Q"8zJJ1>G_tjc.J{~aZPJ)(~衇nimmdɒlV)dXhYEU+AMhQx$rH.U\W|`x1G<8;=Eۏpk߿e.; bE֚m۶cƌKjjjK"L0T)3W Q[iEq1'KJG!*m#q#U,R$v !ֺQNdePTH&y֭[_2eƠ])(88oޕ8"#N#2$'ĸ$QN qǟ#~TµR)|ػw{:fv:|ګ 3o"HnڴicPPMMM3.9J0Ej#(?>щIExqőUIE'>(ĥGSm( @u]8p<"U9 ,H7 ۷l"'I  >9"8J{tB(!Ĺ$Nho*Q-djFۏ@T(4m۶CwqՁVR'(J!!äm]v/xСRB$OG@@m@Zkfߥ1 6GW?]sa#ەPDa*ቮ 8D$# fhAD)8N{>+OD /=3y/J'ȏq=!Rs~rAqbZ#qc6nbɶmm6ȸ;{&3xr H?#!Li1!(!9 @_7mmm󪪪2CCCJk]8)$򠃝FisD\Hz9Nі@d.$^ʽf9:vqI۶qw޷~{ >G)b 8 "¤P{4_R]h((a4ef<8o޼lxHn$RVAT|\GK`oqR"+6ǶmmP0b׮]7t^xq"̜0  ODyf.'c!$|[V# C/yvC0(utt9s"˲a 4.UM~sd8bBb lۦbȎp( d~ԶA`Ţ6MS>zqa)˲L!D0D0&BT*ў={n_'"G0BuCqUSZ'W$$ !!ulž4i!\ql:/KN$H&IR4]HT$nnԀR^Rl[EdH$31^A%駟|wQ*$tmkkkkKKK[ssssCCC}uuuU2L !DЮ* C8s]{ `ID*@~@—^-G\A0 D$V4m% ݇><`Hy a2ADŋ\rZZZ\MӤGb%N]dt:tynkkk{Z)n)aX u]Q||7OY# _Ri4M""KR1^0f@6"|b@BXǃv!0,f֖ N* ugbc76S 7>ǗͻUJŌ$|CH)ϟdҥ+3iLD!4b6GD5y'jappt]۷oݻ16mZ9s͚5ka}}}C*[BYd?HmE_`÷ƅ&Y|w(ӀT Z H/`շu=P4?!!4M~ʔ)555S,J& KuqǶ[-}xIDATl6ߝREk)R5 +i骪t:]Ji)۶|>fYPJc'-X#{[/ =+>qZ>1 BC$h0xOXsWIpIHBBq`&lٸ|۞y DaOD$rBDK  Z"6r#"m" Iv 4zNoqs8KzWqcUBΉ 5$892LvX0mol'3g#%|h("feS`&&?`@GFgIaZøB^bDp/\ ^Srۖt` Qt< T`lᖳO3֜e;ӐzeBEV\xC RJdRl4 `w:_Zj /S зߏ_0E3_ΫAP ȇh!bf%p8ZkWk ~'oy7-NG=I` 4CK"ׁV3긐*!D Cq^eXuj\.8T@&d&dijObo }Dp1ϨFUS=je0~]p#}6l>R ]FfOt(uBB'٭3e&V$!fV@L`F[nT`^a2RP<{){}О.eFv "aHXk{B'y]!+j.'SFR~߰ .nP9q& D!u,^6a4zp8: L``@&@BmxN H)ap  |fbzh6C Ѐ%>D Ȍ6zM1(`jMf6AVrqI@牋5_@H)y#H=i/`륹i` t_{JVA<v> ьn]#\ZC%siyTݪ<1 VAZHwaJ] S+&Ҫ{{Q٨o+̬Y{Hs#~Տ~Apo3pp?0 6zgXi,XSSt˽ظz!ӛcnoLǒD=lDY =$5XG!V=wB`&eVj!+ Ҥ=h݊oų+p q?0 ʎPX Q7e .Zr?VlNjU` p7ҏ2JEtشuf_,1}?%9yP\ $lh?_$@~0D))$sg&`6"nIC e?ҷ4>"ӏ4y΂5pG>3X|q/3˘5K0҂0XX& _|~z^$Y!1t8PA QXSY$jho:iØRR" ⭾` Ľc˳[Gfkzޛ.+!}$ 0k0\CEDw*r?pb HY&M&baMVD`ԫtmc-Wbb#UjYWwB ;?œ𫔳R\d!h'5Pν>r2uJ5)$_OC *tbkZ2ۉ,U6t2j ωԪVz<!Ob#N4RQ7~J -p@&{R0  xux|I){OUN 0n}|sw@ ֹ&FXؚKH6U;[. O aK@V`I{C ,6R@EGtt ,-aS'^f>e\ 4^w`UU󊮆tXT&2L%p/33Cc$a8}V@3bH!Z$@[ǡu4zʈK{'%ZA U``6aY"^Nh/4Iu?O}:c}CLb!!d.&]<'`>mL G`x~ .Y㨛ۚ|='S`$Ȩ&BkW?[SB֪RhMZQPs{_uՎJ*g*f=(qC!|M`1ә|O# ,MW^BBӌX VAdrirsLӈ2h}A=3$z'ֽB}AA/|co!E']:8H8p2y5/ kN$&+Rm~x^tХ5)q}|Y;hpZjB+OW3"YN;Ӗ=[o >`2Rn׌fI2@>f[VdHJc| f4NfLPvF "-~=p .:#"W?>̄-u4p"FM054]s~iŧP.P=`2R"s[Dod s mbKq:wX{?o ph8CCHLQdQWz{'~a^jyD$,9s\!~ÞR"u E"\N<`dcOG{dsz357dҤ3D>d짟x/(z00o6J.R585999ΔA2(R7we]o޵e-siO%lX_{[{B7C*2ɸ_˟1s2`'نڼdӓ?Om}GqdhP^D!Ofor]f&K*{eoP;>NL&7U3 JѮ/E'<"ZcO-{{G+bnYʒ(z M J.#3,2l-Q:(qeferYv(|Y/ kA+zևHEdZ[3f* EMFq|1,"-?H%-Xٱ}`(#U%!3wRR5@ߺ}Ηl f]rv }?{ 3B4?%}c91@^蟾u+bGJ}*Ua @45ԵS9!P!OdZ>0 ~kVi32ir*)n_@OT<Woy`w_n~N4c@u%n ;T2f#8v!' @.)>" o<')\B&{Wkה`2[?DEkFQ+xڹ+ `u@;@GLLE>ܳu>t%=0J(0R0.@EԷfmN_^f 6&5Rv{IC fn!DgP|,4i0`vfeE[@Ld @Vke$.hT 爛={ze`=Ax P CW.4 qlZ͟|k4rzT!L ZkO3 @.fW5狅n*-=] a{C63z}\͹=8ucgבe !Bcqx *n~r0]sc_I [ @WKzm4Ќ>)e_P=p `{%j̗ΟfQ0!L0nn_=@dODT27UOGf3N|VrQ7ܴ_KRuB.&VN:Lf6ܛ >ؗà't,ϵ0}Lh{fa9WpD8@ <Y`y "kB ɴ䫮$^&t,= \3^]xU(O_pۅ!'y$G\?%>#MS?ӷ Hvß+5,loaf=mc X3 &ҧw↓2j?OۀB)tQg'ah9m=3O朿"\`5aPKoع.:3RB`|U̧L 0|`Af19醙SH;uɍEdZQ|'RHC:]T!L&ZR .ǕO ."`'^ק=OK߉WLjAdFyn 4`VtmoCz )yRP @/maL*L&xJ>(yz׫Ќn!D1}P$BRڄODC?ŧ4L (o{̉[v7X R|N !R#!L79⬅0{KDaլϓRH$SRuY~{?,D}A5~DT$2y^g,P7zչZc@Jya IDATxy|?>gfO a&,ʢH]VXWV },bˣP**AJ@%la K͝s~ܙ0$}^y]f9s>r>s$@2P @T_$m7FqmwYvuu巷B1X 7746~j0eo_|`DӴ|Ν79rr]\.x<\.Ȳ A8!QJt](u-''g٨Qvmzp»Ted 0B Y!"$I"BL皦AUUh]9QEY5a„]z饫6·v K,eee2YprzJ<N'DQXTT$nt:ijj*/--%^1PJaigAUU #%UU潈K01ϊ$F4PJcN>33 LjJ+mPdڴiFx4+n^ZZJҠiAH0z:ԿTMڊ`0hU "YGAp7b13D4AUUaapΕ1c+**j6+p6@s9ӧv5'8N\3tPv `g>2mmmEWWTUE4MxA "!>@$I `DQ(­i UUP(@ Ji9ĉ_,++54M{{II<s9Z>DGGb("bt]?$%HHMM4oaZB0:i<~H$PVV{tAl`?k,kiiiBJJ F8ITV`~hmmmF0@~(e#ldeeAD@ɤ̍Y[.DQb1Ť6Jۍx(@(\.SYYӧ-]tZtH< e<''gtaaXY$gffS]*2%lg7sh2_eB pM0nj5XN̡iBͤF(&Ij[[[>K7"OKK;dp眘C0םL t`ɲ  ӉZ=3D5&s ;0!8^;N)=== Goδ^$Isu]G{{{BmZ=lS][Ur20؇79㜛EŽt3S9F?]KYb,1\.S#(v}ׇ~k} N @!H!RUU%~ߚҕ fGdk88*)))k̡Ձ14?[d-|f=Ƙ'ڵkСC[-g" 4\n0jp_[%b8?xiK2N,'&qaT]cs.D4iizsΝ[@rss/_v^/qp8e9nU5@)MdivɱkdetwX.eo7c@Gbt/I&_zYJJx5.vg>\`T&v|[NE対Jnzt^PP|ϗNB&aV_*'+9&Y&NTUEVVપWcX4pZt xMMMW^WHII %%%$'''Gbf~7͂9\3mrw t؇oVbߓ]dOj5Bb(=%%]UUU+Ztࠔ.u}bNNNr(++À8yUV*YZcnx;OU{L6ڟՖXb:1!DE᠀T `Oj(B1CdvH]*dD%DսGw&5hf!˕tkI}7/RG#&Ϛv8| Km۶ᐲ0j(@9&N~&xvwHdJF~2jfR(BBf$+BdP((^޼ |„ kaY?3:j(I8s1:f?BrA2k‰D{9 fҜ6WEኢUUy,cHu BFp8ۋ^tE/**2I`ĉM2:Jz!Cy޽7óU8fֲLOX'*'{=v-LXV5Mfp]׹1Z"@4m0` ~"8CD@}я~^eeemw)1޼H޹}`gzw?{=+cW}=Ƒ;lnnF8~%3 N4L𲲲SRR,˪ ۝8Sa7N}Xeu>̙%S=OŇ9x`Y҂+W\`oq 8Q0BHȑ#1ބtA$uzbzdd5ӨxBޝ9꩝|b2hy$h$IxHMMszKN}Ȑ!}>_,˚233c}O69Oj'KI֩N47ɪ^CBUCYMmnz Mp8 СCc555X`vm=8/z0w\̩O&eiyKJC;Ⱥ!Tz1tDQ ,D$.Iꒊc;w|߮_)8'js.r"fgw !bh&V X>35njN' LHO@IՉ RJ:;;šC۷oiÆ ߜ;p@Ñg80t)bqo}V &(>x"9G؞dͬ)i Xb\ycfzf̘QR O@)9J[[[`9)dNlځ& 4H b5nv`&p2I2NT~oH0$Is$ID._r :TAxIڣ$*vUnJ}Y5j?9@axћfI&vMc>1RȲ̇ v~|=z! Sn7u+B<qg2&IiR+f-;ZFlw=&~]OfZGw%n:9;;`Wt8p`WSSS4##a$1 y i'v[;*f<@H̲$`Wf' ӓ|[{kLp}A)%xxmxhPUUUUIIɨh4c qn } "'VrMӈu9ۿ[fY&j{n3dm־05i;KFis?'tlr󶶶# =7OQ:8)]]]h4l!f =|Qvošl(k{g\vd?"Fz,˖-[Y__ c,Ez Lq߿t3hРlEQtX 3ߪ O7; .7o7ۓMw|wdY쎡vؙQ6a+b6oU yq=A0 @%rQ,V]׉nw8 )V2jc7II`G ;d$V3LݐH$cdG.]W1Jr\ї88:A۷o~$h4ʌ4%TU%֝-ܓdΞOnefo Z' +{Rɘo.uCF{fj(<P(*Kify@:O$ZD) VUUUq8iiib4x.GQ27dN] A`{Ow}ak$DF']yݕim)@HA#[n .X]׃Ji5"G6nܸ]uJeBi& #D"(z1%SvOxaBaURoU4u $@7F}=D"¼y;pWF!BHsi8FݜB(B0A!hmm=PYYeƍkkkLQ1`QTu1:D"x} u%@nRo]i$ g2o-;O$AOf!,4p"{>裿"> SJÆ88I J)Ut]" !Nnݺu )ii>xܢ(JZVVVܷo_BaqBG Z=pcN=]ZEQ4̲TUEٝY+ivvfaJI k׮ ,Xoc6sĐM t]!UJhB8A02 G7XC&knUUt]8ǖDy2ޔ|b^Xݻ~f3ngy\UUbPaÆ>H$rpbTBpsVbFDQ@@ Άs.qzv0{MBM6}5t@  Hj3תRڃL8{0cXmsHu]2f^DUUs/L g+(  Gf09u]XbEӼy^j`L^=Bפ 5 vU߰u͌u@IIxHQKZo&'"ָPMΤ @3iҤk.±>Rf, :&`=XcUaSbdnm2]j0I㍦pp\p\̪-$`n 5kzu333sfeee^p$QMh4vtt몫k"H3'v:(XqGp2 #|x^C[׺k+Nw;钹<!f?tҤIKKKx^̘oHAmI)4kBV4yMkp\,syI{O\.Wbk;pMѬ0!s?^jժb(S#)cXL5hFDBhxQaĥr"8'W_ M-Tt2{8L)U9"j3 x(:cL7:Cqb X ֬YSjժ:::!cFwpe#'*Q߇BB7I1QD\ !Q IDAT\=I 缷jKlpJ}}K+.8\4$@ f0,RJ=1n!@7!)s@|>_AJ<_~).+ښ) KpԱ45H/%++kC=￿v[ !ys̐ !⎠8RQ}ٹYiv$ RcXLD"J0 uĩO% .!P-uvҽ^ouI$麮uuu@g{{{(~ĥSj3GG&SUS3&G[5%?{Np(wdӽ}cpHC2+z{Wvwy#;t]ojkf"O<4556558:0 >IMLP+q D9 pn:!p~ C6C60*@q%v 9)<sʛmc/'ee¢jnkV&:% TWW?F*\f̘Xeeӧeɒ%oy7u! 0̈QFѪ1q"X3 n0݌Uh!J {M8eddZ Ѝ f(;8(o4,v Gq7m(-bt}3o+[^{;H׺HX x:8gQKM򶷷z1D"?ݴi\1.''-[TF"PJ6QaN!ڢl2c8!<@H1֋& Oؽ{Q URUM+Q~ě2ẩ=p?WQ JQ8QO <)̛HP ib HմȎo6'EzB$}yͩ"77wfuul}?*˲1A)us Gcc IN24O0_yVMy`8 o(V ;zi M;?g}#p{/ k rp+Q6!$F)qƘ ^'|z*@~h!@XT@k]+撒qhtW_}k7pù]tW\q؊nQF]c=2v17o-psͨZGr]w^?$ MGV~6`z)z–s @V7='ImAb#Ua(1BHs *J) nsH鿜2;="9{uI.$;󖊊?O׷Huuu§~gҤIp̘C-^r&LpݺuxTTTfY iEv]=':`N8% ܊xG 81 p moͥSFD#AvG o^N(ء"a" R\~qiS"t+K6mz#\hmmmp8;tP .ȫwuuiǵjժ}o?`ӓO>??OxС:y<ܚؓlmՖ?o * \tJD 65gQq]'Kv!D Vr=E1= ,KU׬Y3j̙o.IOOϽ?+..8~Dgձ@x&MoĈi󈪪/Kwq~ii\SS綴cǎ??/ 80{Ƀkkkq(]2"Bg@qw9eRyssǜ?ڝ.^̦)S6k; u \R8:!D#pMZ_z2bh:KWggg?vQ_$閛nnh]]7g33Jgۿ-[~&OMXQQm'xp8!C_|^qeO:{ǫW?y\oJJE)++sUTTt_x^[g͚5q̘1۵kW ]w8oJɀRZzc)J!ԧOŇ/c}Nlݺ?c]9998?(>!) F`2۷!TAAAF~~~bqcڦMj:kiii8qPM;m-  طoozݏ='_}sȱX_}/7557oW\Leeg(jVR n`w#B˞BT^~!9%%媝;wNt:#TUI))'ۍ춚VWW7x׮]gggHOO' =zt{cccgkk묔<uu;UVhuvdᄏ+##{Ι3vYqaC !t]g)))Œ3>MIIAyyz?rܑ}l>^6S;^~jjjؓO>7"ph_-FXLC;pKnNⳍ}FgٷH{<A&I@ gϞM (̤%D[#F 455@wss>s.OMMeYؿѣGw:Xnݮoq^)??wyZZZԁ:ͬ#A$Ip:.ϟ_3cl-Тz-Z7xoc_1_( 4TJG36~p锲[䧩JSӝ [Y@y<Oqq1;rH.IY~;,4hĬqae_~?ի')#yhw͝;wc,ww@˅Νtƍ[u]7?Diի^{U[ls=:|Ammm^aԤn;x^G!A)3"fv?9q΃+<F)u}7cZh4ڠ3o:&:e_,[3gLUt:?]ƍ+&IDI(~敕eegg|ͺlQs 2gΜ?l޼jхRMMMۃ>#GoW/yR \={﫪^o .nٲ%m۶oVsApȲ,ހ+8Ã|7;(͒$UfQc8.ĝYo^ yioA[] d͚5X,n71A {nذ!y-5 ǐin;%k/¬ ߋ/7XAI7=QsD3(5Gѩ]|7>!##֥N3roFFFιkkp}2I2&]Y>Prܺjb/*u]7'---k׮]wmɓ'g466{ ]tEi< Yf-YxWU1V +WDQLg aC)\fz@ ՜Xz"A(iT{9iq[48d[?'B'vttd| [nQqq1 ͢(FC6k`8e9NaR1y_[ nB<"~(NgYfffZYY766>=(׿U%%%dCAh!ii'b81BHPP2!B)mB\xT Rش@ &D^|_dddpÇ-##Ɖ NA.TP"sB2G]c-esYvv6/s9眓SYYׯ?녅۷7b1.Cd}&"11+Hi4ǯt] x} @u]w!6 41۽{vY7%%xСƍgMpXݿNAR92駟~߼4)'ΑwTۀH |c`k۶myww>y䑻.K/IM PJ2Wɞ߃n(Yƺ04W9'J0'B.4}v1*//OmkkS6lذGDjSm):!l]׋W90nLNEhA]p}?2BBψ98yҥK_x߿iSO=ƍ>={_h6N,(];̷JTύ|8cϞ=_(--}>DLӴ(~ιs3ҍ̕^GhVUՏ8d&833۶mLCgN%I)9/朧 :z!uuuu0ӹ4 c$@]]]i]]SCܽUUUzI{6;;;2eȑpb~梔f22gJQ)!añuK5 |޽W)2ry[ZZ?C) u}؈# -pv.X|{xt]|7g G%f,iib|(B^g"ڪ-eee E9#ZWW~H?:euh#tc*Z3Ql&#33󎦦شiHo޼˗p8dT"] 6J:HiJA ޞSQQ1q,] 07nƘ1Q 0aBahټ2&ć{l l\pO>b:;;]]]Æ ^^^>)33Sg=u:VAb)whsGxuuu%%%7ڵkG]UZZ:wީ,)) w5jTyydYnΝm۶Ғ{#f fzc>hG߾}|嗏 4={hiiiwmڴLII~u+V>qƟ (TTUmN:QkA.]vժ(߿ҦM~L 8`ܸqw9rȑ#3 .|F1>G)pνbŊ[<ϢAFg"Mnj{Ś5L_vۈzg-Z^yy˗/?PRRoBG4MKKKܸq?|IZZڋjN]u]4mt]ߏLXN !۷oSO=5kҤI?tѢEJ~Wy睜6 IDATwܹPVV-)))80uԻnjs3!$ƌ?D"+ $ 1ՄI??3Nwg{Lc]@@饗*EEEkG}?x@JJ6_B֕'r\w߳+W<9p5j2Y/~g̘n~~MMMM|ժU/i7 Q= .lʵs"X|/`0kkkÇcCi7oVvikk~i;S#?p'e7L4=rh/eP@ }GTWW-\pٳ3O?uo*--M3fеk.Aqqׯq[}:*w~kG@H;̹u~5G xIF>#?XL2eА!Cٳ'#lذ/llnn\1cƔ?;@?e]QVnj}Bgf[޽{/6mgG170133fs5Mӫk׮G"9{U|y˖-ܬO6q}o+;;[ڱcǾk3g|]Qo.=? :ҳHARpzyu9p7+***׬Y󳚚ƍGW?~|n~~o߾'|pcǎUF)22(ǥ+tglх1J^q0#BW>&e˖U>N6s.䒬niT~~~Q(KNSk)lݺ?ڽ{7UUUq p?m%-Kq$;KW,Ei_^x%EEECo޶bŊ /pՊ(455չs΀(nxaŕgϾtZjKxeti/C?ڃvq}۷.D;v566}>ݩp]b޲EO'&,# sbR I|KȩE-_'K9Bu޷UuM;^pcxL<= ,̅˲l[u]/4MӸx♃\~}dfgg+`0{'&&|$89>핕'nƬW%2 A!& !sV8d-IRP$ d`)K$YY13 qqMbVVݻ>}P(LZZZcLeuJ+$mZB*rg2a 2vqBHs9g1%H:ԉ׽KG@x0=tPJ=?z-TUui6m|ҥ+**.u[CR tl8#XF%zثieY5 ca IDATxwՕ>{㤞i4JHB!0Y `ll w55fNlvYmd06` @PHUuUVh$#~U޺=xo@>o; zPJRuֵNmY֩I& D"&L6sm,K-+rƍOڲe tL&3E)Bvo>30d]]ݖ &>cƌϟܹs믖 dɒEK,`ݺu3 @$A(eYR2MD֚lFP@.ԩS:co>PzZ@Ys~X PWWp8Bd&a $Ak uٶmE8uYklۖtlz}65һ vڙwyU[lhCCز,EDBAxhiizDQH)!3R mömdYR)A:F.RJ+d:::g>sBQ -H]w)esss BR 4҂8q"hYҕRZ A:"Nmu]6\袋>sYg=Rԍ7g}D"x>@@P_? ², xΜ97oB2d|P5<122\.q`6{Q"Jɋ/³>*m&$C]?w'NCa|QGԩSˌ̯@```CCC( e8N`qs9ؗ^z>5Zk QWc\/>k]bDQ)㏧f8S_j'ˡLfsEe 5k ff.,0 H766E"---ޚ>} Oh@@0?%&LXP(dq>)Hm `wH&AX,;>=&b vgԧB766njoolL:u0П~W@@Ps}? N450=Xjkkۍvj?`۶mm뎒z>B(@D0 !`ߌmPJm#ömD"g~xѢE|/y= X,6퓟x<d8C1w\ETv13sY l߾|X,¶28BH)aFF#AJY;|g,ii̚P(L&۶1cƌ':+O9唧G>;.B8hlkkc=|%A[ۋT*qP(ү.34M b6m&N!D(c%2 yxxl7 u]NE>nj3⋿y!=0K/] D訣;&?c`` ϣP(wX0 ĉ1}tB@DcF|Bd2N&Q^Z:o_|ſ=rl~Yf}$ p8,'MD3f(3S6.mKaB0MpgFGGLBRcfH)FQ__OHfD(r7xC'yPh=Cbϗ31yA/dgvIzdM6떢1@L7MX |0Eb>|b&, ͘>}:Q<G$10&L_/| /vuuMCI>k2cٺu~ccBD<z icuݲt|D0gq;J+%?X_O\|Qq 0aIPH$/gN{/_0mmmE"KJ !d}}=I)R3j ?۶0j4M̞=X̏ˌ#?CFϧ h*P__!31O]]]:::#@uuu$߷_\/;eS"tT2:l`ۂQixܫ^gdq bf)%KûIdB{uG"RabX*jVo`8)D9dH$~ve]oxD4 #ZN#m6 0ʌ6`6.jii)ğ$4AUZVSW;!Uh-VJs= / 0dѲw`hk4fh_#bXb Z̪/ ֢Ys=pF*pz'~/3fu)e^8F,h4JJIvu*x<###PJWWyЗvn ,RiNRJm߹skصv;?a-\'|/ڣ(EQaYfbvέ/}ծmemSYGpao_KsTsC׮]{#^;@[n:H$"ZZZx֬Yhoo466|FIZVY _ XtTosF ^[+boںjjjjZdV]c^|W^yZiMMMv(2hA%-?*~k0L)b{,z7Q S̤ȯ&@P]vك;wH"pܹs裏&eWFOumUӱ4Ia`ʞU2lOTXfRgak&"8aMKf͚3ϗnWc@eN@-?2=>"{S8VJ (?d6x̙3<sG fty%kNl&766ʓO>uuu0R% ßRUZ`'Wm\@55k?> < k\ތeQ,E:mlC5:Hˠ9% j4aD"Fd2eZxO(1`@@8n5M0 òQ?R tfURԒZG-p05RecsC0?Q :؁Y)%]u̙x9v{1h߰1!0(qRc1?dɞ`T&Z OPe"`y՜б|hZ<xv=:Nގ[Ij֭RodF9sk&)դZ/2^fjijerT\)S9~۫YyOe''"B3#O6M`ySRJ uf9ˍya!kƠ4V Jn!̱fcHPdJki'=jH$B>xA`xxxƍnnn_,mrxx,ycXmV+E̪<T\j}ವj>@v}0]$>%4&"5yW?!"a6 CCCH$zؕ'_MM͌*vjeײA Tc@]K#K\?W-CYgOE{M1J/p0FH80i;;;Xbq7?(Y0J^S+%SR?W*ò`'V(}&V>KZRxdrP)J)CJXPD2.SOmmmV&3mdfA5X~,J Xg`Q,R"cUsUK0 =+ jZ)X}ZN;ȸW2QI .0]]}}}?O;3BD3ص;(@im "Y|>?ϛ4iRq9eYPN vfy:1hW:_YwЙ 'XN]VNЯT4@ˎ8Ja^\. ! 0f(6PW^#ojjj3 EmOl߻]iռZߊvY jfPKګ1fٓď+߃PP`q022Bsul+I@ADP"m6lذrƍ]ZHɲ,y ۶[Q\(ysᛎdTcH%*'` /2{J(j fO#i򩧞z7߼% Ȱ62W^۷gY8RL*<Q(K)8T(?d~5s%T!n)<ʯWST3ic9l~\((jXvw T@@rjnC7H]TI4 P6XE4{JW\ٻrW È544$D"Fx̲455MI>󽶳8K1RJzoVER&%$F|~;4M"%L"BpXmf:(+.-HTmSjG!c1%|Ue%j7V۶MbC߃G-~y Rzom:3dPT@>r%?os˼@ "6"-4|?744$.\xf.;Q_Wj%ݬRBuZbkO0gjO2Q*ŋW=r^O("Z9!8*qƹ:7Dʕ~uf05G@BeF0g^b) aW(յ @h3\>HNZXXp\.|>|ߴ-9 ˣ:As|^+8/{嗗r9a)eHAB@4C.]{}hٲe8+ >QZu )iR촐hs{,P,Ak 1o}Icha wcɒ%n=餓immm* p]W;S%rj/"w(`f!$l&B!_ugU5mXdqXJ)~UVW\IJD":qIDS]]]}86 0Y۶d2T___wwwwWWWg.Ǯe`fȡH@ ؘ/Pwnx:Xo$ (`1ہz7L߼H1WE@sEOOO N8ÏM$ud m&L9PT/*Z= 666N8qb;R b BlY(FD>ʕ+~4226m;ۻw}@|Hzυyטz=1= 9zG ^vϜ~j(Ie3eLy)C$"Z+P@+!;w|a4$hrf%mW_}zk9s̛7oIDQXff"bQڎfWۆb7mڴjÆ +tg̚5방SH$L,Otu]_T,QAL&7-]եPs!R\zVz-b'#{ ҄ǘhZ;$ ][bf)*,ѲLgɖ n:͗u'u%3," ̊+[b+ӦM5y&LhbuPHNX`o>JR;{zz:7@y(z۶mmi &Lioor8) IDAT6.Xi2:f2l___gg71Di>EN@k84?$¥(pӴi/Kq3Eݚ_䫙ҏ-57}N%f9AwIҩc6rܱSR}{k3:WCGr8"ld " y}I;XQcVDJZ y16*͎d!bP9ENDYl y1hHOx_Ak./d~ ޑGI})TxټeV?"VDV4b4#c&!ra0M**$&p=!UEVfQbLM 4]2#`'Y>7ap<~BPi|l Dʆ #쏿}\t18dq13Deb|AѾ<"J uuN*XHV#Œ1;&Tz"f٨I,HeA}*[ގN!`0DH[JL?aO0"m @.9<m)B`u`0{9d"C]3 Y7hzO>^$A@溮*zeg?f{}kW7bz6g0S `A̮fÀppCj##>ɛ~ S\%_A2>x&nIpZۅ# dm 뙓ki挑^q< 5DTD)TfE]ixY8L`7MQFSQr7DzPp"nPԴy3ftvv/"@9S1*Ok"r2ھ$lfVY@g0DnD[p@Akƈ74w-f, S)Gphm7;UgшP9ɸi:V)b$4 x;Ĉ@Eely t ,ϝw[!Ĥ&V(&[G46 BӉ0 \k]f#;^(AhBfvDr%N~2@ 0IXRV*E6?АUZ0D `\$;+Mn 'a =05V@S1#) ro.mkE7>sj RfpR"+An!. %_CH确/(0̠4ݡ}7uWͿŮtli"X0ՄARҀD"1 `;ƾO\_\#E+WU?nilD"Lͥ=B CG_p§ԲE ;V?( ܮ;=:{¤4ML   e yk_^P,RLʏ\q]/]S?YNv+<s}kI_&ͮ#Bk6XF0'I,CujH}0?R]W:HFce%Nr\YaT g)ޥ){9/ wl?¯r쓎و#*daa&of"vuAuw5H imB Yʵ=#eZuQf;UC!dAh;ؚ0;@Tbk2dE 1'4t_o>IͶ=l4 f͝ aCBǗ)aKɥXGW33)ܢ) ~쉗N$XX[B&  !y:dRʑSbq뚣>r@m_j|;Yi5|'^[뒯.t1אMӈ0\8KF$'t~9C/~ J&_`J {s<,2@z f'H?^aFVJUJuѧsTU[trUa-K.%:"dbV)TAlZ[›D0F?!"Z]u;?Z+w?K ~O3g}b)F;O.&e1DgX$EC0qS $q <1yխno7sd;DVREW ZX+0qŗM>QcH@  v&~]QAK,VP߼OlV\~V29`&}iEŧx~Py9|_;ztm6ܑBaAldAdJaJO.ϡ=@1cvS4K P30Yd 6F@vG5 k"<-ivɔJDP! 7CPÌH +5ݠ}غG_/'"MK X+(3Rf7#!b%';(ս5{z>t?J1pSqe 'T޸M nvZCY7\NF)yGFhFCRŏ~x?/ݯhlqF<d vfA}u(]DbRx#ki[ 9-Ov:ҳ H6V&{~ AC{hЫ= 4L|L9ġLdĦʝ[&/=O==?ز #V._;HQBHYeװ g/Kìt7 mӏ;X"\t=1 mDpH'I]{hA4c=O%+ ?uN0;E|HCdfȘ\`se\}= ED9a0@EG̀1a$iU42~h+ I%R{rgӾ ӿ_扻^H4Z7hkNfvX[;6.{  1!yfD)/:w|oŎS{8Ste6Ζ~f1ZuJ)m?oCw9%4R&bY'a=lʿͤ J#I)3u2P"ÌIB S3Ǻ;HDN w+]W( au?J6Cmg>w7m[ɫZP#A\J(Bٽ}凿LHٶS% `yb&G]ФӤX-qO=Ջ ԗV3!.~O>&WכtJ:eӧϮ:RjZV -7ճ +oN-x/ЮRf(Hȟc ꩇ_^2RAfc.nbί# +;1IN.)gb :MkoQk.- qwy0(ziuF:;w )xn4'byW 6R _3{Yشe.hLmc8`ǘ-F%r3Q*f n I%ap1($ߤ +_G 0k@b@);o᠎F m3=̫hdAּj>fJ9ĩ@V;#piؘ$ z۬umϚQ 4w} ?pua=&D%M8 SJ N[:P)-_H#|2gP?RBp ϐ0MpۄDdFw[C';Ha6-G{zn9oVi(z; N^Ii!oc{JYR>ﹲ{Y$ur}=rLB?Ǐ,=9~̚@2mCiֺϐ֝t$ S)N(؛!f*uUYNi*8dr;HUsup6&z{]e?.!KN)vܫ;4PFh#^Xt(%Lw$sT^͢Vng}_)s\dsO̬έ0ЭwXr֌A" 0h<1StnJ3D 3I){ߧ _ݓ[ C[O8Cn fgU49΢# ӉNHٟTxI"BA ;=b▏+Fh6=Kx[DF }:(O ioxy^ q~`[Mu4fLg w5ʪ$IRN®̜V,Å2\+oW>aޣ^%!NKSC"DIm" ͏mٰX K ̷# +?QX||h8֋uۆ~~JoRi]'׋/P_S-iCv0tc2W$)e7pO 5hN bDr;Tj,*%醏_rRyS T~k)w2lKΡmfơYfɦ3fsq_]pkR-5&fӝO.R`U?DD;R~g@}[>MxWJp鍤cc[FNĀ҂BPg]iC.B1D||oz@-'ƠrK|`kV}} |u=)(ӆIDAT_[mXu7q~O_{WVs8!%hEYZA$(hu@hX* H3*PI2bB4ISHq؉~̏n!4$Ky~~sY"=-#~&@zV>W(UJE9Qjm]oL;SY)UTx"ٯ8[kyifhRLV<03Q"l(o5J2%$}Ϯ['o#= Z{ p} qUg8eCyra(o)dgYm~΋UZnj9ݹQṷҵIn9k; QZoj}GŞ=sRgA@)9Q0'P)&⮭z4ҰnqZy!&ڙ6sۆdm~ 8\*t-k3"`%g2ki*:ѽ̕K/ owZXB)< c')3k->52e "_׊Tm>(D۷st*ÂR**0s4sYPs*QTu!@*IeD~(L薇pW*cp |tC(  A vuRecQsqnecmNݿnur{pCo؂kyHٶ0p_7v',?8Dg=\ LHLHҶ% Dj^.lzq}p.tg; zbdolhI;z "ڼ3tgV_$пFE"?tޜY&cly{m *}3Du[yn(nu[8 "˗ǬDq&?)@*4j w'}'#/ 8sY@)k} i J@Ehlr8:sϝ!!;+G `Z j hHE@{NzwG*̫߷4G{fGr>ȖTN'ʁzЎ}܃APJ>3LI"# T)ܫ;;c S-/oOw*Dtþ?v%WgYVHlߎ=43Ӗ  SҰPYyхô$p9uHo$ڴG t<"j+W,gSN$9 hczi+ǫ,%"Tz*;3c@ Ml7)' R8J})1?jcMMsOO<?9ۥd Sٳkh씱1jؚ=c׮B !Bzm`y-tmZ$@㩲m[k-c&nP9Pc ӻ$"cƧj$1pG*`{pG p8F&'E0#IENDB`ukui-screensaver/src/assets/weather/36.png0000644000175000017500000004577014205074704017477 0ustar fengfengPNG  IHDR>a IDATxymUۻ w7K==ͣ [`xlVb05@ҋƴ@L33,,W`0&(ϖ-ɒ w:CGU{g,VZ{{oxz<=Oxz]OܘC{e|wؿ [?_x`otZUםW}$}r gWcyVy|Us|:IO)}7Ɨ_d2-z-;z{`]p8Ɠ>* p7~;>#)0ԯ«3x~qb.8_^*xǕ䡟_gxJ\$b\='1]UԔ ̠ĚӯaPh@sU?q͟㩢 owGO> ~9,nXs[_mJvoꟹ[?ͦOꩢ  __5Cubq}akAvPk6j.lo[\?7/ۯܴ XѿTQrww q\~{rmX 7b6l0 (;s)(? &_|/]wz|șramai}iqOx(w= l'.}W 7kޗ l\l/֯|#S;X?_,{t|۳F׍]Q[Sx&_TP4k,(7-;~U7+"~駿~u.p&hx+ȬOx|5[|7~ >K>xXח6[ksex-;`=^g~_  :DG&GOLqƳ]qgk~_w=?uF37|/:Ak|m}]}}/ @qw}KO}s7CkfplcDl=(*8CAi?gBpӛ˿eo)5RnnY//?홻 MFI;7ZT W}α \93^C`4O5]2:?c*';\WdW ĎDmQS4/;}Zm9Y~M [v<Jxl ֲdU.TL˓C=ȝ4m;(dTlVg/ 6:<&:887QC kP%5xu-ގ25d]qكll"lwbf< reb[Ⱦɷ gNuM 3aq#CvmB֞/P6\c NN<<tI@ԂvfWDv(A5_Dv`SnKvUuRv=޵O^IO =Oo^xW}`{5ruC;hАmlY; B pa`NsIv }'ʭ{Q? {Nj~bN"P@{?!*.ϓ~hx#hxȌ~` ZOr31z wgX)so 'ybǓ n?_/~ڳ?^ {ؗ`m?HV&; rs0́;UA6Ԭ2A! j 0ǾAHd* ư ^&xO @O­wᳶ񻯞c}oo(<n7;iQχ7|wozݣn:Go[, f|#+_ ]3ܱa(Gm)*(}U)((@%.>*RUJ nAT#T~~?&~s\~?>ry}wx޷9wMpQoSxdiOV@CKϽFfp ٍۘ+Nr@~嵗ޞ>u;5nF'(|<3ޫ A掕WGA (H_@ў]>]:w^8Ԝun m'{dIeur/x˭ O/'r0_mm6-DaU=֞}@l21<=֮:OѪWMU !)kM=]BV@ >f'4* r-oҀɃr4*GDnMo}W{W)-' ~헲MTua;`=GsU"@%H#(&eF .I 0;KĤlhne()xjdh`J@m m"23V*m/' < 0|ßՅ>׮P3X>f *Ll9 YAgQ[]Օ%\} ~E1P@#]o\E+amjH]C* 9@#P>sRO%q+>Ru֔?|{\}5hSEyWCY@$30U;Mq8(eP2Q)es\:DDݛ%StH6 uPU(ɭ(G%ui%|-9'O 8w~Y3VGD d WC]_;hs D*`W]ny-.ΗXY:, ` ˹ ѱŠV so R(X$Y(Y;b5EM.*A<8p"NYc $ CS$J09@-$PA "d6swMw U5 L*'n>sB#%궡nTL@‽ h2Q@ %A^A0jC @b*ǍH #z$I Tc0]Ơ<$P L Pg"NFZXhSd%fP:.~Jj@DJX2x sdDzq: v{S%4uAaSp;rTzUvp$Òmo@`[ }Tj)S DD!|j{E/(S 9D LD\Iʽ'S3±=E Y \Ԅ+ .v{Jۧf@ d3p 0 QUa}' x20kE h)L4ND 6 l=(NRp|pgP|NU֒ {)bbR}OG@?ϽkBNO'{))dR!8YeĢz(P4NS&)O=a\Ɏ 'f\`Fe9'|,^Sj' +0Zq'ZZt.Oa;n!LT ǔSLBA ܀C !i<5S=Ox< .^rw؁uSAGފ̃(BR^Vn>d S>Uܬʢp{KY8V14аg1S|# YB9jo|C=Tւ~G?>(|X(#|Y?7ԟЋ'v-z}ʳJ!f,qIq[G@c0VHXXy$l R'؅X*PԀ@%h;)ԌaWmPquw_}ky_o֞Lǒb~=w;_m(MS(w,k^!Kqpe a2s'ZlёW< ' ~zͱp;k4DAgb#ѹ3$5 @dn&XBxIJBc03np;P 3b~wvfQoCکn*%X?vߑfy luevֆ7<ߙdd(|;{ Нcq3)a'(ۑ7xY @}m)LҺ&լ᧪aLѵor%!@#Qe|NYy+$H~/ ]CfK;ffv&*RYcאy_'P0Kdo7ttm& U='/MX[(79)@<`'صb3^nt e{O8]w^ f$ˏ8 ֺr1Qx&=_}7]!ePm_fP_lN~psQh~頵SJT2nt`6x%V eJ'e=g|j5l }Wlݸf8x06ahȋ.yclpAt-M J.Հ\<:ƵuɊ5!g+%X)Bl|&(.'~HP./ntK[6Z7KQ 7oj%/+"Is|4#=cwŔW]}3q9\8mLr@u]xDj7^okY}N2fXԮsA)K#br4]g"H"]P?JZW*~O cW>W%3dg<| _nCEjimÀA\B)XQ]l.IT8)x%c`fZh+w gx=#]_L3L qD)匜B gԌ@v<Gia\f [B5o,ڨ4ls('d̏uB|-0x0xA79x\?D?^xva6N @M,qy {D'.J4m@ӣ7EZrf-;Fkg&X)C p  :U'BSS*e 7wfv=OU560`ٿ ̘ȑ`<:6}dd9S57q2N+X{h;+3 HY,Jx#}- 5K:VX}*@AP ulgJ픽@]8AWWCDOD=Mx4DP ,}]8Far[luBD]VCS:T*k,oc?!n\.}N="D@'ȅR9G\q]z,$J84axHE=ܲzGڏ~M!_vzXS p=ouٳkb!m<_/ y6˱~+Y t٘%@HKIG.MhBN8BvUtۏ 4zm©G-Hr5:q5؞b (*lc탔 Rkcsɥ?JQb <)@j˼3}6;s8~|ll-'7\U#Me6ɢxR: = 9z^u.Hd}h$A[f? e(e'MO4zHX`UhCGBz5 q~Iv63. MzY6W`GDQ T(!!:PDl0٘\_/4k ײhQm63@A - ,)]2ty_UU'JX@T6lOLE! -1sIJ=BR +IFԝw^B,Thhcd͚=jw>@G<@ؐ-k2Rir$5(ޥ$U+ʤȗaT32*CtrlQ:BRXƸYG o4$mbhI!#e13W&.d:BȎҴ5 ^<.W7?qLzq))AOy| 012[=uM{{Yɇ'b %Sdj&ƒ$yZRx#.QS&q 'ujbh徵JY~2mMۈ ҹSBO1ElkEȡTD4%p Tu&u۫(~vp7[F}SR4C6UuBD&D1Mwէ>}/D3MQbj#*]pZhP `SʖEFtX5]1RNH  :Te>*V!h7&A @ ~:TpUw}{5s /}o! fLT1D%GD#V۹t9 ~z#S!+DxfA<<LwZSgOc{1Y*SaAEإzI i^) إ N IDATu%(5*XB&' 1#l.d>_k"7pZ%gbgx sknsrp>)H 0Fp)TuJ,rР僚}yn3ʔg8kՎ]2O4ڹJgIq,?*V~ R4e_O]K IkO$=)E+K)LHBCH-M hg~ϗJnf^ 3nv'~eto.YTd T0#*!x1L/Ļ*r6>q3&L6aOS8@BWiB(;)zWRiw@K{ Jw%vHG(!YPT4JKJ8Nqs __,/vv[sn~8v]YKfv>M9˖f.$YM9  BUD^BɈ٪!"ynlQdeT#CMX@d"I˶̀;ȹWxĴ+GD/t5 @7IB&:~@ѐ6j:KQgOxJ]  ubٵ? bO*jm]\s)V & z-ũ燐 :i cUeL}@88 0%3x劦ojc䣑ڲT[jܰ93"c*2fTDTjCD goedR`KP6Fx!}afgrbze X̓f=+OxBjaW՚:. `Ew(:i z*WԹ VEr7_086tsCڪ:Or.'"g&RTnb%v{(Kn5CH#W_\94ك[ e8Οư :3IIH[%ۣ;'Iq)Dh**mk@T=뿿lIA]GlBSOQ†ŊqX2[{o[.oëZҡmnIpaa9fma`*MbtI)ܯtMrA5VT;6N|!,b`]'Pʐ8cUFNalu]pQ@*9;֫4ijhNdGpm/dzͪRvEu{4I&-_4Adgӯ݀- <ȊP06y)dW@yhA]jH""ndaE:~WL @W^^am!J)3؅zz@ JFo,#taU[ƍRyHՒ6 | Ϙb?lR&_X;:n7>H_4xDkm]K y|6hgCmElKn@!k61/jjC!By/n94ʕ,{)vr̛(gEaUXr1s *Ŕczt=@iMtу h+Poj 'jEvm3ohIZͣ.ك\?8~{Tāhnsё?}I-{o|ꮻwA}5 õk͍od%ekGv9j? -5k{{RT,WGLu֍=yqcrÔXm;t-\K*P\˗ –~wSx JuWmƭxo:OK'4vd(x+& kf4"^%FUwhl{V%byP#V7bs?k]Uemxfllpr`+G7;jnӵ`k 2 >Aqj"aaw$$^?gGҔQPw)d!" $N N0@ tր,AgVݔ+"bcכr*&[VOL }]圠K[Sv)7Z\E G;YvomhT-qm6l/e/?1NYV:1Asn?I4%+ΕS_~$YpbRHdɭ'Ԟj6sTC%ɷPqCnX,$l12eIds"B9 "&cj4(`b S |,m{?jj%_C UEmٴuf -zV7w 5S@΢[N ݊HȀХ#X5C]}Q62 t%/Ie*p;.92xi[Yf&c>U9s7,Bh@M,cUz3 3?aPD -HGB\5F%N?@AV]=1l IjNM"bCOS6*`Ԁ_B@=,]D@7uTaX:[.[;XS(- F庮(UmAђ̼`湈"؋[}FY7yZӊsD֒5e b⯺%w6K UC8[I6w "G,/WtqFM@ѭWݭ؛MChJkJ mYJ\ 3h,ڰeܒ_f˗˼s[kw28 d{H9砺DlgTh:%c yŜAaUQ Soase %?Ca(Qu洆zbQ2!.ɵ3XkIl*HP="'f6asdQ nKvjdVV9]>ĐZRA\p դ| 1:ywhԌ:ڿdB('@dY G~"rR'O]$ƾj50SVi 'H(\uu /+[*6l@5Hk ͕ib[\ʈRXAD(3C=$4h/ˇH:Z fOKۭS' 6}KzBOr4?~db ֺa 䘤!4PWZW NxCT컂dzۀ q)P5Pm@RCقz2l@DJji2~HQ<$]%6ػ GP nGPc,>nú}@Qn͖JD#v9-6'!jʒE@}rBT]ѹa*vZy[Qx…k&5: - Ģ®Q<\*}Y:#9EA1怔I"HITg*e:|9j]SFABV}Cb\(j%Zx8rv[lZI5g]Z.ޯᲣ=OP`Ll J e1ܲ8q%q]* Z^ҩ_檶BJR2i؁aM#*V !.TDь4!clΰ*WG(5 nm' Q Hɰ-6cZiW,lLb$wиAw$ fҩ?; u $$0V$kʒDTeRr"# 3U)K=` ".'_h+?4rfUI]#Edj7a*e:bӜyn|ia3QQZ3f.2+PdY(nܳ`I F>"&Ƿw2&ifjJSh;"k3Al/sNbqUc+o_񻏙ƞ Q,PY|Ո]Md/|vؗ?%+gDibI&U-]rrʒfͣB?u!qxa (@\UDDe!XCRETw"~d[{m L{nL(_~7fw޶(& GbUP5R#y\+hq G@2}O[-j1h8n t֞]R6ƪˏD:Bj8kU͝&L|uv\Q"U+kpG) FQ6$A1 4z{ JF%oҮ=nĢnhjۉ9FNa.}m'Ɓ 3KOmC%ۋVYEB\R`@L fA2xGá{F,u*0*R"_Cb bH9]yWqyX]XOacĻ_i~0%*l1Hsřk 0% a Eش/~>*":r,3W"̱1&H"Pӷ[VW s=+"p\ԼX%3bm4 _*~? +6J,7PD18GtpzQL՛{/zW4&2X6E-_Ŗo}gR N1rpK@ij3f΅ k-`+3sq%V+lm/l)z Xтܸ:C\[  Vz +QLn| X'1?dMVYElVk8oփE+XBq\ylwjwK\v %16FF E{uP2@ẼB5}g:m>|/"j(`G(}vmRa`nƗ&_Xf[Od3*[Akb\i[a -rP5/<0! z<9/(N?`LDj#x tuxoevX]+tA0QB 3ګIs_x`W~`@k(Ȁ$Vkj>kmد @c./D@ra.=j 5|eANۈ>\%?CTFі"!@F0Ǿ C=&R`QoD \~uJ:3s ~jƔM'urĝ<e'^eC )Ơ.3\.HLjqyC2Qe, Z ~/k?q~ _"C~1U08JyW}Q;xx|Sg#tF ~-_XdnPn" X)&=>C6vcgN7_dʚ&vݤ NEk;A<1nQ$¸-ɤ6J 0ǝG#T6[ f#'?x=Fq>!RT^qup+4^[xg㉼Hu\Q_GQ>)~>FF=oLpo!hvߟ*&giI,N!qIENDB`ukui-screensaver/src/assets/weather/24.png0000644000175000017500000005133314205074704017464 0ustar fengfengPNG  IHDR>a IDATximWU&cf}{$4 H }y (P~'JFR>1)5`" $ M01 hIm=n9ǜksnH}ws^k5;17@jx㍇EMR@u~6{> mν|vo%wt~ww1}}~70կ~uMo|߷wEY,A7ܢN@$4{?7޲7^o:V~8O4{g11kl;pn[x˭y0/{>{ֽ>G ;oLǤ"\0,OSVc VsCn}Egj{"*SV8d6=ǡMB{U.{MQ7ܪ쎥͊|xcf#|˟7ťvWvˢ{7M$N@JN#^I͟m~Vl)_Lt-V>;C[>;3gw4㕏AL U btyd1fyj9ZPQBg϶y@!m3(>C5OP5% JDetId 3IYYu]{]93)6,I>=1@K2Y$ݣ$t"蒂YBh=Ʀi@+!Hj=Ʃ{l%DQ-FI@QPKURctoBZ%AH sRqI=S;HruH UUфy<}@*K1j4Si$,t,zLiCf!6SxtdWK.QWO,p$ɂ*K.WetWYP+߶6md:Ljc^e[61mt2V®]{c3N HӥŅmx<ժmGd A \R'H{^UM6[I&%Cr; Kcxo;PH^<( m۠* [q]YU5hFuS{#ƣ9w6 r oNn[Z5;hiড়8LH&Qw%WYUﯫVannvN3$_])>~Yp4~rqNMr eQ7ʵQ;?׫y%/Mua^/{{u2;bL&?/|yp3 ny'lwyG.]k{ӟnqG>}#=O'zgo>Q޻o~:=M3Erw½_:ǟk{ӟrgqmLSHS?_R`i@܉q;8|QG{>gŽB]W1BZ|~#n$ *x~8ٳW]u;?.㝿꫿ؿ3=5gkB] յ w޻pжm/~?|_=.=ψlee/}KW\asŲ,(T\#m`-^I f@ +Ҳ ,%rdm! w}7v܉(ffڶšC9Gyywя|fFfs=oң>$k<WcI'x̺㗯&??\L;o[nQN|0 'tg>[?;vZx3ض$eM\z饼B1o%v),IK?χ 瑃2,O{hc|l밶x;wj2b瞽zU9pB/ɗ.>kmk>/|IdfFRE(@U]uqyy0x{mn!.//@kÎ:b -^ }^7}|S_:N;4㘟ys?SN'wDoy[pߟo6,blWݓ*!X l!(]hvvf(p̑; 9$%3ٻp _oe h~Geٛ~f8g^p'ݻTUU1AO3Ai$eiyz`]wN?t7iUU68>G`~!IK˜olۖHXtZŦmyns" O~mgA*@26I,TѴO!F GﯽD \KHw~p6AxK^/~\ZZ]?^>vN[\r _ann.AKA#{m_xoӜG^eۋ}GK*|Qn"Lf4__SO\s5x_wu 9g~cN8[kAe8X__PiږF6GiӚ4ɴfCzйn.}0 d_dNhc$<O}"<`fߎmxq갅[+iuWr~~fo:'Cw_:Pd30'`uܿY4 xWN@4?3)#M7݄kO|Gp1G|c2iJS@l76v`, @>' rYgstG]UN'ػw/-/cqq{,wWSN~r&۷㪫§>)/O__'R_)|ަ;eYv*4Pff p!CA۶\__g#wyOYx[ނ`%^wh)eB1FJ _}xހOMSt҉ꪫg?9/Oٻ4m,F'j*w@ cC]Ӣ(, 7УGuW۹lN6dYe_|e/;pڋN{a8!i0p6/1vJ>~V{ ~o+?}2p2o;>v< =lr=$M){wm!+Wmִ1,+_IWw$d'syy4-OXM/Y?g~Ǟ6ܗ2r")3z!8c_uTfGsu`M61@hd'<;tq}}mя~ԛ;L_syYs^Ž{UɖsH{wq_蛜S9m1>UgͶiC |$ <unbX[ۍضm vt:Eߡm#7Lu]! \ՍvKre<Oi_w~7Ӟ3{o(6o }ݶo?Iio_z@Q r~,sN<#v}拯}γO?m~~}Օ~ڋN?,gκ23Ϳ@t̰O, X!1Gp(RUUinnN ZXXGj@]U1DUUH GaGg>}/|M&73z=^ƓN}کG3[Q^iL y\/-.9h;w=E>r9;hSw2>+ëg M4n&ʯ%ّGPŽ{ᄏ;+@fxO>^U8/ovVWWARIc=]Wu[ft5cp8ԧ>)}CbQ_\;clov%*‡q}}/s~ǟ}{%ig ;yםwzӶpmL)amup*)r k6,~InAJ]Bs_Ry{ 9#',*ꓞ!~ܱޯm#-Ncw C:p4ƶmtǭ 'Hb<JF9Ӗ?W>!Z!o;$a4OycvvAtjˋ +GX! Ws9x Kss;,u-xǝx w:o#i:0[A HT!6 h<;o{k!Lcǣgm9<׾J?[Y3cp}ʲYHHQmqĎ{ vvH|᳟>G"4-o[nu~PFmq2ǢxӞӿִY?M3mGu'mYm XYFޡ73GqݣᰝLhݳ]\[??Ź]z;'pmh8ؖb…!{(Xn6UO[k_3Gxf:90Ѵ-V ڠ ̌ *H$ C wi0* 5w9 IdPh2*4hGwյGw_ٿʶmD 4czuثfaa~4 6ۈQz\~7Ub3*'Mbz- Rj%zpej-WcUk~"wHh!o% G \[om&blF?_^NRo8\*eQ  2e@Bb.rmu\ͨ^@UShLf xZ4׫}%%:x4X潲t)Hpis )G# v0:N~V8g;w -.I(hr4jun FOTowx( (!Bg  Ky~Ï<拀vE87o}B: 㞉6i#u&MEcFPNfbI7uhC ;"  @H)P,c 81 heLk}*c8VN۩8[[9IaBQޝڿN-8m>` .D`Ad 4 p38 4fV,H+`VG =#C%0:؂l$,fVк%KIHJSHǶ2>я@Uu{2{H? }>mQl @ _('@z%8-8Ӄ.X C\9m$q Rp{~VH7߫ ӹ+>{N+`rErP:DrJS '@>`}ˢ-ʬ'")-r)Zd#ppM*"'WE 0F^gۃ@'['N]r*U4 2FB,ĖD4SE hme , seѶ rX) l+#p r$`>$+0919Y*@g d_z%t =J$10&(s&O@rX,0̖ۢ]ξ̂(XL>?[5 18O>610%ќsιSn~Pե]P*,V wXn t&=3<&aPe˄A,@X?l^ XM`10 b'UP#kW@luSs[m?ku3K* A "|gBRd9ڜƈhr40lE!rA`!d,)H&\(A[H=ASu&N ($3ћ\|_4 f¿PSeEks1 ȁ@i 0FJ-niz*IK@l`}h&08,DVpqfﶹ*,$"Ąj&* 6UX&}?{ׂ̈́z@l=f};lIa v:ҀPEh4X)CR(PR2JAdA!0yooJ@uEV-0Zd G)c/dL44f B`P)28- U 08"r] &T0 mDj夨UBM]s)AWo+u\E|< bKh}|J'{ue`90 ӵN$8l bSJcBYz6ݿ j b^(.i"+R8i>-A8$+D`An 3RL fQ]dR(M 0͠ɬwdF:Ft"#1&p` .J{4"„Ј1S@SO*a[?oDS(D ::pXI2%BsPk(DnlY9բE) Ę4+g SPPD0J=ƒ&?q2$H,3 ~]8՝A(Zh/5CS%jjEƹ!:v쩇L j~ 9rwX&X0OpఁyAt>4iCv J!$lNr2 0D D!*J6K!0 wNhbbR#*B(D+Ƴ"v4|Ji@ykRhFJ6z984\4ʇȅD&INlik%S4qXkuo=i_x~DB0p/؂̖%[Q ppY8H2ULRD4|Bip jWXeۤY:)FYi%1 5qM}G\L&5tsL<~YMbZs"r"(M_frNah UԥUP)T]tA_@ U@ Dm5k- 9h\2"Kɐ1> )_iR!/9 Y ibf.j LRm`E$eGlpVӔ@ɄIO.x\@@Z&(DUT"IH,RT©D; udhBzcR# \7x?]p55aU#aT!- dh *ghLQBbPQ ΔU 80 H-)/9X{PC}1/L`B)AʇWs%`JL3$q`Fp8I7P=B9 Rq~i톩HH9=5u@kzT kRj%a+#IZD T&4"EHh\y48B+ҳBQT8XnzȊHߩ^ eb&W2i[_"ΰX;l!CSR>f\iRiɩBNߜPT/\~"Ah2w0_@>XZHDK d&N3k.FdRT0F"2$NRo!1dK x \?,HfPLVJD+a-ǂyMReԂ"*X 1jV s0T5?û c*82,tC0=GEiBr0~Jؒ$NL%R6cR)!-RmQj9^ Elȵ*q:g=D8,fjv^xAY:9 )σ@Z0(T9(dNUHA 1EʹeL~TC*RfXG*("2\ )S-TtO@`˩ZD"T ZVQ"VN Pu;)F%.̓)0F?A`"iVQŃK /!$# gF.ȒB@i98(pB5%`Mp `T#TS^K#a%E8YQ1毧/D! 'i b4&Tيyj#Sl8~ڦU!z"ɂLr8%drN!5{pݛl.T^tA敢U0\`a_>5"6I/E Ex9v%"6(͋X,çBd̕Z"Euhۖ&HHFl#) 0M1KEҺt("L JV'd1K}=uդZ 1m^Yf`~W` RW80 9_fTg'œ#cPIxI`1tXH< hs7E.l>hbO6BF:H@cL1Lz޵7W_x)N00E[A a (27SA 9HShQ ٤wˀ׊;ޑB\>{=UܓK- TsZ/UV *ǔ#@})BMqAJOIHR5Iɋ=EB֕pK)4G @% 5#MnEC*@5JS7wr"%1怰HEVA9)5_i:ȠF@T+h2'Y>M# @**xSezT ]me}Bs v1ӮEs؀2z&L>W!dLtYD$BC_2bi*@LZH ݃!]KY(J( W|5 OtMq"&P%mMq"C)03vZK> Xsp]F=sZ)|fHX~ r0yᰞhK-8lQ!rN}|R+0dK]8p)F nj$n@ё%2OGdlRR,x+0h>Sa#BF֑ʃ}91#mb~10-դUn9jBFQ!( &:ߗsnN߸ lz./\8@/YPK\XQJXƯ >` L~z2+%Ihd *Q*dU֕q '%+ 5 4&Dd=挠O"LdΏ؈KfDZi| c P$.Pb?.q CT6)եU $08Mk)/y >O`WXB*T*t:d!\6M)2 6QP7FȠMgp*HțM3?~x[M!*IVd!G1%|H8]$bZ[4mf-dA`cF-g6U1 !D l*Nx3:ZņH&&!Tn));QGKj0,g@)@M>;Ҍ觛gaeJrE=~ڠP@Eu҂ h TH&I"+R0 !SgoKQdBEHxJe"4%R}[c@H8A<@҄ \$T攜\bTfJٽQJ Rt_8HNuPCvk^x~GKz"3>ai4PD] S;aM$(E_Hf1dbDԍ(/%DLRV @V`EJuV+giNx u#r%&ߗMBi]CI-QDC9OEQ$S> εEȠ.d+BO(EBlF* L#8U8 |eoeP0yP ,rC%%f_'Ӵ46i\E3 WJMI)JCRb"d9xG&֏3%"D f@=||bnZi jL08Y)ER}W&X"0@DOKm)^g%(XL;,ݹ H䩸JT:$ٵuu~3 ͙@z(sUSN@ɥݺiGR\&V<&k13y`D76&L)a`1q\f `ai%&!~9C3&JĊb;SY 4[Oi\Dp%pd^[I ś6Hᒃ=J$ZRCȣdVQᛪxEjV'>2.)!Mُ\$UeP파8q#!ДVųL B 9#4A:g&Y[A"~i-os#WVX+Ap% !i0(L vD{ .3j5ho+8Zf`i{V \ i$ 4sՓYyuqLFsyE5щT":iNT trgF`hNS@G)^+8Rʢb~6xz}O /ȼ~A y%+@ . g1P#Q8FTJAD@);y 1͹BtKx=9=C )0d2mUҞ1G1 7op2{FKHjKc+"JcALk鉠p%}0ݰHQ!Am@ϟЊ RHeiM*DL-ĤF!nhD88*VSl?;z KD@48AE3c(J$Fd" t+.2B'@J96-ko_icl PQHLlU\5 F,=iR܀ (TA , @̠&iKM[a @:v%yMY@ f@,*&k)P ha;Q2&qKYi7;J 8֫sEYQu"-@( /R*[ JġeaM@7JNA5A8HKpI39r63WJ!FRWN/xŋK}L8#G?e_gG$/U м o<9S9U{Q$.x5q@ ehp+JuRb~-7z m5+]EH ے@Gs T6w}(H@z4I1纻{p<[I0mC:nwhr19>i`Vي6R'SߒD dCqWoDBE`MjUP-&Nb+^n`-Ѝ[Nm\|&ĭ`T󦰗dϸP4L&PryP9yji9r c'j>z[^T̑pftK"7R,FjpSoK)}4[u\ Wvn^ WH%ke:25U=Ԓ1GO ]n|t"kȀ]Y }dH}I$!#L['C| g0yɠ٬/www 9t*߬ 6ieiFQƐd&ې2Xn3;a%[WpGYBX)SQ+kIT0Բ> /{w} <HWg8tl Bb; 0C}?QBycN76PB?Qe 8p]RڛeB Ua=GYG3`RW0], 5;8qJt6@Y=J?9(MrW$D ה{Ǖl) dV:Fk?i.q ADqVF0EPĀDrbMeGT(n BJ1l[q* T7 ɭ|^[v ׹/ϛ!\wEGA0g&p8V:2JK{w\ GYyJ(/'rLT+I>gUyv3`MA i}a+i_Fi#&[ 0JȕbHhkKX6^@l(݀j'p-i1  4.C UFZy,~r,|H֬cII&3J f8BЪjr {n1$Pg 6:H$_)8 Kį'ȮVݾ&CdH;v!5&"g \#u2߾UUu83h:] w0t\N"x@͵v;hx`S* UH{&`qCF;pNnB(5P aډJ|P$}"lK V8\H\ܛঊPghN| xs| ̙u/^xgKoț@AV9vLB GBWhV^t!/ᰅ1H\:RY-LZnȼ&s OQJ?Jm*opX ʄ2_Jȡ~w(IU3+ Eq{*bj9ƕkmNJgψ7e޵,r+㗟|<ZGM"ek11Qad(mEn !\b ϑ^)`OމFc EɣcMVNǿP$ ϞJ+J\"e ^wR&Jk-/tזP݀W ")84h=.b|h[ 1xp/oJ\@?'&V bՃ{5+ԮM)|ж .r® f+HS=)&L%+\AXҶˢ*m ͭ|j{ꄞg1ɌT"mְBdں1e_Wc CX3.弄RRPAS <! P/pyDɇ5>)h8.FS )eCӊ,g7)Eh&:l1@DD 1A$b[q" &0X~}CأD/pK2X5CXCs@7>Eϥ5U7u]',x|g`JX8[i9!v5G4:nXf2,wʄ f9Zfάo˖pI3_?r_^ 0d4J1‘'@@=pDG k@7A]Q̢$rژkȸP([μQKSXP nX(aѳFb\pvBIjN#&,`sb:VBY$(-򲃷NmJ➐e=wƏ?Y@[:JBJKBp,Q# 9L-nB [*Ԭ TFe TW"Q -WߍF0ßhģ%:Q:SOY?$(RD$(@KvB gaOm7trۻҾj<=GO0I' {gWp+_k2wd)ȚLpkJ^a9Ťo7 (G ։"o:I"Qp$ے!70²$eRNQ4eƭ狧GJ'H'`vn^\ &G&C.9;G ufʂWJT^=߈= %׹x | ЃrxMYWL3~/?ꖴ)̍ 2*^FfW\Q?<g,vq /("pm;.dKW̙ 'jIa&¢tA2-@Nf7gOsbbGQ]53juʴwBMx~x\?CJ ƘhWh!:օZe+d\W 5KĄ[88Ǖ*M da H&f LT8FԲ9v1Mw[p67mMͦ|bK+6PHdu A>}|IN=]"e~:઒ĖPI~TDKh=АEZ!kF'w%( Ĩ$AEkJ#=>Cy^o1s'щ^Y&Ȗ1bKHt%"j-d[ܼ‘ 9!W&(gTbC)NuOb8y{hNlIlh5K}h::|jA2s"ppz3Ļ X~lb4X\zB@")9@B2r X]EZ53F9vn-]_w|Or5_~gĕV"WJbCdd9\;zt$?_6&:*w.-MfE(=Cyj&6(Bʰ{$2Nq*>/7rr+{Rs@:r@5TT|FΛyq{/?+MLN8%d9}tlG ?y<^pXEC,Ne?'1ŋ~yO/Oɑh+t4O\kƋ8//}jlB-R =Yb}^tL6&p?{o|+.8-ykB|/2).'gkw[5ߜow:hOi<4xOi<4xOi<4xOi<4xOi< x@{IENDB`ukui-screensaver/src/assets/weather/16.png0000644000175000017500000004645514205074704017476 0ustar fengfengPNG  IHDR>a IDATxy|?>gfO a&,ʢH]VXWV },bˣP**AJ@%la K͝s~ܙ0$}^y]f9s>r>s$@2P @T_$m7FqmwYvuu巷B1X 7746~j0eo_|`DӴ|Ν79rr]\.x<\.Ȳ A8!QJt](u-''g٨Qvmzp»Ted 0B Y!"$I"BL皦AUUh]9QEY5a„]z饫6·v K,eee2YprzJ<N'DQXTT$nt:ijj*/--%^1PJaigAUU #%UU潈K01ϊ$F4PJcN>33 LjJ+mPdڴiFx4+n^ZZJҠiAH0z:ԿTMڊ`0hU "YGAp7b13D4AUUaapΕ1c+**j6+p6@s9ӧv5'8N\3tPv `g>2mmmEWWTUE4MxA "!>@$I `DQ(­i UUP(@ Ji9ĉ_,++54M{{II<s9Z>DGGb("bt]?$%HHMM4oaZB0:i<~H$PVV{tAl`?k,kiiiBJJ F8ITV`~hmmmF0@~(e#ldeeAD@ɤ̍Y[.DQb1Ť6Jۍx(@(\.SYYӧ-]tZtH< e<''gtaaXY$gffS]*2%lg7sh2_eB pM0nj5XN̡iBͤF(&Ij[[[>K7"OKK;dp眘C0םL t`ɲ  ӉZ=3D5&s ;0!8^;N)=== Goδ^$Isu]G{{{BmZ=lS][Ur20؇79㜛EŽt3S9F?]KYb,1\.S#(v}ׇ~k} N @!H!RUU%~ߚҕ fGdk88*)))k̡Ձ14?[d-|f=Ƙ'ڵkСC[-g" 4\n0jp_[%b8?xiK2N,'&qaT]cs.D4iizsΝ[@rss/_v^/qp8e9nU5@)MdivɱkdetwX.eo7c@Gbt/I&_zYJJx5.vg>\`T&v|[NE対Jnzt^PP|ϗNB&aV_*'+9&Y&NTUEVVપWcX4pZt xMMMW^WHII %%%$'''Gbf~7͂9\3mrw t؇oVbߓ]dOj5Bb(=%%]UUU+Ztࠔ.u}bNNNr(++À8yUV*YZcnx;OU{L6ڟՖXb:1!DE᠀T `Oj(B1CdvH]*dD%DսGw&5hf!˕tkI}7/RG#&Ϛv8| Km۶ᐲ0j(@9&N~&xvwHdJF~2jfR(BBf$+BdP((^޼ |„ kaY?3:j(I8s1:f?BrA2k‰D{9 fҜ6WEኢUUy,cHu BFp8ۋ^tE/**2I`ĉM2:Jz!Cy޽7óU8fֲLOX'*'{=v-LXV5Mfp]׹1Z"@4m0` ~"8CD@}я~^eeemw)1޼H޹}`gzw?{=+cW}=Ƒ;lnnF8~%3 N4L𲲲SRR,˪ ۝8Sa7N}Xeu>̙%S=OŇ9x`Y҂+W\`oq 8Q0BHȑ#1ބtA$uzbzdd5ӨxBޝ9꩝|b2hy$h$IxHMMszKN}Ȑ!}>_,˚233c}O69Oj'KI֩N47ɪ^CBUCYMmnz Mp8 СCc555X`vm=8/z0w\̩O&eiyKJC;Ⱥ!Tz1tDQ ,D$.Iꒊc;w|߮_)8'js.r"fgw !bh&V X>35njN' LHO@IՉ RJ:;;šC۷oiÆ ߜ;p@Ñg80t)bqo}V &(>x"9G؞dͬ)i Xb\ycfzf̘QR O@)9J[[[`9)dNlځ& 4H b5nv`&p2I2NT~oH0$Is$ID._r :TAxIڣ$*vUnJ}Y5j?9@axћfI&vMc>1RȲ̇ v~|=z! Sn7u+B<qg2&IiR+f-;ZFlw=&~]OfZGw%n:9;;`Wt8p`WSSS4##a$1 y i'v[;*f<@H̲$`Wf' ӓ|[{kLp}A)%xxmxhPUUUUIIɨh4c qn } "'VrMӈu9ۿ[fY&j{n3dm־05i;KFis?'tlr󶶶# =7OQ:8)]]]h4l!f =|Qvošl(k{g\vd?"Fz,˖-[Y__ c,Ez Lq߿t3hРlEQtX 3ߪ O7; .7o7ۓMw|wdY쎡vؙQ6a+b6oU yq=A0 @%rQ,V]׉nw8 )V2jc7II`G ;d$V3LݐH$cdG.]W1Jr\ї88:A۷o~$h4ʌ4%TU%֝-ܓdΞOnefo Z' +{Rɘo.uCF{fj(<P(*Kify@:O$ZD) VUUUq8iiib4x.GQ27dN] A`{Ow}ak$DF']yݕim)@HA#[n .X]׃Ji5"G6nܸ]uJeBi& #D"(z1%SvOxaBaURoU4u $@7F}=D"¼y;pWF!BHsi8FݜB(B0A!hmm=PYYeƍkkkLQ1`QTu1:D"x} u%@nRo]i$ g2o-;O$AOf!,4p"{>裿"> SJÆ88I J)Ut]" !Nnݺu )ii>xܢ(JZVVVܷo_BaqBG Z=pcN=]ZEQ4̲TUEٝY+ivvfaJI k׮ ,Xoc6sĐM t]!UJhB8A02 G7XC&knUUt]8ǖDy2ޔ|b^Xݻ~f3ngy\UUbPaÆ>H$rpbTBpsVbFDQ@@ Άs.qzv0{MBM6}5t@  Hj3תRڃL8{0cXmsHu]2f^DUUs/L g+(  Gf09u]XbEӼy^j`L^=Bפ 5 vU߰u͌u@IIxHQKZo&'"ָPMΤ @3iҤk.±>Rf, :&`=XcUaSbdnm2]j0I㍦pp\p\̪-$`n 5kzu333sfeee^p$QMh4vtt몫k"H3'v:(XqGp2 #|x^C[׺k+Nw;钹<!f?tҤIKKKx^̘oHAmI)4kBV4yMkp\,syI{O\.Wbk;pMѬ0!s?^jժb(S#)cXL5hFDBhxQaĥr"8'W_ M-Tt2{8L)U9"j3 x(:cL7:Cqb X ֬YSjժ:::!cFwpe#'*Q߇BB7I1QD\ !Q IDAT\=I 缷jKlpJ}}K+.8\4$@ f0,RJ=1n!@7!)s@|>_AJ<_~).+ښ) KpԱ45H/%++kC=￿v[ !ys̐ !⎠8RQ}ٹYiv$ RcXLD"J0 uĩO% .!P-uvҽ^ouI$麮uuu@g{{{(~ĥSj3GG&SUS3&G[5%?{Np(wdӽ}cpHC2+z{Wvwy#;t]ojkf"O<4556558:0 >IMLP+q D9 pn:!p~ C6C60*@q%v 9)<sʛmc/'ee¢jnkV&:% TWW?F*\f̘Xeeӧeɒ%oy7u! 0̈QFѪ1q"X3 n0݌Uh!J {M8eddZ Ѝ f(;8(o4,v Gq7m(-bt}3o+[^{;H׺HX x:8gQKM򶷷z1D"?ݴi\1.''-[TF"PJ6QaN!ڢl2c8!<@H1֋& Oؽ{Q URUM+Q~ě2ẩ=p?WQ JQ8QO <)̛HP ib HմȎo6'EzB$}yͩ"77wfuul}?*˲1A)us Gcc IN24O0_yVMy`8 o(V ;zi M;?g}#p{/ k rp+Q6!$F)qƘ ^'|z*@~h!@XT@k]+撒qhtW_}k7pù]tW\q؊nQF]c=2v17o-psͨZGr]w^?$ MGV~6`z)z–s @V7='ImAb#Ua(1BHs *J) nsH鿜2;="9{uI.$;󖊊?O׷Huuu§~gҤIp̘C-^r&LpݺuxTTTfY iEv]=':`N8% ܊xG 81 p moͥSFD#AvG o^N(ء"a" R\~qiS"t+K6mz#\hmmmp8;tP .ȫwuuiǵjժ}o?`ӓO>??OxС:y<ܚؓlmՖ?o * \tJD 65gQq]'Kv!D Vr=E1= ,KU׬Y3j̙o.IOOϽ?+..8~Dgձ@x&MoĈi󈪪/Kwq~ii\SS綴cǎ??/ 80{Ƀkkkq(]2"Bg@qw9eRyssǜ?ڝ.^̦)S6k; u \R8:!D#pMZ_z2bh:KWggg?vQ_$閛nnh]]7g33Jgۿ-[~&OMXQQm'xp8!C_|^qeO:{ǫW?y\oJJE)++sUTTt_x^[g͚5q̘1۵kW ]w8oJɀRZzc)J!ԧOŇ/c}Nlݺ?c]9998?(>!) F`2۷!TAAAF~~~bqcڦMj:kiii8qPM;m-  طoozݏ='_}sȱX_}/7557oW\Leeg(jVR n`w#B˞BT^~!9%%媝;wNt:#TUI))'ۍ춚VWW7x׮]gggHOO' =zt{cccgkk묔<uu;UVhuvdᄏ+##{Ι3vYqaC !t]g)))Œ3>MIIAyyz?rܑ}l>^6S;^~jjjؓO>7"ph_-FXLC;pKnNⳍ}FgٷH{<A&I@ gϞM (̤%D[#F 455@wss>s.OMMeYؿѣGw:Xnݮoq^)??wyZZZԁ:ͬ#A$Ip:.ϟ_3cl-Тz-Z7xoc_1_( 4TJG36~p锲[䧩JSӝ [Y@y<Oqq1;rH.IY~;,4hĬqae_~?ի')#yhw͝;wc,ww@˅Νtƍ[u]7?Diի^{U[ls=:|Ammm^aԤn;x^G!A)3"fv?9q΃+<F)u}7cZh4ڠ3o:&:e_,[3gLUt:?]ƍ+&IDI(~敕eegg|ͺlQs 2gΜ?l޼jхRMMMۃ>#GoW/yR \={﫪^o .nٲ%m۶oVsApȲ,ހ+8Ã|7;(͒$UfQc8.ĝYo^ yioA[] d͚5X,n71A {nذ!y-5 ǐin;%k/¬ ߋ/7XAI7=QsD3(5Gѩ]|7>!##֥N3roFFFιkkp}2I2&]Y>Prܺjb/*u]7'---k׮]wmɓ'g466{ ]tEi< Yf-YxWU1V +WDQLg aC)\fz@ ՜Xz"A(iT{9iq[48d[?'B'vttd| [nQqq1 ͢(FC6k`8e9NaR1y_[ nB<"~(NgYfffZYY766>=(׿U%%%dCAh!ii'b81BHPP2!B)mB\xT Rش@ &D^|_dddpÇ-##Ɖ NA.TP"sB2G]c-esYvv6/s9眓SYYׯ?녅۷7b1.Cd}&"11+Hi4ǯt] x} @u]w!6 41۽{vY7%%xСƍgMpXݿNAR92駟~߼4)'ΑwTۀH |c`k۶myww>y䑻.K/IM PJ2Wɞ߃n(Yƺ04W9'J0'B.4}v1*//OmkkS6lذGDjSm):!l]׋W90nLNEhA]p}?2BBψ98yҥK_x߿iSO=ƍ>={_h6N,(];̷JTύ|8cϞ=_(--}>DLӴ(~ιs3ҍ̕^GhVUՏ8d&833۶mLCgN%I)9/朧 :z!uuuu0ӹ4 c$@]]]i]]SCܽUUUzI{6;;;2eȑpb~梔f22gJQ)!añuK5 |޽W)2ry[ZZ?C) u}؈# -pv.X|{xt]|7g G%f,iib|(B^g"ڪ-eee E9#ZWW~H?:euh#tc*Z3Ql&#33󎦦شiHo޼˗p8dT"] 6J:HiJA ޞSQQ1q,] 07nƘ1Q 0aBahټ2&ć{l l\pO>b:;;]]]Æ ^^^>)33Sg=u:VAb)whsGxuuu%%%7ڵkG]UZZ:wީ,)) w5jTyydYnΝm۶Ғ{#f fzc>hG߾}|嗏 4={hiiiwmڴLII~u+V>qƟ (TTUmN:QkA.]vժ(߿ҦM~L 8`ܸqw9rȑ#3 .|F1>G)pνbŊ[<ϢAFg"Mnj{Ś5L_vۈzg-Z^yy˗/?PRRoBG4MKKKܸq?|IZZڋjN]u]4mt]ߏLXN !۷oSO=5kҤI?tѢEJ~Wy睜6 IDATwܹPVV-)))80uԻnjs3!$ƌ?D"+ $ 1ՄI??3Nwg{Lc]@@饗*EEEkG}?x@JJ6_B֕'r\w߳+W<9p5j2Y/~g̘n~~MMMM|ժU/i7 Q= .lʵs"X|/`0kkkÇcCi7oVvikk~i;S#?p'e7L4=rh/eP@ }GTWW-\pٳ3O?uo*--M3fеk.Aqqׯq[}:*w~kG@H;̹u~5G xIF>#?XL2eА!Cٳ'#lذ/llnn\1cƔ?;@?e]QVnj}Bgf[޽{/6mgG170133fs5Mӫk׮G"9{U|y˖-ܬO6q}o+;;[ڱcǾk3g|]Qo.=? :ҳHARpzyu9p7+***׬Y󳚚ƍGW?~|n~~o߾'|pcǎUF)22(ǥ+tglх1J^q0#BW>&e˖U>N6s.䒬niT~~~Q(KNSk)lݺ?ڽ{7UUUq p?m%-Kq$;KW,Ei_^x%EEECo޶bŊ /pՊ(455չs΀(nxaŕgϾtZjKxeti/C?ڃvq}۷.D;v566}>ݩp]b޲EO'&,# sbR I|KȩE-_'K9Bu޷UuM;^pcxL<= ,̅˲l[u]/4MӸx♃\~}dfgg+`0{'&&|$89>핕'nƬW%2 A!& !sV8d-IRP$ d`)K$YY13 qqMbVVݻ>}P(LZZZcLeuJ+$mZB*rg2a 2vqBHs9g1%H:ԉ׽KG@x0=tPJ=?z-TUui6m|ҥ+**.u[CR tl8#XF%zثieY5 ca IDATxyWu/[::HdIX'#'@y $/k]!${3 71sB3ƃ !YeK,Yu>Ǫ{?Wiwlc^rN]Zƽݿ6QG:Ϯ?=ztرckͭj++ʘC]Z\.w|ʕ ?W0jkC zwuvСC8qA \3'1`fhJ(˝755ݲe˃ׯ?\cQi߱cǹwuO?oT*is#<8"AD=: `3܋1Q! Ch~uxx͛7t%?۶m{ۏ#3uO?ws<577w 3S.C68Zkǁ8<}r]7!\?"nۈZ'|fRJiUh6 `ʕ߻ mo{ۍ?*$o;޽gϞa8fff""y,r~v0::J)6Ƹ|YgaddEz:~ib ،6@b{פsfdčtĞ{챷ooy1=1?_nqvZ>3)P^]ߏi/fKHH}7zE-&q' FQc \ץl6KZk1l6k9rfkN^TQ2 {S8+_uU7aR)Z{M6U8Ih9la9%6ݗmqc񻮛Hi= ߌ1M!"qJkMB!/C}/QoBl8wxuX1^X:GFFȶD+\Z!lBR 6m`k^ 8=u]r]6mU(Fqޥ^z"QRpر-[fffV3lF)qKR;W 'owAB!""T*MP(Ȗ.k[61iw϶HE"[ڣ4s(:1fV+AV|\Vr}sWE?l#Y۷ݻ7MW)@D_ऄd`1QL&s(f"ba%-Ml~6H6f${\v>I~Ad%@Dr Șc4Ma$ FAJ)VJަM>]$W~'?ZIxuy>|߇8$:VkQ%~rEJk8v hrrSSSpZDFQ@ǁ^H0̌ n@iކliDm8nEI5&A)l6n `̌w9g7B? H!"D&R@ԝ)10 V^s! @P͛1>>HNJ|@ص!oZ*H{v~&HdR%{y|26G6M'vnyqq04qE޲ek?܋6~=z>/9rʱ1AZv-&''Q*Ȟ|я6tZ-,..bnnJV zabݺu83ɒfr:L vlqꦘ 61<L&a@A3m?(8j6ڙ>q ?O0K(駟vWo?orr2|xwǙRƍ.B.v}J<==2)iѣGQViA&u],..&uZtFVEz"}ORAV;EƠr/cO<\A/QkMS//_9~xCſ Z~ۼy3_pk_xDm#KIudPհavvӘ,jbeY7T+F^ tɘ..nl<@q6Q C3"DRR=r7n۶=ϣv}n|./,,`ii Ƙ@"X,bXbEO Fa0 h4Jz0V±c@DĊ+ۆI HEqB=a3Bwlbr 11*c=11o Jɷ-y^&њ5k~zcܛTIbt/M|R=99͛7cxx\.\.'_zEdY$xcK -]Ah Bm_u]a<K*E`1j|||jϞ=p:" .ઍ7l&bٲe |ߧ>>+6c$AD: ,6n܈5k$4CچT-͢\.X,&.vD\EPH!8NbkJMGt͠*Kl"s"#y{>m~Ǯ*f6rylZA2@^zGFFFd2իW'_Z i70tˣK@Bccc=Rd.I:Z*~ҧannZkJ~P"ж - AVJQ.#q)JK)) @M###w15223p;et`C%8bӦM(I'EhQҩ\[jq u]7??5{r@?WJ%o "y;Bix$vTVf{ֳyN|_n#xbb\.WE+d(v[%fI,|qn:J)ó"vyF S6hroaaJ)hu]J%8%HoF#2lٶ (Ja}G.Kr6Smcql;w_c 000.%is=iW'Xv~~||81D"PL_z{tJqbd(]\FF.K R.bϳI\"-$6sILBn' .H ifǓ1׭[;w~}~(tOhۼo>ؖ2`9∴-.9<$!+m%_oCbulIf%Mk1c8qp]'NH+ s]|>AtPف$aaHn۶3u]^*., #/ . J)vDrd`vqd^BZZ0CCCd2I@Gb v=tX7Z\\DR00L\R}032L*1}K*s!>0S-0jۗv_~kGR/ PL.[}eƍ:˹Br$.-vvm8 vqJ$/m #fZVBty3LigiIOVyLm I(i :{됊 >_P̅^kʕ+'l6K\.4 h A 䯝 =OM F[MEQRgH"h)]$Dȉa& ҿ}j1 ˿w=99f2Uzm޼֔e(Ձm祉Av:bYni^l 0??FrYȶ"ݒpfw5wPlaήHQ֚FEMy~^෿I<9Ԗ-[XJgA:\{z=q$(b=y prYGWtHy@R<*()yK3Q{ Z dz'?!LU* `޽1s N.֮]lٲ1OSV]דB'LY~yB>G&߶:?1%rJ i`1$شj%ޅ̜ qX}jsp&좋.)tnʎpr7(rD6Y\S}EEbUM4 <3իy)FBIHGQ Pj')vP8dZߗg2^z5 IzhZXZZb#rıC k3yZ-TU۷k׮E.;]l I #HD'c$v:q]08\.7D.O3}bժU?qT'@yp!j@y97v?d,'#~nvZ~MKjR+._ZŁpg&^r?4KRH5Nv )!"ʣC|[B0躮Pd.M4zb,'~7` @?Kۏi¦گ?ۅ^$tqqĆ J?v}HN K!lS2]u9\.7.u!=lbjdRODJ¦9_s|!~o&cCr%pD+gub bS=)9"C9f *Ö~hя=F(.54A -ҒF%B d$ ų,}ٞg9GZEVK;l6х.].9sl{oRJQa٬𘹇t_pj*,=&{"$kN7f*-~fD_O7ӵ~s{ HR`ʕ=*n?[* /I+A)r|<R M"&=A+v]bف$!,cH6ƨFQѹzd3Fwvv֚PvMl6ގC'{_ԧL~t:HBc43C~ْlo%'gA;*(ܯD;u8n=s @O(ϻ,O2vA=$ ,viO2Wb/ =A|F#mrݯߴ^tJr'yvN x*ae63tnaT tѣQZFRuj՚%{Igۙ~E29if6~ރsI|?c}N66$j!j;`;$cB愈(n7==}'[60 >zW]΋lOpzMrPoSZelL/a9&H/ K3B?GI3U밥5N6D :B{ u]ߵXwW1RAa@'ѣǺuZ;R\.+J39l9W"]0IlU emصǗGZͤs<$_wgLa+r[ˤ~KCяtx> IDATE~߹˩D9DmbR1,hϋ̫Rfw盃 `"Ra|i~n$pE!VcÇkRծ F c&B믿9rū_׎d(cõ-Y2OY='|_>&}:/e[v&x~lf(J@a^;VbL'(ޟ633ݻAu"Z&nccL%|'Bw}ݾ{]|+/9+ u>-buÎJ)Juv5FL`vG];/r:G =،VjA`hhf)edrDZj'|xBfn `A)fNBDSJ傠8p;w|СCǫjEUNVQQ8^-wghDٻJ#T?I؇}mNvöe740'Tj%[(jMX@V޽{IDRj]z hwQ%OĊ[hVU߽{Cw~@T* JRX,;cVXꬳ: d2NN @{wiuB|@A$f=v@C~4ʲV'N  '=Y "#̷k8F"c ;Q!ڰHWkR1}0SOzziCDٮěZVj8f* `hhEaf#T>픬-cSX@[ZҒ`6؆gZ;~8000%#׊d-`ϙ]s(^VEnRJ8pwvcBtWI4t& 6w'>+pWNٛ' ErdR9cL0===qsMgKBNi4tKb3Y|aGv CZ&/wP&UZlZkuM7]7;;Kcp +7_~Na{V.>z7n=(X),X3jsk֬٢rМ$3 4>퀓rj#Gvp+lk^cffGA.`B!!t >a2:p[nY=*~rchD[_Z;HpB4*c(+Bpΐ2hԮ⊟NDS&a@jzU&^$R&+qeN[ZeQR~$سgjZ"X,&ɵtAEŤWo/-}Q[R!ęhlHh0sKֺi`k>{k.1jQOF+gE k ڣȼ @W|":5f(ĉϜ{ʭV>r]a`Qi)bKKKIlV\.Yca3fƁy  "fffzl ۀxu)ٖ# J0000y׭1FUDvHE huz艧zA"2 32՟6~/ԗcnijGfue^.)0Uo>0(0338x;?gu_|bbb*+c:[ww'[ .e\ qeiBFCCC(~v2?Ƴ>fLvQu + ;+0 Q(zDP.Q*Vy^ ʹqsn1jZx7@ MTSkώ}.. Z31{9ОV^1QEK;K >GU7pW6>yOVcǎر+VjժSSSkFGGGb>:]HB.vFU՞&RR$].Q. +0Lh44ku[48J%RBle)yDE}udR hDwSl6<[om~~i" l;{`5P}Ww?{@w*]sYk^ ߹^sa3Dt2RLJD4R(FJ ^^,ݚveauE]ׅ"CzrXbIEvܐ4Q%kZ!|l[* hhNj֮BB|RA6T幤F>6 jRyGۿO14qX!C?+w+{8Nc솊(gw.]dL;|sx c0 {]gfnJ^o,,,͛7R5` el;"9D"ht"8.".TpkE9]bfK  , x&8H0ƻn_QJy_ 55cL@P‡ .@Qgrۀ!q #': bFP|Bg W/יɎy=x@` PP9<"ʆa8}ĉ7bGQ7݉#Z!:U19og" OPۚ(@)a Poc /bP˶> LZŸ[P,L3,OnyEXLBfŒb S(n9 C nWz}R%5uqpw e-i*>i=$j%ib=KdjjKL>p aaLYk@T ni̞Z2gPe9d2.@&qɖ#xi|BE. Jh:VӠ2!aD05ډWl>ވ\L8ڀHXt8y)IBʹ_:YQA'{K}}߽n'WJ1f@52 i;ɟ|0Ic~ts`0 PO +֟QMkw%h~qJ@jE'xZ1ѿlgJ.䲌b#7π+ fq0GFZ&ҘԔn{'H}.NW80 jl6n߾۷HDdYBGǩuӾLEzgL/3PÃX8+՛@Ql89Vރw?&f Wm0h: 6#~9ҌFx[u434!iD6WF6ӂvbʾbfYaAŖ{K?3/*P0h?x\Cqhq 8:fd2Yd3;x5.B+.C *  4o;Ĉ RqL[/~?F&glzy3ݪr t :Z)4Z !*_Wn71;?ﴠ~l&Tg{\#׽|LgN3ʧACE[@` }2W]}t2\ V…i?&dar7õZxܹgpoX":w[y2r>]ïc(|P"&0*:~ _O(;8o{x@A،)HDTeF%/ 8LN)ɤ &Xf<6t1B!l"oW0`^y1 H|XNg_vઃp P,<arl=`fQ]R#xNC;shG섏 7\y]s55.+*J1洆\=w#V芡$L``ʂz3v֚萙6^_:mizΜ唆_X0jjXM!2 4nնg=28^sg\'}(_š;HKx D |ZN `(r0_M98dT]BM; A0ζ^D%kGYTnZjll6u]>n71+,Q='$ i gbX-Q^@ob'68<n~76㌒V5dۯ".SLChBF\ysh C9=uH0DG6C6y_W*2-~'PăO P(02y`5sػ*Mc0_yYL) (sB,sf[)3Z@ Gg<,+Yr()`R l4b`j |TkO0qGM5}e(\ `NQxWѵX<( BtI6BVEݚ~MDNѵ^{ӽΟ]#9tA`4@dA"piu]ҊLvbg]gn=O9^xA\'DWʁ|;Fs{&1,:dm] $-'@Sڧ; ߹g O*#,:RZuM4t"|h ]D=}R"A:thꫯ{^7bIɟEGu ޷Mc Xe@J`EV' f4,0n}{uoraww_ЏI`-kq!( n!Pl0X9@c_}kǂ!wgf |l1: ]pÈ"ύ3PNt?b(Ϲ{gUm('wҗ'*{E18`׷(wBy'C΢$(\qLqsn ð͝&~}RϧP&Hv9?ϼ#yf4W>7 U**&M7^Uk4n}]wW|mdx62̭{ExEr.\6V.ACx3?O;pmo{^K^wTQxҸ;Vߛc;3;nE< [#3.FbI,APJ%7#y7A^O HDk/ CZ"r\u*JqwUTE'!Lgg ؾzK]x `Y!Բ~]OqIM2RghYw{O47pjO'򺻔 (L_;'໋[R},=gH9nI\VLcL>}d2N4M}gݻo׮]?~ OD>:)pɄ_"R iw:UŸLma7/nkP`F^qˁ}ۿ8zKppΦWФ |,:t]o[ɜuTTE/reǎS=nQ g Yt,ʊ?q6<7zHgxP]w_`E&6"Xw3'%A3y|#?̊W._NJ;®O}w]CTxqظ1jpqS%]E~coW+7T b&:N8V UժjuqaaaR,4NO\T#fnZ.nBit_2O4(mb4Zs!7"2E%t݁0mxeE[;wGaFJك-N`l@av "eZy/V<ּƟh9@8?t B_ݭ~RT'HafGXN^X)F6HJ[ 'u(o51m܃ApWIDATn6/{o(x7zT ](44oIr]&qڗ1nUvu'9#ܾCsqֆ%"?B'+;ŷ !t&?͹vvqy":({/kzV*WkLA8@ #J8GgyтQ#K2-f^bt,t l!qR3Z녮<<ȅjq;63NHL\[7+0r`LLt(zrDZ܃BcXB3wa nWcC#r#ĎPR!10O4W_ZqN9fZGgB T tm߽-#+s9vrAqqǜx GD`ffL1:H)/G@D-TKk6No pdǟ+o|{׌eh\r~}k FKZ=B_z(Fuh)f+i _{ߍeWhaUA R`)9j:﷟o}_ZEݣc"܀uP^{k §1p?~0B"4!6TJDhfF[_=k5OzTkv"z֗yݦϗz&nŮ:,_"#k}U1 -1&3Ł0pa~YqTu8ak7<1GQ]k=rMw#8ేÏe?yq \”;X`ʟ욽uöO]8MKv K(2o{Uuwfy䡄U(Wu|MjmkmvJuԱjZZkU|RD" <ݼ6d{=􏻫7!J|~f2=^s\3L4l:B"TE{oU?Ό4d kg -N5Hj-)eM\WǤٰg"1iNu55,%1 ",X_*ىߘ5>6H&JӀ0^8P3;a?\Jt#|)ۯ TTg +Y&&~8&43:ky䛙1FJL0m\thiVL\be;U1Z8NPp '=c $< ӭԭiO0RRUbeƻu~UmZ{L 񪧖7 ѩD|'Gν/;v'{ZROjQDy&Vdց ww< _*̉qֈn|CIX.xOw=L G*E)Մ}W9-aIyZttgS;Q "Я_ޛ*}hθ"0LC_x}ꔲ+].Q 3 d_F/\P [42Zh5F{RژN#"љ1|ܛ햍^A~8(\ގg^]٩`VbJJFn6ӒU/Iz6&hJJ4T޷@>)e Mn)#c5m<-+NOc37J)}zs@P_S8)xNv`'^gSTҐ-$EzNSHV&!RK,*񅭛>1WiɲYp|9o:(2kxⲭE`$*.fnTJ5bxu3"0>ߓG}kuτe 1Ts!1ʙ Nkqwtܔ|iC ʎln!@q+73GE/o@[F3{!mcW@ϛ #ǹF@m+dm%z;H7%j{ɹ3tdHdX݋n"H[>Fi֣7ܨOՔ|ts@/5;KwBmb)bWԳgF{wT5=nfaZL$f.Q(k^\}L-Zv8eTcډo^3ڐ4h˥+ŧ(P mB/g9d9P0u(RcT+kKVTnYBDɋj;rGgw,$Ku  F4JZ';B⼉d&~ A_s55aߚ,D/kҼ*&F}>p*SMs[W7֨mH)1&fҸ5kWZ5 ] wMe֝< D m^WW(u_(7ݦ{=ha74$m{2k#̞}w hRb?B{(2a {)VwL:~v)'b\.MOOX3%+@8G{ Y~oֈ0QR N'\̨"jVZQ׮۞?`M .^u E+֛%4:kv#3c$@0!YZSƂqOOشXu]rki'uwo׷~YoƵ"y8=bU}ɆOPXD,_y]jdfYSIheckj|rG0)R/CcDؐ A~yW|_0uΜY8z-W,UdT61 ֢ )ϝ=ٖc&HWH)iJ; $iGi< PR K)W\{ iwCYm>:>:6?020$c%JkeBHkjZ!m=W_QoY Q޶*{ͭ`1s?^ Bc^!mDc9#,-%@ރϟ.Vt0ʶ:kW X9Mu2"@DqWzrYz%c2Z+K9W;{#nѬ@|Y~5M޹s|9KўXy71FJdzzhE7nnrye[-]vǓDIYw`kЩ nVR [. Cz?`o|]t3,3۲qqǾRRa$ZKi0tn-`pӨ2 _[w'+i{Ϸ+̑f2R1kRBa:FDG9!Fz  2dm~? 1[HBSJ;([|-/2xE[wJgʹIENDB`ukui-screensaver/src/assets/weather/66.png0000644000175000017500000006604414205074704017477 0ustar fengfengPNG  IHDR>a IDATxwŕyrF9$D0`km]:c#dL4 d$I43t熾UuΕ66\_IuK?vFD5`0D@.썃(~uJM[^N>l#}z& [5Kמ. X >03z0`6tx_< cP!| S|6^pee)k@-wMvAb=T*{x^V_P;j{Eo}꺧mϝr^# r"  ~4%B)GHdT|'AP"Xyw @g}v(g2y~rؖh?Dp;/<󪨲U\Vȱcɑ6+ 03k36Fþi Z`@q@H}c7F3> +gþa#6J) O[, "|92\aEm˲XI} eBQԢ|c_iD !@ k ˒ X>|e'b Az8Xkmp$"eI`Yima1l1J1JѾbBzv$vuYWs㺞q w}2L}_+ˉΘF;1xf6Ckac`lf+L|x̜LJJ%F OcH$0|4lTp˒عc+ld2==T0 u `ƕJEMgDjz;S"`0'CUCucAFi7הּ*+,q<˶V &~ %ƷƕkG}G)m _[^ݷ*s6[)xkʰRa(&W'rJ>lqwk?uJ]khB-M.T}'y!!Q021V,K|"^۬T*2f;;D1 <EBhfCL"0S+ (0 / " 0[8qF.M0b8 |ΎtsSSm=&5ҁ6 ]iF:qLD[p4aB `Ske4QX2e2D?=SG&M^ )9ukp3wɹ(#§bͳŔ#r0fYv?V˖/knKgR,)%n(TGJ,^{Yڭ3:uѨ淬>12Ͼ]YGK!2Z[xū|%A,f#_W޴ozbj{!Y&zE8_JBs/(<јߏa۶XeIՌ; @gg'@:q{v,|Eƌif)% m=0,RJH)IZ^>OI5[dijN˳OB;"/ܩ{ѡX~/6lM[:R{mRݝQaذ1KR1N$"LF9 #;9G&cyמh/9{9}иa[zzs+*b5ڴm@4VV4qvߵ~%?rNX, _>3h*0tr 0 %|@G?3 DE֮>1 ׁc"$'D6I=, {wAU, "A(j[{s_wK .Mi*p&Sƨm[y]; n|Rݝd4cÆ@`Шd, !`"b*޳,I<͚wP:f>};&Zj[$S<><>d͒C?sW3-xEDq]_x8;Շ=7e_ycqPۭ<D:bb/m+~pYiqضL5:)u-'_sڈ_2.\r;ﺜ6DlGYd>}M#,d)aɂ@EZM]EGM44a ra[ۉq}}x晵%O<oy Id2 "_"`Ĥ l2l JȾ9fe _ТEHD83g?USWydjЩ a&Bi~%}'.G~V@@P3q]$&O֬AsJyd%0bX5m_]pT03uvf`c<AE0PF*%x)??yqs9f6O=Y?Uش͎cl qS4':CLL( dCĤTmKJUĐrsͽ?{oeIVJ+!oWlUkY;Ѿ$AjIC)~8 J`H%+8[Q˖m+)bkF olށ;\ݻwV3ϜȎch޷o'5M Xb{D 6SN<OgN 5ݭ{,'bv!#$>II]yD$Awփ6G,|.=/o-/eI#@OOdzd,U6 8%–i(|V@鄂GhЂ-3 Q--^\n*jG?RpIcsRUUDD= °DmYqA@2d @OY{O=[! tBet G|3%ˀ0HNǛ\d2t² H1Jىdz豓_zṵ̐Rp{{ٰ~/H*33.HT%zV0%TB O/)}@:@0K->^j7t G{YصO`Պѣpg]Cjn=,@U" 0gwq)=JN0u~/T`4?KNr2 -bi VDL2_nȜs` ѳi>ttus<-@P@H c2b(lh1xYðB!!0 Pɦ/Nu æ((ӌn#F߄[Ϝ9Cis;/^;҄S&bx8p ÆՁʫ?tj5r!#aE9y;.M;6sY1ұ3C_ϟ…O:AGQI ,k""RʀG67'h+8=]- qs/ʾȶ-z ʆna 퀠`#1I,lE" ƏQ'TK@<*P ?EvvYB'8aҌ ً$ c'߂Ø`‹ǍBA#GW2hu ߒpw"{3Ғ nNzK82ܡi 24utfFee^~TjaIA)G1R`sT}MD<߶bT=~7" D"Z`@ː"4"kZ)( |$(=eN`FÀt~~ ;D=J6FN924z eK7#a==y~5DTǍ2>%$.o`#h}u$ BMg4yi_v/S+gp (M\%(XRb.xR Dcb'@ڵ=uCwi"8B\8ADEe@>\L< ˢ@hDxi%6`GadV'| Bl{bٲF=R7GYDB,ZaP;!mbX `ۖZlY"l܈XHQ˒}AE}Eeb S>-}U!\(&Ͷk۶DA"d*ʉd1g?q,k{y >H !J@v:}/zKA.0?7`O + *"+O; ?㝵PS^1rqlD64~D<=mDl4FLvawyl f ;o LK{wtd`&"2R٬s_{\0=_.b`^ڻ7m$-QT0J鴋;df<fH9`ˆM^y#$ D^M{w7W,s'*Jiڄ8`.  @i/V9ARt.j43ZR:'~X L@N X%j7*x䈯É$䈨Nx$, 2 6nx;O }"d!Ú6HBk&m !!L`bi =, |垪8faXA0+iPo=f?$p}_C)$e :j',7ZYХIkDmSEG $ AF0rD`J`{E0D˶HD굁cH#œ@Ifds6qM`8~8 I0E*y6Qøn`#,ba \1Ӥ[8!jVX Xi՚#Θ.g],-Eq\=E&ߛ#gs;=@e]K˖$<1v}\6\׹W:9O]_kJ: 1IsՉp+hБ}&=?8i렩_f^ݜ ²w )O )>hXy;bc4 2T˚lH-e堆h;0y|ܶזWhOEd{%_|t65*Xi0hz/K(Yu,̅%łhtwKDd6LR0lDv9sH WY" %fٰ11L\(jM&۫BABV&Hdd Y6R80|(@\"03$8A1ED> <PZiSO OB oO"fc礔ʮI-}/>E-+GLGژmv[ I㛷﹧#E*USoO(B!=k2 >*"yC `t؀"VQ **^+-m+[t/ E h@xe }.slN$+8g1c¡^.H:)ܷZ;]Ix@!P1 FpF~"261f<.;"A+>%PT,lY-*ԡ`).C8(\QTȔQ|PBH|O}?iB"2I^NڬY+ɨEG4}z+ކ;n禕-MM‰YM&R*/M Ϻ@@j 0t?s̢Z#GI/}iu; * =*n[5hMPaٺ]hצ+[_uӚRQLlo${#֋ӫAn_TS4DM~@Ҷyk+vf9vd2ջc?0&KĽ{6Jhm'F?U\_{lV'7θ!sx;95GABAJgQ_'}}"Ic?VgRymf "  ؟هrY>WǾwC#s5p<g4:ykUZ+j;oG}Rʄ}9vANDd@H&x/ܡtl0h4*B[4>PLp`&#+ #_p]]4O?a]/e/9u;\a+UJoQ+|!Nea|Pe!P2*79@q`C)oo7 }nE# IDATWUUvOJu׭HbذK.tv}}{꫇1jf[WyJ šE+oAoUl0*rm9خ`&pnyB)euѵw^˧=xo;toz[ҢM$z՘ʬc=3$E `PC:V jj6 m+C@3/ _QeQjΜ/6w++lMYuJ&ԙa(mFQpclVy֠Q/@?O@]sx:aÒ:IC&-ZԾ䩧v/t][Ov#&Ww,; έذm'* ?Qᒤ +|WO6z-[̉O}i'6Lg',x+*nw^u}EES(ںҰOQ֜͓֨O6/gz{}kd)4=ztjĖ-?[;R),X0%@V,i!~u 1bdM I)T23u9못!b"}/n7"-bkMV;1ѿcՋ/.uo"aOw +%l{3/ٺ~M-tzw09[u1Z#Q+߂C0+Gx=TzZ_}H'6cw[_xuڵ=Q[ LQKxkyZ;=< +8T^2Do1sn:kܬ/-G >q!P*f6da#FE&ON$jmE+^}}U:R)[ez1LI8kvbh=heB_5oy>N"d^ԉFE&nf;1_yC[%?ŋ;V_߻=dRϟC0k$n}Z#/+nj{-YuKl֯n`[QQ$ζ.dak!R2XVZq@ iYŽDN8uuj;JDzЌ"ϥiu+qT>Y_Tk@$(۲Q?y</Q]\,X0 Y{꫗EaXLV64D"Ne4*lY(eR 2lflPDPDe[q$"ɶ %2؄2>"&H;N,&#Ѩ8R"iN{Ec|Ra?MQb" }wɕV_Uo 7^~ +Zgl O,O@pzYLXUo2$ѿ>R8" (4 b(eX)6ZQZ)1t"gbض`@&iYBHI$ 0U{[!u{n홶^gԐyQ:챡ڑVK 5^K:eдË۟p]eo6Z̜Y7a߼vmDBXQV8?r_xuu$j&L:bDrpe]p1#!0Jc R+J)J mOC2BɰXICp#Al[`30,ZJk!d,2M,m ض0 ^nkoϞ¾BtvD.5/vR;U ycO9{3KOeBu2vV}f㧎>˻V='JOE ?(У߭Z^;4"oS#6YK8ٶcYMe%%lۂ2eGe  1es:2=tZBAK(ϖq.d\ۻy?2 Gn~ҧ{{٬fJEh SI#=Wߘr#?~z¶%RD`rGܼyAO,EOA@"^<&ʌ U#:fbmSs.ݮ.w^k^s߾Bo&2g \DA}<`f"=/Dh4=r?qcyƊTŸM6y ۑҶɑvy1^:||=Ӆ|x{>M}|q3x#:fMo;cUӤ.]qϿ#WhZ ѴQ"fЃ1c!^%81b;uAGۼsԶmٝnGa1~/yCgf}'H3`LƷZZbN<ÓCf7glܘv Ufv<_d-{ܻ+؝jǘ['?Sq+̓c8m>$`h)!eFG\}?jd3Xյ[Fg|cZ?m+S%"t҅G%#mF>U5zM+^]ܵT)&.~깻^ʳW_h;q/5孯rOn_$>~|3wn<y L^7q֬ɤLmۖ۳re{֥wi)ɳmÞ{4+ɾE}Ħnj}W37V$59gkiX)Xwe+~J`.=c҆eڃsX_%OOo>ZXH4-V RZ3W-u7wqǑydn`׺^Gs g~pOK6!v"@Lwz O;Î[>{88H'Fny"s:I~uٲz{t4*U"ar9)jalֱ ~y˗_28] .-^3tg †|ow94&ÈDpL%ik1lmzECMMQ[P|0>F :b A߬7FF\rCm퉷ݴ,A K =۶zp#eD[{ڻ}oV絝;mT] DOC@4y?fG~[E=zۯ[PD{VE.#tVY/2la~1,`3s%+?9r7?_~{^UDLRѺ\PE^CrFv?{rKKoٷMy_H%\]S{]>U pYIBd5ysM66F>tNs֌3nI >xꎃu'!"_ ҥ3[$3eQp?SƊ*^X_qs'UykG75=nEQLr蟶6M:Z=wv@0˖XD;'upGw-P~6jYt×>]h3IH&'4XKbКwDa w|ޢYeKޖ'e[}ڴm<:p\-ɂ]Isx ydZV3l ׯHӾ5uj9sZ6x]/,]v,&=!(smS> XQ.[A`I)l)aIAIA#-uvt+\VVƒ1ɖcv%2ؾCeW]딧aL$AXhsMۍT%}nk0.JnG3QZ1B lRqu ||]źBO[ǻo3CxOIJt5Tv~M ;Cն5>i#wm^mG5㈀"uS=BA>ɷYWQa o3D\q0!B4xJ&2YQ!`0)GxG5=OvNU0<%*N6Gvܹ ƻm^n*e LIݗE'E䪫E@DkHIJ>RS]T%VBJh yA{5EKC6mUޢ2ϞgG*ziތz5?#/U3T6wxE.jQK9$,%%HA$%I)IXI)CU2Vq_D+m\7׎2mڮ4ء;8v}j}UN3gxVM>刺: _W\FԒ6v%;b'_7{?qzS*1KvQFֺԬ3kEps[G>g΀0ydo]i#`Z 2oRaD* K& fXab֚aL=;jgdu纪IKӦ*N]rYj׷ua 7)A;ۖm)KIlY`Y) ȉ;{~ujQmy2 p yyڻ&~ ya>Kz񶟕|1J}P!/{̈ $?;o-T{]v˿2P[W5cy|q__Rk+#!}Eh_3 }*C{, MԿqI梐@9TX^EG[<1S'XWJ)"y~0?oDGd`#>;傈wYx|_\rWgߞ};8uUl±ꀝGZBHrmA%qAH3]g$N[;VUT[=VúVb]z9rQuY!-߯Qro~wS @+Ը.wxO>[{lt_[wVMg)Έ)ruxw NJbxN\ [K1i| 9k/>($ mi bV…/-ZF*en{>z5gU;bhmS Q53sϥ*ɨ\.k gTȡ1*!}f}y+c!d{#Gʺ=jBR # #*˩|&~뜯#!d 4qto=~ჭN%_].zrJe};aVd{gnye_DٖT߭z{{yaX &\V^>Q0ʉ~Ш"Z,A2a 7R:""-оB!횥 6c`AJk(6a(6G(/?5~ M[_\;8 Ӭ㻻;9eإ?+nl2hM3⍟_m4'5lt[ Ɩ[ɱceEE|_u}ƌ=9'_p"@k']W.dF|3ZsqDqEq6ؼy♌ ?}z݄CȞ?sg}Lۮ]tZeaWJ)OJ`fu}RqitatK,*gAD¶ 7(7"bc8D>ltG{b[>0M:VEsK#&e£܊Z2w{{yQMF{ =\=Mb&,m2=MQ1#$lBw c%d!;ꏞ/zG |8܊DwGtYV18?y76%|^RRML8[.}]nc6?}wU}LO0%)H69+?u]uaՕU %dA 0gsWx.hX\w9szU~5(EK-; Aw">*ANM$=ڮl咀U{ǣFmPê]ǎ[7Ē@݁eec]6Uo>һ1d+JZM+@=Buc~MD+\ҢGN"Ok:hܸ w|CM5d C|y|ZN}Kkhә~u˛g4'5Oe[k\ 01DYsxh-2|#dh9Nh<XpEmʄF&APd IDAT  *=dm D(SOXvEb;sZ^.6\Gު/*>[Z n\ΐ{LLb~Q\vxa4>|=C1J> d7IJkHipWJ|jzXo\ %-jWU/~ UdMݙ/7W 檁@@zGMnRt`]"u\6yg_^sUm\x}DCsոJj8=[pcowQ"IٔaJSkMۧא6( Nt PH@M{6vl'3IޙnjM3fj_q3$v?vo߾x FڠP(BR)Eb1P#!$6M &0\"JM:!IB` 25#p7 i0TYU:S dih JYO:6O&x<輱)ܚkGO7ljV8$e̘MX矟 ;skçocG^YO:SոSj ^_x4煗7CQ0FR;n81F !adaXJa:K!$!4QR(o(|q[{s !{פ-,3Ls{eszbS Dr.a(`33,F\vnJO>}zt.D\ ]=덛>xO=ҘON}O`"f&mbnx;w-y~TOnrk'?ڞ'WO VUhȐsDp֜Y+Vƛ[/mi^WX1<.݇*LF+r'4Yi4~E,G- q:KIu] H&߆!iJ<%J!S%dl1"cۯ)EaDC1<-UcgBKs̘MI)'JRPeUξG{byƎC `_ϝƅ6"z, wþv{a~Èj6  5_@t^/KK]Փ˻ ?%l/3С]yeU ZÌ*q^Vx--L5/ZzO˶z[SptOh|`d4h`pv^k~!1 .u]"]sHB00 )4 [ i.1(0cxRL0d<ɯ E<9BN!A)DfRsz}I2B!`PomjJp {jQU'-ߵҀWV_qAH;6F`s6co]yZ%47.xAm q@ʸqh$CwE55i3g_[S*ᵛLV ,=juky-lvH^ܲc0--/W )wU׶,7IƢ(U 4q3s=d!LÐ 0RJ%XIDB01E`LF,Km&ʔFH"'nƥ?jܣ4HDQ3i": DY34>K)QD(A";𠓺җ<5zMfw+?Y ϟDk__U{j=jc,zo Q3I Lr^}ummF?:yg [u{|>kVziD?݅wײ kr݋͗32m6?iak¦xB CBȴ" %b"V{Ba p :aNE2<}[p dTwa0J.`k㸿DC)!0>{ˋ;$ C"Nf)Fǯ Uύ:If{Lc4| !!Y`Ba14 ff{k WF2읆ck%H*K.$69{.U7?qUAP]1^?⑏g8H-Z-%u&GKzֿ[ջw$e_{:tS0K]<.*Z967w`y7],?G?,}][L$jۍq:RxK* /|N?8VŇnw+u)W5%هso"r;z_{x*;6|7oWLQSO@k lxB7a&Z\Fm;'_5q _l B sB3i>wvsZ 8eo|ɏ%i ro->/ߴ9=Oydy< Ct&z5}(9#o ط#[G:䗸އ ,K]e@HH}/_R70rYPkj= [1@Ed~mW/8K8oy`__Uiǭɳ?/7NSUqpkӎُv2$.rq. HzY\^X^\R,"DN'Q׭ Λ6Eư,A?q]aXv#> y/hZwu+#ɣ>ۿ=Ⱥmylm[}3.O 7]蕯%Y %Ocxaf[NqWᱯ 6{c+-vݼ+ b,24c4iE]Qwpt'_mХ 0{-zÌ_۳:j&P`l[H1n7QJK]eEELC)vJ)1pѯj^3{vtJ 6gBk.}eҤ- ^xCxòt q3ocܷ%W |Ik>sKOʹӟ^m?x@tl?)=׾ú_}2 JSow$8{2\)5 :q׶;vE{KGmL03kn1"Dbʽ$>(^}/8I~@GD4MK)^!ƈϚ'pk~'o#=cUkN 6 8QT;nR|G~n#/+KuI!HVTi !:^gOdweelosVg2X'SI x o-ӟ>Ԥ}操[@7mJ}gzdKGՏ>lӂw]Zq8 mʔ3gӺd&#5z#T?cHU* V &pDŽH pCK܌3Ð"SվTI#PJulr.u%BZ*`&BaXNS)?&8,U!LEJfb ƈ0`E]^/,#P5;3Sz"KW},_"BS@f!YW]߿o_tHlCtJ1it^ Kq3q{ȑe[\paXT7g:uph;oۘ[:Ci>ΑűnHi$#iR c:?FY5ưTAee4BuaM<ۙۃ}Čc0ÁU.v{Ai $ C^&H7}d+!s[8H8(EtRJH%m?gG!dRa0SB(! jQ@pna1"ƊR$4IА%&%zPx!dR`꧃BI_8`@ G: `9>z{%KV;)>[>>8EF^]-_t;SN1Jj L.582L.aaR:.xÔ bJ)R0F 1˜`` lH2vX)=BRˍ$E!G̀1> :QFRUL05'Q3Ң듍Ɇf%Æ 1AՅsigbpv;H8$)`pvxS׮ޮ|ƍ.7S?/;L7fyD@fw's\!C[\8u 2L' i0u.EKHHR)V>ԃxH"(E&))RK cHa G\Ä cdG,N@J :2HČBzhknZ[[ẌiIStI)5(ˈQʻa#ܾ.tۘ8:7u0pӒh)q6dwľdZ7(#华dE m&5!l`f %kK{ ao>|v~{$XhlvC3Zf^rÓ0~W:vl[ׅc{ؼu.SU̧M7Ӷ3f[ *wkF>#]+ϟ?:n;3{Ju,e3OO,C=ZV{_۩>xotgѴMfY?j !AHnKI^E<^eDzdd}9gvm^y7q8v2Kڇ근&? 싂?!5n(_}{58 ;lܸ \W]=Oq,W}e-5ji`gSJI<6-[7@!/is^Njhtudd?Cާ/{񙉟f}5C{t6w3 @e@GeHIj'̜6@CοQ(>[4` /bܰE9G~Ts_͛v͓|~>~>\ fqTd"MId7]f)ƈ!)# )0T >UX{`sYcWF ڣGF//Z-k\kWdK͔wXƏ\QsoݥEE΢5k,YR0Dԗ诼ګۦd{=DJNY)/?sl`o^8hRMC2ڊxsp7_[/[+`@n9oI/3cv.Ro_( qTZvʔ5WiN?#Fl@@(E%YVR*/)q9 4e݋/s=4 5oi[n_{O,Uظqx+΢[omwy d/[ְ~Ŋ Ɛt+;x򝱕f߱s;|Ѱ_Dns5j1Ux?PrEvv99j߯:؋b) ưY=y{{b' zs%7=ͭk;A(d4SӦl̘ q5?Q8jTٵJ֒%_}y&脠h n@.s̟23@ dJDz\.c ;1UJLS K!) RL$E${-:46QW!~ _|qi>>ݤF-RƹL|Tt]8}>}u]ۼqɒuS>rUQ*%(t8c>y].b @94-Q d2JJ@8U B!D3VMzVsN|-*nysGunP/xxZg8!K#~!4Lɒm'bRU.CZxBa[_!3/6萏­fg] m"<] " -S0SU@HBfcSVW[>p VYSji QM*Gzfywc#y18>61noذ+];vڵ)SQUPQyy 9t]`](H躥JY!-T0 !0RH$7|F,,+Ҽ?-{_B3}(P΋\2Ki1ӗBbf ijx )%=R Ô"(Xa 3JA!DLT]Ιר5@Kڏt箮4yD DV 1&"() >i< mА;t(qСdM05Ff4e! 1#&H7K]%c+2I6>}ߜQ7MV|G85gGlyNr˰zHsVrEEؒ~q0 Kg–~IÐR(mP7b3g #7 %"9*Ndgv\Ull h`baL0rFU&!` MD'Q#Ңz0ԃzK$b 32!4B[.%ӔHē^ @Əb٭ͷAa'߭^˵ͅI6~#u1n\#jn׫si$7a3֦Z[X(dq3iB3My<3&vVSJ1EUA[/,8TNB0%f7-&X(aٽ6sYx?.$RO$t-hԈF<H bf,qIӔz-ʢI.%fE=Nbp`YYJu_CY_oE_VV|H{d`UKsdK[z}Ƙ?2z˒i/7Sqq2&QvkM Sq96lΩ\wVE3MS Ns@-PpfQ|MWKҩ&c~S?%0OyvG߽;sчTia[rj-_M$r/эlj|/9GaJq,?nק?(N&=lv&9~}dLկlnN2OҨ_'NѨ :yKp0X]ۼnΔ&83Pט1M$x}eKNhiS8Q)fMӵɤ` \1p*KDc۽k770dc-N y @H-d[8% HTSq*Nũ8TgqQKIENDB`ukui-screensaver/src/assets/weather/39.png0000644000175000017500000005016014205074704017467 0ustar fengfengPNG  IHDR>a IDATxyGy'{s=MҕdI1@6 aK +0!$IvlobY%ݷRUGwm+ɲ2WStuuzJؓw|Zvw"_uV /(dz ;X\3 O|o϶RpZcx]}[~)䳼o 5O `޳)(Hlw*'[F_GWu*ÃWkwSMI\k@MNUȡwY hGB@?<>|k$ 8?t$1Zk03* 6}5|e/{D @q_\yz9Եm{D5q'Z;Mn_~qm#8_&YF 3_p')Z4##7 ,}F٩rV32Ī cO hဳ/.7RoZ-;=oG゚^XX.V}RJ+0BH)!$!(C1l31F&IBvvZ_??'{@W+_4׈kE;p z[CD<TMExGtK vM%QAobYFD-@X0H=O~…A:DHNݠ wXh鶄p7dwKIZ|9>OyB矐872/k볟k+&''YJ+ippPuA@@T=0 IDQvV t:u]Sש^rw//K_ҷDz>IE`s!wIFM 𶼈W@?OO-ush l,iEDbF-@d𶾜?? [#SoerƯx 8]*ۥ(Y<ɺ TTF ـ1 9MTL~%Dm w&'>˝#mx./+㴯e[&!o7~ݷo}C>rȞIyRaޱc." Ƙ,ւ̽ccL:ufggvÆ Wf%_^-jpdc B$0A r˫^xK@Nb=B $` 9* Q 6]0",IRU0\;*f-GS Vvko~|ᮏs 7߿RRtݻZ"Ii%>'|e[Jnecx8^ Dfk$fτed絞 " 0`Nml R Aj6Lpk>_|Q^lG6;Lv藿gc8*ڴ5w݉7'Ix>u oR^'8ZoF@":㋬1==0 {&aZggf&0[CB•12T*ԫ F}L`b̃( 6 VιM+g5aq~>uy0[k0'`A p:r(ل$ "p!}VH .7H@fϞ=kZ⺮ oFڰa.g /ryLOOq7`L*&RRqZGׂd" a6K`؈mA\qI lz? <=P`@&9_&oe0+X&H$r4ETwN<Ӽ˺t x>@Ȗ]Zx'ǡGGG!tF8g )Z+DCB@k )%y`6I Nbhhc-6XZ8#Co܀X@i6md*s`P+:ȀɃ 2!& :UYAQC֓K~׀!d.k4R\Py_~;FFFjRJ۷o.(!>3fYn6(zA)իD)%0119z$PEBDD0FCn7Ɨ{1/+oK@aL] kCiL( TQ8U8 6r@2؂^XH Dpsjkǘ/xΝr9Z(077#\LjZ!=q` 188ػW  1P FģWG߿  ֐"d'^HM8$1 B 3LH`f@%}U"Hft@|ow]}_nʮ"I—l 8(xrw1<σ8PJaӦMزe uBZVFFFj0??H=t!/bS "s"%wT*h4 Ppťx/rn:Ӝ >lH8 ({>SSSV0􀒳˜1 z3,?c * {el`;O`_5 Cy,?#TO L0b9LgH Ŕk] >sEd]B@jZK뺔Y9; V,tȯAр1gi^?8)sdQLmʫ0 !dۀm6`#sOa&m#[ I*LE02tmo?t?87b;'pLZ @A0~ZBj8xۼhHԚY"0\#|Pe1h-0޽ej*8\*ئĦSߚ[6 2";iz2n0[߬n~Yְl=~My/Ѯݍ6_cWEMn9MB CWRyϚAch.C|psQ$J>F!"t:^|!'xr6E@.J}XvS54NNO$-"[N aR !zтB`-k+Ed[7P=8a+*Xy#6o7xIw׮]?xWwq<۫m;'h@9(ٚ0'@N9q *vڼ,H8'F5TԖԛw1v(r0)]@T`R2P`X,tGX3Ⰽ}klah0f:gE@P۳g^{pppkܣ)S̅_;N`-Y<3øRB}HY!:Q#He—?hM))! HrNɒBٹ78tD`z1fldd$}ߙݻyƍ[E-=g8W򶊿m) EEq h?5m( BȒRO,.Z[9N b  %14MK5KCo{ө_6q~Ǯ|{E)Hs={h4R:|>"Au{(2l~׏{Nc ,l۵xJG@H3/x*ƽz^BpHtt[nIzi[$+!""fk >BL ={_NBp,^oC}A?\&t?2ˊ` s;f ff qL\BHLJdA@+"35j#pb`-(^6Ypr/rY3g-oM6mV_ϗ\r c>k(k+/?_^r@-7<D^res2*>Cy2 C^j?2~5ع0@fH*)gVC%abX^-P]}b ,4Z.3###ٳA h֭'gAϥ%t5gy ^t U+Xr_aE{*b0,I.u"8`b@PjR/.6B$ Y \LTWN-'!2q2k׮\z饯gM)`.򟞚㺮SSSp Y\+++ð5YՏy<\r>К~1{G D GG\E|-Cj1S2]a&HLooˆnbJ/nȓ*TmJ)r <:'Rjz3L[U)兡ŔX(L?_K6FJ_H1|^, 0+d@$T`ȩ[G6$쌇xoj<Ib8ʻbI"?(( Rg{~3.<l`sȠ 4䀄bɩ cDVM?|' ұP}2kr0czq"zܠ o."SH2H<~B: |`OH8` \U5P5KΠaw ʟ~EH:]M?ྦྷzbV31eEQ&"w pRf@=qcEx|Y˥<eQ,sܜrE5h`vQ@2R&pHa=K&V 6uFةT]=s{30\;;xsЬ)J?^f+rAN5{,!z3X>E.dE.|/`!m`bJ}`Yj`aC%(i VM%yuǏl||m `uuuc(B(z7em8g-r2^/wE SJe6_g?]d5IB*OxIEz }r+ưCweJhIr$ˮ;c{gi/`a)s@1[q~a㸯=[YO/Ё; IDAT (2:[.1ʳx~r6D?!$|Oaq5 cx0sfP`&;zURwA=cS{l~c_6 eޓF{2733snJ"n100@ys~P>W&zx;ŝ@me !l:q-gmK^l;z4"DP=e֦ cIJn+J%:OK__X>eX%@MJNcR`OzKKKN:u|ttt*It:bl7eX13kbEs?-\=S'y_K=W+ΌAKPXiFk@r 8]db#薠h^sJ/>jl'v. lcF+ [JM/J `-`r_0s{߾}_˶FQqRg˛Wʄ/*{yG?y)/&-ާx\m lWϕD˜ ah \2``Ӆ0MK?'1~h hXF4/ Xlx=ؗ$IDtԛew\s'Iիel7JRP?W8:bZ~~^2_k<[XHc9`"pBHV%E>'yhH!(-cM&נ @@$M!Ć]vZ)iV њ</&^E@H""[/{ʚyOכ+{=V_D{>>Q! #DQn0X@l &KJ~% ,!rVWhQGJݛ+3̈g`[)+eΙ  h6Bix*'CL0 tG n7<?|E ,ђb̭{mebdn"DFVĉ3;v<$t:OleͿ8sʳ0 v6@ G2ʚ}y|OtDV;C`a;1|f $0]A&!!SOuXf`r]֮|9OIP @H"v{رc ۷oq'"mZ2p_O> ޏey_Nȿ+<~P^ЭT'@;? CQ.FkObb GZn ߉ 9$0` #XN4>}F楔4&O ;cM@3皣"CmYjk))vTd~~I@sq*_~L'p. ]Qvs[ǞD-0Qq@6 l$ Jba?dd|oD/wA}A)֪ 9v{y޽ߊDql(yETܭ 2;.΋qG?S\e=ܿ)E(.VVcxx -U/B ;a 8&Xj"ÒMk䝌&c3r=0Ng$J"رc۷`L\׭[R2@P0J`.2:=L*`,nr3lQUWњ)se0y?(BA7XY| X^!pd¶' `@&a4ъ>>5β*x=d}Y9z[ZayG:ttfffl(D$#1 lgv2kfz}fbcEl ϗq2Y.'QktU7Dv`Z]-a&&P+NX*oy㛼}_YBb@8HM*e>y>YSBj~ZDdǷtM7Xk<}%~?]>PTŠATx#O7,hﲒYU]DQֽ;F 0\ 1T`BE`;ISAtW ؐ`buGpozo1p撰[RJiAn8]tQln6fsvnn.w7<:99u|||C2ZLl,ϲ~H\7,')+^Yo3HkYEpK! 7)8\@q e9Yq4Dl:&#A!(Krp(??:?Ooo=0$ɜ=y}^f1(Sfg km}kŔr"H$ev(߃ 38yB(+I4!o)9 0Zc,:KπG0T]ڬ]Eql2 c:jRzP/#/[0"at U?2UC }2^l[,:ɱr|'bmOjߗzZΞe I)}c y 8O?1AdY.h\t뭷g@Pe0/l.Eq$1pMP (q!FyCI m<[E5@HR:=jX݅+`= yxN G ʠk4 vZˠ9־*ZO~ʞ8tsɹ艶62g KU `̂0o&y ,M#BhkmfhbÁ3^G>0,%cz$X^^>uwW\qu]ⱱFVVRP^$O5BDa(Eq`ۅ<7Q\=_r.ӕIbF tg&+<78cD!@ WhH$ 4*Ab1P1 ^ ᰅ5`.ٯ<9&h"fĂ(ۖ!g(FrgζQJoA3кjG V\c#/|h WdcJ4;;{5[A0 =_BE!(0 rIknCn.u:];1Z0a2:!1# D"J!r [InA$Qh.:ŇPqAنς܋ Ld %#HC !V !(ѨAcbDy]NNİM%%:ѬE*e( %/Bg[Ĝw@c$Z8C#Vsk܀" Ï\{vw~ @@ (C \` HkӨL"@k Jp]8D+,aF"rK-)P,SwMd ts(҄0`Wzxɧql  xam**5;V.ffzgM|.lU/6YG X* f`(X Br(Ô40o_@9?IH 8RsNߓb 8JpDmc,ᒗA0H(# z *^`6b"[UU;/@$ h4l4Odao|4`؎؀"ғ C 1SWboaӒ Y ̡etJRL^d2͆ vk}fRHP `!BعEƩ%JY*,X°t er\ @R q>j-#=~#wUm(b-`=5HJD -x*F3—\7y"l&\РOa)XHXkg"?kX6b%m { k%y$%s|xYˀC̒ҤFEr j00 A>u FS|h@ $Ʀ+ aL )WTp-c6|#+p^X`jH(XjxRCŀ0hoZJ'$4:lW@V4s5&=V_|.^1  ej)ª*gn= B2V< ,IG1x'О=j%%z<C#LT?0! ر,1%Bmjr{A-pa hT:.P& Жbb 6qX} 1CH܅@űD160Dl([;=B2<4N ڌ0wy3UDR#_ 3XP TU,G*؂m(#lCl dGz1`$*$p,X0 `+[&+ߋ[H|yo 9=J9w q'"$as !"rafT6 6*7:ض)8 !{"}(}sΦWrs[3O@33bsc \{5P}H#`=Y03?C8j& J5\H L 1M%O>x9 V`zcPmR!9 @,-6nmw#u/@} Ê =8@3h9bY&*T 440EBzDa]MK`@[dpash;v-C Ch˜ڤoWT_@4@@ ca*^\HQĠxnL$6LWDh̴#.0`y5P?͓Iu`] ~Fi- qv$XIb>r cDX^DJGt&R_AUcfv #SY bHKx&7JtٓZͦ0XHpr"X_Sw;Gc }]}"Ѐ2j!E4*H ^($D"$Mɦ)8T+DX] I}탾.rl vA99L")ĩ'a/+\,!b+yAnҘ^#/@ֹ8fI雸 ć@H*_cuArplKae.C'2A-O@@5< E7r2/:ވ to'LGrmh*st{fU \y`xmFӭN1q 6v Ώm(# !z HA ! Xf}˶z"%${%ekd ex(uW@E  $]PŁwQP냀@ qʗW{T%ӪΪ)Ӿ}cjъx0a5`2IϲlA&"LI ml .džb pŗ21m *.Nn,a+ȀItYFK˕poضIOPx'!֖ؒ\]`cV O(DdM(t%-#1|{;g~O=bX&h=-Omf;Ixڻ 92{{fzC$lEcŃZ]p]JD]YBVtaCDɒ!$@$923=}v%L2ͯfys + KXnٸ3Hg=s3:r0y"HUMT3@1]5pxfh@ KeIՌT2"ٙ[!;]G6 tqEK"'>CZ(}n e2y! Xk fM8.Tl &lwx  Hr `wieaw3YF E'5\Kb̟;#`5U&C0nAw<-bL8{ 3!XDs@fvS6UȞQqb1[L_^*xgbSTLJ V!UHtHpb ي_5O>Y?*THTR)\Qie&{،wOTWJx BI`cAs0JQ3 Ѩ ]*tabX;,,>{$Vi}[Aj7X 8L!^d2DWh@~U}U|Y ";U`esP觏T㖤x9껀sC̶\ Vd[XY~^SBL~U$jy&tr lv3 Fω*!ZGB7/l/&IS^~B+ 4U=_)} ,=TRl1'IDAT0d~ k\JշspRs] CRlMA!| :ZZ$8|VuWHƅ^0 w, < 1?|H:+|fWi!SH~CΘ;Xa0#dkSb z'm"*x;|[D|T5ىa9P|*d2% 0)ԶU 8xֳ7?W^-Khp#q0XV1%~Ť=Jm<_3HBV|UME ,H.ZQ{|WSjMZuh>D\JJqF^ʇ+zBg?TaL[ H(f0B|wͲ"=Fa4n5y%`ӎݥ5#'f @@Pbӳ@Ƕm/"!xupYȉ |1c4D==vde/t~XbsHJK;N}=o@ tLV;w2 9 !¿ap%: Oס5H)tjmOJJЋĜ0ȶ3"!³0kwEϾh 1FvYM\D|$H +CFqp}$a^ֺa7J(;&- 1˒̎n/%TfwaɃMUDBs`:^ $] j@`Y}#*Jh%WBX #/a;\mc]TC,Nf͢`~sθg cdM{f᝚OsmI8  A<K@M'NJ9=q@ dGGpt~6Ms5Wv.6BQ@ME+K a6BvwvdB'5<:Bg2L $ S?o 7s{OQOג;Y't'F;\gae4pKvhCQ9+@@nsi{l*=DTFc^w+0i CNJ~9 ՙ3ZL*CeF[Syd@vjFԲsfa>!a+)XmPMjkGn19 F>uPV_|Yd΢P@s)`#bj;m犠z\ݝ{,֢ryDU/ӪܠuF挔2@X"* IA#0BfV}T[{s pS#_WPBȤ:WS&1ysdsd.SS7i9Ek5]_)\ӲJ?LKKd cMƋg]󉕽;+t~c`1(eHrߓ==0)B!D?^[^2a3٥F `~lf4RLA8^7޻kcjFU{~K ?bmAn"ZH|i 8E"A R iǷ][¿?Q`DkRP*U W !+{MŽV&qqf%vm`2j%!DFꓸ\TIHcC{P$74Ri[;S]M(3·T>BWތG>Cri POej:м YƈBiRWCߥfaZ4S)̘)(sد7i\Y+8H*왃՛'O* jwf#:@/lYiLZH܈|r }3OQvM, 0RL"$@<ZA{RPJRKcyt/jKi*h&cφ{6`d1f 2_R.&FмqTknwcH`s@Q3Y#tÙMBE RbW`{>hQםcۮ~+.-uv2bf3~j=ki 7e(X僕\1r,˧pFIr}~7o>eZ% x@~ZWCC?hٰĨ?*@uH !"*ibm3\w^{|:giAʽpI! H/uR ;H_fB T}V@^Wo8ԿCCyA-hm kHܷ25S@FODҕ:+&":@0T*kvN-[Rɚ87eX5Kmo߿/%lO!i23*dDCoJ4`?oNg]d/y#VmNz9 E03Bȟ>]Zf D^[kۙLΘ_?4fD|[loxa۝5B H[mZ_?&C@Mp'qZ6ѻ{cDpjڟ,a#Z>˶z |tnO ʽlĺEAgirL<*L{G]>;Dw{4XF 75G2o[Q 2Lpx%B'nEb1y{IUa8 טpqf-czB[ٍ!AR&soE? -ho? w$(E{iǝtbw2O^9/`3# T]^ =k]wVLZB$ 8R/[ ϦC?{$tP$J4v+\SO:jJ}Mu&`1L\Q{]#pn|5fDޕj%% Aup3^>zM&1qU1k#ܴdO%CBƴ L\x;0]b\ fdĥ uo`DC{Mqm*o~S@3}v~x˽MПZqLSJEk|[:Fzvb?]1y?Y@[ϲ[6]P 1^6|i?݃&6?!LL[54,x%?Am:W<Y; e@b0գ2f>z|8Eka\dc[ M! '3+Ny2ؼo螕j&oRh溅_6tfh9!D>[ fFԾƕr) ٧!BqA;) 3|&aĄ@MG0uoXDCA(흍v~Кbn}t-vA1uǠ0GWFjmJ)Jw鯣ZZZB*U49k~6oa3ǘh>ÒR+@$_G#+ˍ.mڏQq7< DXMuZ4# P&431u44.?>3 [LDIfN>@2C9E$hQF @ݼ3>VWJ9ZIq ˲|۶ p8fhhhMO:+b0ɀ AP*aIX~צ}Oy4Nm 1Cۭ-=D˦($λh0$6->p_K?iMJvIENDB`ukui-screensaver/src/assets/weather/47.png0000644000175000017500000004745114205074704017477 0ustar fengfengPNG  IHDR>a IDATxyG}/m9s-G6[ly`yqya AnK/7y cf1x7dْ,hߎ~fzLԴh1vHr_}>szz}KU`0ȗ_;T/c/kcGEC,:ijjjyZ_,L,H)m9W-!T2<<{?*Yx_G :sΓlrѾ}.;T*p]w^x-80MJR s?HzvٲeOvi-[6v> pd?kx7ܹbxI۶8,˂i` GL1}!8SUy_}Ϛ5kj3{d Cݻxk7nީRcBi>5|yfYVD"05"$k8tw~{:Zfffl6l7yU*f+|&r3IH?ܹ|ms߯-Z\.t::6s0 atx $?D:y**Jh4}#Fh{_'?_8y=\rw9?5 v|^-^}}}AMWV"<ADO }JEMLL^3BJ2rO|^I4fu 7ٓO>|>o۶H)Mqxb`fYuջ=] Èbfљ"PT011J}_뚞M]{zx5`#fmOtU+V@6e$qݰy ӧmU?Mx@\ׅyjjrrzI)Yq|3?edؗ"0DdPڑ'>Ӊ _JK,Qr K$,ubϑBg]IrI)P"ŵIDCJ 48L<3R"H_u5x10!-C<80555T.1822g$Qw ~\:A1a,+ @V574M!"Ljl6{X,BR)l|7p;WtMu]ڵbl&A:m0MSr%cLNRJ)yp]רVJ^600t:I(u k(Ql9)]OB^뺑Q cT*W*Ư߁ ^I gvۇ{a( fm[pUhx"9猈<SU*A~ 1VAc~n6J&{j:GNG05˲H$"G#HDѽ9\ ((DTZ8Ԕui}K!R ~wqyD& LdiL&BB4,}ri&j22FtT*m,[ mGY'K.IoSI]9BD lFg'3H?!j#(uYRqs}sK `wz H$ ۶Y>ǂ 000$>w ӁMLXjZ* \Q(jC:RJP8#[t⒔Ai*XqIݲ,RqD"wUTb TX <~_\/hs;x;R===A"2 .]SN91lg}"<σQnav ~NԮA"ӘtMyFjF$EKy8$|Nfbq!L$;^5駟vO`/WO~};T&Q㘅BA^-Z#, u#MZ (Vj+M4ȴs`6g {"7d*Jt6~O:OϦ30OoTJ1՞@C u ܅(D}L ?\T9zɤrPWft:znٴn_affJCB/ҥ&HtfTH$`fD(]͛dFji2DP]uaY,&He!LOJafi g \? Om[$ _~qMڍqFPJl"LD"8@ItJH727RJ4 Jki:g @ tɏ3@ ȴ}OUYuIPC87_"UVk^TSO2:q7 LNNF>@D@',Q,199 ˲a&jbtCqCI yA5Fٌ3Sa ǿ8Sr002d&1RV\ɒd4X]jtB7}}D*\dYtYlF..Jbx@^XtEt BfS7=csX}gyر[bq `W^y_ d28c.\P ^ !P. >I48N$dȽw;* rt!3AN'65]ѽ9HRQ+.sדOjߞ^xEߕD:<38J<ϫnt յ.rիv{{{188tDꙀY2DPZP0\׍9 ݻa= LRJM0!RA ^#8 ]@@uYyի^u}*L/Zt<4=H_" @q~".\G*Ƞ'wg.·@gB2,)< ۶t`0Ix5ݯjE#/I)RJ*?Q8rkɤJ$HRu t~}rɍ j H ;"gnL #HRL^T:< !Jd}4bnP2w!y4,ːR{zz.,J`-R5rI_~RCoo/DvQω>Lv?.:#}\q3"\..:"q\@cyCM7LR3 C!t:mٳJɎ/U3{zzzH0X2d}7MdH$>C'sy%t:A)Iq~'-#Г=HiG܇b qIYex8R im+1fR'Zn@>DӉPig<ZqE(ԯTUr9RT}7 t:zA'Z3*r9$APDϥI>s`Fիݼy.fग़$cժUXj9et:c'5R %0 8hM62ntWT?BO5V"=i M$ۮ{/zƑ&"Sq:2ܤ LD"QKNs ⓋKi9!)sFRTu#T3I7w4/.'m;y(X,qaR)Ad2UJJQJOмh(p ǩR\|>T*hlFiBU;}}}L&3 K$Qp|tVA`0fz :SuN乤>yqFczK&KH}CZ#Q.(E=J]tQH))* ðg'887__z[BY% F8qFXR:ㄣ!/~?:h DO}aR*#K#T$4=LtA"sE!1pj…oݺ%W7%{O; ,… U__f\'tki2hㆸK»?gxXgEiF !גs!q9L A +! [ڶmOp?VXa˗/WK.UlX8}&'_Wu:a*xx%]E <T*JLQ̟>dÉյc2Z Ey^hzn,T*Zw(4-|]wuǼyx*3:,tR8Ѹ*%ﶡK~..sy%G;gd1t.r]DL&\.ͧaWQ"W2}t9 L47LMM=]G7q~[-Z$Sϟo}٪&esEL@ťQ}\Dqw[G"=GEM%T8SI-2914h-i(4Q8pifR*ϯFۃi H$\rd2)s=7">=HljN&դWt^;^*v^lqF3G69RT#P"?biD zK7Iu  &SI @ׄR*l6w;$vϞJ)B`q*1Gغ-nD/sį7ůqϑ-&\#3bb\^A t9MQ^N3Fi-bNBD 1ٌS暿RL\b A'q.׍HP\D?Q>=LD! @^GRARA__ Bm=i*N=} V+JS@R1<۶ f6ƿf ۶x6hU~h5TG󱈥3 } P#bڸNt5M3B"zr*B. OZN:館?Ҩ,ˊ2z1>m(2LĈHRo0 8Nʲ\4bn իW_oYJ… U2dP %J6hD'ct:sǒۍsQg|<9T'H$N1>>={`ɒ%0duYs4GPV$a()%d"JU*p~ bŊm[dY$4d2 'Εp&qƊ98\7lO'Bom$u]RV;Q۷CCC7hiyU[hlYP)d&43R4dɒSrGy#JuH@7L*).R}m=I"ѾKi s_@bQ~E-[od8EFLӤ֨jLE:j*dGa `3¨fʲ,|IcǒĹ&N?NZ7Msѳ[=OâEpL&2R(bHuH˶mx 3MsgeYq*/:_OuMF81&l(=pu#h4v>u[bL) bJa=Mr*BVCpdJ(7 fht&qL& ӓ֙kŽ6q:1uK<\xH}&tE#DϮkBqd"O[[քA#E0 z`22eR츊ヸڞ l:SG(6=}⸧{)2Hs$)@ehү% Sa00^W3":5#únꜸW/mO\MW׺ L-1ԍ/Uuǧ7d< TUA%t1~0b `Vl6,Q5b;fiFߍúIH7?x@H*?uuHeJX\qn<ژ1gThhRF|>Nxz7EUh`!WT~*L$0&'D%"n%M0t_um.ωt@BV/q@JI 2BY=4JF)F{xLs-!766v@)2 ds[6SR>NҸי[۱s׉|<"rZg,u;jV!}O=TG=lp8p`R*ў> 93\%ѴS7mh.;8q&!cm?==Qx=s O2.$@m猽k׮* qh}5On;WD~}befqc ⦡sƥZ{ wƉMA>b ͙y,sTJpfffnݺuŋW+ͦAnKZ :g?g=@RJqXJ)%?3Ŋ+V\tɒ%r\Ήn=TYʶmF8uO!h">-Ơ6t}ncz F6t Xh^c֭uR(7s(fJhi[no4c-yKD1^K_>O^z͛~ RBH0ƒxT۰aá 6< H$l6L&St:iO&뮻 \swtBd魛Aj]➌P: {/ey/"~ƍQ,{赃::y:t(Z)D kCVi6*&Ps! cSJ5.b:ο]Sc'oi(%$RRlc]n?CXhЩ:\. Ex.:tn&I>$Q/1fSB\f Y%;ΰ:x0==N:IS<ޏ 0Ƃ s>666q# թHbvitQQaZRrUd2tD%“VUI)뺂1f ݸqSc@z0UcN͊R[3fBmN $ R}=Nroa~pxx/Vo&ժj4*̲,E4$NG|!f3խV 0 B D,x}bÆ 8x` ڱceFK)J) @*o8П^po^3 W}1n)]v߽{ի8/8r z'"_v;ku08|0,XI:vԪǎ;wzR2y^ ?i.}lji.=Kt l6YBmկ=pfƘTJ4:#Կ xcϝ*v&6rK~~ 4&f[1 2̔2 .xG/8?㋥Z =&P0ƒJ`֭nݺuK__I+W\bŊzzzh%+ef:^633 J%4(1̠T*!J!ϣP( #Fuz%N^ FFFm!΂1bYaY'O oA|_Z-j$ػw؃>xO{T@0OMGzü5MWEMc%F䟽O-_Պen^oai*v3Z3._rBJ$Y(@6#I |߫LL&&Kc˖+$8{zz#/"ڹfA4жyDHE.GNJ1ԧfL@ } 1A|u_|K&ͦ2MӸ;~m@)UP5 *h(@=1>@4D?`CW$('iZRV%dBA[]H"ۛ| 9",LgYJnIx~SP} A:+gB.ku#A<4ҩ86Lӈ@]{< -'C)g `Iض1n{Tmz&`|W_[o?1n?쏺3#% ~xO@=Drnq> PJ7=@V;_?מcfs .Kι,+眑]KDZ{x]ϝG[G>UEߒ2483Paeoc!"8NB Rݞ'l>7{e$0d”-+UBQ%YSIU  @V,{Npռg <%$\MTz̀)$m6;q\ac 4H[W7T*<+N P n l qi#ka>Tq%[^਻[؏jB*eGI{PA I0(jA}{Q~@ @1VB49>jk8ةg[୸*y3?s`G|T 0XjhH!ł5y5d˗IӲr  57om\:MT$9mlq|^2 p{1 z-Rzh2a; z/CWo@qv/ JFdɡd]f{NOA* ٱl&(ͩ~S (RY_Vu4FDe̗]OD™ Pa0UB4 èVw=smgL Ѿ Y^ ,Ɉ@ (4o_MNk,Qoj~Ϯk1YU2A-Ho`d7l.'xpKӻ]՞|?RJ1ɸ >un97Q,D_a$Dшb ZJI09ö iN00 08J*(T10M|zTl6̲,c˖-{o喻10C?6+A1GX_łj W  azGG3Wk{F^Pqse\&*0SR}k/\eZl۶mҜ70\j\fmГٳ/Ēgo0 S@6mw (20 ՚6R4N;m@J)Ňj@˗ QEUEa[au]+ww>t뭷]J1FH|˲~''=+vm􋉱u_۞?ݐk/umd*+ R &eЂvLTRJ fUVs[(l-溁,,Yl/C,]XLݘˠb m b~̟I'b޼q#J X)Fǚ0[XftTTJ-hu <9A~z7͛7vI]ft [|MKHvfEi:ʕCcG'.5l{}&糟PettGk;AMB\.9 oSW]/OG>SGGGo:餕g^ŋr Tuu*vFJB5c-Nx2"v~c٬tڄPՐL&;JפX0c| !$c޼,* _ RJMA`ӦM| `sKJY~df >iL`ŕ@$0 !M%^6pR~>0xVcݯ,cW)o4x=v"mh)%@m۶߶mzw%LΗsn%nm33%L90 (ߜKXt&8ؐho iAwdm˖-[׭[܁m찊j-e!^y% wxډ:V_{q rmwco‘_]}w+| ݙ@~Rnx6R kT@1#F>Zzi_&O f`<\ 87$-oRKc{Y>=e}uWm.0f\YUӌ 333ݴiӋûz1|~+!h_ܼN s<;X fǵs#{;bs:呍#΂_]n}k1(0<dƠО,R",`}v_Ύf郧n;u0vN{2}Tݻ':tpϞ={whТ+ RbʯG9,A»'^ m Wղㆋޠq="Fz'|=&U瞎Y8U ϓRR FfS ^u.aT\e~ᇶo`gB'NsʙoҥΖjDG8,}?-s.p[AШU*Vm333ӵZ6HWV2-W'*cI#s01ۏW.*Ov}SzhWz@9k}e,Öm[te4wRM.CD6(]-RѐR6B"=jhmvr)VgJ)Zʡy+>ܫlȆRJq?X) dRk;-{Ͳ{望J)":]Dg1VׅM m#W-sn/~I:׊%̜c?_NaO}d]jBVldN?}ob}=ɶ<ۏY> !J"/) 8 ^h[5t\n,]p;FAa\q|ܦyM\|Xx_72}Nۋ0B0?8iN(eQR1\_l'YnWLg*01>z _n ~K]\)Q< [ETϩ~Sn]Ɖ{&E/hAjc !JJvB%KI;JV"S^TAޅ7l&vowIDAT[}=d%םMXO5ŘЖv%p$-X0!u{K-ډ2?ռ[~_Rj3OAS3WJJ(i'T̫OU ^k;Y3B) i%%Mۧ6V˪' `oBrq^#180.MBB|4 /B}p\G9wd}_ںK5=)ئŽ7<ԳGjw(|鋟w߽3\}VT? LGN?ʏye>]'N=W~RI·U1WJBZP{~HōdNLE ;d;7s]WY'ݹAKf)1Vv f 13yhzqޓ1+rgT_3i ( 濿v&@cWbAagפ݀ٲ2L$yZS۷xD+_HQ yil~)˗nOG ‹L;d9{e)ҏ=$齠-&Dy+im)K; h@sdߓ129}?"1`o[,LR*xjR c^+زGCCCwy⋁_t/.Z F(١ws'I5 euڎ| <ށ6`ӷ/6O 5QY?3b5 ꖭ_9r%'gF}? )PK\][ |vf{1SR| ~w  P'ЙJ7r}.l ITuuȔPSܧ~3FRpj*p g΢EC󀭛| :Tb`480X9$ ~xpU@Z b4sѓi0.Fn?rۙM+f9Cg-+WŽhuMќɱI"i=@,ͥ)Oghp3rZ) PSڗ_^eczY5K(E>3Sm !FϫsF&T ί<;f=@3&3&r"3i`qB 2uWC$EǜEI@K'scQ9yv\C՟{Z2 3*cac;/U3x`h*\Ÿm5"u9R^՜#|r ^i$X6TC2qNzTֻS]6ρ&4~^ctOJlU-uksUӴK-%#+W.n|Dmim=jăv0G=K9|#L:UCfǓn_\ +hRB&0Y&zD3fe(i‘`$t׺wI3iFң2ū%>6<.4Fgn깹\İ)D&:8j7Í"V{+u2ۍ00tH )YSoM=^Uo{uٽPT:bR񥍎otrJxʚq-㮔+@5,?nI洩wIP4{=U]SؑcU)1z>2 -*p@I( ;!R ~kKR'tqW8Pwpm +d0<;Hǁi6@2@A~_³g/mX4ɓQrT0ZceF|+g}}%Fa31#wAY¤IENDB`ukui-screensaver/src/assets/weather/29.png0000644000175000017500000003511714205074704017473 0ustar fengfengPNG  IHDR>a IDATxyy'{yTe7>p A@ ѤHlNZK+Gx:bcv?GlMwgN(uѳ&,Q#J2%[$M qq7FQUY_WY 4@/"#32{ l7vl7vl7vl7vlh~]M @e>*:!K_6V#sҥ&R!PB 0::Jj"yֵ~`ۏ<{Kn=jGQ4y^A)U؊B !R !.Baf``{.bEl{Ofy[E# eY0 BPF^H)1h`J7mo{ ] B_4ɞĮӟ#G7]Vg pXnD.K62zn8SC6  ?'LAvX^^Vv[qRJjy=o}[M|_@k$&ţ>?ݻߛ*RizbjjJJ%@"sNׁr;?fEr(˨V"ϫ(DZa8100+.:uj? Hu;vs֯_f TDZ011)nYz[s.q2y m4ϒ&@XXX@^O%Bm۶iyySxUAW<;;_3MsyQ⮙6lݻƍa(% h!t'A}(`ğc gyeaJ HSJ)=ϋk{sA:sA0{o/; VJYJ~;6o,LL 5~Z'(^$D@D{zFtR$@y'(2 |߯vm(߿2gTh֭۾/~4u:Pa*-[[ 0t2qw.(AD's<WX{%@@B}euE$j!PU*+ͿX%_D{fJP)e;]vu pzp": Hvn{80 QPeY)(^cWYUFvϫe!TQEB,3?M\08Ag e.-˂izsssG@ ֍\.BjALd\ Fa"pF`$FQyu%H)u]u ?z^{6~>O~kv6M3؜P;wBN\|F'N3g !<ǡp -Ҙ?:N*-jشiqʽo]H)~ :X)0Le5??8maPMӜ+O4^7 %lC=oofir9%4l٢m&tG8(033(P,Q,ӐeYrD4ASTaӦMp]RJXf BI@(yh3<󎊢H(Y.=3n$x`7;V˶,KI);v["X뺸p F(JV,188OrKp."avf%,--PJaO;۶S`&A4n@F!:ZtzK.$83<433s70|/@ @sΝ=wv0 DZy--[ z888QE8lڴ ۷odž PT3=|oF*)22r\A8< eCATt% 皦i&͛ٳg ro4 B8ck)s̭y2\oW_}Z Z X," cll e|FGGQ.100o,'El=D\"K.aqq2^^CJ aZ@7GtRUCBn,Kt:t:aX211Q;pǻ\x#g?';wv;TJYccc;w8 #qz9N?22ݻwZ^ዢ CJ8"D("rلy)+"(^GRG)E0Mh=JO>z2=p`s?I0B`|CBM\.N'rwqR<^:`nn))%nqR!!PJQ]CF&yf@RC}DR`bDQ$'&&vkOc%|6u7К@WDrnGq[[nUZMDQ۶/3H/\sΥ/ رcG뢟GxHEKKKis>_0==jc5O{ڈi#P(\.T*tiZhHJzNr5Re }Jw f?48U>7o6U\{ӧOZR6nxY1FVg+R+06$GFF011)tY@IPJ23yT4yP݉-U.G|o:@2][K {#4×p'd(q}J6"UV{"|֭:N9ݜ rFGGaÆD|P: ɵm#ϧ֯_T*ҡhP80 Om߾~>ջ0irf;N0㈱1aQ[<8fLDX쩮V{tN7I}B`VS[%Rexq2-@duw̏1\sz@GFF>AtM6)۶ !=1CleYt< Z|O8OMzl9& c6*J82|߇8iLmu]3"5557nٳg[`Mz@ܳgϿKT*4Ae)W^(egP,ݗKkT3y^?[K%⦍NvX^^F㳔I n#ݻ?Wэ DX[x=]Ht166\qʥX"cDx66vD" IK)AmL; t͟Dž<ϻ ܤT!4MSnhX?[V+uW-bsG\-ڶmb * S(O8N0:ǟ\drWZ?C/%j'DRI@aDQW*ɭ[>pF[Z bUlpJJ)**ωEv,//cppB!iӹ= C!GQ+W#8'8D| m,dh4)1-J'l߾0 SJY ٝ7Z-fрRyؔ`^Ǿ}!FFF@SKRZùH z6}7\ iBs1SC|*?$=>6l+ryhJx rvݎYTD<4Νþ}4oX6mڄѴ z:@\U_-]KzD \)BY$%P(LLLuСJ⫊^ Sa(J)B (U+HkoL۶qY?GX"lق۷2 5Ł8t]? Dni)IKΨހLCNIjcZ`R*ϯE`e%ףZawoJBy`׮]شieܯ'ۂG݆8^ISacl ) aHcinyDZ֭[0"ZW4b8#*j̕LƛobjR}CPb<fw=]>Y뒈S,XݲqLqUJ|>/8FV2000YԲ˲(;,BmY"upa!044rݻwcjj*u(&9QЉ_$E`%Hi=m|MnuzHBPbVL) t>Wm_6PkY.^jhO[ocT?88 4ʹ"rgySkq~u}4|0|ic*h48y$p]ؼy3FGGS>DнSKZ1g fy"!JvI~A"rYTUjuO_"+t,JyT*XkZ-t!??+P‹F0LtqaC.e8rUAΙW;C- <:tS+4Tujf>{T*=OۅWѝG^kUXrJ)eϞ=zBҶm4'hЈA3k&%C>|z+.H'f#vZ\«N7By\_7 nvm4#ȎjܗGΟ? \.7RJi{O88{&tPijX,nh4XXX,BoWWQ(c\Bqbġg0`+qc|ݏK^8pGr9h;v?~_>.3&0@N*066vΝ;Q[6<<,r0ĉ'`f- ͛111JҳC?F)Nt;M6P(V+Ȫ=j+eVE1*LTeQEj2::z+eRrݱcCRJiY9888q\0 BZ]ee :qsz,..udYf~;vȬjE+݋OQw>e*NٸqFQ:~ߣϚkR"Y PJƣ-N:־QBg֭K %"D? fOR[nl6~۷oOc "ft/2\GS^ŋ8x 2&''m6^ݳ,c.bzq{9#}V%hR`-6mF###wn߾(aP(055^xx2@ħw4{@R 688ZJt=I|> pY[G\FVK- :u,b^uޤBJ):NlYr|J#W+mL+8R0 Y<}?=۶100t ?/ 54 Z-Jt%ӧOɓؾ};>яb``AZ"Koͺz$OOt"FNx7>$  :;  %\3vmrIABKeI0\|+sj5PđF P?OH)Ӱ5FJ1.>OE(DNz^ϯ~ nеH@JRTTJI!D 7Y.~gJDqCCC)@xgX IDATresFGGchhw}7vOzV_YS']+ݛo>V%`UňfqS׭Z!zj)*JDo7n>Y9atl,BcFJj~~~ݲq08}4 ڸ0 PJp9G)EOg3H~xGg>sD,N縤Q︚$gd&ﮔR}q…1_Zxmq# }4> %뺩 Dwi09g oH Qj 3p9r;wMKI Sjz_n:Pus'!0:O~ j`hr>c޽544bh2/]'sT}[Ӊ Xz>(8U*o>lٲGqBbeq~-.|GZIz> DݎM4^y3)Rj̦[ ~ꩧw-lQVܹSMMM)۶E=G/lY"3K\nTOqioVåKTqnz21.uf`G<E׾(r! 6m~4Z-٣r|:ީ~﫟Tw  V8 Q󘝝\d?dyE+B:|BrlMNN|>/Ρ4j_4YqKȯ[MͫJ*KWz"CR㘝Ů]y=_\\o 4%)c+IU!-AܹsK/tO!RGqL*}vPDCCC`_UWx]mzV{ZuH='X$z?LZM]gI{vngggq!nܹsXZZ[BdyyK%DJ)e?쁄nB(")e@roR8UT oI0FR<ۏ1lmdI+^?efj5[ H33d̑$9vF:+g J)88{i0T.,&еz? @<>>RضmDžBp]7ΓػZL "f3t1F}v'}333pw- لR-T.H,~Kq]#0 2bq2i*1h,ߣ_`c5k?}] wT7#~z,--^LDJf|>/;vܹsh]4%K~99O^ekqm ˲D.[l>1 #]c8K{ql:OꄇQ+LLLlŮzQ)0Ti"cꫯ]Nq9E>H0ҹa^-+>Y@O{j־~^tZ9HtOXMhBZau{hʶmAJ}oᮽX~ hJ)tDOB|Lt^ ղsnsB1t}f:g#'ׯzt)'o&# tAZVPl_!:, Ӌ?EF}a4dwWX*kZKQC|,1>o{tbgaW#N,ďgW{Fq\|iXZnSFf)LT\NI)3<\gE7C&#ꕸXw/]thcccRJq,\]b53`4м~4hm+jڈ^G8iXja멧ѡC1ye9oc  6F1?;;;@DQ:Zmp:^]t(D*'>Iy 4c| WEY6j}%h%s"q̿LDZf?HYOFW߯A\4M;ѣG}caJ}j} -䃔"N(j|Vzgs5T.\-xVFQ$0mΝ[?EQSBcſa(y3پ (*NS{?8"DA"`RGո?k AϒD1d1Z=,i4 hmj5rJ!}??'O:u4/'>ykI$ ĉ}x~0,)2Ϲ_% 8aJR*n6]wݵ[!oi sYYOOE\wwe˖ZӑiRJ\{չS{8x㺖`rP,esEd~^Kk:z_|<.]$ ÐX,w>w2f{]\yQmF^)(0=zaǎ{s^2duh@1|.9^Ǘ~᳋8j}e,-+H[sYvW_}uf~~>6 \4Ra(:}_xGP+8WX_2+R 5O<-Xm]@/G90Tƕ%[SlfSnD&@ȷcǎO~oo?~|ivv6Jp6=3  EQq e/ [VH5@?Y?ƞ^u:ˈ͚;LԈF)"<ϋ:}яzK) +5=F':'ΧR\艹@.Y8YY^KV"J~} @,--O<ı':MY=f_˚'% t'/|R_ !D^]wݵyii)ݏ=,"X!SIZO`v8ȹks,T!PpdlVS)""q__:pQ!DOĿn[ bE Œ-FWR(T|ȑbq݆ F %>ӭ)c>jh[٤[J8nQ9ݐ$ E"~ ğG6n]GeYytm[)RfE7PL%ѭ7P={~6n8X*RL2 CixAncqqOn8qbYJYv$Jjr"\URORBQJ 󢅅ƅ .\P_RYԔBn^Vf蒱WGX!>8Py|F!UBEd([xb'\um\?:::XVb1O Of?yԩ3g,58P(j\V+RX* R)W.J"[* fhZDRR`qqИ_ YoZoH-Jm`e%t@ӷ<\ۿO9+%Br.Xqmr \-;SH""jENWZL9Ca۶mr|wm۶-2 #kL2qa}t:|r$hFϢN|Jz@fpDs肠zH DJ)SuH$Nfi:V \Sp&$J{>{BT,'K]А=I'"_oi1b R*DyP+)ĽD+y^B~1Dw=vosuм}ۍBlSvX`% Ms>W1 8;G ,'"D@-j}>U]_KaD:;_b *xB'8tH: *Hp{^~FYϱئiNǮVqrP3Hե6{g8X'.x|ӍN߽o>WK iľ"={C+]ddG-Ҷu᩽%еm֜끮q'[%U@)l.&r< :bJ /@qOM$ed{WqoL.u@, Èn2=}PЯes 3A*'^S !i3sWjtqrK. b\.)_0Ɖo5@/!UƦ_sl7vlޡB[zTIENDB`ukui-screensaver/src/assets/weather/15.png0000644000175000017500000003705414205074704017470 0ustar fengfengPNG  IHDR>a IDATx}yŹ[է>2  2EQ0vQ14Q4qň 7FcD`4F#WMe`}֧]33~TU~k}]-$@`ІA}|d[nojjڽ!r`29nFK^^^] ˫.,,o?^NH8K.=r޽{ B}5MFq\.B@)Mc RZx*k>/((8(Mm@d?h֭?F>@>n$1BA)u2 0 Iu(H$P(]sss?2dȬ#G~MpΝ{ ~a)))HMM5$I2!D$*In7\.dY&B3MӠ*4M0("555@`#~.· bŊUU=#''@p݆p F^/\.a0 UU( (0 BD"PifhF[ZZhmm- ~u=XXXX# 쥗^ƍ%!nn"77deeAg0L?AQB!455&ajhFjkk(cǎɹ瞻c|+O*++o7^/|fiii'999x<  k]߫p8Z@bTUU᰼o߾u]7.zS|G}tn8qn[|RXXכ`H|k$Akk+0"(SXqMUUرc/ ? ޱ}n [>⤦o /_޵kWv^/ O>$///Tg(1D"477# !CUī(LQinihhhvޝdff&~''_KK gEI8{\.x<x^Ȳ 333я$IR I7.++2~?RRRH  . T2ϧBr׭[w-ܒ,xRIܡgnzI `YYYK%~+w^},'ѭ[7n0NsqUez F|V^^~?<ŸݻIhN$ZII`ʲɲJKKNv-r<?7JaW333ѭ[o鴏G#k 0 444QJi(byyy񺺺ӟo߾>}IfN@r,ːeG0;'[,7\dڵk],iͷ'C,N!p߂PJ---L^z飚ݺu;'#$QM<t݌$vۿ#g!$[HߏsxAL8CnBƩ0==lx0S$,==`03c`vI $c;  ׋܄gaQo)o? $Az匌x(>mڴq)֩5  ].a\!6E[յ`ڄ~1^QdyakFO'k)q,vb|>b˹񲲲}EW_}8 B)Mw\(LUU$t%@':Eb:8$9<4d{!/Il_; 1:1 C,X̶m߿߲?ЙpQJI,F-0- Jp%1 ۝Xa|'n'sDOvY@ 1M$MӴ`0;}'܅o9eY ;k=hРK~*AxvZ`=tQ:v`c.79"DHv'KhmD$iСCZn]$ !cƌytԨQt޽  )))R  bY]Δ=\#H&qΩ-%cb|[NE322K,q,) nOwN222}&D,'s}4VNJ։e˖qX@t677_A)%%}܄x<fk&'l `Db:`mI${Q+w -lRԴkR#rss>ϝRs&GV98DibEƈE3X%=8~0 Bq\M6Ƒ᠄o B8H'xbn8,77Wz6dBa!k9H9JzGսG2@8*$8+H3gwƌ1r0p1cƌ{7nLGƐ!CHjj*!_7)g3"0'p9Q?{/JUppg"(aR/ n֭OFCGy睽EУG#tȐ!,++7q91/uH\#pj ۳?kx/_EQ(DUU A} Èbx<;-x8޹ˮj`կ_?ֳgOkӻ'x=C6Ķ8zlbG%hcN@,Z4 7`3+Z(illD,-..74(:Itڵo ς ҥ JKKI϶'KD2Dd?{?clUѴq gDamm-"ȦѣG=r%MT0JKKNIIn[RAAAs|'_pd 8 :s7'V*X|C{c;hFmAE!n|>- \hٳgj„ 8AQ_Aͺ7)##effrul-gXi,ԾQ[t98yȁ@GŘ;Ȳ,k@TTT<#oAG wAjjj<EﴼKj;8M8|Nz쿵DSgxmphC:D\P?^QQ߳g&L0&/K0GxM_wJ88av%ũdB[}wm!8\.躞Hn"2e}oݺ7|sq^185rvv@|>dx<~~[V{/AxitG LH[@kwru"IfWM6XjWgye=dfddtz wʘzJ޵&1 "v1(VmtIVM3---Z޽= .\/О7FPJiV H<>٤r)t#&IE-` =;:ƔLӉ`H\sov3/g=쳷”(c,r<ib(ì ow{_ve?-'<9999^W驪vXff*b@<'^0Ɖi'{;%ECHx[Lc^xbAG'I%_\nOppĹ9ڭ6n 1X,Vy-}X<H䰼=/aB9z~[&޾S]նe쪿=TBa{^o0E@ /bѣJh4,@ d3I2m@T⅋/~'ڃ-~בHv ڙ;bu'Y1B4UU)0[3FRv޽f͚5/袢P(dȲ, ǯ8PޮSK?o˞̀N Ѯ d-NMCHvcɘ. BP 6@[0y޼_u.sL4"ގeG}{g1mqf5JiRs7:I+ؙ'̉4u'tl20c`Hu )(Ƙ@Jkkk],.---MB:O\A{6^,x{귫b!QĶ۳Ng.=iZ#X,q.\"IdF mr pߵkN{Z^rE 99av*p\>h1.nnn-ndA'@%s1;(Oo( D"㤾ommm, ӄ;3mk1x[lvzëXu]'0L0/D/2_4A%xL 23m;CNE3AnH4eak^* 0\8G7-aӦMBPe L UUs7A¾wrxܩ]dfo ' m}'۵K;s4dKEaha]UU_S72bHRJ% yvܹe˖-=ONzzz!X3.|X,&+!v5l`L{*NuN6)唬dmFI(2 6l͞=/`n=n ۠Z@"x^z}EEE~ϗv)!hfFY4eVB;X|礞xaBb(J(w,v3L8Ev&P|ܱXYXLzީZb5&Dch(!Z!B@]]]պu֯^lΝM (a0(:5 Au]hXo!3=GO };lzMnN'/L|'e@p)D"E'y^D(KS@*GqphM {w嗒$I)iii)))@ pۈ>]vuB!a0BG 8>)"s&PGEI 4x[',hޟݙ.5c)%---:׊+ZfϞ=23gc) hYzfVk$fuS.B̵뱆 `Ȟ={0aUU5]%ܒ'[InΝ=|@0'~f3˳_UU*L@ZjU駟~988D29Ӊ7 0d  CAB{͚5K?`РA[ZZt  S`Wvj.mτCj=G0~3h{yi:'f^DUU~/J<,$(#K . /B; !Rq`\v=}5Npa2^p CɣwygNJJ魭:cL&|O;s 35F"$I9,'GN biaY=GppSٳg͛￿@5:@!- "?+\ pMw8?UUu۶mrrrzfggqRD`.qJ''ɄaB!nHb1&.@Ykv{/³%Il}饗>.//oRUC)ID5|%ĺ3;07 HTTT(֗^z/>U< ڠMݢ$$)0|0%g uKxK5j#F8հn \ -uL {FTBؔfќ$QɆ,˰h GfI<ǰ@K/_^kiunݺu-((螗 Gejb1|wyyyE4+C7hRbF6hS+C97!/`="HcԒTRb@?r  P 9s kȾ!qڒ8Rim?i1I;v|l,ˆU{O|>_bk; p¸~Cuu{XxBq+Jb.̥R5viU+!ey1(-wQtn?bY$ck5TuL `I***sg +))镝ጁYx-BlV)WױX uuu۷_~Muuu$I={-)))ٳgϜ7f,3I@N{˗/駟.mhh೜4Ϲ_jB4} N><,2v. ϭ7CD7cu.C`8cL1 S >mQg:҇~8?0РgffJ<;_ii`/~{ɺU!"$?D v-q=ҸŴ#|a tMwȲ{Wr11.:E}/Y\__%\3f̘;u)i\1Ǚ,D4rss#k&0K4vLi H8f2=wyg/ǣ4M[4pyBw13++kbuuOKKK_{ߝ8qUq^ |8 O9s|zy m2YF8,t֬Y_3(gʔ)/3}>_ /Pةab)ZB%[C󱉅*uC'fDTuQ5ax?ɓ'1%%Žo>ddd Nްa-`pM]](8pɓٱcG,;aYDȃs… ͛7ǯ/_R]]mTUUl߾}(++ceeegO@O"w2HًYZ-YSjYYYsyys+**&EXee%kjjb165ڳg G;ux?ژ4i/n_͕222Lu_^[[SPHkjjrs=#Nz_^ΰ;tĸ)3Ƴc<5*@99|\❲k Hnn^z;nr\ -ZV=jԨM0 /G.]\ƍhcY{L {w677WX7|ף>ziMMb&Jf͚eIIIV$aŊt⯨Ս.Q2Obb׿رwRSS7xcڐ!Ck׮wxo \믿~(tw:kNB~cƌC]֣GZ]]*ׇ8޽{狏90%frda (((O>{=2?e˖ʉ'^3f̘̤{={3g^={`PڻwUUg%M@k捲2cܹ;?6lΙ3`>}^p\:u͛7 !BM) Q@mc̰Y8f1[Huuz V3ؾ}H$~-:t+\hZVQQ ʤ g'O^o>ֽ{yw,;v < c$sN^NN=?iiiQ׭[WsW;w &̼7n\Qss3+,,̿/MKKì񌌌]wm=У\sV2%q.+C4!$1@SR6 @!^:M8cX [?Dׯ~X ! 0 gՖ+0hmm͛ujjw݄߷ QYY~Yf=Eie)8b Nc&0+XyhɑMMMy6lU߾}uҥ',&Pp}ٗ>-_u 7|[nm۷oJFFb:ysy Ç5jTرcg._|U8eY1 \jܝ \ޒ$$Bȥ0DWe$]@)C$e˦8p\r[}urIǰf͚'ǖ.]TC㎅1(~;xhf<#k?ͬFWE{Woܸ1G '=$`,d!@|]p\gQJ/r\^oc%5557nxUUU_{ PQQ񡪪/+ٳg[zf͚Z~M6_g1qF={}=`w 6>V3ĉ(755pcl$|?0r] S 8=$ٺuCvbk֬^\M[hx:m`Z( ɓW?766{MzW\1g?G7nڵkWϭ[nݺ] sM!C~]׍ٳg@!b+?s3[&zHt%^PJ/$i0,X,Ny)S|޽{Ν;h4n喅{gРFt`gd0+ 4nРAEoʔ)w-?yz̘1[R駟4hm{i3fxQei!0zqƍX끙8V"I7̍]l0!#F6gΜr0?|}JJJ믿~󫯾h4#˅h4 ×;mTI*++{BEVVBq5\t'---6|G緿oB(lʕFJ (..~H$$iUڵkZ s@:0!~Xdʕ_.z𫯾> 7V}daaa 7OUVJ_z#P3{fXBeX 6}wqԩS?WUU {XL3 CWU;GL0nݺ] }ذakfΜ93+(Rz!5_^~UUU(l $IzR:fd8tPmٲ幪iǏ۳gn{s΋vq3fL9Nݾ}{駟,; _`kii1~_|6.L\/[re c}U{Bx#rJpJ np6x p1@ȑ#߿AUUңG,0D r7o^v}_}m߾=x>ܿUH*?>1 q֬Y_sR:t7'$_n? CZG0UPJ#uʉNctPr."tc-ZhϺuclΜ9  /0 cĉŏ566uDD,:nܸc$IJlj|00ٔsp; 0r9B&PJov\WH)t*8n(y֊ܯ_EEE۶mK.^y{.h4 0ʕ+[/>3x㍃b?+V;vnjs6n8ݑy!(Hn; 0I7mYs;rz^ #J[&M.n ܬkD"e={hk׮mbE-..@^2eʔ `zhf޽sNyQ00npIs8T=N}D믿>,㏿*Ps7"cm۶3dY~n[FX,fDQ#wtM3MMM=Kc 4A}3c} w?sMÇSkk sϝd!dg?{7ؕ{̝DRz?̲ׯWYYx|Z0$˿v\Y1*AUU躾ToҰ$I8O~=z{[׭[7:ÇzoY lP233i:c̳p55Mz~t~IGBI3 #rMn;ϸ[>h\si_OgϞ9s̤6b\.Q$P]`ޣؠ~oYN- B E4={.V?^:ӥe˖͚5kѣ/0 Cҽ]K,󧍍u3 UۮWRJYFinD^hccc!}%B2c^a3f̰kϔ)SjllgYXvS=UJe9zY\,BHoJi1LX`b322Bc־k]X˲`$%Zoc8i0p ߝ-:LY'G߁<@!c;`n7X8wgQtJЩHFy$"~o_ru/g2`' @Z !~,{PIENDB`ukui-screensaver/src/assets/weather/43.png0000644000175000017500000004431714205074704017471 0ustar fengfengPNG  IHDR>a IDATx}w|Uoz3j0HPbņ{/k]We-,VD-(ui H0JBBBzS; Mu綹gΜ3~D)aN7;#Nyt[8t:S[ZZbx ,ˮfVTQ?U^?tkߏTSS3vE1byPJ;Nf1I@)uLmvv&MK@ ~80~$I6 F1BL) g,˜$Izpݐ$ɑȑ#ߝ4i0?M$TV\yKaa},@dd$fqL!Q`4< !J>E @EH@ 9Nf};qĿ\x*}?_ iǎ׮]wAF'$$fFQVN, v;flǩY!IA@ an^@(H].mllDFFƿG3228_[tkbb"M&1h4"22$..uyd9$WQvt: (/ &a"W^yִ4l63F4PPIU$u|/<YKK Ax<:W\1okgSOx<פFbIFFfs~2_ W׋vx<x^|>I0A/w^x@^X?62N-3/;999`4fv6p@T|3zۍ`0A:^ DEIev뭷1bġ^ Eh+q&V\yѯ_?l6&DEEC(ȲxRC+$A DQ<hIDc,5d%I:FcUtttmlllyJJJA* B?7nݺ/rOff&gZlQQQ,;;vȲ JqR8 ,C8C$C4_$@7-`DQ4h6+3336;;TM ?7(rWl9r8&vjlIq\Z/W*"vjAD'dLeEcf( zz`bbbv61cƬlT 䬬7xVUf3 Dmk=tH,mnnF{{;Aǁyp\h  UmOE {<\.PJ>8St7a~N  4jm6~wk}ֆVA~|>AHt CGf!!!QQQ- SSpLs YEy Y|w@ ;sh :L&0J&@/*~?~!@C~00L HHH@||<8H(ԕQj~` AҩS>:k֬5qUSN_fbbbnb$66KTr @ p!y& fHOOGlllu8RpqVfPJ9J)X,!$1??o1믿ވP_?CKLL>h4Ll6#t멫ď:y^}C CAtt4RRR`4;t*T`0f(8v䴴4VZZ?>ڄ_I9:nS  >** F#W#ZF)=NrՙXtN}}Tj Y &t2J)u,)))_:_~j v{_ cLKժ֪p`ЇW1ԊPB^Z)tܜV#hpRھ5,˰X,ڤ$ɐb*GFFrvXVL&-Oh=t կ %H&G &-xmtuhӿ*,D#d9|ԨQ7L.:DcƌOM{О@EL&90˻n6dȐ`YYٓ+Vϟ'x_#Էo)VL&fXZSN G@/)j *B']w.b<I:dF f0H{{a<'T̛7oN1 0ǟvQ, Q+OA0uU= vrK{uj%VYV.22Rk݂ް' @1;&5i5N*z~t:pA=d2BTFߓrJ=1&O>`%O؎B 1#!($k]s2ҦT=õÅċ^ sj}NcMsw]m6PeY8qb%o{< W(tSWޞpjվ '4*U])uwNNL&bXdfcSLYW@Oc&A]`WwIpٕ׆~Cf=@ߧp3/z]z+@r,1cƌ$dkxx8J1p8M cl+D)cL3Pm#\1J^5]5Iz {@C; q>|J/ ! VȲ̔|=НJg IV\~nmUp` LsWLFO%5zǜQJa4СC톯QwQ\EEA;jIX  6SD$Gx4AӶ0%;]A&K^wfO{ ꜫ YeW`4;v`CC?66֤1  |ҩ'zkO+j>\@F$j[:Wje:T^k{sTpvcA)%`XmX:0 Y0^>/eÚeҩ^vg'B{2j5f@H;vv#9c fʼp=Zqkm8hzmwiIztJ5ݕϢ!~_"w'Ȍ1Yi$b?X1}L- NP:/l^SZ~-}rDkP~`kpL]NC(vU z`ttv{kэ2"2o/77wUNNguxg$K&".#Y?p]{gm2[ _Rڥp8g`'M&uM&2c1Q@8(IE7S)&Ƙ @D{{{+`F!Dxd=|SzB[n@^(v{\vpԎ?"R0|ʭq,MHOx7ʲlDFBѣf9 @@eX 3_ WZ .7o7۝M|WpY슡z39u;nE0$~'joȯ J (``(..>h43铠VJD$=,p3]y]@k5Au'K03ZMqzWv8sw Anc,mAJit·89A"m0 u  l~8gÓ+E2\ogݩpkƺːQ߮ZZ#GVVV~f>Ƙ@k&[D)cL! +///...7L QtLVwT7\Z{nvKwփ@w7L}Uk^oF AUꪽ_ Gn,2),,tXuIm;m AU4'Ng޽{ Z$IZ,hH !DEL)of>|>$pe?w©gck!mب~kx8͢7s]ipZj~?S~?dɒǎ۪4!c^\QB2C* ! {",&Y)*IeʲL%I>(o!$1(^ 6U gv%|p ,q%BիW/F(RJ8_A)hIVxb` 8v%K<|G+cr>` F !q!Cr$@ժmv>;R9Pchmsu]8Rg^ Du/T +, #v#$q7n_d ]N"%IqKړ'PDț=͜9>`;v2====555ѣ U2TիWq{FFFt{{㔁ej>Ai(5JAzY}vq0L$ԽQG8h S 2*"Q52YS*zN;1PMcVaڵ_hS׋B Ϻn'|/~I&M={ت4I2MTY=$堂 >>>n[M&g0(Z[[]UUUe> ! @ VR,Of]&<۽1CCCC]bbb}h *jԲ !Ue$)iӦ>ҤIS<>JV&``ϙے)EimYQ)c~9rbX !p,Qz>RJ!Lu(^?eqUUUbnnov# !$ Vw8U)FCh(AAab!a !fƘ0߫!-eYն=OFXxv믿w~9nHNN ,x~͚5(љ/LE9lcLgff=zC7@P]e4)jWRRRZPPcUUU)q~ :thI^ IDATN~%$$XVvkf0qLs=BP__/mݺuw}EqduRLi:PŁf,K4~N$ V-̙3gDDDeff&RJerqq궽{n^x !QeԬ|+r !f$ 222 ?###-...bPI[>rq(1#d/f۷oIII1Faz ZZZ ;s-)))F^SBQPr#РzrCA"!(7iLJ;΍͢(ju: uU3B,BO4QC%54scLz-^'>5J*++k}n7o~ʕ+RJ9A`mcNwzG]'Kvbc,Gz7hX|W %cuJ" 8Asνw~ʦ={ _RiK`-cܓJIe@IC{ZTC)Ÿ[o]WQQr\qqqk׮?bĈ{)tڡ.5 tn۸qVUUUԔ*!BsʷǸ_O'0(^/_\XXx!8Ȳڤ:Y 6~ܿ*$99־}}(zp6U}6Sj8H RJ1fXDm.f"...r_}UC=tl67Oddu##KKK Ahj:N`)S?/oqGJJYk׮ 9~7!DI|,ph")jc,hUl6fϞ}ksIOOO{뮻.v駻^|ſsw}^5贕.&'cNjbfBRچ7ݢ9ZÉNg˥E) 8p ϪnbX ݻw=Ss9}c56Ji+B)u?u-[z_|y]vƍ7jԨ>HBWzϧaT/81f8N$IdDQTU$~:vI_a˖-[`wݻ{ĈgΜ97###~ԨQi<7Kd7h͂փ#iӦM%cQ(Fehw6<쳷~fdd;\rɄ˗{(383ɲ;wǎܱcǧ(ݻw`tt4_WWW1~|N6 P"d{u@AzM_eiiiknڴ `1Qinx<." h~'׬Yg}G}x֭;ce˖-1cƬ^{mu0Ks?~˗?/}=L0555 EJLL]6[nReىFRC/^zo_m6l2>>>&22$|uuu.rrr4xওZ:gͨj%Bg׿z駗 4hrzzzoc+u]N6ɪU6\.וW^y!B[;!NNKK1cd۷nO׿8--L)u0c aPٌ1AA{_999I>l,--6lx%"jx@L}чR ~Nw477f3`ଳκ1㢺?oh{R~B\v_{433s;Ɣ[ZZť|voX&oQQёdɒNc6OJ!_?1cƌNJJ)S&]|/[~ I ?+>ꫯ~^wu#Tp P&&2ݵkׁ~> &Å~O@~rm]yWHIIv\RFF/((h.%B4ɳN #t^z: QE&/ FnѴqO?o͛ gp8Z[ Fj@@mm?/‘ &XhկX,?[l曟+.kjjx≫{ッh{{{ܹs-_|{tȢH|F #Rڤ j(***nztwBLV 9⍈,YuΝ@MM͏,,zξ}egg..//g{۲eKmAAA?mQSSӿ̄L !{6lȞ}?~K~a8 pD`„ geeMrEo^+rt_y~Φ&;|} `J88n8qL&SBݵapd9s|R]]c}]ull\tEGtN`nٲ% %$$ĘL&ӨQݲeKDCCCWa1yB<_͛w9sMLL8sF?ӯA!DE.0eʔ˾O:fY|ɫgΜyhD0fΜٿzEEҥK?]pt3AmRq\5I%Iro}%hhjj`0Y}* !o^ZTTTk׮9Nڰ9''opmm-۵kW[׾q.^|7R `!@(ŔY8.TL~zyUUUaK,ٶsZzlʔ)/{ws} }^sy)+ OhӷQJ)Y&Ϝ9rȑ#zhK|Yg9oҩ8!<@cbbAV|bn޶m[s=?jÆ Żw.^zcTX~|ˌHROyzb,F[Eaݺuk,YСCo9$___R*Եw؎ q^zǏO>NΎ$ ѣgqEftQf)IR,&?9#PJ' &^dɲQF]|Wεcƌw 7{7~G>rGG};/~Ŋ/IԆ^l[:tд}qqqM)sv,BHoP܏̟ە4M<8RSSN6mb1l6kLLn"""L .\VUUkfGYE9ritfO=)Ҿ!e e bF#oISny>@,Q_?_?c„ JCUT)Ng#gbb7xog}vVff)gWii&L),,YvBZ6\0<ˇ eggOm8(F!ʲEHv<˩Щ@&DQleYV^ŕW^9a{`0lٲU˖-kP9 GvIvZ3<}}=sss6k֬ێ=ZPYYp:{Z[[]N-tE@v>}Smc˲Z[nrzz|.JiZ{{;Vk :sŝ@Y_|l p-*.y2e~JL&g!TtC){#G B B. 8n`q\O_‹!F&PJB&, B(B8B衿Pֿ91v? @G}̙Ȏ;_ڻwoc566z>KcǎJ>LI" $Cq7!ώp8p\8ǥ" Χ HQJ t,Z2ōO{矂 n[d1IJs{hmm M6-"FDDw=&&&:++k( $.^>}T\wuYUUU(?U@MxmFK]A-5Դ1L2fȐ!q~ƪ*ĉ'v֭nyܹXYYY(I#F~y#<$:( F}[PPиe˖cǎy >D%_z?U9فQ]S ^cǎCo4??~>Cv@iii(Gydt25D`ʕo^y|%{q~V[[,))VWW>O޾}{lcǎ7n|[l)*:ƜN\WW'׋{m:|nӦM_S`xС;vXVXXxÇg@ 775+eee]Pv\TTǎ1wo}MQQQS}}c7nx7v644x tL0'IfEN>fk>7tӫ@Ff0dD>t c̜kۛ2@m۶?FFFҶ644jސ q\B~mݶp͏ =z駟rW޽6))644#G̼{ֺ)`qULLtݺu?CJJJŮ]|%kkkkjjģG<|~h_xsG۷|޽5;{!+Wiޏ1%%e䫯Z~17|Sv~d,wߝ ҥKZ㕲xAΌIݻwo>|yFxaÆEBn',Be---c>Q]]]7qytvܹsĉsZZZn:uꟳl۶m_|Oɞ Es]|׮]%>+vj~g\pY`?5*ܵp/?-={\.mFəp4Zj-r  fTTv`0e`b4ɸq&''G 9TvVl3d2Erg2dHƅ^8z7mEuuu;WZ C!$`rkkk7o^{?e?q˯꪿ZjYg8dȐxQŢ?JL@ȑ#&$$ `)S_={ׯoZ~}ömfV~}͚55!TJE*'T f)h40dĈZjM7}mpW^;S"Bȹ4D|*LכLL 8B%zOS!_fZ/p6B&S"T2 BH?f"8nZdc7 &A*S}[|_~}RRRZƘL)mP;ltE6"$I&} RQC F g577X/߿H8.UEuaR**5~3J/"%Iwƫ|DL8Ji,c,A8Ll63߯yu:Nt'xKB:R  Bii^OV(IVu={RnwWΘ1cݞ@`8.QXJizb ke!;aHV*ɬ<v#<€(9IGhV>}OJ(!?cI$7n̙3RJތcZΝ;w^K/KqF*Iq%Apszlo8(:(!لALJi q&)V9I (Ătʔ)?///wnVWWJJJ| ;w,ݿ}J{=iMBk&Bg1v~L5y͵1ӳV}O$!`0SK/ɓ'|&B`2]s5M:uUW]uab;Xz щT$S2a@^^>}l[---8ObbbUuEKIIIy?>|xNkk-;;,"""СCb~o|_5ӵK@Oz@0h4^xݻw1c\{֯_Ə6B޽%-^xi N6mG}$+++.??%&&l۩j54hԬY.Q;}WktD FUWWhjjj%$O>ɤ}lYcȨQf}C.ə~_:thdcc?##þf͚¤$5k*dBɚߌDv>|ԡCfGFFf{fϞ}رc3j;vX'|O6lؐ[^^ݽ{wb\n]y睗a4… ˲]r%⋏&_ XdʴʖHHHJIIݾ}e˖-g d2 7o >y VXzȑ)޶zkl&й _& 8Y2^|ڤ<5KOII1=zGd'zezqYc/9=|YG}>066]YYt@(_Wk'#Ç_4{p;!CA$`~t>uLe٥I8uEQ"7F0C % 0@ga`UwJ q 9䛸]< F,4NIENDB`ukui-screensaver/src/assets/weather/18.png0000644000175000017500000003121414205074704017463 0ustar fengfengPNG  IHDR>a IDATx}iuutuU`AR]AAy%%:%%CX{Wڰ ٻpZ]CiRä, "%"%QA@$`fz:st9=e͋ꪬ|;,`hhhhhhhh~+H\ Xj`k7Zs7 @G:cǎ -..꺞BhAw:˝Pnx72Z ĉ'z;vѣG=}UJe# :h5IJ(im/JϬ_[>|f2s~ .x>7MOORfY8l6L&MӤ"B$j=HHxFZu|>?tMw<ވ ^G 6EyX !ifd20MS.5ME }a(!ZbvvRʗvGy -~cb!,088(J,˂"a6hRȹ9T*naP2v}cs;b~+Ǐuj###Al ۶122۷ 6B]ۘHAE0q ٬r4M麮}:#;w;y@ \j Ǐr->Y, bQnٲE B4a?#'sObqqh4h6u]l6eElP(g>н~ RP/i^gL&عsXn]PH0DR"cffJf}A b'QAeYnnnݻ{X(o ]J ?OZppf0&''aB&\:Μ9Z0 }0 ERhqqQm6lhð8ΩWsCCCǶm2ZNZ ?TDv_g?Ąf 41::IA ' \1== Qg<]GhI`;s\.jtt';vW_ ,16=cό[|^,K_~4 i21@@.uDZV.@ !B_a{fF0 fLNN{UW}㪫:¥ 뾹gϞlB f!lc>9}D*AӧOu -@fE40(d 0P,faf0 3[]EQERJ) Лͦ\s-y{~~{ ]lh"qO~\.EͶml۶M " &qR=~mO6Өp]ffA$ui4MA&```>?b j Zdyۻ}{߾-o)+%|o e|2N? CAxzx0MLeA4ضa0\tA&~>4 c~~^j5r2 ‚VTm۶oweYzX4rضm(JXqΜ9uh4-@L5Me!@u`dde-q"prl61??YIv]7 HDLZ@`&ߟMjz:Չ'Buζm133#u]GV3( ð;o÷j g{kqL>T8#~mu-ƯzݘωԾ|]{OOz{{sL|P8Әݩtr[RJEQa=_m\Euu] !RД.1ׯ~'K l66iH_܃RD~NR4MyDQ$(qo}[_߷o+.| 7 !l6ԩSmR4u":ҭ[.I!U#ql="?Q%N #e..l`ڵO'LӔBJJvzI \ҹ'ٶM\ ~CTjcudi؍7G?z-( @d١b84MS 蠡9m$9, t0k*/0 Oh$PUtP}(a6r\NZ-ܲ-?h.HoLMM}_8Z.|LKЌm'3t3y+I;*< r?aرc"i  |Ǐ={\. BT(4۶mfm63h<X!!9cXZv &(0a e>Vw"h L}_k׮]S\NsG/rxxbQd26PiO @N9Yi]LJnD HQnA6`hhȶm#;ZtAc[h'|r?R/ fX6m$m&DPm M?-˂aLV@;hnJ*IHgR'D"wD\/~eV+]P-p>5=3o>w8====A65;000 HT;)9҆\m46"|=4\ cHp6AhQE("=oZ|iGrpOOfQyUW#r[tXXX@ZERB2CQtoރ拉҈i$kHu [^vE{24:_E}Sjl6k]v ˲ QӧOԩSEEsZ"l6\.$n4ͶI .촨^9 ͠i*xF%fhF!ͦ\ro۶ׇkFض 4PVq1=z}?a,`Exwa\.c(Jp]-w.:Ek%pJL܅f u(A [) l遁ڵK^{+KiސVƍ7޸0lBAӛ$8ؿ?^x qP(a c爐;E}ߧt,!qF\qpf3sYc:|n'-,[YA 2j(.8޽{T-YxD;w~C sbbBNMM 4s'DE>OfQ,8Nbyrul6QPVT P0;; 0pWc֭p]w`5ҼK3i Pf2‚ky6m?G?jmp>4@ϟrQTH?8z(Q. Ć;LRTfZl煞'ORx޾}Ig6nL&d2}ddi.* ƒ FGGߏl642mf/#t]GPHRN>JqiyTUٳ'-hcT:WMVq-^*8^1lz]gΜs뭷>t߹s X^\yכ)-B>bPV122x011\.0T%& i!O < hcnOON8|z׻(w1O5?jߣ֓-˂,KX%-BV3u]ewye# 7oJ%=L&i!Rrȋ/JE>Ouh`flӧ~ ahh(A6MZ}}7MC~@<.*JxСB L4@. ݻw_?44r9+hlZfLd pO>%e$'H+ТQ[&ASO=~_vl_ҘnQ'-}&(@0, o :GF5rb\.7Ǐ#$ Sԡl6?8CӀ~_Icp&r>66%U0D`:?5dߜonI󣯯i53WuRL?G  rJ&F[oW'w+ #U_0-&iҶ< Bb@n>j>~7"'@98N⩓k1Qڜuꫯ?^1,Y|4_WGQ_ir%b 0(|۶*XZO ?䘤%j*ms|>O14 @s 7|>/c,|X7ZU}i _E33Wi>>@Q6۶eRCcJ\f^T;i PJ;XLE !z.*i6/\-WWZx8 +iW ϝ<i 9,JF&vS2`Yg+O߻I=ˡaJ!v̙Sh Y@9򧃃a6E\6֯_/7l KM{+9hTʴa)-Tn'=(EȄ/Y/8uN< @O#vvMYe"|}Vu; :b3t>8p}}}brrR R-%Uʝ(U:͌QmB&GQko_زe f2MbK&<8jK">u7^xO󇇇Ů]$S#eݼW>W6>ЮP\5>7uJ% HEM]SJ)h0 Çχai+l}G߼k||ܳ,W^y, iܬ2^;$D` {@"zdfۋ #' (i}Su]yػw #[X O>HumݺuΝ;ePBWKSy̴Xy=*u;:ZjHqF)j"fN‰':e $Lt~2u]QC!o߾^ !FD7y/e]&{zzyjRmҤ3%TuV[v'V4)jqu]T*<Î;P.ۦIä @̧y uez]z'gggŭzyB! !Zt@`_ !rАn eNnAltGd:Vbt'3M"UgAL L:Q,h4077Gy$IB()-FZVFu+_/BKJVt*45\sSoo@2}tt4|DKumv86!\ɮÙiWk&TN&G89x{HbZ Gř3gpe%m[iDe'c"zl6׾{o !L)e</@LNNޔfe<*2hT;i&DgA!\sW ">HU0̻^'W_}DR.I"H4}ffz{վV. {Q6 7g2a۶#3L2SU0o0Mtͼ3W=B@՚4J3C%SYR$_ ^ΕL0 |'NG٦Ru^OSЌZQX\O ˲|!D"cd($݉Eg4Uhjju]_P`iaĚ69vM=)e-W,ğ5!D#6 @BdI!BYiHN;[TSOPgJV=iR{vnnO"Z ׏v EЈ6R4ҽ-!Ix:$-ۑ&Y@M~l!iiJ}vz.aJ2 0x;ޱ@(њ1CAO.I1rۼ4 Ja*3|> (i@H2rJs6ӮM3? ݀Sc "J۶ix4s5C9bx=f0gw@Uj:gHQuԙ:tugVoܭ.T8oWzOh ˲h47ڛ7o9t!D^JI[Gh-hk{U ӧ_m6B^n$)]S'{64iNS\bTЮyRxÙ(yRJ)Ҥ7j窝 5ʡQ\44TmmNs&;[O-8. Qa|||=7v(^KbIPi _&Q">2zK/t|۶m}ߏ<Ӄ im_M'uVu֐;Qi8 Q/?OsIyyj?t(i&@˹DO 3X%Zњ4M^/sI7}٧w~g G!`>쳇LӜؼysu]`L=N߫~[ T)杛n>BǞffz>j}_;qDxw|lF_/ t]7&Z0dh8߰a4irڀTp{XՎU7jDji񉮴$@NBG=ǵ/:jRݻw?~{\:Z&:&訣p޽w=k׮]bB"X Ԏ,vU8Z~jZ@M/tl0 1==- KQ<wj[&s!ϟСCeF!BAے/2@ٔ;ndRA (J&1;-x0w2 ,hPa'?ws+ZqStl@(r$KT+iUՙveYv. MӴ?whhl6pG'e ri8Μ4gO|2-9=Q1#hQېKu ggyJ9O@YmQFlա=ϓ'ʎD/y O?]替233h%vT.]-&6K`iVd(2%4I&!'x 6LoTT@2,l۞3K{h-yhz$g.5$(moX-HuaZ3q;%?F 6HOc|}$հݛdbii~`uD+8djA+N !(8Dx}}}۷oܺu릱,R177+G#G嗏ŒA >{xxxtӦM[7mڴqlll/W, p]gΜi⋯==36Sqx$Ӵ:W4Pԕ`i5^pv,^% @C>> hEK]qr__`@oobXv&15MӥAVkVՅ陙S huִK$Z%um/=R\(iQEz>???̙3V{ QI\r3hgP"'_Exh-߲iR("Z`p8xW$!+w&| Y-=VCH]QETO^jpſ &D͡&+%&6KJIΤV[`dkK, "{3i  - #f5 kZsGOK 0\G()h&h}?\ a#X\F'O*CK쳨J"i%L hj;wP/ ( ÐO -Ϊ`XNqݦ ",HB%@J3,Z8O !B)eiȓRJZEDI`H4l\Dk>irV$j5@U594Ջ 6ѳXg%@u݊ȒRyMG%%gakha:t/1|s?t1)'hfjRf(2e+%mE)4͏ի!944`FQd!(:S4͗Rz&_tu}!R{4Mt4Qr՚N'>אҳN/]jz#WɌ5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5ZJ ;IENDB`ukui-screensaver/src/assets/weather/3.png0000644000175000017500000005312314205074704017400 0ustar fengfengPNG  IHDR>a IDATxwWy7{ך٧XՖ-K H$|$4n.po$$@ b7ɒ,YnSZ3#x]3gښYZ)΁'St_/4ڙ[?.= 7|G~bt=yV~齳Gu˜_o=FH$y>3w}x/!t/';^ݸ޲KoPS'߽zuL -ؿS/3O\tfg~Ǎer3t%?yw飗ftyS3Z>[?U ?wy"v,̖G7xH{K9ީ6c}衪t,.-8w}fgHX\%k/WlKvjK]!+1++x߇s.ֿ'WegF˦yH?( _ڦոW~$*hsn>U+]r䭹jWRϳ^z/?_H[돇K1 _y?s vǿ{? V@Bo̮+vttћ-!uw~uHԊGVmW/JM񬡴 ?#) M]VyU9ĿOW"`k?!G_PZNmN7j!kđ/Lھg/1 )o43c\Ur0}Ɵ -~"Ye+ ޼ysmʚ%5t{"yFGlo {c>oycUx1Rć/R87[ {co~3{'SZ'VVUaס=/A= K;o6:H$O+ny`rOj?k5kҎ\o'{|3GH9ղ*Dݯ8_!=E5[ oYV@hjΊ+ӞHЀOvMvN PMI%lvּw):k\j: $@ѕ`X"o?]S%A VM%M U"`N ma6]0$58vwpp;?|61g >E݋ukf_s¥4i'۷~]~hla>\ׅ8RBf1Q 6";ob?VqkV|o٦Kg܇*.9 XaŶs:\\6& $0'61Z |F#6`h'1+I#CNAf`ZZݷuk={km%jr%H4?߾z`?Id/l۶m?:vد! \.q-4BضMeeY603kb 8"AoIsxV{݁#Qi^w0ydL{ ]꼲rNWWW%o l: H1S $cJg 8KHI `Z":]n={ģѝ{_^kҨek5&<5p(;..@OJD}wja,KT*j5j5J%rR.ŴZ#"AvfɭV A8VlfYS֭8OAc=@zkA>$p=ΦOo۶+V@\VmK0Q^8H'BXqP*000(ncnnD&Y&Z~=O?de4 N]:bQLe<+J@@k*E61DeSs̆``bDBٖԁAܲ(8vAl@0;vX}rUVŮJa^j 2)7cLO=pcHkVeo_۲Z$5HJt)=#ДF 8#IMNf@`$&i0F7Q dm.clJ,AxCPG޻Oq9M60FCCJO[ufe +: A@abHw\MDvqc)8#~ddLs` N'6 4HhlY*`(B@gT[l@0㯼n].sE^8Od(099v8a35"?AKI:U#J)hƾ#1GV; 6o<4xaFybSV*aRSpJ|Ď i@"b8btupw>m<;`k^/J<֮]CCCuXw@?ѯFǘFEv={ eAJ f8Yov 0DEPZA) H{fq3xcW]>152I@p\T&D uFzR@$5t b& R]33`.7^lqrll.]JZ8R FvG|˲`vжmcxx###"S V "6`m$@ )~F1lrLJVXL (`nvG(N"p]RJTURπ/m_F|`6FFF066z@3d۶>1??4 ض w0;'>w/8 /+c"h0 $2 &`Z0 P3"&F 61بԱ AM_?𞣇+/\9[~w8}H3`=V*}ߔe9< ,gH ;ȼ0!&!<ʈF4g9Ϋ_vZmzG5ojOxge=$c?~Yg]mY9#*{GlF qzw]mc||CCC=`(>2OBa8T3}|~] aH7扐 P6gϼvΰHIR[8NksʈA ٌj쏯nᕭFY0(24 =gdɒRrL-WyR+Ȭ%K`pp' *яZ^oj~\6ZM eŝE~˲-s2/W$ga15L(tMBY0*)RIt@d!'eL@!b KS㮸g=Pa@S{=e {lG?ѯ^~ !Rd-]T])^^wfDȌcݏXO/*8<QT*!B YrJc+йX! J0S\QD# td9w 0O$!D"}n 0۶m[}vV^;6lkײyqb"(B3*~^ ,TbF`>@OXu#Bj'"%y睃Ї^VWu500`_xᅼrJ./G.E[^ ? l ֜Ԣ%]i_uco~=C/囇wJk6B_qr]W{_4'Q~ȒC}glg"h執XzX>ٷܿ ^ NR'@&g_$k0F8k MaChӴ$;ΉCcG}^ uGj=qbsV[l?LdŁ?uyEu}E !>GaQgyZ'v&`[I5Hl4D4k:rW~Xf) ̜Lzz@ |E?^`@sH􁁁H“h6jΠBXH49!|TfhQ Pкj8~'S\zv2//"XDad,!y'{HPgb=Z߳ߧQTLl Ub5eFW:յK>r5&) igID-AԹɘ.5$;={NAn yB-8(}2dʸ8(obzt7bAx-9iYBB+RJhڃ첡yW?q Rޫu |)efK/䒍B8$"m(_t33}N Dt_1U48?_<?~EkKa\%khH)tA:H3] &"`A~sOV4yOget!OLad GvvdZ uc,-)Y5%T[@V3]߿]o?N bd9k.g13nѣGr((ؙYYS|A:% Rߢɫ47e1;_Lgci(=x?GeV5_!ys԰7dR6$ Ij"ݔ*h{+ٿ/| H(dFHd`(NUm۶mꪫ+/XjUR L'"ā.]~"7/VwBS1H93B3FGϘqc9ɗEbwx&rp+Z8o#psx@Jhl\~7v˖-jy8f! 4 9@ hV j&uarl bLlZ^Ś~DRnnbj][UC14 0X 0X`4gAdӲH5,4N 8q\~93c/ $a$7;رcjZJJRJT*z88|ϤIljlE-[R6_qZyv~j%**%o\8?;&[1=6ؖBX閬 @J0qٽ}Vg EJ!R`ὃP@oM,2=W~79Q̭y%'^Hc$nl6M~\.%\jcLfR"w~ܟD“T@f-0/P4ԲJFn<iQ=Aqan>߃ގ%"82#"E]pab$K~n:և]\=kÈ  tYR(VW%liõb8"D%0q񘘅pʂ! dK T 9xM$Kl|2H#]x9cK9a@`3!R .H Ufe?onaϽ֚\f1שSvNضS !;oA8EGT*ɂ-a%!BIyRf GѻAT $A$"Y%Ƙ| @_˷~z0jf)rO1:iGq刟UI2zonկ~gnCk8QfTa#!`XIɄJK*:b [ARM| dQ&!$,C۞x^ϣ>І1Ol(u lߛRJٰEqvt ^AIj!CܰtQ"R}tLPU_6ADTz/үTgsl6Sm|05s'=n y͚5z7}[9r{8 HYLA$# խb>g2,2Nlفa,Y @Òl[²}p|r=v7>uK{nx Ai*6=]X6vF۰e GpdՁg:-G] !- 逄  Ic _YH7Y"3#;^Zsv-|?!`ny4ؠ+Ƙy @"|Wj3QkM*!ѹtн2 {ga.Pq+5%L;׌_tH̳3Rx5iR29Ljäj%+v |b&OL~lR&@T2w mSCs~c* L$@H][N\ '9Iaf!{ǡlVO#O: o? #tf'8p㷼HmiO~.N :6S$_~ n|MOڒTJ@9f4Gw r#e I@F3sѪ-DQEaFè$ii#`C'eoA!w%s6ТװwIN@S`Pa3 K%Yށ+ρr t3Q2+KN_%scǢeN! ɻ86azgM%Cy{y#W,Y(egwړDGRT?0@vj2HM!΀1`~KFf0sV6`ljJR]j :1=2 $-DWe,f;!:?Qnu=tcd~|R{̷҇F'W&+N\$tXQCsAu=9JTdZd楀[%xN@(cjKRzXrNVq)yiN*fIu0Ա0{ s՚U<&خ]LaC#inCL1m~p{H Xk"PWd{ )'P[ .{Ru Mm6W`&' -Md[|]?e 4}cl:Oع}ߡ౳FJ翼Rs7wKcTw|yֈG`"3 >oLPU`lM`mt`>Bs=#˂opMD̑6ϷuLtRg/F>gh*Rm[gDd,$@N~Ӛ#KYÔPzt\̬<`+j߉ A24JU'QIn:Vhy26UM^Z1z\02-^%@xÇCe^)f ic~q[w^HGAwGu>P }'rތ&8F$LSʒ\׊X k@pC\  D `Fg!09 58qCUE( Z'|1 RLd[[ Ud _E2~> P]y<=HX9NJg?CgI(R PQ8@XI " X?vm,w$mVwCgltiTRǶRrsΚgi8l)#"{'U7?lk{7b`s?;,M#_~̗4`˫H|`/~DqULg5dDs`rc!2ƛp$`8:{lB<W8[w]5쮗絛Xp;;mt>HMx"}BX//^|1|ap2_ǻϝ^6LӔ]sݥ荷z6/\|J|YӯIBes*:/ų^fL TEVC+!i-JloYFc+*(ˉTTްѬl".}ʸ[^z.R:?k/m{Xm[ic3s.ID)/ '2{!O-? WPȖ$=* 5K#x^Ge6@jeDy굋dM9JcԜ {4 ḦPR$?ce{3*OٛH/ҫQE!8! "*ՁKb3_{[* i'vD(J/Hjq/E;AUא(dT@Uu%]~ ?%O]Jq~n{ J;zf  Qϻ:ꗑɀ+|C=)I0 8\_{{# s`$0ff"9@%ͿpsLӌhN1,m Te%0lS:*g_#G򶭛BdIrT[ ֝, xΡ'hX&*9(e ȑJV6&tV42\Nb~$Laǜ[=d!@T&1UZ26K'de2~57Tvjło?8.M 5Y!{S 2G]KxUxp ^^8nEꜟJ!^A:E/Z"طD8$̟Ovq]_*fRת״v 0v^杦c8Ga"06|Cpɒ[ct._:||.S037@'ڲ4aՑ_ժh>x)IgWO p3LA&2)| y\xox»i?[ 7pY޾h nXX쳷UgL 5n{v  3va:cƵPNke-YcӦdy/z -k_W*V.1?ǛTǚпӧ? vrB>&y|`w,mP`ׯ_MSC<7;ۚvmڡ ! ,d߯/]g'cWeʰK)h̝1@Fa*`>k(̝RKسwKyvEQ4- UD.wսuetvD^PZ8DDd YqXK}R岨W=gCEY9/~-OEiI~ ZAPDR zN/˷׬mWE8Ac5f78ǣ?4zx9"DJ䠟Ğ7YɷGzÇn@2̕" z7!@MKciY,:j[m3Akަ{\2z5/kR';(EÎOݘhu 'ND%`Sd]V2s*?"FQAj|S98P+Lޔ9=oc^f Trg'`;.FP6J2 d"H{ˌ>ipv8[on !n aAԝt}?<҆NUx/_y9 c3y)69aBX!ؙ,z 8&Q1ޒZvP[yF7.KO!ɢEkh!HQXwgtz~y#^V'{_YO# 2K.;S&~5&vD9B7d")6X/֕M(w,|eCVu9 'gY-ߌk{Y  ~4z6Yf4B^wM}U1pG|~} +|A6ypb s?-IАngrK5{(UrA>/'M+[0x;õ{mdg^˚P`x3P1Shn&5bҬ~hQf-RE_ :'P m; CIF5UU}0\(~k?~sڹ;ۥvyOM8QHRY(LơdIQz~4&LZ@wa3ۚA"~"M|@iiXղlN&bMUU/w]܆sdaU>J2h"wiC'24ͻjZC؞:uNێvE@^i "eaj'nX 'fp\:mwXV{>>MK˕x3Vv4ɜ,{wxs7tJ톮]).V:dv]vK;vH8hnq0k|4yՙy 0s$!N_ٝ|8`P⡇~9@@Y~ǼQIHA.NxlFIgo?v7P eͿ:yϋV~4`k?IŪVݟ:݊RѶ`WTfO!l|l.hf݇U<;V[䫇 inŔs3VWwz%|:v}!a;2AqH2̈Uˑ*tǁED)zmVMKAȍ 8Z2boCÁq$ KY%D> #@rН̦Դ܍R>&4r]w'"9x_6|^UV^4㉌2d~{o?N8dGNž"_ҸmKBIENDB`ukui-screensaver/src/assets/weather/4.png0000644000175000017500000004330614205074704017403 0ustar fengfengPNG  IHDR>a IDATxwř?y{]iJ(d&8all33w|wNl8 M09h@$$V͓g1ݣhf~tUycU-& @`@ (KU7׭[1444ɶ!D@Z'M4DO0a̙3NRnGmܸ-[dg)J@gaĖ &:cƌg,Xܹsn믖 tK.`ݺu/ 3 @$A(eYR2MD֚lFXD>ԩS?n~{svZ@Eysx\ H$YLӤp8상 "h.۶Rq.k53m2 ˡN;]݇Fz;`p׮];n-[>؈D"e)"BhiiAkk+544 BJ ! 5Rmm#!N(2 p+ Ap kaaYB B###E>8m=SA(uN_|>;jP|bg8M8Ba"GMSN02A;A X,V48!Ql6k_z?ZC(+1y%Kq5,kmm5(LӔ | 'PKK ǩAfz-ۋl6sE 5k ff.,2 455G"ߘ>} Oh`@0?&LXP(dq>(L¶m `O zJۋRTq}{ Mj'ȿoqvB覦M/q/\ɩSso  Hcc9{p؉FF8qG{0ד~_gYl۶ muݤ!R "aoF|R>( ۶Q(`6"ٳg?xߜr){ X,6cتx<d80w\J%Tvk13sEEl߾BT* 8BH)aF&ttt AJY;|gsg2d2̚X,l6 ۶1cƌ>+O='G>餓~q_*pѨwLKtX,V_k]ai0M0m4L8B PKdYro"ɈB3fsC];78&`^: 5444 GMp]wLW?22A8BbXaaY À'N *u="R9JGy9Ck>쳿q{wdY{Κ5냡PHa9i$1cF5q5lȈW5_ @(iØ={6:;;!4 = e p |8mmm y'8744P0M;_ VȠϬH$9s uݤZmwpP&Li488OUd9/.~|$B644">#Vζm0s%3 }i5MgF,c Ï&)j""444@ALD ljjrFFFf?SwwAC@p (4P"M}; JKϠS7uT ΞyjF}[p"4M466".gl@ af)%K###{HdB{mTohh@2RabTM U;(PI)%!kd2iO~/; 28 aX, m۶4MQaGy~`v Tkkk ~HlWu.CZ2[ZZ~+~^xxAp `1seYI!K)t*iRѾ4F"b KR0UhU'---;9A21c٧z/[[[ab1FvVK`n>`޹Zqh1:: q|摒cPv| UP(P** Zzo}wc9ڨ6hr(8캮( :uɆat\!5?01 Ü;w.xFIk]:+US}Z*o6>A5-?*׆aRJ?po,K̤?ɯ&@P]v};w`2tܹsc!ײv냟۶kckiÌfSMc>֞c/LD6u :::Κ5gus(j8ϴѶ,˜6m/^LUKOA2P(TJk1:~+PݾPRt8Rٶx<=sN:_uQ<۩}wyIکSMMMSNA"< U3 jZKf T_S {;_ &AMu]U,R$2 l۶O~۹sn[d>þsg|H$b.Z̙C~޽:Ydo( Jv=Oۿ_#w{`)`ojz`umF*BX9: ?K.Y'EQ*/^LeIDr*Fo_Z‚`&| 8X~j;zVbǤIn7q K(yF',SLA8Hv-O@"B.C*k~[KD{TT>Z+D =x]{W[b0MSa}{ַ> Y1 CFVmtfYRqf´AwwRN\Oo˲`Y0(88544pCCD"rʔ)v>?=( ~Et L&md"x<^7?~]}pFnl=ml=#z  NU$ Uf7cyeuD"V{{{)Ͽ? 97N&4Y W{\ ak9նVVXWU@mݟ[_}/(L o)hͅ@TCjI0,fի{SQ>Y#8T YҠFMC8F$h4Ji)S%Kk2mƫ$64YJ 0, >SQJ!jzRQşFFn^?rnq'sv~̬s̉E{<4^ oՐa\/<UA M7-PAQgWF&(s$iv̙3D9e"TKO?d X/ ?)F4o&! ! Rӧso{@lBR)&""!, uioZ}u)Y&l;x2A-FB--|Ȳ,BR)ŋ/ 63LʶmU@b,uzQ+䫖Z[+պ/Zg %|!GT;> oАAyƊ4儎೎Gz8y;n @D$[RJuJ6M[O5V?H-I%2}`V&uzNcꝫ6{ZMu''"B3#O6Mo`yWRJ u8fCSAi3(:Վap V"^B)gM;8>u?ADP o"}l޸q--- Jm[T$w kMV{jhYu|c9~so|i׆.x}wek|ZS`ڻI`J) e*1K8hLD/?rJDl)Lio*5`]ϞPt=t.Zjȧ`;{,+6(L!x"jZbŊ5l6d9(zZ-՞z-Rc9:, blZgbT;yk=Л'v ]JR2ʏjED.3Џ?;;;neY @03۶MiVPTPDzA mV|9 F!VKd3x~,{]fzi:@3IuiL)eC()^*2;wϛ7oRHp`nLZ.k)XDZp}B C=mXMT~ iJ>SO=u oB1BJii-`QbdddGqهٶtƝoNb~#Wⓠ6e$|j&{TS5H 뺢?ZqFac 3D4ih4*J8{`nWK{-W\P5c`_-A_m A>BqߛSh~ Yͱ X@I? _PN}x7Ȱ6W^۷r98rL*<Q(3 8E_A\͠ cH5[5O۩fjyEX\.bڵwqϔRYyMkҾT("vilhB#N\oʕ/kllL666&d2&x̲477OI~ e\PBZ1!DG'O{EO%R@0FٯP^'{ɓg23}03{L<걜 & |B i[24Gt*Rg VJ qGY /,Rʐ|'?tyrtyS)/K-[8sZ= 2ﮯ~1-)!t4ȁy^HwNFGF3+ZY]Xt}}}[O>sښ"\ՎT /U8Zc25CTR ,xMP(Jm0XQc 1)xWZ<^rR˲dĉ'ML&͉D!a̬mvl+`2"3QE$ GDEflLn =O[7mFRZ HTpD΀k&][$ *" յk…'q%Ʉ/YbQI>|{ `A33fMMM&NADBT҅B0B!, { V\O3ϺԴ<Hx:_]3H0C$ܮ_ R'&_Ŕy-_o0C-ņ}p c /Zա4 #Ǔx< RJKYvTgL:Itzuݜ7S fQD H$D"Q0B(;hFV)g2KR@)"VFN*,+aWW@ҟFYQƸlO6֧MNthGS,V=pV/%AU>o[ !4]F8.J|OMZ=_03(b{xxwxxx[Z%`ID2YV(j6Z\.7冱A9YDd1 -bƐ!?# ?M\YvW | A伣'SVm?y6~4% \qi6x)^1hA dM:K`j)cUSH=H {'x=!UM6fPfLM 4hb-;"c*N( U̙d0C 2鑲 :o~N(l CnA׃a9DУ.fӗ"o)Kr.pY5٘3}s"ob-~ҕ] dm2l-hفE0#xλ96n + ߁_y6 )3A /b,Mfs/'բ,PX@5J_y cO25yug}?땥s~k/d[jz+zڒJ2Dp2W(@eh3qCx{Bf= r]ifz›} eLLwBzӀ xN:wa9Wnṭܿ%$(@|fQ "*}B=Fx(  h&ɣWOhQeo: /נ IRL(!OdiX$MT2Y /pfRU>}F7 ZE s[qӁ|uƒSBH4ko!vKC(h k"p]Y>}A4;nCJ;!IͬP0[Vf4Y6 BӉ\]f#7♭}P,j&vK L 6fA#ӽ9(;/2.g';j&< L`&0A7]G@I h`|I2oׄBn 2:ߏs'm위C"wˆ d€( [@ۛUˡ#{6ˍq)D2~"w{H d`"k嬦 ]l0xɜd~11<ɝEq-~@=o|b%LS&A &hgJc;0'y̡ǚ@YdSdU>͝RZ ФN =X6雀3`)Ykxo "RJ1FG@t?q 9Fe S fV.X!n;#Rqbm>hZl0tlL2\Ȏ* p R(4ʔ LaНce* ʁ0DTC+uR\oad%;WՎS1lTSr}@ JNmXrfHP&cQ;S(~b. r +YI"V`!L?5@`r93ޝrA\[jlZ:$4r[Gq`MuH@B4d^|qC0 j;826I?Jk󀛂4`BOea0LM*k!ܠCH kwύ5"_^g5w3sq$rB! P?/(0  =}ͿŮtla"û\m_3ՄARҀBE"1`;^gNwPΒ[D(PU?hmjD"L=B CG,\pղCy ;V?(Oс;#:{¤4M-L(   e | k_XP,ҀL^z普_S?) v7= de}kJ:P&ͭ#Bk6XF0'I,CMujH?3?R]W:LFSe%N\ԖT %@K{%{9/(,w8¯tiꗎل#Ƨdaa&ܯf"vu/n+H0Y" Ӕۄ!.k{ sGڴQf[UC1l% TLIla k*52*O /?|Mcu^uf^6uꌇPٍNE0!~`K0K/ac/a\z<+[N]rKXGxN89_NB` bfn³$P0,bQ֯[cbjX)GNJk9 J d]K}KI\C6KN#Lp \dЅa /r}(za ('`UΑ5fI wx9)eN)CcǜQIWmQU †[&/:PK DXHS9`#inhXktyʬ=\7_@'8 w#^ΓI)|:A1IL\$4)A`U4c`t4͛}>dyghJlhG uyeOf%ACyMq|!0Mdy> .׮E%A_)5Uzl +stѧ{V_t9.W}ӴF w4aG[0YGY9,ei &wnnGfpy*yf0+ еwaYƨ<nD斩DmA'L_u͝@ W"F*O1YRfFZ<_,o&zwfЈ@7˒#Glҟ7FԩLdEl,'?Ey-0E縔ZB$ 1=8Zc*ځ#krBw/*U[uIZ[v2ml+J`dzM,W1(D4rF ۯW k!_E/G>LYax#IB)`*L".Ngɜ8)>( Xŷѧo2`"C1g]%-3&Lj"L̽ B#p59D be݀G&8/z8(b L *ka %2J# il m}37ʉCRvS~]ZtaG2.: Kn\In1I ܈:́_[w%/zGѾj#\`΄@)ckln0f!Q"6ĢI ;h;x\Rk=y0& CrI0HsT_Gx/ܮS٬aReU; 3. ?إve UF3Tt88~ؙd4$s99+GDG) mRϦo}tfSC71 K6 r~K_Bpo7^|N)XK#j)6/y|cx=q&"Y2t`Ef S ^^M|_ wdHw$Qha2Gd !f #6P4':oz$yJ==}އU1?p @g~p'D8MF\X*|U|G=Wt~ Yfezlh~cXkK6߰ihoq& "zuk*-Ѱz㏝w>+,~Ͻ:i# SA"kri֙͡2{յgQ^9 Sq"c:ÜI3psia kQZF8Ĭ̥M̅u$z4{9F{>ip]-~ Ghm`Z-sk}H*š ?HD{ݫ J_`=fDxdLI;bpO墍x,y'ǝ~y6mGd4-m~i{ݙ&;T-7*imKܶV!0Kr/TO(DŽP@:mX1>D_Jwޚxt0lPLm۞ !fBy{~ß=(oڝ8w `b9isA\\ϰׯY3Js6MQIWC8K!@\քB~bǾNl4DdcUԖ/o>Ԉ, #lBo`"f!`򾮷0vNM5y˭_ e՟E9+mT:X`0)IY.$hHk+#|O!ޛ'ɜ vIi IۉhG!8ejBqR 6Si/Opʥ4oFyKՅژ͞իcAi]pN)es>q-:E)<נ@ (KLO'3y8+Bi8rC=kJ3w{Zb3:B7߱c [3h($j>By&i%JK7tP y7/{~&!vg~yg~ G|F)r'&LgD]{ W8/"L'R;!x#~xC9DFCZkAv{AX-QjWăM!CD`R@22zq3`a 0Ui'v5(ӷ0]?xFaF]{vb(200ve~alf --"m^Ɩʽ McMQ>}7[M f/(ji(n|Onˆ%2dXR(7d]rF\nXaBG;Z/zm*-nXJ9uet_+޼B}wZIlv֔>SY J)e21t0֠>dO :jRVۗ>rmsM)fӅ^٦i~0=u:GA뇟`X'S_}~y  K|Ș4GM=ޔUv*{oyW6Ş>Ct*̓D47ImAi;'GvJ EB'/"k[R,۷pZNk!)吗2~֜Kg23)(_mXuő>%uIDATWv~O#vѠk;2W `xnY_-*}8y>T i(OAxJTeFkTTv(Ъ L[h&i M8;7go> Lc@Nd]9گMJRQftZ[W;TV @U,^H+8G?~SMjIӊgF1B]:0>^}MPB)!wg$> |#OdPBN ?]PNB]O |ktDhd|Vf8i \Hv(]eeys:/Ue'kmko;WTF1kt~R35R"ʵA;yo{^KU.Pς (F@К|D{et3բǞ?gڙ?{m}2ٶ?Y i2d5"`%g2ki*:ѽ/W^1ߵV)fWSx@H)O3fxe:5"6׬]v}zdDDCf7WG7ڲJ 8&\mԜN#UD4fRY6Mn2g^0ȇL5Jѐ[xKŕ*bl+kpw5v[j^~3nm ycGއTa+A`@Iڶ!r躪3Zf.b>t?3q9сF=˨ʦ7aqcw>] k}[RέO"m.ʎıGJqn,8"U=Q0-qW\WƐaH{ms 7~E@ȏGg[<߽ųH{F;HucKy.M F?BྫྷH%0+Q\c#K ?=y kՃ+BSLDPZJb{R%>P\,s{d(yB@1YtX:˶ڢhINH&<ˣoHN'ْOD9PQ}=kg8`#Rq?OLBVTtc52޲jWg^䙣_qK ]J! 0ݰ3dY--_$;vṭpڴ%0b¤,TV^r-- \5iV]"I6uBV,\yZHr@Z6S cY8Nf?0IPQqUv630y@6os:9&? IT3q왚KXց i~g 45wG-x ~r9+6i-4&fFG`k̺ݻw"jgض0J~fas lA<OmZkmc1~ Boڽ$3U&n*U)cLލqa IDATx}iuutuU`AR]AAy%%:%%CX{Wڰ ٻpZ]CiRä, "%"%QA@$`fz:st9=e͋ꪬ|;,`hhhhhhhh~+H\ Xj`k7Zs7 @G:cǎ -..꺞BhAw:˝Pnx72Z ĉ'z;vѣG=}UJe# :h5IJ(im/JϬ_[>|f2s~ .x>7MOORfY8l6L&MӤ"B$j=HHxFZu|>?tMw<ވ ^G 6EyX !ifd20MS.5ME }a(!ZbvvRʗvGy -~cb!,088(J,˂"a6hRȹ9T*naP2v}cs;b~+Ǐuj###Al ۶122۷ 6B]ۘHAE0q ٬r4M麮}:#;w;y@ \j Ǐr->Y, bQnٲE B4a?#'sObqqh4h6u]l6eElP(g>н~ RP/i^gL&عsXn]PH0DR"cffJf}A b'QAeYnnnݻ{X(o ]J ?OZppf0&''aB&\:Μ9Z0 }0 ERhqqQm6lhð8ΩWsCCCǶm2ZNZ ?TDv_g?Ąf 41::IA ' \1== Qg<]GhI`;s\.jtt';vW_ ,16=cό[|^,K_~4 i21@@.uDZV.@ !B_a{fF0 fLNN{UW}㪫:¥ 뾹gϞlB f!lc>9}D*AӧOu -@fE40(d 0P,faf0 3[]EQERJ) Лͦ\s-y{~~{ ]lh"qO~\.EͶml۶M " &qR=~mO6Өp]ffA$ui4MA&```>?b j Zdyۻ}{߾-o)+%|o e|2N? CAxzx0MLeA4ضa0\tA&~>4 c~~^j5r2 ‚VTm۶oweYzX4rضm(JXqΜ9uh4-@L5Me!@u`dde-q"prl61??YIv]7 HDLZ@`&ߟMjz:Չ'Buζm133#u]GV3( ð;o÷j g{kqL>T8#~mu-ƯzݘωԾ|]{OOz{{sL|P8Әݩtr[RJEQa=_m\Euu] !RД.1ׯ~'K l66iH_܃RD~NR4MyDQ$(qo}[_߷o+.| 7 !l6ԩSmR4u":ҭ[.I!U#ql="?Q%N #e..l`ڵO'LӔBJJvzI \ҹ'ٶM\ ~CTjcudi؍7G?z-( @d١b84MS 蠡9m$9, t0k*/0 Oh$PUtP}(a6r\NZ-ܲ-?h.HoLMM}_8Z.|LKЌm'3t3y+I;*< r?aرc"i  |Ǐ={\. BT(4۶mfm63h<X!!9cXZv &(0a e>Vw"h L}_k׮]S\NsG/rxxbQd26PiO @N9Yi]LJnD HQnA6`hhȶm#;ZtAc[h'|r?R/ fX6m$m&DPm M?-˂aLV@;hnJ*IHgR'D"wD\/~eV+]P-p>5=3o>w8====A65;000 HT;)9҆\m46"|=4\ cHp6AhQE("=oZ|iGrpOOfQyUW#r[tXXX@ZERB2CQtoރ拉҈i$kHu [^vE{24:_E}Sjl6k]v ˲ QӧOԩSEEsZ"l6\.$n4ͶI .촨^9 ͠i*xF%fhF!ͦ\ro۶ׇkFض 4PVq1=z}?a,`Exwa\.c(Jp]-w.:Ek%pJL܅f u(A [) l遁ڵK^{+KiސVƍ7޸0lBAӛ$8ؿ?^x qP(a c爐;E}ߧt,!qF\qpf3sYc:|n'-,[YA 2j(.8޽{T-YxD;w~C sbbBNMM 4s'DE>OfQ,8Nbyrul6QPVT P0;; 0pWc֭p]w`5ҼK3i Pf2‚ky6m?G?jmp>4@ϟrQTH?8z(Q. Ć;LRTfZl煞'ORx޾}Ig6nL&d2}ddi.* ƒ FGGߏl642mf/#t]GPHRN>JqiyTUٳ'-hcT:WMVq-^*8^1lz]gΜs뭷>t߹s X^\yכ)-B>bPV122x011\.0T%& i!O < hcnOON8|z׻(w1O5?jߣ֓-˂,KX%-BV3u]ewye# 7oJ%=L&i!Rrȋ/JE>Ouh`flӧ~ ahh(A6MZ}}7MC~@<.*JxСB L4@. ݻw_?44r9+hlZfLd pO>%e$'H+ТQ[&ASO=~_vl_ҘnQ'-}&(@0, o :GF5rb\.7Ǐ#$ Sԡl6?8CӀ~_Icp&r>66%U0D`:?5dߜonI󣯯i53WuRL?G  rJ&F[oW'w+ #U_0-&iҶ< Bb@n>j>~7"'@98N⩓k1Qڜuꫯ?^1,Y|4_WGQ_ir%b 0(|۶*XZO ?䘤%j*ms|>O14 @s 7|>/c,|X7ZU}i _E33Wi>>@Q6۶eRCcJ\f^T;i PJ;XLE !z.*i6/\-WWZx8 +iW ϝ<i 9,JF&vS2`Yg+O߻I=ˡaJ!v̙Sh Y@9򧃃a6E\6֯_/7l KM{+9hTʴa)-Tn'=(EȄ/Y/8uN< @O#vvMYe"|}Vu; :b3t>8p}}}brrR R-%Uʝ(U:͌QmB&GQko_زe f2MbK&<8jK">u7^xO󇇇Ů]$S#eݼW>W6>ЮP\5>7uJ% HEM]SJ)h0 Çχai+l}G߼k||ܳ,W^y, iܬ2^;$D` {@"zdfۋ #' (i}Su]yػw #[X O>HumݺuΝ;ePBWKSy̴Xy=*u;:ZjHqF)j"fN‰':e $Lt~2u]QC!o߾^ !FD7y/e]&{zzyjRmҤ3%TuV[v'V4)jqu]T*<Î;P.ۦIä @̧y uez]z'gggŭzyB! !Zt@`_ !rАn eNnAltGd:Vbt'3M"UgAL L:Q,h4077Gy$IB()-FZVFu+_/BKJVt*45\sSoo@2}tt4|DKumv86!\ɮÙiWk&TN&G89x{HbZ Gř3gpe%m[iDe'c"zl6׾{o !L)e</@LNNޔfe<*2hT;i&DgA!\sW ">HU0̻^'W_}DR.I"H4}ffz{վV. {Q6 7g2a۶#3L2SU0o0Mtͼ3W=B@՚4J3C%SYR$_ ^ΕL0 |'NG٦Ru^OSЌZQX\O ˲|!D"cd($݉Eg4Uhjju]_P`iaĚ69vM=)e-W,ğ5!D#6 @BdI!BYiHN;[TSOPgJV=iR{vnnO"Z ׏v EЈ6R4ҽ-!Ix:$-ۑ&Y@M~l!iiJ}vz.aJ2 0x;ޱ@(њ1CAO.I1rۼ4 Ja*3|> (i@H2rJs6ӮM3? ݀Sc "J۶ix4s5C9bx=f0gw@Uj:gHQuԙ:tugVoܭ.T8oWzOh ˲h47ڛ7o9t!D^JI[Gh-hk{U ӧ_m6B^n$)]S'{64iNS\bTЮyRxÙ(yRJ)Ҥ7j窝 5ʡQ\44TmmNs&;[O-8. Qa|||=7v(^KbIPi _&Q">2zK/t|۶m}ߏ<Ӄ im_M'uVu֐;Qi8 Q/?OsIyyj?t(i&@˹DO 3X%Zњ4M^/sI7}٧w~g G!`>쳇LӜؼysu]`L=N߫~[ T)杛n>BǞffz>j}_;qDxw|lF_/ t]7&Z0dh8߰a4irڀTp{XՎU7jDji񉮴$@NBG=ǵ/:jRݻw?~{\:Z&:&訣p޽w=k׮]bB"X Ԏ,vU8Z~jZ@M/tl0 1==- KQ<wj[&s!ϟСCeF!BAے/2@ٔ;ndRA (J&1;-x0w2 ,hPa'?ws+ZqStl@(r$KT+iUՙveYv. MӴ?whhl6pG'e ri8Μ4gO|2-9=Q1#hQېKu ggyJ9O@YmQFlա=ϓ'ʎD/y O?]替233h%vT.]-&6K`iVd(2%4I&!'x 6LoTT@2,l۞3K{h-yhz$g.5$(moX-HuaZ3q;%?F 6HOc|}$հݛdbii~`uD+8djA+N !(8Dx}}}۷oܺu릱,R177+G#G嗏ŒA >{xxxtӦM[7mڴqlll/W, p]gΜi⋯==36Sqx$Ӵ:W4Pԕ`i5^pv,^% @C>> hEK]qr__`@oobXv&15MӥAVkVՅ陙S huִK$Z%um/=R\(iQEz>???̙3V{ QI\r3hgP"'_Exh-߲iR("Z`p8xW$!+w&| Y-=VCH]QETO^jpſ &D͡&+%&6KJIΤV[`dkK, "{3i  - #f5 kZsGOK 0\G()h&h}?\ a#X\F'O*CK쳨J"i%L hj;wP/ ( ÐO -Ϊ`XNqݦ ",HB%@J3,Z8O !B)eiȓRJZEDI`H4l\Dk>irV$j5@U594Ջ 6ѳXg%@u݊ȒRyMG%%gakha:t/1|s?t1)'hfjRf(2e+%mE)4͏ի!944`FQd!(:S4͗Rz&_tu}!R{4Mt4Qr՚N'>אҳN/]jz#WɌ5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5Z5ZJ ;IENDB`ukui-screensaver/src/assets/weather/55.png0000644000175000017500000004000714205074704017464 0ustar fengfengPNG  IHDR>a IDATxi%Gy }ݭnݥVZXc!/<`u0f㧣pl/6d#DI))ED|?2jTIvツ3@e@ԘMK>ypńrMʘR Pwf{>J~AIB!fDA$B!-6 EXfʼnTg8~2JZ,8fŝSOctma"g[n:T}%|޴Ty!a˖UǏ<9r𩙉R9J/XQ!6@J1J)(7"|ct-Gq"ھ}7G~DBG 6:DD b~ذ9E)|Kc<ۯOJ&p߃َjwH$"q؊${[jLSI?yUerLI js~;FtN!_ޅDG1A)¯};SFe\kH}Te[($; z3Z4|Hsz}]3tw! S 9C ٫G(S#Aɧi/GSX~g^f(7?er%=|R/:"E'_|G}x"1xcGK~TX@D$P2]P3+(ÀbK* qx87cwOzʋ؊V"R e~򦫙pG&DWLN]0ƌq"Bq[o]2ď|."6TQ\KR*x_O_o|)0N1"A~qPq@|e`{!(I\z|߇n/y1TK(ʅz\mCƃOO{7Z:p4~{ȇWqWRzV|q0,WK뉈pu2奞6F ®]~#93GRPO~;!HPqY~h`CF2}Oo+p_g>.83s@?"j{p97@6Ml/" d E˜LgRf8o=y5}:x-o~O@&wU?}J3&0"?{'SD)<*Q'LH{>D@1^/8JG,eʭ?wCRQb"{z/< ]ӑњj:J")ň, RJa˧8`ک$)J75*=$x:5k7?O[zՖˮ9bdZ訫R2h"H9@D"%1$}>9 l?H $

=,:߾>ayw^ꗤq"cL "6 ݯbGT؉.}q82qJ$$4^0%)Q%tl= `@@e* %5bfL?po_3LSI,D)%vo""{Q_|em c $SB Aqk[G 1Mcˈ$Ƀ{~?*_> N/ 7oo~-onJBCGD Pg)R q9?XMF c@+r|҂q8u1և+#x~gZG&@h!Dʗ{V6>Qk^zeb#eȢQÇN*Zۯ%4я 3 AF?k9drj5Co~9 x=}wl;vhߞ.%1gLd7HR ) sB`ɹ csK=礁1HNS0? Jen2KrCKZ-?Woz=f̔}^ 1 IR "HT  pFsT];w\^ T*)!SqzFI'UdYD8z}n dfvfC&ĭLJ'"9HD1~;:mJ`Y65ٳ$TJ3Stqƀ1$Uv{)zKIq9t;=uk^{ˊlD.;kvtp:\;w8 C)6{8G m۷v[=G! sƅfֳYkgԿJ)<'FN:DRHH@)Ū)u ql6jT8q|n>`g1kr֡jʡKk'Ky wM( [ Vfw!0ܛm%D u0/E}}qJVAeI Ln,3z$IAVk3"v&%qJΩ /78H =/dbW$%%YFg9϶6QLg%StMγsIgIP9+RR!i "v; 'ℐgFQ$(JHOq Zu˾.zv)x]Vuq-Y* "l6ݻwx=p1t:iM(JӴO6/:#)O,=Wԧ"+#ݔꯕi*$v9!l !tb]a6q ?; w5'R^򒋈0IT)eRl9)O Bճrz\o~})kQ}C8̽$IpzNb sND$$IpWqAb{kI ysEeEosa#LT(d6tq/B$bڳ#f)mm}i/@NLL\wu/O~< %=HyMvG?򑏌?~|lJ%*JYx4H%nN9`4\ۇ#,wY]snELqCףnn.z=z=4M(M$띱1ADc"IVN}h/D$qesKu]yr]W:#\ET*LLL(J%,B +-ϠlDETBW7vr `9QJyA@P.! CYV&IiJ)+qoi6@8v;O}SG6M7۫j>Hڑ/R@^Q "d=l q b#$s ?ow x̾gl[qCۅ8)"H44L])%qLvm6s=Ty_ʚ@kFcC 0-[$رw؁X~.3E[뼅^^1[˶oA^F$U39Gqu>Sxt:wiiiwp y䑳/yK2J(q`xx_֭[ZBYyx[[ѽi k\â>*aDD)%iJaRv}V\?_@,dRiM2Ƹ$`dd@@èص%zmF&IrNElQH|$MFeqLqF>k駟~|ffƅ96/0X=ΆrdddIxH\.zhzbޮcĽٳ6a{woV](2x͵R 4$I(" Ð:v:~Cwyvw< !CΞ={ahtkZZ4xHkſc0hIDAT7:?Fۈ,)JBH8(BqN8ugll F?O3zx`;3c9BZV!BP٤fI6"Q7b=n.*۬8_͢ߢS48d[d5xw@i"xKv}0BVck. m1ZAu7nlՀHdUW]U{Gi|>m/x ^>11uhhHu,8>>wr Att\Q/znϋV@yо}.y_/m.>Oرf󪉉^jR '''.RN2$v6*aտbȗW6h6 `u@_IEDU㸭Vk۾}_W;kcj0vm=ДrWՄVp饗ҶmdMFzh_aϮ1ۨ4(z}37|40 A:^8^,..4M篹#}{`o pbttԫT*u]*J>Ν;add͜85PD:e!Ǟ+7QiAyy(O|De'sH03%1DQQQE$ z=j4M'kfO>yi^q$d=s1T*PV#ihDlPl?+03dQyrPlٲ #*o>1}F:&QČ;"8rhhȡC&?7M~#{el/J%ue\VRZ H_ W'w.3EQ?س4Yް^O %ͯMȶx7E*/F%(0 1AEQtooRCo}[wT*?SVѥ^ yު<!)DQtgƵa#:ߜl |cZ.4r Ð̙3'?>s}WZfϸ xEA ƪ{q [n+zq귓kAQ٠k~|-{$p|uM{Rlt/KfI7*qx+^YIk?݇q⍥if$ILnFQDi7Yh\7Ez?`S6u>̼ף^g:tRFQ4eRJ.uݭ7pn]p!0k׮J%t:IN'f4M1ILӔ>|I`$ $lX#X"qm X8lAc3z^c@ZRbӱ&aȺ.;ȥdyy9vQ]RݮMo|[m uemV/ (c/JHehhȯ~\fAPT"qؾ};x&>67 F<^g#ii $ar7r/MӨv~J` ^hfa,"l6;DCD y^nZ۶m[mhhȫj411s:@_˽K<Y) C`E^'8N5濦eA{ !@/6<"?,9vV]Ț YA;`c{1fD IfpCyw(<(fqFuoWISS\c2?Ϗz0{7m]6qF dT r]!fχAHňD!#Zyg!< dI3CrǦBTyh; u]edF'0e1b a-o䯵ZDJ;1BZ:_b#X ΗLgLGV@<0":30üj 94ZkZ}\Q?JD_k&uU e*.|;nj4)\)%jPT>|ٵk+}1V;8؄ADgea6!_@E"=k^CyTU2=G .{ѣxVu Hpyy?w`KlYAJ5E2 ԓMyooSk5unbb// V sP[Lcccu+;[nGDplBRfDZj۽3g,={6\ZZ{ "EDh@ԩSK;vRp]c}IW6ҖEmOL)w(;zvp+"$IV=z8Di֭C7x%wu\0999ygΜ {s4G 9m144GX^ޔe鈹|[Z*haa!\XXX:|q.ܾ}|6 ^ XT SDI)ιsј͑10I966V [w&YCoN&,//dYG ,|>cZ^^ƳgRxm]Wzvlnn.:t y*FRJ.//wӾ7N:uS%D@oߋ,MSjzq8&u16_LLn@?zr2_\\\i*Z~;g7,""sǛz(b$bQ(ӦzSFW#$wH&IBӫEv9RX*޽{tΝzA @q6&Iz^R86qVM[cBv7srϞ=vf*OMMb)2>"Q8|sssm"Bq;9" 2v:?ydG=DZr]4l<~xk޽[o^KDA@AR)P!R >lܱP6o\ ų rA/*>|(H)UKn!,8pLEB"9KT='+nƘSv@IN5Md:EAgΜ6ͣSSSc{R՘BqQezK "J{ٸV,~kfbh*8_k>[t=QJaEDZܑ#GڊI;Ds\ZZ\.2.IT5_zO/,,2|t+g%FFF|%촸<*<ŻXq\m[돲FqbbbxbbbXF#}G8qbsuLDK2ןsLHc) C~رO>yZGi"///G JA,..v?>?33ހO0Eٸt{C蹾jUq _XX~aN4vvp3ILKǏRNReapFذ?Wz{=L2'$\Ik 9NӉfff9Hqcǎ-.,,t^|r9tӞa(y䑣29w.4pYñH YMLJ#%q16l"A !h`&)F hZH0$ٳ;vl}DQDǏoBoc] Hj?ultt4?EhZ9ChyGQ$zEJIɆg \RV"hve#혽 |X1iサY8D++~}~PG 0XC6҆x3fͺn}z 0ȷ1{jySm5M666oSOر ώ ZzWZn&+]TQ6]7X=sQ1Ob<ѳU!GK<_l]$Ïc1ʡ6[IENDB`ukui-screensaver/src/assets/weather/10.png0000644000175000017500000004213014205074704017452 0ustar fengfengPNG  IHDR>a IDATxyU?9{g&3I2 D4DE("/(&!HBBȾdf2Kf鵺]J̄$K,Y C`}w_OH""gϞz ðm-`Nr~mH&hooGoo/yAeYLF.s=d7oۯ||ޑT.⏜{PC6Û|/ﭭ !H$".\SL!^&!~*Bww7$H'Y^^{„ /s1O.X`ĉ{ux-7… hѢt]7ѨzꩧbܸqC3&pL&!DQmD !$m{\hU \3oP @ѫ@83gݧrmGjjj&}ٛDXu:Ĵi&>0<|}7ضCJ 0`̕R (PUurb1EQ@DC 9"˱# mҶmrJ2i:u3K,i\qHo{H3 -Z/Ҷms֬YϖeR3;{{{3-!!|1 "B<G}}=*++T6z 4J088Ad١cѸ-dRdYL:o_|ہm o ?Yx"JhY F̌L&zp]1qDL8 3R{I& `V0M6M)%K}ZmrVF/rHuq3g/g͚L4,:@ܻa$} 3L B@ EQPVVYfv G%c8j[FUUa!BQbfr(XB__s_x0[xۀ @={Gc&N8dxyg_hl6 0r!iPU՘?>lhǩ7C8L*8&Mz$ F `0jsǎg>󯦦IEI4Gn<|3ZD"!'zKlF.63]?4!"> =/8O/!ݍRƭVQQa-ojj:sMxGv]]݉`0 f.Gsq{f(BQUUӧqUߐ0tWt]GUUEAK @+//7f?\Դxx0eD"qu#yw>$iFR!⻉D0uԡzL 8 J#1[V^^}7?(-wh4:Ӷm  ;K?)`hvsOz(2<0D^Uf&J-oDRJ@ p8 .d(YJWTT䛛O[n <#@SU5ZZZ1TUN دߎ^0rt0Lf(F~N]c ]׽-K)*s_[lgyxH0 eʆaP{{;04M ?g&yLu!mPUCMRfCfR= I)ٶmm[q ]8XLN;q DIt}Ct"k0[ 8̛Fd2@.z{c~@~f*\.W[WWײk׮ؿwM%1-XE}EAPu]6vZO.Mߏl6;$];0pP$!~ =(8@D⣊p(PHaBˏ Ew5>7WSOc)%a7is*ڄ(Jx ȵk~l&9&H$QG3gΤ:A"@<힍~O{ &c#w~Fφ(e :Hpَ;75MPTQ7x㳊///7~QGܹs9H0npvn1&ZWf7qK- T麎@ alӦM;EQ:۶[ٜ<#F%ny)xڮ,]Ed2WU#H쮯_5s/~ @օÚF@`_xᅟ br3@" ۶pyhhI0_xد>7DwwGU縸ዩ0MSڶ-FqömDɓ'?r'ANOӉ'Nu8 eߍ8OD,k(ʲ 1? E?]ޫG3м .uߏIx&nI0eYxbHr9J)SϿa֬YM8Lăe@Κ5s9z0̅ jG}4[E xOTۦid28 "^EΡkXCawܶ{{w(-%5ز,b`N%\rJx# OzuN:1~!' 3t$(e?ubL6>RRV.:;;Q[[{w`@@N>h4:AJiϜ9S>don "R)$ɡg#=Ws#ב*~21RʔWEuTЏi\aq*s.4M` \sQ` O:oVVVH$+_h WΧ;鎌{Ŵ_RUy"G-Ydu|"XAVVV.""֊`0F$

G?z;P O @ hPO 0 cXⅻw;u`n7˛M#"`ft~1Y˽XUB#t]G0D0Ҫ뺘0ajժ/_U( ǩ`P꺮z^!$rܰR"V9PJ{ E'KǛK+pʍ /^9aq:ff۶˲'naU4"c( 9:=ukwΛF%hR@àr"FD(.,Q0`0ns1-\X<* bR4 R7X7¼)^۫ 2Cl-%RV +""9a% ~EQa, P0ŕ,b(d2vq~"oF^O8ϻv+LP*7@I) HueY|ꩧ^ cFdi3 @!+ˍ-S\γ~֑Dw]{#ݞ_g,W)|w HUUB؉Dbԩ)65*}*@:KӽmiEa%CcA*R 1G0dիW/7oNq`f2Msҽq`4'ִCp=x^wݥwupC)%=]$F>(1%?XƲz$(X0YYYytMMMi2)%r9v= Y%{Gh ~Oܖy7~"}~r^8w\L0{֭[wB2s#JbE6goʔ)*D.cUUIJ99-{n);[{Er378Nwtɘle/JIpggg[^Ē0cMd\n37gΜ|Md)m/ދ #{YANc}\Rۏ 7 XXc!MT/_pWW!I)R+(hEBGqaǜ1ckZY<ׯ~/und!{@nCo?pnvu?;Iܹز,i,]i9` ,Vg7mڴ4o/R_O2Jv?,l%绛E㏜l衇-N$A%R!z.BawZccc2+4͡≞ P,wfK|#[xzgdd? %|J~>;d2Ϯ\~(t28 6@0 ;̠*j۷y-mmm=L-ҋn$q8*BE@a&K 7"nsKKYvތJ+]}\.GtZJ)Ŷm|[lNHQͦp0@-K2b" 6lhݰaKEDeYYYEEEEe8F""W]ׁ0ZwG[y?$pL*`$qh׆{#SmYuuux.0M9{I8@(R6$v`,(x *if;;;:;;_jǯ4M !DޠN3 @Q\FR &RjϮ7z-e\.g۶twwwuן_'" `J)-2V 3Wwww 8[;PT"҅"r\IEr|^L6mF6 t!&p_rd$lrv$;+PFrc*2U/~P\}cŭlА뮻ijjZCD̃R(TQ狴H†W[s[xۖq`g?@6 BA P^̧"b @hϗW{d26_t1 kznB,nڭpUUCӴf gz_Lٲ, R\9e"⢪a'#e%}Q:ƪU,]T*V7y۶&Jh @>ŦU㧲I"\Ձ1 b'_DH|F`ߴ| wqolY9'9PM>}G0iuݙdSr zqw Ð\He˖l5k֜p0$oe  v֭[w\ressԤRiF00؞~w%J`$;B(Yfp$@ -XoM/@eeeY.eY4M8b1Dn鄂CW a,E!۶fY4ʾuG} 5v1Ɋ'\aÆ׿ *++kjjƍWSQQQ@@4Mefd2niii޳gOc*DAj fN94Qζ eӗ`Z/j5Y ;xlbM_2UU-)e^Jin fD@mmm ,8y Dѧ\N_$=#\4H !Yt:Ҳ-WWWW'"mal6`)b©%\.7\l&" d.KnuBBB[3ǫD,^)f6ό<HbwJ2$z#r:kRYgf @* l"*P(2Vzrƍf͚`ԅB!!$ "e l&) w޴cǎ BIM>'NO$eEOΧ,`!M6ٶd2;wlXjʆ~Fl%`b,4Ξ`,"6w l # 揯1 Py5e59\-y˲r(u!FD* ARmpBᇐvvqbB:N[uֽ\SS3~ &7n|8N0 tIWO&]]]mmm{ݻk߾}` "MMM[6xuu &L?~X, ÚQ IDAT[RtWWW={wܹYb cF!(Brq5dEf?? '#OpLmLI恖*YψgDAz0 ekKK&(p8 BUUuEQiaT*4M3]DR\0#8^XG;R#1}2T/A DׁK-:n Ğ/_`6 N?*+\H2QP GNDs-{a{ٰ"‰(@Dfl X#t@m;L&d2)FD#k8sy!xt3@EEɸҝ׮xMUyL<lymWHc`>qwJEW퐠Hٱ3I gK`fg ,Pr+3ň,H73;1 0JQGTQzu9,֋mb78/%.;(5 D8bZkEE"JeO~0B ;@G,'C= { @: mfi`DjNqp(n]궰b#Y|>OZC ;Ϝpźl̕?:|;O׷򔫮M^<N8cC+sp-3_"Hظ x_Y*Wu`ּ%`m"˶^)e3#>}Bo}KKi'U?d[^$#J7BKA["$[7H10ͷv&9WPhv:.b5{ל:%2.j ;i_ȕw%{3AvR dakuwA(qX(\C(78n`povPzSVK*ك[]vqIjP*j+&{aCa}B{٨X+, 3xP7oKQJ?+k]]U{tp}loߦDdˮiK6RX24ՌibRVl!sW\b ~p/zv̜";tmߺa/ۤh 򢪲x ^\V 2D@sC~o`S?RD ffsφ-/(GmB lS"w?6}x@U WW,AyO{8w՗+PD TU\'p|yGmwr jR=m}=},^E%_nxeDZTTFo4lvv@  H+&R@ 0 mj@!zWJSFq_rM_tgtxu^jb;8@OSF_ز+꧌h߷O/j9}[nyƧ~#EY(Q`om(@VPfAO?}ۯ_z?l5lݷ}2)᷆ 2`mgëNwNiZf0ko \7VX({zsǶ7nj.=@YQc!in:4TU-gaDg> '>TsW DHڶ ([q6-Mm׊ܻkr :@1l?<{{tcGݩl!U/-[y&A Hg]ݒښĸB6`z↔ SMsw m@(@֔d#VXжw}(J,jYfF8eVGwkW_}yo[)/K?ʷX&"\*b7W_n %䅗-I&A%*>z t.Q&۶=oӧ_0H+c6v^Ӏ7҇!ko#(s dY{L>X!\/C7ϴdgN "0%>貉''jC:c_GsH'od6{[wzhݏnśFcN;(/>ZV},GmϞG:Fx İ?c4P.\^8W#1KQՕm, ,aQgqe<3>)^E"Qǜ%ȶ; W9//V2~p*CѼ F,K<ďݹ>TT.eG?w4J@~K|>UnE&l+V w"#6QǒM @yK0_z16ù䗔W3xڛhҴ8_Y8P,; N_\\xi0t *D,|ż shPg(}o[EH"=]>k'E_:,2IW=Rŗ@羆 M+m.0|V yx|q\=nV) ?y~G )`giD6`!{k;`;FK eJ۵+N|Yb֍wu7e@ n} ipzv|Q8b%S_8R,F KQVߴeN73؏_>4ʡ,{>~k.gUTVM\6TV.KڲKwVcCkV\qǺ/m= dF t Ur|<0D?|o~[V79wG x3s=ݐm(ĤUvn)~*:ӺvbͬoxhoW;(cY=f]m@F7$fi9#m<+[ǎ_DWdO'?9S*'ojMVWHY@=@&X揝v𥧜Be3MV nWt;79ϑ?Mwő?N\IhX2!Q "ll<[Ƨ1Y$BQf^&wz} D_]_VE".DR2r8 ~ƍBhn 6`>Ƌ*D L lwr'nė0yDޔk/Y/VD:pTuU|O-Du4jl/TT &;Zƨl)UK1g`P mi(DJ$w'5a"?|Cxom_oÁw@Sl;QoD=H q 3ߍK*aufTb%¡e˞כ"|~4cDlW Om\H$ɑJMk`W[L@]B;qCPT-*m[٧}ŏR.׽9dF$av= =uǟw]=UݪU[9i+si@RD5^zSMY8*@ǼK0eq)-Op'\9u]ܾ^d W95ӿϷ.;7? lsq@klmD?=߷:svowwcs=h-Da#w 8m7[q9VM+mڼg߶߿|A7=d(Sao ?USa6%HnivREս{~_/`\'3DnY-b!L}kvx¾ĜE"VD7`wu=O`v^ ?# Az8=,D4fy64 g  8G9m;w(0-6T^P;[MCU 6n)8x-۶U5Jgxm/ެat %e~hZ4@ XU6sL 8daT8 ; &WL{_jZaš⹉#<VM4=izETr552eDT?˲QgCcGK9pwk4'U ]$,l*$9x;KIǘ5 U/$}M{;m[')͐l[Wg B%|Y4k|͵o~#xsV1!;"eB=?_,#YiΑIWLs޲O>sk]'Hֵt+ӵc\_瞣ᓼ֯%}GT/oDq"m B@ %>Bp(6x5զW=7Fu˗.O~;|.ɐiU*z;ǣܾ?j۳&aDSLzFCD ݶlN{!}\3n?h;yw,KRY.DERlmh[Զ#bL'cӫZ7LeFΘ1w]+J fuO}|uuE+wEpW'Y*Ѧzp^]Df׮ܸL)|FU?bkwܾUVrݣ20(X6Qx @w{,6e fWJu` hq8dU'nxtv&$s@WЬ@:o8|`*l,Sѿ i*&;TB4e-^c_W|p[oVwt5RݫvHk>U-s; p/M3Qf:9 ɗ8(wH!GM3,DV5_ՒHc?>/ȫ滋/N?րɚr=Q8@жVe26|sLJ3>Fɱ|U91RL^uۛ:QuuY p=>8=2 |W-?Xw %)p w-Rf۲e7^mj`xn5sКR@ aVe?u3xSݽBHJ4ˮes_T=B2@4ZmJEB(eHٳ{=rGj5Lkq]}/׌PVaZ ܲ3>۔DWck N> uYP9T[Xn{ P;dUIus믯({K>bvHd:=8PyvE!w(iUC3P+,@&v6E]a[~ۻQ8f$)5޺N]!Q+*mf`VڃL{G~qgz\r cfVI$Uq{t9^a&V_ Q-ÎHؖ0)wķnp3Je9΃%UXre!ɮnAL*jD%up]/3S4DjG~d_ ?m+C͛tEJ;o6xb5u'e[,+ ` .`k_[|Dgh5Oyҧ>I{0볟a>˨r,@Pg_3 lAKIDATG%|IY=8۰өs#]=y{O,XZDUk{߻O/З%z׬=o#uY#EjzP  ݹ2Ho~5rևat(}X=fV$4]+j PQƜoy-uF!jwN%nvJK ~f˓\ό7m;M T4=hD+gh_wH2x}C;$΋'ŗf~ kѲuܸ/az(_?s,H >a-{G z!ot,3-f3oVY9Yxw#շ/N"޾JF%T7{%/5hU#lmaQgFwR!zvfәc` ( Hl?vp@/g>bH5+aY r #Q ~n_z%Dd@7l dQщ,kՅXٜlWh:xB)`SgƖW;v("1Qʚ,VҲhÛ[BD!Tۺimb"`t&Ѳ^FFṞ-{I=zJJMMpp8ʇ3.;mɪbKw5r&C[-U ۄ賀AT:YQHJ]'/iPZ+7rkٌH @>z+XJR:!Bjk䭷tGY_(l@IO?}g"XXd7DLl ofTx!%l$Hw0@b op%#W)~=h`ÇXX^0\1a&DvNNK_ec 9pqG>'W IENDB`ukui-screensaver/src/assets/weather/63.png0000644000175000017500000005327014205074704017471 0ustar fengfengPNG  IHDR>a IDATxw%E?}:t;3wrN0 bZӮaװ]}u"A0 wxs8CU=?ܾgΝ;0o}tWWzOh"D76N&Ka)c:F aQ.&AlKi}}-Y3g36h'Lxb cB3%3 yuSƀbO |$#S ̈h`3!z4"\11#“"Jh0%00fk8"P3 !r AE' hm!" Ar$r36Fah Zs`@qD~ $̡1& ! +&dáa#6JmW MwD "|y34gŠр&2߲,BRUA0A`68U+* &D2$"Cl&`˲@( #ga@kDEb3:D00!q %+M=ڐlXfQQh+2]"UJR Ce30Z)&~ R=Y1v6c)c 9llt,1Z)V*Qy 92PX0wu!c *м+8%wABFc&Ma@RR8[_ A#E*4Ogar  e\L> J+ֵMMYh1R&?f9,ۆR NH_H2L֥0[.60ʳ#;s.=BhF +elds]s-S:~E{1LDt+w+<&.d MQ,hm೟]0䓛pgqI Ų Аq>NZ9~dg)?wГ{~/ğ^Ɔ7}O olR{mA #dYD dljh wPp.r.gsggs.x13|y0_΋f-}Xlvl-Ƭ4ٺcf&F+ͻ^^;?iZZ :u6}E1oƋF 0W j)~|_ !$@V;յ?X`  }`,fRB/w qCtNk%fiϞ>jjBS3bQ,ز 6m+ᵭ>xcWzJ-k7__p2,oG& =;2y W}KJ" )nO~*!H$ , ]B䁈P(ل{vAXtigT4Ɋ3QAaά&, "† {2 ضs}#%lt>7cOB`bΨm[OٸgW[>dhFN&Z. Q g%_ggmZqE_g3nX Px9aA~;cWMOn1BqιKB>K/?AJ+J'43Je iwTߨ o@ $LArؼ@-BBww/Z[̐R`Lւ MMT%S14T~0#6+GjaI%FcB\Sq^n"[@EL4b$0Έ8Bdގ)hnhi@O=ػwϝo<;C^t?}E&cKp98XnټF"lh٧ +$i QW%A{o5ID<[Wgx4h}`N?̌kW?V!c5ogQ^BpG݄g]IǡA% S, ~˵hj+GʫVu-|ڛbva8*OqR@R1w&u!}h0J_?(}efgm _Тw,yyu_'?&Rʈt{*-gZM;7k{;~6eѬu~(,"? P[K5@[Iul֎)ض}X 47g1sV ^u=J?3ޮ`.^҉~_kPP(d@DXe V,uN F3,Kkǟ؂|ENo(c ؋|Sxn)?!˶ -1DMX7 ϡBCSssmG#Ы4 4OcD="G NH/ (5L]]{jbSWvXh;?}7̟? ҮW?-6>bP`Iboh B\x_G.\p˱O;F61Q4\C kCTq%pۖ$ڀR% Ur]t̖]?,KB)MaW^ٍn9NYAbU=1j c@@lR Hf+Z:a]U.9P‚]ӟ>}`ꗪe`~ɭ݃eJ !r> `c*.ת x׹Kq=Ƌ<QcJ`9VTnDBDR@XҒрŀ"LF}۶8L|'Vmw<χCCꪛL8$ =]rƍBF4-Ě?lRpK}[I--9KB_q,z-#;<; +u._qݯ qY5e tLtn!qs6hoWEDkS&8$E-mrJW˒-a .=|s~P&r8j%@U `OQ` D`4ظ-Chmo_y&p]/qeco-o}2$}| VL_ڄV<[$H WK{뮗E6I+λ:0U2.FUg' -`,[r$Ɩ<xWq'T%=Gsk d2 iY nشl Ft̟cԍvbֈҡb]Xb)q'`Hoփz;N\];ᮻᤓq,̛7 coFoL{Z;;W* oC0N%A(K83`9կ W_}|?ą.BP DuǪ CG*.! aTJ>`ݣq9 pNF*ض{Y[dd.,[RZKz!XX°6 "N@E*\KՈXP"Aߺ  D`O0X"!qǟz<ɣAsKq,WX\,z1x;PCJke N8vƆ@V<8/E%J"GJ8=B\_NE틸;֛x^fFSSSNŦ'_Ƨ,ӛW_s20= ً&`HKBZlUFΜ̤&h2]Pd3!^hZ93487IP8.yhw5T;\G f/'xṭ8m xz`DlɪTPuys3AR 8%,K0GN+8LVDARړѐK)9! <𗟻{Ƥ)1wi'?0lۂm[Jy8bS01xZvb-SaY@bI ƄmvFG, J%8~{я?p]Nd1@b`B!, 1DZ02㓟7Q.V] @iEKפ%`Ydݎ# u+2LHY"bA\vb7"IxH270vBD9p){uRn9h=8 MM( !9u>n{Ƃw,^xhtaJK(}}yFDvR*c9+`Q* 1UC5C;w׿^[v8qձ8ELGF#I $a}O)aJBL\Id b5p*(ZB& Xख़1iz-Ċ_m@c!,B|L_0/4v`/q( jŬo Aiis _ApaFs[Oy_ xR'n'$* ]$[_-P*`z[@R K_]hWpZ@@² x+p5+hQ Qd09?crz (m267*{[S&X#03i-"z8"9IF 8:&n:g3a5An#&L[<fNV"th:reOCTVt(W<=@q\$.ܸp KXwhҶ m ! iJ;J2*B /+07뢥-iy'>quF%RAN~2T"@5Y$v&Ӥ$HĔ{P|k+xR-Dn[׷"#ּ%S\I|j T0C2)YgLdVJ˵d3&<7Rm-2/Wb2h89-&YA,$Et6NFeՀL&`ztR%5B(ZF(?) dBR_U*0Z# ^ _# a3+f Z Vl2CM(R^ | D|d\a“QL&hiq h D,3 ER GX@a/Vg&V 0M"r%[lX*R@V522,KYP~DQuq< \T0DCχ͠)\*Z 0FA6|_PTr)p>:e`Xh%3+K™Y̬lذ1Dgm kcB?;EsgAFس^-0!ј035H!TDQk".L8P%]bT A"oT&rbRP-QdCJlZ%`I{+$H}QW*eJ\ю)v>uIEH8tQj]UA!oIX'^2VN=o4\#" a68 gtCxra?!n̵ )Q'רY&k #JKG.Rķb$߂k&L8h"}T V54 baQ.P.\p/ohmm_bI&? 7 C% Pei.>")Pu lǝ `ZSP?)JԖU .ܶ#rNl. xb T%J<85I4a J"* * GAX{!7 vv>5gΜ/>zuppl]3$c&F7ƄLcd2¶mv]WL:lEmw25-UCr(1d10ߑJK1,D 9 t2`I?4SF;AaRJaH*(<묟5k/<̟ϛ7@<8G(Ӭ" `3Ik/Yc3fX*Ԯvnm{'^;*ďD[߇4.ܔrj)eI1ĕsn8>zԗVEdߵ=?iVKt R}qq\bao3eʔo^wu_CļjI ,qzܹlnnl6k)SP(iJuN?0Vu貯Q5Hzy}JVWz6MmJnYְmqmmۦ{… z>?x |ؓ&MZn69#2 g2@$+#@:ob\pz=ԻUUD&*i,!kɒ%z?Zv 'tkx@u֖N)%lۦL&C㌫g#!~2H'c ]VҖf"b?`NP^mJVgV ,pz衟8 oR#x.m|ɲ,ضL&˲E;Us=M&~ɴsrH)׵FW>ԂZUpj/]x꽓N>QTp4!8ꥻk׮<赶ar2¥6?=xiNMiG#IP%B8NkApHȯt$t"IΓp*="ްC_G0p<յhѢ< D\H:Z[x^P"=w&>1_JyHp; 7?N""JDrL&S< "ϽC?3ZRJT*O|:鳄x83~N鎧9?$-=$*N }%j= ԪZ2]g,6!Y(2eY1Ar۷oߖdϛ7}m!dzFX-"Ibm@k4N58AkASKzi1_ms<\.#~lB R |xCP< ]]];3k*V5i9Tobf<7o<4(= 0F U5peSI}V#$hT*TTC/ҁ{&DLBdM1 "_~}X͚5kmy a&ӔÐAHV&i/{I )Hk͈?(p-'~U%g8ZPX=8a$e&"k[߄+( !ʱxKqj̅}vv}6\" dDBsI)eCSSSsKKKkSSSsccc>,˲H,_|ԩS""uEKu\20]FI=7i{j< 1z9-j4j%ZDZ*a zgo喟03uH͝|cymMZz'laݽXDd'RAkߝj !.ٳ뮻a*h/!dkzI}iz1LJxF-lۮko$AaRB5v*ʁ DcGes/sҔO6thWܤv`q#s.E!mfad49֭{bɒ%VX1mxxX Z^KܴخÈϪAyޘ-kfMbz@Lh18 C 0D%\o(jG\ 3Z>Co_mD$bq 2a aDL>_*# lٙmKctOa.qɁ^zm 9sfȈff$6TvN8@VT*(U$ Ju$2 ǩ0RcBB)EDAfb p#܂iϞ=Xzk֬x|ˈD-@\?<3w@b]`MQO*v\HJ"R_W\qu-,JZkMƘj`) CGjh2JBHN?>s"0d"88NBD l Dt`&ZuGڶmU뮻:uj13I U 813<Þ={g}vC=tOOVA2oTT#$2dz׼s0=# B *<7*X+f8bzU.>Nvbb2 @`MZܦR RJaA\6m>o޼E ,7smmm l$)8$c?<<]vٺu;vl-J}+޲e[ly%ϷΜ9sΜ9s͜9sɓ[|>_(Fc``߹sW_}u뻆C Љ}y%Qkt"YWX'6AÈ?qRRl#NYv\s>^>p KߏSfbIDH>4Q!ʓuN ÔJun]Ϟ~ #F05q1eYmmm퓧Mjoiijs\.m[ !1AV*X, D`1&;gu,ADB0dz&5677 BmZP&"+(D{~Ii> Qί "HH צ B~Η?Z@ W$ pf`H&F?0˧^vπ GvV L ќhQ<:"e1VPMIiQb]%"BCM\/˽%`:VLXT0OL8$aXIdT$1 XQǛJD(lvi8&4pdhY۶m[{0'+z_ Ps9~(X e#Cb4`%$$)ΌWK5dca*8xC@*@XFn奵krf&ďactS+xKu~b(OdPA׺̥T'x*E̯|jp42{e 2xjj@d*̧L{Ꮬ9O/\|u@8Ih#F%8\$|tC~|̝^#@ F%IRwy<"s%W*J:ZWCgᨤ#nXyښJ٫Q;E"Jܿl.l~Ɵ*tWK==IV֊I ["A$t`>Tp`V .tw^{Uy̼%=Ȕy^J)O@0e]|>q΅ھq3ևdyuS!@!eKϧN=׈==R)YR { "p'_~{ˏ\x]ߺD!fNNo3qGM7}@8 [<ռڵ ]uͼtJZTxe9ET,o$\E5@oO jh }C(:qs^fBrBWB/P-5j0*a4No֩EV*PBifѪ>C&҆yyYuvw6:EG2S3sN?{S=&O?ƚ/kͷsbk>{7= /Wz~ Hđ$" =.]lAY؜$MI `Ӵ|gV<˒&K4̞`d,Cm @0E`Y˩Lmv씢d4;(4Ns\ QqsÁ =IDH;sL{Xyp=`z[қxw簴{N+e7lxudA ۞-֞5;8+Wc[R/!_1߷L{ʤC[2$m@z)cEضs:h޾]6v@d[(q$0`}q^|g4H͑K@oDҒ@]|ǻ0z6)V.'cv7 $/fK&r[%ݺ61$ }k ȲRMbZk$:a1xtKk@6Bk1CDF)KDS PKlV.K̚Rhh_u|a1&1 ܿ9((atrTnGe^-R6 rsRQit0 x0;vATjum23lټW^mYs)528uڲ~b>cfb ӴVCBXa"(1z4S^E$&:Mˌ1Fp!"|`a7 >ADt_k~+aN7"Č0S -ïCFUgj>bV` :Xsb{ bffP(LE (ˍqj㻺n^[҃F(UyaҤ~z4g?k B76Zgiݱ TFޝ=@iM?3f0ѐi:acK#CBte<]֙4}W7k޸<(ʗb/;C۞θ'~yuO/CI;_t@ٓfn4NenJ]%L=t;O'6hJbht)⯷w*~ߋ6Ϳ\ ؎uw@o b7l?ջ/\y:H!6w.3|% .+_?5'5O;طo_> *%T^PͿ.Ml{۳{nzۿE`\ض עl{_X_O#Xl&:6#rÇ}ԥՐ5xYe9Y-[W׿̜f! lbn~;QK [/9eӷRy<lȼMn=;c`!{6޽va^MG4yw-sVf܌a@9W,pwYNO:/#vmwg۷oJ@GdA}DK;+oFtɗ1{ˀE-$'5O9~ȇ}RXNLOKK'`|pvI-> ~mR(:X?ѽ`#Yfٹjݧ(x1vﺫ}GhVgIDATԤޕGU]Y2[2 aъu)ZVS~c+jJKԥV)VjAqb+ZDP)dL2wdtH}Lιsϣn!ѿ*,RB^wy:-QCd­bڒcScQ5:V+wm>a;wV`8c`v7f 9v?p >mbx`V;^$U˯ak# /-\ށ'LTNY2T/CFsSL͝I,*+[|eN2NOx=Ӧw(0i;(fyT@Wɫf" fLei`ǧv?JyVYL,# 2ͦX]g-c DO _y|[+xݥTc&4;"DBmwE|G˂Y]F&LÕw&, +!Ti,VCBVwYS67߹)Z {!hsa# hSq'$)i7܂νznJ"`W%Ϟ:&:-Ld45x{ᡲu_lPٜ+UDZ(#.{ΟAw^8)8%}*G2 w›x'`dd=xp|:w ˃^g1}K6/%6@xmы-ŀoJ%wyԙ3NKu-W<PSs]Ƃ_fš S4go٣אb0%wJn׮Ӧ!`Q0lou5eP%1K"@Nܯl 0,^"L+ɑBoZʍϙxiʁJ6,x0ʘXI6{ cPO`?-;wK}XiϼB%bF %'y^osvǣd8t?s$2v5'&u9Ē #@$2f%Y4S9dԐ;ILnѓv .efYX5 (с⍳g?V x]v&`+)'a1 T AO-):d-oĝwdע4,@x5Vn寰WefYcM0ÙGB%^q"023ߔl.$TOaV:l6JTU)DK#G;<"o<܃ŋmnwgʌ,XDhɎLMgā]7P[Gض\PCQ54*qs|NNh_l1ۜR0ƃgI|syʵ}_$'}}AWm^چgZͩ*-媲mE@I#{n;8JpeO,S;fCPWo9]u r:8lG9sE9evh PRaoiLt0vڗL6ʺl>+DgH3f 2|D̕MlBEٶ,)XUaac N4$q .2sXdG1]ﲤ egd.R&2yyKXq=6ynl45{G1@^]֖GLhY)@.B;tpMiC,<#B#É&0 y%e,Z :w9K[\Ջ4%Զ(lp›nu2GK TUm"?ޗz0%5ӞZ\fД N2g=. X餴 rFsfʼnLCJXW$zS˭\9<֯;'h=>[S_<PnWBm #Fx+*)=D8=x;f=ܢV~jQ Feŧk֙x~9dpf"7Ȑ!U*:}q8C2nvFQfnf;oʚ7okK.w$b_ C1.7]QҬRUTж!ÉzZ qY:C[.] ym8*G?>:siB-UesW?w/~*|@ dD7Ef}{KvNXRn,wZpɍUI eG+3>n")tnrE#1fMp 9NXXx}+9n Z€fX-Z?Kx%`p/п sdJ#ӞbGu^}3Y >Qaqó;;NZ.ikVUOS0ϹڵTq9D]1';xۗ 78P-eiZP`bp~?sqYS\h(th hSNe5(}$sGJ=ة~۶pQ.R-6t6-Z&!씝iLz| &~fkUx?=b*pRpnuj0c q|C^ h2A tW<]EJX̙dr8 DW*n@N=NPBz4吲ro.1I`mQ~9g_4XKol"[\|WAQJyr,(+@s0mksG>qJ_U?YT.>ln`(9Plqhv;7hUkX^0 jgR4w',@(4,* Fvᅑ*Mf#Ăiv&'T9֭|`c3{h#S,}/?ZB[z8+ŧd0Q!b.>WO;"ho`D92g.9R'L9d0t(C%yxxEH D,W˟ԑzIUU Y^ vzL3dfaܒ- M'h3 _NkѽN-o|E]6ժم,Z6Etվ[`6=Wg]Dff(cd ГS7t1m! ݃@L_<, GkT5Tt"*yj#P`Cx:?~ٕ zkXQ M[5{,+f\زz}E@zp{/~mԴ/̣op ǯ[owɒƲ7Im6;X ^7xp9RQFZ$:v(ZrCbx܎@طNܛ| \&~2 am XWw  Koߚ̶8dX1@08}H]\5hCH,V[4l)0j=Bo9,$Qʺ J6cMV}X̑#%*RW_K>dL"..V v0]\z_0@~p&zy&41/sLug"Zq_bEНBjm-Ҭ'C5ϘMrua8YI3Xp,}>}x /Y̮%;3YB@wADFԦ+)0T* X`vgwHgc@UG[J>_AEd2gUQjvϿ#Mw&~60IaUEeG%)}ukoY8zU;QASKXPM{:z/w:Ž0WTCQpl .n> ($%7O,XW`O0ˆv* R >2+]Vfԃ$f!X]ɼY0 PY~T6t ̵w0\-`[0)$x(Lj>0!a!*`9- ڥ h( #6Ҫ@ PUK0l}p2.!Z&4 `vղ /P?_0L$isIENDB`ukui-screensaver/src/assets/weather/22.png0000644000175000017500000003303314205074704017457 0ustar fengfengPNG  IHDR>a IDATx}ieU޷9^UWuwhmmA(d<p1XbQA!?,D8 `I !A9# =Wի7{{=V׫(oN{ϰkZ8i_5wG2x>\fߕt{zm Hk{[>}aZ뚳5/'I wο\W8=+jv>߇ر&|/_zK1ke]aOhP fO=v'%ر<3;FGu<Pq |5>wc XycrjT>i8\oD݇t][wfHWF1 [X؇p g}䃏5C9+Yc)?Wi~a6!I1,[RhJa^f,cT#%0O<9='GQRSࡱ-9RJw*Fbb!DG̼!Sѽ1 )N^4$`pap >@S=Ę0{-U63ג'7w:B2^` CjQ4Ӳ<۟ @pCfk,EG7k0wn, 总66!4sj+5#b'bbkEXN36^s顛ucc!PC0 U>zC8d(59 EwZbic*BS)%{LɗC7 @Qqbt\4u~ࣸqŘ=(TuR7߳.\8WkS?fHu[!eg>՝yF\féY_3,`V|SJr 1a/=.Oym/3}RSB1 mlƐM }(F0f3'7.,+&ueɿ͂ ؄/V '1K_z;Voe;}~Okx܀mе#qw/ x߱pa[[~#{[e3hpd$xV)|o_zϾuwi s` waV E' IG='Q&~69 )9B0m^ˆ!y7 g ϲ~SSJBc,w߈W}Տo}7ߵx֝Nm[ފbL?Vp 6loܹS?+ 3F-bēz-[{I@Sk٧~>-@n4eP{s3Xfm|S\8`u{almjO?&dykYgf{{+j>$3{3g/w?tq칳~0fffpK99~=cǩ< ܿZ=Ð}&Aӟ~B0DbN_[:0x"Nv0$}|niƛw0 6T?ffCre&vww[oZ[]lۆ f}h~7{Ч{ҥ~/y'Ƅmo?B𔀐sIHɔ6G1<6F!)(96FrYϾ9pDʧk^|뷿֧r~C~z (>p$@ f94Cc &Hl-(@u /2`]fOnX_ ?d}拧1a`з)I`H2+} 8L nH=h f)&O4ܬ?F Jȃ}]D۶޶ vwm.|][88|GN|c??G~uv-gJ.P0`٢`̿><. 5Hl؆`E,8`)"V.}ۑDP0@!9u M?xfԬOvWʺ0y*mmxێt#l!:㦈ܬ8 +t3Xnuo~6`":zV5@!xδ‘S Mv4 ,%94Ab.W74%:|bڑDhbxwHן-={6ð7N^p{?gƗTm\ŢlX X,zxa~+W=-`RL[(֠p !X`XBRpGtG_@bb4'G BP B vT\-q}Jֲ ?;qb`52Y'f,"Б:[n9<)yh{ 9T\붭rV/5 5r1b2q_/RKJ ~ùn53; M@ji49 d0wXSʷ}SQlr[BBh, RZq ,C&?9NJ1d) d<,\uO~Rdkcm dE/,4bEټ72TdmbkCnmG  ̚4A < tGJů8ycBfr fBRtGM+0y"b.B\]׬x08bL&`mGloo_x˗ |ȯ9s'wk0|3>7qmO|!_Bn9C`r@R$BV0c `H@CB4dɞxH9 x`߿ \Α7ЍlB¾}?ΝW|ggfǩ;nsgkv—E-?7o:{(j#o~obq`gkR0 _i sff1C2C2 `ÇĐW1YKyy44 m軝i_dzT񍿈7X[_`bg=_~7w| 7M+|ψʙ^%/Xḻ{a^?Ѕ׾O^0hE(eQhJrP`Oүhm¼  >隍JxYZ67C `hm m¬mBۆ0B3B3kCvM3kCy0 5 !b,h+8|o 3a5M4Mcֵ!`mkCm,4yi٪b..{/.]_:tZCH)!y\0"$"oOC)R{k0k!}12zX!YD3XBa~ފp4̺6جklޅ+uMuiC7a1 +6nJ^k C0w`)*nڀ,l4MYl>6mе}@Ր|~iob;wW᲏+>> UqX,A~ #O"/O_?r͛[r98񳙡)ilyy5fMc`!XfMcmiġyU9?40RNlpWd9Cc캰5amB͂m  yR!g=OABJ~c:X i}ɟ%e1> U7}>~%[Bp>K0s9-s]ٚrN[~o8,6k\jOIe!/ۢl=UTMYa*%hWys^V?/],A.ړq/f[ï4Dp<4y5ʽUgfV> i 6F19!3s]1/jE*) crNLU飑01 rPƶU{/t~`C;!mR}FRc>ۍ6tȓ!ZFAu05u=FMFFS(FHBJʽwdZe@=BFBy@E0HOI75{Sy @44FڧbPC3>h8j0Sb}0 )u>` R\i0&>}T<Ȧ.1CSLٯ'ء02B@TcV!ttO54 (`0.ҏZTChT?x'HQ`ԢR%dfd%)4dF7F-b JQkhP= A $O J2ݓXyƔz035P)%!Fc/&ST CuNĨCu_F YQ@a' Wz^S8BLDHfj MQ)dig0wNPT>:+FA&RH\b`j0 41$9{ #(UVc0d~iw0z4˲Z]3\gփ?Q5Mpy s.ޟ.ZЗ{iւBĨhk .jHdfܮVȜ L63<;Qa {mLCC?iiE2#'3O@PHA#=u|?QrL"2S hiPa3`33ofNJ ¡=a@a!HNB4ieY2Hbj=C<^ú}5ex9[:҂}v a5c]b;h 2(%2R^b7+a4@ϺYt,[ҿޛWkFO9_CZIN\ĬoYh1ՍuʙIԕBp\099? rOKqr-/@bВA>I2c#L5D1D#j2^Q6MW: !"NIsjRVZdW|W +juSA ڔ#qBi柚O SVTkvMͽ~%8e_As"Mԉ#~+Rp\;!dM `twk!6Ѳn\Q[{$Y1Nò_K,H3 3'1rn2jI {(S@D:n`ꖀQɃg44byDѱ]1= ,әN`ԨB=Fƫ 1 xoLUFe7W B".0bBL#^x6LqZMMڱ:2-ej^-k)!4ʨi99i^M;sj"~P#Fr.].h1-hQ GM5h^'cMvͪz]! >-q&jQ5qK(|Kv5Pg)dLOZR8`\W0p4SS.mJ8)dɓ65(Hfk@MZAr.vp4DSBOfXgiJ)׬ZM(P#rP.qbiF&WVf98GMK2jW0U*` q}:MP#8uz?i$кT[jP}3jKF1TTn*`TB\(U!>[hj,@4+ꨙ$TH59VPHiZAރ}kI1 &j&^d^ SdYjJk>ZV΂QFSpw74,YRJ^ԼV4p̣p(>5ꠐuP&QQKk[j<ʤN5~F$\UEr.Ը9~vjuO-3 T9 ~gEd*$k3Y#MXlrB GIW@]pLI21ړkehMO;W81MUR;OTp>g_,Fї%qjRRPtsK rsQ~4LMls(Ii]I[b[`?|eY@Q( 89Ԅ'_D P_hj9ҾդFsyo.<3&"ju)mjWJu5YMQ(;m.…֠N t̀3.4L84Td7lS-5Z&?evHqu;u$Akجɛr Q+oS휫4[`(S>:n MǢCCWIN?)|긛cefb(3limYu#+ƅ`)pkPmL}x~z SŁhX SQ ԂU*#A+Ф_8_/e 8jJc$)\#B$XRGAK5PڻEcr +x&pcB0P ;5U+yCҗ}23aT%R r ǨW҄;ZJKpH˥Z3אOo@KaXa|3&'F7D EwAJfk95@)&h%Wu/ Z9b}!:=K>oǘXʦ74#`?.JPA `P~_GB2LW)Lֵ#( 5RmQOBG~1 2KQA(顥\Ǿ~_I|*'Z2Tc`EĜ("͐seL<ԄkHC.M|Ic\Ck05IVRtuxOn|-FR4¤e}cvʦF+8 hS\d#6ۘZ&5:~LjOVk9B ʲ)iFޘФ-3tw,pN(Ld>]l+12% p6?$ ¥O)7~>IcQW tXZWyu5Uӯ x'>.GH>Q(髶B8|)+A8Yզ9'YL>9WkVMl*X4]u=M# -hU--j *d/}+JΡI-R/P0#W yW(o|\ASDԬU_Ma SQ xh55#>Аa20wu .ٯ Ɨ1"_R_=fU;FC頋g(ӽ0ͭZc̚J'zP|Ҵ0mSf5@Ui> B~W0뱄di-gteZ+Fs(\ xL5uMb# JWMir}ҟ ;"Pj4R&jpGSB{M&Q5- Mb)t5 >=F,A @dR+O.@%UOV0P%ZK"qru…&Y`8tlV}>`| ]) +FP`.NӚ)EprM(edo #m<0R 4M $b?:_ωq>[GQ/o"hA.^ |ZIC4QoP@xLJHkuf'py1ioJSWKŢ1Z#>u$F)o1>֙=Pj2Ќz"x8uQZndAG_qTkNQS G-e[<kPosH<2F@ӵnMr"rZ O Id||iY5V\dgktqjݢ!*h/]BlNM~IM5a }[}RAZ!T[V*TWfct7&v0.aAuJ#[r~hXJ%]RwҲk|RQTTDE{~i2HK$i99N^&J&c)BHlwA'51^2ȇ9>8M Ֆ0]8 偌]VZ/l  ;wǒ9uD3Pr5wY%" AC ,lgz}V#QuZa趈ʕ$jVpkL L`*{hCV:_]`wiӌƜiɫy| K&t .+MԱckƤ*HW6΁M5)-)d8ojΙtJnC ukK @ZV/m). kP+uEy,pM}FmjVt%/ĮݑFzMIU?ZsX(x7):I2t]O|-4oZF:$gd%+P FCqM>蜄Sw]) Mnbg?)b //!?@++:QX(ZQrݷ O<.F A$rh! Y KJ@;H_K@#bj]WFWn0L7A ?*&R_^'Bܱ&G^MQI&UD?ޏ _ Mӧ@,@@P%dͿ"r}:.DQiRI!>MseboX>0Xj)'sp.oi:YbF($" @ Lߏ-u*/d}ڕw4Qu.F9UU626iUV/M vrQjʷ6>݋IWNoSb4L 8Jטek{2 q+lO-SןY0Hu5jmbY1}M`j63(8@4f #Qcq ͨj12qWMD_1Wb&|Rc6 Stj쓮}muVCcؤ=ǽ~*(UkI;i'vNI;i'vNI;i'vNI;i'vNg_Bҏ IENDB`ukui-screensaver/src/assets/weather/14.png0000644000175000017500000002666414205074704017474 0ustar fengfengPNG  IHDR>a IDATx}y}WM,II D`-lqc?;CC` <A`d0)I h_FsztםRߙH(9}]]~_}060G(`RvWW>cǎƞt:Uzs9H`mmvz꿎A x/:pG^df2 !a R B81uA4 -Hܼfo655ʦBIF2W_}u?9uHX pa@uNa TsN8( d2GX쬮^}EZFkO=-۶m!dn2D"@(b1J)R0:cusq8lۆ뺜yBۋ.B5ԧ泟@-hu-\zc"10iTuI$eYu9p]X,"!L&l6|>aо>ގ?455ud%mǎ?'T1MXEMD"@uu5IR47 W8u."4z{{yOO,"m8q/~/0}#G|Y#fYO&'UUU0 /dlWp]82 N8I>GX٬qСoXdK' ?~X,P,$˲J VEU x>"NC\. <) 8ڑ#Gk%Kնah1-tSNhǹ p8Lb9s&!O3iOOhܧz[6lxhڴieYz8&DϜ9$ 0J}Ѿ38ׇbXr avpK81FT*s^t]7_YYcT*ubO}}}̙3pߙl3)gW_z)ShhaH$YH4缔ؑc{!A_}۶ՅL&۶OR8' +B8RumR,kee妦5g^3gΜKUfL _;\rɥX̉bz45M+)_PR_(P(J t]w/#p?0Ȥ0ƈ833 cd2g~/~nҤI*l2ƴIPl+*9DBD":u*뺠JvWB"|>|>_R>)[4D*}DJYFqo9 N#Ţ`mz&Aoo/onn~b…{L_9sLF,iuuu(ׯ:}Ӄb(?( b\x4KIH$jqPJO*0RNNp*zOOtܹs7pd(|w-rRL&1}tbYws]|r"|>_B"h&PYY ]O8ʅrQN0 vmb-W\q.]c$hß^7b1DQZWWG***;C:.sP(y`,*Q|,CCC***JBӴa*؃R 0DDzBjmM&l޼K+VH˯c$)@K PD"^QQAdj/gDeˀ0HQPa Lis>)Px DQH$4٬Ia'N{m6 '0M™;wD"A pLԓ$L,)JOtmۥϢ Z0PQQ)_~_.!)XE5Mxmmmc߿f_1c!1sp&ĉuø<`s' <# 0 dV Ài/j(i#OHQ}MHww7aVVVs{>|xqCC ! H$8a„95 ;8*JT5=| @D"L0aT~r&Rd`l ORx%qΉpbCaB!BA-|I)bL(s:A9 fb1FI,PȨ,rOs=a)u9 pc0cdh8eC4f6^nM&b,3ET$C~V1D"i555]v}^x}1n Ҕr۶I__LӔu/t`ɥX,V"a$W+Y=_d2MW>aquZ]]zwڹہQN'tiJiqϾS+ u!%i`, ` `qu]'O{-rt%V[[뮻n^h4&A "+G(VӠ\z" ":=ZDuSD43 /|fӦM$@^}}Wĉ'b1H$h4J(" WrՆ!;m7aT{Qtz^9KŢ[YYi]V?rop@خ]wod[dHq744$Iq&f]n(B.CڃU4:+1ŶmL߶m?ǒ (H$I3Huu5D"a%&UeB*>> jrrbIm۶lC},q`麾sp„ H$bVVVbܹjjj!$g`{~8+nU##Q,ÁRHPzYF"HѣG/[,O~<2BgNu>~cǎPȨI"@Ԑ2 Ƚ$((fe =R>GTS^\MaL&3hz>'1tww#0Jh4)Sn…0=d<t۶?lnn60I& .UUU/Dr9 c0r>@IYyP d d`I&=O_&M$ )3s^{PJx<Ϝ9O<,QRVhrr,DͧC宓Je ei 8\.GzzzO4op` x]]ŷzDQimm-;R/(yNH6dΠg҃r Á3? PA ۶m9 ~1魋/Ei` >o޼oqjDPl9gOn,`1jcʊT*!rW.[) C]WqF L cP(|>O<N:>o͚5kV\+V< BjϟL4DT*+**ai_4rZ"ZrUS!Fha$TMExTV,tS-LCP B^ ]ם9s搶W\YbŊ1@0hYf]J*Lt,*++r-nɍ+(!U 9# ܸ:8$/ʗA`Y"9l6i>k֬={~rJgŊwӥlmX (yq4eq?):b}zqǎO 1 03 I0$"fww6Sfb{+#iT8} RyPJ9{e˖7lذ~q@˲*+++w$RCeDWnhrv^Q ljJ` IAQe sgƌ믿.)K(*&%yӧ6PN9p)Ej%D 3tߑ\5 -WvwåADH$HDK$v*^|Ñ@gt]䊔Bd/GҰAzwr-"?zDAD gKa 4 I4%aɓ' S`B &! A;rêxG*:!T(7#Y{9 u,7T۩(<h1v7Κ5FQT`$oc3 ~Em# ?/7^POWclr@A9ɿ7CLP;`$+,X,/^F@[3L䠘\/ 9B0O`9HaTl/pmrRcYABV k PlUyAJ.瓔sTzzh>{C)]D:{d2_ u]^(H$w/j' ,ףe!##]i9e&rDCjC/DLg{ ;󕕕VX6 BΙh hS","C)A(_>qUpȢC}q:rv FN)%Fk ;x(p+\|ȶmv̚5k~>brҖbK .sdjh Z'+N]a$ q;9{2 AJCe J#BP,0 0u^+/4 \>K{ 5x Q{ՙ2:ղUQ40'RzYQS|2*!m^?R8/$o߾7lذꫯNa!BJ@r6P 圽l([4Q}A*Dêə9YAre #ȿ %Ѓ*냜r?8/@CP`\B9{^|g͛:>KQO ~q 0] e_B4 z| ӗR=HI38wvv`R 8_c *++BV:cV~ EQJ2W*S5~ *S*.'$ϻb^ic"@ud`B"{cYִiӦEy;p#(7XR ū=!q1  1H*PNr4-@ I~<τ+=s^c;MӜ4yqՊX/ޟ W{<$3=#8p- !$9c89%P <.E  :::lڴiƍgϞ.V( Ƙ뺔1Fcu]HP u_^`/ `x;zш}r=>( Pf!rrLrH__Kџ{UV=/RJ>|<\a0h/0 !!Pgg{O4-L&ST*ǣh4N:B,"1N%a(T-7ڀ鑷~_`r`IA8FPn2ecI%}}}.}ݺu}+WGBͽ;fbH;eP4rxfnpWWA2Ŀ>{Сe+Vmێ眨&@jW DEQ ߗ1GPW%(!@쥠>m7.mÆ \.;~E6!f9c0`ts4l Ph5Bs=wμy\%SR\^:}St] ;sK9u!ކ 'zaDfGB8u]^kGV=}Xt]w-iOe@ ]x/ËD(!~Qs=d<FSSSk~J,:00+z k. .!=+-B=Y˔<@!@a5sJ9СCxg׿KoC!E_gCTO`ŀ1<>jvΝ;w4WWW'"BDM^r/hXL0t:F l.9nc8Hr8)55MӶoߞ{G_miimۢ5M>qĈ2X8ńyGl6K /G}͛7-}@|0  ;i J 3A.w5M^q.\x<O}&tL]GdL"tJ4Jfa 00[T-ݧك惖Gӳ u'NlNbeYaq7}<Ҳ-?C Rc! 1`20@%3 RrY666hѢ+̙3% 2i䠵r$SJrG:C9fhmm='N{ΐp8 ˲' S9<֬Y%q>0JmiRJM0 MӨ8nX}%|]zt0zы M,ι) @fC`&>iҤ]tųgϞZ]]m '@DܧU*:ϣ#{͛7M晳g>&,v9=un4K#>=ᄏ7xk?1ԯl^w~ٜy xGIP0_(tbKc ߩ~#P~r(yl!PyI$5SN9}MMMUUUp8|VAb>8q{Zךd:KBeFMMMSL2"Jhdze  ?e˖][n{^b *`H9UE"D*bX,6 p]vuuu xӐO")# 6B'-ls89OB^@?XA8: <=qS".iH+Ӯ%@刲Tj|PG@LF:6R Spk?}F,gQgC(Rj$#3\o\QwSK=R=s*1̈L!H)-r 1N %0 N,ɡ2Ԇ(TV @PJN4oȱ,8玢p٩X2 D$ĒOe 0lrr.`T_QrM촞K MLιżY*9OC@VJ]-@2}RZ`d32 mt?f78纟P {8]Ns[ԡ@,Qι#t`Hrι GSn)^XRX]O@ɠq8TdG,]P2˾X./|- 8_0.Ar(Q褅N ;OE(r5Ծk[p "~[gy}m$uL˘ ~o5M{M01 ru~۶'ރQ~(Hd ǏQ__WmU/5660Bptq\>}yvѣ$LfbX1Fww1iȄطoߵǎ;f`o8p 3cƌb'>R(W* /2嬠Q \.nnݺusNѣ/ٔRk„ \.Wlmm}q{B֝;wÇ_ yvvuub_x]tYzf,s6l۷ *9t6%wifӳ,O6>J7nܘ={vaɍw}jjjÇ?&5d,9dXp(>矿 /D43NgfΜYo;vXouqSLo~γ>/ׯ7KGSD$}F;?-.ڸq*uIP(F]Ce,XP{ܳo߾w)$dNضmWep7n|9gF @iL4>JuRF b:'v<k֭K[ZZ_T!쥗^zޑ#Gݻw7|޽{oݺu%Kέ~.8t.02GseϞ=3ׯ_m۶mk{͛7wmݺui[[9"6A &L/{[lɬY渮~o۶mǏK>( QnH ޽|R{oj$]xqqݍk׮p {)c]4 GͿڴi]v׎=\vmmL4u]L:fܹ5t:s~޴О$p8\bX _W/_/_wĉڵ+nصkx(dB w]w mPo~@;aq)'=PO>t.k׮cYV/9|>UUU3 ?6՞2 !_!~~)Yɑ']]](tvv>:QJo߾cBs޽ Ø;wu1*5˲GӴz]׫㜿9MkVTc\{ښ.\s]D ,xxϞ=ovsm555nڴ)M)]|oAx@FSL|V4s,xQWa7|Okkkosq˗/o>뮻ѣG~?2GI4x VY``!˘O dz>o~DܴiӃԩS{ޟd]]]3f$8N24^vx́7~4D]R&;+A>l}4L{(O=Ԫ~?z饗Z*++D"{O/X`?{,2/}iY2Lpk)}S0. n喋vi766^|~7 `2Vc=w g͚]ϙ3fn5k֜0 cpV @>.b^z饷<#_~v*n޼9} />oY֗\'p{iOӽ]]]}}}Փ'OUQQ/\pM:C8g7`zhfoV'RB\puկ^]x|X,+W}w\3u]w.]zɎ;2 g˿'6mԵaÆ|ۭO34oue˖=9۷oOwD"14BGϜ2jiK,޶CeU{?fUu]wg34Mcƍm[li7^*8hy6h" @!s^ /v Q 3lxՃP(cwhN 'xﶙ`2ƎpΏc ކH9BH?cp>?S o\h.V9y7ow iZ49}gM}hV۪dt7Z߀sn2N8q Na3f2.2.2.2.2.2.2.2.2.2.2.2.2.2.2b1fOIENDB`ukui-screensaver/src/assets/weather/5.png0000644000175000017500000004332714205074704017407 0ustar fengfengPNG  IHDR>a IDATxwՕ6{h4J(# ˮ]kwiql &gH&+!$HUuVM{4`穧u{ %& 轸 w"zPJR5k'ض$PZ &bm---[OuM #zW_M6Nf2IJ@kajjj61mڴ͛ٳ7Km`Xx /p͚5a !,H)&"BkMmP( @fO}ѷ}ُToo%'@xѢE\Kx<4emm-{qʱ=3?L$>prdF8^dPaXkM43 uaYVmmp}}}o,ܼS.?Znf /\Ҳ LHH&|Rcc#lۆv^}T*.Ų37)Am*&. ,lqF| !t}}W9'ϟɓi$uQGבGh4q#裏]`TVZkd2lݺmuRBaa$`?b J)ömyضX,c̙p ;餓^?Db'?d2L&4MqAa(v+1?l mۆ|>qP,avD!0 \O}}=ڐH$ ,l4xffT(d&mۘ6mSgu5'|3࣊} @wq7{W !x祔?̐R"byD$"+'>q /@; _pA'գ$Ւ=5l[|R34M$ ̝;"1 F1MRJX&L:Z[[)L"h---ڵk/+^蘂ؗ}dòq/:O$I`v,\-;A''YX fB2#8,z;B8H$I}}}P ̿꫟8 `_බ,)+$,K;0+%l3:0ʪٗV41sL$ ?/3ޏs(q'v%0"$Rj8>|_ʯtN bfZ 2MsRjێ;^ε +Z`OO:_Դq²,  v6 mem#8'̯95y>h4zիoG|cz/ 5kLZ?Z__Rb1Dss3Ϙ1mmm܌z(`%I 'm*1+`owGk65JjM{UCCCSGGǪL&C׎zٲe\s5j444ؑHlhhyi(`bBbXV R}5FUl}ЖWag{0Y5 L?\u֭[}衇Hgpq ~7f?~JJ91 Ú2e qૼ D |b|mpxQI]λ7XA秐#auE>ǔ)SN4 u%>&pwwwW_) a9scX,FZO8D4- ƜpTl~5UgO}0-?*~k0L)b'x"~뭷Q S̤{ɯ&@P_WޱcG)9{l># @l"3 umӱ4IaFa΅r4G3y셉d2a=drC[[3f3| ɩ~Zao O?s-2LN8| KO\>/OݮĀp^ ߞNbt8Rٶd21}?[;ATm.Fɓ'7NBMM f<ySª vr pU|ݝ_&i^㺮f,b(4l۶Nzٳgo{d>蠃{X,f.Xg͚EJ3@{ 2P(j_^|jl_0䛅J[=p@kڶm#JP( s1?}@ Pw嗯Fnnn'p$N!'P(t<(,aA0g#~0 ^!`2UP0zzz0a„;o]{ zΜ9ga(˲ĤIF˒]fJ&U;UsKD >JRayKٸP(ȪmW]uG #1cyap$xZZZ^ކ3N#J94;+,]Ntj|JaAݲ,Xh4xIc|%W S*E4e,A%FB%-|Ȳ,D"R)'pG=@4NlvHQy}!'A.T#*|atoT *)dw;mv }A8-2wwD4@&d2g۶96j'܁jIRnJ8TAJuV Ga ߻ 0Q !ز,={ nT "2R鞞"b5;C2*hL(Y8p% >i˫䄎೎ET|y;f @D$-[PJuJ&έRIR*I}L_^8^fժiJeVsT\ u}$DDBbf$ɉi=5B6nRJ uf9ˍya0TcPCc#>[~9 ;!Jj 0SXM=?AFW*Ͽ&pbd$0*ƚbׯ_nSSӼbmۖeJüaϻZ UG E<T\}ವJ>@t}0]$>F% 4&"5yמ<$"DQ6 XT~%543>+2+]͞Pwt5t.r^ e)X4&%b^`p,`n޼yWs12l4^0:5,aOJh_Xò`'V(}&%AoT&8'wA*WJRʈR*7sǪ2 @?looVkkd4l6YFyP ; GNK~:*wNQD89;XnX"Rʊ9pU0UL'g;XR3GPzSX,wؑ3g"bQΨLJ Om)XDUZp>>PMX,=s.eX B  n-L>@""۶.q'[ѕ_~?ⓠ6OA2sTsA=J#XF .0]]===?7:3DD3;(@im "Z|>?s/0aBq9eYP `'U;h~ Y Œ]Bi4 T6{\NO?o}(I}6W%ȝ4@ɤ֮];֭[{3vj 3?|PT*'T2i9l~\((jXz= T@@rnC'H]TI;5 P6X4yNWXѽbŊW H556666d2,+ -'NlhF0ژ0 vQ\/#8PɎæ%|xn|X,R&QRww?V۶PNݬ!& 9>Fq<1s;#J&߿ƍ}ũ_,Kz(e)I>󽶳8K1RJ~{zzVERn&%$F[}w[ ۽4{`1<-aBDmۘ>}BA1?YjG!1%|Ue$7Z۶MbC߃G,~yuooݺ ""fAg_5&t7?w9*tnDmf =ԋ< r& 8GK(l%ѷz/uuu ,8*+W;̃# -iպZAw7 Kh_Z/ L4{ဿ hѢ .|,u{B<zq`w'_D7ra]c x!2#uމba̰Q+HX 2qLj$^'S5z4g,AIC.C>|>oʠٹ|>Rqz'+Ks`樔2" ! ]!]TzzzK,Ys}=tgɕ(:`TԤ9} 4R 75Ȃy%?r4 f0xg8i0/^PwwOVpطba)}'VX2~[U8nƍ76a̬mv2pOOOoggggGG\.׋ ̜Ci ,Qio[nzްAEKi 2bP# b  3: 7뙾q=hH$\U6Q͛7/<9䐣k|* 4rtEc 2Lcu}}}ۈR(f$a˲(`FQ6z` <~wy? m%8͟luwwo^,/s9t5?}{LOs}SW3Fuִas>)2/tDLkeGNݯ W̘"/>ZܩY(av^{wY2k֬s̙?a„Ix\6X6 R6,wض===6lذbݺuo"M9s&M:45"؟;>hR^v%Ky敥PsR\zV;z-bԧ#{ ҄ǘkJH$vm!-}@CF2֪SliuyG̓K}  %3,"˟_|gN8qZKKKk"D"wFK{{]]];;;nGy(z֭kniɖImmo IDATmS[[['5555b14MCFqL&ݼyׯ1Di>EN@k84?$O\rpw8s(1;c'w+e>JM9O^mV- Mज़?~q?M aZYu~32xS r7}QIoy?t`z1hW0DmmmC}}}C2lL&H$R^ʚ]׵b.ɤ`*r]7u$YD%3H!D,%bX0JՑQJeDdPJ`xb3v tَ*#@{JN/9(iJiO55|e; 5;|qţ-fD1>]\U#q&f;wK{/1GmEx5x>dUTV񙿋 po jWXQeK fMqgE`IwA"@JF!6ac/aDC̈Nfӗ"-vf0ZK1ss b 0a*־uwt-똕(d޲jisH %z8Y ^NeP#ZvSj/n]ʽE@g|) :Z(چ (28΃n;@PB. }_8tu,BH"s&~\ta2ko_K\UE Ojk=^iopᯢ1şK=.h!K@pVC?j6 \/ 7?0D=ßKepY%$3ifs#757^ wpdL0"вUsa-s-͜1ԍ?<DF(%Z jG˅gThk6Z% ܂!$㖵b7KxfbW_Ɍaz/j5bAE.% \6?w:cXѬN<Ȓ2gڌ7̌fP (9g`*FwMNUF$m* HC[vK!#QU\fB̒d*C= Vǰj R'IC(F E/FЌ @.9{ aeO:ˤ qyC+M 0 ! }}X6;\Q9E iZwAr&>n#:H%]o_ 4Jt^A)&J1!yK"ao?% {񄣘iB>de`,̱'D"%e?2σ A fa@QN,ȥi~R#{6 C[@/@&9iW݈E(e5]åDžK5YȏlӲ̠ i } ` 8 ~ԁG@Aq mDNP}=8O֢^ djor/`f" }DpDJ)5QO{$bďqe_?``e⮇[kC1('13WͅZC'ZX4Lf5̐Bih|>Mř"`_2Z) i % -UhT W%"Б #`du$`\ 0}0D%.,B)y3D$R(iҨOɔ>" ɨFB&q1(pXFfp?kw/[xti0-oJJ1GBOCBA4dz_}u0 w0~enxe5K1z aj1dUY ZaFJ`w8mv!T׃+X8!bDV#6| A N@ wF|Uo>Hetle<6ih$e+ Q&ѻk~W`h !# x{^8B?vpSm1g;n}x) gۧOUۭD K{)?^OzэR')1뷯|n9P"F㽹+ _pz|f˄MML   e$ } _YP,53\q/\ɓ? ">P`YA(e1tB`ժ ]}nB#?'bX2~Vr;m\mǣ/b=XjDzp56gfDQ A0 *'~EM$)rOO&cw)xvaģfvz&|?ԕ٫:2}*`[:8)qKֵ6v|hO8>59٬#<&HLva xO>Ab)BP4I .nNe"2R eFsimS0E1k0eaփ-LqDZTo|%vS7sGwXHV\ݛ,8de.CjMV ߿calT#NgY"N=9=ZFOb_?io@#v Kj)L@3-!%'isKG$zҽ(eF%KFԚN*FpXLEe/J4b͸ӑ lzdỳϙs瞻i(Xfĉ9";w/%R&gC@ mw+.n,ؗRy1k>tkJZfCuJqˁųIHBͪ֋>"`2zm 6\Y|kn!FɜG;):82):TCSd󄓭y)vv>Xb~>bAHu/;aRԨa4+YeWo󺇞 }`7Kìt7uS9un1ݼt,"cZNP]Bg;ԍ`A4co~p?1`jfvH:Ȁ)͠!H1bsy\w# ED9a1@c*ÜNp+icM+2̔P?/c/ӏť *\_C@wFiߝ^R`ߝ[{),z:6{WB D۽z/Xon]FDxR O0 ;d@H{49gG~a6l's-d-4,5[{13ίt:[Q.zv?[ Ar[zXҵ@4{0Z;j|[ԽnoqL.-+SJ} ?$'y8=:eej4H3s?JkޫSz6_qʌ(g?#t [lq1Z?L .e؛ק5Js{nSq.p—&qI !zR؏ۊ62)u!i90&MQܨ`oP8a_sTpBuFiKkg|mL`f=_~R"Z6CJܹG;voگh^\ԷPD/JS-?no<ϗ5b[ Pq7J4Nefun-ngҷסCl'ƒ!C8+Q|C_{Sȁa)e]?@51M8{r8rdW}oO[êaXթ)~05u:GڙBG7e[5<^POɜEWO1K%4ZBDֻ]> Oopr=RʽgKp[ w?6&Qך|({|W1 id{:wa槹C D~$w =ŴC}Tڗ3Լ/sRʈ]kruR5˟$̢DʭMصQ(uڥ;@fysWJr!jC57VpOz]?gF_jZ7oǛhErfslؐD45G`XjE| %%:te;nEjxhu60"IZ 1)ٴb;sB *a.U7fՕ/" 'پB@iFHf9zt_qDE[M"Nf Yt]@2<4#|dC( 1BG^VX&2v+?>_ؽv&`6ڽyaءQdzLsMgHWuh<(2"̱)hS!3-q ][8aDžךt Z\V^fo}7ŋ9dFڅ?z֘PD.en|u3bPܷ_4K){R]´lCNL.(̤f f2@ŕL y !~xf) 1q0TNh>}֎h}&!+cڔl|c"{\55W@3fT^ W!DRN3MZ&y-dmZ'@)Rc7qk݋RS5Oc أRPJ<8SpQ;qLEIENDB`ukui-screensaver/src/assets/weather/30.png0000644000175000017500000005021514205074704017457 0ustar fengfengPNG  IHDR>a`tEXtSoftwareStardock IconDeveloper - Professional ver 1.0.0, Build 839 - http://www.skinstudio.net0lt IDATxydWY/{Z{p>=wt@”QQO*z s/|WD\AP@` D dN:NX=~s짪v{z*bfGmG݁h? o aEרKw[QYO o}S7DZ11 "1`Si7N$F^0 f8-sBqadܲ-H Ps{^:}V6n=ƤןtdHH`ε?c>! C$YA)zqW! uQ~X IGiv%`cRMs, C$$NBX01Xk")|-CgbꬒfB){/a\/]`d 7uh[40@kܽ5kB,rʘKk׃+}~z{?=sqVnxo͝CH*ȞwF<}5,,`[8#1vmauqXAkã;JAPp8=&b~=D$L~7_D0I0IG'ٞQ)ըPB|=|?߹$4ERN=Ǐ?$G8HyZ)pJ,Tեu/%v稽?HJ)Ẻoתǯo!:,wl1P q z&q&h !%~xoHdb]>QZ9v i \xutߣMfy+uO3ziU^=!D* g50ĝS/)tulv|aIݥ̤4x@%o@*}jh9o'f !a$~T]= 3n=w@ HDV\*%x#z~g._hIp!\ck=2,N:vE/0cH`DJ|wl v_#\X.1J3ԛF.>U\ܺ|_@`^q$4e8 )T$":U kC6yʋG?{_RD)N^'n-2nI T8)ZRA:W ubfDݮ(B)9w掗2(tϬۡm?AZ"yJ#},<)33q,0, /1LYLnEKo81H[_$~s&9w> (;,?fyqūvJMz5[\SaE=7%(:yGwxՕMW~˭,hH"ɬ1F'V0F$ZS]1>3*@ƀBk>F+`&)O4 Ť /BDr73_͏vOQ>q % _8F\ 'W[s9zE2dGIhrO19W]?ՅTNT(w! EBXIFY$M{7gެ3 LNe Hyr hX8`]r'. U_nŢV%nuU]׿u(_ƼnG33D 4`v%% 6BTn\hPyCzMy]qjʨB**k?ut +)RMj}S 2 ẽA> C1!+BW𠅓U[·38z\8eIOzA"DIxC msxMѭ_G/1bؽtW7p|AH-%:+HnG^Z!碰` 3E[nL0F@&)M?0Q:w*nq2;Yk !W@eoy )?& [ %}>wWŠ&1rشz&΄9 x'!CF *!* ;` Ð% $c (3wȐǏab<DBj`k6wᏕx6&{;?a{o~Slр,'*pY*Y!95$Jc 3+!&z p^ H }IL` 0`:#//4dV[ !4ށQpuQ!Gb[q/ "fpeb )00M*͗L|SSM &|ڵ kΚzЫ~ڿ;/GV=2We/ҳs;:d9swDjƮS)D?AAd@ |10,s pjZ3aH(E=ȑ ! t*/[n*2ZNA*9DNEqmwO v $ dJCG~;nܨml|*1iw9⩶gfp[< 0kHUW'M0Ƕ7gAo{Ϻ_uj }: 3 $# 3 m.Nh4DTr"x0F*a1 YR@DEI@ 09 TU[ Uqi)JxW58D?Dx_Ew]}t؄N HUpF7›;HA0s0IU} ɢ& iiAJ IKpX$H(A&vLkn.n3Y#c&Z2X(D#ќM&ڭj!K!L@L ,@@'X]FV71PS@6BR* ET*CBXy)(BAZGTtxpOi%ωp & `0J8!PEfւ9!a7Dt!LE44'BzOԈs+OX89kaԉ=a3=^ZZjdi.$38< S 1 @8&஻8_؃y:J< cbbzA-1W\ׅ(}0Z-bvv%j)| shE|%=$ QALL$ ~9ξeXKNw6MQDdsOg. J'$%n8iB&bm'uU@^(F 1 @EGu +c!x022uaxxJ)&Ud~ Z 8Ǐ,<`lG,\BeHBwDi*t!!JCNǔF+`Y"3 AGp:1C{y[@ IRԈw'm$PiG م`& ! w_~*j\GP vZ858^"3 0ȘeaaFV aBq4W1/o-#(+ Fof F3X\@!ܤWnj #( i$ d/1)IO{ HM PAwe`PƄSĺː2O'qX^z(ؾ}; ̜|fqZCJ&fggj18 $kT OKp!# @(M@D0 2 bc8p1I I;9E@)RrZ~(Hn28H0L @YpS ı_XQ* v؁J8:0:sc033Eq#I~ܝak|:O`*/0R!N0L0*eH&"IDQ AI' :]J.m#/~9߈=Hy^R*LUH0XHR $$  d nw P*{>&''y^_bv~Ik;x''R( Xr%*Js&'{' @VC4fgt:.ZM[b|6onF?=>z8}GwnDs_>ȗ!| *1mL x`щ#dy#[˗ƂzuVQtJ2Sl@Caf="T+#p\2z_3DEolG}8rիW#Yȃn2 h,@G516M|7uW^Tm^͡txjsWx6F9#"f5Ǒ环lIg*68'pZ)Mv 䀹2wNZ0Ӑ>Cv T+rBΊg, PXVu~f/_RTa<"pJW8}`?#iA@~/j13#ABb G?p^?O|Qm-R!пLwZ87ŦJYϣW1ӥuXMRggN׽:g =R.@2F8!"-pFV@wl4?сPJqJ~&/+IBuݾRT*aժU}I>;>0s(3B5&}}Ml_{ssApc?IHrL<zDʕ^y"F(uzsfo;1!YX0OJݿ~9CZb, !T,%RՕpF7AU]![fQ=ʑ|]㍎j&i]x!6]g]v>o3њ /AU%t"h_QBfD0 i IS3a/D[P1 T evL?ODHxyva9{kG vH L}q"&|nK{ϻAL(7됐3}o,<ѸNC1E͆`Ct?Y$|&@J)"-d 1L})_l=}SrBLRٴzWfTDJ68Il#FKvqa8(>ώL}M5slI(}況/@v|_J5˨_7l>}.Q G@F  5Gӳ>eFg]f}BBbBRчppDLIL 9)ͽ+eͷmi9!dsy Q;=@cqÑq$E¦y ipZ@A0@NO>|Ӏ(RM=ܻ8gK|Ol 3l ,8>  ͼvb+gluԊv :+)%YC7ܞ\ M8Ǜ_S$'ѭ9Wʛ  YtqH1X99bb1 "/cjdg9n9ɛAx ;]_|"`ʲ 'Ue jl~AFD.hӽC)0xA6zSP v.\WXU3W _H¯@o^Zax^زe FFFIcvf]aˈl;Lgd痒h5 G<8$Tu6G@ !K$t1@LOh2h| @mtnG%IKn^Nڐ_fU~[n-[yg2`d) 2;r5Cvv.\%>R 1A(a63IC׏f1!2(!f:Og@@DܛUǀ"ZyzB+ y ~aXAP;iӦf=; j<,lIK= IDATs9\}$]$ |&aᘿzL050=43+)t5H J/g vV(""ʊ2_z^ōp4nA4 > o _xgVOJضm;<$IҟϞ9Yiv89q|~,'O|80/i޵u}% 0n~"ط*I@RBDZ2t;YóbG*6:aJv zkl %[ f(h UG{{AȱcpС>Q2eT*VaxxZ n|*K}&Ϩ[g[I[9q@Qc8 C\,xllmwֵ'^7=pm}tՃ}&qjzksHum`^45;_ZL}Rh@.}T4LxjeWb;ꮬ~nN nJ9]8,rೃQ*0>>IE6mA80-k]jܯccN8. C=vW_{o0IbM*xUJq "]T>P\gF(^T݊⇢+(P\H%dKF (jj̘1<<0 VB||ok 0Afl ,Ţg!c1Qk#G oݟk>x`flrV Tm@R |furNDbdhcoF"]oGVm5: Kq]J% T* 12&gǒ$`Vf_t0??c n݊;vi&=3g3N!?Yk06 io_kvt:n0 Z}WWОb#ۗ>WwOCqpeUMa8%K%TQrAA\U $Inۯ/윙^/*$Av%Pfc+`38{3X @vMf(J8o;RJ9z{go/ԍ=&B.b?4KiEMX, UPTӣ uYv4n!QVWAً@əK`C{|lh iEn۴a{u7l׿ Y$1'I : 1p{Ggm?I%8eP"h1^B+j^PF\ƺkbŊ%qdϳt^b3&o:.(qWciHs`Q r x2}.rcg، =vvif޽`}J4 fy^B)'s/8wUЬJF"#(uAqV +Ar7o"DA?c~\gj/{u03:֬YkBkg}&җi{1\<;|bˁ6&%InfnI'Iv@ `*$}?.^0 rRAQ bEPB\֭[QT3e@[g_XXLFfɟ|bѼo;PVQ(34 t0Ki|.b9INVZon$jj0#,}Oia~REҺ;JkkJQ0[(o T+g-˪v~,Zk4 ^a{y v(7DbUVaÆ K%Uj_ zֹ|tIU: Cqx޷{^/k3`${[R:Q`v8&f qe}կin~\Q)P*ƍ1>>~Dg޾1f8t:ʴ}v]Lk tn!Ě5kp`bbbl̶==sm)s⹹9nW|!ę졺ل#B Yt_Ht+u\ɂ^P1s!D^5??(=iZz=j&P1[l6E6<bӦMKiV׼d. Y?ɨ4pΞ̊M\%u]@/>O}(Za\I h͜ 3/zU.JbŊg8@l#jc;xRy^`||by1X,Zl(hصk<+[lANjl3ORw4[K5n&CjiÆ wgOONmoKC{Xro >U۶=,l9r~9cП t(֬YRrȀ u^ׯNJ+PVQV1117}{f#U#eԖclz/ ˑn*qU#:uoVYПpd[\Q3APVq.e68CrV/111џE[^pP1hV~R`ʕXj:PQpw_iOfl ?BDd"-pK":TCf?ts|e }[&e!=MMaxx:?/pZmQahv? c d,.s O{H LDBTOܹe7 9B9 )EyQk[YjZ44 D-̤czg1} 1qYqlBey m.Bv*yll wu*.t݁Gc shH;Mid>031[V/Y@=׏D8bixqNhPEgg‹Ed}Hju}?;Usy1sQa~Xrey3@KAav|c 13%IF1ҫ{j %zː1c9i҅޷'O;'o;+yF ?hؠgc3(63f5;|;X}ݶР~.g^l [ejQ9ݑ:iBk#dbapÆ_|;}_xGYxTɫ뼊|%@0 ŕͤALZPXTQq!۷֭C$lq-ARSٽkmM`B?~|ɓO81oП`?]w99[(^첷( >Kvim,nm鷿#,# x6_پY8K#7MvgX\ם .{_2u.#fީ5o? I &/)  @VGH?8ȯ3=_O ɠmMsv9ILOO@wmydyn]w Arxx8j_###DDvXNsTk< ]LRZo̜elf Bl@\FTB^]ͲaF_;"8Kc/ӈ|QqciL1_Bq4+&G>(.*{E@'/^y/lX-Y2gЖ\}yǰ{rJ(M{[qZkZs?$`5{eb:㘓$Q_Wg>)#̬֦u]ʕ+׆ Ij*@y/Ep{Ե' xAI?<gq*[.+JqulL1 &4&7MPqC){?W*ccc[RT(hhhy<ԥZ^jDa;O`_Ey&/'K1l`sS2MߊNOOOĉh/LcjwȝGډ",QDR8( c (5E"70w󽣁 fժ~[f2]Dž1LLLW.}qL!RS? -T$I׌!"(077o~ @Ig o<ϔ'C|٫ \e2"Oc 2yZd3miH%V_|Xp]-:Ş}TDkfg*gk3ag_M/W'!F^ug-^e 40@ZF^ & @DEYlJn$UO|}%4 tIeQ*yk # ȫ=NJ)A.'9|0vH&>]RDl*j+!+M;axF D d gMj8aъ+o|-[ED[:(t$D u'N>gt:ls1Hb|vM>̳5B~?ۀNo y8FtP^ff3}L(QgJw" QVǀQ=8IX h,q?yK:}-K!AјFbr9?}5_-d{)lH :A9=v`=ǁW^Cwښ?v 5q D28@GH@: @aLT,w^{y{)zI):A/@Zxg$hKF'CN{yifjz)O-;H !,G#1e9 ZL@p QbCdCi+pކ }V!N3{ر#6mژ$ GQ$l ([Ϥ9˚+|#yˈmcfɚ|̶:lg]K HfʞQJA*E QT(z2 VtBpH@k̆Ft05hoGys21s/(n$!~MrlUo3?4:giY@fb?g  "5A X@`AL+BXpIcty6h{)WaodAC\p$J^eݼ9MHy} {{뺢#'t35Py˼8 m'lgfP4WA %3@C @9.Sڟ ^>6A],⍯ҦM(wuk*P?<זf4ѣ]/{67MyRrP {K!Vv(gAfL&v4Ϡ5(si-| {\6SLy'5YtpQUHr;n B(D.X]wB6ðsZƟ9&2dFCD~7]veGDyƽ% γ9|Hg)ik[rm[k;_Y?m*68 ]91 #U'6o.\YPz[6OMPs0zU( 3'o߾{n;7?wvv6tz ,S ug |ؗ1*c|~IR6lQ-fj?a), DԞi=6}|8Qrh}RJG.yo'^l%dm۶ = DD$o/vmG8VӺWKV;M3۞mdc_^r7{Pege{ymfWZ(oJ kI' !xf߾c1YVjn~"M ѿi`=ev3/x F#df$IQSN)377GF&g5f[dջ-pvM}Z-H)MxIDATg<`9W7-<>fYxo1QUu|sVCk4=EĚ9uKZe_v3 g](o7[n̈́-uL {7֭[뮻OV^bҥQ\0j٩\iOTEt3>ڙsuiH+q:5gڝa!}&G^x^"[$dGxo;֭[3fN#X'$N uww/Yr+W\U P)T*"!dg0d>E5^:} mwu:)ƘձZf4ř3gΟ,ϧ Qjl5O rXk%q5衡ę\\4PHD%T&GGG?vB 0T*,GQ޻`+cSVْfkb1P,/gŽf*z2gA%ueMNM?<}c}D:cjЀ1dfZpƷ՚R ۶mo9cXk]<lwi11YJc@Nj=3y35 %!&A`e_ҿic/zq mIVfwH4+/U~ {8s^FALjJ08lr$FF|}Ϟ??bpKo@+RɖRyи1=9Ɖ_= .1&S`2& 0S8e>EsA0;lO? fΞ}Y`Es4@E1 @/>q _WW^~f,LB\nqsz Ih4h1if$l6jQbۨ1868{w?ߟdY|#!,^ܽѢK+U@89]?vÇ;{db˵\S$LdBT  l l򜍏n0.>(z!q R1%f.Æ!YگDͬ 믻]|RBh>Lj4,jpw{G!W-EjQ -ݦ䎥o c5`"IC>/~12[GC@J!$D}r&h:0Y & Q+uDf.NWM#QZ ` B "JBx{n!=G@F%>QJYfu\je}}}RtN ^̵F`':oǏ1DW_vKzz/JbBH()lebzbB;;⋇πVHfcBR)I\3 k[Ih3-מ0Ɣck/,m8pf)誫PZPsA 1 CCCعs'|IqIz@x " :q{5)\./X|K.袋z{{0 R ZkZi}j9uLw'ONN?>1uD=Mg{ D.YK.YquѢp钞%:3Y?ޚNμĩcNNOO@ F,<#:rW@3j-`*m;u!DvMCțGM0q5O?ыq)s=oFDT1tJ/Ř5 %:$|73@! ]O\eHmʍ @ ˬHAH"e%%o̙fN5Ɗ:u4]QB@I, c[27 h@mJ\AD:GyIw!I ̟fK444 )eo z`5B9pmF$7Y爜%`=sR (˴H?n~ a&e,;3^S-!|^ ݼy޲e/}bGN} SO=7JAknP,O!eI>-sgJ!P jT(!ۅ1 zfi LА@!9 g ]ʎ4siS0)Pl^:߾};oذ3j.y RJiӦdbbRTkk '%me*YXN[Զ.g;@IUtd Z 0LT@,-QO@9d "5/mj lV]owߍjzf!2A#GĎ;ZR3a P\>;k4I4S!ZIl+t^i|BxݻGGG1o 0u9P!+w AH⚵8zTI!V:۹vܚ+3cgW|fc?dhrL;7]Zf٠ _"ǟ >%s2ՙOPt:{##$k- 1Fˮw8Wb6ac~Ř }: l,iN̜Lf$Zخvr€A$,5W|fm{5h~?gf>>8T lQlKgi Io<C "QIENDB`ukui-screensaver/src/assets/weather/53.png0000644000175000017500000005427414205074704017475 0ustar fengfengPNG  IHDR>a IDATx{mWU'c̵{K$ !<"D(ER;X֧g*Ֆ]R)W*Z EB!HBͽs^k1~\k}O$<{~9{{91p@?p'?cB6F/6Fn#70MōQwf$]=]#Ѕ^99y{꺟ȓI B)!#d)$}>"nCE""و \3%{;#293I'QDP6' 9S>jeP /w~_Z F >'þ"KÅfVANN<`C"gfPb"Qi2vCODS:!&qN$8J)BjGE$F\k:G }asLPe(Q3Ȕ[ gaЙ#b<,kW+K=#YS8fuT$#H`)qW#@=fpI6=Pkȸ8V`{JοB!H=M{oAg)#q6Kԉё惔 6c'InG<Ց /ު(̌$edL.Ve%Jy Yq=]}ϵ\{?~b<{dg|=Dd "p6+/iοoKݏ}֑슪HNZ&Fs;GQ&QUjPx}fmb !bHeQ{KR6 x@PN׈%~r`K>shSǏp]pdED^U.8~ԉa?JkmWo}w[6mwH # 8~ \z94ɦi;*-5~n8rߏjRUk`d@2aĈ 2jլ@xh@`>&Iv$as$d Y-Z5 k*`$Q dxdQDŚr%'v\싟NFY#>/ʝa{z;^c zz!"aUp9>N T{;~y&@v$k(ȚHA-#W "1RnBQ<2#'G"$wR&3gBދP^=1Qp0dDiAP%(B,a$ZtI[GO.~s |?4׾/z£+ *瞳yQy(R y3QT|=&Ї]{X-#WS~_\v)y}R5 F I-m,ZeVYHDt4:)H`H<Pު$ńH5dܽSoÉ~=a]Q2B{;_[^o^YW1?r)"\xOu QUz~OKܯt3~'_Qѧ|cgqqX+~ؙZvjIaMU+9d1Ni"ә(O#̍}v/#_#%X[1ik0d\s͍Ѻ9Yɀax{;wo!|##/3!#G]g ^㶕O_y3?y5.~ܣ "xֳ|ӄ :?~}te?f ժ*ʉʼnT03/8CdX}S/}Ig 8qD#"eo)l{āI[Fnҍ +'aw =QJ>D.ixEO1NK.m;Ԭa%M+t`f9q 7RI>^ G+7J@{~[GT`zB5sB7[wR6s.z-\˾Yl+@8!{@?G?p/Sݡo>ۉ(ED"Oyַ~t׾c.~r" ?>{ו7[,/EvO|ܮ;']um*j4%\_olJ?LlX'u61`dR r=!ׇ' #=" Cj<㶛߄3§[;xUNvOjMHSr ;}?ў>_< y IJJM</W‹scAmbww/kW?H<]3nc˾it7L.Xc_vR]SMڶfad0٠i{sOktӄب# ~{^Z3i8vL$9+%Biłoyß9Kъ7; 0K.OoG*p~gusڋQ^55?Ol ^Gx̭;ѪODT-q>! r:z Uɻ;f hjRw92oauGn~{:X$3-k^0!ܤӃYgŹA)"ZCg̱P~TM+2(8qۭl:$t૿q~Jk_bGwʳ`pE~%M7WʷCp|^wLW }Ľ>kݴ\$}-(s*cSK^ٯVD'b='G ~:Ɇu0Ak5"‘wnDai a)

^X]vOCԀSs,9S/v|_}>gXJkZ!'=x/qČ&_O|//j]S&ÕG=gbF`Tq>w߿虏7>~ylrM&YR87t$lo A!4ugRjP5*D`~UDi(_^3/'=!*|?Je e/a9zi/x~R>@6.ʑcg1ǏlQ5R8`;nq,˘|$g:w:&RL(2~ darݷB`-2-Q;oV;P8ΰ6TP;uRv$'obч^L9vs-rGjl/{<< Q"Anm+_g|o#㑗^ (rõ/FT];M:M`IAf۹Cvn%dQkN-@-'nhTMN֑^I5\+-@gAjdt "µU/8/?*<`]I txp9-G򍯨pD^6?z K^qoq`ώ}0SC(O/)RJ/|WC-?]ׯ\;d~!C U&ʦԋ OPU=Zpp`l#o.pXu=mQ=T9.R}7dUymm2';E o}dO|h۪nm'^zdlS M3=KNk~z@x?ݽiDQ)q}믿ܮoȈDJ6ANw57|7j?Jlg&!P0"4m Gg#jtSb1 HMFh0xӿO'օV$ S(AR\,Nif1V sȣ}?3DUEE'3f >!(\QY,FLeVVV5WE)%NF7M}񺽽~v Ƽ@ZlzPy0v#@jF)5u)tJ r02ȁkq/~_#}`Ppc ^j>soDp0udDȥ0|(;lU~ojxqhL|^q7YA2~mϣlz6)zfs\=M'|si :lH2< z)0wex lh4ݿ%w!AЀlI RG` #ٍop `?W^**5Xy}C_U`G<<$O>I{wDS[T@ MBgBcrQ h|}/w;/̽,moGsZU"j 1"1<6t4 Qxs18B(#$yLm4*ڈJ,eդUiNMgjը.$3oxxX_'ؔym)ys/e^*YBR̖"J )ҒlvBtPmHKH5<ƓU,0RKdjJq,^j7ZP}/M@?9zcƿCv}t^V)yK.9^#+^zgDUDR@DCUkjM~ܢ$HUF$U TDFD "f"4Zs;i iJf*"e/{||Ӿ^؍]ٮw'Sl[uln!b6X$cީ 4 ѣD0"\DUN15-"QHKbVbEUĂ1p{jU; "jK[6y ?k-kJ[:iTxɍҖ/ZTzj_+,!AMӾ'7 IDATfDN3GG%F&L`qڊ!Si7HBpڃlfQ  W/|d?[pOЮOhJp#%^ üa;Hdtv>gČj%ًj/@hQp/3YTrUս#d,HCtY i Q]"9Zjz {O"Z٢W3I]܌S$l ar~н z+&ܛWv6^p,o-`3F⨕:Tx̪q`,DdA<"j+bI `FrA^ LT:UŒ`5l%7$=Ae2&>|;a? 86{g xݕj,ǀH"E0)c2l((#,K9^*Z "d "Z&p[ci?LU# ] (AԲ^aPq4lI#+ѦQFD:^Z/K2BX;UMK剗=gS(}p_#iּvXw^[;DxˠZJyM Ft`tL"TQUK^1'-ZK`0 #ԨIeH *`aXM5e]+0T[tTDQf""c>˝BMH>Z[!TuWszls'} T]y%oE3K%"" k%axɍv*֒@Qmp!"-jχUioXSKnP#x R"ڊB%$i$a@ŚvE'وhԲ.5ߚ$:KjKT!(CLՊ틈FLJ(ZVaK"I$dD+Tuda&1S> л32DfD/f_·<Y)y^SЈv6Xj(]5WQtWB̚&D1V\@#R)CMM74l5ۖ,a܏fJ 5 (eUYdY{Y%׫ {$O<}z Wd](SoK%aE+ w͹|2< /OEԫj4S;BDy s/ԄjZȺ @KU@Z P@`%[fFH٠55m_=@SDkF]wTTT4lɫHD ^*ۄ`p& ky@JC}Д[pR0MW=ż'@BEjQJYj<ܕF QywJmi]- 5Q5MɯR," 4E p|聪BD=v ^J HDlK@I= Iܥ@ZrUk+@${ F*#j c+4+cKF0a}h_ooKi=ʼ o4/ /f)hdJ()Mz)sF4bRi[+ՄuD-2ڪZ4ݼ' 7ғ b"mE2Q[ @2[fOM-XƬ<:}U߽֜#3%2%2g{pK"jAHp w#KI,޳]{c׷袔6hҝ޹dEU^jhTSC4%͙缰.,%2G S ͇ zQs/Mlގ9hIHdzruig4 R wX4!Rnn`CFuiݕ\:(ѐ}tkD ^rm  3+5t5Ҡ on{NW QHV"B0F64 D T $iJQ0:$wo R (dȘلKK}-1"H (5#c|8\DKVőj mtfMHETy%JHɥd2=DCa+  @/;8D!pƘ:>#p@@d%d$]GU^jy +~w~^򰝇~K^L`EX+NehsE R5h7ZyLDZm[-dj^c+5bCjQeF(#č.[j.[F /3E   "Ny-)[2TPbb}Vj館ZJTm_Uz٬9%"UeZ n$KO UԀZiD|?1h(VMC%7q1c|hDBSd̬++зQr+jdž գ0imEH*  DYeD?Heh, ́B2PJ+ra\p%5m6KR~"nz5n\TgTt^<[%w^.<"poJ(TA5cxӕ~<#\d <%MD!#EZLR 0@B@0o+Wu@JBD 01Ƶ1tIiMS hFH#"*bTVƈ6JpO5kIJD)m oFOI b@U<' ԬZSQ& D=QuR%e[yȨ',*@R-#<r^--ܳZBFSZIhDK7F(݅,Ed4C03ZtU/{)i 8eQ# E Z31"ԇ5RTQF4 \t0րquQEdLնc4KW Ynj0g2rh hUKBRlH}EF܀A4>FIf.;Jn"*ִKKMV9"rɽ4m7["Hn{s <@Du%U~:Z#QK-MoV$mb70«䌌H[KfU 2K^j}Q-$6%Z5碆Exi+"ҤFPu5ϤFD"5ʚvR,Rִ6j#ZT0jNJT:Ō 4yR_UX@GF$QnlzETd1-"O!# ЉFB(Z4>z&-Jj_k0E<*i}.0h^YJo2pbVB&IU]z)8 ZmTDu"*H,Q ;֧T"rtdLҭ2Zjd 5Qj5L^. ja4 ځfU@ބNj :!ыjiLlU-jεϽW"`Ccǎ@@_bQ~HlAH1D Eq<u!Bc$ 8}kY5P;w-ݖ ggXkΚU%`+rX jvKӅ V/a0LۗOl 0k[b] B 0 MR Im?5Psb_ԕnf!`9=$W܁ޞ,%oo]m=ȴ(!3FTMC Si,Jˬiӛ$)iJiA)['i)I23Vnq\9h1^Y3#ff[(w.ZewAI8@jpD,>AꫳH;{5-ohW_{든2Nq3oY_5P@2k2 `U/Шd],y h fEZ3p! b^&bUAZw.z| Ȑ>8xgo=^[Q$9Gff 'H%vPQk TJg5C.T9h6Bpv<2fi5ӵvr1Gbo} k}xU 1-#vsY.h.ZRLfZҴH@FA)/G#@McM$2 N^o'ܲTՊ+Z;,!FI8޶i#svCJ %k>UCoRq[FtVL]9.(T=z8l\TνN Kq5^ZzA*3 CmVrFLb=\ҫJ˱ZD~onf9O9 LUːn])/,d dgGsv)dh6&6&* R&)[*[?ŪeɶT=s (<Rc&>`i~ PLP~@+'Q<م6Y~)-QAL=c qYXK~< ' UQ2ɞHr@E g̱-52Nv`ڨ*ZƳhf]pWvEnՒN6$ƛy1b}II*=3ZA#qW%gkgfqUOo[+I0SRT|4sfO1ȣ$X_؎|OO7?6eJLZ.Jě;ur1e& S4"g5IvߒoffuA3Qn( wJtE[RҦE%S>crH b(#LBR%O̘3|ZpoGļvfK{_WZ4 ^Y4H>YV?jWv׽_[`m MfhfD[%h Q賈rUMKe,_&e_!kITʉkRɰ̫tet3rnʸxi>bb$ }H üc6撚KAS:2T[so7)s68O2PʘNRex%'HE;7xg̘w^|(p嘃.oXp% # )5)EnBVCByYN\ݕP>yxc:m[,Vr9K TXA23堒`4~ 2rbd%*Nv-OB$ w̜BOeZIy#@nhOL@QZ0&)d|5@38=Tl}۱In{3~ЇPT[oݬXisq0vT,S3^J L1vnn|1cDeY&gνad){ Lo#o@eFGrݽ߼~l{KiPطT%#.cNJ=xffMۍFA`a#ro60@g>/`}RʜN7;͟W@i%V-V0h] W+MzlD|kJekIDATmy2(m$h,JלЋ1?PC]8L͜oOz:ai+J%P%.`VZ" ՆefZf,c ,#hl,#œ%b59WD*3ȼ]یmfҦ>\@>cR/O#@g"'74H*AZx<B҄a̅JB>I $_2rRIڜERLDݏ) .eLU1F͛<nH-t*cIBҞs*3YY336%]KsTahNoV ~CF^V,;H!8@ByUK!|z;Ol]_jзK>mxD5c֠:UR`y?n4m{2o)}6=4_37,x9bW9sWQ -FIJ0{vU/cEb2۹[<~Θc_`Mq\:!tD 3gΔtd7]po 0Mhj ȻX81Ry5[)y}:>8O~k/-f>CwF53"2R c c2c"c*cH}{_n}{1A޶X>z}[b%af,<$(])& 7ydDJ ! ׊nʫa1cd3wTn ۝s[fnb r48-E-$+Uˢz9HHKzpYYBQ6Ngʌ@l*˚2H?yB_|zC_R<)!iIO$ߘG$ټ] f}M:޷3c"194&csг2f٥{ nHϵ%\C$%dDb>Y -i0oٷ(7y̹KYSC1Q"PAj^W9j0%=3ߋx,*WfVa HsX3*\AxPu @}<2Z3%]̜z(hˈW11[z ܽH@tA4fFJupU4U6*sW]YUַ'oXӇy@ *]*&96LqE ' m 4z}@/SC*AE@t2IYo*u|8b[|79Nï~3'd$ם/no4w*sJ¼X><y.W2weF9u Y,wym2|" 3_[d4;a6H"CCWLAL,ncv`$V9(6* S52Y$s$e]7$Y$5'm(ug< p[LLJj+w(L9YpC܋mrJy}neO U+I ,7oHUט,yQ4󛔷E4IfXO`Ep>5)KvgTz*ʰ`JY6A-J9GLe"b6D/s-6}?4+YqA4# =W 3Mț*pcm 77p9J ̘0k˛9g8dZF|\) ½փXttyKr P I`1Q/PE"n៘pL9h޼uwo|z!)#RbմQ޼೔iZWz}9Zf#szE$~QЪ2sFAC@@)Q2`Y$s*Lpˬ'|ZzLJ*CUߺ$H( !ۑLe,ڽ( @!i :W\TTB81sn/!{se^׷}l;ͺ5Һ>oV]Siؤl `7(ٹ:{*|ouj3Ȋ㽌4Guۭc/$gxcCxUtU:hb @1' A:\EYI\ WoJ*ff5m)*e))ᣌ(3|/ȟ p'Aw~5Vv|`%% +r+Jm Sk \R} b{Μy;E*(̤L]S02( xDVl"ٜ )*]ڜ( Vwt33pBK zPbWĨJk_]!!Dm"sȄekZFO! [S(ss"ZK "{l$b̘g*Wc{D\X=1O&٪=O"E ܑw`4+ hl#bB%ILd 9J9 @-k"Z%*WJ?-% ͈{A O>3[2w1=\/??Sq1İ:s,fL } } 3%e骁9bⴈ;YT̖ D+Y!V\Xeu%a^3ȧ~- Bq:@OgL~="]g?Lb#*f^ +$.3^0f*wJn3+7 D:ĕfWBgIORA%`7WI~Vb`9S>OjsnMȫ2{+7jz=yC O+vS<%ʶ>馌m|4Z\@{f>q.5WJ@&S 8j=i,TFLR,]\ɛ+ )P'J ڭ"fFqM-ey1 {Fx*e' "e*̈YςuNIwו2_dk v4ߖiy7/0+s_fAlKD e`1y{!cn4*y/Om֏­0fw]@Sƶ8Fp|gi+To=8 :neLYєwss_Zs_Q K&C+2f*VQg)_+uFi,h}4;mE$^$\H6Y22|]H_9 e1ǜcRRV2ѷw?pp/1Zy0s9-h*G,yXFH13< :ySƘs_ʏu iꝩi?|{U|4v-ICս=+8mgýeȲt`9w@I/_Mˤk:/|Mky9.4v:߭wzޭwzޭwzޭwzޭwzޭwzޭw_h~UNSIENDB`ukui-screensaver/src/assets/weather/56.png0000644000175000017500000004332714205074704017475 0ustar fengfengPNG  IHDR>a IDATxwՕ6{h4J(# ˮ]kwiql &gH&+!$HUuVM{4`穧u{ %& 轸 w"zPJR5k'ض$PZ &bm---[OuM #zW_M6Nf2IJ@kajjj61mڴ͛ٳ7Km`Xx /p͚5a !,H)&"BkMmP( @fO}ѷ}ُToo%'@xѢE\Kx<4emm-{qʱ=3?L$>prdF8^dPaXkM43 uaYVmmp}}}o,ܼS.?Znf /\Ҳ LHH&|Rcc#lۆv^}T*.Ų37)Am*&. ,lqF| !t}}W9'ϟɓi$uQGבGh4q#裏]`TVZkd2lݺmuRBaa$`?b J)ömyضX,c̙p ;餓^?Db'?d2L&4MqAa(v+1?l mۆ|>qP,avD!0 \O}}=ڐH$ ,l4xffT(d&mۘ6mSgu5'|3࣊} @wq7{W !x祔?̐R"byD$"+'>q /@; _pA'գ$Ւ=5l[|R34M$ ̝;"1 F1MRJX&L:Z[[)L"h---ڵk/+^蘂ؗ}dòq/:O$I`v,\-;A''YX fB2#8,z;B8H$I}}}P ̿꫟8 `_බ,)+$,K;0+%l3:0ʪٗV41sL$ ?/3ޏs(q'v%0"$Rj8>|_ʯtN bfZ 2MsRjێ;^ε +Z`OO:_Դq²,  v6 mem#8'̯95y>h4zիoG|cz/ 5kLZ?Z__Rb1Dss3Ϙ1mmm܌z(`%I 'm*1+`owGk65JjM{UCCCSGGǪL&C׎zٲe\s5j444ؑHlhhyi(`bBbXV R}5FUl}ЖWag{0Y5 L?\u֭[}衇Hgpq ~7f?~JJ91 Ú2e qૼ D |b|mpxQI]λ7XA秐#auE>ǔ)SN4 u%>&pwwwW_) a9scX,FZO8D4- ƜpTl~5UgO}0-?*~k0L)b'x"~뭷Q S̤{ɯ&@P_WޱcG)9{l># @l"3 umӱ4IaFa΅r4G3y셉d2a=drC[[3f3| ɩ~Zao O?s-2LN8| KO\>/OݮĀp^ ߞNbt8Rٶd21}?[;ATm.Fɓ'7NBMM f<ySª vr pU|ݝ_&i^㺮f,b(4l۶Nzٳgo{d>蠃{X,f.Xg͚EJ3@{ 2P(j_^|jl_0䛅J[=p@kڶm#JP( s1?}@ Pw嗯Fnnn'p$N!'P(t<(,aA0g#~0 ^!`2UP0zzz0a„;o]{ zΜ9ga(˲ĤIF˒]fJ&U;UsKD >JRayKٸP(ȪmW]uG #1cyap$xZZZ^ކ3N#J94;+,]Ntj|JaAݲ,Xh4xIc|%W S*E4e,A%FB%-|Ȳ,D"R)'pG=@4NlvHQy}!'A.T#*|atoT *)dw;mv }A8-2wwD4@&d2g۶96j'܁jIRnJ8TAJuV Ga ߻ 0Q !ز,={ nT "2R鞞"b5;C2*hL(Y8p% >i˫䄎೎ET|y;f @D$-[PJuJ&έRIR*I}L_^8^fժiJeVsT\ u}$DDBbf$ɉi=5B6nRJ uf9ˍya0TcPCc#>[~9 ;!Jj 0SXM=?AFW*Ͽ&pbd$0*ƚbׯ_nSSӼbmۖeJüaϻZ UG E<T\}ವJ>@t}0]$>F% 4&"5yמ<$"DQ6 XT~%543>+2+]͞Pwt5t.r^ e)X4&%b^`p,`n޼yWs12l4^0:5,aOJh_Xò`'V(}&%AoT&8'wA*WJRʈR*7sǪ2 @?looVkkd4l6YFyP ; GNK~:*wNQD89;XnX"Rʊ9pU0UL'g;XR3GPzSX,wؑ3g"bQΨLJ Om)XDUZp>>PMX,=s.eX B  n-L>@""۶.q'[ѕ_~?ⓠ6OA2sTsA=J#XF .0]]===?7:3DD3;(@im "Z|>?s/0aBq9eYP `'U;h~ Y Œ]Bi4 T6{\NO?o}(I}6W%ȝ4@ɤ֮];֭[{3vj 3?|PT*'T2i9l~\((jXz= T@@rnC'H]TI;5 P6X4yNWXѽbŊW H556666d2,+ -'NlhF0ژ0 vQ\/#8PɎæ%|xn|X,R&QRww?V۶PNݬ!& 9>Fq<1s;#J&߿ƍ}ũ_,Kz(e)I>󽶳8K1RJ~{zzVERn&%$F[}w[ ۽4{`1<-aBDmۘ>}BA1?YjG!1%|Ue$7Z۶MbC߃G,~yuooݺ ""fAg_5&t7?w9*tnDmf =ԋ< r& 8GK(l%ѷz/uuu ,8*+W;̃# -iպZAw7 Kh_Z/ L4{ဿ hѢ .|,u{B<zq`w'_D7ra]c x!2#uމba̰Q+HX 2qLj$^'S5z4g,AIC.C>|>oʠٹ|>Rqz'+Ks`樔2" ! ]!]TzzzK,Ys}=tgɕ(:`TԤ9} 4R 75Ȃy%?r4 f0xg8i0/^PwwOVpطba)}'VX2~[U8nƍ76a̬mv2pOOOoggggGG\.׋ ̜Ci ,Qio[nzްAEKi 2bP# b  3: 7뙾q=hH$\U6Q͛7/<9䐣k|* 4rtEc 2Lcu}}}ۈR(f$a˲(`FQ6z` <~wy? m%8͟luwwo^,/s9t5?}{LOs}SW3Fuִas>)2/tDLkeGNݯ W̘"/>ZܩY(av^{wY2k֬s̙?a„Ix\6X6 R6,wض===6lذbݺuo"M9s&M:45"؟;>hR^v%Ky敥PsR\zV;z-bԧ#{ ҄ǘkJH$vm!-}@CF2֪SliuyG̓K}  %3,"˟_|gN8qZKKKk"D"wFK{{]]];;;nGy(z֭kniɖImmo IDATmS[[['5555b14MCFqL&ݼyׯ1Di>EN@k84?$O\rpw8s(1;c'w+e>JM9O^mV- Mज़?~q?M aZYu~32xS r7}QIoy?t`z1hW0DmmmC}}}C2lL&H$R^ʚ]׵b.ɤ`*r]7u$YD%3H!D,%bX0JՑQJeDdPJ`xb3v tَ*#@{JN/9(iJiO55|e; 5;|qţ-fD1>]\U#q&f;wK{/1GmEx5x>dUTV񙿋 po jWXQeK fMqgE`IwA"@JF!6ac/aDC̈Nfӗ"-vf0ZK1ss b 0a*־uwt-똕(d޲jisH %z8Y ^NeP#ZvSj/n]ʽE@g|) :Z(چ (28΃n;@PB. }_8tu,BH"s&~\ta2ko_K\UE Ojk=^iopᯢ1şK=.h!K@pVC?j6 \/ 7?0D=ßKepY%$3ifs#757^ wpdL0"вUsa-s-͜1ԍ?<DF(%Z jG˅gThk6Z% ܂!$㖵b7KxfbW_Ɍaz/j5bAE.% \6?w:cXѬN<Ȓ2gڌ7̌fP (9g`*FwMNUF$m* HC[vK!#QU\fB̒d*C= Vǰj R'IC(F E/FЌ @.9{ aeO:ˤ qyC+M 0 ! }}X6;\Q9E iZwAr&>n#:H%]o_ 4Jt^A)&J1!yK"ao?% {񄣘iB>de`,̱'D"%e?2σ A fa@QN,ȥi~R#{6 C[@/@&9iW݈E(e5]åDžK5YȏlӲ̠ i } ` 8 ~ԁG@Aq mDNP}=8O֢^ djor/`f" }DpDJ)5QO{$bďqe_?``e⮇[kC1('13WͅZC'ZX4Lf5̐Bih|>Mř"`_2Z) i % -UhT W%"Б #`du$`\ 0}0D%.,B)y3D$R(iҨOɔ>" ɨFB&q1(pXFfp?kw/[xti0-oJJ1GBOCBA4dz_}u0 w0~enxe5K1z aj1dUY ZaFJ`w8mv!T׃+X8!bDV#6| A N@ wF|Uo>Hetle<6ih$e+ Q&ѻk~W`h !# x{^8B?vpSm1g;n}x) gۧOUۭD K{)?^OzэR')1뷯|n9P"F㽹+ _pz|f˄MML   e$ } _YP,53\q/\ɓ? ">P`YA(e1tB`ժ ]}nB#?'bX2~Vr;m\mǣ/b=XjDzp56gfDQ A0 *'~EM$)rOO&cw)xvaģfvz&|?ԕ٫:2}*`[:8)qKֵ6v|hO8>59٬#<&HLva xO>Ab)BP4I .nNe"2R eFsimS0E1k0eaփ-LqDZTo|%vS7sGwXHV\ݛ,8de.CjMV ߿calT#NgY"N=9=ZFOb_?io@#v Kj)L@3-!%'isKG$zҽ(eF%KFԚN*FpXLEe/J4b͸ӑ lzdỳϙs瞻i(Xfĉ9";w/%R&gC@ mw+.n,ؗRy1k>tkJZfCuJqˁųIHBͪ֋>"`2zm 6\Y|kn!FɜG;):82):TCSd󄓭y)vv>Xb~>bAHu/;aRԨa4+YeWo󺇞 }`7Kìt7uS9un1ݼt,"cZNP]Bg;ԍ`A4co~p?1`jfvH:Ȁ)͠!H1bsy\w# ED9a1@c*ÜNp+icM+2̔P?/c/ӏť *\_C@wFiߝ^R`ߝ[{),z:6{WB D۽z/Xon]FDxR O0 ;d@H{49gG~a6l's-d-4,5[{13ίt:[Q.zv?[ Ar[zXҵ@4{0Z;j|[ԽnoqL.-+SJ} ?$'y8=:eej4H3s?JkޫSz6_qʌ(g?#t [lq1Z?L .e؛ק5Js{nSq.p—&qI !zR؏ۊ62)u!i90&MQܨ`oP8a_sTpBuFiKkg|mL`f=_~R"Z6CJܹG;voگh^\ԷPD/JS-?no<ϗ5b[ Pq7J4Nefun-ngҷסCl'ƒ!C8+Q|C_{Sȁa)e]?@51M8{r8rdW}oO[êaXթ)~05u:GڙBG7e[5<^POɜEWO1K%4ZBDֻ]> Oopr=RʽgKp[ w?6&Qך|({|W1 id{:wa槹C D~$w =ŴC}Tڗ3Լ/sRʈ]kruR5˟$̢DʭMصQ(uڥ;@fysWJr!jC57VpOz]?gF_jZ7oǛhErfslؐD45G`XjE| %%:te;nEjxhu60"IZ 1)ٴb;sB *a.U7fՕ/" 'پB@iFHf9zt_qDE[M"Nf Yt]@2<4#|dC( 1BG^VX&2v+?>_ؽv&`6ڽyaءQdzLsMgHWuh<(2"̱)hS!3-q ][8aDžךt Z\V^fo}7ŋ9dFڅ?z֘PD.en|u3bPܷ_4K){R]´lCNL.(̤f f2@ŕL y !~xf) 1q0TNh>}֎h}&!+cڔl|c"{\55W@3fT^ W!DRN3MZ&y-dmZ'@)Rc7qk݋RS5Oc أRPJ<8SpQ;qLEIENDB`ukui-screensaver/src/assets/weather/27.png0000644000175000017500000003705414205074704017473 0ustar fengfengPNG  IHDR>a IDATx}yŹ[է>2  2EQ0vQ14Q4qň 7FcD`4F#WMe`}֧]33~TU~k}]-$@`ІA}|d[nojjڽ!r`29nFK^^^] ˫.,,o?^NH8K.=r޽{ B}5MFq\.B@)Mc RZx*k>/((8(Mm@d?h֭?F>@>n$1BA)u2 0 Iu(H$P(]sss?2dȬ#G~MpΝ{ ~a)))HMM5$I2!D$*In7\.dY&B3MӠ*4M0("555@`#~.· bŊUU=#''@p݆p F^/\.a0 UU( (0 BD"PifhF[ZZhmm- ~u=XXXX# 쥗^ƍ%!nn"77deeAg0L?AQB!455&ajhFjkk(cǎɹ瞻c|+O*++o7^/|fiii'999x<  k]߫p8Z@bTUU᰼o߾u]7.zS|G}tn8qn[|RXXכ`H|k$Akk+0"(SXqMUUرc/ ? ޱ}n [>⤦o /_޵kWv^/ O>$///Tg(1D"477# !CUī(LQinihhhvޝdff&~''_KK gEI8{\.x<x^Ȳ 333я$IR I7.++2~?RRRH  . T2ϧBr׭[w-ܒ,xRIܡgnzI `YYYK%~+w^},'ѭ[7n0NsqUez F|V^^~?<ŸݻIhN$ZII`ʲɲJKKNv-r<?7JaW333ѭ[o鴏G#k 0 444QJi(byyy񺺺ӟo߾>}IfN@r,ːeG0;'[,7\dڵk],iͷ'C,N!p߂PJ---L^z飚ݺu;'#$QM<t݌$vۿ#g!$[HߏsxAL8CnBƩ0==lx0S$,==`03c`vI $c;  ׋܄gaQo)o? $Az匌x(>mڴq)֩5  ].a\!6E[յ`ڄ~1^QdyakFO'k)q,vb|>b˹񲲲}EW_}8 B)Mw\(LUU$t%@':Eb:8$9<4d{!/Il_; 1:1 C,X̶m߿߲?ЙpQJI,F-0- Jp%1 ۝Xa|'n'sDOvY@ 1M$MӴ`0;}'܅o9eY ;k=hРK~*AxvZ`=tQ:v`c.79"DHv'KhmD$iСCZn]$ !cƌytԨQt޽  )))R  bY]Δ=\#H&qΩ-%cb|[NE322K,q,) nOwN222}&D,'s}4VNJ։e˖qX@t677_A)%%}܄x<fk&'l `Db:`mI${Q+w -lRԴkR#rss>ϝRs&GV98DibEƈE3X%=8~0 Bq\M6Ƒ᠄o B8H'xbn8,77Wz6dBa!k9H9JzGսG2@8*$8+H3gwƌ1r0p1cƌ{7nLGƐ!CHjj*!_7)g3"0'p9Q?{/JUppg"(aR/ n֭OFCGy睽EУG#tȐ!,++7q91/uH\#pj ۳?kx/_EQ(DUU A} Èbx<;-x8޹ˮj`կ_?ֳgOkӻ'x=C6Ķ8zlbG%hcN@,Z4 7`3+Z(illD,-..74(:Itڵo ς ҥ JKKI϶'KD2Dd?{?clUѴq gDamm-"ȦѣG=r%MT0JKKNIIn[RAAAs|'_pd 8 :s7'V*X|C{c;hFmAE!n|>- \hٳgj„ 8AQ_Aͺ7)##effrul-gXi,ԾQ[t98yȁ@GŘ;Ȳ,k@TTT<#oAG wAjjj<EﴼKj;8M8|Nz쿵DSgxmphC:D\P?^QQ߳g&L0&/K0GxM_wJ88av%ũdB[}wm!8\.躞Hn"2e}oݺ7|sq^185rvv@|>dx<~~[V{/AxitG LH[@kwru"IfWM6XjWgye=dfddtz wʘzJ޵&1 "v1(VmtIVM3---Z޽= .\/О7FPJiV H<>٤r)t#&IE-` =;:ƔLӉ`H\sov3/g=쳷”(c,r<ib(ì ow{_ve?-'<9999^W驪vXff*b@<'^0Ɖi'{;%ECHx[Lc^xbAG'I%_\nOppĹ9ڭ6n 1X,Vy-}X<H䰼=/aB9z~[&޾S]նe쪿=TBa{^o0E@ /bѣJh4,@ d3I2m@T⅋/~'ڃ-~בHv ڙ;bu'Y1B4UU)0[3FRv޽f͚5/袢P(dȲ, ǯ8PޮSK?o˞̀N Ѯ d-NMCHvcɘ. BP 6@[0y޼_u.sL4"ގeG}{g1mqf5JiRs7:I+ؙ'̉4u'tl20c`Hu )(Ƙ@Jkkk],.---MB:O\A{6^,x{귫b!QĶ۳Ng.=iZ#X,q.\"IdF mr pߵkN{Z^rE 99av*p\>h1.nnn-ndA'@%s1;(Oo( D"㤾ommm, ӄ;3mk1x[lvzëXu]'0L0/D/2_4A%xL 23m;CNE3AnH4eak^* 0\8G7-aӦMBPe L UUs7A¾wrxܩ]dfo ' m}'۵K;s4dKEaha]UU_S72bHRJ% yvܹe˖-=ONzzz!X3.|X,&+!v5l`L{*NuN6)唬dmFI(2 6l͞=/`n=n ۠Z@"x^z}EEE~ϗv)!hfFY4eVB;X|礞xaBb(J(w,v3L8Ev&P|ܱXYXLzީZb5&Dch(!Z!B@]]]պu֯^lΝM (a0(:5 Au]hXo!3=GO };lzMnN'/L|'e@p)D"E'y^D(KS@*GqphM {w嗒$I)iii)))@ pۈ>]vuB!a0BG 8>)"s&PGEI 4x[',hޟݙ.5c)%---:׊+ZfϞ=23gc) hYzfVk$fuS.B̵뱆 `Ȟ={0aUU5]%ܒ'[InΝ=|@0'~f3˳_UU*L@ZjU駟~988D29Ӊ7 0d  CAB{͚5K?`РA[ZZt  S`Wvj.mτCj=G0~3h{yi:'f^DUU~/J<,$(#K . /B; !Rq`\v=}5Npa2^p CɣwygNJJ魭:cL&|O;s 35F"$I9,'GN biaY=GppSٳg͛￿@5:@!- "?+\ pMw8?UUu۶mrrrzfggqRD`.qJ''ɄaB!nHb1&.@Ykv{/³%Il}饗>.//oRUC)ID5|%ĺ3;07 HTTT(֗^z/>U< ڠMݢ$$)0|0%g uKxK5j#F8հn \ -uL {FTBؔfќ$QɆ,˰h GfI<ǰ@K/_^kiunݺu-((螗 Gejb1|wyyyE4+C7hRbF6hS+C97!/`="HcԒTRb@?r  P 9s kȾ!qڒ8Rim?i1I;v|l,ˆU{O|>_bk; p¸~Cuu{XxBq+Jb.̥R5viU+!ey1(-wQtn?bY$ck5TuL `I***sg +))镝ጁYx-BlV)WױX uuu۷_~Muuu$I={-)))ٳgϜ7f,3I@N{˗/駟.mhh೜4Ϲ_jB4} N><,2v. ϭ7CD7cu.C`8cL1 S >mQg:҇~8?0РgffJ<;_ii`/~{ɺU!"$?D v-q=ҸŴ#|a tMwȲ{Wr11.:E}/Y\__%\3f̘;u)i\1Ǚ,D4rss#k&0K4vLi H8f2=wyg/ǣ4M[4pyBw13++kbuuOKKK_{ߝ8qUq^ |8 O9s|zy m2YF8,t֬Y_3(gʔ)/3}>_ /Pةab)ZB%[C󱉅*uC'fDTuQ5ax?ɓ'1%%Žo>ddd Nްa-`pM]](8pɓٱcG,;aYDȃs… ͛7ǯ/_R]]mTUUl߾}(++ceeegO@O"w2HًYZ-YSjYYYsyys+**&EXee%kjjb165ڳg G;ux?ژ4i/n_͕222Lu_^[[SPHkjjrs=#Nz_^ΰ;tĸ)3Ƴc<5*@99|\❲k Hnn^z;nr\ -ZV=jԨM0 /G.]\ƍhcY{L {w677WX7|ף>ziMMb&Jf͚eIIIV$aŊt⯨Ս.Q2Obb׿رwRSS7xcڐ!Ck׮wxo \믿~(tw:kNB~cƌC]֣GZ]]*ׇ8޽{狏90%frda (((O>{=2?e˖ʉ'^3f̘̤{={3g^={`PڻwUUg%M@k捲2cܹ;?6lΙ3`>}^p\:u͛7 !BM) Q@mc̰Y8f1[Huuz V3ؾ}H$~-:t+\hZVQQ ʤ g'O^o>ֽ{yw,;v < c$sN^NN=?iiiQ׭[WsW;w &̼7n\Qss3+,,̿/MKKì񌌌]wm=У\sV2%q.+C4!$1@SR6 @!^:M8cX [?Dׯ~X ! 0 gՖ+0hmm͛ujjw݄߷ QYY~Yf=Eie)8b Nc&0+XyhɑMMMy6lU߾}uҥ',&Pp}ٗ>-_u 7|[nm۷oJFFb:ysy Ç5jTرcg._|U8eY1 \jܝ \ޒ$$Bȥ0DWe$]@)C$e˦8p\r[}urIǰf͚'ǖ.]TC㎅1(~;xhf<#k?ͬFWE{Woܸ1G '=$`,d!@|]p\gQJ/r\^oc%5557nxUUU_{ PQQ񡪪/+ٳg[zf͚Z~M6_g1qF={}=`w 6>V3ĉ(755pcl$|?0r] S 8=$ٺuCvbk֬^\M[hx:m`Z( ɓW?766{MzW\1g?G7nڵkWϭ[nݺ] sM!C~]׍ٳg@!b+?s3[&zHt%^PJ/$i0,X,Ny)S|޽{Ν;h4n喅{gРFt`gd0+ 4nРAEoʔ)w-?yz̘1[R駟4hm{i3fxQei!0zqƍX끙8V"I7̍]l0!#F6gΜr0?|}JJJ믿~󫯾h4#˅h4 ×;mTI*++{BEVVBq5\t'---6|G緿oB(lʕFJ (..~H$$iUڵkZ s@:0!~Xdʕ_.z𫯾> 7V}daaa 7OUVJ_z#P3{fXBeX 6}wqԩS?WUU {XL3 CWU;GL0nݺ] }ذakfΜ93+(Rz!5_^~UUU(l $IzR:fd8tPmٲ幪iǏ۳gn{s΋vq3fL9Nݾ}{駟,; _`kii1~_|6.L\/[re c}U{Bx#rJpJ np6x p1@ȑ#߿AUUңG,0D r7o^v}_}m߾=x>ܿUH*?>1 q֬Y_sR:t7'$_n? CZG0UPJ#uʉNctPr."tc-ZhϺuclΜ9  /0 cĉŏ566uDD,:nܸc$IJlj|00ٔsp; 0r9B&PJov\WH)t*8n(y֊ܯ_EEE۶mK.^y{.h4 0ʕ+[/>3x㍃b?+V;vnjs6n8ݑy!(Hn; 0I7mYs;rz^ #J[&M.n ܬkD"e={hk׮mbE-..@^2eʔ `zhf޽sNyQ00npIs8T=N}D믿>,㏿*Ps7"cm۶3dY~n[FX,fDQ#wtM3MMM=Kc 4A}3c} w?sMÇSkk sϝd!dg?{7ؕ{̝DRz?̲ׯWYYx|Z0$˿v\Y1*AUU躾ToҰ$I8O~=z{[׭[7:ÇzoY lP233i:c̳p55Mz~t~IGBI3 #rMn;ϸ[>h\si_OgϞ9s̤6b\.Q$P]`ޣؠ~oYN- B E4={.V?^:ӥe˖͚5kѣ/0 Cҽ]K,󧍍u3 UۮWRJYFinD^hccc!}%B2c^a3f̰kϔ)SjllgYXvS=UJe9zY\,BHoJi1LX`b322Bc־k]X˲`$%Zoc8i0p ߝ-:LY'G߁<@!c;`n7X8wgQtJЩHFy$"~o_ru/g2`' @Z !~,{PIENDB`ukui-screensaver/src/assets/weather/28.png0000644000175000017500000004645514205074704017501 0ustar fengfengPNG  IHDR>a IDATxy|?>gfO a&,ʢH]VXWV },bˣP**AJ@%la K͝s~ܙ0$}^y]f9s>r>s$@2P @T_$m7FqmwYvuu巷B1X 7746~j0eo_|`DӴ|Ν79rr]\.x<\.Ȳ A8!QJt](u-''g٨Qvmzp»Ted 0B Y!"$I"BL皦AUUh]9QEY5a„]z饫6·v K,eee2YprzJ<N'DQXTT$nt:ijj*/--%^1PJaigAUU #%UU潈K01ϊ$F4PJcN>33 LjJ+mPdڴiFx4+n^ZZJҠiAH0z:ԿTMڊ`0hU "YGAp7b13D4AUUaapΕ1c+**j6+p6@s9ӧv5'8N\3tPv `g>2mmmEWWTUE4MxA "!>@$I `DQ(­i UUP(@ Ji9ĉ_,++54M{{II<s9Z>DGGb("bt]?$%HHMM4oaZB0:i<~H$PVV{tAl`?k,kiiiBJJ F8ITV`~hmmmF0@~(e#ldeeAD@ɤ̍Y[.DQb1Ť6Jۍx(@(\.SYYӧ-]tZtH< e<''gtaaXY$gffS]*2%lg7sh2_eB pM0nj5XN̡iBͤF(&Ij[[[>K7"OKK;dp眘C0םL t`ɲ  ӉZ=3D5&s ;0!8^;N)=== Goδ^$Isu]G{{{BmZ=lS][Ur20؇79㜛EŽt3S9F?]KYb,1\.S#(v}ׇ~k} N @!H!RUU%~ߚҕ fGdk88*)))k̡Ձ14?[d-|f=Ƙ'ڵkСC[-g" 4\n0jp_[%b8?xiK2N,'&qaT]cs.D4iizsΝ[@rss/_v^/qp8e9nU5@)MdivɱkdetwX.eo7c@Gbt/I&_zYJJx5.vg>\`T&v|[NE対Jnzt^PP|ϗNB&aV_*'+9&Y&NTUEVVપWcX4pZt xMMMW^WHII %%%$'''Gbf~7͂9\3mrw t؇oVbߓ]dOj5Bb(=%%]UUU+Ztࠔ.u}bNNNr(++À8yUV*YZcnx;OU{L6ڟՖXb:1!DE᠀T `Oj(B1CdvH]*dD%DսGw&5hf!˕tkI}7/RG#&Ϛv8| Km۶ᐲ0j(@9&N~&xvwHdJF~2jfR(BBf$+BdP((^޼ |„ kaY?3:j(I8s1:f?BrA2k‰D{9 fҜ6WEኢUUy,cHu BFp8ۋ^tE/**2I`ĉM2:Jz!Cy޽7óU8fֲLOX'*'{=v-LXV5Mfp]׹1Z"@4m0` ~"8CD@}я~^eeemw)1޼H޹}`gzw?{=+cW}=Ƒ;lnnF8~%3 N4L𲲲SRR,˪ ۝8Sa7N}Xeu>̙%S=OŇ9x`Y҂+W\`oq 8Q0BHȑ#1ބtA$uzbzdd5ӨxBޝ9꩝|b2hy$h$IxHMMszKN}Ȑ!}>_,˚233c}O69Oj'KI֩N47ɪ^CBUCYMmnz Mp8 СCc555X`vm=8/z0w\̩O&eiyKJC;Ⱥ!Tz1tDQ ,D$.Iꒊc;w|߮_)8'js.r"fgw !bh&V X>35njN' LHO@IՉ RJ:;;šC۷oiÆ ߜ;p@Ñg80t)bqo}V &(>x"9G؞dͬ)i Xb\ycfzf̘QR O@)9J[[[`9)dNlځ& 4H b5nv`&p2I2NT~oH0$Is$ID._r :TAxIڣ$*vUnJ}Y5j?9@axћfI&vMc>1RȲ̇ v~|=z! Sn7u+B<qg2&IiR+f-;ZFlw=&~]OfZGw%n:9;;`Wt8p`WSSS4##a$1 y i'v[;*f<@H̲$`Wf' ӓ|[{kLp}A)%xxmxhPUUUUIIɨh4c qn } "'VrMӈu9ۿ[fY&j{n3dm־05i;KFis?'tlr󶶶# =7OQ:8)]]]h4l!f =|Qvošl(k{g\vd?"Fz,˖-[Y__ c,Ez Lq߿t3hРlEQtX 3ߪ O7; .7o7ۓMw|wdY쎡vؙQ6a+b6oU yq=A0 @%rQ,V]׉nw8 )V2jc7II`G ;d$V3LݐH$cdG.]W1Jr\ї88:A۷o~$h4ʌ4%TU%֝-ܓdΞOnefo Z' +{Rɘo.uCF{fj(<P(*Kify@:O$ZD) VUUUq8iiib4x.GQ27dN] A`{Ow}ak$DF']yݕim)@HA#[n .X]׃Ji5"G6nܸ]uJeBi& #D"(z1%SvOxaBaURoU4u $@7F}=D"¼y;pWF!BHsi8FݜB(B0A!hmm=PYYeƍkkkLQ1`QTu1:D"x} u%@nRo]i$ g2o-;O$AOf!,4p"{>裿"> SJÆ88I J)Ut]" !Nnݺu )ii>xܢ(JZVVVܷo_BaqBG Z=pcN=]ZEQ4̲TUEٝY+ivvfaJI k׮ ,Xoc6sĐM t]!UJhB8A02 G7XC&knUUt]8ǖDy2ޔ|b^Xݻ~f3ngy\UUbPaÆ>H$rpbTBpsVbFDQ@@ Άs.qzv0{MBM6}5t@  Hj3תRڃL8{0cXmsHu]2f^DUUs/L g+(  Gf09u]XbEӼy^j`L^=Bפ 5 vU߰u͌u@IIxHQKZo&'"ָPMΤ @3iҤk.±>Rf, :&`=XcUaSbdnm2]j0I㍦pp\p\̪-$`n 5kzu333sfeee^p$QMh4vtt몫k"H3'v:(XqGp2 #|x^C[׺k+Nw;钹<!f?tҤIKKKx^̘oHAmI)4kBV4yMkp\,syI{O\.Wbk;pMѬ0!s?^jժb(S#)cXL5hFDBhxQaĥr"8'W_ M-Tt2{8L)U9"j3 x(:cL7:Cqb X ֬YSjժ:::!cFwpe#'*Q߇BB7I1QD\ !Q IDAT\=I 缷jKlpJ}}K+.8\4$@ f0,RJ=1n!@7!)s@|>_AJ<_~).+ښ) KpԱ45H/%++kC=￿v[ !ys̐ !⎠8RQ}ٹYiv$ RcXLD"J0 uĩO% .!P-uvҽ^ouI$麮uuu@g{{{(~ĥSj3GG&SUS3&G[5%?{Np(wdӽ}cpHC2+z{Wvwy#;t]ojkf"O<4556558:0 >IMLP+q D9 pn:!p~ C6C60*@q%v 9)<sʛmc/'ee¢jnkV&:% TWW?F*\f̘Xeeӧeɒ%oy7u! 0̈QFѪ1q"X3 n0݌Uh!J {M8eddZ Ѝ f(;8(o4,v Gq7m(-bt}3o+[^{;H׺HX x:8gQKM򶷷z1D"?ݴi\1.''-[TF"PJ6QaN!ڢl2c8!<@H1֋& Oؽ{Q URUM+Q~ě2ẩ=p?WQ JQ8QO <)̛HP ib HմȎo6'EzB$}yͩ"77wfuul}?*˲1A)us Gcc IN24O0_yVMy`8 o(V ;zi M;?g}#p{/ k rp+Q6!$F)qƘ ^'|z*@~h!@XT@k]+撒qhtW_}k7pù]tW\q؊nQF]c=2v17o-psͨZGr]w^?$ MGV~6`z)z–s @V7='ImAb#Ua(1BHs *J) nsH鿜2;="9{uI.$;󖊊?O׷Huuu§~gҤIp̘C-^r&LpݺuxTTTfY iEv]=':`N8% ܊xG 81 p moͥSFD#AvG o^N(ء"a" R\~qiS"t+K6mz#\hmmmp8;tP .ȫwuuiǵjժ}o?`ӓO>??OxС:y<ܚؓlmՖ?o * \tJD 65gQq]'Kv!D Vr=E1= ,KU׬Y3j̙o.IOOϽ?+..8~Dgձ@x&MoĈi󈪪/Kwq~ii\SS綴cǎ??/ 80{Ƀkkkq(]2"Bg@qw9eRyssǜ?ڝ.^̦)S6k; u \R8:!D#pMZ_z2bh:KWggg?vQ_$閛nnh]]7g33Jgۿ-[~&OMXQQm'xp8!C_|^qeO:{ǫW?y\oJJE)++sUTTt_x^[g͚5q̘1۵kW ]w8oJɀRZzc)J!ԧOŇ/c}Nlݺ?c]9998?(>!) F`2۷!TAAAF~~~bqcڦMj:kiii8qPM;m-  طoozݏ='_}sȱX_}/7557oW\Leeg(jVR n`w#B˞BT^~!9%%媝;wNt:#TUI))'ۍ춚VWW7x׮]gggHOO' =zt{cccgkk묔<uu;UVhuvdᄏ+##{Ι3vYqaC !t]g)))Œ3>MIIAyyz?rܑ}l>^6S;^~jjjؓO>7"ph_-FXLC;pKnNⳍ}FgٷH{<A&I@ gϞM (̤%D[#F 455@wss>s.OMMeYؿѣGw:Xnݮoq^)??wyZZZԁ:ͬ#A$Ip:.ϟ_3cl-Тz-Z7xoc_1_( 4TJG36~p锲[䧩JSӝ [Y@y<Oqq1;rH.IY~;,4hĬqae_~?ի')#yhw͝;wc,ww@˅Νtƍ[u]7?Diի^{U[ls=:|Ammm^aԤn;x^G!A)3"fv?9q΃+<F)u}7cZh4ڠ3o:&:e_,[3gLUt:?]ƍ+&IDI(~敕eegg|ͺlQs 2gΜ?l޼jхRMMMۃ>#GoW/yR \={﫪^o .nٲ%m۶oVsApȲ,ހ+8Ã|7;(͒$UfQc8.ĝYo^ yioA[] d͚5X,n71A {nذ!y-5 ǐin;%k/¬ ߋ/7XAI7=QsD3(5Gѩ]|7>!##֥N3roFFFιkkp}2I2&]Y>Prܺjb/*u]7'---k׮]wmɓ'g466{ ]tEi< Yf-YxWU1V +WDQLg aC)\fz@ ՜Xz"A(iT{9iq[48d[?'B'vttd| [nQqq1 ͢(FC6k`8e9NaR1y_[ nB<"~(NgYfffZYY766>=(׿U%%%dCAh!ii'b81BHPP2!B)mB\xT Rش@ &D^|_dddpÇ-##Ɖ NA.TP"sB2G]c-esYvv6/s9眓SYYׯ?녅۷7b1.Cd}&"11+Hi4ǯt] x} @u]w!6 41۽{vY7%%xСƍgMpXݿNAR92駟~߼4)'ΑwTۀH |c`k۶myww>y䑻.K/IM PJ2Wɞ߃n(Yƺ04W9'J0'B.4}v1*//OmkkS6lذGDjSm):!l]׋W90nLNEhA]p}?2BBψ98yҥK_x߿iSO=ƍ>={_h6N,(];̷JTύ|8cϞ=_(--}>DLӴ(~ιs3ҍ̕^GhVUՏ8d&833۶mLCgN%I)9/朧 :z!uuuu0ӹ4 c$@]]]i]]SCܽUUUzI{6;;;2eȑpb~梔f22gJQ)!añuK5 |޽W)2ry[ZZ?C) u}؈# -pv.X|{xt]|7g G%f,iib|(B^g"ڪ-eee E9#ZWW~H?:euh#tc*Z3Ql&#33󎦦شiHo޼˗p8dT"] 6J:HiJA ޞSQQ1q,] 07nƘ1Q 0aBahټ2&ć{l l\pO>b:;;]]]Æ ^^^>)33Sg=u:VAb)whsGxuuu%%%7ڵkG]UZZ:wީ,)) w5jTyydYnΝm۶Ғ{#f fzc>hG߾}|嗏 4={hiiiwmڴLII~u+V>qƟ (TTUmN:QkA.]vժ(߿ҦM~L 8`ܸqw9rȑ#3 .|F1>G)pνbŊ[<ϢAFg"Mnj{Ś5L_vۈzg-Z^yy˗/?PRRoBG4MKKKܸq?|IZZڋjN]u]4mt]ߏLXN !۷oSO=5kҤI?tѢEJ~Wy睜6 IDATwܹPVV-)))80uԻnjs3!$ƌ?D"+ $ 1ՄI??3Nwg{Lc]@@饗*EEEkG}?x@JJ6_B֕'r\w߳+W<9p5j2Y/~g̘n~~MMMM|ժU/i7 Q= .lʵs"X|/`0kkkÇcCi7oVvikk~i;S#?p'e7L4=rh/eP@ }GTWW-\pٳ3O?uo*--M3fеk.Aqqׯq[}:*w~kG@H;̹u~5G xIF>#?XL2eА!Cٳ'#lذ/llnn\1cƔ?;@?e]QVnj}Bgf[޽{/6mgG170133fs5Mӫk׮G"9{U|y˖-ܬO6q}o+;;[ڱcǾk3g|]Qo.=? :ҳHARpzyu9p7+***׬Y󳚚ƍGW?~|n~~o߾'|pcǎUF)22(ǥ+tglх1J^q0#BW>&e˖U>N6s.䒬niT~~~Q(KNSk)lݺ?ڽ{7UUUq p?m%-Kq$;KW,Ei_^x%EEECo޶bŊ /pՊ(455չs΀(nxaŕgϾtZjKxeti/C?ڃvq}۷.D;v566}>ݩp]b޲EO'&,# sbR I|KȩE-_'K9Bu޷UuM;^pcxL<= ,̅˲l[u]/4MӸx♃\~}dfgg+`0{'&&|$89>핕'nƬW%2 A!& !sV8d-IRP$ d`)K$YY13 qqMbVVݻ>}P(LZZZcLeuJ+$mZB*rg2a 2vqBHs9g1%H:ԉ׽KG@x0=tPJ=?z-TUui6m|ҥ+**.u[CR tl8#XF%zثieY5 ca IDATx}wřIAD6B$ه|&q |> c,`$Q" @BVJMٝ݉?kT٠y鮪 $@sQ@V| ~:[6D"Q[j9&H$f_ccc~~~ (P0k֬9uH&Smۮ#說Jib98pX h)--0q3g|eر)>B>lP/_~֭[qP(H$P(]ס( '0JI 1qt:d2 qbΝ_o>LW/{73N***Bqq1 SB(TQUUi!"$۶ ˲`6,G0 %Hdy~zv7 gݺu.]zeYVUU!0]יp FQRRB" TUcpe0 d2R)L&NamٶMhww7W~1C} g_ ?͵k;a+ @3f0THˇ,@xi¶C E q9g1d˷qMqq]磌k:uj+C?: /8[Ԥa iII 9s&F`R:2i3`YbǁiòAB܋iF?0mRj֊MMMgΜz̙R3[GJ+kP+|mܹgF";pϜ9q(g);~_0նm Lj>@a*283ƸdfmۊeYHHeeetIO~455uŪi%(6iҤkG]\\AL:Ԉm^{53De! 3^Q E 7BDiZB0\m5,KMR{ҤIs9Κ5ki8 B_W7O:u|8fHDäIp}}}0MlLiqA4-DD"BII ( 2ZN$H&\ٶͳ٬Ǒdf͚?0@X`&LnzXuT)**Œ3H WMW,b٬`l;秩 ] Bee%E'27n[S"@6iܲ,4M-@yK/YOH a+FB~?'` ;{@ `0MPTTcǢ<_(R EQ0濋k5MC8FQQD"DUU RRCE޸q_} /9- cP&O;v`0H" BT(->@ 4-?vPZZ: ? \p\5MC$!%%%bZ |/_4{K0+..V( u= Cխ?Un8O #IB|{݌1(,>Sܸqc>$ё /]tm{Cc(+**R"u{%Ly59Re|NwACF{.R `Yʬh4SMfAk&l d F`q$wRp ]l7"Cw-p$PJ93 Bzyy9f͚Ǔ@ p7CSCױ2c߲{?`}V#UU7o^CA!B8(x**>w\TWWBȠ޵P$LH%}[hQ3b B5]]]/첒{,x}eq0S(̴hPeӦM7VYYsbBMSB?@GΏt51)0 R)R)a15J1JiG4QWWf+͛QGߘl{ƍC)..sXypq^UH#+C\[#yWosDR _+ap0eY4M:]T*l6@ O}S IJA59g.)v4UM'L@8Czry/ҳTQ\ @Mz=^- ImsiA8w%ɐ>dsu F ֞|p8̣(3f f͚E eDyB" 1^\w F^y`d`'ʦMA_=N7/XGA4LYf}naeرykN `)Apa y<@v~}TC9ވ fwmHڂAt]PN&'ZjEwލ#H!5s̹)eee:P/_gkF ~/dj!(B@D?UU8N>I:4kF6es֭={ꪇpHMVYYy;B! B4Ne Z@OL `ʄ  NER߯N>ټy}ׯNۂQf@@yYYY`0H7T̲C$_~HV0Pe0Qwq$9G ء<,0jJrs:00`O<9rQycVD"1G̷/ԩB u$Կ!Dϑc6tr?x*w8Dߋ.pabI(sUU5 b}O>D&O*~R~|74\;F QL (J/>&tܸql?8o}h8(sBHb=U:6z. NUX^={j1c c͛7aڴi׌^D۫7sd~*P~`Ѩ[ن(}^?nwHU~<!y  PD"`/0y,3J%_R_C%:C?qyq_u4~M~Y-UH㧟~\BL @s#p9;dBR%wߐ܁^2&^Mr݅`?I%?? "vN4(ٳg/ =1DP*՛5Y\HwYr&?g߅4{5xv1Rg̘q|DCED:={lK80 D8?IxyTfr 1P t=޺&{PfOu~9UUU0^2wm]]];i`08qtzI>ey|@Y{( @ ^u,&xA0RfNS^iΡ4RH @9-ͶoٲeԩSdYn&MӃ޼|){y3~^oYo~jXN^U; }Ci/ 39G8h6`a@anu֭:s*L&]H$BL0O2=3f@V˒/~?C-IVN&?LtyJN ,r!feY0~ȥqΙ[Hў={6lذaυ^ؔL&i{΋ ߽*;}JV^ey#ہ^0z5Ehɮ\xӥ@2LuB !8<̛,YYf}o̘1PU\+mD^E {o9e f5JiA_k S̓Gi9L:h69csy,Eǡy*49(J$=lr֬Y!`8/Ox;H{տwcy"Qr~f. a8r#l6똦I-[UEQXCL:cLG:!${]`pĉ pc@~ݛe 勎srsvCtoX^{Lj>fa3;{")iWV@`QJ q2/ !A$b=o(JQIIIiYYYyiiiiQQQ$D6bt֬YSjkkuB 1 >3WELjNɛ{(ԁ?bF> 9!fYEά pyWy=~yw6t "X1G0 s L'w@1@Jn9\^#.`@7lgΞ=~``qA7^eR:;{1d+r~[9-"eUN+qPU(0 9'(+W%]{9tg-iGOEn9gcۭʑF s.G8{DKJǶeYȩ8 q8A-Jl۶m[UUՄ4W]/qrS2X8ń6 tK,{ɒ%V^FIbw~)cm;iZ. W*!Du,4r' FZx{s8i̩L  PV_~zZ?=d{d:ޏj^[g_S&OεW!?@9sB4A8RUU+**j****J#H45MS(1LӴ2L&bX߁u>9Mip)*pqiiiY4-F!M4qD"GɚmU5:Zy @kCr+I(GH~:~i~ 5556J淮K77۶z̙=k_o"?v-{) g{/M%i< '!T79q0#rz_[(+]y?u7|kW䓊6t.z_w߷ @[Ty8rٽ4rN!r`5b:聀޻w~-.)9D"a  Es+V_lfҧDџHju֩s˗Ϙ`7J p\&YFBTBmW_]-^o 8\wUc_-@|j-K.Z"gºjjjֵz:z{~WZQYN(n+++ 3tt46o3^wMhjsh+$t&= WmՓhq14 ƏI*nҶewO_rv]}]y2Lwvl|UO=Lݚ"$ƞ.L4H)X2jK\"]]~=onI#Yb3|eP7e\SYIIS,Kʕ &9!oB5`SJi*Uju}=Z˲PzI&{Vk,s?MykW}'OflS)OWǟ~ogNUxgg.<}DZo sw,CH)(q,B)UUUd2XviѢ%\RG qc˖-: յS__~?9;HPoPVaÝOi ][3o>9, mxWӗ]t.^0<;oƞ2Y3hk[ۦdY{?g$r1+ȍjߠ|>\:@Ң" $D4RQQɳٌ#ՕU8<c^:}붭7s޾8ql6TW:)gޚ`ukoo׌#{QM e+7pCk…0Ě:Q]&M F% Sz ն?H$5cjX(m9Rm4PhOqu/Ҳ2G{wL`[.( `'TҝM ۶w466nܻwP/\ "/8MYbי` ȷo6 2"4sN4%fL R,鴶q{3rCKqx`:'ljb&۵w Aap,FM$'0z&OnssPal:_iso~셛tRiWE_<_A*?n?ɪ_uWgϛ]\\y/^${IX>{y_k6ϙ1H$$ ҟH}GwX"h 6777J\|'N7H4MUܙӱrݛ7?zRYS_;39mg2gsg9tp㊢\Ҧ7׭!pGJ;"hnLuտqck~k x${@$)ɤொ"/o޾:e 6M`OZA$p^gvʜgH&1NIQ4WxJh$uL8 ~H(9?ZSc7rt]M܏O"Frڵ_l)Iuax/{ĶꪪXwOj4|c̩SqG+ 7>4K,\0#glk#)4w}q%/.4LՖoF[]wU~wOoQ4Z `Y*>`(dv I B?YёfGS6i4iDBHwΝhkxk +W=ftk~~AnhU|NSimP]#inpH%s׾<;kIfmm ֡q{{윻bϽnjF8t$<<͞ޮ޽px6M{IhMuv<1K/,])o8b3g*Cn;qg;Uٹ}f|^ieUu2{;:_}z1ͱXl$Q=O,YdLEl6F֗oo)oVS,߯iF%tz޿M{l o|5߅3(%|tw74[73xx\S{q ?=Wzk|+Bҙ4ּS[7]z $T*H$1`Dꁠ3?djKJ];7ߵs#BŠp0\/we/]4drtUϞ ;w6)[vljB9slbaûș[.?c漢TUTUREQqغukaDt,5cOU%I-@ @ҩU]Yzzx.zw kz"A0_y-cF+mˊ`3>cnәxüD#pNEdݽpfyG]-w\}ƙs+J::6[YfiMY.e`=F6tX*TSc&t.}j R;[_Zp_NR16wC?pM@[߼ciYMc;/|'Op #8? |70ۨ(Je1:8Fʿ:wlݶ|˪8eĻ:9gkklA1;E{= $I%Ro_G$rőᯒm;N!$M+kۻ%T}pad"gfgYRjzIV*⮽1r3 cއǒyw9_n;N7eކa4mڵkFQ Bz?)MMFbZX_?R[zsFC"SLJH1w]qڶ=u]o_|zWϞ6UUUm9uon>c@%Rֶ|8f&}[^Yui3]61ʆwmw=z×zh4ӥc yݣ.g.< D^z_GpfhcO?+_,SUUMź)!iEӴ5'vePpǰ,5s?~Ï'pꚚ'~UUmj9??e.ulrFiii)@jX u]5՝G|}ݴ٧ 95̦qSUVTDJI"Aw{XW3T7#|QWS^z NPE ðLjVP^ZRQ9{Ͽpnyyy(Lf^^b^Fv҉1a`i]USU]J R0_UpAT[eo`(ͤS 3M*/(щpN}ev]>\ܱ lV1MI&N,{z|E֯ nUUd{cf6 !qv8O>ZtBi78f˯_Vo{}sisfoÑ%Zrwn̄4м{衇-@۶pr+l6>*Ds?%ͭ(eر{ϥO>tSpٶ`0T}OjBx[KD<v: /psZ|y;lˇJ'(>Nϭ2 qNՍ1[*+־?o1~B3ӽ=JGlŊ?vHt"i@%S) hQQlD:3Upr8/Bg#{&m모-t:s Uh<!_{1 ,˚,Ȫ# RPgNZ$cМ~?=Rd2;&~$G&cȲ|bvtm{zd ƈf>p@f{CORj&60 3}v P0Xef4AH2L&?ri֏0`j3Ls_J&#cpW~zy&:͛7U1}Lt% IENDB`ukui-screensaver/src/assets/weather/52.png0000644000175000017500000004035414205074704017466 0ustar fengfengPNG  IHDR>a IDATxyGU';.$= $@XeSP4"Ό#* "QYA @Y: !$ݝN{ݞ:Uso:It&<}}z,UB B@_] ^* ~QL} "H =*ȸj<;Wx~S J }h_PrC1@/7ɍh|!9- iOuʾ@(>(+'bd^R_@ *r3TQq"rMbIL' Z 2BV#)"έ|; $0@D@"!JQ۵g@Q7AB$4a/<0DA(EB23[-ݹ8gǰvmgb BqP"! 5 b}J 2H#4@SYs5UݷR֭ 8Bm; [23kbcD+mi7lִsc9*/XxB_"=w>6Q014Aܹ`sǯ彋C89@>ѭ^}c:JÅ!"b(vUkWn;}=w,*\Vޱq˪C8 1 P){@! (L@BtjB+k#CP0'眶n|V|mtҹbka0YHDPVu]g^|ạ>˶+tEY1 *rD G>!HvDQ{ $"|#&5nE MfI!Qx(h|! MBMRI! H }iN'zCyQbĚU-?ozZ7?گ8lCxHM~!-NK1"YbENtB4Kr'ɹGˆ(Hdǘ =hmmVY~L@9yz Nd*e7}Se2d$!Đ||'ל|ϏuȇG~ӷ3OٷW>E'}k#|Ug^uAN^7,%۔'N, ?z)"D0u!oߺ-VIMDzm{_ړ/xGVO_*[6̈|tWx|7?g\ppP|[/|3O:M*c9Dap O}gFx腈IR,Iw@MAFA>T$!` 1`фKp (0 QMaa@J'v]+2rZE y!- .6︢QfKD&t.B@UJq㛞t.yS^c?3IHu|fۏ{[Ib+'zz1u#g|J3#C0 By$/O#HnD ` ! T! ( $ 1G(&by4(MȑAJ\\,DD4 "04?O2"-H QڭB޼7Ϳ}W]Wh.v^NDӨjPAI~5gKw/|O~}d|/7ΗN~™?x G(+'MEG|W7n_Z¹DTsC ڥ h*e2!⏀b2 !F{t}DGDJj7XD"BExED 7Xc+9xU5tKU9BBD V%JNg`$ [O~ΖWm7>n;PtA!Fb@k>R]9 Q~Fx%2n| /;ce\Z^nfcSJf"16 r3eQ(Ոa;w_ގ9̟KF &0EҐ/]p Z//M&)-( "1{ݹ]YSv NffKj]PNQD5*Er- Sk/;;o?OgJ(bb`kۥK~?KB̃Ԧ|pIh R E@  A1, y^  Ĝ-K]5*k}?璉exI` )=ݻ/Nk ǟvi_U!H1bhF(JSG~>77~Krtڅ13x3mq[C gNx↯{ & b9sSLmI(_s_ lP!| }Q9U-&tXII(jF9]EASIm@SI33Q54}HUQȮ= 瞊}۾ _]臃KxmY:M $lh(rr9+bӏ_ڳo䯷=ԙG#c,4uǂL],S.[{f& 9Ӝt!K#'41m'#'EF0ݴ<:}R`Oh3aHYIF$M8M*L!BH|DbP!ǟF~Oqu0[.n2 1-KQ [Akd}dU DŽVdqe+ןpL}(`M(SBOw'h{,tFpDL Z!; =8y(Ʃ%gITTHb]bQ$ 3). oO[o1ED'|jGwl_`؇BJIU̷W<?&/ 0a $A`*9 ppa/D)}̎c]#淌M$<J !aa!1œ#T9`2s4O#v !}>AdGާikN`6~Ip5m|{5Zޠ0!p.P,wn2B^D$Dщ;i:&"۔Ӕܩ)oŴ@",' ٩UMzi YG& y5"" JfJ$8ޕ0˰W 0hk]kUy Ћ.آ}%Q"ʢ[w, P` !elzHCKn麗 !11'1Ҝ.8o,9GE8%0ZIr6 }Ɖ4W5 :)[üd*L+79pQ0\Tɞ|U3 4#4S}z~O_'^u鎻 B%' Jc (,1q"fLfBNL7QXRxB("(Dp!|" cjb ku1)=252q>$"Ѝ)瞂NZgu- &!c%!OI0%t QAąֽtfi wg <(YvW;?sBMHOv>􄘲?+9Xc Pb:y'~;E' ɩM  %pB!BKf$QT.(7}xD&i@i7 _7wK(±^PKxs D80-y0v FBRϺЇ^w@a@g-SY+Jr$.ӰN1g=kOrwh?YܴןnSL B|.&"yE' %C!q^$ GK'R/DAB1}>%a>a HzUUܔ"@u)ABY_&k] ȉɫ31lk3&|rYKrdĞ! =GW iqt!)"1͍c"ΉH 7V+\z: 9RHw}A +?ZsFx:d&e#XƓ"-HD!AMen$y2&AI,r2.ii@&@DQc1]4/}KT GB@ Ȍ蘅 sQdG`UTQU:bb&D +1bA&ai,[W?s\+ҕeYڭU꺮˺ժ뺮T(p31chbb_$6"2df[$[CD! S Hj9:P%sRוtfʪ\Y윋u]sYVeUU\N\QRUJ*'"eEDC B~i8 ~6GaL*ԇ@ v3g&l3sFw WpY#@( Ǻ5UbQRĹ * fv &,<3ApX+1rn^ ™h$FaGB$B!$عjFYU]IJb*@eA\q @ qN @)&LBeUTErXV[E}ŕWUV;t:,q`+B5q$.8gf+˲tEQp\Y9ǔE!9)u]KUURU|.%;ϴfhFECb拈3sSn Z-nP׵EZVUUUsΉseY:#"X#Ibf"̄٦UWE؇3; G# aY"/7)t3SYTUkZkj]]e]ץR}YS!;fypy*\_3sGlMԁ*pf1F <g( e>&h)wN2]n1sP""*yC`"R 9,::GL#i~/^W-o֯__^577ש]׵/"eW8 Z##yEsDTQUQɮ e!#8PGAHJ# dꔆG"c2(yQZ |]AD A~cš=d_A吏 Ƶ8g1d*X6%> 84]l2}͈.物4[a2-fWM_ΠQ6U `1@VDg_ODNU #Gp@Ὧb5tH?1T uz<&i0|\˜z! -|:hhnmccp _߭P?Ne5eE PPׂ4DD7X|A\ =sZ>&_Հ*0M1",acmkTcUɹ&5ZC7͏9$;lG*lgl?-JX[ wdCMt(cmɪ 4k݌d(G0dQ@(9$>7uj~T~&JO09" /?. IDAT|mn9w6lQWjk_AƂcmb1(HØ l]筘zk߶e@C4^;(( ZPy\~*p5=@P*K B]M#[2+@Pm.1TӦ!eJҺ?~iU*>~^a5s 1f1(L#i(HDTЪꍷ0"z(ujsW0`B݂cqxc٥4r}z}Ip)hTZ0~dcz*|$Z;ț}LzeGMG@TfMo!ium+cZ[>maLJJl.V{rTm  @acm ߴ/6!N CZjaZpP#(=b 3ySIZE*$ЩplC)yz{zӁ^5Khġ gUi|,(LZWZe$T% *5g)U&y~&, Mxڠ&@@<0&hޫ͌)e:6RA5MӂWZlۧ@ӁY`l5PPNQg VYQű"oh~+mk@0L _@5M5:LlLiSA6`Ckf-0iUJ6:QM7[AN=bșP)}1@gQm5"d&`y[ϵ1Ζk}HLn꘶S볶SfUSmn#cWW/:cCV{I߄2L,aS[&Љ s)P}VlLdtMmz?NlccA7f~EV Hvzp˩ߪ>Yv`6[O3(,e ;\UЍtY볹fXYG#JLuD>̀ w6L}]6nB; #j]Aԫa5ۚP1{ \.Siڦ,* qom c3j`aTF2*DDyy:{0W+MLOj|eiMH`Q`6hoL]5 ]`q^N;z^̝ KaBKf ?il}H&6&[@[Ȧ#=]ftE3uB!]tI}Ҍ|Nsmxu2t )mgESeSkt51v"2I"- Ў[aс ZHFj5l^jnpݯɧ@ W-3BeYoYkgiD6*QSLz~.#>^k͊34ű &CG1LЁ`ӮvƳmg&Z:6f٬6IgM{ ]ݪ6 eBK|AAdm}iPHm/`LvUtF$sPS)t 00G4v.PX$֝ReHKֿp0 Y!뼂24ժo´~jYgTVN|\go kΟn%IaL:0j-,Y:@#SmT^n4،d4mz Ky֌WĘWXj2^f1G@{10)hN7w@gm"ܙuUK,+ _""1G /h"cFu Ǝ̝T.ݧ&S3t9K֜ŭmԅ;¤")5TTe ڴH* zt|Vk,%Z'(EaltD&B%o]WX8j s |Ċ6q͑!ֻ#2q㫹;kfQ?uۦM2jr̫ڭt9E@*8i>\Q̀*b (>Ib'VFHCj2Wa \Lm͕Ś[ЬaE;gX46=22YcLoOn?c ^,OtzچlEHSc%5`q6 IX\͋uJ>86r ڷ`&$S'sq,md/U -XlYڵDP:_wxptށz: ch46QGMJW +8Z(0^\ԕk`'}4~tHu6g#$wt0)Г""kx#!Q۱p@d4x[;o=[cr_O^ p+^Vًke$'Z5 .!zr(; +nEձ~ؐTvtbͲĽ`ojɲ@;ǙKX|W^zkz>=b$ha$LCm'w"2+(>s9x Ârb> nD1;s/ XjMSJ6Kx(GM):8A ?>[_Gigm2l"L>tfE\ӂy2+ q<_BK "Zt"XAZaVa,IixIE/ HkGzŻ >@U ky At+*0-WEW9TYqyWV&IȈY,l5 rm4llWoL %?4L`P(*(h']mg>G}D{;nHcFE_{h:r+"*Dxs!HpUMZY:PkDB%P]LRNUu"LgAjZtoN$ SpY-kW3 0WoUZuH6_0Mq*%|P!M;#4?~A{_*g'}t,Rd/zd #р@妎h 5SĐNWdj}'^8ibsj)3^!]ԯ@ǜo"zr;9gL1 ZDYDdUUNgv!='ٽ(x?QQlذzuTԮk6˦?vTCm*WEMތH`⒬X B%d)ʰ_/:PD$fGəVˮt|މ8tx>~ V嵟 lC_vcq'q֘D,"EQ<9Oc8p`re[l6ܓ|#">Ȫ-T?Z ڐ H MO'!(R_KD#2 R˟'oHq(!!]92']Qԝ뿰UOΝHCԘ9im׽n=u]z&T 90!yANh$(po(̴$1vqWXʴozW(Xa1xY /^]1NٕX: "s-n/ݔ`eb>BA>6&)<0zQr%Oc;qo06.Rz5dBg '&aSF男Nk|Iⰼ [[nE97#>&YNi%` H 2>00F<(f $:vn8q͕Wo!Ώ;rx6Y3u39W>gM"x"jA*)'BsX?|E?HeHe5Ɣj _P^WϮ}[zq07]8ثN\yus;Gl0ZDĈy֭~ CYD.u'?-G!\}W`H w "!>Yf(f=crwdVѰhӦMNDbe궫S  ~+~ʯxz7,vwzU/gWԺ *("(bD_5vϞs>_ f=6?#-z{ 0IߙlK36L⩶5yI9~z3? ~⪫GWP%ѼIvlev/腗^=wW߼n{ #t9m>u>*zOFʳ/Ls.;vׯON%3یr$P_(Hr'PHC!cpۭ|.|.PЯX.4/g].73(濠֭[_׼p}(ַ}WV3y/ &"7۞2;wciߍ@&-82!OXQ WҞ?I11f_`&]F`dEADDv A\?zo_m{s7 s }3o-qu}lL7(ƫ8pˏ>Iv$yaW_ WO09!u"i\=wUu_$[ќwtMj4 VfV[?/|k_Dn=|(4oZ^g|'>m7c&`zfaL mw\u7Vt9s>}8K뺏o =˺<7 ~Z[ {/-%_G N:i7oU|xpiӱsϑ+M s~>;6BfO8K>ַq)Hth9x뭷>(6qP5_HH~|?LsQ)G`^z?oox-yǮa*8ʋ:o2|~6oK%/}r ehMfk~_S@LU/ X^y}]ZOcV*u~K[keݮukg#t|$ _5yڙ߇8wn%gyӛ߽z] nPw=L>]7핟|܅;f4Ъx~n/w^i`[}m[]-|q@ݬϜ?]x՛E~ }wu:k/#U! v߹aÉWQn6@͊s7q%bh-sGt69yDffʻ>?zTo"G݋"o[~6o~> <w3bq;pG63zuU[ߏ?]8aIDATBԪW7cWĀsQY=wףɠ#Qw+:sDEQ3޽U]<*no3.BwCX/sKv+l7{=V+cXya IDATx}yWg==Y d e0!@%PaL R0LdȐJTPS\d  ٖek6Kz{wIO,Dw_߾m}4pkƭqkƭqkƭqkƭqk1ī}XuW,nר/1~MHXXx8c[k-!B}o]R4AgϞY\\ܹkiiuNgnOa8tZJEVB@)58h|R9W, =3::zGԍs(CtC:תtB/'?9pw,,,j p, RJ! d{zq#"k۶Wէo~yXH5*^k Wr{m=ϝ;}l6lۆeYBhu$Z BJ)"|5ߩZK)Fa)H׃8G&''vnn7~(DԊZQOzɓvsJ)8˲"qE"c @ض y ( p]mg,\k0 !z: A CGK)cB^' eՖ-[޽{׿t޹lfWUP|+oŋXkyTEX)DP@ZERJB@)d:Ih#Ntt݆JXq, Pna.j{:=ME OV*?qh0 BJ%LLL`||\e8!8hJ \1h?Fvh}z= qVGNz/2f7V|dVUJ q ܤy @1> FJ$Jqv ڇw]hn+(BHain;<; rP ܤ?878BA`׮]b֭\.>hհrdME:JZ&\a"")DEy?Z/:u WU no}G>>==}_Ղ:H9͛7c֭P(dͿ%|??y۶i&!DESܦ<\><#SW uQTRJRqw:hxxxAp̙3j7| @.|/?\YYDZkZu{m&R9P3b 0Hf6@Ǡ+z #:^\ ta Bk{͛#W3X۷}R^B(۷oRJz\4Nsp P|?$!2bJB}F/\4,D~_WU+_o_xq78$Z8p p.v]Wyz۶m" C@g : Ѝp` -H$(;|,fH1G )E뺢X,\BvCqv}… 4ޟRdz5}Ct:B0"{xxX}A 3Ing1) C)L}Fc,if(Bk.*eYSwuׇΟ?"nhz׻>wN*(͛7 ˲DZ[bZ+yJ@oNgia@jJH^<H pGXVBeY]v}/q T7!J##+NG}ev*}hg { @xv۲,KGQvءeL7/) z^ aqB rME"%}m{P B zB@keYֺ<;;^zo_+HDw[[uݲRGQvܩgggE\/Y pAfnz7LP(d/3M§~ #+)QA)Rm۶pٯ7^N%1555O}Q)aE֎;;M&WlYր1|eYEm2x\)̔g\|ώ`YJ(u]7cbVi)nu"v^w!I {+RO~Z8a333z݂%> <YLQ`=?Pmm`aaKKKv}Ad"t:t:Pvjk"^z^OP^_*f7o<3|^Ip>ݻykIqu^/&g)vx\\Js}8FG^Y* i^Y4))pyRn^Zkj_J)vé{/>}^7R@o}{NK)UXwy'n6 )3/fQ9}~V+VN(!%N"!J/!Ro$t2D$[̙3߬ו(z%Z+'%I˵ڻw.J,d(U h?=&̂N<0mkYxxUJNv;Bˈ9HLd1͛w*V$qя~?̼aZv޸q0CܕBG0k۶ `e@<'+'a { PML%y(#z}{0 ZvhdddV)ɓ' 8;v nWq,{nq&o nmy\x~|8saee%s='q Q:xٚ<=R +ٖ x;vv۾Pp=@"Mc_ qGBk޽(%y4YQfoOb[^z%,//gs Sw8@AG.vS(dt/X t) BRT: {YSs=~533/i68. \JQō.nX\\WULOOgu}d7[a$R`ii KKKY׏m8qZ,JK*(~ b*0e. * *J`Me@RJQV= `!cٲ{yj@x7lY.qyހ%hܟ^p7 D+jHy§ Raaaa… myDg Tej |HJLރ2~ک~9󨒥k bZEj2=p]w*=o " X@-ذaC&|NJ{d.^Gyo}[3+Nм?NP `&Hv:9$^RZ˲tzϬR4b3R,ऐ8BJɗs\/1ȕɌ&5dN 6g%+})J4::'}7P0:>'[1&ХJM)><6%\.I8r&''{ 5tb1>uL \.t ROg쥔6)R"/mnB%<2[ۜ<ή N@VVTcksrO""TU<䓘C\ΊK&.Jf5QC~VHOKǺk,j*Rar׽)۶mۂ--GsrT*e<:[^&51%''p|IhZ ES lC(Bd. 1?O˲yRt44\ Xa֫η-tw<],]ILaM0F@9OxӶKz= b USA1P*@w27)#c!A(ҿ @sϞ=-oyްapTҥRIeTUJM+^˽ ! HdAY9~!WR'ŕ GpΝ}{)ekӦMzͨVSdwjaaS/]sA籏ky ]8\xB2Z .\2*J?ފFހ{@N򀼪jxFZR7vmJaP}sĉbvT*䤵sN=55%ϻ\x1[0 | 渜RsohIPz }ǩS[cB xoICZ6@(џcǎdX,Z7nwqj"śSDp~s׭[=S7nھL ])<^~%T NJ FpGGG'\ ժڴiS&t74X޾s:5LgygynkEOR`~~>(85ϐ7Y @J}^/|O~ť<صkׇ=4.QT ~K%_KWtyk~ \P ɏM#P3 Fuo11170"tR.,,x9$2 p @lbQh۶͛Nqp-4O7'/*g\<L湭Mhй>}<[%<wdF!VVFiaj۶Ǐaj?ɬ(ؾ8QPJ'_K] "Hz>k)?]NܘUQ}ݗU Aǣ2fӿÇ'$x!+RI۶EEխ|)r_ OA׺Nny0MiHZ\\*D417DbQCi}M6]` P(JAS{H)ֺ\z#p(B1{L 8Z1ЌyB_ 󘟷<,yxl7z'z,mVT0J)y??|]5 6?>u5/[Qn6 /k׮}qǂDZ`]@ Mb#y BT>|xq֭;ժN`6S>Ԍs ȱ-&q"(V"F 'k8HCB'xq˲j&Eo3qǜ FD2M㜂YsZu*wXӧOZZJ)ֱy֣>zsܗF@@G5OuڔA:3Ϝ P(QD"2>'Ww]N~_GQ$87SOjsAH%2<@yɏINEF8}4jl֖e !D\,Ջ/X?jSs!@'!hQZ^YYp?=zti~~>t:V߷(iHY+vEa Hfy7-I,k'bUȣJC厛 n=zZ i˲R*. "38uTY}&z\ 0:i)b?Zk-z~'x'ZTjHZŊ뺞Ron|ߧJVd ٜSmڸ§59ƠlÜoGA4A,cQQ\(O?vxgD8c)%gzСRJ+8Y=|WHKO0$t2B828Fqhг LŋO|oZGQDBK)LHS^'<ʧJty\~lt̵¡wcddD#-jyϾ#XJiqZCI@CL1b֡Nc ¦MJ+Fm6tTH:Z`LVE1'g ײtE:HM/Y;mϹspAr]eŮV~衇R8H=zJpձ= 'p 76S##ǎ;-[{NRotcRigz͚f8q.^8{R:tGxmR~wυ*G_BzZk"%$&VW'݇Rߓ AI}3]*Sy*n3`H+sJRֆ0\0DƱcDz'qiZ*O'On64P~n<66&=ϋ/|'?#R0&6(71+j(W<੣SN_f===߷wޱrL `D ɜvEVJl6 {_݃+'h'O̪tTPH+zsChz Z)%\ՎsJJq\7N<Uy9+HRJ1 {l$ RPPK_BPz=ڵklttTA)%RX一xPh4v [],Ji8L}KKKx/y&1([L"Ze ۶yzjjJ;v—oBZ9gJAYY)EI. 0D JPH M͍oٲ6::T6'@?F1R=K)շkZVt!}&hցͩ]]m z0-9qRJ?< pIJ^k}^W=:/dֺU0 `$j*B*d[UݲwJEI)cqD(Q 5 Ak-D6Q#wٴQohz8z` CR(teYVryy<_Hth:vZ¿Gů%q ssEu 0D#xB'tXٵkΩԊ+I$epl`02*\$lOyd@)%R,.JJ{|fBI)曀7|\q=`:RbU za$᠊U%( ͛7oR)&e >$Pd7SC838W5҅BA{nCBRH{Jˊ^!JBE$'EWEfТ-*n۶mۖR;m[ӔLe '9@|Y))~z-&NMwo=_7]˲ a&"PMОUfo>344VJ'd>9\ LA1P,"% P@gu MxBS)\pĉ~A }F'zu> amx' v]}o}vÆ #b1Gǔ>RO#DP-."ϴV/ѼcM˲8ͦ>x0l Cp-E""|( b ZkR,"/&)Y$p6mڴaϞ=۷o߾ybbBZPJŴb1D}ADZ?c- D" )N8~G}~бcN#J;Y5W.Nk7RU.b (EP"8;w~[FժMKQu2һ8 u8HOZ^^O{&8YɕgfC_Q7^7It#eWS (Ц<E!Y9Fr4o|||x˖-fff'Gju]?"Erny " F!tRڸU!I)/nFO07~4w4,Zkꃠٸ|Vm yV`Z2 5>Tj:}B)GěRR]Y+WY0|:9-Hq*|PٓqiWR$tz_?o!{.|B\Aw\9n&7P}Īs¥J@Y@+pimàDyn q:nF.8rܿL%qe@7qo0n>oܬ @+]% <<7i @fZv^?-^MᯅLhf7x($@.`Rq\ XwBDR0JJo:kE [8X}n7C% Uc)e58ozZW>py_kL|:)@0->xf}kƭqkl?3F\IENDB`ukui-screensaver/src/assets/weather/45.png0000644000175000017500000005527114205074704017474 0ustar fengfengPNG  IHDR>a IDATxyչ{ϩmf@WW`W͍&1hL7Fcnx .QQ %#2/]]y?}Pյ9I@?(BA2pg" 9Q5@`f(\)&ASΡ--e1R9L4aV," hD,Zد٫C9.3LS5pNɔ;& 6.P9(a"fswz2+Hņ 17:k D9dmJe;M)S]@ ymw?7%G>y׼r2zy\\=|Cyew@ }tYWSӈ Bb^i <ޝ4UXN& R! & % z% cw͝r>6€'/@ =VNJ P= ƸУMp~\Svl(՝,Mq3/ fVC1Xb? (fQ7u%t)64 I$D^#H$@k;f@Am;hRv).{ DMH "?{e@sCu9Q)Wùw+r?DŽ ͧk (e;`E4SYP2FH(D@GpAmP`fVp|紃OL$|nW>B*L; ̊]Uڥ:8u:7 !,p %N+r]Ŭ 8 8ۖ庮bufa>qRd} 9l+lR. ÊfŶb%DZQQoZzB@D#RNSш{|MXIk eA) @J0(۶v\'IH bvDi=OĠXu]ȳ1ڰ,U̬HD %)NRp\jreYJ9R(qk;찐nL3c!2E&miEͬf2( Juڶ8n>2SrJ)=E&.r} zJ)V RJ:;=s9GQQR`N׀D"Rd@FOHPhā{c%I袊qTǶ% Tw\GE@:)YZ BW>H 覲A#1v8F&PRJFOpNH_H7nD4fm8t4ͣO x{ē ۄe9,v;b*qn'x#41}w*"AJ8KND76=◑1#$CwK:׽j<28:hLW4OxvY-R."f&Lۼ@>QYܹF?;wmŘq`[ c+/;.ݻɿGRF*=‡ӧT%DD>7n身O)] /܀hd1SYGo]0lËK&lf.$^ՉSq+{O5864"MG:EHLF9 qcb .+Ou/V+WHSOy.>iǝy, =BJ.*gYYwnܹgX4*ьam<4mۦY%XwgmfdQSu$D#竅||!$@$p1f`a$ t;lg.\\trq?֯MdY3$NټzY_j]Z4mK&}iE\KR,uw~^gڶ+2W]@4H [ꎫ)O#zt8q/ P h,'8iҤ8rE8ze`fH)0-CuU:0aB 13::2x7ʫᣃI8|# DFT bz4M Ӵ/מzGA, 1S?M 4BO8K$"!DUU(ҪA(j$KrG%, fw{ Zf%y/[̮X]D:-Y#m9~~5H7ܰP_ w'^<것eń$#89IPɦe ϣl06nl駟f C:GygWqH'kԩ# pꩵX,ðe2zmx5rUBDAa|/_%%q\uHک0 }q!.T[۶{|=R@TEW!Y \(B9= ~633/˺~yܙַM[~* )!Qg˩+ =-ZCuΙ5,_{ QR?kUo&4] "#YD(U~Xc7?ƒSUU170b6 *NW9?, LUUUwM2q룦M^jbKS/QgK/6`sjଳFb[Cj5TWsx۷=cGӾh޼`fjmMl CGZp,I0$[EaY6f%^}+i ͮǒ;؏X"h(帆G4D Bm4+;$躄 "2v %G%Z$X;4Mq\mGAظq?n PZچɟе$ RVszC>zF7H9/ (5kSkƌׂ?a%lr>7#8wh؉F p Ŕ zO@UtW`Ųe[r X]ZBT-yO ^!<) 5!& 5 H/ɤ\vցk"03ߘJO-zzMoGGQ!cEM9Oa"z^g*/脬T}]Hb1eK7#nAqX,Gpp%+RYYDD_X)BE|Ve~{dpƧŔ/7^|q,.pfFGg6 84`ހ֜-wψhFUE"'-R) M):EhԨ"Ciݼ}!hFQi`A4vDH(c眑9)?Of=l&CGmf*w\U "ϯ`Łf7?X} @娝0!4I;,0+ݻrV ;k =gOHDèQ`YMyʇT#ɀdǿ- P 8!NaChO߆yF6kcI9@ʹ ro8 62L,bdRYiw6O< @5,]@5D# h3<9B Єb$8XI(r-Pp/"`A=y @c О"dmB$B8}xo eId6" / ݌ S/C3'g ) ٬ 8sdQY3)~/*YPx@!ݕٟ | mߊ4yM<\/3$l|M(JV[0 Bvvfwq0&!5=#:(v`&]&y=5 =v譕SAIO! #\W_7=g =t=tX)Kz'f7.ё_ 2 -X5  O~&H] JYSi_0lō7lA$"+QhP97}8. !R Ȳw,rp-FN+kCH\]i'xVN "&$IG7|QMa0N.6 yBc:} FAu ۶!^\a¶E0x8^]455f(Tz`.CaY᷃@|I zmvzٗ\rλ3~GYrxFr._u .HDLFQTC(ڋh曟? Es Q 5o4M ;nS es$!@  @Y^LJ P^Y Wu1 QR]Tg7,SS{[`:z}.Ɯ9 z\m9)hhox$6qp'ۿ̤Ҩ7?t&/̛q BPnpY)45y:a.L׊իwg`玽κT5sM &=#RJΠ݌ `R{Nh%v)`JO\Ad9 |5UrcɃˌ"T)S~ #VTw@㦝EZ_\c#41|ʸ+Ep\CG?wܵPe (VP좴"0j 8bO@;S/ {?_!T %`*yb%ޢ0X$4-s._ yK&2ԕϋ>Q?TLq bm}&]@_y/H`:m%_5H,uSxѰmPpqW悌bt-H0thTױ@A+sGqM-R4Ҧ GclH9yHgLM}GLsR)L<".HABfգdpR42Yi3 31eU>n,9btBUOxj;uλl2f73뒦K#BFL%qT#X3_Ø['"xj/~gDT:_-ڨ ) |j dM8,3!R.,Lg7\ǁR #3{`(fW Pւh2!=ZȦ3>V\D4]U:XH "Q l6& A23\!`HM04QUp6 HI9i f&庰- Y3î lSkoO)f3rX[ vX)Gl+W*u㘶me,{37l^">`q9 XM 磅ő/jXhhp6ϛe&([AJ pT3Ngq{ &-V4 Y64 #3f@ CH@{}E O6pͬ}Hfpɟ\iHēPʁcfSiNli[[ۚAV2I83;2`VX)JYm. YQBzb;ٛW.01ޘ035H!3x\Xs@wcO@1,A\#"ǹҏk‹KAD )u/s!&@ )ymd[ ضfȤ2iQ;OٽSt"6m{WƐBtTZY:ُ@K!{fOBX*M'(=0r@Ys/zr\<ZAq_s,@H֋A&=D!k>oA5R@ \׆"cf`id2eCáVK@\ 8-} PN'3(vr"c0 ÈzU]]=0"1mۢapQq;w H!|$>Çr]B[|8X|){qlΰ0.sR s-Bkg{AK-d,Z[ӯ=}\?eʑ}m;{>0ߞJK>4D {9 p2=` 4m{;LD&ifٲdY6۶mS6ifJa& #ySryԨ8NDJ],`Jfc &|n5 CVUUqy;Jq&>q{ᦔ=\9b" =*'|-mضl6 ˲8۶ q^qv]]ed2417_2$<]\ADU\BD3 q2eee;?qA%%%6lXϦ_8&p!. mp]7w-| mq6MS;z(3gE2> IDAT~ /\$ F@3K۶O~o}}Hĉ)c8?:0Û: -$SHzgn A)[8ėf)ɰmNwww^w̘1> AO @@?ٱXl^8WTTИ1cHuK3)@~_ |0 "^b!Ez9L;9 p9"<,ɦi"NS&q,ˢ]vɺ_\?'A!*OǏ/|Od-**ÇÇÛNlf"|!'UQ,;ViD PqdYxơtٶm{׮];c^gK ,~ȑ#)--X,JKKL&a R6-x?@o=֙=˾z@X"zp+NX] 4)軦ip]oI$A$!]Yuǎk}w={p|蕕S$h( A}| `` 2 lS4H$ҧ r@`?O'DŽA-"@`P^~ V`tƌcp.Nq_!*Diuhv"qg_(:4lP ]'k@ <3aua "S<x<.i=ЍYq\i h̜44 Aw⊁/CX(^ Xv UBcHh_@ q]ǁeYSNQO@` "HgH D  lsj!9kaIЗݟ.޾З*dם/ " @,X,&RΫ?~>D\({)7 pdmþ!"+i @ߏ2-bD"3gμɧq@2a۶J)MDcР.+e<^ M-^ E'eB R)SN=&hx"ٖ&_/ D!?=9>p _LBx_@K!ÜD"$ OBB6D$~ W34̓ 7t4ٲ,N{^:җ,ϝRS~!10 E@vE{I|@H13x4&M`@DouE!D&aH$rЗ> W3 axúA#;|xr/|B7*uݗn4MǶmύ@Tm(ڳg>`ϧ?JuLLD,C|yKHX S1_"RmI&UPDe_Wަ>@y;Sߙ%KP__iL^+q 81\_>w؏*/,Bi?;<ھB\X4 #Lu2MSY۶iJضM~ y B^et>?2Bϗ.u.c~?P*rmۖO>ҽ{fflQ0OH!${Dwnhhh8lFUiii 0ef5XWŎbE~,X~路pi_r5}a~}CB: pd2ݭRq'x7v !2X zV kA&h{{knصkWX,VD8 _̙L}qlYdG&o/OBaa1^H䫹$A!O"attZ),Xx߾}+"RDa4>͂Kť 0y7]ݻwl6+ \J)L&Cl!u/  ``= fٜJ prB6N! 8a$dQggKDŋwˏsRB/N*$Bd]͠G(5XBĘ[ZZ[ZZ^ZJ)JJJJKKKKxضmU @Yx4 ? MDO '}V ۶ۓ foJfaSϨ4E>&L4eʔnN|v>#>si1º79Gu^ضmm;@\z(j Gl6\וo <ݽ/-xn'+6wЬY.y'_;v}:th5wO}cذa]]].3K`9''P՜fdNs$@aIDQD"`2K2MSP Q|)9 `fjll /ϥK @?ix%"˧Y8E;ﭷZq^|WLۿk]׵ Tk׮]!s93av֭[VUU,,%K]T*)ktMo3V4M ,t)lhh<#رݶmCR \o79C~\%Ktvڕ]dɇ< 6=J@k h0/ /-3[X$L& ڵk;MQ">PI-tJ)]tw޴"!.15arrDR Jub17` !aD"Duף|ЊUV\ps{+** RSWW7tРAd2nu]8㚦iu߿;رcW&9 ~6 @S)' e*PTT4/4̬9rPuuuM8BD徘'lUQu7|m۶m ?5iҤ!,O)x g(daݟd8qd&vܹ?*ݹ`V,-6 #cPo fw,YzED%zKK=7o !DD؅8eYO,$~(i;`D$oURJu/˗lذ#F5lذ *+--$ ʷ, ={ٴiӶ{o-^3._pߊ{a0vxgk  QVVvF}}oVZnhڵG=ZQQҗtVJu'na/PDDI1_u@SJ#iV\QQQUUU54H$xTu)J)eYdݝ---mM^:GsOuBA1V NjKKK˒dI2麮tvv=z'@vԩ֭[q 9 $[&I@x,D~izDl (kkkkkll<1sI~۷Zx""" wu_Y""ѣG׭[# 8Nȑ#9#o eF&7IR:s*Nf|1HrC+**Jvv=\uM{__T!} X@@\p-CׂqMA*t-JȉI)e3SJ~k_8… w0Ḋ0 zms֖w=ݻi͚5٬lٲif%TVa*x OB90g|Ia׏={vvvvVTT/]t駟>]jGB V¹ӧO=4ϝpWZ?9B@Ji(ZΝ{} ˅ھ}ݿWϘ2кu6UTT y뭷6^zK,MMM͛7`-h4,Y,H'gWSN=kРAEEE9s慳gūnֶ_>t6]/}^x aU@ 55u=WO>{èQѺm۶+@}{߻_͛w!CJ;;;aÆ6oެmذy?_'YODhii)kooF!vzq5l. ---MoE=o|#Gy#cƌ)}~|k #Ha)8x඿;~_+ַ~e˖sTqqq^JM<*ND?h4Z@{wtCjȜ>Y۶*++QTTy7>^d~{{K/=/޳gOm֕W^yݭ:^`͚5 MMMm/Ɋ+6}߾Q)uq(%{jjjjjj7pW_}MMM;󲒒I͛7gӦM&M4oؽ{7]nذ?oV\OYQ"`,]yכ=?O3f򩧞D.0NӴJx]({W=<C.nv5-[8޽\h{MMM?Ek5BLpS# o2J.3 c~9szѣGÓNaW^vA^zu۪UZ7moiii᫮?z`"]׫p:~-~s)+HhѢV/nؿJx+{ctgΜy?iz>L1bĵW PG8Ix g'w)BB\4k֬_޽ٹsgo0xTVV^idx1 ?~c=_8 466555ɽ{f8yWr-_gIk 3wQQ\YzifUEE "5:f\ͦ!jqK'L&'$Qcc&2s|V'EdnlQ݁EEtzwhWw}:cnao-+y FT9\.KJJ ,--wM:xO.*:rFN&??/8@QYYauKEf\uy.HZN'@rrǎJKKfY֛8kCCC0/,>:f͚FcVGEEpGbxԨQӛ.,q 8I$o|x0{pA@'L0kǎ{bcc?\B:f̘=KG]v @aÆeeeG5444|qgB-uS/@'2ڽ!.{{[!xZ1ޭ wܩ7rsssCCCO:uST* B%MJJSSS_p\A &3]V^+ /IѴ:ulaaa5*ZPx Z/Rk׮%'Ojeff:3c ]ꫯ }wqu{(a%8)#:1BZ!eݒ+?Osqf~ɺO˹/9R\6,Ydl~~~ŋdɒi&L_0u[.Rh4mݺ/Çׯfa˖-/// u„ # *_xWy'"4 d2VTTX~}ĈtO 6PWW*q8_v-O֮Kw BlN@)8rȱO5jTիWem{9gϞFu*[8yfffʖ-[y6l6srr_fΜReee~uuh4f fB&+lQ]ApYnnn\.ߗSN]nfl\.oB G;7( 0'd4E ,`Y H(KٯMG{ T*UB0@:0 7n#G. `xT$GM vgY@{}p8hSSmnn6ͱk׮aC I__"VgfB02eXܟe;ߑxq7'0 L0L?!XB8 !!J=% 8p6.Y=A8mXfϞ>==ZSS'(''RJu:] ׯ_YSS.CF & &7TTTDqO!d˲Q wIa\㺮 0XT+..n҂|pBMRR!^o7LӧSSS+Z[[CYv>UtgMqn;pk ϝ;#SNHdDDD`|}}M{%^RJ[9c!l]` wMG% C1bD vy[4cƌFGGOl6̘1cSjjݻw˿zqW$;=1'uJۧةSzl://5+VR􍈈t:A 4۶m;^x√G]wW'ptZ!eo@w#h;R FcjL2&22߾}5eĉΟ?FKK ?w܉ .@+**LNS;9&&湯jH$_-.vߊΝ;W}uKAAADVlnnM*`ܴiӾdW3wacƽ饮?M˗/.//H)VCC^z٭N'X,tD!l ߿ҥK_OpBYvvjҺ:{YY_xF&MLOO|ќMrrrƍ#oZ=.# gqVRJS*zꩃxy7ocXren_~\W?3&dee;6l7!AP !<&رcU[[/gYZRR.Z-Ș8q즦&{KKKNkMHHx?""bPZZZαc..;lfᇴ'O333֮]IffuM4iRn'ZݜtTUUtf~ӓjkk FzgS@>|^xpCr bDBƍ7w>|!^[RRj^᳥R7˲Ⱦ?xdYYbϞ={6,==Ϧ@BHFg577]6L~>>~ .{nn}hnnv;(JR 2Yf2iii'4Mnh¦j/_>=>>~^wdffF\.666wܹO,ߝpDZ xB<!'wTD"G}}w򜜜_~YF֫W,,,9z P@G )Sӧ?[dvݲ} G>Ӄ<7B0 &L+**||||/^xٳ)"DƩb~+}nr3^vd\.[rߎ?4B 2rế+ >?ȘՇYl^Kv}%//`y_AMaDD*LU(KR!cY @W}yycc!$j_f\>pd).(c!P&! qܭYNRáx@`޽۷RTZRj$`F뢃w̰q3x,q?0XW>10-D Mt=Wq1H4V$nGEϲltx2 tq)f ø"2q|= gB<ahdjż;yB=N:};"Hq i[bqpuϳX,gCZZZ~ݻiӦuhv@l~ B-&aRAwpadОH|:Ͻ̅PfZ[]Ym8 u뾷~n\tB1~W dgΜ>} 0ەJ\N(222$ǏoB-fDpDZ,BG3Ͽg'X:0 3EB0L˲RϥayB8x13eʔy>ZBiYYY[AA6##ʕ+ڻԔBv2}-3E횵^1!;b O>?{F'~f/**j$>>>҅ .NHH`5Æ Sk+cݿ@ʼY1 )zRSSeeWt𠠠_f hHHHK$+WȚ5k:4{wE#~ 'Dg₂J$[[[$39///[RѸ н n۶K&:u3ៗפT*e !CΜ9s^uu%ƣfxqMu:]Ullz}cc;11A?RtڶFؙÇ|fZCzt:k߾}Ǐ/V?~$; k~;@tttСCYf=6v~٬OOOOpBPYYt+=}tZdeexxxxy?D"ay3gθcǎtka (TTTرc>}T*Uq``OHHŋKٳpXpkOagHbq@jjjE||o6vȑ!{M۵kWL&#)hO} >ۜb?dJJJ|O*++6lXZVVLaY6ߜ9sf,,l_KuueX ѵwH(?jժCzXhdd;iiiA=B!zBhu뎏73ϲ,"BCq{p |ZmOG}tԵk2L~¬˗/gD"*Q8ztE"IOOϫm$yorDW߻y?AXb8p\T BuW:;qp]qROWVe,bjZq"w%hQ a/`3 cyDqW*ͮZ}޺V筮ڻqnC51(6 Y^uy;N @\pƃ.RNYWn8un}{{7Ã4R.2r+q=t/?D lHIENDB`ukui-screensaver/src/assets/weather/31.png0000644000175000017500000006604414205074704017467 0ustar fengfengPNG  IHDR>a IDATxwŕyrF9$D0`km]:c#dL4 d$I43t熾UuΕ66\_IuK?vFD5`0D@.썃(~uJM[^N>l#}z& [5Kמ. X >03z0`6tx_< cP!| S|6^pee)k@-wMvAb=T*{x^V_P;j{Eo}꺧mϝr^# r"  ~4%B)GHdT|'AP"Xyw @g}v(g2y~rؖh?Dp;/<󪨲U\Vȱcɑ6+ 03k36Fþi Z`@q@H}c7F3> +gþa#6J) O[, "|92\aEm˲XI} eBQԢ|c_iD !@ k ˒ X>|e'b Az8Xkmp$"eI`Yima1l1J1JѾbBzv$vuYWs㺞q w}2L}_+ˉΘF;1xf6Ckac`lf+L|x̜LJJ%F OcH$0|4lTp˒عc+ld2==T0 u `ƕJEMgDz@)L0ӓơ wVZQR`kf eF+EB Ғfk#O{rz#۔6ۯ-^9-됐(+WymV*ZDmy̘LQ"!4!f&)DLc Ah-u8DGau1j|PAgnù6ojxH@vxϮ4ib#t8&"C[D8x0p{x2B,2ljjO`_x#O/ɺ5λ\ejSkbʑCPP3߬ ;㇟p|eK57hq3X)Mt7R #{vw%/^_K,yrgh k[V _|g|.s^ϥsRDekUGg> Ep/_]oڷl=1QSiRuRFop/%h́ǰm[,K²$FjF}AHU~j H8=HX @"Ac4 uBb)%$- /'fE-K2 Y'' KVWPWvyoVVg-F=۶X)EΨtlXј%R'N&H#\]kO4zGN4nؖ^wdGl-yk{㩻6mM8MDܶ{w_}Ï\k:…׾"J5 h?BL%BCGe? !$Qрkw0Fh @Ahۻ#Fԁckv`"aqWW7b3kg*k됬1BaL7llu }?#N;}"3~ok$;5$ 99ANDQabfԥ)ǎxuhұxFlZ/4}gsr+<~v{X캾hiC\ys]7$#eO>\>-[ќ9 ];QӸa(Pi*e  }wdͺ "$_];CXu`~ $ĉMwROw7 ݻ1xP,Kh;{Pp=yܗw…wfGoں @1jyy}#_yTw>Mذ!"4*!KrH"!,KAf}C:3OcF@μV%7O7YdO}ܧom ^Ѩm\'cܸhݽ Q[-P[[cR Q_Ş;ȲvfFOO˗wv%/o{K bfIDdq,r].x: 䢇NuX*ʆ5}1T"0CJ>.fvBDQYV˦jL)IUex?]YJǍ/~$Ӝy箻^l@4j[>Ü_=輢HW\qy,D\=i{E$ G'8HGMV@pH$`{Mx8`fZ݃c3c4vԩC 0<ɁXF /2Q<5,H )eA))÷,s$d3w*G"{;}E -B 'ׁAL0FӄgO5v+cXˣo[ʀxafy(-Suͦa#}u+gqIo\!6׿ 6λ.g "GO|gA+ |JX*l PѷVohSGѵQAt.5 Mؼ%\(b8Vvb@{߼yyfm-[BER"W1i1 <% oΆ`Y/h$<̙G^%<=vډʸ1FR!w諗(pkr튀dfQ6d +>4yy7:vƄ7Q۸oJafO% GYcG0t?nBXPG3qɀˀrf+"Lk,S5k`DGY;| CiVM׾@\8LY~5Ĩa#BAL"G|2JF<}^x\Σ٧MSO|VxOU;6mcBܔA6P`"Pg91{3+lےR1;z@|>:_~{s^iYJ!;p啿1[Z֎;{%IZ}~f >@R (VT7DzeJ؄Z|۷w;cxU%3'c/ZI̓quSk-AiÀd}:ԟ3Ϭ)ēᙧo=BMwˉkD mRRD`#$03I)D]! "&_g?yyKdY!ӓa2KմMV{h~kPY']*ő%o:LI2  ka9d񦆤,*Ll"dRv:z^xn-13k6 +Ḻ U-$L`q3@(PxJ`h#xwM7a@DxрǞyvXb3`&x%g[Fde|">}Ldiw\~J=xL:y%ա<~$MRLHXڂ-GlG-{$뗮2#Blڼ]OF RXD2ʡ/-2#F ^0=PH) T˹l~e =8/h |473gNo܎ŋ4aؾm7}tt,>?Wpө+$qQTR㚈2`Iy0 NO{Wdu/=k\܋+m~m䨲[XBc; (1c 0DE1K)4mG~nfBmT ?O OE @wP C4p<{Btu:BXxɷ0fl*#uxq!%PЈD,zѕ (~xcG-r]B·$ "ެ8byi>9 whZ M2QYEss3׬չ`XRPeʑG ?Xp?}_'Ϸ-xU e9H0Dh0*2$)̈́ C}9<e ʸ1! @k`Y!0 ß_Ο*g<S ĻvdusOݐ]ZHP>;>NQcY&%B(>%Q6j_ D0 @YU ,ư''߂۶{X=+`ฑ}MFGV0m};y0hd}Hض%[A!7"Ròdp_PQ_aar٬wԳOK_u|ED,&"4J:@ImڶŶ-9pHF9r"hOv {{^a Bæz3t`@r*4NjDP A4̥ hJCHʁxg.ԥ𻻗@nr**Mg>>>p}i["?DZs`[hjoi@9hS>޽i$+|6+?)'l^{{e>LeW9lM4IKRbfF:bN,Y>ٴq;R0AWDBLK{ ؽQԫC9%4QmBpE0EHZ+x Q)DH5Xu-)H,l QS',U[F 2ƐaUu ~}{ A$`6 &0LVyXWrO zHXf30 V4ڷ3J\ᾯH2aOv,Ҥ V"#oeVL x#DCI0%0"@"e[$"DyW@ıaN WTd |xu3Ky0?}ca$|g"iѴuѯeY/nUaYBRKq R~1R2%+v+̈́McNy:4``4%:IX\ƎBb e4zBF%"2&)`b"_vx9e+, g`lX\ &.yS5̦` F a +K{\$2 2Eo)\Q`V>u .XQ""H@ B( #;\s43k6F XZLFy'LvWf[l^`kNMzeɆgN-3>E²e(& ņkDIvW|.D LT R .)_pVSb9PiHsϥM\\ao& #(0Tء)'LZJ'! l 1 ]sRJSUQe$>seqӕ#jjr#m̶]rXS詷JTѧHtc!Аg˞5}sbpJp}<p0:l@}+DVV-ҀY"4 kC|n e9RB6'V}}mɳ}mܱiP/V$v[MI[W@~TcBQt8#? D@@iw3DI_\ߎ(`K_ҬwVP0| (*CdJ(>(!V֧>՟v4ca!}WZ${'m֬dԎŢ #>yҕW?osږ&,~s& iuvDӗ?\Cۉg]h 5e||]fQ ^sQ|ؗ:SQGyW|Mk7筚F4&l.kq-ՋiC &6!KD@@c\$GH8rWeJyTG|P潑lkŌG]xOs u_M?d iؼ;v;e2]]qxو|%^=HJ#́́˪ /d_sD6g\p9[~f YP3>$Di+U)<϶ 3wD@` ϊC9P+[cơ߹qc8k3gyրϼct5uף>)DeBGZU'"B2C h$@P:|KL4-E( 8s SׯHAы.xډ'ԟծ}qjLªEm7ًG'0>βr(u߃8q{7>""n IDAT۫*}ʉ=:cʽݑI\N 'CByN B`5eKM =U'U% @V$zz|1lXr% :>pϽ~~5 "뷠7ӍH6 H@JMm9ԶlWr?G8]<DzY:;Ӟg7w7\=-iѦMR=jLeֱM[]]f0! D+IG[@pߗׯtԲ(5g΀O]vq~;6yڋ,:FT%{QiwPp(1H+43Kt wYb7;h/C Ǣ)Mm]i`p(kNĈHw끿zkJ'c5|xS=:5b˖֭e,Ax] :YmP_A12&*͙ud1_?]y\NUUvM_ڱ[7'g;p=l]wLO:i=;㑨E{ Wyo!#}DڋnmgON$BɉjOV{Xݻ/кtڞѨ- dxx%֎<Ӟ_\G Fs975n֗#8Ib(3kF0h"''o6zѢھ*V]BY_2=XbSp珿mQk 1TX42bc!I/Oo@~'IK/]D"\aaWDF{~v䘯ޭޒ֯B2)O!Kx5K>둗ߕcF}Öۺ%6vTeWp^7}o(QJAg[\MĀ06-[Q u7`~ ŶX/_j۶`kͶ8U#7VpQ%JI|ŀ~N>ϙDBd͛$uz]KƏ[s.тƱe~$_HNv.t#%B"" EK<)%I" Š1c6D0j;`֚1l`|?u!'&IIBJBdHHE01]zwU/J9K8_zyްcj.k{޼qf}uNz37kir1 _L"N+x#*ض2HXDŠ28"BID fyxJ}cy})H,`o +8kck,ab"VQa'jjHeuFcYBXfhHKREE̴Y HzcD/r*~  mY^uըpџw&(1PFv@}wy }/_wt7/|CĆ?HUT~3‚S'' 8W_,&E}D,*7 __wWj J12(e @ Ad:JZ3d ll[0 m,!$`YDBS@m ê޺={L[{pjH<䌨wPH+ॅ/%twm2hI _E_O^_\}7y-fά0wsyo^g}"!_?r@/<:JY5&T1"9Ү nPƘ`IǑR1Z)bkm'V!!dR! -dYCBi-JIR2[&B¶l[AY/۷gOa_GgC{:g;"w[ u)C̪Iq<бӥ'ܲ?~:Ž|~ @uo;sNG>SG]w]zh]]^We'"QYJ V-k]絓HX5&U;bx*eU(֚u`T6^fU>QB=XiJk.*s&Mm}XGwV,%l[zqDZ,&DzȒmaS²Uvc#Ȳ A9Kxk{:{L%gKvsj`2KM03 ml"4INq޸1roBA= &{~KO&川imsOZԸ_Yّ+4-چhZ(s^p3VAAd1靺#m^׹~j۶TmM#0qN?~xw_33n뿾e{V$d&[--~'xɡZ3Z[ݎ͛{6nimu;]xR*B3M{`r;/^ߖJhgd=g]VZjN{c̭瓟 1lʿ6{XyXK04Gۣz|O?yT,JQڭ ^޳i1g۶GN)i:IBڒ6#U*LSŚvԦ.Zq Kz~sEgYcc?]ByA/Wn'Q7rÿ?/^?bg;{??{޼e cUDO8kVdRmYu;zzٶaw=GaNCdߢp}bKK>C+v xO?w +oܚy34,?%Extyi2S9iy ȨfoS-, +D R) -qЙW|󺍛;S <27k[ι3?G 'sf%L]H]T\};_=}v?a-g=$bT#]<9sZfqDn?s{lY{~:* qǔq\06/j].zK`ӎ}MˎIap7z;~G}a"F8 gⴵҘ}6 ʦ&-(K>\j#`1 o#f.[!nSYa{ L ކm[l2l-}=7]F+tHDFu[X;a=nVg p'/Oe280ZN0 6x͚gΝXLT.‹?T! ^t# w?{l=-("=|"FZGP:o0 w0͙99h盟m=/G*"U&Wh]BhuN9 TTFX@#;p^=?o[\ܦ/$ޒW.YLJj=QU. G̪ ,\${}!޼&C|k}9k^{oCw^YQﲥ]oKz->mʶQMk8Wd9OC>ub]e}!'-ݷTBމ!K{~p$v|me*; K&M^Knhj[MϻN#qD@rƌ)rv[oԂSz͙rG GJr!X¾* N[ٙ3(F͗=fĿ?ȅ._SeÚ1kvѸ/{NZ\"mt~Ͼ\顽ڎ jڅ&߸~sQH|*k]L5n\s[ ]oRH"-zéGL sj͜ \x c1j֗-j#mEVq3q*[1֩ay(ŚidT.Sy53* a~ƾXR3^?uȑݐGr\{8 V k}ܒ.y=9>0i׽3/lTDxkV==0tH,atY.a+/֘'>ȏ <8TO v⑈袁8VY3{_Ť -}}=:5h zf~6۽tkVN|0(Dw?hTMpl-F 0Y w)hc !vRrff5FS0J m Lο}Ϛj/ށ^qWiV]ɝ2~S76ۍ?Ӈx&D/6G{RW dDQcK߭ر"{ cƿy/b r˓c\2b#[[]?98H|@l޼eLFE >nСdOٹ3߾ysm׮|G:2ư+%'n0inA40%Qi "aF`1r6{ޣ={-&|J+ˢʹBh2QnEl;s=߽XKSNx Zp y6Ϙޑ P6໅1g^GO[_n؆^> }nEۣO߬yӟ<^؛HXnEh\w݊D>l)rISLprvv[޾~}B1pm;J*Tyz'f$VŜDҟ쮺~WQװ*tE2 ydf3ӹ+~T4, {9Unw?"CץHpwWV;e i'&~mW OrIQ6(aUJH|ܮcGڭk~bIv2V?7]FC%&y S!IuIip)fAUW}H9nhH=bڵ'+,XP$ԩ}Zሟsܸ W,fΝe\nq.hݵ}{:2ŒaRiOV$XE"|%ۿD?{[GZ2FLCwP\@aq/8ꁉ/Tu~Z4@<7!~X,d Jpk )X7u "DY \Y^KoxyO  }}4$M⣏-ڰ!c>VAcZ?B4(ϠA)кkw!U%c8~'ylӯtGfw/~*X~QK~Q_?05u~!QJXU4{^Iھ4?ߙ*O?|VyEŝV|Pu&dH>lTFb*mQosw6מORgfRG%I@qXCW:q1Pex"y.niѣN'ӧA4n\;,+e]{m3w۷7\ɒ{2PЧM필#XOٸ [o]oOqc &!2~3g@6cFxi;Um5n,B[4/QF}2B!|WVQ>-lξ5g3@ ГvŲ_.[O"uIGo2 \w'4kuOk,WOpfeB# Q XE IDATSU p2N" Nv|,{;㎍E"X1[9-/w Vren#o՗u-t7vG.gH=&&W^(Gxu !Y}DHDimqH%R5`j4+q]%mg\={7o.EE֒ߊxsb+ު*2Lŗrs@ dz=ԣ~swA7|v:oosݮ]}UU:.h덼iq3/gwq]i6.}sj\%EjHy-8X7GZ;~(^lJ05&k O'(px~=;wn7Tr5B@_x`Ŧ3z/R8Ff{Vo_wOzC 퉠TV{cg]`_'?Q<Ntn͉uzᵣ'ӛOyDund2f&O,f} ׆CF읹571l٣Fج'|[PU)jQݩn_/]/_:"}P\._|tEMyi̊''޾g'Ӌ}^|03_7_板um;ǖ0W2xpZ0pOv}QL5. A!aBƅ4u]p]cCRLC1LSJ)&H2D]zWK|q'kpMqUD3)z9g=$ uH065%[ZP8FZΆ=(eZi@^+8 _#ЎEu1i<-THN~u?_Y<`ԶQE{t8J eܸ o4j!Cλ뚚ƙ3ϯשnM[N+_]U6;g$ ln1}Bc]s]*Wke$cQ񸙌ǹHd2uaHTsP)%H,$B`"PE !Q`F0R#}]6peu `CP$NbRrX5Qmuz$"Ѩ4cd"䬙}{y(" OBvZxI]hKTum3镟,|hOۯLtՇ?{Yk_tpA55j1o7GPP&L zy96#THԼ3{- :g>յp+jk=4"Bv {{kنw9kntö]ش5haSSBX-vJcqfSSt }5{svƿ8 Q[ctOp-nZ͂sh1H3&s@ٯ2rѡ:*WIp%$(Uʞ[w BkZ=Fۥ6Nzm뙵vma\1Leoo]JuZg/ӾPt?L@%GcgC{v8}djۑͱd*5'qduZ(n7fe)Yyyjn~#?7ב$sxMzK\]ܳ'2Y3MPUS$qpO]kj>^T-yrOoB63y{E]zGiVl.T8q6eʙIH3i]2NZ~pQ*bV1* VJBcB$I%UnƙaHNj_$(:69: !-!\0,QQJySB"%31cDCLQ.z~(Ydzr+þG/!)B q3А߷/xu$b!:c 4e:ℌ8tȲ֭ Xfy,f:F8]v?m-kzz4p{ {W45%[=9״)Sٺٹ[@R)""N'3I!PӴ]HX74  ɑ4MM)1BV#Ƭ?cX* F @2\Giu0 &Lr޾UbF1LAU =vanxNRU@@DJ&r$X}}0D)E1lx (A.ҥKxwݵr1ECES>m;s}u7>g5 V4 ^/Ӝ0튖|jC}( ʨ2K0?|Gra 4KB!SL$燛>CB9έX$"p:)J%AҶj )`0cP)!A(80 Jb cEDU)BɤhkhHjkꒇA=i<2)Ec0 A[oZ/OV{ I v Y#CQw|Ü ^_xpɒ% N AW^FMym-VV"#{v/pPsAyv%G&\K&MS]00M)us]<aJJ1)#BPj aL00kRb6H$;,  !DF#ujfuE#L*&ѨiiуdCs aÄB Bʹ4MSgHG1{8;$a08Gp;LwtkWoyreFSFៗM]utM"B YTzڻ9.ǡ-s^u:Bɓ4Mu]"%$S$)HsoxjIAYPFfApa "p)H s10#aB`L1#h' B sD$bFB!=j57kFk,fĴ :ȤeDLVMS3f hkp\߾qwӼ]}+7x ;,?46-3/I ?+C @;­1|x={lܺj*Ӧuirѭi5|\mqmG s|KN|_=}:2'b_jzSν/~??j d.~uI8U *K2&| {ߛ.qc@C|G*,tw=0, @ƍpG#\-D˖5ص+fʻvfWxq䨹7Ң"gњ5[,h"PW^mSK="DO%,N96 /XfmEMolp8Tޛ/\rn m}$Dᗙ1C;tڷW8*-B};e+4^~g@#6PRJLBv "M}_T,+)q8򜅁r~gxz`p`{MnX7ߴn7᯽'G*lܸ O<Εgѭ<P-kXbEccHs:iLhxj d %?;Tj:cmCA}O"tzn|y\8ViwPgG8'_ ~{1ÁE L&e$/"7}I DI]ƈ* qz<(9GgWrE1cܬaAtBP4Ioܝ-6Wik職u@V`ƈRo{Kۆ,RJgǍߐ\zin{1# ݉jF"Tm1$*wm~Y߇ovک'*;_h:q y\ARVa@ko|7A!p0B@ATU&ތ 99j~NZ{<,1D(B@(:ؘ1yމ+32+éqv`ʾrɒΟ;["dMxIVG*.7W[qͧ֯v8DN{"<teĈ Jt@JR c"G \"]z  ĘPz>L(4eiʈkwqG0mY=J5p\C9꽙$X IDATljNFC, Ëw*-O+KJC n7I ~TJ P%cY.1*%B)%A)&" juuuɽU[x}xJ/4GnRcz)\&R>F*Q\.>˾vW:֮m޸dI:ԩ~rJ9r(Xp:1Ǽ.q1UKb(DZj %%B R *!əlqG&=Z+uvg9]]<׌:ve<<-R{3KPِ dICR1~D*d!-<lc0խyyݯdggtGV q3ʮybU.EB BDDv)c*a u]$B!IMT8ITof s&#=hs#fd i^u/^>(.G}b~!1XV`45bEckaJV0"U_F&.kTyZqF %}GuusWW@JR"B"i@JU4 `PolhH:8pP&Q3l2pBq}iOW^.Nyر$w VrE>YboΨ&+g#pӍ#^{}VHeXʹteg+9|g`alI83MaKaHi)lPpM6 (S3Pbv`c3;Ds.[*6BʰIq:%L+HFm/k ƀ1>ces}2܁3%;0@"afa7 '"1YР55immzK<Σ)ٍ. CJϚ5 } UR#l^tQޠC/J$ mƬ֙$El؆P`i>˝ź{RpBHaWaK_YA#$BHΥ4n$\O&LrCׅLI$V(o)yD-gOLC*Q09||a|E!gv@wHPƘ Smi A` 8Xd5un6R40d0&SF9OPFO0@sd"Ѩni[A= V%1CuR!iJSJi I`N| Wxc1[ݠ0liV/zf$Avzu:7s57W߹]@Rt]dᰙhkcF,24<}Mq BX`)CTU-˗Sc UF '! Pl3sӈ\l@,0]`ނv9,<V'X4jDQ h$bb13aiJ=Ujpe$YJ'B18u],%/𡬯/++>=2{MS0ے}[v)>6q3&%9g$XZ&RShimÚ&dWv[/Hs!N D&W:(CA`(Xq8HJ7h)E̞SK6eL 0iBKuߐk! Y,S48B|6' LLSQʮ)WZ\lIR8R%u1)YVsyc̟?[NxeɴΗW88(;@&@Lѩ\u6vne"E)}TSqrS9][(S B3AKR>rۦ^X%_T1 jt}'}liH,MEӖlXr0uZ68.v*$WSWW^ŗ8eo~td? SOq Sǎkȥvh[ڹM4-95EOkǏ&qUz65D[>08ZߟLS'{6aw^v>}J&eW67kN'O' iԯS'JhԄNW\Q8R,׮m^}{hgJ nEOaxk̘&<LJزmI4ѩi@]dR  ͘Cek 8q[޵kΛo2qa IDATxy%Y'"r_իzh-Kzdnzifiz04i4Li n`0`aIm%B%[JU*JケE7d}*[>(ɓ%2߷x^iW+J{5W+ 8u'|{[Nw|_*bNvnM%{7}]SG>==Re߾$Nw<WowE[dk{v ;Ҿ[JpcC+|d+AK`*&#&NOL09 0<>ď}~(mϾ:X%ֹ6k9!B˸m͉k%d՗}oqmn_Ī쌞Dqd7>x{q \"JF, /Nukgd8wxto3Q/?;mSԁ=୯%UWu~+McTkj GS9vuwQ\Ԁa8ps<;f~h˽ Pb4IF? :s/}n\~$B Mk_o)巕w<;~(Wxoo[_1v= |?_ҡKMA*ٱcy/1~9wκT% Э+‘/_?{Z(Pw$3h&cj켝W&/R0ezƯ}v4 @Rmfb_񟷾o۟u^5Ҋ6#7#aՕ+9Gu'N25f`zw_ G) ,}WlzC|eE0ñcJIf/^h/gwI9!#H!1yMA{YSZ2վ4r>m( Vɿl_k ±Lǻ~g P0`4ͭjӆ׌qwL4 }{ӱ+;`)-ۊ!c]RNU wAxarYӄ$R 6^CvN^(M؋SOFK^;N"7i̋Kէv`|Yo'l| d~D-|%qDXzV*T0ޭIJ ޘx W[x ] 1uhIJ/|%o'ljA `7y "4FF$f@/p ~ϲ^>&uA"<56+O86A12[ D0QCajL 9o5M{w& cA21b:H)|DT mi.xgm]u1w_eݞ/R)P;_'"C^׎B${ O 37S_^~AJ4frDWN4@AhLprӛ9aI]#׀'`A' [!D%E$1 12ǿsk?.jv@0?h~~=J31Oɫ8cgo%њq  EPA~ׁ Z=x;VA @,&А Gw@\[:w`p6q!c_GSbk0ܜ-GJo{A{g?׎KN};@G[?{w|ws[>=_Gsכf6>~ {ARŹ @ @Ѿh4HTQD`d y=l IKJj 7-c-b9(ce{ww'.>.;>O߆l=y-0܃hm<Z|_]T8{ً~C_TAPgFmmmLcS& `N@G3 V ƪ١ss-#00evp.{H->,AzJ.ٟ7o~Cܒ>L،x wHsAl@~UqÉ<\ԉj%k"f1\mW^/e( ỳ .E4V0>l*Ϋ sE }!"`z x£D1א:dkc ?4<@^K BtC$*t}{WݲOpW%Q_ l`@Ҁ+J<@R'bE@av\dE1H}R)6xdu@WvX)Wǰ: |04.!^]2rR\n*JC/c& 0H bcplHVT_R۪$[pHB&-zb`.4%3[Zpq`kE38cpAǿhfL"$/*r,w8] 64vw 9F ,8nY Uye`I{64Mu?xAi𰂑7W~ipU`,@]<n0[46y F/#`!@BX˵88ۻ][c;v9u 0]T>`2蕃:3`cSap 6$E`sMދl>@zn/~K9KV갆٩q~pS-s|tp F[^31oYH@b(b%.asTUsE@/z0˵v!ļPB0G?~~鏂 cPB3F2TB"-O x=іRs^$̨`k%38z %ml%Nts*)t0}ɪc P%ՊI>NLF(2)$9FXsoߊoP_|Ư `LK^"ot+ 'vBl , pPХm$b\*@bG^E@q$ rݽK:y4xM tRJL 6)X ԊDP} `2QT"X:_umr"4W /_%)0DG2~(( |H^8uRO)Z0&@2)}fOh5cf}n0>| LaJQscVg%!@q^9"rui:P?p];ߧ;A=ksvMRzjEHvfea /),, (# }@BRm2?}L1v\⺫:L%CȲ%fe[@~IX}3W6 hˁ 6ppUt"GPB }NT>v߸4Eb7Atn8_`cN$b6[ۛ[ubt87^!@Yly#׈5A+U:꠴ L SP+D$9_(:;ŧ_>2L ]9|%$X7i~1[f,͡܃ýF13BRZ-mZ-a!ƛBH~n^a 1 g+75L c I u$>E=-CWe)BuFI(@ ]$(3t J/>ZHNtlH@D N {ښ6NmbT5fMcGbޖ[;{8lNL8&&''199v ?1fFcJI9.._`y%_޽{CtFvx{V|G;n l6133M6lVJp%ͪh4}FǏ'<~B`Be2DYWٺUU0x=e!=gM`ʬ.H|>@O]]HIO ݃ݿ)T1+.Gɰѭ-Foec~d/s͓:Mh4EEe]rKzsAk c RzXZZBEвbb,C>?O~\M`; D-LkƐa=Wz PSCPLb6kb ˂Z3cL. b.Cz r/ЏS" 3~PgFG޵F iӦM+!DJDw?[gfiy sE,ˠZ$>y|CaGhĄ8H@42ԯK+d!%la _1HJ T#$@T)@+t{CDЫ&w;G@wQI2* TAKJ[?Hs _}`.gPq9IC|Q|T6?rdGc<^&_0پAɉ rFCĿe,,, \4MBf!t5(cRRPZ#M)>s_kwx-6lKJ p Pq|cQA 6^Ss4F~W~h}BEJr'.l{(Z>n'Q☚&.}Z5bq$I( MF)2T{?nzvvHN(exk}A yvy{ @+4>P[$Ԓ )O1`f5`y[h˓tӏ/ L_s+_۝Nm6\ou s DYџ9R0DƖ-[011B5e&agjth4*A=FC >NƘ] PoVLSJ}icccE;0fAT$x! ޓas=\suakha BV%h e!CZb"b#$s47RnV8wmT75 ohfhVK̐;胋k⿾5֔R|GEشi uV4b\x,K| fffNp{JZ>c0JU 27vJp& IDATÙXKuvq]UeU1QQ[l$$ l3:Kʷ/_K{ù@po?~s{Xdx-q!z\@)58f k}kY5 Hڰ$}1Z50;0`O qrZtQ;1Qy0R4 A!)d -=k./˟w~$8g {TisyOÃSݦ(Zyiz}FkMLLl-kE%UcZ>oh!vBS3ą3 qY#ItVm` D@։Lɢ,&'=r=ן5jKM;3pn1n9lASb Jn'V=IŲlAbɗ){Zۓ;.ݥUi6R8T E> n‡7lx۶n]nhű i 4q,q7;hqẉRJi:p "l^ ,(ߺǶKb  4aX&J3t&b")_&s88N{Ĥ08E"KHu=q,ګ#7LLĝf4Mn1::F1:q0{~n3L RA1h44tcy%4Pk`aQSjW9_8)'XINOZ/Ƙc3 ղZkDp9|Ӎ?;۷,Z^\n=zLbXa_Q Ybbqxq*.;Y=_)A&U狒'G}NýO,z@LXvKsQ{׻_S>֟K$FWTEy Gek[SS{ӛ"n[u]a 2gǮPƥ}?gj5cyY)4QK72$ rJjhv$!hI&S\_k)׾Itn#[46lHW_}5A@6:WwÆ ;`n>rs%\VՀ=fA HEe9Ҭ9{1ǗI195Wx4TE+ï0b%3<4wl_ҼuSjݻ]ms7;vl<茌;vF1nTs} L.(TD X\Uꭨ&(t{9G9^5tTCT JCR^Y%ѵ*- FYa-qmaRbM f3?#?'F#hZbضmaYsuq\q3g;^'=`mF8(*k v 6\(* 4123Ia &j620O_MHH+ V(vø3.$7៍DqFFFM|X~ɘs9%qqbs&l݀mn i$IE}th?_|n{[6 ($ؘ$CL2f-`LaO{ { /W5=er9嵅g\@xttt_[m޼###TO9%}.\/QsB9zr?&%g6*(( GB\> Zq\ .a` pA̚0FY_ScHwdN][)|J @MNN^;66hT3|wP<7zd0ca%z~ϯfsu [i@k zp?t\uL<@ 1o B S,y+uQU8Kgvǯ㘃 0Q0 f8&}UYxDgS?f?136@F7&S߼7G&1@ 2`{_~v̀s '^4>>.RQ^^z=N߽+ \Ѷ3սg"$ںPְ ( \C?SG'hyRx@ <A@. <_A/?rĉ)rڙQ[fns ^u4綺dagw[Y{p sRUGuYр+F%+sh]њ}a2 ! ㏿0==}D*s2EQ%lkg[cLķaəanKx7iഢa:\pY\!r;|H ,>(2ZA(./@Pv/gsj.B2A[W^MLLq,R)'I2X-IXeY]?lA3NvAgmņNQw5`$zR`7^nX]r|'=HJlzEg %!s"nǙ^#bfO nvP1}|G]XX#aFRJbf,  sRJ1\%H;|='F0\uu.`mlRk~~3H3 v\xJ7 >{/88dg383QJQ]#0Ig}/x' yz"2( QyRda!iV~}_'0c%]?]N-+ad=ㆫg{,8MSz|jy|=aqӈ-`aX~O1\@`mE(1oפ!EQtؾ} R6ZVl8( zm'$1FCL5әV iX+z2gLp]:ebwmk.+<,˨qR{TNl<ƆIoL3DRx ^V/ r"J+)`ÊjKQ@Ddiit ʊڼuc X%:Rb߱;ork`VTS1 h`aO(뉻{{-8 /v[57?xӲyvϷ73ՑeiPKLT19ADDB4O4mn-yf v@!I^0U%ubAU6}dAdY,#ʵ4CHKNIpZĽ^~;B\Ø?_as `%~Ƿ@\m!VPIҀdb_⽾IFkcj9"eR+uzRzn~~,#UB,89l:[OG9J'#U0a'80Bb)Jɶ*HfyN֏w{otAd$si@B;V ?\Z{켗=AQh]9i!J8^%J ŏ+K853w]VEa*C:CAP})HVO+ge(IyΆ )iiRLGQ$ gi Ō?)$ R*^ GIooEފ9Eas~}3<׽/|ɓxhoqq!81=@/ p2FT py2HT,BƘ%Gg4BmhyD͂Y۳׽ͷ'''%<)_ɑ=#!K)UJ!KS$iIis ?4S>m[# c8)c K^WuMPSx=8Oœv`D@$dH+@aRZ4yn4M*[V1bB4? ^v5>VvslѨ/ 1np(BZ=+oie\uzFh@ Q, !1P<^ly?PcO{X1e۷O]v;[. hԈB߃{Hd0ҴOϟ#'daæl2)d" b}e |}_w}`Q9 @s!,6-@e+%_ "_ bѨ Q#:(2`@ľߙ޶mfK7mܾ}jtzl0Hh2 Z)yY 'M6wDĞ{qJ# Hl|) hdG1ғ fRy<{3J>JF$37zۼc`Pqѕԛzլ]*Ț@`K@w5ʩ9eU|G$&r@H-`$( ?.m1`&hS^qlvZN40}c!6üe #]ZYf%"K(~&"*TSldxhF4A$,ƒI59\?s"dzxD4h,.Й#:P!`Օ4w _{w)ߩપ@*J$1udw(@3LA`7K 8w @"D!@jE\ (ʓD2J̯$ɼ8z %yπ../Gh +I^ዹ9>I~+b.0\`{7OQ8JYh.tJ}~8>KfUk嗛É>p-;X*f0R$!0 L H| dMP'?$-PN@ `Chߙڅ B&PV0(T9 1Bk@RgJIK"+1@BGgOK4%ij% J'N_o7G[hdIA0 +'{cd(B@@1s/veRqKP%4h 1@~ .:@6^J4FQ?R1{ *# |Hm٧!B0Y yѓKWD/<NR2% 0GGGR0ƣ''<'_s$|yPA  T#9~խmdV)폾Zݺ(mHF@Z`de^^3xv'ƫY4jK WT$H @aPJ >;-M $P= ֎q# )0KS)ucۿ 09_.)GU Q@*"YyyM?=k= ˁn ,D=ÜG$o6jE4w ٍ.JbD*)Ӝ7&*Lo\v(0q.HqYU%n,y C)BY!EB B"%ؙâfL`HҸ<׹uցs030``j!_.:* B,q㇋oݼSra{g/_E!33D]RT}zqpQ'>T}≫Um˳ miFIDAT+Y{.io@[zI*]Lg0b:A&LoB m$EdecW?~p?7v]8d@;>@!VR $ih0,[ىQ#\֘B}6lE7^\C,ޗgc=BpM]SzDԁ ƁTaj8{h:d:@3l@MywCcۓoqXs )5j`l:/!^x7HMH 3L`d!S߁>`Mn_5J Hyv_# h3tY3G窱*h+h]L5t f}DԂ ^#`Eiܫ NPQɋ@)e&܅S1 aICB[G/6Ӵ,*p2PWPװD[8sܷT&H$\}HV;+;QV`@ζG%Sq@%C=`kbzYurL%iAXglɥdօ\]rZm% hzY߀]2rnn@̳xD7k^κӳ Ü ?:g;;3., ^G!&SrK!ɟ,@u)ٸe~^⡍k~߿%cawf,qTUϹiWk EqX3pA ]Zw (%@ HT3ߤM_SJBIξK#W݊vY[3Kߖ:jWVn331̠*iV6B*eٍNB jvRT,@4rYߵNz.`mjsORlݻ,_ wq57A0J 8omHZ6};/8O)ۤhӶ .ߴ~eJer kR.R..!zBIENDB`ukui-screensaver/src/assets/weather/62.png0000644000175000017500000005216614205074704017473 0ustar fengfengPNG  IHDR>a IDATxy%U.s"ƽys2kbFfAfjETDpBG[mOVvnmgyH)L" EQSAU5eM9gޛ7s#"nFF̬Z7'D$0RPvdžB@p3G0i) $6+ɥi͆!`Zbnϔih!}"@0$6fuh#`qQfM:~,f',/@u &jĈGЩEE t|JдB ܆\8,˅'%b!Il[9H*2]sUZfavɳ$oAֈ{qD}l70s찀@YX顒/$1 II[ZVc>NT`%-9& 4ADRBkA`7>k"͒UR!HPaW7 Bk@:=}(5hLa>xsi趌DŽ׽&B,4sȀAY b@M &i7R ŝ)X +pr:GD,(@ H0E=9 `1 f*$ }A9\׺\,xM f)5lG璢Y984~" Y(,QVPL2@@Jb(.jc*لňĊL#M<Π22 IR`C&BdPR2ƃ փkM QaHb8Eu{P6\3Tr("p f&f*jx2!iA:giD 4TJkYi Fb#5P!S3s !*s ABD2(`A!3B )΁f C Ќ0|!#^aYsXJ  h02b5e Z `H",iEÃ.yURQ2B,@}C'!P1aj5R +XFY֮]Â@ VPœeNz'L(A$83B\W̕vz(ji) ]4i[3kfJH)f Zۊ Qg  `H2$hqD@C0 -B׎>ԗ+VRL>oBӲ\hCxD`vo:H{%op}ޠ! b#qMfFCn.B)̀0U^Pi? eas[ȶyg.D=C3 J.}&O)Va_P fhPKcª7<78H2*-E 9y̦}2ّĂIH3xQߥZ1b"Ŝã`&( @l|$@jzd,:܆+e2qBc+"003̜[! .OS'@c.%7V V KБ1 fhE?'J]ysgfM)vO۪.f -h) yPD$C03\?m9{]υEm*]ןſl|-u S_ C,$A1^e+XGhB 9bqG@`hpJ3P#TJ3@ǙvRJL9&!X{ʜ*Ʌݟ-;o 9#fuZio3CT7_6w'!4?Yw޹3'o9STM+yˏܦE gXƙW Vi[?-ߚ9[=F04 "u{e4#4"yǸbID۸&G36A Z3!nW9 k".{rTRr$jۈDNdh-%[2j0*M g73w޶!wյǿ<0wryh^tX";gx?>B7tid +^r?,:g#ARLD &f&Z#Al5O#DfQlx#ߝ@`Y)@ifHDW:K7\xyǢ֗" A0E Ȋ1XDq\: ut1G%` h֓("ckpQ@Qp\(/ e(# Pᆏ0#=`Mݸwf|5ر]S Po!TKAHQ aF Mnz.?_:{ dH-xąmB$so=0l?m\Y!L :V8f_֊4 GLJHiQO_jx֑;ÖՍ33Xѽb ޘToO^*@NRD[ ) iDĤ IC0aqfbz|= /GRg1v@i|;^aјc)9iQ˦eͻ᠎pYk0 JpTYeydCVs T}+wCգaNN QБn%Ę)"O-G`R~ĩ: J1kYP1+(%u&&sTBBD y%]a`(MO26os14diX3 @bSX4Y ΙbyW@KQ$yZ1ErX"o#c~n˜ h>00f iVq'I4<"$ E !Nn5̤cK3^ #Fq'$X! '|z 6`ZZm46 !H0XG&d;zH@HB§xn:?aխoC] xǫ@y\X@B{*58c fKu`8-| HH b {J(UTeӆ- $)tq bߟ- `JtI*1 K s!\ oua!w}7 َr)@UmO9LAp| W~u0@`2D1FI]ԄV`x`F{gNv/D q֓0.q5@M4 @mIU&yA?N LWMM" AJ#gDY#,\2'$aF|'TPJ[ſ윁Y[ '#ۜbʤbtf Н"A\}ZGHغƀ 1Oaؖɓ 1>o)U UU.>2%I1͌0#$Hd42-NK[<'aւDN8J% NPAdmb%Hd aXjd¢4*0ИT23O.+@-z SarhPJ\ C._#X&4&FYm[iKÄe ̚TV9Uiܿ{}_ a $ g,@U0z(M Sh|I1PJEE0ō0*訓LUl"3U/@1!JmT̋ΘΘv*lj9w qf-`@ioE#Y#tJc!5#- @HH5YV.,8ټZj <z J EVT>& E( I NM@]v΀eJRNC&i\ 8(Q-h*Է`5_)EΣ-0}w? LH@(J ?RV٤hNƒ>H ) RΪ) )! 0HҐlUbCiPiᇚ}ODlna-A%Ux@ 3`h ^dn3@Eׂ7@YNH+xۻ֟<6t7zhLf8`͆n6 iE`Q:F?(1+ѱJ%c;1}Z=B!@wu"@IQ54d(Ei)ο퓍xf+GQ@/vI 3 C\ŨpD@ȄJS7wm/ٓ%S 9v͈Ƴu*fF\kĵ< ?xu`ƙ#-@Ek; 0OB3a$k񬕘%bq hb8 >ۉSQ7fIhKHi@j&mh*$eX+^mXc mi:vPc20/>AcXifBi8ĹԙMWdJx &"!SEEMbFsxT1a }\[ `pUu,$$UguFf<lJPHYpx4Fio\@!#EBJ֐ iF(iIN_mJ&fQ< U#lQ'z5kSć- ۿ_N1#P1KSҠ.M2oZ@OE<WRD cys:_A %LyH0,!/r4+ %Sa_4m)E!"  @P g xQ1idaPkdEq0XC0AXb3©fTsu"t4,L SKC&Ă8f%"VX8U&*Mɾ%W0f(gb) dIH(;K=nKܳQ†L򫆂xÊe_cQ<(89S( }{o6K"To9~"~Yǝyl`^ZE~qoz!,tW)I] $S9%tdZUMK>#ŠF3e~ E@/2uڮu-EN )"/sٗ€VZA~  <ӬʹuQLM1 !#@+nDZi0}eY9,9ۦvr6@jG|6 #!⑉<$92h .Rռ$ܒ5,GXd2:OXBBHAq]R($I?'W+h}ҥZsESSSDR>8Ir͆Cb1^i59ݞZ֮Ȃ k[.9AJܱc:::nG?#/JR@_WW7k}tʔ)uB'MD , 0`ƨNO:* R Bq?]'֞$K':ݾZ׺.[GcY.,HAđˮqA={$}s%tj.YCy{~QWW644s̙3AD0Mfyhx濖ՐJi0f5{aκ֧gJ@)Uyp]+ e}?عseYoq`If͚unX|>b[[[ɲjgMn3<σaCDDTՒZ9qinX9/ݶx4Ld4T*wꫯ~[oyG,ȵ-1M,|mk}f ˗&ڑ"Zv 4ֽkYέe@s<@`)WKBB9o޼pZjg}38BN0lnkiiH|,˪_A!j=xO| VQ?^|jZ=],)FD, G%xcިFhE2Ӓ륔0MeBXfU_-ӘBZ!ۦ#jizZ'R*I>#SP຺:.X~gLtDD ȥMxrNc!$afzk Hڛ'}}ZصΫv~Y0dUiض ۶P(ibڴiX,~nhD@a1ED ) .kbZQB{ IDAT1ϚrKQ#R eYyɒ%K,:)ݱ0ރ'13'f>`Y`ԲَȚZbZxiӘԕ0{H}HGZ|d,7 ֽ#adYI)Ucc#r)&!ۑ:9Fwc5ApGUY Enj!֓Ǫk<]oۜ-c] ,Ku~&GBrX`iuT/@DpcǎP(R=#T5ђjx#fZ_7d;:+]7[Oj OuZ.3dϊp,---sv„D@\Is޽{˭usBP_5;~:kMg5?=|˴'&Dz#@} gX|(]oص,Tڒh>bA)54|x3'pٮj qy49-c=X DbZ N8|-a$L'-A @͑tǺ_VsYl}Y9`mffض3MN)5h"eBf>[z_/sNJiRR}}}57GO iAsi8^c!oM?S-ג~@-HD km#}M-K&"8y(cW0r2a߾}/?3ַ_.i2 T]A$eMjR&"{i_kPqH6H kE Z2zOHM?Gv_c}0ffk8 @\.ǛX,"TNҬYP*""4G æ&k ?ͲӾ= 2G)4H"CV Y~ +ج09mjl}: Yc(0ra q1CJZ'3 '|"^U"Q51m?,KD1QY=ovlz=RW6sYˍZڞJqrG{'?ٳgBhc@Š`wޝM]h RAd/ԊՓNNDH h\{ZhiiL4jWδfAp$LR:eqO]]]b?T*Dph&.ZQCkӵu]](D>g۶aY!.!`Y?Q' Z<@MRޟ/Fiԓ$Y%۵PϺXJs$JZ!6lذ{+<㦃'f~]]]]W_}[f̘a+ l&۶9x! ejiLZk"z҂OHB5cZf@kJ>Au'x @$#4 !lMj ID_}a:9ˑR. yMYyx?Wv]5/_pD.p@BV1 BADyq6l/sppP`Y%x x2Y;îyaJ)Jtּ,j &Ydޏ 7 |iޗXtqT*8{m]]]/" ᇉa -EǿS{;= TDdY*z6o޼~կlܸsϞ=kA`i) CRJdq]\e?(C40hx9/QGZJOdD kk%x?}teT*T*3vۋO<>]0,`̙‡;+ؙ1C|xg!ob׎Uo:x[*c#" ;e˖l4ͺƆBPW,iDDgyͫwG۶-tfYwIZ!V"%~$Pˏ{ڬKKr-e}}R)`_Q YDko,3+XuLG>䙳Yx \"1#YC((((? KmF p ZksΌ^HLi0$pڙ5Yԓ -uy|sreIf[È!|#ol8r=SZk-Xk=QoܙAȜWL*;0{- _)cfR 7o~:s]T*B;j]v?=—iB,'qN$,*4j>3Gi3gA+s Iqw߽;M=q׸ R*x=n8 9Trh IƵBD33^ f.Y X^WWK(Jk-8z)㎥MӬ60듓sړ MH$Xu4m\jkE` @AP~~ǻOJ)Jbx `t&~`d,ў'_#$ `"i!Rb(K_s 4r] Іaȧ~;ԩ.]:Μ9mmmzrJ!u'|UV<+0/^&6/y",M7d;~&agoXAurWX'|iӦ͚7oqs̙>!o۶$B6F___y޽wرsΝ8p3H ===+Wܹr&O1k֬93gΜ1rar}:02W<wٹaŊ9۶[[ZE۶iRJҞ9 JqIqGGT uյks=' BP(-˲-˒ajr\vg( XB[kqaoƈLOM@di?HKv%akx``?HχG@!'>|NKpˎ5g={P?@Bh|F <'b;r8AX=z&8-Mbҍ9{\8ej$mIr*vt&hO'rD:犷odsϠxgKT$U?hSzSsIϮ֡Ԟ4c$,@h.nR]CF>/ %ffee $BBgdi8ѓ<9a .釮u8PB̜ݦzD}>Rطw PH&-(MYN=~Ug Ҕf[)Һ^"̣AVC 0ϻt%[Ƽoj'H1X&5w?:Sÿ{bkZŢ!L36Z얗 qQ9\R !׃v74w]w\iYPoQCcS+3'禗ZSuvNsGzL:4mKrhhl `Ǻvy"Oz8d!m Diǘ4\C@/;S oY拗'O9x1?&O# ǦWǕ GOLCbuũgMc^J!8xUvѴ\v%W_={~޷_Js>'`TB |!Z S钿}gڻ_PTP/i? fb}-OzM#o)Se xhpk\~'z_䮃K9W^;oE ͜-<~Ҭ_E_?a)۷絻jGave[3mR:_(M=]g^xRS9Cah[ !P.Y0= )kBpv!8رũsl`ullveQBoT|d/DdXw>"Mr4-Omn`0P,кR|\4Ru/ݺE/D˗T˒$ۄ>۽v-t vk}wnټ^zϝ7ƫ硝¿:8+JP L~U zw}b޼KFy r }O@夙z&y:_ضOƖ8YКa+%% Qg~=vv VQ.IkڊxtӾ|gϝT8].,e`˳vvž5k~5l߾k ݷ%'M~}/61rc-bb{k *(:n؃p`^熗J[Kuuz\'^<(o.tϴ~W-3\vuXNMRZZ| wy\Dwwȴ sܵs8 ܷopW׺]]J%{ar_]ΝϽzK}2l$ 3߷omVW9<@0Pz/V/ 8{@eRW(o?ŋIV۽gV's| ?:?>+a7!D}@{Έ=}LNbu?G2vTX K:@BL;m:GPog,ӚaHO?Zt7~so@א!kpFI{{GSyg 1_|ʱ 0վWn!ʷ1RRk罺0o};o0Ob|4p~ݛu6ڳgZ|Dv|<]fVPAY#*qZy5_nefo30w_Q% X9a%N>qhd|=lOd Ww +J+WkC_*bDJ:C.921iJgeUT* =bf?j'>qۅ~'}'MԕW >``!Y\[xj@{v<7.xyբ^׹c=w<`'| Ja  4`;>?sҌw6V.G78L?On>o{g_Eu93s]rsaS( ER./Z}}[WK}ؾ nViՂX@Iea Y !!ܛ3sNH^BRPڷr3gf99YʕmI⑭H(>8xdw'&JvX\ŷ]H=Ōt6lRBhjSWs^/oy" ]!;5Pn4/g} &0;ai '-s;`1;To_o[i]^=?xѦT]d (Fm!h +}7=$s-E LWήs6˲JUՂCIEjR%QtF|:I@F9Z@iت~lFl.:$A&lyW#%yb-iCʶ\[iq GR ͘9^sqӿŹ7@p/*X4+;9 Yj R|+p.oTr20F8⁀'1D#Rp9< 68ps:{q"@c9軋N4%I%©brȩ0]O 37a$b*`ee'F SnqYW<>(޹`ې9ƇD~ CCҐfIc'iH^r}zzҺӓ67vMC3 =yU_}$bQf禰Av>4?)&nIIǭOF1M$a) ߵ@^%[vطgv9iKǎO:X饥Ǵo-oāmݱe3 t3@7yנ,+/?]5 Óh #47o-ܩ9k`Ly%ouM [MFr i!Z[XS֝U>0[a й.+%G:Oz{7r 6W,&1hn.s΍HJH{po[)@(Q;mxoFrc-CP_]W'U<<{OMf^O)iҘeu*^[T]?t5;qF~XN0%*4>p993i&#&A*oUs?3hIV^fQ pE@QLٱL+}. D"MU_߱`D.wC($ d%w̚gOl@S-\d#ADYieXW yyChI @XYQ_$\PzU]ߘ:\( `j 3f w׶dey7Hѩԩ\ίԮ,d0456$QX1ӟ?avɋa4x9kK9vvb#6TH8]-u ~8;9úu/8NC~җ/suK7%y6DZz,V9GhDc@"85FJhM.WX7wg\_Qj1I׎n[2 dĢ Oܻv4T@$QZKK޷uy"5#eU+|V@Yԗ-۞{m/܏(8^O5mO+Cڙ83Zd2 E!z-{\.k.UPhO 1ӡX'L?k(I2Y%ɢ ]CᤤtoVr뒇QZ\S1X3l$wn<.uLe @GVL}3/ԏ>ꦱe1lvdɩFT7;klHޫi[T٠.w,B[}jXG n1^=wtN}XLyCxvn*6"3E<.YJN $S|,?跮iz42*Jh +qIOZX٘?x9]zLS}1Рq-Y2d>f{|vٳ撃oV}~͐aVgܽHj4yP =9#g_cVnƪs$޽$%4iµpY?|md{)>͝GkFDqEo+NAmQ*wi,p@!IXA,+_{lDYDJm6@<<`d_,i/sk/yik~qshUQ{fEH=IȲ$/ssPB :ƅs /{Z(0ӞM(>*j&D9ߚ"hӫ% ) |BUOqH-լ."I4$n[X&oZ&4M§/z؟˚VNu5bP,2QdD#v;t@ES2IGUpa:cj)jq5l(:tC\1c&l.-=\PUU^_/0fQ̸^u15d4*k"]Up a[t|'JB4WM&7Pk]{9ˑoIENDB`ukui-screensaver/src/assets/weather/33.png0000644000175000017500000003376414205074704017474 0ustar fengfengPNG  IHDR>a IDATx}yys("R؎/6kVi1H4qm PmVFil+N؈;孲,kDI!E̝qw7K#E<}޹}o}97ƍqc7ƍqc7ƍqc7ƍqc_ j4.U?`@ct}  :??4LckRV)e ,v rAu݌x^G*?RZC[kVJ)(5|k-୵j֚4uJ fݟFq]|=c?sݞR ɲLc4**jjA8@ "MSi80 `0@jyV)q[w}q~ g~tyyߜ9s[kjYYcyjhhZjVRbLx5] ݵky]q'J)Zok.Fcq/y/cX܁RKܟzSJ4˲`jj8pj0ș^^ޮ^ ]y+ͿA^+kPJyY%o|կKp@pHw}]z_z,2˖-;T8V${ǿ8Uq ྒ$9Kˆ5QJH+B#9ZJ|GEzJ}>uԉ~]U\K}N c]v}) 8-92?O@S`M@JwZ(Fk-"a*z6I/ݻ߷՗^z$%Vz/t]}eg{n%2aewi 8v/K e$2nF ] q쎝`0ZZۼ[{鿙?H] ~Skm,nV{-`P04r ?P0Ӄ~i{x`Tj2yGq>a0d,y^N~wΓ'O޿UJv7N#9 Ͳ߳gݳgt'$n2Ma%n y2#'AQN)e E}Faż*6ݮ j%&>O pMPȃOLL2$i۷oW*,Q-5fQ`ZdM5-PΝ;}DQ`,K`0@C+qk[QJ*c 8i4lٲek!8?~Xk 6~] cl\9/ #sqe/1 I,//caaΝҒT7yh3;"cXkپ<~?ݸq!k'N|/kF]-;y{zFku}]w!/!t\|)]s?F2rM9$AqtyHDW\_ KN"~1SH);*gm~^x`yyyMf~~鯔RհڻmPԌ2{7RqY>7W.t:={gϞ-A\e,O"݋Rz=t](\#9kLt@c˖-~b\q<PC޾}Oqiرn޼Yi"bieGF(A`eSrN-y~e7Pҽ-&&RV.#8FEEQ4Z[<;}o]Z`gϞCy{[c1ợ˛!m\)Wn(^_%XZZr?rѯrLqYto߾}?~7 ,cc*_Ѕȝ Er{`qy.֎`!!ժNnDZu.h^8ͬ앃I[jd<*Q lV4۶m{7'O>˴W ~;,ll7:ɛmQVgb0 8o1VV#s%(\xJ c%Lo(R>w޴P(z]@;ɓ' ^`\ Tdݺuoݺy7l`k*q%1CJ-p9ܜVcjFSi~EKX]]u'VVV <'Y!,sg9Z/3Ɍ,ˬy*"k׮7v0j(h+_ym ޿{kZA7lؠɖ8ʂ.s ś2;77(y}@!" nap~!5XiZ;)g80 udabff333v֢hlx$QtY޺k׮0 /IRշmh4,j˖-`Tb5(?e0;2;M锑ъrͲ \6ͦD.7tJ)_%0 dIf1GeYٓO>:.\@/}orle Oj~)ٳgQTP\/Q2WOӴ'p9,//'1 |hү2-͒) @ϻ@ʩL4`es7@5su$RVsE*nwl},..:pzBQ1X&yP*JĄaذaí Gr5c|> 3 C* z\_&vkhjo#F 7Rf QV_F A&[z@\F35T?0~!٬=rʲ lJx9jbcJ |Ka˒tA`eei9?ij|Aks,l6ZT!O  ;z>HqnOpINT9E Xn-9HSKBKvUUJTMMMmPpR^*F1ST&Vk0,;S2,S@J㴍朂nE6a|h4M](RXA8`Gb08@0 KT+0ƨ jևa {i"p)PT*ua61Fky2lL%oEV+kx%5+}^nCN&Sӵnj9 j5e9xF|i?^}l_GVsg" e(jSjur0 l6'RɈ2%OyKvRʜFKp{Y*1IK2Z4ٝL` DW}a8m6ߚb*Xk:OZkmeJF"j2-dFJ~2Q,,x${^$L9z, {x2a-SVf\f32ЪѲB0\{Wev, X`|ReVk1?Ԝ)&@!Xb#5Z^XeEQD +ӗ§EJ.JVrv% mq̰yE\R. ;Fڿ&<.oiii9ce,tKV>1I8HƌJ!Wa@E7"swI&gNh jrs$`d-D eRlzPQEN^$kmy^ Tej8CCG@'e2gUV]??Ei82fU biH$1J&AZ;TK3^31:jE]5s:bESSS3i4MS2 A`@P(D edNPPXLŘ"y dI r&UjYF_2.ð,2+++ t$/InEƘiKLP,@Mr5MΠ)kvJckHZEuE^ZlpLB2KH_/ 5p) -*tIZ--//q|] ;7&a)4JEFeO8\YA|,J"%L)"4M,,V-6$+2!HkH}IЕ,{^C@ɓ$*XwfΞ={\-JKF3\xCwٲ Gĉ\HكdL-,,IүFBB$UDLvXL)*9&P^;3[ IwEi$Q9=rM@Zk =77LJ)16MSŋ%M#Q 3e3v; Nǔ¤O&z\P111F 6}HO%YW FOaw FYHZkuǏ6IDATScزeRP@x̙c^WTZ|]&=yђs'VQ{@r ?lt:.|Ҳ$}qh!т!^yxV{Z8j9),l׳Zk}ܹΜ9b.25ON ,AaI /ܞS 3^oj\ŃSKg9t]aeextG\UTҼVފI*MS}玦iQX*Gwر/c]،N%A@RCW@H:\@a_~QsŐ)z=}yy<ʪ"&5T xL^;3|EZTI#G|ÞPB^c >v򚳦eˋ+D7ѳ\n%2סS-?cy7us㲬Q0;;RIm\,1<D`4)d`$BIV eL+ZO?8?2.8.W {ܹs|L2J'^ ȅNgTǏƟ̲(| \4iR& AˆœVAOL&&& .DԔ1Xp;dC"Jv1J,2,K"Hk핔 5_ԓO> kZk/5O2j-t]墒\X]]u ͣ\ TV%i:\Iq!Գ,0<fv<ڛqh1|&-#=ϳY,˼̰԰.0Z,GY Ɖ'?}s7oޕZ{@q5BH 0RA l4쥗Ţ(촙@F///?(s9YBD3Z1z>jآ:˛C(CVy䑯aV*ft @Sz&H7CJ 3t5YX㮬sI4Mv|EUSCҋF*"յQY k_aN[.+g*>?,---aXL(@`R2H^\-kZ nnMsԔÛKLYvL9W dT1 VB2&bA$nDZ P?8O|@ˡ_qY%uRjј޿mI+/9f 4=de| '''155v/HeW$cz^X@JZ3!Y>ZDZ@Z9#xt&Ib}}}ɓO~Tz pE]\2ZkcÇ4??yVI yCFƒ4lbaUh4\cNOO;ƻy$jGƎM)DI0 ð'{ܽa_ʲj5}ȑ|౔:E.{90y!_RJw:Sr>gRc-h \KnǛG!! (7!vh\/AkVm(h,Pl\A/OX 2e'9;n0VkmY_Ƙ{ch_A<_|mVn5iސrM:YHaM0sY'RkYZ;`4MLOOüMfX~= 1% .LUʉ%2u WaS~(zȧ?0KOpU 44Mi|`9vKDc[o}uu5j*nE@$e/,Yְ&:* fgg+rIXSf$jչҺ8 ᗵ_솃ܞ˲iZc?:qSyH.j\)xI xJډ'ݸqٍVج!jȌAڳb(9oELh*{i!Xxjp&qDݹ5L/ߏ;wq6\v:ťj6n]MONo>7G7jN$ &&&0==cݺu1,im3M/4I8UER~~0MK|bȕ@N>g4`0ɹw]ZmmVTT\+ҧˬ(b6M3 6I5 yީS?яN3|I\@xN!---}w0ZMU*!44,(IKKK8{l/o8Y=CjcǨ똜t'$0I?N5 x8RJEQگ>VCj?a$Kz\ pgd`DjNzZ߿o$Yȱ2X}<;gFx-*Pe[V!t:XYYq{vIS/WrЅa܄f-)k}f4UQPc؟~~OE\XGcgy &w޽3}yRb) fMimʬL6,sB֦n;k5uBS9YLI }1qA}_W־1B—X٨ "O?Xј޹s8"F%B+ 0tTK_. E$P9 (.#S>iJ` +|*"y;x1w> .k$Rȑ#V޽{w&Ib1J c̯%aD?+)Vjnrm2$j099 Z&hQ~$g/ig ¿eZ(-<?/M.|KPB@SO=1ݹ,t6r-FA^TJ[ijPpC.^AUVH~lNJ(28}c~EktW9'sɦc-CrRg}޽{{F j i&3j+l ҷ,}${at> W#ȗyK7(2Z͛ʯ}/S?isc- RJ'O|_ؽ{1&SD3_h[O.1E eLm?5oۮi]lIk枿 6^ no~'~SG}: ʚϔ/:.<ƁJܣ>7|ͳYkT*6g-+Cdt<DhfL j8SOٖU6 .45 >j>;\f?Ig*c$m4މ'V~~|3c2)FB,Wq,+! >vӏ?3SSS6mZ3cY(;`o0`R%] 0F}%b9euDQd 1>OO"+5_ _}Wl9+orEah`xjBT'5ozӛy;oy*z}A"(#E4\\ER 1v6yja迴a o'?/?Cǐ> ReG/MP8U APfoo>455UK&|@-88(K`'Q5y晅~[Y㼡C p>ٳ&~,=Ɓ(b0gɍo}[tС7_[+ +3L 8 L B c٬Aժ~>o_NEagS.)k1 | P(Rb=kZwm߾&>J6I:.8`BN 8BHk(myajZGy؃>$I15H,|W]̵J(A@k@T;(BTLkسgϮ~߾}ggg'H5b M(rP(Z1*z;vO_ѣ17R|;Z$ˀBCG.\ A#EPȧW]vmݻwdž ֵ@#GcR:RY]\\?>#<?wȑ1KAJ^jU>pcF%%Fnì"PJU?9fgggnݺi۶m7o<;;;njjYVCJG\,LߏWO8q?}S=FB6I%M:}{yS4ڿx5Q8 Rzq{WJJ)P$J|jf111lZVUo45J1YYqW:d{԰5ߦv4U.R &$ŌW< [ļxvyeR(5pUNkm N^5ƫ `,#i^R%ð-Mwx|.zm7Җ\G" ?5>) >!FfK`/ ߛ~YˠPwy(k"޹Es5)8 l*˳ ("02 [BdIaJ_>N˂_3Nrsi/-J@ ,_ [7WpH p HW%x s\ʚ=K^rkZ9&<1=6b]@y\ PJeZ4e, q9` Ҽa=3p^¸i$~p.6'#xu/t9^c\i)bc(kLr0`8E-==| Ƹ1nƸ1CCҲ}IENDB`ukui-screensaver/src/assets/weather/58.png0000644000175000017500000003546414205074704017502 0ustar fengfengPNG  IHDR>a IDATxwŕ6VuqMЌr` b kp5^wl/w5g#$Q$$F8A3pgnTqjZ}'h$!֜禾uT=E:;VH|޶m[}<I$ucD"444C'  fzlݺu۷3t۶k ! R?s9'l?}WM$'x▦ 8%!! 2EQ!(BEPUB!Bm۰, mqrD P8D֜{?׸}aÆs-[veYWTT 2]יp FQ\\L" TUcpe0 d2R)L&NamٶMhWW~w5|G* @z[lϪ*RZZjNt]#!CQ眃ʟW۶a$8H0MٶMa-W_}97W Ds=ݽ{-, P(΋Q__O*++  /ī俷, T dYXeR)#}5\{%,_)N$(T*u}mm H0Ǐ' y$>̗ .i$ R)id2n,1MӶ,K촯꿹W"qa0]>⤦s}rߪ5t]׃ F|ڴi:Tg,si#L4MX5 ir0mcr-7oގ EnWD@<\~&MHqq15k)..c,xAԾ|8o&l>R!sLl;t'[VVu@III{YYӧ` BO}jllT0 Ϟ=DQ0@)|4lc, ===H$pi˲i_$W0ɀmR3 +//w@"__q(MDH,Coo:V__ϛ?nںC8 M5k֕hjfkC|/"Y-97J 3eeeNo> mkAۋx<)4Lj{/~5;w|ڴi8(5Mi8~b  ($[/))AMMM]{~6ߛj 8"| B)R eeeVww)=_/I+++gsΉ(Tu8HHxe;> BH޷Ppy\p3„MpaII 2%}]wNO)xIIɔH$R9gs"B0 1ᝮBK,_&5vB B '1`0dgSӱ*'N4p8ͫMZV~`B m"B?ι(u(祋JAsFO?j)/^C(Eܱc->~Ik BH)ܲ,咮<(@Wh@NVVTT?GW1>7z 1yپ}3gv%TIJiq}}\EQh"Դe!#~6$s z~G}^ƋTΑA$"ضmVl۶h;|pX%V]]ɫjܹs/,)ha躞_JiȶA&ǫY(tyJhy#B(N;͛7wLyѸKt"%+^gɑp$z4 1m|B'!a8ڵk!];sq4f,C8fhT)--#b`! _ԇ2e_BJ}!Gw~}$M.dXMMM3M39>oii)BJKKh4щ'ӧM|fAk&l d F`CI&oQD9EEEᦦx<9k @)]8yUUUf(0gL8#392*!;T~+3F,KG+Ư{G0!غu"*8@'RUUUF0 TUU磪Bx~v  g*F*#UGB&qUH$ Uwvv]yŏ?xpP0iP}˖-ՙ@@I,!dPp" < /#>~4/xDQaHRHR" 5J1JiG4Y[[nĉ+= OoL5 &Pb1:|^^^NEG8x~ 1 #H2|ޚעx0 n,\Jf666>O~raccX~2y睷+RjGQuƌ|ҤIs>w/"={}#ڐ葳#ў/ǫ4\j6p7ZP2 C68q}7x]28F` xMM_W^ <qaΜ9PvOdۼ'$y "oez: l`pl0#_wՅt:u>h >gΜoQ]׭p8?>{m׉$n 82:@oX%H9z*|4>PΡ7Yl&a]y(䩫W^hѢp b )!z޼yWuoJii)/++#|=}n({ZDҨP>} s PO+z 9$rw4M#iiiG1`$P83f̸0n<6ozs/+Tyd*{ ߽y{YCɦ >ې m@up GjS. x("b ~BL*޵ &9 "1G(z;TCwfMIgNSVZ0s0J 07FPJiy$)<޾Р )[7QHRT~#P}*q/p$On]0 <+X*))9{{i @GUU X/ +!Կ eM ׏dBTFޓB9 ? ׻0~Z<`~4>Ϥf38Eǡy*49(J$lbΜ9!p6^.x;H{տwco(y`R_?y30_Oy I6uLӤ˗/_o߾(,(:cLG:!$gϞ`pɓ+ pc@~ݛe 勁srsvCtX^xG|b3l0@ C|%9g3 ĝ AZSSvM&LP)X!f @f,2es j(`feyMq^Wn .? nwC2 g~ /&+9Wq!:OۚL&Í l6beyn@»sDܯ]ff{ Ծe.2zaL&CRcYc-۷oKog9l*s 91@ٽ{wSSS@ PYRRRL!nǘSlfe{%6dݫ =6Pe_z#a AjPre2L&cE8NA)͌YmP]MHP`<?[o8N8 N !Ķm7L&3 wJD<={dr7!D4vKhp8A[eMCz#9C%K<^TTD"pw`'N@@/^xl:@^( {u@2.$2Զm"4 2=GpS9immŒ%KXtpL:{Y0!˳!0-b˼tie){} >-.ߺw[e v 00 G,+}핕***-r s_:y8Y^/'JL&+uif<:G!xNJ"CWEijjcB  [4U~g?uq%C6ž]xl~_DZrI#Du( .s9X,J)sB!:&d7Y#)lʇNbhtEQdi'"# ! `^ׯot<ofuh4iԶm'Z}}}jnnܒdfG)`Cj@˿O?+/f #9d.[Mɡ SrYͼ .={h4* oKLm\mSsOݵkׁP(?~|~^4ޓP(!p8^?ҥK7YfӍ8?L4 kE 6{Mk֬Y׷@H0D xc,kFsB 1s.Lk9՟&d92)tj8p82Jov(:uy/n.@J#pw}۷oʕ++'׌IDATO<}ԩˋB$G СC}oݵkW޽{wR/AqF"'NPW]]]ZRRG"rZ0 ܲe[nmp&LC A#+pI(Za'!I ?b&ঢ়y9\|隫.DWUUCKksK/O6Tނ94mԹmmm׬^IP 9 !rpҒH$ AMJ)e14L&c$ɁC9ݮ}rH;SUXIIIi4-F!M4qD"1 #5IUUM+mpfu)1wLe9($vgpvrߏƆ9  sO=pɼsnx_n{kͯ zq<fS,r "(I #MNq2 $+.T.0XRkҕ:8 gsWvN=%5 lܴGUg-8 y=0BG"F)@BFLG={{WXq)I%q,*M Es+\ffҧEџHjuV̚`7~J p\&YFBtMJ rpm0W5 rpܶ/~﫟Bld2((Onӝ}zMqyq?&\|(-b B>K  @ bFի;ӼRB  gܲדT"A8pDK)49M %OQ0ʯBb:S sU$@3*r$kmjp]NN=aXh c͙5h٧o{? gYmYN:7Э[lx}2!j \YjΝ;4 xtu___Xζ9gE0Ӷntط@sރ Ԛ0E T(6A|9P4>Ze5<u+Dee4MCWW4+*.%繤t/_lZcLBgwY~q,a0m ۶x뮫/^7nڃj_%O.ްwK+r*/)MYP0<r בR:Xduέ۫ōW\qNחCY/lqyi4lB!( Ҵu߾7SEQ][O]_^S{ V*iB/³ׯ[[ۗQd!Xx(9ؾ_Et2ΤS4A)5X549Lq?1X @=[O?pǶy0Ӧ^8^^! &w7q '[EE{!|}wvmY"I>Br'BX,Ɠm|o~Q?Fp$4L:]IE}AϙgoH3(Yy媒@/ -:shiy 'L EQ\tSiܲm1ƪbQ οWk$DP8T;BPJMX4ӿ{Z.4uD۶u7f4-J&8o?]X3UTVPŲQt,0 Z_^^4Ms8ymZ~!:#Tucvs%/Tq ?qv9kkSO?t6r89O۶*-)YIJBȡ.RpH3.\hA!,Ƙ9sYi4ZWWZKLi'-omW5%S)ӫ{m>Dr ;0xOO;#{ B&7U }o篼ܱLӲ,ej8tX 's&R]*&\O{\x9t sGqSJ&i7n܎o$G_LX7LZi*im=?Db|C9#xd 9n\esjm6㚮Scs^ IzǪǍ;; k0i~,~񕰭^ e_CO>lfș ---CܷN$:-)(#Ҟ.+-- 3 t,x3^wOjlsh+$be#iuH4øj鄉EJ6iӲzl.?,H־흛z|O?=[z4 9\ܞF(mJҌeYЗAtU/rU8wvv]q۽Gbrg *oڄb3d3Y2mULrBm߷g~(j;T*504e:XL&\ ~穯]Ϝ:eYN?X ~xG9oWWQXQQ.wmɴ(E@y0Y!d230DZTUU5ɼ `9re>§NJ_~y-!$9Y|yl|, ʵ맿q/sv< G\:4ͲҲ2^]UE,dPBQ\g)"Sh޽4m^CUxvygf9N&3;BymsyzRjem:tf>q5P8ொ"|yigisxҲ߈'ɹUP˖y;cdRW^EC|qկOE"ؐdS=Bi!]{vAYim} _q4jnbKYEՕU7LШ[W^}m3Oܬ_ e]X[Uɺ@ PUU]YZZYO{'P L`7|{0c,pݞSonn G,4Qd2USVVS _=F~&Ԛl>X ˶478"kϳ>Ϟ{YSSvhx{w_bEvqH *yz؛=){{{T?m>+.S&kkx"1K/WWlԿ͞=`gg)reqVcg׎FsK** qPyqWenIzX6ɥnkIUi陙l6F|7N\ꔿ)_]ɲX5MN_{W?OSSS/%7|Cg9PJ7pb좇z\Ϳ+' SW< 8kҚƭ^V|3 yqI F"(JSɤn= (9ye;::ްn#4reMY-e`#F6txk.PSc&:.{z& R{iw}:!RJP~ปl޹̴ 'Mh sα>SgLos Asӏ0۬(J1:8f tm﬙3O۶}ETVUs,ˈwv0=e[mPwʋ]pH&xmKۿ}FMp:"o!W WIih *>Xǰ Pķ?v65)駞bR/#7#{] i1;cx{~K.8C<֢KrV( hL5i/>xTUU5E I+Qh=?  u>gW6n1r +hIEVUW8H,ਪm{zhT%Z ̱ ,V{W}!N'x˞=,[^Ғհ, k;:j>Pyͭ555r`'m `F&ywx\#xc3_7k/vw,Ο/%'N[ǃ+//'奥\u5ޚnqR8L&ȅrhȘO_|n֤{6qӼ{Y7u>Pf0'LqviQQ(%in;H뮧{:;CS' F^uYe;]B-2Mf XI!nxi*EUeeeD2yyMQxIK'cD$  a<Jn|u`(ͤS 3M*9c~d8g߁]>.vwL6$ 'ڻ˻zE>ׯ UUd{{:l6 C .>VtRiP:@g_L:=H$49P;l(_[xĔN @w=(mpV\hq2̶gLH(EEE0YZVZtܣ{zB6s;vN:UQ[:vkQVVƋ9'T񞞝c`0eYTwg6'WUc RPgO^$cߜ~?+e2e?3xǒN=k}lntzt *ƈf>p@f#τRj&&0?f.`ǎ `̤i$5M d$~=L~Ҭ:i40 *c,9)Lxhtt^qeLf#>p#NIENDB`ukui-screensaver/src/assets/weather/7.png0000644000175000017500000002417314205074704017407 0ustar fengfengPNG  IHDR>a IDATx}y%Wy{f_43h$ !cb!1IaC`\! qLX.@L$$ȣmFHh4[w>_'iy3ܯsη} h@Ѐ4 h@Ѐ4 h@Ѐ4=eɖ+lM)w7O Lh 18lzΊw+,'l+Vp"wO$-璹)f(3?|8zb8[0?AY]TR+Y8!HOȴ*YG_g3UzLTw=6"ׯi '<_ł2m/vw2]8x}_m ya7PU!\vi2F515z :FmPPT߃}x$qwg|@ -;t(f&r 'sw7iUCZj`?ڗbe,1iw"[ 9#PXB"S4& ([!HZ` @dDqf1(@OCw8G!"0W,?WynR,+X@KPd #1.@ hjZe6j  ۊH<0EHQ82y( FO FЛ\5 ´Qf 4C\'uJ俙 d(>4VXZiЏsǔM5r62- \~8 !.%AaI jwhB=| ˡeGWpRkN&`5(k)]}}q `eW@ӭHb\`A(R`օIܺ;7EO;-(O2_WEO0觇645iǹ/xxPi<`0zP@h\{7G pt @+a51||Eac;(í] ]ҴM4ftsT"Xd"@9f3E2E]8 f3 fF\a)S-J5=0 c6R;)]D9 cCqz{i%h(D{bfdPٿt*Li'U_P(( 4N!Z\("vbL4(;y A(OrC],`IT@Ҫjyj)$c8!"wjF<7c)ʩ^C8@a 8"$7TigRYS@AV7vҴPJ\^[tZZ߈/hOcA'Nx@95#sh6SOf4 Eиph.HYZjCy.OV? G!(XF@B@a B :Z 5* y4vPX8KPwJ@ZJX ! Pbr=*܇V*М_]Y,ipZKڦpچ3Q*x℈4BG\]WJy-y6*ʠXx(ꚪGc˿sګ aZ2uE*GВ1ƦVMQ2٧([Xl|}"GC7+׀IM0H݅h V 㘩PUN/&p\\Y{@JipIUFQ))NLx\! dM3#EP ȵ+Ui)Wrd,+zzd{;yO9T?K+|? f&^WA>5e}]Sy΀N @f[-AwiSMKBY9hm`9p3@Oԉ),`0M4XՒ fSP QQ+.猠L+SYf^ S4Q+ώ4e(\i9TZPi(AbAFsB9p F5yZE.i(311MMfµ8g O^3 ͦh(^>w.7'H S5G5:ҧ)XjyT*nd1i(b|X:Kw$Mv@3<>*Y\OZ1 ]L^FVQIc5lOb5;P9u9AP[WI0ҀS{' \N>1FUъ(9mΣ*4J<έ>Ԣ!EY2(iғy>dI+AOސѾbLj0H꧈O]b75(R5 aqU7Zasyyq|/6P0dl~ (bR&n-f N޿VMg4}R3v >GM03shM%T5UQF* BQ5VaK@Y_Ne&"F|QY 'RK9 ZO[<֢34۔d` S'5Pm蛓'{B,xe,ǮjZ(;MK!c%SL)Rt|f/j ԧ)B`Sp$;%HqErB2K1j _DqAbk,Ѹ#TsPkM,Y>Q{vP` w[a;iOvQN]DrUv'gy>Lҵt;(F|f qZ ~'Y+~(6AKf[5 "[OLR06`k ~_IS49 J.QIi,- FLI¬ҞJ2*&XRr&Lf]sS5dAFfP>1\¯}+kRtfSj5ب~Ĩ/М˚ D1@!ʄQP> cZE$\9V-2)8c2_ٮP$j,P/:b@(3Y@ >A |N8DP˫l 0`/kNs%RMZvFX6RwfBv _k^t)vufB@#J2%lW!Ѻ[c>Z-SDz5&Ё"$kǬ6jfW3d1殼 W=wSSvtBz~j6@iD K(R`r66gV0kla!E|d$!l֏Pk9jRzc[ 4MͩZm&be(*'QfwI:226;֎Hh,i ߼y턙EjX l[Q6N>?:APr(?D,2kV k2N >.x՘uҟY*0 ʕVj8ՠ'J ܷ?9Ժ Ww?k Rfǝ֕sf63I_vsشi݁vtl[s晛c3# p!R{?$2 zf6#VS3F8651\vǤ;L̷c襩s 6ϣHe΢HYufkeJXX_n˟4Fy.~^ࢬrn I:v8W箻8{a3644?j?@-EkuGyQ ޯcs0Koѣf=E/>o#N,]M~pyzñ<Jkx&ʏSyc,/*;/ ` gEE,n'QWWE!}UQB)R亻c۶۶mAa|YSuY+3jh3eHἸUPRG琷guG9t[ٹs[=p{E} .qck{jMb_eK|!͡j. !h̷vnmO* |,#Lqǝ΁7;>$B9=; &ɣ|UHFvC1[ff8̝wk.o_\m"@aRu "Zq/ܽ{-N>e 3f֝$Mټ@(,!F49>1q.cf  ;v%4{6d'?Ͽn[t^YT&WTn:qMϴ>VNkwzpÆU;]1B+bwtC@E8vgvkW]BܘeV"o]{ Ki !nM7נHUmGFbvГl}(|.T&z?I| 'ӄqeb]U(7iZţu%eiq# ؊Wނtrm. ֣g쥛!O%@Jn>66U׮]j޳4_q++(Grؼuizk37{^^\09qc/H?-?*- iXDKM;QCu O4~`F}<8ZȯnV(vrL u\?0 i<۰aM7˃o|:qD?WiX<iQ!2o5hL<-~h<=cެi#(?R?8Q*-nȅ!ǘ(j`@\uk/sb N6IDAT=,h ?Q"rn޾iEv A!" N2*ۏjcaG-ׁCk=-cO8 R\qlнmox0baV={q]_$(FHzPMߙhzHW{7 `?=!? L4ʹCq56lh̀gP~d(|i"Q(uaECpGg~f: @+( BČ}f8L{y?aum_xvz%lhYx^6 Cc٣&_syRt%jRNh Ϗyu{[[Vo?Ow-=O"c^s/_%aqt7 7_ᯟ{N6;aZ.Z:wBz󾽷z0 (^OgO%GugZ6w!|v+N4XVj~E%s}~n,Kq~әٲe۽-]0t?poE4n۶q2?I͓2 %_6/[t|ƞ={$N4uRg)htO69vWD?ƛ֮B{O}/^W,GA[QI"Wj\ivw:8u~S>͕ɞpq8 wurwnВ+J>/Xb$u[.1|.gɳb  0lVǦsz#^9HRr!'VDR`i[bѦs3_N΂u̐O9~[⿺ܝV8qchU7gkw>\{?wMK?ȱe8+:r[_v =|`'o: 'ok~ߵ"7ԥK+Ez( vٿvZR>ZtNKO<{biÆf?cթvкI1hlXt.i/}y:{/|KoWt5M؎"(\Z)@\n%l=6;w͑%h[_Ms: 78l:Msh va`v܍,A1o~‹}Q$:,AUٺ p9΄k;Q_|x/7qh _sd׽e&O;o/N%Eю3mk6;}d{$i/뚌,KAfWgRd}7m~F<˭݌ك?~Lb9Tgnb3!Ξtм|]'n\k7䇻F1N+% <o_vl^kW_3/9S2;Ə~#_[.p#Ȓ) S=W H=t`1Chם{֞;|#3  / k4jCp;zU?vT]^mv{5ʲi}੦kZͩBznyh7aOe֝[2kY7C{.t?ո.{63GGkkT'՛?o?:Ϻ֭`;l@2s?;_Q?;)پ\K5SY͆pOƿ|3`"dU㇗g`:trl@f h@Ѐ4 h@Ѐ4 ?R"BIENDB`ukui-screensaver/src/assets/weather/38.png0000644000175000017500000004670414205074704017477 0ustar fengfengPNG  IHDR>a IDATx{mW]͹~=>sܼ#!$$hwVڶVr5FZ:(lҒ!e@K(-)AyA $!{{Zs_1Z{}M#Ocz޿9LT?95~3I Ik߬'[kSӽ0nΙ̽^ }'no]}֠Ͷ#{uspn`r}:9ǝk>{J=,;Okgz.@3eXyۿ~_am-M[t eEA%3nJ#S\Ui;& đ~mk~ܭtʞ3%̀u[Bs}\zVҨ|iϫ3t],=Ycu[S)gqF 7D!^ ] ".,/GRUAuj?HA04U4Ո4wFA5fG AQUЂ)0=-G$J+ɀ"U""AD96.މk.HmZ44)7Gvu˱q1^'_tʣZO&❧c괸Ղ!8%x!Dswyʲ|XnS3VlT "Iv2q[ߊ }}. ߁ mpp+_ ?នpJ|"5DUUv\[/xwPuˮڲKFEdx|7EQ!V{L@-YgdpwƵj\͖$A'@Ht$ mŌ|;QO@k#h""F륹$"u=o9#ফvPt@;/>C"4^;{,dv[ Ə q E5jkfqI~f2Ml[Ǥhvϯ3QE?K@*ZT@:-ChDWULFht!P UBs5" !hIugN@&cw'!prZмf!|PtYpmF*tL-bcXuau!2ZYYYfԅE4^L`kkwѠ)d`{ \@< PⳀM6@[U@wu>}Bl~a^#X>wsQ"M@mG%(&dFUγ}2AQ |@b !rhFEwٗ\Y5rt;{> tTys]ϯc'1bD,:=Ll>ácG s, 0ꖌ73ÌWs_m lT@*eaUno}{6J(c7P{E1hP/kHzr=U!XAF') Q#$Q T0 nW:K~>Y wwkM i&~Uu7O=(Esys;r?o >n`#hT@rE!ܔ~oPT}F`K6G~$]>epM]ٛ`ڎ VQ)۩D!JMQ7JGYP5Ԫh2apEt 9F`!;+R]m7V}Y}q:ưXmzT|sӖL愞i IBAk) 㪬?(Ʉ'hRcZ#ji$ƞTM׼1bނQ ?EQ]h՜Ж5 (RԪTXهÌQ-0 jעۥ4ݨݫ_9{xp 8 m&9kSkCQA/!n.(Uf]}0L\dQ&7.=Clz/_x46E1vTBIhPU, b58gĠXAc̢YB1( S"=w7P, 5'0Rʢ`KD`ԠEixbCoƜ5:o/cb>Y~ubG*AS;*i)% ;]Sh7*+ʌsNPkBc,ZEqz n|` }ۛW˺lOK z""֖%E-=9(ET3j)K(*(W1>UD )A RA Fc㪊zQ_ٕ}wz@:@#(HW06,Zd5]cBc]XԴڊ=`qpD+ĻypM˺g>ϟ)[nBoJ-ŨHaTK~WAe~[D5IE[*R` D`Ljְ%l>)"Ctz}NR0&*,zG5flt r.L4حw_yl<,8O8" "}Sj"_D5M/ `/ϼ.-Imx0~&'N+*eXEŠF(x>óg$)EؠjKEXE:] V) L8xX>1Ob{#10eciRO~Q0IS 6f ?緾یJP$(53G?o#mt͂Jڢq{h7߿/r Lm :u5hjT@)uFPy˘O-/oSkAlKS%{@{) T~ݝ!ϻӯx,BH}zPxD-Lkk*FaJXS$< hyWnǂ:htH0=0kow!䙶(/-/)E<:+ALG@wY(X#1ccQ#/ ##Ų]]9$"9C E-HPvU^tK)ȅ0a.WZ)T ` X 2cnUjAՠ!ՠ*hHu*}5#ΫA*jz<$y?Mn]ʚ "uɠˌq˟kP1p ތEppf)fL~VA01w(t±#,c:]T,*17̈0vc,"`C+[СQb\pcC]l`2 ϗ̰cr5pBְ ĴVb6ڽR׬ٯ hQc@L{f"b*-^+9Hܞf`#wF=ng"#lOm}#k1mNA<! H1%ԖɆ3)=j!~kܕު/oYZ˜+19\1={EkQ-" Ao=fS.b.C'5H@LL̋ `)c{X5Xk0`m5qڸ#fmmx^KXCa}ւ5+>@BsŽfF h H)*~1OLt|={~ S9R4 R"q6iQU #jďƃ0\db{WL?01hT`cl~,lMf6"FФB`hXEL6&8,be#:P -"]bxV5ه 5Z溻8o#g"@`6?=L%IRXcܱ"]ӗYaH-lP0wmnTC X5&rml!SiIUt_Q-F$+ILy,٥#>w먟tT LzD/K }e4(UHtv_$-Ez=X) A5  "C %dśV!x@muDm 3i `1oTłcbx̦:ԏ v'X86\B|[^W9^OTCUTWaԔU8yc.zWk yDdI"Nr݌D7&ݫ=&1?=:+_GXI7}"4CwQAE|%:MEbհ 7FWpxJ;P,إrSr" s/ԬBp1e M알c3q`X u ma:L=4Zg߮sI(.~Q cOQdRoY0HS݀'LBm01/o- _}Ͽzjcʠb1E%<łX;DyR{vF(Sg`J2i8uٗ {y\HwN<_7%toH c4LP?FtNޱC~ǂBe4F58Net]V \?~فގvh͏%[tztxS,x-׎]9Bvuh%\Ao'vIBh IDAT0dhZ\ܟ!]Gh#am0F.aq5Q"D+~Hm1n{5n[~έ6.lzW~_u䇞W*kg:-t޳tz[cKҌܔ83l\'9.S_@A)0`09sij#ND,t)LmM)PR|ucc %>V_&BB&ܮQ702ٴ!lt?W' /3ry!B!"wj{.U]j_UtϜxͱWPڅBMxؕ7XԕψɆҾ}k-gZuObJ͗dR!s}`#w_PITwG?RoPf^Y ;H pS B]SzV[1ӧͣb7䖾2!o'=}"IKd.-M=f*ɔ}UP''g>.L 8ЗX8o]!Qd6Xq+=O5nW~$G΍[d~H+7{O4焟SyϏ^9P2iP]Na=rOwʰFtxzg ]?, _k q;u,:e۶Ή߼X}>ZXFC  lݏɖU7Z;`FK -Ivl,O>}|?מKs1$y@Li_qCCim{aD"Ro(lZcDP\Rȥdk`d5f[⑃+W zP~sbMs-: H^c8>#fRdG{jY Lh*:jܮPXH\8$f6 BCKjwQٗ>gǟέ.^MX:W<oNt뷏$$icXWz"v_)0=hc;=^ D "aZ!JN/e`GD6ު:i3pE+ s/8K7RZ\6Wz?6^:̹ao/3AsF~saOh_CJ_c0vj±K9=Zy&+K0C;^w\Ln.MeH[uRoa>icp Da'>!OBI@n xADDkW7\ܿc{LCvsPkoNGj?΁ķR9%͑2yKN4⚆9a牜=Ü'۞qa}B 0ԠAǙ,D0űk|e9խp@P/©wΫ[>v 7/\ IQ,O{k[ƔL\5\..sݗd}r)046y~bKgkšI]_}^9'1M࢘y^HW;ww'}5Ѣ.XHȪoR}&DWDbIޑv.!n=ݽ8#^͋@Ѯ4M\|OnA}܌:_HBn>.w o7 N"V#ՖzǺ/ǏWtN<Gc]bS_jU|e5wl'Bm堽Ϣ{˥XZEQHSzy_$)A~+1p@:k#9g3s4sŞ-"@'rHBS*?Du0 L&V »R'OFrB Vuk>;n/CygbO? M,K +%8ĠGUybZՀ*2Ş+Q΂AM'B l$|u3ܝ\ě9o{ﶊ#Kl1*i:J807B]hie|ߎß{-,hBK1wj1;? /7tUuX8"Z.hn ˖n*  c×XY]p]3kTAӜxIo@fsk~\Ds |$|3f!ZUԛN2:UT ,ݹ{pJX!u#U w3t@{{ ,eEKĠ~cՃJW Ctā Y)%CG,-`f,}Q}“3=A3DoOņHrq[RvOzkֿ\ ΍w<>|OX'.A((njK?E/x̖YS>:MA)Ĭ>ypr>u32Gd3{o'Ảʏ=4~w~:B.t 2xFw̽v}w^d6]YC> _L#3ƒ 0 + H@!yGHI#$ g m~ NfKw̼7kNIKXtbN)?=rtJ}=JK3'F{'mE N`<&V4m0 ʤݫ=8tY bVnBdSXY#Q|s~n$"LyGEubhAoHVA'0f!dI,Κ\\~sBl; T(\ܹ:E5K7B1M4G/;o\ l6"4'ӎF7=߅yͻY804FLR.TnZp8\ gͷE Tuw1uPu@}׬|_-ڵ`qn~I3alqG45a9cm,9OfnΟ{dkeƂЎd c9G7hh8R`P* ʘPK=Fd0H, .M *3?x^gVZE휸M qtp5]ވL1QN9BFZF\m^&Z:ؓ s@s@h5@ʎ5 f 1Ux:ZTH]t;'&[zv;#wy T@]{^r跋S.{R1ܠyt~ka#Sm,I$Gd>_͛ls~\i=RA#H0LH(„!"ꌨ#[^GF}_dDv6|kp饷W,ĔGn 8ă :ƠV 8[$ CfFTrؼn9W\&cf?ğ[NHKhf0| ~7V;F@Z.S,:kw-˿{Ϭ2#:/]0~_w[uW AҪWX. rhA\~0FG[HF01uG= MQl3gWnz/o4zQļ! oB=-Ueau굕C+RYr]Rxzkpqw$+G;~VgK9Hms@7*mmv}RCeU`Cg7*<8 uFn::x፰`aT0Yɭ#z)-?ܽẫ\vEɊqGX 5+dOB=^`@$h19͈߆ ZORǧJܶS'CΔ`3LD%s>f'ӘhJм`#MuP 6V4)*uh6UT/jgIҠt~;\Ib̬s!@JL2ৱ~ 8`X}@K!"Vu|nn˿Z sK1kUHIJX;=ӱ  %Z+H'*DMXö`ҭ /{f*5d9 SJ#yo*|#$Lƨ#@-IcJhQbS蘁> z f.]d ^fÔKToomTP-7` :.ؼhɀ&u`z19=QEf%Ō HۭҺ~1MO¤'M'D eWtyX:]mHmh{# F@O.cL!YU!X3@GJA,L*=B R֘[ڍ.r]0K5oEm^)#@#6-]p[FK:L;#&zwCŨ"R[DVN?kP!\.pXa ֘R/,S("**%b{.:Li1e련?q $LӻsBy^pY Z`7z/~֛HG}:VJe*("XJkU6v+lc&"R*Rɔ~u Ϭzv1h:q`CP޵ueյ6۱dE 2I`fÌF#/|H $⇗@B$ #y8q^NbwlUU}{[UneLm![jW\uo}cub^,,#jjBHBp!( a%#0P  'nYxiz-^b\<)wR>mM}myx2')\O? 5 هJ*]X rquU.7{n`{A B QWYbW;uDL@q iƳg 0P(X}i `\I1Q15 nz*oSFƦ\T _h'?DMH^ *=Zo˂oيP:{tU9P\#ڨ A_WҩP8P| Yv뵂L 0n٢|Ze4ӻ^Q-Sx⧒7%]\:UCC+!)S.ʾQ;0.nɀpn!`) ԨjxxQ gs{WzhkՕZ^IFjQ %~_*Vy1*B8p'mq ~ !%#(fnC&^A^ʁOǹ6J)\ehaFW@@G<<3 .̇ n#$28=j[ G.vHR/_o]^.\^+7/fG ~p9;FK&5TNM vOAma"X@@ɻbLjG$uxrpsMf .: `åUȀ&K+[[{9p&;w>p@xtnݿSX[1˳٥AQg1=Uo謍압e;dؔt 8+k7ųX@]cIܦ^H+@u -uBz%(6m<TunPgzd&,f]LF+IU +2=w|޻/m\d@Hg꠴6;K!mn"UdWʳG:r:"P>{sM%4vbꄵ ,u~T+1PWB*C |ɡ*I &H{9.5z-?' NɆksh-Ei鮾t!w*|\u)m%TEO}.7]Û?IZS&3_J AI"P$ ï]Ge Sx!p%*"ʗC] pVtT9RQ@an9䆋^-6TrYiО1L@_TU|rs "cz\WL6_`lƽzr{i4<.[$$Q׀D3:5i@z N\aP6a*ͮ(torpi8#̱* ҩV@i^/4iLdEw00Æ{o,8 j-y4՘=۬!:h5=JESV3\NTXUƥK N\A#'0fg&l9wc^}!fuP]|Zf 甃rKJRX$q+Z1Gԡy VJF8dsllcDFD& O}Y"Cs- ԕ.&d;LIj9 i _[*߬lT1| |GQy-`M*D$"jsphRŠ2&VCf*/:+ȗ^]^oWQ!#P'FPfSgߋ.{7$֊7<[>3s8sy%ᜒ&UKs `DUE_xc iH Y Vaڶ8a'UG&<[EEƤĜB55rQ05Ά9? ['_k]iIg#{f `"vhk!.R^D]|QH_K]݋pZ$ w}r (UjTK CT1mQFOU'}cO* ,Lds qd1"R՘8+5-`H?_Ixu1!A'Ky [~io k[Q7Zg_Z~ d◵I xiV~V)UDt@FE60qT5p.} 28j_ǝiDnN4 cU:.2GT$UVr42\޾x&2IMէ^S V?p qFL짠f4It-0@{&z푯xoSuNiU6SI-kJ$z(`">>% >"ӿ(. `ld%WFZ0 X6Hsoc/MP|߮uuikϼ3a]UNa)\އw sW$ rdk\g^?̄A=j8vjV7_j4;Cxz/.mg*:BuM6WFm2o~$iUR: sɁtژzuB@@)̼?(*T* Xb~0QLOmI;ܪ/(DK՛]`4Qi2Rc;輪e~b7Pw:Z1m\3ŗɦiҼxF@wt6eV-O#]ox2ЉGE=n57~}fX2(R;tsZ^˞Q!!}ӳiFB{d3޶=ߪ*B'qYH 4+iwQ>cjecA\2:ut5G5̀YwCUH&8F @aکDs[يtPTo<$yƘwk5oV.//UC= 0 @B$<\HX6umy">m/5̛b&Pk?9p=P1NN-1t~o"*+S~ǽn q #9-PSɫqoNW)[D=~Ш?l dLD%-mgi!T}DZEWufvN@MA۸㶐y |ҎB  s2?.mxԷ' AC=G_5{J= >#hɷg.+NW`a&xya}GM>֓=<9fhbMFI6?*}si@%hwfWc僘X;MZkJnK~Mlb`{2|<))1w*O XQ-xo 429D*||]q`n4ve+1cչf4@ATPm.}8olw-`;d+_=\1Q % [蹿{?lE@7*~kmvo NԿo3L><4SsIENDB`ukui-screensaver/src/assets/weather/59.png0000644000175000017500000005522314205074704017476 0ustar fengfengPNG  IHDR>a IDATxy^E>{ߵ}3{H5,DD}DFt3eDMDQP"I0@VN: ~T޾yU>{߻Tխ:U6PN?(~`j!Bpco`& RIhm{{z[RjƎ]Uh7Ƿy-K$VVP>;F*?Vso|~G6˂ :QQ0||L+$S^ZxNw]) A`3D2UpHE`"?%`e3Wh<HРc;.2~1@T?7`Q_Ki4"PRéךњWN_MB%,$ ,) IkI`C5d@>Q2{2ݐ tQ瘏 Kjc`v1wιfM/&4jbRhD L&DkLA`ac&k5I奥A @h>s#́l$O|V#mv`9^ACTdrx-. )_؎ AKLPl{ RP|~Hq'KEBX|"Jr A.1|&A>3|5ig bXxLz7h@G14%i~WE7LM!%(*xY, ["ݐ38h\90J(7P$'+Jl, /oL=຾dIA,@ #*WDy?4@&IH, o xغ0c&rUYqˉ 03E;@SN㚫 q?pz|;/a' |"fhX b֚)Β.i?$N׬EO*sWĥ7n=5%f?XǢ&( /[;e yYHQZIPR0P@w*cp+{߄dhm͢aL յ BчFA`Jn-KvHPGUmʩ<2i+pAyAXi~N-s(D>#p :}A72dA C@& IN9-c(FȯH BF0|b$P&& F&dxc Gڡt@yL/8[{}6}M^=\A'3'Ҋܐ1"2 e/Wöqijె-rvtJ ŵhn;Z{j'?dpCV z$@ e&ö)`#w D L#Ip=3VoFKZ 렲?!-.K(4L1S^hQhF0i >fN-ןX*#_qnD:)5*loiB~Gd܅EpU$!I0 RR s/&tJUOޝvgT2v[`|^fh@]N FU}XQJ IbhiI ]# u ]׃ش'uDfZ#h; Ȥ,L_}X6\sIY\2h%'.C"Lf9HIAHXe+RIr M ;_?㧾LAkBr!Z"lSJ>"l ~ЕrP A`_cU P- Q|U%"P!=)k@ CC2&3ϟY:a2I\zXHP0PldڂklQ52i) ʉ˜l$6b f-N75~֝,JH PqPP BP3@h&-ݦt{7syM(蠓}*m4yx\ RI+D93&3&èP5Ұ- ;:`<-soh:z o@k`kLfRBX6 5[JKN_7^bm0~@# ˌJ[Axi8!I$hEġD) B Y*@Jt:pt`}m•eGŀ@3j2~F|'CcMRd-@ۀ Ap=?\fAj BFPlٴ! ؂4iJ:vگ/rxzkOvB̂'ϰA 20# 5 Hj43Ʀx}G/OAQȹpuy%<7+O~vNä,6}(㣫W7w߆yU*8;qky2 aXܘB+:1qB5|aIΞ|>)$d!- YҭC5\+ւ9XP x‘ ~q'z #@! (&Nӌ>?~tfR+FA1 |CKh<i ƴKAЂ{HX8s0| U*eEȱ!]CmM(@cJ0UL!&k.bE`* D I aY,,Jn)\U-L,…04Y. )!tOu-+*NJ$,6e:tp(ib* 3|)iE*kaks\GoVCiZPI"8b914k>/7t%!E"Vi *f@j* \<#X3cS{՝*? fK'`i52{ _V f{` "h 3.aRK[1ۼpNه.ch[PYh,(pRKdžy$@ !P>&YD)aHA}M3|怖VPW9(zr<2{:M]NdE"㒴U4_R4bq!`.@[3Rյ%[J.Q  B_=L;2ĜBe%$$RI&z"x#ASV^)S(eh )*:@BsFDXioJA)sQ,P,q|zz mGrb ڗ]o=-y$G\c da's`"1Buq͜9 ;@2LcǍt:h;iQJ)/VkN3a( I [aDRX @ QJ Ƚ&a`J2%㳕T|_=  ;C\BB9uرcWL6ϳ׸`5$&<eRT ?J%m'8Lc[Ng=f! STZ+h]GaNj6Pb!#* =HF˖eA[0! H o'`R J+ qy{OY)҂Y+rC(H&'Oss/Or0,V)h DN)*`Ffa[3gΜOL8qR%Icƌ!f.k~IQBi*>qD# ߜ7 GY( ;R6UB kv RZR#Rb, ׇbxhԩ?P m{ 37Q3Q9xB}}>Ldjkk1i$Rd#(* o:/.qqiyP03m+o =C\,C!oo#;ko6$R2 e2d2ƫ;?hr-1`1seYI˲`h 7y,U\\C*(|?b>dTjg8#ğ)^aH@2(}+L?}/*6B:R$̜ " Iu̎GZixX *ѨR{GHU1G뎳A"@2D:t:-Ϟ0{쫎QG S$'lWm܆#iqY X)(+ G{~GR(ڌ $iN&f|21I1R IDAT\.7N%mDчԙ:u4;FA2_oSk+Y2uT*F%[N;$"[  fvzzzB33~E,*#Os^I}? {Vp%M ?*QPH9$۶IJ뭅  =k9y^śR?Q*9@=xq4fq1qYD"s=uK(e{{|>E&!;Cl3d"J\kvr[ofLRNWg ^WdůEJ97ۦwQS&ݻ8f̘y.\ץT*5LpQ팧T 0) yP4t* (?h$hLƀs4fTEF0H7oD?Q͏J;zXrg6.J@S3#,6Ţy@00|G?(}͚5k/CCCڶmi&&RSlُS~?\:5LMYH D08LPIHqb΋1aWQƬ M044J(b ""fy'|l7²,>M4}xǍd㿣hSVt9RB^]Pb+ąXt4>G|$d1 (8h !̜D:zppX,6.X` `FDDa'8.xɨLE'FL4ɦ;~`%@,$8=q!WJ#|D|>uG<#?l|B. 0 .S6 P +JCPF*o27 T(hhhHkiÆ C|> 뮻߻wKa9"*0so fADѥ2D0 H@wwu֭_z]vjqluRk-Z PJB@ⰼ?(֛NtJ dR%-w$ThfMYvs>ED? rB|o)` !T1H (zzzZJJ)kkkdlƲ,Ă f;6ADL&Ikq91ѷLF?8N)`hLÔDQ6ŝ(84400X/Ru]@8T,59MRi߾}t}!u~0` xHJ;ZxPo“?y j-{{xHP0ټ~&<ܲe˖iQfPDT)<89m8D.Аr.CP@>b 1=b!nI#bHCR͛7?ر$"',&)R֤|>OmmmΓO>wu떣dCKYkm`T਋+\ٚ_eN>/ׯ˝W1 @ 0! %̞wyuY@!(Jax&JaSiT(RPڶmi _@:F:d2D"1#\XA+V\y{=|LCCCqN8q|KKKccccMUUU&LJ۶X,z}}}vѾcǎBpm@/>}Bu6 8wJG~hׇL*%?@6+F9 1[wy͛7W@Ry2!2FBǁsΎt:8qbc"mt:d2d2iGDq4&D03:::'|~7%1؍#$ ;c+uP&gzE2@xcx[XR_/^(; ~SJiPb )` &$BiU)Y"J߿C=6y䙧risΝؘ`}LDl"5*B&q]ؾ}ׯ!LL6mܹsL6mZSSSZJY&:öm#Q@bʕ+7?/k+n% 8HZk]tCD$(~rB@Q?ODEfkt\&|oEu&FʖwO؄`-`K)-_&[BTcdBMӧϚ1cI&MhhhNL.1 o޽vܹ}g. oI!fL4iԩSO4i|KKK}]]]"͖L8so۸qÇZǿΈF&kL.}FQ@+8x OI ]~YN(7'Ϸ픗xz3ʎ$Q68 _?}yڵh3$FQXUX___f2Lʶm)ZkW( uw6h!@$D0RL*m۶{{{{Gv#fFGFшaR,xh~G:~Q=h:V0a|v_8TUlꫲz]cOgGk *-2}n3fHr)nPJEoM ((`QsWgg现hxt <0cO6u(P#њM6D3|>ߛQFqlRKaۄ p . Jqද_N]PK3'ٍc*:죒f_رbqyt:9s<_o[nݪ믿'O=7x{'R)aE;E&$QHb8{aqID2z]gp(t" Ll̝{9@TbM²CaQ>1}#l%N 4|(#1}|]GCW|~~G`d)0D0s1\o˃<%% @l۪¦MpBkruֽrˎ;455iӦrg݄ D"Z !2<`h؈ -9򇖏S s?|˧|3Oھ w3qAz*Ѵpg"[?{ƢzmBJ bi&@20>+pZugt@_к8:@.:npYf-*ϼK[/^|%3[ZZj9看/WX{WI'{m}O?mڵk!l5Qh.Fr!aEtd@$Yڿu+\Ho+V,馛6ٳnoo>;oF>wÉ3g{ٳ>UV=dɒϯXb1-+\pK.?J2)R6F>}0z.\rbu0'3)Jg%e5<^-a"̞={CGT`[fC@}Ň&l V&a/2=E_~b;KOtR$]TUm mF ;&kk/m{>yE+W<[no.O3g{+-%c_<>{'1s?鏦Mִxs׮]0sŒ0(+8qh"B(N;L}ª&Ab2y簔R2-̬'"}k ?ĉ(jGWgdu6.:H^p˛/}ieYwڶ}UW]+ժioo5ͮEGڸqX~oŋ6cƌg:k_+'K,9W^we}VtKʌL@Nz@,L+30NSa„c\qu?n{j*L3;yɭSj_(+^9=5lr3< \nݺ'tҕǏ߷~6m [N heݻv͗]vمf>0_&k]7NW_}uwܹd,  #h \,"G F&ط{z?xjN=}2ƶTcŲz55 5:_@x=̋YZIfSBtuvC:::rܛN/dK.gfX,fͪ]z?c˲ =ww޾p3~?N?~׿uϙg|嗏]n]Nkhhgy[kN;38c]0s& t٤`jMJwxw:P5k~̚GnXmcXQS8Jǯ_>{>daYc/n/;?#,f2?ɓ''\^{go~3Ͽ0{lqw0o+Sg/_{ [ZZ]]]΂ +V8-k}f֭3O2ytR]mn_'͛7W tl m߯ڶ-;::ҥKNo5 ̜PJԯ}}W]t+bĉ-zge˶=cs/nkk[ ҇47z/_r~_{*GDfWڵ$o'JyNYs~ `cQsglٲMMM{0Oݷo[wxhoYguvDwnBdcmw1c}ҥKK$x7uss/e*tuuluu5.\8 _?ϙ39Ng D񧿕 Hh gI{mmm[ֲ|/Dd+D#!ӼzϼY[O'bŊ/e%Rm۾b``z۶mkNA,Oo.oڴi)HJImc``TZkuwo{[Wkão)L K) .^>o'N?Z;J)Ä !jP^YDѼkZy'jSkme}:Rf̙3ץR'OtZrs=1qQttt>/`566N\hQֺW^}7g gT(RڿHT|ee:\.9\ڬRk9\rfoI:2ҤD"a8 Hm`xM!\ 2 5UR5iM vܸqY'p+V7~RUUUS'֜J/έXOT 0|||[n_Z[[iC+Wl߰aCUkkkeYսc+ҁFK2HL_tW\GJiڵkSOmz„ ˗Y>WJm۶8ps=:y;h%Y3BIDATW״ !RItQf,mw0o|S_8u{J'lJ_}XJ$w drڵkH$t 3f̘v '$D8_gΫ3<W_}o}ֺ6m!.\(z?z J)h}?|o~/ϟӣ_xSZҥKoIRT7E$"m۲m[:k܂ W_}u޽{78ÒeYK.ڵk7|춶'?ɃD4@n\fv}wUUUwlllD.+i~믿kkʣ{R"bTPq cl]GccYM4Ǥ3㒐$f6LҚqƎ$Ak$(wDbP޻wx"!s;ݺサ}6nܸP5jZ`g&zH---cF|#XT*U+<[A0SJ/p @-J_>##Xx }@6o޼Pv^"=gR:::8((?駟p?qk1p8<e>裓׭[w_1zha}6mtL$Jzvp䍂8Ʉˍٳg?[z!dR>jt&E{{)aݝfn8u*6[fJ~d2矏x ߁+S!@z?WVVv,_H>쩮1cFje}}}dժU{sss7k4xj)t ұ`[:|-cD)meAF yTcEWIMc,.+?q?76>uTT$بǏr===A}}}SJ;A1\0!p8GI|=8 ڵ/Zvh `#tj@6].ƘWۋx^ c=1 c̪O1fS>Fly?sLŋVRKHHt:unՋG=5ܶ1 q\ !$DQP(] N9!h INĹ{i#j!۲}_~KCCCSLLL([om---u:!11Qn$c}uB{8&1y`8SRu) of MmYYkYfN.+8`Ϟ="##ȑ#1f̘Սb@@@3glyĉMO~c8x]|~~0 Eݒ$5KT+b$Iu$5@*)F#[RSSfwU*ѣz'+**.‹礤G8LOO(0a\%HI)k_o~BY|~UWUUuFRJkkk{===G}T5jϼy֬^={lh4=f ܽ[|le~:uȼcǎlf###nkkc*}* <̖~f79ذaWs{nz޴iS݆ jcٳg]N_7o۶ڵwx{q;ݟ{SwjD\z쌌줤$I'xbv@@48;448qg[ @WRyE4z hrnIMMr6l8v9s?~|xuu;44?uT#G-C,YeV Q6t?*I.r+1jjjf=;511qoq*Eb1Q .؋m1XMMk͚5YyyyEJKK#6 m]yCtdظy SNe9RRRmnn;::_|ٳg]JKKvHUUU#~7QT +nu hRSVX5w8U6pmʖ-[/F$?> }֬YO/8N:qDŋlݺ2$$DU^^^7o޼E|m۶bŊuw@H=1#!0؀`ǫ\tI7$I&bZXXXRTT8}޻;<<\)9F{」'Bca B(h?$ne?&\~5Qv98ŋW|s>|1mڴx^^^ /,--mj팊?S###GUZKϗ_~ynt UUUf_p( 4_OB ܉Vw0NQ< RѣyyyM6fskyiҤ;v۷@I0ѤcbϲT1R]ar -Z-BMX)IcΩSZhy V*ڽ{*sddA$v-lmp;`0N12[{󁯏R#}GZ$I.N+,O:1Lyy!/_vk>ǟ{=&M2o=ѣO\xIlzr<⚢IQ]vP-ϻy)B{W?-**Z5kݺugm Fқ)^aK6J1zlW9,U{{tϮ+//085c -z=%%]vO>Oz衿ϝ;wJBFFÇgBHDhQ r8ܹs '$"1䭟'-a>qx;ΊUe{qXa*jktm HJJ_t9s 9sV(8 99yΝ;+++kj!w.!I,ÂYT7~C74Xso Do<YDJ" 5dA̱c QTB&goS ƹnSyyyϜ9sٳLիWX,=;vx/X$ R~~~ɓ'!<.#9 L`P+d-qM*)UR$I&Q<O"㸥H;^\s]p+\}Bb(aZ3NV'qnڴi%K2kjj)0@^; n-&Ji nQ#w`a$Iь1 (^ u`;[Ec1}x^pmZ^@F$b %7!$R 9|f.2Ƽ۩; RxnA/ߍNŢ?ȖrHȪ@^Xj=@~?‘ŏʱ0+! EѫQQ?u:PPC?8~3IENDB`ukui-screensaver/src/assets/weather/67.png0000644000175000017500000003616214205074704017476 0ustar fengfengPNG  IHDR>a IDATx]iXW~oUu1%5c5h411,F2j4ѸDb( ;4{W~THL@Qq<4tWWݮ:u9= ?~!-Xy#C@rss^|1{uDm S걮͛˲ddd@N!cv=&P硶~srrfi4{r{ذw^;<nʼ@zڃBCCg-\pl@@@ &D>Ɵ&(o "̙3YH^^g}?vA>`EV$&&湻+f%66oO^x鵵BpƟ\pt?G///Œ{"""<#ϟoU6X c6O>իW>GÇw.++8%q M)UO.žȠ .|%222/--y&R,6nx866֪Na/\]]t͐JKKW_}56&&&''kv111Q?{-:+J?wp% :uСRg̘1ٙ>iҤ==={ュ+Vk Ywb a/FӘ`,++>|O>pرӧOptt***!+j@ e;~1G{7 :s~\L555:T9Z,Tܞah0(n xhpСbcc̙9&bmEEMEQJCkA6 r''G 6,((#MMM3+W홁Θ1cʕ+'0aɓ'o+// bC)(6u:]Caa>;;[ B4MiCCC(-#ho.YyBt͛&bNΜ9sd2L2hڵ^4o69pPI$\}$,Gb ./^)##c $ ?~ÇKOO[.@}wbY$)T*=X8˲Ym/lƹ>(66}NGu./xⓗ.]:R ##c҅a!T?|pٺuXq ׍N.**7nL(///?tR*0J9H9ӎsɡzXիףׯk3g~(//W]v644=B^EQ`ƁeYGRֹsg:}HHH///Ŵivcz6--(...ɓƸlٲN:usxxxc=ƍ% 7bYYر$HZ9¿MBVVVj& 82 @g=_,7OZ:~:H{ YYY^ piqsNNN>},;1tԩ;;tLTN[pzVWWSJ}Wm6bojTmM[WYY闒&%%"f4 q9q/qބwH ؋/V7}/44t(? ...B}ZZZ}ffnnY 4y]͛cQQqҤIxs+ Rh4Rj4illlEmmի׫o92fi jRWT)**[nݯV… Cڔ4%bj "**8%%%O>#z{cGO>@/\6sE'N*Pcc⪫Źsxԩ2K(L&l6[L&e̘1;ӧϻ7oެ[~},>>>Ĕ=i \rt:ZYYI,999\sLLLܻwuJz={}k]xjJ)]|J !^^^}/^kn >OMM9::1p QQQř/(Ҩ޽{0 ,ww !p IC5vw>&%%455jՇKKK 5TƑ#G \\\LNVUUunr}6>rIÆ lٲvu~H+))RVKiAA mlluJ)dgg7$%%(JW4o e!t;qSJekG-5LTQDg̘3JJJGVTTT{}Ϟ=i~LJt@4̏pׯ)&&&nڴ))11Q_QJi|||UnB(~6 tذacy`!͏K/m3TVӚriNN`XKSRRRSSnzU ͟wm ^^^SSL/xbbb4>cbbҪ*nݺso߾Sxqw Gƍ{xeMaav֭7O>]I)ׯ_o4^AyRJU*o0^K.&@5pvzB:88}>ڴiStII ty /0BH+EFFҿw===,ۓ҉n΍ 0~&5] lUV6GDDT_rr|sppH,fwy=~RzĉիW_JNN: ĒZXXhNJJY,zСe˖,((О={-~{e!Q؃8ɨ|QTBzz6l 鄐y?<i$R8ZGH,es"ÔRvׯsss yyy7nr)\RRBy`$!d0$faͭ+jihhF#_RR"TUUE^VWWR'$x孷::~ҥ_{`,JHm.ctmB M6]1bĦ;v\/xRP<O>1 3$ ܏aAmll:͛7ocaaիɺׯ, X,R^^n㏓=<}(z=x0Ɔz1.]*NIMM-9y?APP(Kf8,k# 0(]v^+W_|WVVV qZ)]Ҍ10 ,#C?Ntuuv֬Yžt{N vqqqJOO $$k׮q1:~("06G~ټysrm۶UVE+JZUUE+++d"8;;Ӑ˖-{7Ѿ}{[! X:`)_@QdDQ43 Bjjjzeeey ðR^5;`0N3Ph4zZ-޽˗wn{:>##}PJ-L,!so `/kΝ;NIIU<8q_edJjԩE&Ig4zl6m۶VVʉ!fmj I C2+ f9D+/Ve:A@v øI)uHKKx{MIIIY8iҤc'O o߾#oXB!~[ju: $aY Go˗/~Y06cǎ.))1y{{~ĉzb2駟AhhX5`U-#n qvR{Q( 3 $b@ !&e8F#n/QT*,$c'V? ,AjBA0~lX9t:>>>544G<}te֭[&Mٳ@S^^wy޼m۶h4CRZB^hU##˲fBa!B(&Q( <[p{9 `Ei?>9==]%o$:JRH)m3BcwoQ4dL~Gsf͚թB\he˖ 9sߢE.feee'&&fqqqsgGaY(ZBA7h{z VnAWS+jlrmȟ[ ׬qo*?aH. (>O?=]SSS\ZZZ1ɒȲeO>K)B̲ 䧩54(~+m}Mk M^9BEQ˩_yB(H) ~`KqB P9ЕeYAݻw'6f̘JҡK.>I.@eYҵV s+o5BxJf Q3ZS!Mo*{Nq'pEEti6%%%qb&TY$xS@[eYA!JHהg(BSZYBߪԏaFM3k]@V #OO<#HE m VXUZ 4++kղ*j˲ڵkW٩ST@۝ =V:ejO03 cE!{/[ yyysrrvܹ3000plv寉N>X12 gZ֥ҺQJ+( 2mE[2lBrܹs};u٫WN/7nܒ}>T*ɷ~g}o=գG˗/%9܍UUфg߼(bN@ҧO=([n]Gt:w<`ذa#Μ9s/ZJ|:vX|ã޾]vM=)]",,,gϞnG=3{zzvtwwlj'ϟ" ֢ Va.MxP8q"STԦ[nIuogW  !!!ѣGC g͚PLsXXX\ddd /ydd*$$d i>|yZ?Edddwyln A|WV3}}}݃{;w.C*ڵk9&f8pd2O?=3`'DQL4)T#չ(N8ӷzXeee]G м|:)hȑ/]Tp dϝ;-IDAT_>y5c=ذa#"dNAXfs݁v<'**ꊻ{[>}S3f̘ݻwoJUyʕMk5nZҪaHM7v>\ `ٳ#sssi||.,,`ƍ7D_ƩݫUH:tS zmݻ&NEmm-X,… UIII.\ٹsg˗K|}}{ݍ.**t7}a G۷o?+00p+WST氰lR&&&  xy8LHHk׮ݛiJHH3gΔM:uW_} #~Hg䈤sνt)Zw]LJJJ`Yևi{Ο?2666m̘1}:u*믿NOOO8r ϙL& wHP7|3YbżZN:mᇬ7nls_U֘9v״ˇzj HIIIJJJJдzL(8Bl|||z888˟w{:N#$$Ә1czeJXjqj444g}ӳڵk7ju'SRRҿ7o^W__piܮҶ</BXAIII)uyakƽ"ZRjƍܒ*V)==aΝ';nڴi_uRt0:S~=zz100pٳ_ܹwzzҥKIm2*==={[۞xك *DuT(eYB%n)B QHOV hĽTV/_|9swww~jkkM۶m˲(jq9o޼Fرcgz=}*Jz?Ү] ·0eCBB2bĈq5j , r7.C oc۷f͚u>244]:,KXuo :q+HGi`YVòl=˲jeYeFQEkĽ)Viba0 #BLn|#J$@W^կzݽGtGjwnP(,~=zegg)_eX 6B ްfѸ@Av m) 51Hm\@qnh~B,e@@@gUm۶-+WJJJL,˾Ν;3\]]999ܰaрA45Go-u*.{*qKp+"@1<;SʨFY]]mVTUV튏;p@z\h4cTTTFQмAnzIuĐ{8"0 c; ! 4PJJBdXhTwܹs7x5N2eɓ͛+99YL&]v]j߾jZQVt?XAEQH#Rj)yգP(4s(;v||բk @+ê f;qQ ؈XQQaL *nȐ!qqqE111?nݺ 6ѣGo̙3g~QQQ:0 fMԮpP(=`|@@Ȼ~:t4!!vl%QQQ˗_رBhB: uqM/ ^E0"r'fddX⇓'OVUU;]P(rssk.\[ZZM}Q|ffŋڄ}vvо}KTzA-~5ZPYY雟o `|M^͛PJK/AeNIK#0cccc /]TWTzbvܙQPP`~g$wmIjZիJOKK&$$,lRJ]v3jԨAsѲNwwmF`2f̘93gΜWSSC?&11qȐ!J%vuŋY+Vxȑ#DQ4e @sy1 ëT aH޽;^!_Ν;YE?>a?o !DEEB"Thbl? i;uT3{`A2` 8Ya^o^tI#Ґ!C>}{lA{.]tBDDD.@Bȣ<.]Ri̙nŊ)t߾}L?Ojҟã<𪨨pEoܸA?z`$B&ԩSeǽ˲B>@eвyc@@zZSSc7nzHt/WW'7|sϩSr嶭1O0PJÇz7z866vni*iz-333())i͛7KСCGIpԸ/$ AWy[ua,,0!Ѳ͎eY?e^z֮a'NiMNv.rر|%W\)iRR<˗/:{z͚5;U*={*//O666nhy:{a:A{Y&RJNFƍs7ҥKjF#k׮krrr,&ɒ`gg7.4t2;![l9[\\L+++Z}ŋ5۶m,..a_~%5::ڈZvy_{HVcKmFZZZh,Xp$""BE)_z_r _PP $$$hM&5TӉyyy/>0`ۯڮ .RJpD:'v^}կirr)##ðybZ^^Nϝ;W_XX(|}aaatڴiŠ -oB忭Ō`l1>333kyVoX_~yW^ܹs:Nt:X^^.?~xϞ=Eh4RJ)Udyzܹ*ww nu;~)nذ#G j5ץf3=~erS3k֬sgm/;}6 f7}00mڴqTΚ5Ǔ'OWTTXZh0e :RJɓ'۷"׬YTQQah4;9pgC 2#^y5jao9Cʏ9Rwފ7j4.dff=zx@{a84 <nHEQ\`Hœfx,5BEEdɒAAA$%%JKK-gϞRJݻ W$?fbddd$~b2 8LfСDGGݼyӘ"F/hKKK`.]j())㵟~iJyy9}w#lll0 q~?%>}rQiTTT?3f=3Ffj2 D}iX??sU3f155ȑ#%R;ɲ= s ܥN,pke˖4{|AtQQe]xxxu~~p]BBB#Gvy  n3)cĈ !ݻwM6mڹs~~~,X0”1b~d^^_DQb~F#5 bcc#5 l@@c޽e 4ȅ+!,wA*ef2\X6o޼a֭ʪ|b~zYf,Z ,g[[.<==RJs׮]kܸcǎl"fQRFCvd*JM6̘1_RJO>]/SJirrYRYzX\\l>x`74 `u%SL9XUUeQtО8oHs Hq cOq]v W_:7!! ':OlF@a`*qs!X]{{{/SJ5kҺvvRf[lI;uV`?N`J`` :t'e7!oxH@a:>1mEX1Jaaݺuvvvv<_6`AzU}~ @?|wF5jILLjtRJmEQt_5-bT;NԐ_ܓlhKF5~Zh)ԝSuvvvFlly50(ܔW^pBh#vرcfy)Ѻ!< M[ʱ@!f D5yQ}JiڊǙ冈rsb„ !4...a(wĪU׮]{PF۷yWRJa4a2H[k^qؚcZbZ,~kzU(a1Le!Ӿ"(dggPJO:?w3fX,$"""UEBp9r*JekkkeYƴH+;DEyH7$BȲ,/71@%^̧Cj$iKTӆR aӧOo5jwXXXʄ ze0a ` Ŷ>q"_Si+y^E[ FMQX+ޗ`mIhdBSJ#&EDDZ|WgnzҴa7 0e =|Nk[ YB:@Rbw/TZKiW `|[<8$0 R'_ n~ش휵S=wڊGdKiqBEQogYV*d;ڈsMhM<([ z%^! Nɕ~ ܪ`UVWOE,<!J*5nc[ pk~TihF@VkeI7C4bXmbV7[؂Ow p+Ǿ).Ca IDATxwdY'{ϹstO(˒`d|10b2]%.>:8aKB%Œ& +xqY_|yjֹ9˿{~7,^.hh0?ˋA6]yRv ?7wO+xsm: sO Ӹl Y,Oc@-2llk~G222OW @frW@̥fLD(> (u D%r3pӗ@ʇA1}| mP2v_;J;h{wscvsG>~B԰x?o{D66]Nzb$J]%؂H\a4,8qv> c_v~@]-B[3|Z IyN3X߰2 _( h?y|1:Oĺ1/=X 4DW+]gr+v6]?{\ .aXSBg`R)̗*p5Zs#=w*Tc8'U`޿=jU|#:ƈ3|] x(f/~ r֠42x0#<ĒjZ[fK" cl~ W<8A c]Zc?@@iZ҄z ~m7 B8&y9Ͻ+v;Ň?uŏ|ǭ͹Xvd{>11 v1 J <)i{Y m_㿒+W:.Ksc 6~e5u Ux^J`1IAD€ Fj͎} e| ]qK_;G}QfP x;B'V-S0"*}8sJ[ 29V} p߂?qG# Ҕa4;wKw |@z <`f"XAPIf0cZHv'?޿7S;\\ ,tI PaDE:QVv/G,2؋&̘C8P:S' ₀ )B5x0Q .'U< L]H*?| A} x)%bbNl/E9L^{W7"}g[D'1ag%Xà[gWt?^(m0?]p`vY }x@X0`DLKOyQ} 秌q#D㱣ȵ6[3cb뜺e D1(XfH!Ѝs?ym 7E^KJq-3)@x&9\^-@81d %A\ǎ+ vh0A@c⧿v?OVD3}92{8XN]-s?ڽc@;-&>&Xۿ|7_\S;:,|)2}&| 09[b&bO:?Q(Ñ;͖-w݈s d_iX` @ 4["~E~_Zt" OeL ޓ%oim}YG p~!3>x#T+/^qb4F|"0\d?zJ8@݆ h;10'W=Ƿ_yb QHmww>w׭7ބ8}%@鷔J13B\.}? *韛Xo'8օv|LyH443 e@3$ c,N΂'!Av塈wK u}E~A9(wt=ίF?xmXPEdK--7#nm鞮LDmk(-ygpY2DY[t >. րܤE6Чqi= H3[xI| Q8Sk3ݷ2i ID@XJR0<Ѝs?r@f} Ӄк'q( !ąG”.DO9l%@/.߼ T={$+xc!^ƛ+?t'rea˹.̢IF2c>'HC]wL|!!HV e_hlxc;]@< (`fܹ$.>*~~`hȩm$:cК. }C!Vzޠ?/渴'xrzKM!˜4" =LR<f9Vzxk?_+߽/W^'?v>ym͟x1B+Ɣ]/.c(-¡|"7wh8{(߱`gc<9D1U[Tܜ.@2/s05ЉU$^a}8Iޟ})^a mAq1a uJW.dw%_),3*l/. &x+w_F2ؑZ:PA,Uxtkq-^C{ poMoM낾`]Qt)\xR;|^f;Eeoz.ۿNsiPKPz ^*=߀n#/b"_ LNƫ“NǎmL0;C'bW(+*/bF JvP 0zImlх *Jɥ-'XHCE/[·~oy7L᣿:?NOrKKQ˂P9#.4ԙYB2jf7D'/4ר.G@/G%;>5?R $ eF}y9jaa#$oŽH! 8u\0 ``T(kye-@“8 H!,v2 3G}1h or4,H5V| x;nƱvGﻀ4sĶa Zl|?RҔ1=yWM ڽS/13VGSI xp4DG'ܧI~]1#GgY[эKlA#fIbU_$~r?[kCJ_䐩Ǖ~g HAR qdrmpQ|ފGcH3zþ*~Кc: 2N.PDł`1~;]+Eq,j%Dspq-nǎcfō&эRzahIHs_GgO`6M!˝%t=F.xra?tl@dʠ)\Xp| m,^5WRŅvAqҸjg)Kd-!I,}c v.9*u/= If -exRbi𒛦{3٠E3}xˮ~Q<{~QŚ"SҋgwǗ+v@tz D~SoyMoqq^`zjܥ}}[|p&gP vC),!e߆Z!ɹ\dZ:KM]y E/ Lqb HHXcM $,yqS g2(O~ қf@ju>9 ߱oljs[|WS];(uM$cO?:l6cHOI*Q \ ŷ}ult~Max;~gӣUzLhvlIH&KRv5~/#ƞR9WĻ8k}ObbD16"Kq*e1xjg 8e?vcz >t%\ MKra(l,P jeT8qR׫TZQ쪕5{˦I^7.@9ㇾ{`D,@.Y0q`JmVwHLy. Ój+=}}?V/4 HOt66Z[&ˌ'egCK;[YZ.BKXPہ$sц-E96JyÌ.`-ì7gc,>X VMyAv*.9q[kpvm^fku_nnlwӬIr)6>3d[ºH@(m=v0ES[JbOSe)2M0eh5= e7*DKOA"lqCIX~ I2næ֭iC@l_hJpgECHXGYR1ʀCsC58f1@rH \2T>1R̥P!–bֲjr,Zkv~dig gK?j˚~_7[oϳ2)|@i 8e(\vմ.l2, Ԫ~+Xn,CGF)0Z \sh(#2m䫽s})@ 1KkV*ULiy* r4K`a"KكRV'|"y^\VBą^WeeAaP9!-36˕җm?!Ҧio"Q¬293zFm#^9u>;nBa/WNz=Ǭ#sAE c4X E6J/ʸ΄iӊsGO̳3ӤDM,eHaXNQZ%G` <ˠMNIц'>󉏞7ܟeBXvֆmRM6&G $Hl --S V{McXL^s3I٢8B1\n!eM`P:e\eV#+++a pH80lm6zc$Tj] aȨNԲA&ŗ9^odCio .cL“ӂVW:01>VHFEj[ ̃N׌C *ׁeHirlPgi/~|E |_p\4!W-]3n_ (|aWț(` PͶ 3A2Tklo=A)G/\̔I SH:G12 .7DRH)3W9d$|Vt`\ %z]r+A;r0zhum?Bߞ}׏7DQL{LҥrZ##ΒHiju%֫{>t=s3)g9e `vΛ-Bri.e75&>$W`(\N| E$EiR>D髮f߸h[\Ȳb6Bk@";®16`ڀmaƤԱ`>v3c4hiŹa|0Ơy,3Pb~,G╮imtxQC:voĸR]h8se?dԔ*U{]?}&*33Rzm@RZCjT82?q? \Z>ox֦33$Z-ҢLm&eGliы\{ai~q|j:˞V&MMyE"y{~aP6(Y̲X1 32g@f-'zDG?~dm-H8ue{̀k IDAT]LGJ Q<@f9׎BkFs2 y m \SNwӔew&Ѱ=Z(Ȳn[ڊzccfsF23Zf5'IjT}|޿R0_?;XGv [{P;=lmyM!8QXs1u Xb2C >pbp1Ev)xL-"j.3bi!]0Ň *%ص,v9AR0oKve#FE$!d$c ivNT!I XS167]1jb ܂FKw@cn. ǭ C ^imX+..} vG/,=(/,=eJ9ZKmZGI!e!Yl~}Fb(&H0FBkž! |Ǘm")t fc iF*{bf ~*(_YPjkjऊ g"yhE1,9XDZk5WV*+ F>FjU03c_fZ娄AQU֖@>#Sa`~4|A/|ΜYZYVAV9okr@- e\n~@legΝ\XZ\3NZYOWKs'ĕ[.vZUyQY4U6|IJssXf4ϲW'};51QRD/dX[cK,!|CQPm><ɍzVV;ͭhclZ/\Npi!5rt!02\21$&|˿D&6 Z@R?c r/$5K.&I)5";nt kN㣜$)1 jAg.yb 5eZ^^nv:y\[`nz}cLW5{ dc;H"W c t5`VAJQ3 C R-?bGxC[ܚq(Ck͝n[mVV^g޷^]DJA2}M!bZn'''F eڕ:I?v@%{R2 ALD䄵wJ*qblN7p5zH)VF \-y@dn/g/5] <| n Zom/J yBT+$$͐.?6{XZݍ;Lic˶TDB""nRj|K瞰ebcc }8lom3kyR1aPu"q֠؄yycO@zuZ NDm,@jjY^YťeZ]n0FU(*}0vg^&ā:")t,zH0(>* ! D'Ƣhwr o w*2m uj 9B}ɇ 3S쎩q;R+Z0i]I'y(ŅB\Yp8Ni^//_hv4{{Vڢ6R  =g EO!ՁV*(A$?lS B$7pݵ:xؿRCk-\5s3lTA)íVN$Jڲ6X8qHQl>>Y1MNa.̄JҊ/[ ]J>C:2R9canZ yaO&y@~-ay<獍$ީS XJW gRJI;`i"(SPj~;Ap>X0TV$IAxwz)##訳 J)t#Z\<# Zh@Gd(aF$`,sBD1ҥ'Q0%ifyB+mV6"p";}ȅ5HSW\CGkLطu:57WwYcx U)+z֝ByӧIZ9s|. CŤ&"}™o<V84L /PZ,N'JdhK.3dH)X^:H]V*UihNfڥԩEgAIQ(4Z! EeLNnP0zcٴ}X @!73jn 0 / (kV܋:pig)E4doKpa|Uu z=|œA TYVrU XF JkE :1=zlԩ|r`p,̙mlll;BHӼ x=zd9I50=9n KY@$Hkbn]e němZ:wRx c@:33[72(P"bht5P0D;Ei%9Zz/\S*bc2g[X_[[.V cǎ^)bX oVֳHkn8F7-1eZhkփ2"a VBB7S\_LyU733&ܕ˂O a18:?kS&Znw.:~1IzcuNnq$DJGF! YB8=3w߾) Sʲ,K9th;riaaatwnll4{= ω,^/()ԩ+QdR9ccn X !%ͭ,}PP...n[\ ARJPYt F W%3D%4_n]Ck482gY;sj[ zQu. sAY,3V ⚲Ie49lsqG1ID>촡R5 !@a6r 2vw#k D;vRYN ;,#.O*\ J|ߣZBZk\su7HU SRyYzg8-:])0_ʅv 8tX乢n/4|ʛDH4ˮ&l-ceeU @4N̛2(D^̠&/Y !.է~,3iyQR.ZX4J_)^!(e q܉66Y][-jD@Pڠ>R%5lA ى}=ϗED21ey)'9 _`llܮ~ws61yikMO=y$\*# @$Y `R^/Fdj2CFZv3?m$k-qn]X:wXC.-WEOP'Ok(K;3]  ϝa@V`sc[Qŭʺ1om TÇeXd}vvb+Zkhml ,;@NM(""j6Յpt p 6ƤeBRe)<⨄^] z0733Slw陣ǚ˗_s ooү Rl666 ̔ȔR @eYN++nd<ϓ$9$szh(%G{LKOQn޸l0|wܾ \,%tp0H}~ CpTRv}pG`ℋ<*Y, Hvv` lVmZ`McDZkz":! Wvd$iV`eY&uL]*:CDPucۙ8M+j?qRDUY9K&"XhD{`2ϛ42S|ij6X"QEQU򺇩68Ir/2Zfsp|ڵM"]`,]r)4e?wN3Y rȲ&+GfڮzcO)l6 B|tt8Ͳda?[1ݿ{;f#f]WI)+ZNZ̜3s8P.No>]/%-Gu~˸DEpC; ۶? ʲK$_[YN4]s0T0h96;;nf{Ed4T7 ;wn(1{ 6| ) ."`fV3wv#g^{&>h8Q4[vxV ]}Z1cM"-㮭cyNB$R] 㪢irABu07= \}e;=8(UQnݺ/@o!:,+Y+%{T,(=Ӵ<Ol67("5F_%UktHV׮}bKˤ-[`)r'O$ kMA/9 `=-'5 yYʖTQ5-666zbb8$Q4mnJpxxluZPYo}aZl{ibk-iR j[0 #*˚X=m3urr4uxJP,+Sl@z]-] A0N&iTDQP]G f8Npx&`Nf7v2e̡뙦~1 SR5 -J+̀ bTQ ޶]ea0rZ^ `2AA-+z=+W(]ceZdrg4. -du-a\ \%,p`x~/$ 4W6@m@u1E:0^'&D. ft8ʒ8 8IbG^~5;7w~z0<$(6YJI]'ѵMVg\ i> ?k90MdI {;LDN"rSL-hlS˅5NC=G2SεDwH+Myҗ{I !uLI.m}_7MO>`]ۦ[>>iQţ @ !,˶WڶCLgR} @OQX1\7X ;辮0b::$WJ+Xց2 ,[,d8 0D"i4 @n㞃 ]U#e@U Bo:I`[̘vc6IgNLk,kL&pm. eg.5lnhb.(jGRٴ%N;4Kl!7X,-t1\m@pbk? hq$QlhgJ@j7n{pJ\>5=.};(5ڽ{S!|6sI 9(fU1o:^(7WӐhX8v6)*^UiEȶ{cL*rmY\QskRʖTe{95,ˋ8pp۶vx]]5)[$~RN"&sX-JGaE2Yk a W\@k9 ].zy)e;B;LIS"mx}y/W԰JFQڞj@TUѴlz=SR9 A]0L͚\0tA5t~@E$\H6u Kڮu+%pqNq1L6OѼER*k áM#paO =Qp ,tvU@Qdl $S̬Yuͳ0, |QRJ-0Mc˔e,~']d6s !@y6w>|J h`<2Mrqʠ[K$uyfV,REVJ }!Ó .(H:99l>XR]KuR^oU8kdߧ(LFc<ČDg8I|>3ivaf߹u]ƍ#/J\FYE$qe-+U <>4.Q"~0@G"t@.s.[,]6lmLvU$`gz}Nydz+f u0qp狰[Ү,ΐRq*&%3 fh ASX nr2NSc6Mt_#0i#^@+Idx< Wku4/'tP苪%̓0R -߿@+z]D蘈uv%0VqH p8 f2n)E 3\X K0뚪R~뷈^}G1m[ھpG`Y|rAۂ!%mZ<xgJTy^y^y^.(PVPv*mn2ml0$(Ҩȹ`X,g-Fיi9]'=O&JIװh2DhlÉ#P X~@;;LiF{{NV泫WMaeٱ{Ǔ1L/ue𧪇e,:>% ɭ-/ ͛wY-wsB'8"*%#Mmajt<Ν%@LGh (EP?/s!'E+k]gr[[}\l?7AX-q2ܾuJa}0?P$΂ br˵fH  d2tÚ =׿5߿7g֮s߫Ţ<:7ß=O3 On8r2j_t)l\w~/y;R'yQ莎[[f-g4 9)Ulݟ>>b֕R?\X,E4 z=e*ˆn޼qEM~Q` y^Okm;Ⱥp^Sys9?0lRfRj9aTQY E ;@@kA{{x0 h/h|G#3^=eR$|4cj[?=RJiԴ NJ^C@`ss/]׶DB@v+Dw`a2x(XN?N#ϝ.b,DUU¦pzZK9-_\`ok`^/|VED.?5M~e*lM_olk},_' _CBu[_7})lqYoɟΛm'Z/Г/yW״W~(p &3G0R^@y Xm[K"0Csy939Μ[d%Vlk'G-H6*p`e,e^ < tt"9`^; nGylMlf{Q'2VHT^}'ȐZ:;{Z-}ҝ0o!@oڋ&7B7Z}):f~ )MCv/3IY'o$C/CKarEU굑ikk+z*17-6XguͶLo ~f]%y}诶ujޙˁ$%{AѼ5QϮ݂[ HZaSZ[msQIKv*>Q3 輎vr ` wBw ͘Gu񼻵;/3bi׼5k(=:.RF̓sjz<͛ǮAHs_嬤Fa]yZqM8j:t] Pzҙjv},PWvd5{6,ݴMLProf#&27.=^mlPWV[}̤ UwP5lmY_XS="wR>ΤQcv1nwfRܶEvTROYLG&:]MU4V쥱^i,vw0ױ '=4@U*/juYIENDB`ukui-screensaver/src/assets/switchUser.png0000644000175000017500000000065014205074704017734 0ustar fengfengPNG  IHDR;0oIDATH햽N0ؚR+e` 12P) OإOQ1vb):fBNJ }qe\槢HVs'@L(|^г]Í&+Zg(̵TtP141.4(kK#SLĸԠa^ClIlR떼-+bu):wx{:rhRc^=Z07NpMsfTcFxcsӮ&st>9=M`Je+Ʊs?]w!M0]+qcv Wyhsɝ;dރZZwDDQW^IENDB`ukui-screensaver/src/assets/scrollbar_down.png0000644000175000017500000000017614205074704020611 0ustar fengfengPNG  IHDR;֕JEIDAT(c\HM(05#)D׈,U36jĥiFրU#!x5/ AK.IENDB`ukui-screensaver/src/assets/combobox_down.png0000644000175000017500000000026514205074704020435 0ustar fengfengPNG  IHDR |IDATuα AwۂbVdX-rl &# 7ǟr_0H `VbRCr#yIENDB`ukui-screensaver/src/assets/unlock-button-hover.png0000644000175000017500000000104414205074704021517 0ustar fengfengPNG  IHDRJLIDATH?hSQ !@l]J?)4c fp02XRS](TC %f"nb*XQ儓yr|%wodv!:K@ .~61sXO"4U๩8j} &gC=|AGpޚzA dCʪW*as3qmzdK6c,]=b +e'yQ( wZ@ b4଄ TX6;*;+twy20tpw&< sQdRcT^i '|@d?{ cXPR~KǯST}QC@G m !D[nEy=[ȾNhh:XA2m^ 2{|Jzz92݂$2Hj d_ rF N.*D,eAIENDB`ukui-screensaver/src/assets/capslock.png0000644000175000017500000000044414205074704017374 0ustar fengfengPNG  IHDRĴl;IDAT8q@ D_%@ na[0-mB q a!|1_d|j%G%I ׼V  pyYdvAl(i qlkW#hKcl T^RTg%]Yh:%:$,6 q䂄[!ql_SbCUcUIPZ e>),LjxVт~ڮBI9`ouE'ݕ2IENDB`ukui-screensaver/src/assets/unlock-button.png0000644000175000017500000000103214205074704020373 0ustar fengfengPNG  IHDRJLIDATH?LQ?m*t"2i\k8H;1`h\& {FJ ʟjHUPk~w޻~ݽ~R7"t n7/--<ܨjnL9SVDkm z4+@! feM JpG.^8ck_ Y)sx|o6>hvM}m KivFm aP9$!yVŠ]94(- l<9nCii 3gg"qhMFW D?:0D &yJ{ k=HҊw-^UBzMU6խ-H>m,TL&p?4;<Wue Q x7t\~ ?_;0fvN5IENDB`ukui-screensaver/src/assets/scrollbar_up_clicked.png0000644000175000017500000000016314205074704021740 0ustar fengfengPNG  IHDR;֕J:IDAT(c 2pr5DkiXl54]3F4>)4 ý΄IENDB`ukui-screensaver/src/assets/powerManager.png0000644000175000017500000000076514205074704020232 0ustar fengfengPNG  IHDR;0IDATHAJAEkO f&Bv+/ 1Ⅲ'KN4+u#&?&M3ӍCV)( *{fK6/L6g<(.ylPEѣGԎ-?Yi3s#>z#c ]hxU%ǡ.8<6NyTp@Oc}g\0pY-'|%QKi&&R"-@)5Sx] bZǗa'eD*"+"2*ij}GQTɼY) k6qDz36qD6 |ø["x6@=@.)̐KۡZty-@7XA@=t%\יXO g5v1k,-BoMYeG}io6)j1or)JIENDB`ukui-screensaver/src/assets/shutdown.png0000644000175000017500000000220514205074704017445 0ustar fengfengPNG  IHDR::J(LIDAThZMh]E=תmZ?HhK[(n,ZAugn YIƭ[qEc) .jkB]ԦҀ.zwyށ;NftAe$w~|| Uk+̟6$˖j'U1?<!I\!9>GH"YX 9Ҡ~=Bv(*<:@GYO?MBm%yƩ{V CrNI#ڈjV'IvxՋ86TpeZ; -+tn1BYk\FQ %jo8m%Qt r1\1.cijΉ'ng6>RVZwlWIbB(ka(Hj2\ }f] קBB-L-꼑UXŧBBo`@| xwq˲lBhDG俍("cq3b =m9_̇mLKY X[}C#: ?T X!}\|Yw ڋiEkx/fY :\Zn#kWjDRr;$tZ~=4Ǡ* r?ɿFB_+ {0wR,iQ!˲MFj" xB'\AuD G:HaQJOw2RGu.WK穯srfZiŭ&;P+$r8j2͓ 8Q!4Y /* [ |"m$5[Fc NK %_-ƗADQgdФZ*eGrQXBfg"eB˙][zYڠ3|y5S$46P(|X/j)fF.=XT#YBc]z4760]T/hWGc;Z}[M;{ H"Q[>C޵kfvfuR巕h WjqhATʛ^AIENDB`ukui-screensaver/src/assets/bio-login.png0000644000175000017500000000026714205074704017457 0ustar fengfengPNG  IHDRw=~IDATHA@@{}m_AɄ沝Ld5sdt'GzUS$%yBa dOi/( 1j-Jy}pARe` 0tIENDB`ukui-screensaver/src/assets/scrollbar_up.png0000644000175000017500000000016314205074704020262 0ustar fengfengPNG  IHDR;֕J:IDAT(c\XMr5D Ӡl54]3F4>)4rNGIENDB`ukui-screensaver/src/assets/waiting.png0000644000175000017500000000064114205074704017236 0ustar fengfengPNG  IHDR((mhIDATXѕ E)(,b v`t~H`P xwN~+B$H@d9rgcs !&8C =6X{)pdhJύ盀07_|1-s5.?598N{bq XV@`21J/@ Hjx~kBId͘mKsɻ3a*fi{|m}.M{{&8R3!)Un. 5-CmƎ(||zyu~]%xܘs9e]35x cͳOPVHn]IENDB`ukui-screensaver/src/assets/scrollbar_up_hover.png0000644000175000017500000000016314205074704021465 0ustar fengfengPNG  IHDR;֕J:IDAT(c-\Xsh543ft8 @׌bh # OW$WIENDB`ukui-screensaver/src/assets/switchGreeter.png0000644000175000017500000000204614205074704020414 0ustar fengfengPNG  IHDR::J(IDAThYKTQ=a RlZ)EAm °u;mD~`آڕnlѮVPDJEF6]3/g\9{{J(X#Ah@%_z@ fx `=#u6œ8''HnQk\s2f43rShw醏RmQ1zH2I 1By",o5Q ` >8QqlKPQ&PG0F uc5= rXt:6a2=Bq"IcU;m=yWN-In]!P9qǬI%kZVV#ZI6yMLݎ8b\4.0|@Q;f:[DJt60"} %P(V&udJIENDB`ukui-screensaver/src/assets/authdialog.qss0000644000175000017500000001065214205074704017742 0ustar fengfengQPushButton{ text-align:center; color: rgba(255, 255, 255, 255); border: none; border-radius: 4px; outline: none; } QPushButton::hover{ background-color: rgba(255, 255, 255, 20%); } QPushButton::pressed { background-color: rgba(0, 0, 0, 30%); } QLabel { color: white; font-size: 16px; } #userWidget{ /* background: rgba(255, 0, 255, 30%);*/ } /* 头像 */ /* #faceLabel { border:2px solid white; } */ /* 用户名 */ #login_nameLabel{ font-size: 24px; } /* 密码输入框 */ QLineEdit { font-size: 14px; lineedit-password-character:9679; } QLineEdit::hover { } QLineEdit::focus{ border-radius: 4px; } /* 大写提示 */ #capsIconLabel{ background: url(:/image/assets/capslock.png); background-repeat: no-repeat; background-position: center; max-width: 22px; max-height: 22px; min-width: 22px; min-height: 22px; } /* echo mode */ #echoModeButton { background: transparent; image: url(:/image/assets/hide-password.png); max-width: 22px; max-height: 22px; margin-right: 5px; } #echoModeButton::checked { image: url(:/image/assets/show-password.png); } /* 登录按钮 */ #loginButton{ /*image: url(:/image/assets/unlock-button.png);*/ min-width: 26px; max-width: 26px; min-height: 26px; max-height: 26px; icon-size: 26px; background:#3D6BE5; border-radius:13px; } /* PAM message提示*/ #messageLabel { font-size: 16px; color: white; } #messageButton{ text-align:center; font-size: 16px; color: white; } /* 切换用户 */ QMenu{ background-color: rgba(255,255,255,20%); color: white; border-radius: 4px; width:165px; font-size: 16px; padding: 5px 5px 5px 5px; } QMenu::icon{ padding: 2px 5px 2px 5px; } QMenu::item { width:130px; border-radius: 4px; height:36px; font-size:16px; padding: 2px 10px 2px 10px; } QMenu::item:selected { border-radius: 4px; background-color:rgba(255,255,255,30%); } QMenu::item:pressed { border-radius: 4px; background-color: rgba(255,255,255,30%); } /* 虚拟键盘开启按钮、用户切换按钮 */ #btnSwitchUser, #btnKeyboard,#btnPowerManager { border-radius: 4px; } #btnKeyboard::hover, #btnSwitchUser::hover,#btnPowerManager::hover { background-color: rgba(255, 255, 255, 20%); } #btnKeyboard::pressed, #btnSwitchUser::pressed,#btnPowerManager::hover{ background: rgba(0, 0, 0, 30%); } /********************** 下拉选项 *************************/ QComboBox{ background: rgba(255, 255, 255, 20); border: 1px solid rgba(255, 255, 255, 30); font-size:18px; color: white; combobox-popup: 0; /* 配合setMaxVisibleItems设置下拉框显示的条数,超过的滚动显示 */ } QComboBox::down-arrow{ image:url(:/image/assets/combobox_down.png); } QComboBox::drop-down{ width: 30px; border: none; } QComboBox QListView{ border: 1px solid #5187bd; /* background: #4682B4;*/ background: rgba(255, 255, 255, 30%); font-size: 18px; color: white; } QComboBox QListView::item{ background: rgba(255, 255, 255, 0); } QComboBox QListView::item:hover{ background: rgba(255, 255, 255, 20%); } QComboBox QListView::item:selected{ background-color: rgba(255, 255, 255, 30%); } /********************** 生物识别切换按钮 **************************/ #biometricButton, #passwordButton, #otherDeviceButton, #retryButton, #OKButton { background: rgba(255, 255, 255, 0); font-size: 16px; color: white; } #biometricButton::hover, #passwordButton::hover, #otherDeviceButton::hover, #retryButton::hover, #OKButton::hover { background: rgba(255, 255, 255, 20%); border: 0px; } #biometricButton::pressed, #passwordButton::pressed, #otherDeviceButton::pressed, #retryButton::pressed, #OKButton::pressed { background: rgba(0, 0, 0, 20%); border: 0px; } /********************** 生物识别设备选择界面 ************************/ #lblBioetricDevicesPrompt { font-size: 30px; color: white; } #lblDeviceType, #lblDeviceName, #cmbDeviceType, #cmbDeviceName{ font-size: 18px; } /***********************关机界面**********************************/ QListWidget{ background:transparent; border: 0px; } QListWidget::item:hover{ background:rgba(255, 255, 255, 20%); border-radius: 4px; border: none; } QListWidget::item:selected background:rgba(255, 255, 255, 20%); border: none; border-radius: 4px; } ukui-screensaver/src/assets/intel/0000755000175000017500000000000014205074704016200 5ustar fengfengukui-screensaver/src/assets/intel/icon-wired.png0000644000175000017500000000074514205074704020754 0ustar fengfengPNG  IHDRw=sRGBDeXIfMM*i5uOIDATH UANAE8\wNABx| ? \MIZݛ6 鮪鞝$ɿ,E|Qb#yM1yMyd!F",i0^ 8Wm#G mV<;qIǂyxk& ḚgEg6aaxUxՅm(LTwB?~;`123y-mpD_iӒo絴A$:ٴ[rhu*ֹ6xtFߚkܥc@W6{Mvc$;zL:q-Mh J\8ݙEW&>5WҌ_}IENDB`ukui-screensaver/src/assets/intel/wechat.png0000644000175000017500000000062214205074704020161 0ustar fengfengPNG  IHDRaYIDAT8OӱKa)h!*A! qrhpZp"R$j*ZԈBǕ2dǿ~\:"?SfC F=zy fl@$IENDB`ukui-screensaver/src/assets/intel/message.png0000644000175000017500000000107514205074704020335 0ustar fengfengPNG  IHDRw=IDATHKMhAӤɶ&545ЃX*4O*͓ୠQPx&zQ]K JC!UJHlҏmMv99of[naࡀI)S`[kqMK\BuؗEWHcf-7e)VXM뢷eN\b='eH`9S [Hp6Z~edTͥ/Ըv))`9[Mt~FBn\;6d픦r336`G-ޤLWu՘:s6/KMS:"}b jp}-q|fOaNw/u.e=h==xPw3+̮,LUj\?7:v̶}e-NdIENDB`ukui-screensaver/src/assets/intel/cancel.png0000644000175000017500000000045314205074704020135 0ustar fengfengPNG  IHDRaIDAT8O1jA`+x6z)SDb 9D! S 4x`̆'uYQXfv \HZՀEp7J7}@X ρ+$08R%)z̮ZP-p |}vz_ҳuY{^&D`tV H^V`{1X,π;IJE`{=p XZ..'I׊wg(`6 L.&HwM|8 Koc 3#;Ԍe{3E X_Y ༤ǶGEBXJ:m{p\<^ n -̍lQ=0"A }}ޅdWۀyy%2YR['^~JS'm!kI t%ofNPJkf^іA*0~WJ uR>JlgYTD$5ڎ%}+郮9Ȫ*Us(=IUI$zZ .fVK*Ov˒ZmLj']%SwBh]^\'W`{eQiٮ &'sbτ;c&k$*^ReL523V74L5JIENDB`ukui-screensaver/src/assets/intel/icon-wifi.png0000644000175000017500000000122114205074704020566 0ustar fengfengPNG  IHDRw=XIDATHK͕ۋq?Ln%k"R%cB")$E˃!5Hm xp(M K{Ggƙ9g4So绿e}D?3>D`tV H^V`{1X,π;IJE`{=p XZ..'I׊wg(`6 L.&HwM|8 Koc 3#;Ԍe{3E X_Y ༤ǶGEBXJ:m{p\<^ n -̍lQ=0"A }}ޅdWۀyy%2YR['^~JS'm!kI t%ofNPJkf^іA*0~WJ uR>JlgYTD$5ڎ%}+郮9Ȫ*Us(=IUI$zZ .fVK*Ov˒ZmLj']%SwBh]^\'W`{eQiٮ &'sbτ;c&k$*^ReL523V74L5JIENDB`ukui-screensaver/src/assets/intel/logout.png0000644000175000017500000000100314205074704020211 0ustar fengfengPNG  IHDR((mIDATXG혽.DQ' 6 JѨuJGBU(4BȊN% 9r]{#v-vwfܙsψE̬Mu2AʷlXƊ:M=>>IF `J{F'Iإ0x0m^QQDZO9I.=Abfwr.i:Z}A|ÌwxݱSLR񛇌wYe#dOvުͲ>84h IENDB`ukui-screensaver/src/assets/intel/sms.png0000755000175000017500000000050314205074704017511 0ustar fengfengPNG  IHDRa IDAT8Ocd0O[o&,f=fϔ?}#24z 2?6(g0c~ J$tkiaO} cAA;V=}慃ۊvO[d=A3uf蛹*0`<{AV 3Yϔ2ߔf.d``df8@dddŃe  Q gBX`|$1\By4RaIDbPkϓyIENDB`ukui-screensaver/src/assets/intel/slide_unlock.png0000644000175000017500000000063014205074704021360 0ustar fengfengPNG  IHDR szz_IDATXG픽+aB,LQY RMd"' N2Yٌ۱ٰEu{szߓ:=}&KM'b1F ]eIE`rY7u ^c`[Uf6L@/Бw Z0Ufk:0.?Guh-Hr_0V`i];n.!dfcd!M 86%y/%[KyB髙K20skߵ>`3OrؓtǴF"mlHe< fx J̩Fkhf ҬH\@EF@L &D]!μ+IENDB`ukui-screensaver/src/assets/intel/icon-wechat-noqrcode.png0000644000175000017500000000643614205074704022730 0ustar fengfengPNG  IHDRF IDATxyE'Hm+PR@LRF "ȍV@[,A@P*(DQ | ك$aIMlT}Lz."H$D"H$D"H$D"H$D"H$D"[5 `=8EU/H>#"P"~"":IpMC)"DTU%I.|d"rzޑ&q΍N+;Yꑈw[-O"upMUuI 4+QT. tttG%/9V Qv G2ƘZ)Je2?f F,/ڧ8U Q=Cm)'F"'u[[idU" }{J҆9^$"[ I~X<>t,rGT'9 "1 Ƙ˒Dб<"rB+ú t2 f H~3t2-IC'" cHЁɓH.2l:v@Dn Eܸ )9MQD3\,"CW$|NUE Y`i c]:@gȩCG򾔓RƯT*y~kt#QDfWUR<[{ec;V3ЁʚDRϊr΍A׍%g6R8t"Y@rA|7ZmSrY'eTZI!~qέJ$/w\_%x:S-Uչ;IǑ̀}CC?D c T퐖$Wl"GeL$S9AE@1W}[-9s`kge%Ri6vH$E䊖ZɷXKrn=۸e dIfTuGJKSK()ei۶-ɺfuEv`-+lCO8E_eYU/"VfH$XIX,j֋ιkxKl %ݽYj [|ODvI3B۔3 ǤJIz1꼒ZC۔(|#<_(t΍WB۔%.J9VON{Ot$د:'UcRՉ:sy\p&ݝsk'; `1ު]z*BlgO1'o3}!pTp1zzz6FT_Lm+D?Gsdɒ V6n ?_ŽșO!"N&duݛS wOM52|$ox^Ƙ$OkݡQvY,"w#iPf_X<#3$O :97PX~A\FJė*n y(tb4Tp^xts1K匪Nܫ0jnytqέgxIZ9aH:9pBZ97d1T:|u=%y}T,/WNafVkv)%2U={ι1z"PG MD'iOHpxȬJ2\.("<9Yl!"ȕiȂTPG2j3@L= B!q)zMڞ$ BADv rɫA5 x`Q$'KBa3Z<*xPX"^}jGҫ0x@rCNP(1r@ulgW) ޯ6'vFuK)8V y{Շm+f ( @ $ճ#ϡ'uvvn2 $]ga.ɩs# j,cS"J) T"[xx z>c"r5n%y=8RufxmS- V5qFDfzZu5wH+6ˍ"HD#9>qx.24@ckHU4AUꝡS yoo[z!FiKl40Ɇ 2'sKBǥP-#Ƙ2<.3 ^px#vRX%Kl@ 1H.3:FUC31[P. {W@{[`<6jRׅw[#+Jn>=(mwzzzhBDVFR9HeM$*^;x48zuG-$'G˨꾡INHzZhEZ?'3 êeFZ+^Oapέ `f򮚗G\S1oOs⡪zy^Z!a­1\uV@$D(F`N_|0GgWi 1rele=c<̊[@)OPW;o3fAا Tn{),KFC_@~W]IWN.VbقUA84IENDB`ukui-screensaver/src/assets/intel/delete.svg0000644000175000017500000000636314205074704020173 0ustar fengfeng ukui-screensaver/src/assets/intel/powerManager.png0000644000175000017500000000107614205074704021341 0ustar fengfengPNG  IHDRw=IDATHK aZJòdل @! D%(hb%ȊPwFQȑܙa;̜{eOO X nz>Erf}U@Y>0d;5sZX ,S? >_%U@&] sXHDd|SV 7hV}'` xK`0^p8\WSx%XnMA#"4<\4W4 :KqM-pm*@"b#𠰊lU4^DT .?;<`zUdi -;*7 ^l9yOT‰lWVd'{>ܖ4,6A[  pm !z2  ? ǸIENDB`ukui-screensaver/src/assets/intel/shutdown.png0000644000175000017500000000205114205074704020557 0ustar fengfengPNG  IHDR((mIDATXGK]S蘁xDBI*a]600QhsHڒ"Q BhCxK{~"޳{u<_|8 cuZ/YGHzFI_F*a3'JI`D 86AFeyX)k"`DRX\;'zK$E {ϴ"X#)k67f=\ҕI7 C$}5؊u%GX8x?56KZ=VNDܐ6J ,E:ǔ>򙏟{##d'E/#2&L?c%}R`DܕgvHZ7-`m.HwK37Elw `Dk=D;%FIkSJ]d=tրJzmN_&9vzwϿ:F.":frHgK%0ZpkJݾn [-;S+_'4 D`DvG@5 }-n~K'"%-L{ԺA_nX·VV7*3֤mϝĖ`Dܚg959f?[;4fZ}5|Y}cgbqrC<Wz8Wgfplx+^܅l#½97 ܥ~^LgpSlƮ[_瑱d!yo7r̲tmJmU"8ԇJcb݀<ڞj, s^9_ef 8!:O8-IENDB`ukui-screensaver/src/assets/intel/qr-reload.png0000644000175000017500000004353714205074704020610 0ustar fengfengPNG  IHDR dsBITOtEXtSoftwaregnome-screenshot> IDATx}6Umlcxc1a@qJR?"U E* p & PƐxg]K|ӺjIVU;UI]c=Qs/1&59ƨWB"ISPJJ4DJW.ՊqxJ{9M/!TW]W ̟bPPIZOlJ)2 ";lQmg̺|zއue)}Q:5PZ\u"sՕf]̸ mA+Zkx!Zl-b.9?==eE"BRzzzZ`0ķ)~'ҳ3t%$ڇ Y+4E! /Ψ"5 ^C0>PJ?|Ok)a4+蜪YE!eb\aձ}G.xgw*"Q' 2}Z(/f .0s]9ڋ{ݾf7kuB CqJ \]wx8ιecܷ+FGvԄu4|Dن`M/Hۇܺu+Cd-rrΕy߿}v)^ /|4Fcn6F؇u]Ӫr6uX-VvՇpkqdqtUjZW<ոvmqdSSTwawMFѻqM\1d1Wq槈d4kJPU (e6B2Ϲ8S_Duj??p8"=Eq[Vv.97s Cs\.c QF逳3{> v{0k89&w' Vkuzna!4wE i8nJ(V?G'e0&d[.QTc]@+D#ER@ K=z]BY!ܔ%Ow)bP2geͮ7pI6C#}Mk|Wd.t3\: 7Uy]vMgd#؇ʓlNik`+W*nY:PGM] FCZzMjp]]ԡ2ԎF( *DIR~ަbؒd^oQZᥑ%bL{vU9_,z]+įPA:@6ݻZhTp$ٞ>ҝky4MLv167Պmkv]~W9*o5j1w?T,دeUk먞z7܄V֮d~e X*UȤ1w2B[ˮ)fuUgp VEKsl}q6Ԏx= fჃC <$#.u&7z86#Iis?W}[D.Z*K뙟k\pA~l+ϠRkvϿɕvinIOeem=0lR5:r*a-Кo.L\VB?r^fL)v)[)d>W_i&6pCr9{ctYjjkF)?V+|ޟޭ:6+j_y m3uf*E\gm7ْltqT4͖e'NJ/Z|L!P+vzzjKJcx|5E~xxjY.qQAKO9gPu|>c:}o"? 0nLMR&p19 y1s9$BKKӄqD|khnSTӻaR_աI1n)]QzNڝvUPJXcw\4$|B"9ij@t1&)ιٟJ^7$I|NL3BA&@Ƀ:>VoD(L,cڥDQ]qZ(n:VibnՈo6Rg|f3̏V,Ij?Vt{]L<JW`M|&&7~_0VѰ٬KeaxJH> [u>eI^Zug~ ]1Vd lZp:%Tf`9T7~'chbG/~,WSYG%gJء{ѯ0,/B0 (fbb :^|nbTIYմO=WK6=*Фy-0Gځ)NNSj*UNPj#$Is&Rw :\2 DV3m$ٮVX-]-!`fi8)ږt<."njWu]@Vt: "NcyѺ9NΘ87]&:wjp'fRRڷ^/4>׫2[$d9k7DvLRgggY<|L>aO>4Mͱhݾ]oi[jB1`}Zd_rzWNOPp ۄڜ E Y"eܕVb|S6h\ɟl(*eu#]gq6E\>+T7K%~JK؋X;?y7DTjUJa8cdpRӏQ*uQDcg@Pp75 tVEćjWgsQ(!Vϗn]f$!osK$(#s',ns) Q D167 !@=y1'.Ca%ߒ3(R `)}/+0Te^/K"xPsCoݾM.^\:0!"GJwVX!5\:.;`Xwn!4Dԋ$ܥ&8>99Dt]`@^=?Im Ay#7s@k4e&:YZ4(&c(W`f>U#2zWbjz .$Df$-RN9+fΰ$5tmXw2J>6f<:4pH&y@r)Ł:קR*(\ւ1VbJ! p)e;ks:6uUJ_T}`w*y+U,vV]1JYf0J)1bXd“Uh<Ӕ LDbbBC&rGM5P8,΀aQbo s!R!6CsąJ8nX(Km !mfn6rˋBY14D.0Ɗ2Wvlltm|ҥh._i' 6b?yly@Zl6[,s!bW%|qQɩ۾z v KKj&.10u{8j5r3H)!7MUVc"J1wQp8l8&Kl4M !Tn6:|h/JcdWbj*O\ dHmJS$]gkݻW`0dX3"I\LU׳VA}6՟C5)FeQdʄ{Ho⧞z'V뉰fsqDe |%g RF"pfd+; Ce5کr%ݖc,MS*d4=WnMqݻ$NBGQ$p9J ??{1` ]ȚfђJcFcXHD-b]AG%Ut:Ѣ=햙aPK9a[ۢ]hF2D`0#35흟!|>` dv^+a5qzze$z\]@ynb{Z#/-x?q)eT1IM>t=z9;@9PIJ < \˃V0n: " Jg=*kAt7M\V}rr"&4ME&fOy@a\EPLvT)jn9 @><Ii"$\5u +C~S,9TGá~W<~0T_Qx:L&PW;wIJnA,:?-p>z6jŹErڈmU.ҩUdWX(;f G҉cr("iK<>)8$ _o~>s?c^V"b!"(yib1&L7vY6kυyu*\\9hv{猽//~K͒QP\dDTzX:Dތ|fqwMV减Nl6_e;W?p4MR*(" ='ʌ^[z[$L4E7W\ʟw8, _g} _RűO};>0 X)}Ł"o^\ޕL.S0j$[ջEtb\\Q0H Ŧvah>:j,泟?=Ԟv5Sw}[՚Nvu)ÃlvPSqkzi0l#ƙzMi)(F#!^o'sI۔C`XG˗U+׿o V_s.`8!9Sۍm=Q!gN+%$r L9a) 'OkSʤ F+d2A(===PBGGg޽+b4oee`*`"T Ŋ&adsE:5]3Bh8k~_DXD<~=B~'onyPt+B@48M%TXCmŢ 5-B.ZJ8V)2HsnՌytz|{~ѿ~׷9H}ů}y'>xj 4XdB;UeϞ/z]#e]x@QX?0Q DIqmыjw.z[ !C?c/:\@"ZO>(X񖃇$E^UoǭVaa!IREqvi|ƚ~gwC !?ӿ˿2Oo|_tNXQ"Ld^G8nf-9z[eFlo?<8㖧FCiNZvcu IDATu[rIi#JeW3LEK9E?;?{BozSnO<< gqTUk\:_*:^,HP;/ 0i]$I8;Mŗ^B=76H.ܳo翿/};@!HJSa-pEHDH e9xf+<Pخ ]nL.ĦvK{p_?.rxxMӳL*Dq|-Ep)看S2 t鞘f{wQpjN'6!$r߾} !}rIf٢bC#+gӍPg_M{vgR}wsls^v*s0蟞{oKpd&7K{vWµ k~2@b4"f@%Ʋ]WZKS=PsWC\EYIHЄ]PHL%Ѽ7o<<4߽27 8;)y1t>C lBFSaN]@tkn > hʉ( 1dzYka8BHuX{7@X2ߨNn|t7ÇS.1Iq{^7@[rd2.0`L=TD{ Ҕjq$_~9RL&~̷s~p0e!8==+~_-ZSJJ<$$&!`ע4܈ᔤ X*S󙵘fmEKҔ0Bt݄gy3ܗjU3.g?ےx 4"pfIyi!37 W]qnc\ă?r7rMZ˘ܗR뢸!g>Lf~ )"FX7*6ج\ik"xSW|d)?b= ǧXaxgߟ}͞_6}3~JSyyUu˝.Ã+;XRnVq(AJ|UjmD=S`:&>O `"I!;:ʎSptL+[-׿HS곖Tv>|SxF c qD\\)xC}h>{ۣ>W/u;564wp FrJT`7ܨăyLw3D l6M@b0^~&mGRb0bX,Nt;z}_Y_yGBqx0j\.ŵv58owW$ٮ{hd\,ZUNplun7~Ƀh]vŭ|@|K~yidL\'š#4o^x_xW~C~3o??U'Qd2D]rOU$Ij{'Z]|Gv޵gq!dKr:OSɢ٬|~'!ZvF_泿+\.B'(<{q|+ SZX!Vp1W[D~<;;VJ2c,"Ҕ"6v!?~Z??y%9b?O_繁rH$3MP,}ݴ}|QHٌn& c![ZzdRd3^A#jkzh*8vs^$Z!k^<9Z#iY6t]-W5川N[;;E4M)MT\FE+:v[{ӛ3oxC'Ew:qB"R,Sv]t [kIɣ\҄+:PTb0]:u(r'T,zWM8&y7 @S#o_m6$~}ozx<8<8lDѪs.`jÈKr]ǺDJ >=ۿ^w7E\d ]AV^KpSswj,jKTR=7^ gө=|ts(,NI׫twƮ æҽucdr96̓}˜3$sܺuKLjCҴ(m `@+WH<C~G^БԤ(mGCtz~~VWl٬pGB"9 "\hLLy0Zj h-zK7 9B,b&W_o@LSqQ*Fe GWSp˃OWj4m2N)guN]ŋ/:-[RLϪ cUP]ijU^j5Yey#ȓW7t_." "`B.Hļ 8bX|+_A. qtb\Nʔ2Ȯi!ں@jʲfט)Hf0H$ 4闿eQ0?,\ԼP(b6D0 GIYxRqlOOO'!v!uhMw T !4 |*&K+b8Q1F3NO9[,NOO_~d\3 ~As:ɅmN"5/Z`wK`pX.fZ$Ufy-H#5&Y:勆{5:jVVPhE +c l /pttxWcٹjM}r-= 59bʷ z OnoDt Ə_rBQ1Lf_L&;w騅Jf H,Lk$dPIQ_sd3"\-ePg&>'CH@1Ra <ڹ 8猱W_}Çբt:yW(\hܩ[BCc ,5"̅rɎ{&MgUprrg:һ-$ZJOcM?)onX,EUrř"tCQz=Q18fr{^S6f6OSJ4M3^4DXY6Rj1ikfЄҤ{f9r=|^"D}v 1fʮ; vJX3Ą猱['҉.ob>GQt:~`L,l6M ]J-\_ &ҥmdWD֗<]ɮombfnS7WBDRnc~qܯ~k7g~܀,5;8BE8ORbĉ4Mtsjq?KR9KS*($vZ/W+m(WHx R@Χ+-]*LX[ sέ. P6Ɋ;䟑-}%*r8𪔾<;5B0c\K).1ƔR#@i$!'i*0?Q)B %Z8=)^ҷZsܺ}4z,qln=H‡K%|jzwk2$qёUAH-cX7TDS@ar;Xz9c𦪐M6;l: ; v ]}%mSm 1G ;`7cRdüef߂2՜3kJLggՁЧJ4:MnU(`_E-\ϩl91&q5/*n5Q@ T:ոZ6{^\}g)u:!*jɹ!?;pH~{xql#uj*:~/ ֩z ϴƕ]KӔX)Bv*DIqB)vj{/մkJCY"[RR#8:l2+3Yv8ƑE_}; mNQCj58^q#@6iIG,/KH}h9fN'UKQsQ|xtE1-X,f&9H+IG 9><0pqq!lP@,.qL (5A' If?׍ځt9{&aC^"Æ1JpJSrr$($sz/bڱ)+y U3c~] ** rii|2fs d/Q?ũ cSiET9tUv}w1ނ0 XŽȎw<)կdEx!~li8/Axجg@C%kK; ?nʒ_dc[j4_C5_JG|]+Vr+.״®{:#)܍$温7a?Y^yU+5Ty4JpwVj1a*DF3?_c4>?%es~qܛ $οѧaf\j!";ݮŒ$Y.Z~i?pIvcOk1Gc"_aO~SxgOaN #TT~j/BH ιOdL0n:EҔjX,fpqKˎEĔ]8BN74H,fb|KhRt{i%ιqVLd݉\p5?PXr5 9s-3,S<*sΙ8F:W[# -(_qsX:f1لj?r5Z=ϮC×E)yF~v]>@w-U|H@Y䋪$ɉIֳpU$gEp(Hsu-6)}Qi3E<YC[ChSʦ# \4, 15Z4iOR[/~fֿXfE8hFfxhl܃E±nN7w̶mi1N$IrY#lvuvnq[AZaYkQT5_4nw+4"f6' hD>6zYx`Bn߾]G*hg%Or^rN8"`=Ti1T ZNfyīF9f ;Fe' ӽ#Um!5q+Xjɉ'EE@wxHT$6'і2t}gĹgjiR<֒יY2(%RUTZyzW:F:﷮ʕ捺 +`znuCs4N8n|PcÒU^E 7?өV~KJmӀؿѲ&o]22]%da R-f,o~dʺ֊|*ێQO #/Ez]o J[n.H4H0iNEjlޢ?Ag~"< 6$[󠎉vV<Ԟ\Ql(U$VbNet ddfEAԜ:Vxw&E:z7'zNJ 9ZnL?-mz*'Kiv%e_˸x6Mv511yn9"06Wȣ+cVA#@Z/vTK$RHqιkUDqHK9'ĭ-n<'<2G$ʴx8wF}2NbQhn3'*DobjªrYD陧qstǎII4t:&_P AQ6@Ѵ8+3M ̀1f s&ǯwp ;m|fOG!![\IDATE¬.Xi_im1KHVS@ڒ-vh2Rj{dXgZJʳTadՍz ]_PwMV_c/rgZ쪳!*֩U֪(x&.(8m],]W}f'O@[OͥwoFp8Rl6O8#<=*3M -Bgk%ff,5c7"L&QX_&RR>B9ZfZr0Np-7BhMs{)~P|0t{Ȋ^GޤijD]fl6+`1Vn&XAp& Uq+6v/gͿ-̏?ܠ=amħ-5=4?s%jtjnv#ܠ=az&رIz=ywg j,*b%zF n4Y@ْJ-Dy*l%ePEj #ZFܺ6)ASnRV"VKYrjS{^@r_jMq~'R5bYk 0nHQj(*!@ou!fH6|x7?Joi&]W< KGg7(m[TCP]bg],4o_ UcU/zfE˴|=pS֛kW*kL%lin`FٜRVp\z),27W\5!Y.hJMit|cbHaiBf".<$gF8k>>n*sƎ:b7dC:I DF ^wr8{|i;\}X:E: '#tp 4ʎHjНsomdCo`n"r݆7^301~y u39~/A (CZ \7$'׎o`20T-9s&"'XmqFs}[>`)o7`h&`Xtu5BvVsӚh櫔elkZe57-Pca%\UVsx/&X'B7vaCaks[q^oI֗EQ~ŃSy)Tn8/:1hh)W Q+2e $Uh+5 kIENDB`ukui-screensaver/src/assets/intel/pin.png0000644000175000017500000000044514205074704017477 0ustar fengfengPNG  IHDRaIDAT8O1+Fa+IIٔɦL g)ɠl2 6o tqS'ss?#=&I`X+@}LwX`U}Bg6^I6K\i$ހ u*Lr lSg G5" \mY8Ph :paHW>rXe"]lofĒ,p8 W}"zCoi![lZkmʭ֒I_r @ITRXR  A[JaIAD #w-N9}Si[;jy"z3$[ fRni|,RXR *ݻ΁u),)R]fmLA4\r),)R-\3] pg+ZrKaIAD4Nhw}EL}LRM?έ4d)HUsW_6!b>]n[ K $r]d)9.θ‰`fI,)RsK;ߙөn K $rGPƔKPrj%%Y 2EI4Rh":%Y r9=ڏ](r#.jNE7+%Y -;Ɉy-{&iZ&D5xl KAr`fqܰJJHޙT3ƽےI_\ֱ^=7N),)Rb6bTr+[n) o-7sc;r#487(%)$HAf3TZ'IENDB`ukui-screensaver/src/assets/intel/keyboard.png0000755000175000017500000000045514205074704020515 0ustar fengfengPNG  IHDRw=IDATHKmB1 ν0G&&ݠZ(AO<[?;vDP}f|Ѐ )3AwA~:KI50ڒfvj2`&iSxLr2` O|/𞦓 kI> $Ӛ)x9 pxPA;$cz.q*0Ɓ+`C}0pxS#$ہkuc[:|deU*Iupo5/rk֮UT@fW!u4pzOd_@T(f%IENDB`ukui-screensaver/src/assets/keyboard.png0000644000175000017500000000025314205074704017373 0ustar fengfengPNG  IHDR;0rIDATHK \WFPUC͈)Y#",~۪W4Gݚ (O꼪a~& {gSتUȮn~U-c%vKae ]0(hIENDB`ukui-screensaver/src/assets/iconFace.svg0000644000175000017500000000147614205074704017325 0ustar fengfengavatar_128ukui-screensaver/src/iconedit.h0000644000175000017500000000371014205074704015533 0ustar fengfeng/* iconedit.h * Copyright (C) 2018 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, 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. **/ #ifndef ICONEDIT_H #define ICONEDIT_H #include #include #include #include #include class IconEdit : public QWidget { Q_OBJECT public: IconEdit(QWidget *parent = 0); void setIcon(const QString &text); void setIcon(const QIcon &icon); void clear(); void clearText(); void setPrompt(const QString &); const QString text(); void setType(QLineEdit::EchoMode type = QLineEdit::Password); void startWaiting(); void stopWaiting(); void setX11Focus(); //void setEnabled(bool enabled); protected: void resizeEvent(QResizeEvent *) Q_DECL_OVERRIDE; bool eventFilter(QObject *obj, QEvent *event); private: void updatePixmap(); Q_SIGNALS: void clicked(const QString &); void focusOut(); public Q_SLOTS: void clicked_cb(); void onCapsStateChanged(); private: QLineEdit *m_edit; QLabel *m_capsIcon; QPushButton *m_iconButton; QPushButton *m_modeButton; QTimer *m_timer; QPixmap m_waitingPixmap; QString m_iconText; //文字作为图标 QIcon m_icon; }; #endif // ICONEDIT_H ukui-screensaver/src/monitorwatcher.h0000644000175000017500000000302214205074704016776 0ustar fengfeng/* monitorwatcher.h * Copyright (C) 2018 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, 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. **/ #ifndef MONITORWATCHER_H #define MONITORWATCHER_H #include #include #include /*! * \brief The MonitorWatcher class * 监控显示器的插拔 */ class MonitorWatcher : public QThread { Q_OBJECT public: MonitorWatcher(QObject *parent=nullptr); ~MonitorWatcher(); QSize getVirtualSize(); int getMonitorCount(); Q_SIGNALS: void monitorCountChanged(int newCount); void virtualSizeChanged(const QSize &newVirtualSize); protected: void run(); private: QSize getMonitorMaxSize(const QString &drm); QMap drmStatus; QSize virtualSize; int monitorCount; bool firstDetect; }; #endif // MONITORWATCHER_H ukui-screensaver/src/powermanager.cpp0000644000175000017500000005276214205074760016774 0ustar fengfeng /* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include #include #include #include #include #include #include #include #include "powermanager.h" 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"); #ifdef USE_INTEL PowerManager::PowerManager(QWidget *parent) : QWidget(parent), lasttime(QTime::currentTime()) { resize((ITEM_WIDTH*4 + ITEM_SPACING*3), ITEM_HEIGHT); initUI(); setQSS(); } #else PowerManager::PowerManager(QWidget *parent) : QListWidget(parent), lasttime(QTime::currentTime()) { // resize(ITEM_WIDTH*7, ITEM_HEIGHT); setFlow(QListWidget::LeftToRight); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setSelectionMode(QListWidget::NoSelection); QObject::connect(this,SIGNAL(itemClicked(QListWidgetItem*)),this,SLOT(powerClicked(QListWidgetItem*))); sessionInterface = new QDBusInterface("org.gnome.SessionManager", "/org/gnome/SessionManager", "org.gnome.SessionManager", QDBusConnection::sessionBus(), this); loginInterface = new QDBusInterface(login1Service, login1Path, login1ManagerInterface, QDBusConnection::systemBus(), this); QDBusReply stateReply = loginInterface->call("CanSuspend"); if(stateReply.isValid() && stateReply.value() == "yes"){ canSuspend = true; }else{ canSuspend = false; } QDBusReply stateReply1 = loginInterface->call("CanHibernate"); if(stateReply1.isValid() && stateReply1.value() == "yes"){ canHibernate = true; }else{ canHibernate = false; } initUI(); resize(ITEM_WIDTH*this->count(), ITEM_HEIGHT); } void PowerManager::powerClicked(QListWidgetItem *item) { int interval = lasttime.msecsTo(QTime::currentTime()); if(interval < 200 && interval > -200) return ; lasttime = QTime::currentTime(); QString name = itemWidget(item)->objectName(); // if(name == lockWidget->objectName()) // lockWidgetClicked(); if(switchWidget && name == switchWidget->objectName()) switchWidgetClicked(); else if(name == logoutWidget->objectName()) logoutWidgetCliced(); else if(name == rebootWidget->objectName()) rebootWidgetClicked(); else if(name == shutdownWidget->objectName()) shutdownWidgetClicked(); else if(suspendWidget && name == suspendWidget->objectName()) suspendWidgetClicked(); else if(hibernateWidget && name == hibernateWidget->objectName()) hibernateWidgetClicked(); } #endif void PowerManager::lockWidgetClicked() { emit lock(); } void PowerManager::switchWidgetClicked() { emit switchToUser(); } #ifdef USE_INTEL void PowerManager::shutdownWidgetClicked() { QDBusInterface *interface = new QDBusInterface("org.gnome.SessionManager", "/org/gnome/SessionManager", "org.gnome.SessionManager", QDBusConnection::sessionBus(), this); QDBusMessage msg = interface->call("powerOff"); qDebug() << "[PowerManager] [shutdownWidgetClicked]" << msg.errorMessage(); } void PowerManager::rebootWidgetClicked() { QDBusInterface *interface = new QDBusInterface("org.gnome.SessionManager", "/org/gnome/SessionManager", "org.gnome.SessionManager", QDBusConnection::sessionBus(), this); QDBusMessage msg = interface->call("reboot"); qDebug() << "[PowerManager] [rebootWidgetClicked]" << msg.errorMessage(); } void PowerManager::logoutWidgetCliced() { QDBusInterface *interface = new QDBusInterface("org.gnome.SessionManager", "/org/gnome/SessionManager", "org.gnome.SessionManager", QDBusConnection::sessionBus(), this); QDBusMessage msg = interface->call("logout"); qDebug() << "[PowerManager] [logoutWidgetCliced]" << msg.errorMessage(); } void PowerManager::initUI() { this->setContentsMargins(0,0,0,0); QHBoxLayout *main_layout = new QHBoxLayout(this); main_layout->setContentsMargins(0,0,0,0); main_layout->setSpacing(0); lockWidget = new QWidget(this); lockWidget->setContentsMargins(0,0,0,0); lockWidget->setFixedSize(ITEM_WIDTH,ITEM_HEIGHT); QPushButton *lockPB = new QPushButton(lockWidget); QLabel *lockLabel = new QLabel(lockWidget); lockPB->setProperty("class", "PowerManagerPB"); lockPB->setIcon(QIcon(QPixmap(":/image/assets/intel/lock.png").scaled(40,40))); lockLabel->setAlignment(Qt::AlignBottom | Qt::AlignHCenter); lockLabel->setText(tr("lock")); QVBoxLayout *locklayout = new QVBoxLayout(lockWidget); locklayout->setContentsMargins(0,0,0,0); locklayout->addWidget(lockPB); locklayout->addWidget(lockLabel); connect(lockPB, &QPushButton::clicked, this, [=]{ qDebug() << "PowerManager lock clicked"; Q_EMIT lock(); }); logoutWidget = new QWidget(this); logoutWidget->setContentsMargins(0,0,0,0); logoutWidget->setFixedSize(ITEM_WIDTH,ITEM_HEIGHT); QPushButton *logoutPB = new QPushButton(logoutWidget); QLabel *logoutLabel = new QLabel(this); logoutPB->setProperty("class", "PowerManagerPB"); logoutPB->setIcon(QIcon(QPixmap(":/image/assets/intel/logout.png").scaled(40,40))); logoutLabel->setText(tr("Log Out")); logoutLabel->setAlignment(Qt::AlignBottom | Qt::AlignHCenter); QVBoxLayout *logoutlayout = new QVBoxLayout(logoutWidget); logoutlayout->setContentsMargins(0,0,0,0); logoutlayout->addWidget(logoutPB); logoutlayout->addWidget(logoutLabel); connect(logoutPB, &QPushButton::clicked, this, [=]{ qDebug() << "PowerManager logout clicked"; logoutWidgetCliced();; }); rebootWidget = new QWidget(this); rebootWidget->setFixedSize(ITEM_WIDTH,ITEM_HEIGHT); rebootWidget->setContentsMargins(0,0,0,0); QPushButton *rebootPB = new QPushButton(rebootWidget); QLabel *rebootLabel = new QLabel(this); rebootPB->setProperty("class", "PowerManagerPB"); rebootPB->setIcon(QIcon(QPixmap(":/image/assets/intel/reboot.png").scaled(40,40))); rebootLabel->setText(tr("Restart")); rebootLabel->setAlignment(Qt::AlignBottom | Qt::AlignHCenter); QVBoxLayout *rebootlayout = new QVBoxLayout(rebootWidget); rebootlayout->setContentsMargins(0,0,0,0); rebootlayout->addWidget(rebootPB); rebootlayout->addWidget(rebootLabel); connect(rebootPB, &QPushButton::clicked, this, [=]{ qDebug() << "PowerManager reboot clicked"; //rebootWidgetClicked(); reboot(); }); shutdownWidget = new QWidget(this); shutdownWidget->setFixedSize(ITEM_WIDTH,ITEM_HEIGHT); shutdownWidget->setObjectName("shutdownWidget"); QPushButton *shutdownPB = new QPushButton(shutdownWidget); QLabel *shutdownLabel = new QLabel(shutdownWidget); shutdownPB->setProperty("class", "PowerManagerPB"); shutdownPB->setIcon(QIcon(QPixmap(":/image/assets/intel/shutdown.png").scaled(40,40))); shutdownLabel->setText(tr("Power Off")); shutdownLabel->setAlignment(Qt::AlignBottom | Qt::AlignHCenter); QVBoxLayout *shutdownlayout = new QVBoxLayout(shutdownWidget); shutdownlayout->setContentsMargins(0,0,0,0); shutdownlayout->addWidget(shutdownPB); shutdownlayout->addWidget(shutdownLabel); connect(shutdownPB, &QPushButton::clicked, this, [=]{ qDebug() << "PowerManager shutdown clicked"; //shutdownWidgetClicked(); powerOff(); }); main_layout->addWidget(lockWidget); main_layout->addSpacing(ITEM_SPACING); main_layout->addWidget(logoutWidget); main_layout->addSpacing(ITEM_SPACING); main_layout->addWidget(rebootWidget); main_layout->addSpacing(ITEM_SPACING); main_layout->addWidget(shutdownWidget); adjustSize(); } //息屏,休眠状态Hibernate/挂起Suspend bool PowerManager::hibernate() { const QString service = "org.freedesktop.login1"; const QString path = "/org/freedesktop/login1"; const QString interface = "org.freedesktop.login1.Manager"; QString command = QLatin1String("Suspend"); QDBusInterface dbus(service, path, interface, QDBusConnection::systemBus()); if (!dbus.isValid()) { qWarning() << "dbusCall: QDBusInterface is invalid" << service<< path << interface << "Suspend"; return false; } QDBusMessage msg = dbus.call(command, QVariant(true)); if (!msg.errorName().isEmpty()) { qWarning() << "Debus error: " << msg; } if (msg.arguments().isEmpty() || msg.arguments().constFirst().isNull()) return true; QString response = msg.arguments().constFirst().toString(); qDebug() << "systemd:" << QLatin1String("Suspend") << "=" << response; return response == QLatin1String("yes") || response == QLatin1String("challenge"); } bool PowerManager::reboot() { const QString service = "org.freedesktop.login1"; const QString path = "/org/freedesktop/login1"; const QString interface = "org.freedesktop.login1.Manager"; QString command = QLatin1String("Reboot"); QDBusInterface dbus(service, path, interface, QDBusConnection::systemBus()); if (!dbus.isValid()) { qWarning() << "dbusCall: QDBusInterface is invalid" << service<< path << interface << "Reboot"; return false; } QDBusMessage msg = dbus.call(command, QVariant(true)); if (!msg.errorName().isEmpty()) { qWarning() << "Debus error: " << msg; } if (msg.arguments().isEmpty() || msg.arguments().constFirst().isNull()) return true; QString response = msg.arguments().constFirst().toString(); qDebug() << "systemd:" << QLatin1String("Reboot") << "=" << response; return response == QLatin1String("yes") || response == QLatin1String("challenge"); } bool PowerManager::powerOff() { const QString service = "org.freedesktop.login1"; const QString path = "/org/freedesktop/login1"; const QString interface = "org.freedesktop.login1.Manager"; QString command = QLatin1String("PowerOff"); QDBusInterface dbus(service, path, interface, QDBusConnection::systemBus()); if (!dbus.isValid()) { qWarning() << "dbusCall: QDBusInterface is invalid" << service<< path << interface << "PowerOff"; return false; } QDBusMessage msg = dbus.call(command, QVariant(true)); if (!msg.errorName().isEmpty()) { qWarning() << "Debus error: " << msg; } if (msg.arguments().isEmpty() || msg.arguments().constFirst().isNull()) return true; QString response = msg.arguments().constFirst().toString(); qDebug() << "systemd:" << QLatin1String("PowerOff") << "=" << response; return response == QLatin1String("yes") || response == QLatin1String("challenge"); } void PowerManager::setQSS() { //设置电源管理按键样式 QString style_sheet = ".PowerManagerPB{" "background:rgba(255,255,255,38);" "min-width: 128px;" "max-width: 128px;" "min-height: 128px;" "max-height: 128px;" "border-radius: 64px;" "icon-size: 40px;" "font-family: NotoSansCJKsc-Regular, NotoSansCJKsc;" "}" ".PowerManagerPB:hover{" "background:rgba(255,255,255,89);" "}" ".PowerManagerPB:pressed{" "background:rgba(255,255,255,12);" "}"; setStyleSheet(style_sheet); } #else void PowerManager::suspendWidgetClicked() { loginInterface->call("Suspend",true); emit lock(); } void PowerManager::hibernateWidgetClicked() { loginInterface->call("Hibernate",true); emit lock(); } void PowerManager::shutdownWidgetClicked() { sessionInterface->call("powerOff"); } void PowerManager::rebootWidgetClicked() { sessionInterface->call("reboot"); } void PowerManager::logoutWidgetCliced() { sessionInterface->call("logout"); } void PowerManager::showSmallSize() { for(int i = 0;iitem(i); item->setSizeHint(QSize(ITEM_WIDTH*0.8,ITEM_HEIGHT)); itemWidget(item)->setFixedSize(ITEM_WIDTH*0.8,ITEM_HEIGHT); } resize(ITEM_WIDTH*this->count()*0.8,ITEM_HEIGHT); } void PowerManager::showNormalSize() { for(int i = 0;iitem(i); item->setSizeHint(QSize(ITEM_WIDTH,ITEM_HEIGHT)); itemWidget(item)->setFixedSize(ITEM_WIDTH,ITEM_HEIGHT); } resize(ITEM_WIDTH*this->count(),ITEM_HEIGHT); } void PowerManager::initUI() { /* lockWidget = new QWidget(this); lockWidget->setObjectName("lockWidget"); QLabel *lockFace = new QLabel(this); QLabel *lockLabel = new QLabel(this); lockFace->setAlignment(Qt::AlignCenter); lockLabel->setAlignment(Qt::AlignCenter); lockFace->setPixmap(QPixmap switchWidget = new QWidget(this); switchWidget->setObjectName("switchWidget"); QLabel *switchFace = new QLabel(this); QLabel *switchLabel = new QLabel(this); switchFace->setAlignment(Qt::AlignCenter); switchLabel->setAlignment(Qt::AlignCenter); switchFace->setPixmap(QPixmap(":/image/assets/switchGreeter.png").scaled(58,58)); switchLabel->setText(tr("Switch User")); switchWidget->setFixedSize(ITEM_WIDTH,ITEM_HEIGHT); QVBoxLayout *switchlayout = new QVBoxLayout(switchWidget); switchlayout->addWidget(switchFace); switchlayout->addWidget(switchLabel); switchWidget->installEventFilter(this);(":/image/assets/lock.png").scaled(58,58)); lockLabel->setText(tr("Lock Screen")); lockWidget->setFixedSize(ITEM_WIDTH,ITEM_HEIGHT); QVBoxLayout *locklayout = new QVBoxLayout(lockWidget); locklayout->addWidget(lockFace); locklayout->addWidget(lockLabel); lockWidget->installEventFilter(this); */ actService = new QDBusInterface("org.freedesktop.Accounts", "/org/freedesktop/Accounts", "org.freedesktop.Accounts", QDBusConnection::systemBus()); QDBusMessage ret = actService->call("ListCachedUsers"); QList outArgs = ret.arguments(); QVariant first = outArgs.at(0); const QDBusArgument &dbusArgs = first.value(); dbusArgs.beginArray(); QDBusObjectPath path; int userCount =0; while (!dbusArgs.atEnd()) { userCount++; dbusArgs >> path; } dbusArgs.endArray(); switchWidget=nullptr; if(userCount>1){ switchWidget = new QWidget(this); switchWidget->setObjectName("switchWidget"); QLabel *switchFace = new QLabel(this); QLabel *switchLabel = new QLabel(this); switchFace->setAlignment(Qt::AlignCenter); switchLabel->setAlignment(Qt::AlignCenter); switchFace->setPixmap(QPixmap(":/image/assets/switchGreeter.png").scaled(58,58)); switchLabel->setText(tr("Switch User")); switchWidget->setFixedSize(ITEM_WIDTH,ITEM_HEIGHT); QVBoxLayout *switchlayout = new QVBoxLayout(switchWidget); switchlayout->addWidget(switchFace); switchlayout->addWidget(switchLabel); switchWidget->installEventFilter(this); } logoutWidget = new QWidget(this); logoutWidget->setObjectName("logoutWidget"); QLabel *logoutFace = new QLabel(this); QLabel *logoutLabel = new QLabel(this); logoutFace->setAlignment(Qt::AlignCenter); logoutLabel->setAlignment(Qt::AlignCenter); logoutFace->setPixmap(QPixmap(":/image/assets/logout.png").scaled(48,48)); logoutLabel->setText(tr("Log Out")); logoutWidget->setFixedSize(ITEM_WIDTH,ITEM_HEIGHT); QVBoxLayout *logoutlayout = new QVBoxLayout(logoutWidget); logoutlayout->addWidget(logoutFace); logoutlayout->addWidget(logoutLabel); logoutWidget->installEventFilter(this); rebootWidget = new QWidget(this); rebootWidget->setObjectName("rebootWidget"); QLabel *rebootFace = new QLabel(this); QLabel *rebootLabel = new QLabel(this); rebootFace->setAlignment(Qt::AlignCenter); rebootLabel->setAlignment(Qt::AlignCenter); rebootFace->setPixmap(QPixmap(":/image/assets/reboot.png").scaled(58,58)); rebootLabel->setText(tr("Restart")); rebootWidget->setFixedSize(ITEM_WIDTH,ITEM_HEIGHT); QVBoxLayout *rebootlayout = new QVBoxLayout(rebootWidget); rebootlayout->addWidget(rebootFace); rebootlayout->addWidget(rebootLabel); rebootWidget->installEventFilter(this); shutdownWidget = new QWidget(this); shutdownWidget->setObjectName("shutdownWidget"); QLabel *shutdownFace = new QLabel(this); QLabel *shutdownLabel = new QLabel(this); shutdownLabel->setAlignment(Qt::AlignCenter); shutdownFace->setAlignment(Qt::AlignCenter); shutdownFace->setPixmap(QPixmap(":/image/assets/shutdown.png").scaled(58,58)); shutdownLabel->setText(tr("Power Off")); shutdownWidget->setFixedSize(ITEM_WIDTH,ITEM_HEIGHT); QVBoxLayout *shutdownlayout = new QVBoxLayout(shutdownWidget); shutdownlayout->addWidget(shutdownFace); shutdownlayout->addWidget(shutdownLabel); shutdownWidget->installEventFilter(this); if(userCount>1){ QListWidgetItem *item1 = new QListWidgetItem(); item1->setSizeHint(QSize(ITEM_WIDTH, ITEM_HEIGHT)); insertItem(this->count(), item1); setItemWidget(item1, switchWidget); } hibernateWidget = nullptr; if(canHibernate){ hibernateWidget = new QWidget(this); hibernateWidget->setObjectName("hibernateWidget"); QLabel *hibernateFace = new QLabel(this); QLabel *hibernateLabel = new QLabel(this); hibernateLabel->setAlignment(Qt::AlignCenter); hibernateFace->setAlignment(Qt::AlignCenter); hibernateFace->setPixmap(QPixmap(":/image/assets/hibernate.png").scaled(48,48)); hibernateLabel->setText(tr("Sleep")); hibernateWidget->setFixedSize(ITEM_WIDTH,ITEM_HEIGHT); QVBoxLayout *hibernatelayout = new QVBoxLayout(hibernateWidget); hibernatelayout->addWidget(hibernateFace); hibernatelayout->addWidget(hibernateLabel); hibernateWidget->installEventFilter(this); QListWidgetItem *item6 = new QListWidgetItem(); item6->setSizeHint(QSize(ITEM_WIDTH, ITEM_HEIGHT)); insertItem(this->count(), item6); setItemWidget(item6, hibernateWidget); } suspendWidget = nullptr; if(canSuspend){ suspendWidget = new QWidget(this); suspendWidget->setObjectName("suspendWidget"); QLabel *suspendFace = new QLabel(this); QLabel *suspendLabel = new QLabel(this); suspendLabel->setAlignment(Qt::AlignCenter); suspendFace->setAlignment(Qt::AlignCenter); suspendFace->setPixmap(QPixmap(":/image/assets/suspend.png").scaled(48,48)); suspendLabel->setText(tr("Suspend")); suspendWidget->setFixedSize(ITEM_WIDTH,ITEM_HEIGHT); QVBoxLayout *suspendlayout = new QVBoxLayout(suspendWidget); suspendlayout->addWidget(suspendFace); suspendlayout->addWidget(suspendLabel); suspendWidget->installEventFilter(this); QListWidgetItem *item5 = new QListWidgetItem(); item5->setSizeHint(QSize(ITEM_WIDTH, ITEM_HEIGHT)); insertItem(this->count(), item5); setItemWidget(item5, suspendWidget); } QListWidgetItem *item2 = new QListWidgetItem(); item2->setSizeHint(QSize(ITEM_WIDTH, ITEM_HEIGHT)); insertItem(this->count(), item2); setItemWidget(item2, logoutWidget); QListWidgetItem *item3 = new QListWidgetItem(); item3->setSizeHint(QSize(ITEM_WIDTH, ITEM_HEIGHT)); insertItem(this->count(), item3); setItemWidget(item3, rebootWidget); QListWidgetItem *item4 = new QListWidgetItem(); item4->setSizeHint(QSize(ITEM_WIDTH, ITEM_HEIGHT)); insertItem(this->count(), item4); setItemWidget(item4, shutdownWidget); } #endif ukui-screensaver/src/test-accounts.cpp0000644000175000017500000000164514205074704017071 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include "users.h" #include int main(int argc, char *argv[]) { QCoreApplication app(argc, argv); Users users; qDebug() << users.getUserByName("kylin"); return 0; } ukui-screensaver/src/ukui-screensaver-command.cpp0000644000175000017500000000715314205074704021204 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include #include #include #include #include #include #include #include "types.h" #define WORKING_DIRECTORY "/usr/share/ukui-screensaver" int main(int argc, char **argv) { QCoreApplication a(argc, argv); QString locale = QLocale::system().name(); QTranslator translator; QString qmFile = QString(WORKING_DIRECTORY"/i18n_qm/%1.qm").arg(locale); translator.load(qmFile); a.installTranslator(&translator); QCommandLineParser parser; parser.setApplicationDescription(QCoreApplication::translate("main", "Start command for the ukui ScreenSaver.")); parser.addHelpOption(); parser.addVersionOption(); QCommandLineOption lockOption({"l", QStringLiteral("lock")}, QCoreApplication::translate("main", "lock the screen immediately")); QCommandLineOption queryOption({"q", QStringLiteral("query")}, QCoreApplication::translate("main", "query the status of the screen saver")); QCommandLineOption unlockOption({"u", QStringLiteral("unlock")}, QCoreApplication::translate("main", "unlock the screen saver")); QCommandLineOption screensaverOption({"s", QStringLiteral("screensaver")}, QCoreApplication::translate("main", "show the screensaver")); parser.addOption(lockOption); parser.addOption(queryOption); parser.addOption(unlockOption); parser.addOption(screensaverOption); parser.process(a); if(!parser.isSet(lockOption) && !parser.isSet(queryOption) && !parser.isSet(unlockOption) && !parser.isSet(screensaverOption)) return -1; QDBusInterface *interface = new QDBusInterface(SS_DBUS_SERVICE, SS_DBUS_PATH, SS_DBUS_INTERFACE); QDBusReply stateReply = interface->call("GetLockState"); if(!stateReply.isValid()){ qWarning()<< "Get state error:" << stateReply.error(); return 0; } if(parser.isSet(queryOption)){ if(stateReply) qDebug()<call("Lock"); if(msg.type() == QDBusMessage::ErrorMessage) qDebug() << msg.errorMessage(); }else if(parser.isSet(unlockOption)){ QDBusMessage msg = interface->call("UnLock"); if(msg.type() == QDBusMessage::ErrorMessage) qDebug() << msg.errorMessage(); }else if(parser.isSet(screensaverOption)){ QDBusMessage msg = interface->call("ShowScreensaver"); if(msg.type() == QDBusMessage::ErrorMessage) qDebug() << msg.errorMessage(); } return 0; } ukui-screensaver/src/sessionwatcher.h0000644000175000017500000000247114205074704017001 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef SESSIONWATCHER_H #define SESSIONWATCHER_H #include #include #include #include #include class SessionWatcher : public QObject { Q_OBJECT public: explicit SessionWatcher(QObject *parent = nullptr); Q_SIGNALS: void sessionIdle(); private Q_SLOTS: void onStatusChanged(unsigned int status); void onSessionRemoved(const QDBusObjectPath &objectPath); void onConfigurationChanged(QString key); private: QString sessionPath; QGSettings *settings; int idleDelay; QTimer *m_timer = nullptr; }; #endif // SESSIONWATCHER_H ukui-screensaver/src/common.h0000644000175000017500000000647314205074760015240 0ustar fengfeng/** * Copyright (C) 2018 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, 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. **/ #ifndef LOCKCOMMON_H #define LOCKCOMMON_H enum SwitchPage{ SwitchToPin = 0, SwitchToWechat, SwitchToCheck, SwitchToResetPWD, SwitchToConfigPWD }; // 和后台规定好的 错误码固定值 enum DBusMsgCode{ Error_QR_Get_Timeout = -8, // 二维码获取时间超时 Error_NetWork = -7, // 网络错误 未能如期获得对应的数据 Error_VerifyCode_Timeout = -6, // 验证码失效 Error_RepeatedRequests = -5, // 重复请求二维码服务 Error_NoReply = -4, // DBus接口连接失败导致的无回复错误 Error_UnknownReason = -3, // 未知原因 Error_ArgCnt = -2, // 参数个数错误 Error_SetPsw_SameAsOriPsw = -1, // 设置新密码时 与原密码相同 No_Error = 0, // 获取消息无错误 Error_TelHaveBinded = 9009, // 手机号已绑定 -> 更换手机号后再试 Error_VerifyCodeDiff = 9000, // 验证码错误 -> 请填写正确的验证码 Error_AccessTokenInvalid = 9007,// Access Token 失效 -> 登录状态已过期,请重新扫码登录 Error_ErrTimesOverMax = 9014, // 手机号登录时验证码错误次数超限 // 账号密码登录时密码错误次数超限 // 1小时内连续错10次触发 -> 1小时后再试 Error_UserInfo = 9017, // 用户微信信息不存在 ->老用户,联系管理员处理 Error_WechatHaveBinded = 9022, // 微信号已被其他账号绑定 -> 更换微信号再试 Error_DeviceHaveBinded = 9027, // 当前设备已被绑定 -> 请联系管理员或班主任解绑 Error_HaveBindOtherDevice = 9028, // 用户已绑定其他设备 -> 请联系管理员或班主任解绑 //以下错误码保留 Error_NWUnused = 6, // 网络异常,请检查网络链接哦~ Error_TencentUnused = 7, // 腾讯服务异常,请稍后再试~ Error_NWDelay = 28, // 网络延迟大,请更换良好网络~ Error_ResMalloc = 301, // 资源分配异常,请重启尝试 Error_DBOpen = 101, // 数据库打开异常,请重试,或重启再试 Error_DBGetKey = 102, // 获取数据库密钥失败,请重试 Error_DBRetrieve = 103, // 数据库检索数据失败,请重试 Error_DBDecryption = 105, // 数据库解密过程失败,请重试 }; /*! * \brief The QRCodeSwepState enum * WaitingSwep 在DBus、SSOBackend、1.617 版本中未启用 */ enum QRCodeSwepState{ WaitingSwep = 0, //等待用户扫码 HaveSwep = 2, // 用户扫码、等待用户确认 CancelSwep = 3, // 用户扫码后、取消确认 ConfirmSuccess = 4, // 扫码确认成功 QRCodeInvalid = 5, // 二维码失效 QRCodeTimeout = 6, //二维码超时 }; #endif // LOCKCOMMON_H ukui-screensaver/src/screensaver.h0000644000175000017500000000371214205074704016257 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef SCREENSAVER_H #define SCREENSAVER_H #include #include #include enum SaverMode { SAVER_BLANK_ONLY = 0, SAVER_RANDOM, SAVER_SINGLE, SAVER_IMAGE, SAVER_DEFAULT, SAVER_DEFAULT_CUSTOM }; enum TransitionEffect { TRANSITION_NONE, TRANSITION_FADE_IN_OUT }; class ScreenSaver : public QObject { Q_OBJECT public: SaverMode mode; //path is a directory or a file path if mode is SAVER_IMAGE QString path; QString lastPath; //for images saver TransitionEffect effect; int interval; private: int imageIndex; QTimer *timer; QStringList imagePaths; Q_SIGNALS: void imagePathChanged(const QString &path); public: explicit ScreenSaver( QObject *parent=nullptr); explicit ScreenSaver(const ScreenSaver &screensaver); ScreenSaver(ScreenSaver &&screensaver) noexcept; bool exists(); void startSwitchImages(); void stopSwitchImages(); bool timerStatus(); friend QDebug &operator<<(QDebug stream, const ScreenSaver &screensaver); }; Q_DECLARE_METATYPE(ScreenSaver) QDebug &operator<<(QDebug stream, const ScreenSaver &screensaver); #endif // SCREENSAVER_H ukui-screensaver/src/grab-x11.cpp0000644000175000017500000000441314205074704015613 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #include "grab-x11.h" #include #include #include class XServerGraber{ public: XServerGraber() { xcb_grab_server(QX11Info::connection()); } ~XServerGraber() { xcb_ungrab_server(QX11Info::connection()); xcb_flush(QX11Info::connection()); } }; static bool grabKeyboard() { int rv = XGrabKeyboard(QX11Info::display(), QX11Info::appRootWindow(), True, GrabModeAsync, GrabModeAsync, CurrentTime); return (rv == GrabSuccess); } static bool grabMouse() { #define GRABEVENTS ButtonPressMask | ButtonReleaseMask | PointerMotionMask | \ EnterWindowMask | LeaveWindowMask | KeyPressMask | KeyReleaseMask int rv = XGrabPointer(QX11Info::display(), QX11Info::appRootWindow(), True, GRABEVENTS, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); #undef GRABEVENTS return (rv == GrabSuccess); } bool establishGrab() { XSync(QX11Info::display(), False); XServerGraber xserverGraber; Q_UNUSED(xserverGraber); if(!grabKeyboard()) return false; if(!grabMouse()) { XUngrabKeyboard(QX11Info::display(), CurrentTime); XFlush(QX11Info::display()); return false; } return true; } bool closeGrab() { XSync(QX11Info::display(), False); XServerGraber xserverGraber; Q_UNUSED(xserverGraber); XUngrabKeyboard(QX11Info::display(), CurrentTime); XUngrabPointer(QX11Info::display(), CurrentTime); XFlush(QX11Info::display()); return true; } ukui-screensaver/src/permissioncheck.cpp0000644000175000017500000003216314205074760017464 0ustar fengfeng/** * Copyright (C) 2018 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, 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 "permissioncheck.h" #include #include #include #include #include "common.h" #include "wechatauthdialog.h" VerificationWidget::VerificationWidget(QWidget *parent) : QWidget(parent) { qDebug() << "PermissionCheck"; resize(1000,355); QHBoxLayout *mainLayout = new QHBoxLayout(this); setLayout(mainLayout); WeChatAuthDialog *m_weChatWidget; PhoneAuthWidget *m_phoneAuthWidget; m_weChatWidget = new WeChatAuthDialog(1,this); mainLayout->addWidget(m_weChatWidget, 1, Qt::AlignLeft); mainLayout->addSpacing(400); m_phoneAuthWidget = new PhoneAuthWidget(this); mainLayout->addWidget(m_phoneAuthWidget, 1, Qt::AlignRight); connect(m_phoneAuthWidget, &PhoneAuthWidget::pageMessage, this, [=](SwitchPage s, QList list){ Q_EMIT pageMessage(s, list); }); } void VerificationWidget::paintEvent(QPaintEvent *) { int x1 = width() / 2; int y1 = height() / 4; int x2 = x1; int y2 = height() / 3 * 2 + y1; QLinearGradient linearGra(QPoint(x1, y1), QPoint(x2, y2)); linearGra.setColorAt(0, QColor(238, 238, 238, 0)); linearGra.setColorAt(0.5, QColor(255, 255, 255, 138)); linearGra.setColorAt(1, QColor(216, 216, 216, 0)); QPainter painter(this); QBrush brush(linearGra); painter.setPen(Qt::transparent); painter.setBrush(brush); painter.drawRoundedRect(QRect(x1, y1, 4, height() / 3 * 2), 16, 16); } InputInfos::InputInfos(QWidget *parent): QWidget(parent) { initUI(); initConnect(); setQSS(); } void InputInfos::initUI() { setFixedWidth(316); QGridLayout *mainLayout = new QGridLayout(this); setLayout(mainLayout); mainLayout->setColumnStretch(1, 0); mainLayout->setColumnStretch(2, 1); mainLayout->setColumnStretch(3, 0); m_pPhoneIconLB = new QLabel(this); m_pPhoneIconLB->setPixmap(QPixmap(":/images/icon-phone.png")); mainLayout->addWidget(m_pPhoneIconLB, 0, 1, 1, 1, Qt::AlignLeft); m_pPhoneLE = new QLineEdit(this); m_pPhoneLE->setPlaceholderText("手机号"); m_pPhoneLE->setProperty("class", "InputLine"); m_pPhoneLE->setValidator(0); mainLayout->addWidget(m_pPhoneLE, 0, 2, 1, 2, Qt::AlignLeft); m_pVerCodeIconLB = new QLabel(this); m_pVerCodeIconLB->setPixmap(QPixmap(":/images/icon-sms.png")); mainLayout->addWidget(m_pVerCodeIconLB, 1, 1, 1, 1, Qt::AlignLeft); m_pVerCodeLE = new QLineEdit(this); m_pVerCodeLE->setPlaceholderText("短信验证码"); m_pVerCodeLE->setProperty("class", "InputLine"); m_pVerCodeLE->setValidator(0); mainLayout->addWidget(m_pVerCodeLE, 1, 2, 1, 1, Qt::AlignLeft); m_pGetVerCodeBT = new QPushButton(this); m_pGetVerCodeBT->setText("获取验证码"); m_pGetVerCodeBT->setEnabled(false); m_pGetVerCodeBT->setFocusPolicy(Qt::NoFocus); m_pGetVerCodeBT->setProperty("class", "GetCodeBT"); m_pGetVerCodeBT->setCursor(QCursor(Qt::PointingHandCursor)); mainLayout->addWidget(m_pGetVerCodeBT, 1, 3, 1, 1, Qt::AlignLeft); m_pNextGetVerCodeQTimer = new QTimer(this); m_curInputState = InputState::InputWaiting; } void InputInfos::initConnect() { connect(m_pPhoneLE, &QLineEdit::textChanged, this, &InputInfos::onPhoneTextChanged); connect(m_pVerCodeLE, &QLineEdit::textChanged, this, &InputInfos::onVerCodeTextChanged); connect(m_pNextGetVerCodeQTimer, &QTimer::timeout, this, &InputInfos::onNextGetVerCodeTimer); connect(m_pGetVerCodeBT, &QPushButton::clicked, this, &InputInfos::onGetVerCode); } void InputInfos::setQSS() { QString style_sheet = ".InputLine{" "padding:10px 2px 10px 2px;" "}" ".GetCodeBT{" "background:rgba(0,0,0,0);" "color:rgba(38,38,38,115);" "font-size:16px;" "}"; setStyleSheet(style_sheet); adjustSize(); } void InputInfos::paintEvent(QPaintEvent *) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); painter.setPen(Qt::white); painter.setBrush(Qt::white); painter.drawRoundedRect(rect(), 16, 16); painter.setPen(QColor(226, 226, 226)); painter.drawLine(QLineF(0, m_pPhoneIconLB->y() + m_pPhoneIconLB->height() + 1, width(), m_pPhoneIconLB->y() + m_pPhoneIconLB->height() + 1)); } void InputInfos::onPhoneTextChanged(const QString &text) { if(text.length() == 11){ m_pGetVerCodeBT->setEnabled(true); m_pGetVerCodeBT->setFocusPolicy(Qt::NoFocus); m_pGetVerCodeBT->setStyleSheet("color:#2FB3E8;"); if(m_pVerCodeLE->text().length() == 6){ Q_EMIT InputStateChanged(InputState::InputFinish); m_curInputState = InputState::InputFinish; } } else { m_pGetVerCodeBT->setEnabled(false); m_pGetVerCodeBT->setStyleSheet("color:rgba(38, 38, 38, 115);"); if(InputState::InputFinish == m_curInputState) { m_curInputState = InputState::InputWaiting; Q_EMIT InputStateChanged(InputState::InputWaiting); } } } void InputInfos::onVerCodeTextChanged(const QString &text) { if(text.length() == 6 && m_pPhoneLE->text().length() == 11) { Q_EMIT InputStateChanged(InputState::InputFinish); m_curInputState = InputState::InputFinish; } else if(m_curInputState == InputState::InputFinish) { Q_EMIT InputStateChanged(InputState::InputWaiting); m_curInputState = InputState::InputWaiting; } } void InputInfos::clearInfos() { m_pPhoneLE->clear(); m_pVerCodeLE->clear(); if(m_curInputState == InputState::InputFinish) { m_curInputState = InputState::InputWaiting; Q_EMIT InputStateChanged(m_curInputState); } } QString InputInfos::getVerificationCode() { return m_pVerCodeLE->text(); } QString InputInfos::getPhoneNumer() { return m_pPhoneLE->text(); } void InputInfos::onGetVerCode() { m_pGetVerCodeBT->setEnabled(false); m_pGetVerCodeBT->setStyleSheet("color:rgba(38, 38, 38, 115);"); m_nextGetVerCodeTime = 60; m_pGetVerCodeBT->setText("重新获取(60s)"); m_pNextGetVerCodeQTimer->start(1000); } void InputInfos::onNextGetVerCodeTimer() { --m_nextGetVerCodeTime; m_pGetVerCodeBT->setText("重新获取(" + QString::number(m_nextGetVerCodeTime) + "s)"); if(m_nextGetVerCodeTime == 0) { m_pNextGetVerCodeQTimer->stop(); m_pGetVerCodeBT->setEnabled(true); m_pGetVerCodeBT->setFocusPolicy(Qt::NoFocus); m_pGetVerCodeBT->setText("获取验证码"); m_pGetVerCodeBT->setStyleSheet("color:#2FB3E8;"); return; } } PhoneAuthWidget::PhoneAuthWidget(QWidget *parent) { initUI(); initConnect(); setQSS(); } void PhoneAuthWidget::initUI() { QVBoxLayout *phoLayout = new QVBoxLayout(this); phoLayout->setMargin(0); m_pPhoTitleLB = new QLabel(this); m_pPhoTitleLB->setText(tr("Verification by phoneNum")); m_pPhoTitleLB->setProperty("class", "titleLB"); phoLayout->addWidget(m_pPhoTitleLB, 0, Qt::AlignHCenter); m_pPhoPromptMsgLB = new QLabel(this); m_pPhoPromptMsgLB->setText(tr("「 Use bound Phone number to verification 」")); m_pPhoPromptMsgLB->setProperty("class", "PromptText"); phoLayout->addWidget(m_pPhoPromptMsgLB, 0, Qt::AlignHCenter); m_pPhoErrorMsgLB = new QLabel(this); m_pPhoErrorMsgCloneLB = new QLabel(this); m_pPhoErrorMsgLB->setProperty("class", "ErrorMsg"); m_pPhoErrorMsgCloneLB->setProperty("class", "ErrorMsg"); hidePhoneErrorMsg(); phoLayout->addWidget(m_pPhoErrorMsgLB, 0, Qt::AlignHCenter); phoLayout->addWidget(m_pPhoErrorMsgCloneLB, 0, Qt::AlignHCenter); m_pPhoInputInfos = new InputInfos(this); phoLayout->addWidget(m_pPhoInputInfos, 0, Qt::AlignHCenter); m_pPhoSubmitBT = new QPushButton(this); m_pPhoSubmitBT->setFocusPolicy(Qt::NoFocus); m_pPhoSubmitBT->setText(tr("commit")); m_pPhoSubmitBT->setProperty("class", "BindBT"); m_pPhoSubmitBT->setCursor(QCursor(Qt::PointingHandCursor)); m_pPhoSubmitBT->setEnabled(false); phoLayout->addSpacing(8); phoLayout->addWidget(m_pPhoSubmitBT, 0, Qt::AlignHCenter); phoLayout->addStretch(1); } void PhoneAuthWidget::initConnect() { connect(m_pPhoInputInfos, &InputInfos::InputStateChanged, this, &PhoneAuthWidget::onInputStateChanged); connect(m_pPhoSubmitBT, &QPushButton::clicked, this, &PhoneAuthWidget::onSubmitBTClick); connect(m_pPhoInputInfos, &InputInfos::getVerCode, this, &PhoneAuthWidget::onGetVerCode); } QSize PhoneAuthWidget::sizeHint() const{ return QWidget::sizeHint(); } void PhoneAuthWidget::hidePhoneErrorMsg() { m_pPhoErrorMsgCloneLB->setFixedHeight(m_pPhoErrorMsgLB->height()); m_pPhoErrorMsgCloneLB->show(); m_pPhoErrorMsgLB->hide(); } void PhoneAuthWidget::showPhoneErrorMsg() { m_pPhoErrorMsgLB->show(); m_pPhoErrorMsgCloneLB->hide(); } void PhoneAuthWidget::onInputStateChanged(InputInfos::InputState input_state) { if(input_state == InputInfos::InputState::InputFinish) { m_pPhoSubmitBT->setEnabled(true); m_pPhoSubmitBT->setFocusPolicy(Qt::NoFocus); m_pPhoSubmitBT->setStyleSheet("background:#2FB3E8;"); } else { m_pPhoSubmitBT->setEnabled(false); m_pPhoSubmitBT->setStyleSheet("background:rgba(255,255,255,115);"); } } void PhoneAuthWidget::onSubmitBTClick() { QString tel = m_pPhoInputInfos->getPhoneNumer(); QString verCode = m_pPhoInputInfos->getVerificationCode(); if (true) { //验证成功 qDebug() << "-----------onSubmitBTClick"; Q_EMIT pageMessage(SwitchPage::SwitchToResetPWD, QList()); } // DBusMsgCode msgCode = SSOP->m_pRetrievePwdInterface->CheckVerificationCode(tel, verCode); // switch (msgCode) { // case DBusMsgCode::No_Error: // emit pageMessage(PageMessage::JumpToNewPswSet, QList()); // break; // // TODO 更新提交后的错误状态 // default: // break; // } } void PhoneAuthWidget::onGetVerCode() { // DBusMsgCode msgCode = SSOP->m_pRetrievePwdInterface->GetVerificationCode(Cfg->getUsername(), m_pPhoInputInfos->getPhoneNumer()); // switch (msgCode) { // case DBusMsgCode::No_Error: // // 验证码获取无错误 // break; // // TODO 更新错误状态 // default: // break; // } } void PhoneAuthWidget::onQRCodeStateChanged(QString username, QString password, int nState) { QRCodeSwepState state = static_cast(nState); switch (state) { case QRCodeSwepState::WaitingSwep: qDebug() << "info: [QRCodePhoneAuthWidget][onQRCodeStateChanged]: waiting user swep qrcode!"; break; case QRCodeSwepState::HaveSwep: qDebug() << "info: [QRCodePhoneAuthWidget][onQRCodeStateChanged]: user has swep code!"; break; case QRCodeSwepState::CancelSwep: qDebug() << "info: [QRCodePhoneAuthWidget][onQRCodeStateChanged]: user cancel swep code!"; break; case QRCodeSwepState::ConfirmSuccess: { qDebug() << "info: [QRCodePhoneAuthWidget][onQRCodeStateChanged]: user = [" << username << "] confirm success!"; // if(username != Cfg->getUsername()) // { // resetQRCService(); // // TODO 更新错误信息 // } // else // emit pageMessage(PageMessage::JumpToNewPswSet, QList()); // break; } case QRCodeSwepState::QRCodeInvalid: { qDebug() << "info: [QRCodePhoneAuthWidget][onQRCodeStateChanged]: qrcode invalid!"; // resetQRCService(); break; } default: break; } } void PhoneAuthWidget::setQSS() { QString style_sheet =".PromptText{" "font-size:24px;" "color: rgba(255,255,255,192);" "}" ".BindBT{" "background:rgba(255,255,255,115);" "width:316px;" "height:64px;" "border-radius:16px;" "}" ".ErrorMsg{" "color:#FD625E;" "font-size:14px;" "}" ".titleLB{" "color:#FFFFFF;" "font-size:32px;" "}"; setStyleSheet(style_sheet); } ukui-screensaver/src/fullbackgroundwidget.h0000644000175000017500000000700514205074704020144 0ustar fengfeng/* * Copyright (C) 2018 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 3, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * **/ #ifndef FULLBACKGROUNDWIDGET_H #define FULLBACKGROUNDWIDGET_H #ifndef QT_NO_KEYWORDS #define QT_NO_KEYWORDS #endif #include #include "types.h" #include #include #include #include "logind.h" #include "config.h" void x11_get_screen_size(int *width,int *height); class LockWidget; class XEventMonitor; class MonitorWatcher; class Configuration; class QDBusInterface; class TabletLockWidget; class FullBackgroundWidget : public QWidget , public QAbstractNativeEventFilter { Q_OBJECT public: explicit FullBackgroundWidget(QWidget *parent = nullptr); void paintEvent(QPaintEvent *event); void closeEvent(QCloseEvent *event); void showEvent(QShowEvent *event); virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override; void mouseMoveEvent(QMouseEvent *e); void mousePressEvent(QMouseEvent *e); void onScreensaver(); void onBlankScreensaver(); void closeScreensaver(); void setIsStartup(bool val); public Q_SLOTS: void onCursorMoved(const QPoint &pos); void lock(); void showLockWidget(); void showScreensaver(); int onSessionStatusChanged(uint status); void inhibit(); void uninhibit(); #ifdef USE_INTEL void propertiesChangedSlot(QString, QMap, QStringList); void onShowBlackBackGround(); #endif private: void init(); void clearScreensavers(); bool eventFilter(QObject *obj, QEvent *event); QPixmap getPaddingPixmap(QPixmap pixmap, int width, int height); // void checkNumLock(); // int numberMatch(const QString &key); private Q_SLOTS: void onScreenCountChanged(int); void onDesktopResized(); void onGlobalKeyPress(const QString &key); void onGlobalKeyRelease(const QString &key); void onGlobalButtonDrag(int xPos, int yPos); void onGlobalButtonPressed(int xPos, int yPos); void onPrepareForSleep(bool sleep); void switchToLinux(); void laterActivate(); void setLockState(); void laterInhibit(bool val); void laterStartAuth(); private: QDBusInterface *smInterface; #ifdef USE_INTEL TabletLockWidget *lockWidget; #else LockWidget *lockWidget; #endif XEventMonitor *xEventMonitor; MonitorWatcher *monitorWatcher; Configuration *configuration; QList widgetXScreensaverList; QList widgetBlackList; QList xscreensaverPidList; bool isLocked; bool lockState; ScreenStatus screenStatus; QPixmap background; QDBusUnixFileDescriptor m_inhibitFileDescriptor; bool isPassed; bool m_delay; int isBlank; bool isStartup = false; }; #endif // FULLBACKGROUNDWIDGET_H ukui-screensaver/.gitattributes0000644000175000017500000000006414205074704015667 0ustar fengfengdebian/changelog debian/compat debian/source/format