Compare commits
3 commits
master
...
work/udp-r
Author | SHA1 | Date | |
---|---|---|---|
|
4269ec8c2a | ||
|
dd187274f7 | ||
|
194a819302 |
18 changed files with 205 additions and 34 deletions
|
@ -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")
|
||||
|
|
|
@ -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"),
|
||||
|
|
|
@ -80,7 +80,7 @@ void LanLinkProvider::onStart()
|
|||
{
|
||||
const QHostAddress bindAddress = m_testMode ? QHostAddress::LocalHost : QHostAddress::Any;
|
||||
|
||||
bool success = m_udpSocket.bind(bindAddress, m_udpListenPort, QUdpSocket::ShareAddress);
|
||||
bool success = m_udpSocket.bind(bindAddress, m_udpListenPort, QAbstractSocket::ShareAddress | QAbstractSocket::ReuseAddressHint);
|
||||
if (!success) {
|
||||
QAbstractSocket::SocketError sockErr = m_udpSocket.error();
|
||||
// Refer to https://doc.qt.io/qt-5/qabstractsocket.html#SocketError-enum to decode socket error number
|
||||
|
|
|
@ -133,9 +133,11 @@ int main(int argc, char *argv[])
|
|||
QCommandLineParser parser;
|
||||
QCommandLineOption replaceOption({QStringLiteral("replace")}, i18n("Replace an existing instance"));
|
||||
parser.addOption(replaceOption);
|
||||
#ifdef Q_OS_MAC
|
||||
QCommandLineOption macosPrivateDBusOption({QStringLiteral("use-private-dbus")},
|
||||
i18n("Launch a private D-Bus daemon with kdeconnectd (macOS test-purpose only)"));
|
||||
parser.addOption(macosPrivateDBusOption);
|
||||
#endif
|
||||
aboutData.setupCommandLine(&parser);
|
||||
|
||||
parser.process(app);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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]() {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
39
plasmoid/package/contents/ui/Clipboard.qml
Normal file
39
plasmoid/package/contents/ui/Clipboard.qml
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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}
|
||||
)
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -25,6 +25,7 @@ public Q_SLOTS:
|
|||
void save() override;
|
||||
void load() override;
|
||||
void defaults() override;
|
||||
void autoShareChanged();
|
||||
|
||||
private:
|
||||
Ui::ClipboardConfigUi *m_ui;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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,49 @@ 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);
|
||||
}
|
||||
|
||||
#include <iostream>
|
||||
void ClipboardPlugin::configChanged()
|
||||
{
|
||||
autoShare = config()->getBool(QStringLiteral("autoShare"), config()->getBool(QStringLiteral("sendUnknown"), true));
|
||||
sharePasswords = config()->getBool(QStringLiteral("sendPassword"), true);
|
||||
std::cout << "CONFIG CHANGED KCM" << std::endl;
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue