QtPass 2.0.0
Developer documentation
Loading...
Searching...
No Matches
fieldlabel.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: 2026 Anne Jan Brouwer
2// SPDX-License-Identifier: GPL-3.0-or-later
8#include "fieldlabel.h"
9
10#include <QContextMenuEvent>
11#include <QFormLayout>
12#include <QKeyEvent>
13#include <QLineEdit>
14#include <QMenu>
15
16FieldLabel::FieldLabel(const QString &name, QWidget *parent) : QLabel(parent) {
17 // A field name comes from the entry, which a shared store's other writers
18 // control: as rich text, <img src="/dev/zero"> would have Qt read that
19 // file without end. Plain text before the name is set.
20 setTextFormat(Qt::PlainText);
21 setText(name);
22 setToolTip(tr("Double-click to rename this field"));
23}
24
25void FieldLabel::mouseDoubleClickEvent(QMouseEvent *event) {
26 if (event->button() == Qt::LeftButton) {
27 startEdit();
28 return;
29 }
30 QLabel::mouseDoubleClickEvent(event);
31}
32
33void FieldLabel::contextMenuEvent(QContextMenuEvent *event) {
34 QMenu menu(this);
35 menu.addAction(tr("Rename field…"), this, &FieldLabel::startEdit);
36 menu.addAction(tr("Remove field"), this, &FieldLabel::removeRequested);
37 menu.exec(event->globalPos());
38}
39
41
43 if (m_editor != nullptr) {
44 m_editor->setFocus();
45 return;
46 }
47 m_editor = new QLineEdit(text(), parentWidget());
48 m_editor->setObjectName(QStringLiteral("fieldNameEditor"));
49 m_editor->installEventFilter(this);
50 connect(m_editor, &QLineEdit::editingFinished, this,
51 [this] { finishEdit(true); });
52 // Take the label's cell in the form, so the editor gets the label column
53 // (which widens for it) instead of floating over the value next to it.
54 auto *form = qobject_cast<QFormLayout *>(parentWidget()->layout());
55 int row = -1;
56 QFormLayout::ItemRole role{};
57 if (form != nullptr) {
58 form->getWidgetPosition(this, &row, &role);
59 }
60 if (row >= 0) {
61 form->removeWidget(this);
62 hide();
63 form->setWidget(row, role, m_editor);
64 } else {
65 m_editor->setGeometry(geometry());
66 }
67 m_editor->show();
68 m_editor->selectAll();
69 m_editor->setFocus();
70}
71
72auto FieldLabel::eventFilter(QObject *watched, QEvent *event) -> bool {
73 if (watched != m_editor || event->type() != QEvent::KeyPress) {
74 return QLabel::eventFilter(watched, event);
75 }
76 switch (static_cast<QKeyEvent *>(event)->key()) {
77 case Qt::Key_Escape:
78 finishEdit(false);
79 return true;
80 case Qt::Key_Return:
81 case Qt::Key_Enter:
82 // Enter confirms the name only; left alone it would also reach the
83 // dialog's default button and save and close the whole entry.
84 finishEdit(true);
85 return true;
86 default:
87 return QLabel::eventFilter(watched, event);
88 }
89}
90
91void FieldLabel::finishEdit(bool commit) {
92 if (m_editor == nullptr) {
93 return;
94 }
95 // editingFinished fires again when the editor loses focus on hide; take
96 // the pointer first so the second call finds nothing to do.
97 QLineEdit *editor = m_editor;
98 m_editor = nullptr;
99 // A colon would start the value early when the line is written back.
100 const QString name = editor->text().remove(u':').trimmed();
101 auto *form = qobject_cast<QFormLayout *>(parentWidget()->layout());
102 int row = -1;
103 QFormLayout::ItemRole role{};
104 if (form != nullptr) {
105 form->getWidgetPosition(editor, &row, &role);
106 }
107 editor->hide();
108 if (row >= 0) {
109 form->removeWidget(editor);
110 form->setWidget(row, role, this);
111 show();
112 }
113 editor->deleteLater();
114 if (commit && !name.isEmpty() && name != text()) {
115 emit renamed(text(), name);
116 }
117}
FieldLabel(const QString &name, QWidget *parent=nullptr)
Label for the field called name.
void contextMenuEvent(QContextMenuEvent *event) override
Menu with Rename field and Remove field.
QPointer< QLineEdit > m_editor
The line edit open over the label while a rename is in progress; null otherwise. A sibling in the par...
Definition fieldlabel.h:92
void removeRequested()
The user chose "Remove field".
void finishEdit(bool commit)
Close the editor, putting the label back in its place.
~FieldLabel() override
Takes an open editor with it: the editor is a sibling, not a child, so it would otherwise stay behind...
void renamed(const QString &from, const QString &to)
The user typed a different name and confirmed it.
void mouseDoubleClickEvent(QMouseEvent *event) override
A left double-click starts editing the name.
void startEdit()
Open the in-place editor over the label.
auto eventFilter(QObject *watched, QEvent *event) -> bool override
Escape in the editor cancels the edit.
FieldLabel: the in-place renamable, removable name label of a key: value field in PasswordDialog.