QtPass
2.0.0
Developer documentation
Toggle main menu visibility
Loading...
Searching...
No Matches
processoutputpanel.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 "
processoutputpanel.h
"
9
#include "
processinfo.h
"
10
#include <QHBoxLayout>
11
#include <QScrollBar>
12
#include <QTextCursor>
13
#include <QTextDocument>
14
#include <QTextEdit>
15
#include <QToolButton>
16
17
ProcessOutputPanel::ProcessOutputPanel
(QWidget *parent)
18
: QDockWidget(tr(
"Process output"
), parent) {
19
setObjectName(QStringLiteral(
"processOutputDock"
));
20
setFeatures(QDockWidget::DockWidgetMovable |
21
QDockWidget::DockWidgetFloatable);
22
setAllowedAreas(Qt::BottomDockWidgetArea | Qt::TopDockWidgetArea);
23
24
auto
*contents =
new
QWidget(
this
);
25
contents->setObjectName(QStringLiteral(
"processOutputWidget"
));
26
auto
*layout =
new
QHBoxLayout(contents);
27
layout->setObjectName(QStringLiteral(
"processOutputLayout"
));
28
layout->setContentsMargins(0, 0, 0, 0);
29
m_clearButton
=
new
QToolButton(contents);
30
m_clearButton
->setObjectName(QStringLiteral(
"clearOutputButton"
));
31
m_clearButton
->setText(tr(
"Clear"
));
32
m_clearButton
->setToolTip(tr(
"Clear output"
));
33
layout->addWidget(
m_clearButton
);
34
m_edit
=
new
QTextEdit(contents);
35
m_edit
->setObjectName(QStringLiteral(
"processOutputEdit"
));
36
m_edit
->setReadOnly(
true
);
37
m_edit
->setAcceptRichText(
false
);
38
layout->addWidget(
m_edit
);
39
setWidget(contents);
40
41
connect(
m_clearButton
, &QToolButton::clicked,
this
,
42
&
ProcessOutputPanel::clear
);
43
44
// Hysteresis: while the user is actively dragging the slider, don't
45
// touch m_autoScroll on every tick — a brief overshoot at maximum
46
// would silently re-arm auto-scroll without an explicit release. Only
47
// commit on slider release. Wheel/keyboard scroll never sets
48
// isSliderDown(), so they still update immediately.
49
QScrollBar *bar =
m_edit
->verticalScrollBar();
50
connect(bar, &QScrollBar::valueChanged,
this
, [
this
, bar]() {
51
if
(bar->isSliderDown())
52
return
;
53
m_autoScroll
= bar->value() >= bar->maximum();
54
});
55
connect(bar, &QScrollBar::sliderReleased,
this
,
56
[
this
, bar]() {
m_autoScroll
= bar->value() >= bar->maximum(); });
57
}
58
59
void
ProcessOutputPanel::append
(
const
QString &output,
bool
isError,
60
const
QString &linePrefix) {
61
QStringList lines = output.split(
'\n'
, Qt::SkipEmptyParts);
62
for
(QString &line : lines) {
63
// Right-trim only: remove trailing CR and whitespace, preserve leading
64
// indentation
65
line.remove(
'\r'
);
66
while
(!line.isEmpty() && line.back().isSpace()) {
67
line.chop(1);
68
}
69
if
(line.isEmpty()) {
70
continue
;
71
}
72
73
m_counter
++;
74
const
QColor textColor =
75
isError ? QColor(Qt::red) :
m_edit
->palette().color(QPalette::Text);
76
// Apply the optional prefix per line so multi-line output stays
77
// attributed to its command (e.g. all 3 lines of a `git push` show
78
// "git push: ..." rather than only the first).
79
const
QString prefixed =
80
linePrefix.isEmpty() ? line : linePrefix + QStringLiteral(
": "
) + line;
81
// white-space: pre keeps the indentation the trimming above preserved;
82
// rich text would otherwise collapse it.
83
m_edit
->append(
84
QStringLiteral(
85
"<span style=\"color: %1; white-space: pre;\">%2: %3</span>"
)
86
.arg(textColor.name(), QString::number(
m_counter
),
87
prefixed.toHtmlEscaped()));
88
}
89
90
limitLines
();
91
92
if
(
m_autoScroll
) {
93
m_edit
->verticalScrollBar()->setValue(
94
m_edit
->verticalScrollBar()->maximum());
95
}
96
}
97
98
void
ProcessOutputPanel::limitLines
() {
99
QTextDocument *doc =
m_edit
->document();
100
const
int
excess = doc->blockCount() -
MaxLines
;
101
if
(excess <= 0) {
102
return
;
103
}
104
QTextCursor cursor(doc);
105
cursor.movePosition(QTextCursor::Start);
106
cursor.movePosition(QTextCursor::NextBlock, QTextCursor::KeepAnchor, excess);
107
cursor.removeSelectedText();
108
}
109
110
void
ProcessOutputPanel::clear
() {
111
m_edit
->clear();
112
m_counter
= 0;
113
m_autoScroll
=
true
;
114
}
115
116
auto
ProcessOutputPanel::processName
(
Enums::PROCESS
pid) -> QString {
117
return
Enums::processLabel
(pid);
118
}
119
120
auto
ProcessOutputPanel::isSensitiveProcess
(
Enums::PROCESS
pid) ->
bool
{
121
return
Enums::processInfo
(pid).secret;
122
}
ProcessOutputPanel::MaxLines
static constexpr int MaxLines
Oldest lines are dropped once the document holds more than this.
Definition
processoutputpanel.h:35
ProcessOutputPanel::limitLines
void limitLines()
Drop the oldest text blocks once the document holds more than MaxLines; called after every append().
Definition
processoutputpanel.cpp:98
ProcessOutputPanel::isSensitiveProcess
static auto isSensitiveProcess(Enums::PROCESS pid) -> bool
Whether a process's output may carry secrets and must never reach this long-lived panel (pass show,...
Definition
processoutputpanel.cpp:120
ProcessOutputPanel::clear
void clear()
Drop all output, reset the counter, re-arm auto-scroll.
Definition
processoutputpanel.cpp:110
ProcessOutputPanel::m_counter
int m_counter
Running line number shown in front of each line; reset by clear(). Keeps counting past MaxLines.
Definition
processoutputpanel.h:107
ProcessOutputPanel::ProcessOutputPanel
ProcessOutputPanel(QWidget *parent=nullptr)
Build the console (Clear button + read-only text edit).
Definition
processoutputpanel.cpp:17
ProcessOutputPanel::processName
static auto processName(Enums::PROCESS pid) -> QString
Human-readable command label for a process id.
Definition
processoutputpanel.cpp:116
ProcessOutputPanel::m_autoScroll
bool m_autoScroll
Whether append() scrolls to the bottom: cleared when the user scrolls up, set again when the scroll b...
Definition
processoutputpanel.h:113
ProcessOutputPanel::m_edit
QTextEdit * m_edit
Read-only text edit holding the output; child of the dock.
Definition
processoutputpanel.h:100
ProcessOutputPanel::m_clearButton
QToolButton * m_clearButton
The "Clear" button wired to clear().
Definition
processoutputpanel.h:102
ProcessOutputPanel::append
void append(const QString &output, bool isError, const QString &linePrefix=QString())
Append output, one numbered line per non-empty input line.
Definition
processoutputpanel.cpp:59
Enums::processLabel
auto processLabel(PROCESS pid) -> QString
The command label for pid, as the output panel shows it.
Definition
processinfo.cpp:65
Enums::PROCESS
PROCESS
Identifies different subprocess operations used in QtPass.
Definition
enums.h:43
Enums::processInfo
auto processInfo(PROCESS pid) -> const ProcessInfo &
What is known about pid.
Definition
processinfo.cpp:58
processinfo.h
Enums::ProcessInfo, the one table that names each kind of subprocess and says whether its output may ...
processoutputpanel.h
ProcessOutputPanel: the dockable console that shows numbered, colour-coded git/pass/gpg output.
src
processoutputpanel.cpp
Generated by
1.18.0