Page Menu
Home
GnuPG
Search
Configure Global Search
Log In
Files
F34024218
passwordviewer.cpp
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Size
8 KB
Subscribers
None
passwordviewer.cpp
View Options
// SPDX-FileCopyrightText: 2014-2023 Anne Jan Brouwer <brouwer@annejan.com>
// SPDX-FileCopyrightText: 2016-2017 tezeb <tezeb+github@outoftheblue.pl>
// SPDX-FileCopyrightText: 2018 Lukas Vogel <lukedirtwalker@gmail.com>
// SPDX-FileCopyrightText: 2018 Claudio Maradonna <penguyman@stronzi.org>
// SPDX-FileCopyrightText: 2019 Maciej S. Szmigiero <mail@maciej.szmigiero.name>
// SPDX-FileCopyrightText: 2023 g10 Code GmbH
// SPDX-FileContributor: Sune Stolborg Vuorela <sune@vuorela.dk>
// SPDX-License-Identifier: GPL-3.0-or-later
#include
"passwordviewer.h"
#include
"clipboardhelper.h"
#include
"passentry.h"
#include
"qpushbuttonfactory.h"
#include
"settings.h"
#include
"util.h"
#include
<QDialog>
#include
<QFormLayout>
#include
<QLabel>
#include
<QMainWindow>
#include
<QPushButton>
#include
<QTextBrowser>
#include
<QVBoxLayout>
#include
<KLocalizedString>
#include
<KPasswordLineEdit>
#include
<KTitleWidget>
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
#include
<Prison/Barcode>
#else
#include
<Prison/AbstractBarcode>
#include
<Prison/prison.h>
#endif
namespace
{
std
::
unique_ptr
<
QTextBrowser
>
createTextBrowserForNotes
()
{
auto
textBrowser
=
std
::
make_unique
<
QTextBrowser
>
();
if
(
Settings
::
isNoLineWrapping
())
{
textBrowser
->
setLineWrapMode
(
QTextBrowser
::
NoWrap
);
}
textBrowser
->
setOpenExternalLinks
(
true
);
textBrowser
->
setContextMenuPolicy
(
Qt
::
DefaultContextMenu
);
textBrowser
->
document
()
->
setDocumentMargin
(
0
);
return
textBrowser
;
}
}
PasswordViewer
::
PasswordViewer
(
ClipboardHelper
*
clipboardHelper
,
QWidget
*
parent
)
:
QWidget
(
parent
)
,
m_titleWidget
(
new
KTitleWidget
(
this
))
,
m_clipboardHelper
(
clipboardHelper
)
,
m_contentLayout
(
new
QFormLayout
)
,
m_copyPasswordNameButton
(
new
QPushButton
(
QIcon
::
fromTheme
(
QStringLiteral
(
"edit-copy-symbolic"
)),
{},
this
))
{
auto
layout
=
new
QVBoxLayout
(
this
);
// Setup ui
m_copyPasswordNameButton
->
setAccessibleName
(
i18nc
(
"@action:button"
,
"Copy to clipboard"
));
m_copyPasswordNameButton
->
setToolTip
(
i18nc
(
"@info:tooltip"
,
"Copy title to clipboard"
));
auto
titleLayout
=
new
QHBoxLayout
;
titleLayout
->
addWidget
(
m_titleWidget
);
titleLayout
->
insertStretch
(
1
);
titleLayout
->
addWidget
(
m_copyPasswordNameButton
);
connect
(
m_copyPasswordNameButton
,
&
QPushButton
::
clicked
,
this
,
[
this
]()
{
m_clipboardHelper
->
copyTextToClipboard
(
m_titleWidget
->
text
().
trimmed
());
});
layout
->
addLayout
(
titleLayout
);
layout
->
addLayout
(
m_contentLayout
);
setPanelTimer
();
clearPanelTimer
.
setSingleShot
(
true
);
connect
(
&
clearPanelTimer
,
&
QTimer
::
timeout
,
this
,
&
PasswordViewer
::
clear
);
}
void
PasswordViewer
::
setPassEntry
(
const
PassEntry
&
entry
,
const
QString
&
content
)
{
QString
password
=
entry
.
password
();
QString
output
=
content
;
m_clipboardHelper
->
setClippedText
(
password
);
// first clear the current view:
clear
();
m_titleWidget
->
setText
(
entry
.
name
());
m_titleWidget
->
show
();
m_copyPasswordNameButton
->
show
();
// show what is needed:
if
(
!
Settings
::
isDisplayAsIs
())
{
if
(
!
password
.
isEmpty
())
{
// set the password, it is hidden if needed in addToGridLayout
addToGridLayout
(
i18n
(
"Password:"
),
password
);
}
const
auto
namedValues
=
entry
.
namedValues
();
for
(
const
auto
&
nv
:
namedValues
)
{
addToGridLayout
(
i18nc
(
"Field label"
,
"%1:"
,
nv
.
name
),
nv
.
value
);
}
output
=
entry
.
remainingDataForDisplay
();
}
if
(
Settings
::
isUseAutoclearPanel
())
{
clearPanelTimer
.
start
();
}
if
(
!
output
.
isEmpty
())
{
output
=
output
.
toHtmlEscaped
();
output
.
replace
(
Util
::
protocolRegex
(),
QStringLiteral
(
R
"
(
<a href="\1">\1</a>
)
"
));
output
.
replace
(
QLatin1Char
(
'\n'
),
QStringLiteral
(
"<br />"
));
auto
textBrowser
=
createTextBrowserForNotes
();
textBrowser
->
setHtml
(
output
);
m_contentLayout
->
addRow
(
new
QLabel
(
i18nc
(
"@label"
,
"Notes:"
)),
textBrowser
.
release
());
}
}
void
PasswordViewer
::
clearTemplateWidgets
()
{
while
(
m_contentLayout
->
count
()
>
0
)
{
m_contentLayout
->
removeRow
(
m_contentLayout
->
rowCount
()
-
1
);
}
}
void
PasswordViewer
::
addToGridLayout
(
const
QString
&
field
,
const
QString
&
value
)
{
QString
trimmedField
=
field
.
trimmed
();
QString
trimmedValue
=
value
.
trimmed
();
// Combine the Copy button and the line edit in one widget
auto
rowLayout
=
new
QHBoxLayout
();
rowLayout
->
setContentsMargins
(
0
,
2
,
0
,
2
);
if
(
trimmedField
==
i18n
(
"Password:"
))
{
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
auto
*
line
=
new
KPasswordLineEdit
();
line
->
setRevealPasswordMode
(
KPassword
::
RevealMode
::
Always
);
line
->
setReadOnly
(
true
);
line
->
setPassword
(
trimmedValue
);
#else
auto
*
line
=
new
QLineEdit
();
line
->
setText
(
trimmedValue
);
auto
iconOn
=
QIcon
::
fromTheme
(
QStringLiteral
(
"password-show-on"
));
auto
iconOff
=
QIcon
::
fromTheme
(
QStringLiteral
(
"password-show-off"
));
auto
action
=
line
->
addAction
(
iconOn
,
QLineEdit
::
TrailingPosition
);
action
->
setCheckable
(
true
);
action
->
setText
(
i18n
(
"Toggle password visibility"
));
connect
(
action
,
&
QAction
::
triggered
,
this
,
[
line
,
action
,
iconOn
,
iconOff
]()
{
if
(
line
->
echoMode
()
==
QLineEdit
::
Password
)
{
line
->
setEchoMode
(
QLineEdit
::
Normal
);
action
->
setIcon
(
iconOff
);
}
else
{
line
->
setEchoMode
(
QLineEdit
::
Password
);
action
->
setIcon
(
iconOn
);
}
});
#endif
line
->
setObjectName
(
trimmedField
);
line
->
setContentsMargins
(
0
,
0
,
0
,
0
);
line
->
setEchoMode
(
QLineEdit
::
Password
);
rowLayout
->
addWidget
(
line
);
}
else
{
auto
*
line
=
new
QLabel
();
line
->
setOpenExternalLinks
(
true
);
line
->
setTextInteractionFlags
(
Qt
::
TextSelectableByMouse
|
Qt
::
LinksAccessibleByMouse
|
Qt
::
LinksAccessibleByKeyboard
);
line
->
setSizePolicy
(
QSizePolicy
(
QSizePolicy
::
Expanding
,
QSizePolicy
::
Minimum
));
line
->
setObjectName
(
trimmedField
);
trimmedValue
.
replace
(
Util
::
protocolRegex
(),
QStringLiteral
(
R
"
(
<a href="\1">\1</a>
)
"
));
line
->
setText
(
trimmedValue
);
line
->
setContentsMargins
(
5
,
0
,
0
,
0
);
rowLayout
->
addWidget
(
line
);
}
auto
fieldName
=
trimmedField
;
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
fieldName
.
removeLast
();
// remove ':' from the end of the label
#else
fieldName
.
remove
(
fieldName
.
count
()
-
1
,
1
);
// remove ':' from the end of the label
#endif
auto
fieldLabel
=
createPushButton
(
QIcon
::
fromTheme
(
QStringLiteral
(
"edit-copy"
)),
i18n
(
"Copy '%1' to clipboard"
,
fieldName
),
m_clipboardHelper
,
[
this
,
trimmedValue
]
{
m_clipboardHelper
->
copyTextToClipboard
(
trimmedValue
);
});
rowLayout
->
addWidget
(
fieldLabel
.
release
());
auto
qrButton
=
createPushButton
(
QIcon
::
fromTheme
(
QStringLiteral
(
"view-barcode-qr"
)),
i18n
(
"View '%1' QR Code"
,
fieldName
),
m_clipboardHelper
,
[
this
,
trimmedValue
]()
{
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
auto
barcode
=
Prison
::
Barcode
::
create
(
Prison
::
QRCode
);
#else
auto
barcode
=
Prison
::
createBarcode
(
Prison
::
BarcodeType
::
QRCode
);
#endif
if
(
!
barcode
)
{
return
;
}
barcode
->
setData
(
trimmedValue
);
auto
image
=
barcode
->
toImage
(
barcode
->
preferredSize
(
window
()
->
devicePixelRatioF
()));
QDialog
popup
(
nullptr
,
Qt
::
Popup
|
Qt
::
FramelessWindowHint
);
QVBoxLayout
*
layout
=
new
QVBoxLayout
;
QLabel
*
popupLabel
=
new
QLabel
();
layout
->
addWidget
(
popupLabel
);
popupLabel
->
setPixmap
(
QPixmap
::
fromImage
(
image
));
popupLabel
->
setScaledContents
(
true
);
popupLabel
->
show
();
popup
.
setLayout
(
layout
);
popup
.
move
(
QCursor
::
pos
());
popup
.
exec
();
});
rowLayout
->
addWidget
(
qrButton
.
release
());
// set into the layout
m_contentLayout
->
addRow
(
trimmedField
,
rowLayout
);
}
/**
* @brief MainWindow::clearPanel hide the information from shoulder surfers
*/
void
PasswordViewer
::
clear
()
{
clearTemplateWidgets
();
m_titleWidget
->
setText
(
QString
{});
m_copyPasswordNameButton
->
hide
();
}
void
PasswordViewer
::
setPanelTimer
()
{
clearPanelTimer
.
setInterval
(
1000
*
Settings
::
getAutoclearPanelSeconds
());
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Sat, Nov 29, 7:11 AM (6 h, 26 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
91/37/c84b8fe114846fe26ab482e1e537
Attached To
rGPGPASS GnuPG Password Manager
Event Timeline
Log In to Comment