/** * @RDE_HEADER@ * Login Dialog * $Id$ * $HeadURL$ * $Author$ * Created by Mike Wille, SLSE, 2016-05-05 */ #include "opm_login_dialog.h" #include "ui_opm_login_dialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef Q_OS_LINUX #include #endif namespace OperatorManagement { LoginWindow::LoginWindow(QWidget *parent, bool isAAR) : QDialog(parent) , m_ui(new Ui::LoginWindow) , m_done(false) , m_isAAR(isAAR) { setWindowFlag(Qt::WindowMinimizeButtonHint, false); setWindowFlag(Qt::WindowCloseButtonHint, false); setWindowFlag(Qt::WindowContextHelpButtonHint, false); m_ui->setupUi(this); #ifdef Q_OS_LINUX QTimer *t = new QTimer(this); t->setInterval(1000); connect(t, &QTimer::timeout, this, [this]() { #ifndef LTS_DEBUG if (LtsSessionData::LtsSessionData::getInstance()->debugFlagValue(QStringLiteral("Login.ShowFocus")) == QVariant(true)) #endif { Display *dp = XOpenDisplay(nullptr); if (dp == nullptr) { m_ui->lbLoginText->setText(QStringLiteral("Unable to get screen!")); return; } Window focused; int revert = 0; XGetInputFocus(dp, &focused, &revert); XCloseDisplay(dp); m_ui->lbLoginText->setText(QStringLiteral("Focused window id: 0x%1").arg(QString::number(focused, 16))); } }); t->start(); #endif setWindowTitle(tr("Login")); setMouseTracking(true); // register mouse movement bool mmm = LtsMultiMonitor::LtsMultiMonitor::getInstance()->isActive(); if (mmm) { setWindowFlags(windowFlags() | /*Qt::WindowStaysOnTopHint | */Qt::FramelessWindowHint); // hints.. setAttribute(Qt::WA_TranslucentBackground); } m_hideTimer.setInterval(30000); if(!LtsSessionData::LtsSessionData::getInstance()->isTablet()) connect(&m_hideTimer, &QTimer::timeout, this, &LoginWindow::slotHide); connect(m_ui->leOperatorName, &QLineEdit::textChanged, this, [this]() { if (m_hideTimer.isActive()) m_hideTimer.start(); }); QList labels = findChildren(); for (QList::const_iterator i = labels.constBegin(); i != labels.constEnd(); ++i) { QGraphicsDropShadowEffect *shadow = new QGraphicsDropShadowEffect(this); // cannot copy this.. shadow->setOffset(0, 0); shadow->setBlurRadius(22); shadow->setColor(QColor("white")); (*i)->setGraphicsEffect(shadow); } LtsSessionData::LtsSessionData *sessionData = LtsSessionData::LtsSessionData::getInstance(); if (sessionData->isTablet()) { setGeometry(QStyle::alignedRect( Qt::LeftToRight, Qt::AlignHCenter | Qt::AlignTop, size(), QGuiApplication::primaryScreen()->geometry())); } else { setGeometry(QStyle::alignedRect( Qt::LeftToRight, Qt::AlignHCenter | Qt::AlignVCenter, size(), QGuiApplication::primaryScreen()->geometry())); } QMenu *shutdownMenu = new QMenu(m_ui->pbShutdown); QAction *action = shutdownMenu->addAction(tr("Shutdown"), this, &LoginWindow::slotShutdown ); QFont font = action->font(); #ifdef TABLET_MODE font.setPointSizeF(font.pointSizeF()*1.5); #endif action->setFont(font); action = shutdownMenu->addAction(tr("Reboot"), this, &LoginWindow::slotReboot ); action->setFont(font); #ifndef GUEZ_MODE #ifdef TABLET_MODE if (PROJECTBUILD == "ahtc") { action = shutdownMenu->addAction(tr("Logout"), this, &LoginWindow::slotOperatorLogout ); action->setFont(font); } #endif #endif m_ui->pbShutdown->setMenu(shutdownMenu); #ifdef TABLET_MODE // m_ui->pbExit->setFont(font); // m_ui->pbShutdown->setFont(font); #endif connect(m_ui->pbGo, &QPushButton::clicked, this, &LoginWindow::slotLogin, Qt::QueuedConnection); // TODO: can be direct (?) connect(m_ui->pbExit, &QPushButton::clicked, this, &LoginWindow::slotExit); // connect(m_ui->pbShutdown, &QPushButton::clicked, // this, &LoginWindow::slotShutdown); connect(m_ui->pbDe_DE, &QPushButton::clicked, this, &LoginWindow::onLanguageChange); connect(m_ui->pbEn_GB, &QPushButton::clicked, this, &LoginWindow::onLanguageChange); connect(m_ui->pbEn_US, &QPushButton::clicked, this, &LoginWindow::onLanguageChange); m_ui->pbDe_DE->hide(); m_ui->pbEn_GB->hide(); m_ui->pbEn_US->hide(); const QString languages = LtsUtils::ProjectSettings::getInstance()->value(QStringLiteral("pdm"), QStringLiteral("SystemLanguages")).toString(); const QVector slLang = languages.splitRef(QLatin1Char(','), QString::SkipEmptyParts); if (slLang.isEmpty()) { qWarning() << "LoginWindow::c_tor: Missing 'SystemLanguages' entry in project settings file!"; } else { if (slLang.size() > 1) { for (QStringRef lang : slLang) { lang = lang.trimmed(); // qWarning() << "available language:" << lang.toString(); if (lang == QLatin1String("de_DE")) m_ui->pbDe_DE->show(); if (lang == QLatin1String("en_GB")) m_ui->pbEn_GB->show(); if (lang == QLatin1String("en_US")) m_ui->pbEn_US->show(); } if (NGL::translationLocale() == "de_DE") m_ui->pbDe_DE->click(); if (NGL::translationLocale() == "en_GB") m_ui->pbEn_GB->click(); if (NGL::translationLocale() == "en_US") m_ui->pbEn_US->click(); } else { QString lang = slLang.at(0).toString().trimmed(); // qWarning() << "available language:" << slLang.at(0).toString(); if (lang.toLatin1() == "de_DE") m_ui->pbDe_DE->click(); if (lang.toLatin1() == "en_GB") m_ui->pbEn_GB->click(); if (lang.toLatin1() == "en_US") m_ui->pbEn_US->click(); } } QMenu *styleMenu = new QMenu(m_ui->pbStyle); styleMenu->addAction(tr("Light"), this, &LoginWindow::slotLightStyle); styleMenu->addAction(tr("Dark"), this, &LoginWindow::slotDarkStyle); m_ui->pbStyle->setMenu(styleMenu); slotLightStyle(); // PROJECT LOGO QString projectLogoFilename(QStringLiteral(":project/login_logo.png")); if (!QFile(projectLogoFilename).exists()) projectLogoFilename = QStringLiteral(":/project/logo.png"); QPixmap pixmap(projectLogoFilename); if (pixmap.isNull()) { qWarning() << "LoginWindow::c_tor: (PROJECT LOGO) file missing or is not an valid image '" << projectLogoFilename << "'"; } else { pixmap = pixmap.scaled(m_ui->lbRDELogo->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); m_ui->lbRDELogo->setPixmap(pixmap); } auto setFocusCb = [this]() { QApplication::setActiveWindow(this); }; QTimer::singleShot(50, this, setFocusCb); if (LtsSessionData::LtsSessionData::getInstance()->isTablet()) m_ui->leOperatorName->setFocusPolicy(Qt::ClickFocus); else if (mmm && !LtsSessionData::LtsSessionData::getInstance()->isTablet()) m_hideTimer.start(); setMinimumSize(sizeHint()); m_ui->leOperatorName->setFocus(); } LoginWindow::~LoginWindow() { delete m_ui; // qCritical() << "~LoginWindow"; } QString LoginWindow::getOperatorName() const { return m_ui->leOperatorName->text(); } void LoginWindow::setAARLabel(bool isAAR, bool connectedLocal) { if (!isAAR) m_ui->lblConnectedTo->hide(); else { m_ui->lblConnectedTo->setStyleSheet(QStringLiteral("background-color: white;")); if (connectedLocal) m_ui->lblConnectedTo->setText(tr("Connected to local database")); else m_ui->lblConnectedTo->setText(tr("Connected to network")); } } void LoginWindow::setStyle(const QString &name) { #ifdef TABLET_MODE LtsUtils::StyleManager::getInstance()->loadStyle(name, true); #else LtsUtils::StyleManager::getInstance()->loadStyle(name, false); #endif } void LoginWindow::slotLightStyle() { setStyle(QStringLiteral("rme.light")); } void LoginWindow::slotDarkStyle() { setStyle(QStringLiteral("rme.dark")); } void LoginWindow::slotExit() { LtsWidgets::LtsGlobalWaitDialog::getInstance()->wait(tr("Shutting down ...")); //QMetaObject::invokeMethod QTimer::singleShot(500, this, [this]() { m_ui->pbExit->setText(tr("exiting ...")); m_ui->pbExit->setEnabled(false); m_ui->pbDe_DE->setEnabled(false); m_ui->pbEn_GB->setEnabled(false); m_ui->pbEn_US->setEnabled(false); m_ui->pbGo->setEnabled(false); m_ui->pbShutdown->setEnabled(false); m_ui->leOperatorName->setEnabled(false); if (m_isAAR) { QStringList args; QString cmd = QStringLiteral("openbox"); args << QStringLiteral("--exit"); qWarning() << "start openbox --exit"; QProcess::startDetached(cmd, args); } //QCoreApplication::processEvents(); QCoreApplication::quit(); // simply exit event loop, cleanup is done by main() automatically (THIS is the only way to exit the application! via the Login Dialog) });//, Qt::QueuedConnection); } void LoginWindow::slotShutdown() { QMessageBox msgBox; QFont font = msgBox.font(); #ifdef TABLET_MODE font.setPointSizeF(font.pointSizeF()*1.5); #endif msgBox.setWindowTitle(tr("Shutdown")); msgBox.setText(tr("Are you sure you want to shut down the system?")); QAbstractButton* pButtonYes = msgBox.addButton(QMessageBox::Yes); pButtonYes->setMinimumWidth(150); pButtonYes->setFont(font); QAbstractButton* pButtonNo = msgBox.addButton(QMessageBox::No); pButtonNo->setMinimumWidth(150); pButtonNo->setFont(font); int ret = msgBox.exec(); if (ret == QMessageBox::Yes) { #ifdef TABLET_MODE if (strcmp(PROJECTBUILD, "commaster") == 0) // may add a new plugin or projectBuild for that? demotablet for now { QByteArray queryTimeline("$IIXDR,S,1,,SERVICE_CONTROL_PRESHUTDOWN*79"); QUdpSocket *socket = new QUdpSocket(this); socket->writeDatagram(queryTimeline, QHostAddress(QStringLiteral("172.16.255.255")), 10110); } #endif QString cmd; #ifdef LTS_DEBUG cmd = QStringLiteral("xeyes"); #else #ifdef Q_OS_WIN cmd = QStringLiteral("shutdown /s /t 0"); // s = shutdown t = time in seconds #else cmd = QStringLiteral("systemctl poweroff"); #endif #endif QProcess::startDetached(cmd); QCoreApplication::quit(); } } void LoginWindow::slotReboot() { QMessageBox msgBox; QFont font = msgBox.font(); #ifdef TABLET_MODE font.setPointSizeF(font.pointSizeF()*1.5); #endif msgBox.setWindowTitle(tr("Reboot")); msgBox.setText(tr("Are you sure you want to reboot the system?")); QAbstractButton* pButtonYes = msgBox.addButton(QMessageBox::Yes); pButtonYes->setMinimumWidth(150); pButtonYes->setFont(font); QAbstractButton* pButtonNo = msgBox.addButton(QMessageBox::No); pButtonNo->setMinimumWidth(150); pButtonNo->setFont(font); int ret = msgBox.exec(); if (ret == QMessageBox::Yes) { QString cmd; #ifdef LTS_DEBUG cmd = QStringLiteral("xeyes"); #else #ifdef Q_OS_WIN cmd = QStringLiteral("shutdown /r /t 0"); // s = shutdown t = time in seconds #else cmd = QStringLiteral("systemctl reboot"); #endif #endif QProcess::startDetached(cmd); QCoreApplication::quit(); } } void LoginWindow::slotOperatorLogout() { QMessageBox msgBox; QFont font = msgBox.font(); #ifdef TABLET_MODE font.setPointSizeF(font.pointSizeF()*1.5); #endif msgBox.setWindowTitle(tr("Shutdown")); msgBox.setText(tr("Are you sure you want to shut down the system?")); QAbstractButton* pButtonYes = msgBox.addButton(QMessageBox::Yes); pButtonYes->setMinimumWidth(150); pButtonYes->setFont(font); QAbstractButton* pButtonNo = msgBox.addButton(QMessageBox::No); pButtonNo->setMinimumWidth(150); pButtonNo->setFont(font); int ret = msgBox.exec(); if (ret == QMessageBox::Yes) { QString cmd; /* #ifdef LTS_DEBUG cmd = QStringLiteral("xeyes"); #else */ #ifdef Q_OS_WIN cmd = QStringLiteral("logoff"); // logoff #else cmd = QStringLiteral("loginctl terminate-user ctc_ws"); #endif /* #endif */ QProcess::startDetached(cmd); QCoreApplication::quit(); } } void LoginWindow::slotOperatorAction() // TODO: can re-show already finished dialog when some there is NO modal window that inactivates the main background ??? { if (m_done) // do NOT reshow after login (as window is hidden then) and the return key will be processed again, as we did not return from slotOperatorAction.... holy shit! return; //qWarning() << "slotOperatorAction"; if (LtsMultiMonitor::LtsMultiMonitor::getInstance()->isActive() && !LtsSessionData::LtsSessionData::getInstance()->isTablet()) m_hideTimer.start(); // restarts timer (hides window on timeout) if (!isVisible()) // do not use isHidden (see F1) { // windows (linux ignores that and centers the dialog automatically): setGeometry(QStyle::alignedRect( Qt::LeftToRight, Qt::AlignHCenter | Qt::AlignVCenter, size(), QGuiApplication::primaryScreen()->geometry())); // m_ui->leOperatorName->setFocus(); show(); } //raise(); QApplication::setActiveWindow(this); m_ui->leOperatorName->setFocus(); } bool LoginWindow::event(QEvent *event) { switch (event->type()) { #undef KeyPress // X.h defines it case QEvent::KeyPress: // respect typing into textfields case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: case QEvent::MouseMove: { slotOperatorAction(); break; } default: { break; } } return QDialog::event(event); } void LoginWindow::closeEvent(QCloseEvent *event) // TODO: override reject() { #ifdef DEVEL (void)event; // event->accept(); // emit signalSuccess(); // pretend we have chosen an exercise .. // deleteLater(); // .. end don't come back #else event->ignore(); exit(0); // do not allow access to the opapp without login on NON-DEVEL #endif } void LoginWindow::changeEvent(QEvent *e) { QDialog::changeEvent(e); if (e->type() == QEvent::LanguageChange) m_ui->retranslateUi(this); } void LoginWindow::slotHide() { m_hideTimer.stop(); // window hidden, no need to hide it by timeout hide(); } void LoginWindow::slotCancel() // TODO: override reject() { //#ifdef DEVEL // emit signalQuit(); // //QCoreApplication::quit(); // end main event loop so that the applications ends when main() ends ! // //exit(0); //#else // slotHide(); //#endif } void LoginWindow::slotLogin() { if (m_ui->leOperatorName->text().isEmpty()) return; onLanguageChange(); // not really needed hide(); emit signalOperatorSelected(m_ui->leOperatorName->text()); } void LoginWindow::onLanguageChange() { if (m_ui->pbDe_DE->isChecked()) NGL::setTranslationLocale(QByteArray("de_DE")); if (m_ui->pbEn_GB->isChecked()) NGL::setTranslationLocale(QByteArray("en_GB")); if (m_ui->pbEn_US->isChecked()) NGL::setTranslationLocale(QByteArray("en_US")); } } // namespace OperatorManagement