diff --git a/qt/pinlineedit.cpp b/qt/pinlineedit.cpp index f70a1ae..d0309eb 100644 --- a/qt/pinlineedit.cpp +++ b/qt/pinlineedit.cpp @@ -1,107 +1,166 @@ /* pinlineedit.cpp - Modified QLineEdit widget. * Copyright (C) 2018 Damien Goutte-Gattat * Copyright (C) 2021 g10 Code GmbH * * Software engineering by Ingo Klöcker * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * SPDX-License-Identifier: GPL-2.0+ */ #include "pinlineedit.h" +#include +#include #include static const int FormattedPassphraseGroupSize = 4; static const QChar FormattedPassphraseSeparator = QChar::Nbsp; class PinLineEdit::Private { public: QString formatted(QString text) const { const int dashCount = text.size() / FormattedPassphraseGroupSize; text.reserve(text.size() + dashCount); for (int i = FormattedPassphraseGroupSize; i < text.size(); i += FormattedPassphraseGroupSize + 1) { text.insert(i, FormattedPassphraseSeparator); } return text; } QString unformatted(QString text) const { for (int i = FormattedPassphraseGroupSize; i < text.size(); i += FormattedPassphraseGroupSize) { text.remove(i, 1); } return text; } + void copyToClipboard(const PinLineEdit *edit) + { + if (edit->echoMode() != QLineEdit::Normal) { + return; + } + + QString text = edit->selectedText(); + if (mFormattedPassphrase) { + text.remove(FormattedPassphraseSeparator); + } + if (!text.isEmpty()) { + QGuiApplication::clipboard()->setText(text); + } + } + public: bool mFormattedPassphrase = false; }; PinLineEdit::PinLineEdit(QWidget *parent) : QLineEdit(parent) , d{new Private} { connect(this, SIGNAL(textEdited(QString)), this, SLOT(textEdited())); } PinLineEdit::~PinLineEdit() = default; void PinLineEdit::setFormattedPassphrase(bool on) { if (on == d->mFormattedPassphrase) { return; } d->mFormattedPassphrase = on; if (d->mFormattedPassphrase) { setText(d->formatted(text())); } else { setText(d->unformatted(text())); } } +void PinLineEdit::copy() const +{ + d->copyToClipboard(this); +} + +void PinLineEdit::cut() +{ + if (hasSelectedText()) { + copy(); + del(); + } +} + void PinLineEdit::setPin(const QString &pin) { setText(d->mFormattedPassphrase ? d->formatted(pin) : pin); } QString PinLineEdit::pin() const { if (d->mFormattedPassphrase) { return d->unformatted(text()); } else { return text(); } } void PinLineEdit::keyPressEvent(QKeyEvent *e) { + if (e == QKeySequence::Copy) { + copy(); + return; + } + else if (e == QKeySequence::Cut) { + if (!isReadOnly() && hasSelectedText()) { + copy(); + del(); + } + return; + } + else if (e == QKeySequence::DeleteEndOfLine) { + if (!isReadOnly()) { + setSelection(cursorPosition(), text().size()); + copy(); + del(); + } + return; + } + else if (e == QKeySequence::DeleteCompleteLine) { + if (!isReadOnly()) { + setSelection(0, text().size()); + copy(); + del(); + } + return; + } + QLineEdit::keyPressEvent(e); - if ( e->key() == Qt::Key::Key_Backspace ) - emit backspacePressed(); + if (e->key() == Qt::Key::Key_Backspace) { + emit backspacePressed(); + } } void PinLineEdit::textEdited() { if (!d->mFormattedPassphrase) { return; } setText(d->formatted(text().remove(FormattedPassphraseSeparator))); } #include "pinlineedit.moc" diff --git a/qt/pinlineedit.h b/qt/pinlineedit.h index 9448888..e67ced8 100644 --- a/qt/pinlineedit.h +++ b/qt/pinlineedit.h @@ -1,61 +1,63 @@ /* pinlineedit.h - Modified QLineEdit widget. * Copyright (C) 2018 Damien Goutte-Gattat * Copyright (C) 2021 g10 Code GmbH * * Software engineering by Ingo Klöcker * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, see . * SPDX-License-Identifier: GPL-2.0+ */ #ifndef _PINLINEEDIT_H_ #define _PINLINEEDIT_H_ #include #include class PinLineEdit : public QLineEdit { Q_OBJECT public: explicit PinLineEdit(QWidget *parent = nullptr); ~PinLineEdit() override; void setPin(const QString &pin); QString pin() const; public Q_SLOTS: void setFormattedPassphrase(bool on); + void copy() const; + void cut(); Q_SIGNALS: void backspacePressed(); protected: void keyPressEvent(QKeyEvent *) override; private: using QLineEdit::setText; using QLineEdit::text; private Q_SLOTS: void textEdited(); private: class Private; std::unique_ptr d; }; #endif // _PINLINEEDIT_H_