/* greeterwindow.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 "greeterwindow.h" #include #include #include #include #include #include #include #include #include #include #include "globalv.h" #include "loginwindow.h" #include "usersview.h" #include "usersmodel.h" #include "powerwindow.h" #include "common/configuration.h" #include "mainwindow.h" #include "virtualkeyboard.h" #include "languagewidget.h" #include "language.h" float scale; int fontSize; GreeterWindow::GreeterWindow(QWidget *parent) : QWidget(parent), m_userWnd(nullptr), m_loginWnd(nullptr), m_sessionWnd(nullptr), m_powerWnd(nullptr), m_sessionLB(nullptr), m_virtualKeyboard(nullptr), m_languageWnd(nullptr), m_greeter(new GreeterWrapper()), m_usersModel(new UsersModel(m_greeter->hideUsersHint())), m_sessionsModel(new QLightDM::SessionsModel(QLightDM::SessionsModel::LocalSessions)), m_configuration(Configuration::instance()), m_languageHasChanged(false), m_sessionHasChanged(false) { if(m_greeter->hasGuestAccountHint()){ //允许游客登录 qDebug() << "allow guest"; m_usersModel->setShowGuest(true); } if(m_greeter->showManualLoginHint()) { //允许手动输入用户名 qDebug() << "allow manual login"; m_usersModel->setShowManualLogin(true); } m_greeter->setSession(m_greeter->defaultSessionHint()); for(int i = 0; i < m_usersModel->rowCount(); i++) qDebug() << "load user " << m_usersModel->index(i). data(QLightDM::UsersModel::NameRole).toString(); for(int i = 0; i < m_sessionsModel->rowCount(); i++) qDebug() << "load session " << m_sessionsModel->index(i, 0). data(QLightDM::SessionsModel::KeyRole).toString(); connect(m_greeter, SIGNAL(autologinTimerExpired()),this, SLOT(timedAutologin())); connect(m_greeter, SIGNAL(authenticationSucess()), this, SLOT(hide())); connect(m_greeter, SIGNAL(startSessionFailed()), this, SLOT(show())); installEventFilter(this); } void GreeterWindow::initUI() { //电源对话框打开按钮 m_powerLB = new QPushButton(this); m_powerLB->setObjectName(QStringLiteral("powerButton")); m_powerLB->setIcon(QPixmap(":/resource/power.png")); m_powerLB->setIconSize(QSize(39, 39)); m_powerLB->setFocusPolicy(Qt::NoFocus); m_powerLB->setFixedSize(39, 39); m_powerLB->setCursor(Qt::PointingHandCursor); connect(m_powerLB, &QPushButton::clicked, this, &GreeterWindow::showPowerWnd); //虚拟键盘启动按钮 m_keyboardLB = new QPushButton(this); m_keyboardLB->setObjectName(QStringLiteral("keyboardButton")); m_keyboardLB->setIcon(QPixmap(":/resource/keyboard.png")); m_keyboardLB->setIconSize(QSize(39, 39)); m_keyboardLB->setFocusPolicy(Qt::NoFocus); m_keyboardLB->setFixedSize(39, 39); m_keyboardLB->setCursor(Qt::PointingHandCursor); connect(m_keyboardLB, &QPushButton::clicked, this, &GreeterWindow::showVirtualKeyboard); //桌面环境选择按钮 if(m_sessionsModel->rowCount() > 1) { m_sessionLB = new QPushButton(this); m_sessionLB->setObjectName((QStringLiteral("sessionButton"))); m_sessionLB->setIconSize(QSize(39, 39)); m_sessionLB->setFocusPolicy(Qt::NoFocus); m_sessionLB->setFixedSize(39, 39); m_sessionLB->setCursor(Qt::PointingHandCursor); connect(m_sessionLB, &QPushButton::clicked, this, &GreeterWindow::showSessionWnd); } //语言选择按钮 m_languageLB = new QPushButton(this); m_languageLB->setObjectName(QStringLiteral("languageButton")); m_languageLB->setFocusPolicy(Qt::NoFocus); m_languageLB->setFont(QFont("Ubuntu", 16)); m_languageLB->setFixedHeight(39); m_languageLB->setCursor(Qt::PointingHandCursor); connect(m_languageLB, &QPushButton::clicked, this, &GreeterWindow::showLanguageWnd); //用户列表 m_userWnd = new UsersView(this); connect(m_userWnd, &UsersView::currentUserChanged, this, &GreeterWindow::onCurrentUserChanged); connect(m_userWnd, &UsersView::userSelected, this, &GreeterWindow::onUserSelected); //登录窗口 m_loginWnd = new LoginWindow(m_greeter, this); m_loginWnd->hide(); connect(m_loginWnd, SIGNAL(back()), this, SLOT(onBacktoUsers())); connect(m_loginWnd, &LoginWindow::userChangedByManual, this, &GreeterWindow::onUserChangedByManual); connect(m_userWnd, &UsersView::userNotFound, m_loginWnd, &LoginWindow::setUserNotInView); m_userWnd->setModel(m_usersModel); //显示lightdm传过来的被选中的用户 -- SwitchToUser() QString selectedUser = m_greeter->selectUserHint(); if(!selectedUser.isEmpty()) { qDebug() << "SelectUserHint: " << selectedUser; m_userWnd->setCurrentUser(selectedUser); } // SwitchToGuest() else if(m_greeter->selectGuestHint()) { qDebug() << "SelectGuest"; m_userWnd->setCurrentUser("*guest"); } //如果只有一个用户,直接进入认证界面 else if(m_usersModel->rowCount() == 1) { QString userName = m_usersModel->index(0, 0).data(QLightDM::UsersModel::NameRole).toString(); m_userWnd->setCurrentUser(userName); } else { //选中上一次登录的用户 QString lastLoginUser = Configuration::instance()->getLastLoginUser(); m_userWnd->setCurrentUser(lastLoginUser); } } /** * @brief GreeterWindow::resizeEvent * @param event * GreeterWindow的大小发生改变 */ void GreeterWindow::resizeEvent(QResizeEvent *event) { QSize size = event->size(); //重新计算缩放比例 scale = QString::number(size.width() / 1920.0, 'f', 1).toFloat(); scale = scale > 0.5 ? scale : (width() >= 800 ? 0.5 : scale); //字体大小 fontSize = scale > 0.5 ? 10 : 8; qDebug() << "GreeterWindow resize to " << size; qDebug() << "scale: " << scale; if(m_userWnd){ m_userWnd->resize(USERSVIEW_WIDTH, USERSVIEW_HEIGHT); QRect userRect((width()-m_userWnd->width())/2, (height()-m_userWnd->height())/2, m_userWnd->width(), m_userWnd->height()); m_userWnd->setGeometry(userRect); } if(m_loginWnd){ QRect loginRect((width()-m_loginWnd->width())/2, 0, m_loginWnd->width(), height()); m_loginWnd->setGeometry(loginRect); } if(m_languageWnd) { QRect languageWndRect((rect().width()-m_languageWnd->width())/2, (height()-m_languageWnd->height())/2, m_languageWnd->width(), m_languageWnd->height()); m_languageWnd->setGeometry(languageWndRect); } //电源按钮位置 int x = m_powerLB->geometry().width() + 20; int y = 20; m_powerLB->move(this->width() - x, y); //虚拟键盘按钮位置 x += (20 + m_keyboardLB->width()); m_keyboardLB->move(this->width() - x, y); //桌面环境选择按钮位置 if(m_sessionLB) { x += (20 + m_sessionLB->width()); m_sessionLB->move(this->width() - x, y); } //语言选择按钮位置 x += (20 + m_languageLB->width()); m_languageLB->move(this->width() - x, y); //虚拟键盘位置 setVirkeyboardPos(); } void GreeterWindow::setVirkeyboardPos() { if(m_virtualKeyboard) { m_virtualKeyboard->setGeometry((width() - m_virtualKeyboard->width()) / 2, height() - m_virtualKeyboard->height(), m_virtualKeyboard->width(), m_virtualKeyboard->height()); } } void GreeterWindow::keyReleaseEvent(QKeyEvent *e) { switch(e->key()) { case Qt::Key_L: if(e->modifiers() & Qt::ControlModifier) m_languageLB->click(); break; case Qt::Key_K: if(e->modifiers() & Qt::ControlModifier) m_keyboardLB->click(); break; case Qt::Key_P: if(e->modifiers() & Qt::ControlModifier) m_powerLB->click(); break; case Qt::Key_Escape: if(m_powerWnd && !m_powerWnd->isHidden()) m_powerWnd->close(); else if(m_loginWnd && !m_loginWnd->isHidden()){ m_loginWnd->reset(); switchWnd(0); } break; } QWidget::keyReleaseEvent(e); } void GreeterWindow::setBackground(const QModelIndex &index) { QString backgroundPath = index.data(QLightDM::UsersModel::BackgroundPathRole).toString(); QSharedPointer background(new Background); background->type = BACKGROUND_IMAGE; background->image = backgroundPath; static_cast(parentWidget())->setBackground(background); } void GreeterWindow::onUserSelected(const QModelIndex &index) { qDebug() << index.data(QLightDM::UsersModel::NameRole).toString() << "selected"; m_loginWnd->setUserIndex(index); switchWnd(1); } void GreeterWindow::onCurrentUserChanged(const QModelIndex &index) { setBackground(index); if(!m_languageHasChanged) { //获取用户的session语言 QString language; QString realName = index.data(QLightDM::UsersModel::NameRole).toString(); if(realName == "*guest" || realName == "*login") return; QDBusInterface iface("org.freedesktop.Accounts", "/org/freedesktop/Accounts", "org.freedesktop.Accounts",QDBusConnection::systemBus()); QDBusReply userPath = iface.call("FindUserByName", realName); if(!userPath.isValid()) qWarning() << "Get UserPath error:" << userPath.error(); else { QDBusInterface userIface("org.freedesktop.Accounts", userPath.value().path(), "org.freedesktop.DBus.Properties", QDBusConnection::systemBus()); QDBusReply languageReply = userIface.call("Get", "org.freedesktop.Accounts.User", "Language"); if(!languageReply.isValid()) qWarning() << "Get User's language error" << languageReply.error(); else { language = languageReply.value().variant().toString(); onLanguageChanged(getLanguage(language)); } } } if(!m_sessionHasChanged && m_sessionsModel->rowCount() > 1) { QString session = index.data(QLightDM::UsersModel::SessionRole).toString(); onSessionChanged(session); } } void GreeterWindow::onUserChangedByManual(const QString &userName) { m_userWnd->setCurrentUser(userName); } void GreeterWindow::onBacktoUsers() { switchWnd(0); } void GreeterWindow::onBacktoLogin() { switchWnd(1); } /** * @brief GreeterWindow::switchWnd * @param index (0:用户列表窗口;1:登录窗口;2:session选择窗口) * 切换窗口 */ void GreeterWindow::switchWnd(int index) { if(m_userWnd) m_userWnd->hide(); if(m_loginWnd) m_loginWnd->hide(); switch (index) { case 0: m_userWnd->show(); break; case 1: m_loginWnd->show(); break; default: break; } } /** * @brief GreeterWindow::showPowerWnd * 显示电源对话框 */ void GreeterWindow::showPowerWnd() { //如果已经打开了电源对话框则关闭 if(m_powerWnd && !m_powerWnd->isHidden()){ m_powerWnd->close(); return; } //判断是否已经有用户登录 bool hasOpenSessions = false; for(int i = 0; i < m_usersModel->rowCount(); i++) { hasOpenSessions = m_usersModel->index(i, 0).data(QLightDM::UsersModel::LoggedInRole).toBool(); if(hasOpenSessions) break; } m_powerWnd = new PowerWindow(hasOpenSessions, this); m_powerWnd->setObjectName(QStringLiteral("powerWnd")); m_powerWnd->show(); } /** * @brief GreeterWindow::showVirtualKeyboard * 显示或隐藏虚拟键盘 */ void GreeterWindow::showVirtualKeyboard() { if(!m_virtualKeyboard) { m_virtualKeyboard = new VirtualKeyboard(this); connect(m_virtualKeyboard, &VirtualKeyboard::aboutToClose, m_virtualKeyboard, &VirtualKeyboard::close); } m_virtualKeyboard->setVisible(!m_virtualKeyboard->isVisible()); setVirkeyboardPos(); } /** * @brief GreeterWindow::timedAutologin * 处理延时自动登录 */ void GreeterWindow::timedAutologin() { if(m_greeter->isAuthenticated()) { if(!m_greeter->authenticationUser().isEmpty()) m_greeter->startSession(); else if(m_greeter->autologinGuestHint()) m_greeter->startSession(); else if(!m_greeter->autologinUserHint().isEmpty()) m_greeter->authenticate(m_greeter->autologinUserHint()); } else m_greeter->authenticateAutologin(); } /** * @brief GreeterWindow::showLanguageWnd * 显示语言选择窗口 */ void GreeterWindow::showLanguageWnd() { m_languageWnd = new LanguageWidget(this); m_languageWnd->setObjectName("languageWnd"); connect(m_languageWnd, &LanguageWidget::languageChanged, this, &GreeterWindow::onLanguageChanged); m_languageHasChanged = true; m_languageWnd->show(); m_languageWnd->setCurrentLanguage(m_greeter->lang()); } void GreeterWindow::setWindowPos(QWidget *widget, Qt::Alignment align) { QRect rect; rect.setSize(widget->size()); if(align & Qt::AlignHCenter) { rect.setLeft((width() - widget->width())/2); } if(align & Qt::AlignVCenter) { rect.setTop((height() - widget->height())/2); } if(align & Qt::AlignBottom) { rect.setTop(height() - widget->height()); } widget->setGeometry(rect); } void GreeterWindow::onLanguageChanged(const Language &language) { if(m_greeter->lang() == language.code) { return; } m_greeter->setLang(language.code); m_languageLB->setText(language.name); const QFont &font = m_languageLB->font(); QFontMetrics fm(font); int pixelWidth = fm.width(language.name); m_languageLB->setFixedWidth(pixelWidth + 4); int x; if(m_sessionLB) { x = m_sessionLB->geometry().left(); } else { x = m_keyboardLB->geometry().left(); } m_languageLB->move(x - 20 - m_languageLB->width(), 20); if(m_userWnd && !m_userWnd->isHidden()) { m_userWnd->setFocus(); } } void GreeterWindow::showSessionWnd() { m_sessionWnd = new SessionWindow(m_sessionsModel, this); connect(m_sessionWnd, &SessionWindow::sessionChanged, this, &GreeterWindow::onSessionChanged); m_sessionHasChanged = true; m_sessionWnd->setCurrentSession(m_greeter->session()); m_sessionWnd->show(); } void GreeterWindow::onSessionChanged(const QString &session) { qDebug() << "session changed: " << session; QString sessionTmp(session); if(session.isEmpty() || !sessionIsValid(session)) { //session不存在 QString defaultSession = m_greeter->defaultSessionHint(); //默认session存在 if(defaultSession != session && sessionIsValid(defaultSession)) { sessionTmp = defaultSession; } //列表中的第一个session else if(m_sessionsModel && m_sessionsModel->rowCount() > 0) { sessionTmp = m_sessionsModel->index(0, 0) .data(QLightDM::SessionsModel::KeyRole).toString(); } else { sessionTmp = ""; } } QString sessionPrefix = sessionTmp.left(sessionTmp.indexOf('-')); QString sessionIcon = IMAGE_DIR + QString("badges/%1_badge.png") .arg(sessionPrefix.toLower()); QFile iconFile(sessionIcon); if(!iconFile.exists()){ sessionIcon = IMAGE_DIR + QString("badges/unknown_badge.png"); } qDebug() << sessionIcon; m_sessionLB->setIcon(QIcon(sessionIcon)); m_greeter->setSession(sessionTmp); if(m_userWnd && !m_userWnd->isHidden()) { m_userWnd->setFocus(); } } bool GreeterWindow::sessionIsValid(const QString &session) { for(int i = 0; i < m_sessionsModel->rowCount(); i++) { QString sessionKey = m_sessionsModel->index(i, 0) .data(QLightDM::SessionsModel::KeyRole).toString(); if(sessionKey == session) return true; } return false; }