feat(BRIDGE-88): added context menu for quick actions on input labels: cut, copy, paste

This commit is contained in:
Atanas Janeshliev
2024-08-07 10:19:40 +00:00
parent bbfc9beb04
commit 81a3c2aba8
10 changed files with 165 additions and 1 deletions

View File

@ -75,7 +75,7 @@ if(NOT UNIX)
set(CMAKE_INSTALL_BINDIR ".")
endif(NOT UNIX)
find_package(Qt6 COMPONENTS Core Quick Qml QuickControls2 Widgets Svg REQUIRED)
find_package(Qt6 COMPONENTS Core Quick Qml QuickControls2 Widgets Svg Gui REQUIRED)
qt_standard_project_setup()
set(CMAKE_AUTORCC ON)
message(STATUS "Using Qt ${Qt6_VERSION}")
@ -120,6 +120,7 @@ add_executable(bridge-gui
UserList.cpp UserList.h
SentryUtils.cpp SentryUtils.h
Settings.cpp Settings.h
ClipboardProxy.cpp ClipboardProxy.h
${DOCK_ICON_SRC_FILE} MacOS/DockIcon.h
)
@ -148,6 +149,7 @@ target_link_libraries(bridge-gui
Qt6::Qml
Qt6::QuickControls2
Qt6::Svg
Qt6::Gui
sentry::sentry
bridgepp
)

View File

@ -0,0 +1,25 @@
// Copyright (c) 2024 Proton AG
// This file is part of Proton Mail Bridge.
// Proton Mail Bridge 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 3 of the License, or
// (at your option) any later version.
// Proton Mail Bridge 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 Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#include "ClipboardProxy.h"
// The following definitions were taken and adapted from:
// https://stackoverflow.com/questions/40092352/passing-qclipboard-to-qml
// Author: krzaq
ClipboardProxy::ClipboardProxy(QClipboard* c) : clipboard(c) {
connect(clipboard, &QClipboard::dataChanged, this, &ClipboardProxy::textChanged);
}
QString ClipboardProxy::text() const {
return clipboard->text();
}

View File

@ -0,0 +1,38 @@
// Copyright (c) 2024 Proton AG
// This file is part of Proton Mail Bridge.
// Proton Mail Bridge 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 3 of the License, or
// (at your option) any later version.
// Proton Mail Bridge 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 Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
#ifndef BRIDGE_GUI_CLIPBOARDPROXY_H
#define BRIDGE_GUI_CLIPBOARDPROXY_H
// The following class declarations were taken and adapted from:
// https://stackoverflow.com/questions/40092352/passing-qclipboard-to-qml
// Author: krzaq
class ClipboardProxy : public QObject
{
Q_OBJECT
Q_PROPERTY(QString text READ text NOTIFY textChanged)
public:
explicit ClipboardProxy(QClipboard*);
QString text() const;
signals:
void textChanged();
private:
QClipboard* clipboard;
};
#endif //BRIDGE_GUI_CLIPBOARDPROXY_H

View File

@ -26,6 +26,7 @@
#include <QtWidgets>
#include <QtQuickControls2>
#include <QtSvg>
#include <QtGui>
#include <AppController.h>

View File

@ -132,5 +132,6 @@
<file>qml/ConnectionModeSettings.qml</file>
<file>qml/SplashScreen.qml</file>
<file>qml/Status.qml</file>
<file>qml/Proton/ContextMenu.qml</file>
</qresource>
</RCC>

View File

@ -28,6 +28,7 @@
#include <bridgepp/Log/Log.h>
#include <bridgepp/Log/LogUtils.h>
#include <bridgepp/ProcessMonitor.h>
#include <ClipboardProxy.h>
#include "bridgepp/CLI/CLIUtils.h"
@ -347,6 +348,8 @@ int main(int argc, char *argv[]) {
log.info(QString("Qt Quick renderer: %1").arg(QQuickWindow::sceneGraphBackend()));
QQmlApplicationEngine engine;
// Set up clipboard
engine.rootContext()->setContextProperty("clipboard", new ClipboardProxy(QGuiApplication::clipboard()));
std::unique_ptr<QQmlComponent> rootComponent(createRootQmlComponent(engine));
std::unique_ptr<QObject> rootObject(rootComponent->create(engine.rootContext()));
if (!rootObject) {

View File

@ -0,0 +1,79 @@
// Copyright (c) 2024 Proton AG
// This file is part of Proton Mail Bridge.
// Proton Mail Bridge 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 3 of the License, or
// (at your option) any later version.
// Proton Mail Bridge 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 Proton Mail Bridge. If not, see <https://www.gnu.org/licenses/>.
import QtQuick
import QtQuick.Controls
Item {
property var parentObject: null
property var colorScheme: null
property bool readOnly: false
property bool isPassword: false
MouseArea {
id: controlMouseArea
width: parentObject ? parentObject.width : 0
height: parentObject ? parentObject.height : 0
acceptedButtons: Qt.RightButton
onClicked: controlContextMenu.popup()
propagateComposedEvents: true
}
Menu {
id: controlContextMenu
colorScheme: root.colorScheme
onVisibleChanged: {
if (controlContextMenu.visible) {
const hasSelectedText = parentObject.selectedText.length > 0;
const hasClipboardText = clipboard.text.length > 0;
copyMenuItem.visible = hasSelectedText && !isPassword;
cutMenuItem.visible = hasSelectedText && !readOnly && !isPassword;
pasteMenuItem.visible = hasClipboardText && !readOnly;
controlContextMenu.visible = copyMenuItem.visible || cutMenuItem.visible || pasteMenuItem.visible;
}
}
MenuItem {
id: cutMenuItem
colorScheme: root.colorScheme
height: visible ? implicitHeight : 0
text: qsTr("Cut")
onClicked: {
parentObject.cut()
}
}
MenuItem {
id: copyMenuItem
colorScheme: root.colorScheme
height: visible ? implicitHeight : 0
text: qsTr("Copy")
onTriggered: {
parentObject.copy()
}
}
MenuItem {
id: pasteMenuItem
colorScheme: root.colorScheme
height: visible ? implicitHeight : 0
text: qsTr("Paste")
onTriggered: {
parentObject.paste()
}
}
}
}

View File

@ -362,4 +362,9 @@ FocusScope {
}
}
}
Proton.ContextMenu {
parentObject: root
colorScheme: root.colorScheme
}
}

View File

@ -331,6 +331,15 @@ FocusScope {
x: control.leftPadding
y: control.topPadding
}
Proton.ContextMenu {
parentObject: control
colorScheme: root.colorScheme
isPassword: control.echoMode === TextInput.Password
readOnly: control.readOnly
}
}
Proton.Button {
id: eyeButton

View File

@ -39,3 +39,4 @@ TextArea 4.0 TextArea.qml
TextField 4.0 TextField.qml
Toggle 4.0 Toggle.qml
WebFrame 4.0 WebFrame.qml
ContextMenu 4.0 ContextMenu.qml