Allow disabling clipboard auto-share and add option to share manually

Continues the work started in !396 by rebasing it onto latest master and
making the "send clipboard" button from the plasmoid invisible when
automatic syncing is enabled.
    
I didn't find a way to do the same in kdeconnect-indicator and
kdeconnect-app (why do we have 3 UIs???), so in those we always show the
option for now.
This commit is contained in:
Albert Vaca Cintora 2023-06-07 19:48:25 +00:00
parent 5a93a48973
commit 144a60b58a
16 changed files with 200 additions and 33 deletions

View file

@ -98,6 +98,13 @@ Kirigami.ScrollablePage {
pluginName: "remotecommands"
device: root.currentDevice
},
PluginItem {
readonly property var clipboardIface: ClipboardDbusInterfaceFactory.create(root.currentDevice.id())
pluginName: "clipboard"
name: i18nd("kdeconnect-app", "Send Clipboard")
onClick: () => clipboardIface.sendClipboard()
device: root.currentDevice
},
PluginItem {
pluginName: "share"
name: i18nd("kdeconnect-app", "Share File")

View file

@ -51,6 +51,7 @@ int main(int argc, char **argv)
parser.addOption(QCommandLineOption(QStringLiteral("unpair"), i18n("Stop pairing to a said device")));
parser.addOption(QCommandLineOption(QStringLiteral("ping"), i18n("Sends a ping to said device")));
parser.addOption(QCommandLineOption(QStringLiteral("ping-msg"), i18n("Same as ping but you can set the message to display"), i18n("message")));
parser.addOption(QCommandLineOption(QStringLiteral("send-clipboard"), i18n("Sends the current clipboard to said device")));
parser.addOption(QCommandLineOption(QStringLiteral("share"), i18n("Share a file/URL to a said device"), QStringLiteral("path or URL")));
parser.addOption(QCommandLineOption(QStringLiteral("share-text"), i18n("Share text to a said device"), QStringLiteral("text")));
parser.addOption(QCommandLineOption(QStringLiteral("list-notifications"), i18n("Display the notifications on a said device")));
@ -264,6 +265,12 @@ int main(int argc, char **argv)
QTextStream(stderr) << i18n("Unpaired") << Qt::endl;
blockOnReply(dev.unpair());
}
} else if (parser.isSet(QStringLiteral("send-clipboard"))) {
QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kdeconnect"),
QStringLiteral("/modules/kdeconnect/devices/") + device + QStringLiteral("/clipboard"),
QStringLiteral("org.kde.kdeconnect.device.clipboard"),
QStringLiteral("sendClipboard"));
blockOnReply(QDBusConnection::sessionBus().asyncCall(msg));
} else if (parser.isSet(QStringLiteral("ping")) || parser.isSet(QStringLiteral("ping-msg"))) {
QDBusMessage msg = QDBusMessage::createMethodCall(QStringLiteral("org.kde.kdeconnect"),
QStringLiteral("/modules/kdeconnect/devices/") + device + QStringLiteral("/ping"),

View file

@ -64,6 +64,7 @@ void KdeConnectDeclarativePlugin::registerTypes(const char *uri)
0,
"FindMyPhoneDbusInterface",
QStringLiteral("You're not supposed to instantiate interfaces"));
qmlRegisterUncreatableType<ClipboardDbusInterface>(uri, 1, 0, "ClipboardDbusInterface", QStringLiteral("You're not supposed to instantiate interfaces"));
qmlRegisterUncreatableType<RemoteKeyboardDbusInterface>(uri,
1,
0,
@ -113,6 +114,7 @@ void KdeConnectDeclarativePlugin::registerTypes(const char *uri)
registerFactory<FindMyPhoneDeviceDbusInterface>(uri, "FindMyPhoneDbusInterfaceFactory");
registerFactory<SftpDbusInterface>(uri, "SftpDbusInterfaceFactory");
registerFactory<RemoteKeyboardDbusInterface>(uri, "RemoteKeyboardDbusInterfaceFactory");
registerFactory<ClipboardDbusInterface>(uri, "ClipboardDbusInterfaceFactory");
registerFactory<MprisDbusInterface>(uri, "MprisDbusInterfaceFactory");
registerFactory<RemoteControlDbusInterface>(uri, "RemoteControlDbusInterfaceFactory");
registerFactory<LockDeviceDbusInterface>(uri, "LockDeviceDbusInterfaceFactory");

View file

@ -63,6 +63,20 @@ DeviceIndicator::DeviceIndicator(DeviceDbusInterface *device)
},
this);
// Clipboard
auto clipboard = addAction(QIcon::fromTheme(QStringLiteral("klipper")), i18n("Send clipboard"));
connect(clipboard, &QAction::triggered, device, [device]() {
ClipboardDbusInterface *clipboardIface = new ClipboardDbusInterface(device->id(), device);
clipboardIface->sendClipboard();
clipboardIface->deleteLater();
});
setWhenAvailable(
device->hasPlugin(QStringLiteral("kdeconnect_clipboard")),
[clipboard](bool available) {
clipboard->setVisible(available);
},
this);
// Find device
auto findDevice = addAction(QIcon::fromTheme(QStringLiteral("irc-voice")), i18n("Ring device"));
connect(findDevice, &QAction::triggered, device, [device]() {

View file

@ -58,6 +58,7 @@ geninterface(${PROJECT_SOURCE_DIR}/plugins/remotesystemvolume/remotesystemvolume
geninterface(${PROJECT_SOURCE_DIR}/plugins/bigscreen/bigscreenplugin.h bigscreeninterface)
geninterface(${PROJECT_SOURCE_DIR}/plugins/virtualmonitor/virtualmonitorplugin.h virtualmonitorinterface)
geninterface(${PROJECT_SOURCE_DIR}/plugins/photo/photoplugin.h photointerface)
geninterface(${PROJECT_SOURCE_DIR}/plugins/clipboard/clipboardplugin.h deviceclipboardinterface)
add_library(kdeconnectinterfaces ${libkdeconnect_SRC})
set_target_properties(kdeconnectinterfaces PROPERTIES

View file

@ -261,3 +261,17 @@ VirtualmonitorDbusInterface::VirtualmonitorDbusInterface(const QString &deviceId
VirtualmonitorDbusInterface::~VirtualmonitorDbusInterface()
{
}
#include <iostream>
ClipboardDbusInterface::ClipboardDbusInterface(const QString &deviceId, QObject *parent)
: OrgKdeKdeconnectDeviceClipboardInterface(DaemonDbusInterface::activatedService(),
QStringLiteral("/modules/kdeconnect/devices/") + deviceId + QStringLiteral("/clipboard"),
QDBusConnection::sessionBus(),
parent)
{
connect(this, &OrgKdeKdeconnectDeviceClipboardInterface::autoShareDisabledChanged, this, &ClipboardDbusInterface::autoShareDisabledChangedProxy);
}
ClipboardDbusInterface::~ClipboardDbusInterface()
{
}

View file

@ -14,6 +14,7 @@
#include "connectivityinterface.h"
#include "conversationsinterface.h"
#include "daemoninterface.h"
#include "deviceclipboardinterface.h"
#include "devicefindmyphoneinterface.h"
#include "deviceinterface.h"
#include "devicenotificationsinterface.h"
@ -21,6 +22,7 @@
#include "lockdeviceinterface.h"
#include "mprisremoteinterface.h"
#include "notificationinterface.h"
#include "photointerface.h"
#include "remotecommandsinterface.h"
#include "remotecontrolinterface.h"
#include "remotekeyboardinterface.h"
@ -28,7 +30,6 @@
#include "shareinterface.h"
#include "smsinterface.h"
#include "virtualmonitorinterface.h"
#include "photointerface.h"
/**
* Using these "proxy" classes just in case we need to rename the
@ -276,4 +277,15 @@ static void setWhenAvailable(const QDBusPendingReply<T> &pending, W func, QObjec
});
}
class KDECONNECTINTERFACES_EXPORT ClipboardDbusInterface : public OrgKdeKdeconnectDeviceClipboardInterface
{
Q_OBJECT
Q_PROPERTY(bool isAutoShareDisabled READ isAutoShareDisabled NOTIFY autoShareDisabledChangedProxy)
public:
explicit ClipboardDbusInterface(const QString &deviceId, QObject *parent = nullptr);
~ClipboardDbusInterface() override;
Q_SIGNALS:
void autoShareDisabledChangedProxy(bool b);
};
#endif

View file

@ -0,0 +1,39 @@
/**
* SPDX-FileCopyrightText: 2021 Yaman Qalieh <ybq987@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
*/
import QtQuick 2.1
import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 2.0 as PlasmaComponents
import org.kde.kdeconnect 1.0
QtObject {
id: root
property alias device: checker.device
readonly property alias available: checker.available
readonly property PluginChecker pluginChecker: PluginChecker {
id: checker
pluginName: "clipboard"
}
property variant clipboard: null
function sendClipboard() {
if (clipboard) {
clipboard.sendClipboard();
}
}
onAvailableChanged: {
if (available) {
clipboard = ClipboardDbusInterfaceFactory.create(device.id())
} else {
clipboard = null
}
}
}

View file

@ -170,6 +170,24 @@ PlasmaComponents.ListItem
onClicked: fileDialog.open()
}
//Clipboard
PlasmaComponents.MenuItem
{
Clipboard {
id: clipboard
device: root.device
}
id: sendclipboard
icon: "klipper"
visible: clipboard.available && clipboard.clipboard.isAutoShareDisabled
text: i18n("Send Clipboard")
onClicked: {
clipboard.sendClipboard()
}
}
//Photo
PlasmaComponents.MenuItem
{

View file

@ -16,6 +16,7 @@ kdeconnect_add_plugin(kdeconnect_clipboard SOURCES ${kdeconnect_clipboard_SRCS})
target_link_libraries(kdeconnect_clipboard kdeconnectcore
KF5::GuiAddons
Qt${QT_MAJOR_VERSION}::DBus
${kdeconnect_clipboard_WL_LINK_LIBS}
)

View file

@ -17,7 +17,7 @@ ClipboardConfig::ClipboardConfig(QWidget* parent, const QVariantList &args)
{
m_ui->setupUi(this);
connect(m_ui->check_unknown, SIGNAL(toggled(bool)), this, SLOT(changed()));
connect(m_ui->check_autoshare, SIGNAL(toggled(bool)), this, SLOT(autoShareChanged()));
connect(m_ui->check_password, SIGNAL(toggled(bool)), this, SLOT(changed()));
}
@ -26,10 +26,16 @@ ClipboardConfig::~ClipboardConfig()
delete m_ui;
}
void ClipboardConfig::autoShareChanged()
{
m_ui->check_password->setEnabled(m_ui->check_autoshare->isChecked());
Q_EMIT changed();
}
void ClipboardConfig::defaults()
{
KCModule::defaults();
m_ui->check_unknown->setChecked(true);
m_ui->check_autoshare->setChecked(true);
m_ui->check_password->setChecked(true);
Q_EMIT changed(true);
}
@ -37,17 +43,17 @@ void ClipboardConfig::defaults()
void ClipboardConfig::load()
{
KCModule::load();
bool unknown = config()->getBool(QStringLiteral("sendUnknown"), true);
// "sendUnknown" is the legacy name for this setting
bool autoShare = config()->getBool(QStringLiteral("autoShare"), config()->getBool(QStringLiteral("sendUnknown"), true));
bool password = config()->getBool(QStringLiteral("sendPassword"), true);
m_ui->check_unknown->setChecked(unknown);
m_ui->check_autoshare->setChecked(autoShare);
m_ui->check_password->setChecked(password);
Q_EMIT changed(false);
autoShareChanged();
}
void ClipboardConfig::save()
{
config()->set(QStringLiteral("sendUnknown"), m_ui->check_unknown->isChecked());
config()->set(QStringLiteral("autoShare"), m_ui->check_autoshare->isChecked());
config()->set(QStringLiteral("sendPassword"), m_ui->check_password->isChecked());
KCModule::save();
Q_EMIT changed(false);

View file

@ -25,6 +25,7 @@ public Q_SLOTS:
void save() override;
void load() override;
void defaults() override;
void autoShareChanged();
private:
Ui::ClipboardConfigUi *m_ui;

View file

@ -29,20 +29,20 @@
</sizepolicy>
</property>
<property name="title">
<string>Contents shared to other devices</string>
<string>Automatic synchronization</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QCheckBox" name="check_password">
<widget class="QCheckBox" name="check_autoshare">
<property name="text">
<string>Passwords (as marked by password managers)</string>
<string>Automatically share the clipboard from this device</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="check_unknown">
<widget class="QCheckBox" name="check_password">
<property name="text">
<string>Anything else</string>
<string>Including passwords (as marked by password managers)</string>
</property>
</widget>
</item>

View file

@ -16,7 +16,9 @@ K_PLUGIN_CLASS_WITH_JSON(ClipboardPlugin, "kdeconnect_clipboard.json")
ClipboardPlugin::ClipboardPlugin(QObject *parent, const QVariantList &args)
: KdeConnectPlugin(parent, args)
{
connect(ClipboardListener::instance(), &ClipboardListener::clipboardChanged, this, &ClipboardPlugin::propagateClipboard);
connect(ClipboardListener::instance(), &ClipboardListener::clipboardChanged, this, &ClipboardPlugin::clipboardChanged);
connect(config(), &KdeConnectPluginConfig::configChanged, this, &ClipboardPlugin::configChanged);
configChanged();
}
void ClipboardPlugin::connected()
@ -24,20 +26,47 @@ void ClipboardPlugin::connected()
sendConnectPacket();
}
void ClipboardPlugin::propagateClipboard(const QString &content, ClipboardListener::ClipboardContentType contentType)
QString ClipboardPlugin::dbusPath() const
{
if (contentType == ClipboardListener::ClipboardContentTypeUnknown) {
if (!config()->getBool(QStringLiteral("sendUnknown"), true)) {
return;
}
} else if (contentType == ClipboardListener::ClipboardContentTypePassword) {
if (!config()->getBool(QStringLiteral("sendPassword"), true)) {
return;
}
} else {
return QStringLiteral("/modules/kdeconnect/devices/") + device()->id() + QStringLiteral("/clipboard");
}
void ClipboardPlugin::clipboardChanged(const QString &content, ClipboardListener::ClipboardContentType contentType)
{
if (!autoShare) {
return;
}
if (contentType == ClipboardListener::ClipboardContentTypePassword) {
if (!sharePasswords) {
return;
}
}
sendClipboard(content);
}
void ClipboardPlugin::configChanged()
{
autoShare = config()->getBool(QStringLiteral("autoShare"), config()->getBool(QStringLiteral("sendUnknown"), true));
sharePasswords = config()->getBool(QStringLiteral("sendPassword"), true);
Q_EMIT autoShareDisabledChanged(isAutoShareDisabled());
}
bool ClipboardPlugin::isAutoShareDisabled()
{
// Return true also if autoShare is enabled but disabled for passwords
return !autoShare || !sharePasswords;
}
void ClipboardPlugin::sendClipboard()
{
QString content = ClipboardListener::instance()->currentContent();
sendClipboard(content);
}
void ClipboardPlugin::sendClipboard(const QString &content)
{
NetworkPacket np(PACKET_TYPE_CLIPBOARD, {{QStringLiteral("content"), content}});
sendPacket(np);
}

View file

@ -41,15 +41,30 @@
class ClipboardPlugin : public KdeConnectPlugin
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.kde.kdeconnect.device.clipboard")
Q_PROPERTY(bool isAutoShareDisabled READ isAutoShareDisabled NOTIFY autoShareDisabledChanged)
public:
explicit ClipboardPlugin(QObject *parent, const QVariantList &args);
Q_SCRIPTABLE void sendClipboard();
Q_SCRIPTABLE void sendClipboard(const QString &content);
QString dbusPath() const override;
bool receivePacket(const NetworkPacket &np) override;
void connected() override;
bool isAutoShareDisabled();
Q_SIGNALS:
Q_SCRIPTABLE void autoShareDisabledChanged(bool b);
private Q_SLOTS:
void propagateClipboard(const QString &content, ClipboardListener::ClipboardContentType contentType);
void clipboardChanged(const QString &content, ClipboardListener::ClipboardContentType contentType);
void sendConnectPacket();
void configChanged();
private:
bool autoShare;
bool sharePasswords;
};
#endif

View file

@ -21,19 +21,20 @@ Kirigami.FormLayout {
}
Component.onCompleted: {
unknown.checked = config.getBool("sendUnknown", true)
autoShare.checked = config.getBool("autoShare", config.getBool("sendUnknown", true))
password.checked = config.getBool("sendPassword", true)
}
QQC2.CheckBox {
id: password
text: i18n("Passwords (as marked by password managers)")
onClicked: config.set("sendPassword", checked)
id: autoShare
text: i18n("Automatically share the clipboard from this device")
onClicked: config.set("autoShare", checked)
}
QQC2.CheckBox {
id: unknown
text: i18n("Anything else")
onClicked: config.set("sendUnknown", checked)
id: password
text: i18n("Including passwords (as marked by password managers)")
onClicked: config.set("sendPassword", checked)
}
}