[plasma/ksshaskpass] /: Add custom ClearText dialog
Kai Uwe Broulik <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 712db7cf09e18eafe836b390c8a90c705f0c5637 by Kai Uwe Broulik.
Committed on 17/08/2026 at 14:10.
Pushed by broulik into branch 'master'.
Add custom ClearText dialog
ksshaskpass used KPasswordDialog for ClearText as well because it wants the
"Remember" checkbox. However, it is not great to use a password dialog when
it clearly should not use one.
Instead, implement a custom dialog (inspired by KPasswordDialog), including
the "Remember" checkbox but that can also show text in clear.
BUG: 343562
M +2 -0 CMakeLists.txt
M +3 -0 src/CMakeLists.txt
A +168 -0 src/cleartextinputdialog.ui
M +33 -18 src/main.cpp
https://invent.kde.org/plasma/ksshaskpass/-/commit/712db7cf09e18eafe836b390c8a90c705f0c5637
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7b9f85e..515e84c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -10,6 +10,8 @@ set(KDE_COMPILERSETTINGS_LEVEL "5.82")
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_AUTOUIC ON)
+
find_package(ECM ${KF6_MIN_VERSION} REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH})
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 2ec6914..22a7f85 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -3,6 +3,9 @@
add_library(ksshaskpass_prompt OBJECT prompt.cpp prompt.h)
+ki18n_wrap_ui(ui_SRCS cleartextinputdialog.ui)
+target_sources(ksshaskpass_prompt PRIVATE ${ui_SRCS})
+
target_include_directories(ksshaskpass_prompt PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
ecm_qt_declare_logging_category(ksshaskpass_prompt HEADER debug.h
diff --git a/src/cleartextinputdialog.ui b/src/cleartextinputdialog.ui
new file mode 100644
index 0000000..26e21ee
--- /dev/null
+++ b/src/cleartextinputdialog.ui
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ClearTextInputDialog</class>
+ <widget class="QDialog" name="ClearTextInputDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>412</width>
+ <height>152</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="windowIcon">
+ <iconset theme="dialog-password"/>
+ </property>
+ <layout class="QVBoxLayout" name="vBoxLayout">
+ <property name="sizeConstraint">
+ <enum>QLayout::SizeConstraint::SetFixedSize</enum>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="hboxLayout">
+ <item>
+ <widget class="QLabel" name="pixmapLabel">
+ <property name="alignment">
+ <set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="prompt">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Preferred" vsizetype="Preferred">
+ <horstretch>10</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string notr="true">PROMPT</string>
+ </property>
+ <property name="textFormat">
+ <enum>Qt::TextFormat::PlainText</enum>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ <property name="textInteractionFlags">
+ <set>Qt::TextInteractionFlag::LinksAccessibleByMouse|Qt::TextInteractionFlag::TextSelectableByMouse</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer>
+ <property name="orientation">
+ <enum>Qt::Orientation::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Policy::Ignored</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>400</width>
+ <height>16</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QWidget" name="credentialsGroup" native="true">
+ <layout class="QFormLayout" name="formLayout">
+ <property name="leftMargin">
+ <number>1</number>
+ </property>
+ <property name="topMargin">
+ <number>1</number>
+ </property>
+ <property name="rightMargin">
+ <number>1</number>
+ </property>
+ <property name="bottomMargin">
+ <number>1</number>
+ </property>
+ <item row="2" column="1">
+ <widget class="QCheckBox" name="keepCheckBox">
+ <property name="text">
+ <string comment="@option:check">Remember</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="passwordLabel">
+ <property name="text">
+ <string comment="@label:textbox">Password:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="KPasswordLineEdit" name="lineEdit"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>KPasswordLineEdit</class>
+ <extends>QWidget</extends>
+ <header>kpasswordlineedit.h</header>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>lineEdit</tabstop>
+ <tabstop>keepCheckBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>ClearTextInputDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>260</x>
+ <y>145</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>252</x>
+ <y>192</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>ClearTextInputDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>336</x>
+ <y>145</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>359</x>
+ <y>145</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/main.cpp b/src/main.cpp
index 119a82d..65ec991 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -17,12 +17,15 @@
#include <QInputDialog>
#include <QPointer>
#include <QRegularExpression>
+#include <QStyle>
+#include <QStyleOption>
#include <QTextStream>
#include <qt6keychain/keychain.h>
#include "debug.h"
#include "prompt.h"
+#include "ui_cleartextinputdialog.h"
constexpr const char *PROMPT_TYPE_ENV_VAR = "SSH_ASKPASS_PROMPT";
@@ -184,28 +187,40 @@ int main(int argc, char **argv)
}
case DisplayType::Unknown: // just in case.
case DisplayType::ClearText:
- // Should use a dialog with visible input, but KPasswordDialog doesn't support that and
- // other available dialog types don't have a "Keep" checkbox.
- /* fallthrough */
case DisplayType::Password: {
- // create the password dialog, but only show "Enable Keep" button, if the keychain has a working backend available
- KPasswordDialog::KPasswordDialogFlag flag(KPasswordDialog::NoFlags);
- if (!identifier.isNull() && QKeychain::isAvailable()) {
- flag = KPasswordDialog::ShowKeepPassword;
- }
- QPointer<KPasswordDialog> kpd = new KPasswordDialog(nullptr, flag);
+ // custom dialog inspired by KPasswordDialog, including "Remember" option,
+ // but has the ability to show the password.
+ QDialog dlg;
+
+ Ui_ClearTextInputDialog ui;
+ ui.setupUi(&dlg);
+
+ ui.prompt->setText(dialog);
+ ui.keepCheckBox->setVisible(!identifier.isEmpty() && QKeychain::isAvailable());
+
+ QStyleOption option;
+ option.initFrom(&dlg);
+ const int iconSize = dlg.style()->pixelMetric(QStyle::PM_MessageBoxIconSize, &option, &dlg);
+ ui.pixmapLabel->setPixmap(QIcon::fromTheme(QIcon::ThemeIcon::DialogPassword).pixmap(iconSize));
- kpd->setPrompt(dialog);
- // We don't want to dump core when the password dialog is shown, because it could contain the entered password.
- // KPasswordDialog::disableCoreDumps() seems to be gone in KDE 4 -- do it manually
- struct rlimit rlim;
- rlim.rlim_cur = rlim.rlim_max = 0;
- setrlimit(RLIMIT_CORE, &rlim);
+ if (displayType == DisplayType::Password) {
+ ui.keepCheckBox->setText(i18nc("@option:check", "Remember password"));
+
+ // We don't want to dump core when the password dialog is shown, because it could contain the entered password.
+ // KPasswordDialog::disableCoreDumps() seems to be gone in KDE 4 -- do it manually
+ struct rlimit rlim;
+ rlim.rlim_cur = rlim.rlim_max = 0;
+ setrlimit(RLIMIT_CORE, &rlim);
+ } else {
+ ui.lineEdit->setEchoMode(QLineEdit::Normal);
+ ui.lineEdit->setRevealPasswordMode(KPassword::RevealMode::Never);
+ ui.passwordLabel->hide();
+ }
- if (kpd->exec() == QDialog::Accepted) {
- item = kpd->password();
+ if (dlg.exec() == QDialog::Accepted) {
+ item = ui.lineEdit->password();
// If “Enable Keep” is enabled, store the password in keychain
- if ((!identifier.isNull()) && kpd->keepPassword()) {
+ if ((!identifier.isNull()) && ui.keepCheckBox->isChecked()) {
QKeychain::WritePasswordJob job(app.applicationName());
job.setKey(identifier);
job.setTextData(item);