...
 
Commits (309)
......@@ -7,3 +7,4 @@ insert_final_newline = true
indent_style = space
indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
......@@ -16,3 +16,10 @@ KDEConnect.includes
*.qmlc
*.rej
.vscode
# Eclipse settings
.cproject
.project
.settings/*
CMakeLists.txt.user
Please report any issues to [bugs.kde.org](https://bugs.kde.org/enter_bug.cgi?product=kdeconnect)
\ No newline at end of file
......@@ -2,41 +2,72 @@ cmake_minimum_required(VERSION 3.0)
project(kdeconnect)
set(KDECONNECT_VERSION_MAJOR 1)
set(KDECONNECT_VERSION_MINOR 3)
set(KDECONNECT_VERSION_PATCH 3)
if (SAILFISHOS)
set(KF5_MIN_VERSION "5.31.0")
set(QT_MIN_VERSION "5.6.0")
set(QCA_MIN_VERSION "2.0.0")
else()
set(KF5_MIN_VERSION "5.48.0")
set(QT_MIN_VERSION "5.10.0")
set(QCA_MIN_VERSION "2.1.0")
endif()
find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
include(KDEInstallDirs)
include(KDECompilerSettings NO_POLICY_SCOPE)
include(KDECMakeSettings)
include(ECMAddTests)
include(ECMSetupVersion)
include(ECMInstallIcons)
include(FeatureSummary)
include(GenerateExportHeader)
set(KDECONNECT_VERSION "${KDECONNECT_VERSION_MAJOR}.${KDECONNECT_VERSION_MINOR}.${KDECONNECT_VERSION_PATCH}")
include(KDEConnectMacros.cmake)
find_package(PkgConfig)
ecm_setup_version(1.3.3
VARIABLE_PREFIX KDECONNECT
VERSION_HEADER ${CMAKE_CURRENT_BINARY_DIR}/kdeconnect-version.h
)
if (SAILFISHOS)
set(KF5_MIN_VERSION "5.31.0")
set(QT_MIN_VERSION "5.6.0")
find_package(PkgConfig)
set(KF5_REQUIRED_COMPONENTS I18n DBusAddons CoreAddons IconThemes Config)
set(KF5_OPTIONAL_COMPONENTS)
set(QCA_MIN_VERSION 2.0.0)
pkg_search_module(SFOS REQUIRED sailfishapp)
pkg_check_modules(QCA2 qca2-qt5>=${QCA_MIN_VERSION} REQUIRED)
add_definitions(-DSAILFISHOS)
include_directories(${QCA2_INCLUDEDIR})
add_definitions(-DQT_NO_URL_CAST_FROM_STRING)
else()
set(KF5_MIN_VERSION "5.42.0")
set(QT_MIN_VERSION "5.7.0")
set(KF5_REQUIRED_COMPONENTS I18n ConfigWidgets DBusAddons IconThemes Notifications KIO KCMUtils Service)
set(KF5_REQUIRED_COMPONENTS I18n ConfigWidgets DBusAddons IconThemes Notifications KIO KCMUtils Service Kirigami2 People)
set(KF5_OPTIONAL_COMPONENTS DocTools)
if(UNIX)
set_package_properties(KF5Kirigami2 PROPERTIES
DESCRIPTION "QtQuick plugins to build user interfaces based on KDE UX guidelines"
PURPOSE "Required for KDE Connect's QML-based GUI applications"
URL "https://www.kde.org/products/kirigami/"
TYPE RUNTIME
)
if(UNIX AND NOT APPLE)
set(KF5_OPTIONAL_COMPONENTS ${KF5_OPTIONAL_COMPONENTS} Runner)
endif()
set(QCA_MIN_VERSION "2.1.0")
find_package(Qca-qt5 ${QCA_MIN_VERSION} REQUIRED)
find_package(KF5PulseAudioQt)
add_definitions(-DQT_NO_URL_CAST_FROM_STRING -DQT_NO_KEYWORDS)
endif()
find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} ${CMAKE_SOURCE_DIR}/cmake)
find_package(KF5PeopleVCard)
set_package_properties(KF5PeopleVCard PROPERTIES
PURPOSE "Read vcards from the file system"
URL "https://phabricator.kde.org/source/kpeoplevcard/"
TYPE RUNTIME
)
if(NOT WIN32 AND NOT APPLE)
find_package(KF5PulseAudioQt)
endif()
add_definitions(-DQT_NO_URL_CAST_FROM_STRING -DQT_NO_KEYWORDS -DQT_NO_CAST_FROM_ASCII)
endif()
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Quick Network)
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS ${KF5_REQUIRED_COMPONENTS})
......@@ -50,85 +81,48 @@ endif()
find_package(Qt5Multimedia)
set_package_properties(KF5Kirigami2 PROPERTIES
DESCRIPTION "QtQuick plugins to build user interfaces based on KDE UX guidelines"
PURPOSE "Required for KDE Connect's QML-based GUI applications"
URL "https://www.kde.org/products/kirigami/"
TYPE RUNTIME
)
configure_file(kdeconnect-version.h.in ${CMAKE_CURRENT_BINARY_DIR}/kdeconnect-version.h)
include(KDEInstallDirs)
include(KDECompilerSettings NO_POLICY_SCOPE)
include(KDECMakeSettings)
include(ECMAddTests)
include(ECMSetupVersion)
include(ECMInstallIcons)
include(FeatureSummary)
include(KDEConnectMacros.cmake)
include(GenerateExportHeader)
add_subdirectory(core)
if(NOT SAILFISHOS)
add_subdirectory(kcm)
add_subdirectory(kcmplugin)
add_subdirectory(daemon)
endif()
if(NOT WIN32 AND NOT SAILFISHOS)
add_subdirectory(kio)
add_subdirectory(plasmoid)
option(PRIVATE_DBUS_ENABLED "Use private dbus session for kdeconnect" OFF)
if(PRIVATE_DBUS_ENABLED OR APPLE)
add_compile_definitions(USE_PRIVATE_DBUS)
endif()
add_subdirectory(core)
add_subdirectory(icon)
add_subdirectory(interfaces)
add_subdirectory(data)
option(EXPERIMENTALAPP_ENABLED OFF)
if(EXPERIMENTALAPP_ENABLED)
find_package(KF5Kirigami2)
add_subdirectory(app)
endif()
add_subdirectory(plugins)
add_subdirectory(cli)
add_subdirectory(declarativeplugin)
if(KF5Runner_FOUND)
add_subdirectory(runners)
endif()
if (NOT SAILFISHOS)
if(NOT SAILFISHOS)
add_subdirectory(kcm)
add_subdirectory(kcmplugin)
add_subdirectory(daemon)
add_subdirectory(app)
add_subdirectory(indicator)
add_subdirectory(urlhandler)
add_subdirectory(nautilus-extension)
add_subdirectory(fileitemactionplugin)
else()
add_subdirectory(sfos)
endif()
add_subdirectory(smsapp)
option(SMSAPP_ENABLED OFF)
if(SMSAPP_ENABLED)
find_package(KF5Kirigami2)
find_package(KF5People REQUIRED)
find_package(KF5PeopleVCard)
set_package_properties(KF5PeopleVCard PROPERTIES
PURPOSE "Read vcards from the file system"
URL "https://phabricator.kde.org/source/kpeoplevcard/"
TYPE RUNTIME
)
if(BUILD_TESTING)
add_subdirectory(tests)
endif()
add_subdirectory(smsapp)
endif()
if(NOT WIN32)
add_subdirectory(kio)
add_subdirectory(plasmoid)
endif()
if(KF5DocTools_FOUND)
add_subdirectory(doc)
endif()
if(KF5Runner_FOUND)
add_subdirectory(runners)
endif()
if(BUILD_TESTING AND NOT SAILFISHOS)
add_subdirectory(tests)
if(KF5DocTools_FOUND)
add_subdirectory(doc)
endif()
else()
add_subdirectory(sfos)
endif()
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)
This information is provided for Github users who may wonder why issues are disabled.
To file bugs, use the [kde bugtracker](https://bugs.kde.org/describecomponents.cgi?product=kdeconnect).
To request features, join the discussion on the [mailing list](https://mail.kde.org/mailman/listinfo/kdeconnect) or [Telegram channel](https://t.me/joinchat/AOS6gA37orb2dZCLhqbZjg).
Patches should be submitted to [Phabricator](https://phabricator.kde.org). See [here](https://community.kde.org/Infrastructure/Phabricator) for an introduction to Phabricator.
Patches should be submitted to [KDE Connect's GitLab](https://invent.kde.org/kde/kdeconnect-kde).
A tutorial on how to build KDE Connect using KDevelop can be found [here](https://nicolasfella.wordpress.com/2018/03/30/building-kde-connect/).
......
......@@ -5,4 +5,7 @@
# Thoroughly inspired in kdevplatform_add_plugin
function(kdeconnect_add_plugin)
kcoreaddons_add_plugin(${ARGN} INSTALL_NAMESPACE kdeconnect)
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${ARGV0}_config.qml")
install(FILES "${ARGV0}_config.qml" DESTINATION ${DATA_INSTALL_DIR}/kdeconnect)
endif()
endfunction()
......@@ -56,7 +56,7 @@ NetworkPackets can also have binary data attached that can't be serialized to JS
## Contributing
To contribute patches, use [KDE Connect's Phabricator](https://phabricator.kde.org/project/profile/159/). There you can also find a task list with stuff to do, and links to other relevant resources. It is a good idea to also subscribe to the [KDE Connect mailing list](https://mail.kde.org/mailman/listinfo/kdeconnect). We can also be reached on IRC at #kdeconnect on freenode or on [telegram](https://t.me/joinchat/AOS6gA37orb2dZCLhqbZjg), contributions and feedback are warmly welcomed.
To contribute patches, use [KDE Connect's GitLab](https://invent.kde.org/kde/kdeconnect-kde). There you can also find a task list with stuff to do, and links to other relevant resources. It is a good idea to also subscribe to the [KDE Connect mailing list](https://mail.kde.org/mailman/listinfo/kdeconnect). We can also be reached on IRC at #kdeconnect on freenode or on [telegram](https://t.me/joinchat/AOS6gA37orb2dZCLhqbZjg), contributions and feedback are warmly welcomed.
## License
[GNU GPL v2](https://www.gnu.org/licenses/gpl-2.0.html) and [GNU GPL v3](https://www.gnu.org/licenses/gpl-3.0.html)
......
find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Declarative)
qt5_add_resources(kdeconnect_SRCS resources.qrc)
qt5_add_resources(kcapp_SRCS resources.qrc)
add_executable(kdeconnect-app main.cpp ${kdeconnect_SRCS})
target_link_libraries(kdeconnect-app Qt5::Quick Qt5::Widgets KF5::CoreAddons KF5::I18n)
add_executable(kcapp main.cpp ${kcapp_SRCS})
target_link_libraries(kcapp Qt5::Quick Qt5::Widgets KF5::Declarative KF5::CoreAddons KF5::I18n)
install(TARGETS kcapp ${INSTALL_TARGETS_DEFAULT_ARGS})
install(TARGETS kdeconnect-app ${INSTALL_TARGETS_DEFAULT_ARGS})
install(PROGRAMS org.kde.kdeconnect.app.desktop DESTINATION ${XDG_APPS_INSTALL_DIR})
......@@ -30,7 +30,7 @@
int main(int argc, char* argv[])
{
QApplication app(argc, argv);
KAboutData aboutData(QStringLiteral("kdeconnect.app"), i18n("KDE Connect App"), QStringLiteral("1.0"), i18n("KDE Connect App"), KAboutLicense::GPL, i18n("(c) 2015, Aleix Pol Gonzalez"));
KAboutData aboutData(QStringLiteral("kdeconnect.app"), i18n("KDE Connect"), QStringLiteral("1.0"), i18n("KDE Connect"), KAboutLicense::GPL, i18n("(c) 2015, Aleix Pol Gonzalez"));
aboutData.addAuthor(i18n("Aleix Pol Gonzalez"), i18n("Maintainer"), QStringLiteral("aleixpol@kde.org"));
KAboutData::setApplicationData(aboutData);
......
[Desktop Entry]
Name=KDE Connect Application
Name[ar]=تطبيق كدي المتّصل
Name[ca]=Aplicació KDE Connect
Name[ca@valencia]=Aplicació KDE Connect
Name[cs]=Aplikace KDE Connect
Name[da]=Programmet KDE Connect
Name[de]=KDE-Connect-Anwendung
Name[el]=Εφαρμογή KDE Connect
Name[en_GB]=KDE Connect Application
Name[es]=Aplicación KDE Connect
Name[et]=KDE Connecti rakendus
Name[eu]=KDE Connect aplikazioa
Name[fi]=KDE Connect -sovellus
Name[fr]=Application KDE Connect
Name[gl]=Aplicativo de KDE Connect
Name[he]=היישום KDE Connect
Name[hu]=KDE Connect alkalmazás
Name[id]=Aplikasi KDE Connect
Name[it]=Applicazione KDE Connect
Name[ko]=KDE Connect 프로그램
Name[nl]=KDE Connect-toepassing
Name[nn]=KDE Connect-program
Name[pl]=Program KDE Connect
Name[pt]=Aplicação do KDE Connect
Name[pt_BR]=Aplicativo KDE Connect
Name[ru]=Приложение KDE Connect
Name[sk]=KDE Connect aplikácia
Name[sr]=КДЕ‑конекцијин програм
Name[sr@ijekavian]=КДЕ‑конекцијин програм
Name[sr@ijekavianlatin]=KDE‑konekcijin program
Name[sr@latin]=KDE‑konekcijin program
Name[sv]=Programmet KDE-anslut
Name[tr]=KDE Connect Uygulaması
Name[uk]=Програма KDE Connect
Name[x-test]=xxKDE Connect Applicationxx
Name[zh_CN]=KDE Connect 应用程序
Name[zh_TW]=KDE 連線應用程式
Name=KDE Connect
Name[ar]=كدي المتّصل
Name[ast]=KDE Connect
Name[bg]=KDE Connect
Name[bs]=Konekcija KDE
Name[ca]=KDE Connect
Name[ca@valencia]=KDE Connect
Name[cs]=KDE Connect
Name[da]=KDE Connect
Name[de]=KDE-Connect
Name[el]=KDE Connect
Name[en_GB]=KDE Connect
Name[es]=KDE Connect
Name[et]=KDE Connect
Name[eu]=KDE Connect
Name[fi]=KDE Connect
Name[fr]=KDE Connect
Name[gl]=KDE Connect
Name[he]=KDE Connect
Name[hu]=KDE csatlakozás
Name[id]=KDE Connect
Name[it]=KDE Connect
Name[ko]=KDE Connect
Name[lt]=KDE Connect
Name[nl]=KDE Connect
Name[nn]=KDE Connect
Name[pl]=KDE Connect
Name[pt]=KDE Connect
Name[pt_BR]=KDE Connect
Name[ro]=KDE Connect
Name[ru]=KDE Connect
Name[sk]=KDE Connect
Name[sr]=КДЕ‑конекција
Name[sr@ijekavian]=КДЕ‑конекција
Name[sr@ijekavianlatin]=KDE‑konekcija
Name[sr@latin]=KDE‑konekcija
Name[sv]=KDE-anslut
Name[tr]=KDE Connect
Name[uk]=З’єднання KDE
Name[x-test]=xxKDE Connectxx
Name[zh_CN]=KDE Connect
Name[zh_TW]=KDE 連線
GenericName=Device Synchronization
GenericName[ar]=مزامنة الأجهزة
GenericName[ast]=Sincronización de preseos
GenericName[ca]=Sincronització de dispositius
GenericName[ca@valencia]=Sincronització de dispositius
GenericName[cs]=Synchronizace zařízení
......@@ -73,9 +79,10 @@ GenericName[tr]=Aygıt Eşzamanlaması
GenericName[uk]=Синхронізація із пристроями
GenericName[x-test]=xxDevice Synchronizationxx
GenericName[zh_CN]=设备同步
GenericName[zh_TW]=設備同步
GenericName[zh_TW]=裝置同步
Comment=Make all your devices one
Comment[ar]=اجعل أجهزتك كلّها واحدًا
Comment[ast]=Fai que tolos preseos seyan unu
Comment[ca]=Fa que tots els vostres dispositius siguin un
Comment[ca@valencia]=Fa que tots els vostres dispositius siguen un
Comment[cs]=Sjednoťte svá zařízení
......@@ -94,6 +101,7 @@ Comment[hu]=Egyesítse eszközeit
Comment[id]=Membuat semua perangkatmu menyatu
Comment[it]=Unisce tutti i tuoi dispositivi
Comment[ko]=모든 장치를 하나로 동기화
Comment[lt]=Paverskite visus savo įrenginius vienu
Comment[nl]=Al uw apparaten een maken
Comment[nn]=Slå alle einingane dine saman
Comment[pl]=Uczyń wszystkie swoje urządzenia jednym
......@@ -110,8 +118,8 @@ Comment[tr]=Tüm aygıtlarınızı birleştirin
Comment[uk]=Поєднайте усі ваші пристрої
Comment[x-test]=xxMake all your devices onexx
Comment[zh_CN]=连接您所有设备
Comment[zh_TW]=讓您的設備內容全面同步
Exec=kcapp
Comment[zh_TW]=讓您的裝置內容全面同步
Exec=kdeconnect-app
Icon=kdeconnect
Type=Application
Terminal=false
......
......@@ -72,6 +72,16 @@ Kirigami.Page
onTriggered: {
deviceView.currentDevice.pluginCall("ping", "sendPing");
}
},
Kirigami.Action {
iconName: "settings-configure"
text: i18n("Plugin Settings")
onTriggered: {
pageStack.push(
deviceComp,
{device: currentDevice.id()}
);
}
}
]
......@@ -82,6 +92,7 @@ Kirigami.Page
delegate: Kirigami.BasicListItem {
label: name
icon: iconName
highlighted: false
iconColor: "transparent"
visible: loaded
onClicked: onClick()
......@@ -173,7 +184,7 @@ Kirigami.Page
Button {
text: i18n("Reject")
icon.name:"dialog-cancel"
icon.name:"dialog-cancel"
onClicked: deviceView.currentDevice.rejectPairing()
}
}
......@@ -193,6 +204,11 @@ Kirigami.Page
}
}
Component {
id: deviceComp
PluginSettings {}
}
FileDialog {
id: fileDialog
title: i18n("Please choose a file")
......
......@@ -68,6 +68,7 @@ Kirigami.ScrollablePage
icon: iconName
iconColor: "transparent"
label: display + "\n" + toolTip
highlighted: false
onClicked: {
pageStack.push(
deviceComp,
......
import QtQuick 2.2
import QtQuick.Controls 2.2
Loader {
property var plugin
property var lastPosition: plugin.position
property date lastPositionTime: new Date()
property bool updatePositionSlider: true
sourceComponent: plugin.canSeek ? seekBar : progressBar
onLastPositionChanged: {
lastPositionTime = new Date();
}
Component {
id: seekBar
Slider {
from: 0
to: plugin.length
onPressedChanged: {
if (pressed) {
updatePositionSlider = false
} else {
updatePositionSlider = true
plugin.position = value
}
}
}
}
Component {
id: progressBar
ProgressBar {
from: 0
to: plugin.length
}
}
Timer {
id: positionUpdateTimer
interval: 1000
repeat: true
running: updatePositionSlider && plugin.isPlaying
onTriggered: item.value = lastPosition + (new Date().getTime() - lastPositionTime.getTime())
}
Connections {
target: plugin
onNowPlayingChanged: {
item.value = lastPosition
}
}
}
/*
* Copyright 2019 Nicolas Fella <nicolas.fella@gmx.de>
*
* 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) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* 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 <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.2
import QtQuick.Controls 2.2
import org.kde.kirigami 2.0 as Kirigami
Kirigami.Page
{
id: root
property string configFile
property string device
actions.main: loader.item.action
Loader {
anchors.fill: parent
id: loader
Component.onCompleted: {
setSource(configFile, {
device: root.device
})
}
}
}
/*
* Copyright 2019 Nicolas Fella <nicolas.fella@gmx.de>
*
* 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) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* 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 <http://www.gnu.org/licenses/>.
*/
import QtQuick 2.2
import QtQuick.Controls 2.2
import QtQuick.Layouts 1.1
import org.kde.kirigami 2.0 as Kirigami
import org.kde.kdeconnect 1.0
Kirigami.ScrollablePage
{
id: root
title: i18n("Plugin Settings")
property string device
ListView {
id: sinkList
Component {
id: pluginInfo
PluginInfoPage {}
}
anchors.fill: parent
model: PluginModel {
deviceId: device
}
delegate: Kirigami.SwipeListItem {
width: parent.width
enabled: true
supportsMouseEvents: false
CheckBox {
checked: isChecked
text: name
onClicked: {
isChecked = checked
}
}
actions: [
Kirigami.Action {
icon.name: "settings-configure"
visible: configSource != ""
onTriggered: {
pageStack.push(pluginInfo, {
title: name,
configFile: configSource,
device: root.device
})
}
}
]
}
}
}
......@@ -31,76 +31,62 @@ Kirigami.ApplicationWindow
width: 900
height: 500
Component {
id: findDevicesComp
FindDevicesPage {}
}
Component {
id: deviceComp
DevicePage {}
}
Kirigami.Action {
id: findDevicesAction
text: i18n ("Find devices...")
text: i18n("Find devices...")
iconName: "list-add"
checked: pageStack.currentItem && pageStack.currentItem.objectName == "FindDevices"
onTriggered: {
root.pageStack.clear()
root.pageStack.push(findDevicesComp);
root.pageStack.push(Qt.resolvedUrl("FindDevicesPage.qml"));
}
}
globalDrawer: Kirigami.GlobalDrawer {
id: drawer
title: i18n("KDE Connect")
titleIcon: "kdeconnect"
// bannerImageSource: "/home/apol/devel/kde5/share/wallpapers/Next/contents/images/1024x768.png"
modal: !root.wideScreen
handleVisible: !root.wideScreen
topContent: [
RowLayout {
DBusProperty {
id: announcedNameProperty
object: DaemonDbusInterface
read: "announcedName"
defaultValue: ""
}
topContent: RowLayout {
width: parent.width
DBusProperty {
id: announcedNameProperty
object: DaemonDbusInterface
read: "announcedName"
defaultValue: ""
}
TextField {
id: nameField
visible: false
Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.smallSpacing
text: announcedNameProperty.value
onAccepted: {
DaemonDbusInterface.setAnnouncedName(text)
text = Qt.binding(function() {return announcedNameProperty.value})
}
TextField {
id: nameField
visible: false
Layout.fillWidth: true
Layout.leftMargin: Kirigami.Units.smallSpacing
text: announcedNameProperty.value
onAccepted: {
DaemonDbusInterface.setAnnouncedName(text)
text = Qt.binding(function() {return announcedNameProperty.value})
}
}
Label {
text: announcedNameProperty.value
visible: !nameField.visible
Layout.fillWidth: true
font.pointSize: 18
Layout.leftMargin: Kirigami.Units.smallSpacing
}
Label {
text: announcedNameProperty.value
visible: !nameField.visible
Layout.fillWidth: true
font.pointSize: 18
Layout.leftMargin: Kirigami.Units.smallSpacing
}
Button {
icon.name: nameField.visible ? "dialog-ok-apply" : "entry-edit"
onClicked: {
nameField.visible = !nameField.visible
nameField.accepted()
}
Button {
icon.name: nameField.visible ? "dialog-ok-apply" : "entry-edit"
onClicked: {
nameField.visible = !nameField.visible
nameField.accepted()
}
}
]
}
property var objects: [findDevicesAction]
Instantiator {
model: DevicesSortProxyModel {
......@@ -115,7 +101,7 @@ Kirigami.ApplicationWindow
onTriggered: {
root.pageStack.clear()
root.pageStack.push(
deviceComp,
Qt.resolvedUrl("DevicePage.qml"),
{currentDevice: device}
);
}
......@@ -140,5 +126,5 @@ Kirigami.ApplicationWindow
id: contextDrawer
}
pageStack.initialPage: findDevicesComp
pageStack.initialPage: Qt.resolvedUrl("FindDevicesPage.qml")
}
......@@ -28,17 +28,10 @@ Kirigami.Page
id: root
property QtObject pluginInterface
property bool muted: false
property bool updatePositionSlider: true
property int volumeUnmuted
property var volume: pluginInterface.volume
property var lastPosition: pluginInterface.position
property date lastPositionTime: new Date()
title: i18n("Multimedia Controls")
onLastPositionChanged: {
lastPositionTime = new Date();
}
onVolumeChanged: {
if (muted && volume != 0) {
toggleMute()
......@@ -78,11 +71,6 @@ Kirigami.Page
}
}
Connections {
target: root.pluginInterface
onNowPlayingChanged: positionSlider.value = lastPosition
}
Label {
id: noPlayersText
text: i18n("No players available")
......@@ -158,29 +146,15 @@ Kirigami.Page
RowLayout {
Layout.fillWidth: true
Label {
text: msToTime(new Date(positionSlider.value), new Date(root.pluginInterface.length))
text: msToTime(new Date(positionIndicator.item.value), new Date(root.pluginInterface.length))
}
Slider {
id: positionSlider
to: root.pluginInterface.length
Layout.fillWidth: true
Timer {
id: positionUpdateTimer
interval: 1000
repeat: true
running: updatePositionSlider && root.pluginInterface.isPlaying
onTriggered: positionSlider.value = lastPosition + (new Date().getTime() - lastPositionTime.getTime())
}
onPressedChanged: {
if (pressed) {
updatePositionSlider = false
} else {
updatePositionSlider = true
root.pluginInterface.position = value
}
}
MprisSlider {
id: positionIndicator
plugin: root.pluginInterface
Layout.fillWidth: true
}
Label {
text: msToTime(new Date(root.pluginInterface.length), new Date(root.pluginInterface.length))
}
......
......@@ -10,5 +10,8 @@
<file>qml/FindDevicesPage.qml</file>
<file>qml/runcommand.qml</file>
<file>qml/volume.qml</file>
<file>qml/MprisSlider.qml</file>
<file>qml/PluginSettings.qml</file>
<file>qml/PluginInfoPage.qml</file>
</qresource>
</RCC>
......@@ -7,6 +7,7 @@ target_include_directories(kdeconnect-cli PUBLIC ${CMAKE_BINARY_DIR})
target_link_libraries(kdeconnect-cli
kdeconnectinterfaces
kdeconnectcore
KF5::CoreAddons
KF5::I18n
)
......
This diff is collapsed.
#compdef kdeconnect-cli
_kdeconnect_device-ids() {
_values "KDE Connect device id" "${(f)$(kdeconnect-cli --shell-device-autocompletion=zsh 2>/dev/null)}"
local devices=''
devices="$(kdeconnect-cli --shell-device-autocompletion=zsh 2>/dev/null)"
if [[ $? -eq 0 ]]; then
_values "KDE Connect device id" "${(f)devices}"
else
_message -r "No KDE Connect devices reachable."
fi
}
_arguments \
'(-l --list-devices -a --list-available)'{-l,--list-devices}'[list all devices]' \
'(-l --list-devices -a --list-available)'{-a,--list-available}'[list available (paired and reachable) devices]' \
'--id-only[make --list-devices or --list-available print only the devices id, to ease scripting]' \
'--refresh[search for devices in the network and re-establish connections]' \
'(--pair --unpair)--pair[request pairing with the specified device]' \
'--ring[find the device by ringing it.]' \
'(--pair --unpair)--unpair[stop pairing to the specified device]' \
'(--ping --ping-msg)--ping[send a ping to the device]' \
'(--ping --ping-msg)--ping-msg[send a ping to the device with the specified message]:message' \
'--share[share a file to the device]:file:_files' \
'--list-notifications[display the notifications on the device]' \
'--lock[lock the specified device]' \
'--send-sms[send an SMS. Requires --destination]:message' \
'--destination[specify phone number to send the SMS to]:phone number' \
'(-d --device -n --name)'{-d,--device}'[specify device ID]:id:_kdeconnect_device-ids' \
'(-d --device -n --name)'{-n,--name}'[specify device name]:name' \
'--encryption-info[get encryption info about the device]' \
'--list-commands[list remote commands and their ids]' \
'--execute-command[execute a remote command]:command id' \
'(-k --send-keys)'{-k,--send-keys}'[send keys to the specified device]' \
"--my-id[display this device's id]" \
"--photo[open the connected device's camera and transfer the photo]" \
#See http://zsh.sourceforge.net/Doc/Release/Completion-System.html#index-_005farguments for autocomplete documentation
#
#The --desktopfile option is not included, since it rarely makes sense to use
#The --shell-device-autocompletion option is not included, since it's not even in the help (and only required for scripts like these)
local blockoperations="(operation sms)"
_arguments -s \
'(-)'{-h,--help}'[display usage information]' \
'(-)'{-v,--version}'[display version information]' \
'(-)--author[show author information and exit]' \
'(-)--license[show license information and exit]' \
'--desktopfile[specify base file name of the desktop entry for this application]:file'
+ '(global)' \
$blockoperations{-l,--list-devices}'[list all devices]' \
$blockoperations{-a,--list-available}'[list available (paired and reachable) devices]' \
$blockoperations'--refresh[search for devices in the network and re-establish connections]' \
{-d=,--device=}'[specify device ID]:id:_kdeconnect_device-ids' \
{-n=,--name=}'[specify device name]:name' \
$blockoperations''{-v,--version}'[display version information]' \
$blockoperations'--author[show author information and exit]' \
$blockoperations'--license[show license information and exit]' \
$blockoperations"--my-id[display this device's id]" \
+ '(operation)' \
$blockoperations'--pair[request pairing with the specified device]' \
$blockoperations'--ring[find the device by ringing it.]' \
$blockoperations'--unpair[stop pairing to the specified device]' \
$blockoperations'--ping[send a ping to the device]' \
$blockoperations'--ping-msg=[send a ping to the device with the specified message]:message' \
$blockoperations'--share=[share a file to the device]:file:_files' \
$blockoperations'--list-notifications[display the notifications on the device]' \
$blockoperations'--lock[lock the specified device]' \
$blockoperations'--encryption-info[get encryption info about the device]' \
$blockoperations'--list-commands[list remote commands and their ids]' \
$blockoperations'--execute-command=[execute a remote command]:command id' \
$blockoperations{-k=,--send-keys=}'[send keyboard input to the specified device]:keyboard input' \
$blockoperations"--photo=[open the connected device's camera and transfer the photo]:file:_files" \
+ 'sms' \
'(operation)--send-sms=[send an SMS]:message:' \
'(operation)--destination=[specify phone number to send the SMS to]:phone number:'
project(KDEConnectCore)
add_definitions(-DTRANSLATION_DOMAIN=\"kdeconnect-core\")
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
)
set(KDECONNECT_PRIVATE_DBUS_ADDR unix:tmpdir=/tmp)
if(WIN32)
set(KDECONNECT_PRIVATE_DBUS_ADDR tcp:host=localhost,port=0)
endif()
set(KDECONNECT_PRIVATE_DBUS_NAME DBusKDEConnectOnly)
configure_file(dbushelper.h.in ${CMAKE_CURRENT_BINARY_DIR}/dbushelper.h)
add_subdirectory(backends/lan)
add_subdirectory(backends/loopback)
......@@ -33,9 +34,11 @@ set(kdeconnectcore_SRCS
dbushelper.cpp
networkpacket.cpp
filetransferjob.cpp
compositefiletransferjob.cpp
daemon.cpp
device.cpp
core_debug.cpp
notificationserverinfo.cpp
)
add_library(kdeconnectcore ${kdeconnectcore_SRCS})
......
......@@ -2,6 +2,9 @@
set(backends_kdeconnect_SRCS
${backends_kdeconnect_SRCS}
backends/bluetooth/multiplexchannel.cpp
backends/bluetooth/multiplexchannelstate.cpp
backends/bluetooth/connectionmultiplexer.cpp
backends/bluetooth/bluetoothlinkprovider.cpp
backends/bluetooth/bluetoothdevicelink.cpp
backends/bluetooth/bluetoothpairinghandler.cpp
......
......@@ -43,11 +43,11 @@ Where the message type can be one of the following.
This message should be the first message send, and never at a later time. Its format is as follows:
```
| MESSAGE_PROTOCOL_VERSION header | Lowest version supported | Highest version supported |
| 19 bytes (UUID ignored) | 2 bytes (Big-Endian) | 2 bytes (Big-Endian) |
| MESSAGE_PROTOCOL_VERSION header | Lowest version supported | Highest version supported | Other data |
| 19 bytes (UUID ignored) | 2 bytes (Big-Endian) | 2 bytes (Big-Endian) | Remaining data bytes |
```
This message should be the first message to send. Use the maximum version supported by both endpoints (if any), or otherwise close the connection.
This message should be the first message to send. Use the maximum version supported by both endpoints (if any), or otherwise close the connection. The other data field is not used (and should be empty for protocol version 1), but it implies that message lengths of more than 4 need to be supported for future compatability.
Currently, no client will send this message with a version other than 1, but you *must* accept and check it, for forward compatibility.
......
......@@ -25,36 +25,39 @@
#include "bluetoothuploadjob.h"
#include "bluetoothdownloadjob.h"
#include "core_debug.h"
#include "connectionmultiplexer.h"
#include "multiplexchannel.h"
BluetoothDeviceLink::BluetoothDeviceLink(const QString& deviceId, LinkProvider* parent, QBluetoothSocket* socket)
BluetoothDeviceLink::BluetoothDeviceLink(const QString& deviceId, LinkProvider* parent, ConnectionMultiplexer* connection, QSharedPointer<MultiplexChannel> socket)
: DeviceLink(deviceId, parent)
, mSocketReader(new DeviceLineReader(socket, this))
, mBluetoothSocket(socket)
, mSocketReader(new DeviceLineReader(socket.data(), this))
, mConnection(connection)
, mChannel(socket)
, mPairingHandler(new BluetoothPairingHandler(this))
{
connect(mSocketReader, SIGNAL(readyRead()),
this, SLOT(dataReceived()));
connect(mSocketReader, &DeviceLineReader::readyRead, this, &BluetoothDeviceLink::dataReceived);
//We take ownership of the socket.
//We take ownership of the connection.
//When the link provider destroys us,
//the socket (and the reader) will be
//destroyed as well
mBluetoothSocket->setParent(this);
connect(mBluetoothSocket, SIGNAL(disconnected()), this, SLOT(deleteLater()));
mConnection->setParent(this);
connect(socket.data(), &MultiplexChannel::aboutToClose, this, &QObject::deleteLater);
}
QString BluetoothDeviceLink::name()
{
return "BluetoothLink"; // Should be same in both android and kde version
return QStringLiteral("BluetoothLink"); // Should be same in both android and kde version
}
bool BluetoothDeviceLink::sendPacket(NetworkPacket& np)
{
if (np.hasPayload()) {
BluetoothUploadJob* uploadJob = new BluetoothUploadJob(np.payload(), mBluetoothSocket->peerAddress(), this);
BluetoothUploadJob* uploadJob = new BluetoothUploadJob(np.payload(), mConnection, this);
np.setPayloadTransferInfo(uploadJob->transferInfo());
uploadJob->start();
}
//TODO: handle too-big packets
int written = mSocketReader->write(np.serialize());
return (written != -1);
}
......@@ -89,8 +92,7 @@ void BluetoothDeviceLink::dataReceived()
}
if (packet.hasPayloadTransferInfo()) {
BluetoothDownloadJob* downloadJob = new BluetoothDownloadJob(mBluetoothSocket->peerAddress(),
packet.payloadTransferInfo(), this);
BluetoothDownloadJob* downloadJob = new BluetoothDownloadJob(mConnection, packet.payloadTransferInfo(), this);
downloadJob->start();
packet.setPayload(downloadJob->payload(), packet.payloadSize());
}
......@@ -98,6 +100,6 @@ void BluetoothDeviceLink::dataReceived()
Q_EMIT receivedPacket(packet);
if (mSocketReader->bytesAvailable() > 0) {
QMetaObject::invokeMethod(this, "dataReceived", Qt::QueuedConnection);
QMetaObject::invokeMethod(this, &BluetoothDeviceLink::dataReceived, Qt::QueuedConnection);
}
}
......@@ -29,13 +29,16 @@
#include "../devicelinereader.h"
#include "bluetoothpairinghandler.h"
class ConnectionMultiplexer;
class MultiplexChannel;
class KDECONNECTCORE_EXPORT BluetoothDeviceLink
: public DeviceLink
{
Q_OBJECT
public:
BluetoothDeviceLink(const QString& deviceId, LinkProvider* parent, QBluetoothSocket* socket);
BluetoothDeviceLink(const QString& deviceId, LinkProvider* parent, ConnectionMultiplexer* connection, QSharedPointer<MultiplexChannel> socket);
virtual QString name() override;
bool sendPacket(NetworkPacket& np) override;
......@@ -50,7 +53,8 @@ private Q_SLOTS:
private:
DeviceLineReader* mSocketReader;
QBluetoothSocket* mBluetoothSocket;
ConnectionMultiplexer* mConnection;
QSharedPointer<MultiplexChannel> mChannel;
BluetoothPairingHandler* mPairingHandler;
void sendMessage(const QString mMessage);
......
......@@ -19,13 +19,14 @@
*/
#include "bluetoothdownloadjob.h"
#include "connectionmultiplexer.h"
#include "multiplexchannel.h"
BluetoothDownloadJob::BluetoothDownloadJob(const QBluetoothAddress& remoteAddress, const QVariantMap& transferInfo, QObject* parent)
BluetoothDownloadJob::BluetoothDownloadJob(ConnectionMultiplexer *connection, const QVariantMap& transferInfo, QObject* parent)
: QObject(parent)
, mRemoteAddress(remoteAddress)
, mTransferUuid(QBluetoothUuid(transferInfo.value("uuid").toString()))
, mSocket(new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol))
{
QBluetoothUuid id{transferInfo.value(QStringLiteral("uuid")).toString()};
mSocket = QSharedPointer<MultiplexChannel>{connection->getChannel(id).release()};
}
QSharedPointer<QIODevice> BluetoothDownloadJob::payload() const
......@@ -35,7 +36,4 @@ QSharedPointer<QIODevice> BluetoothDownloadJob::payload() const
void BluetoothDownloadJob::start()
{
connect(mSocket.data(), &QBluetoothSocket::disconnected, mSocket.data(), &QBluetoothSocket::readyRead);
connect(mSocket.data(), &QBluetoothSocket::disconnected, mSocket.data(), &QBluetoothSocket::readChannelFinished);
mSocket->connectToService(mRemoteAddress, mTransferUuid, QIODevice::ReadOnly);
}
......@@ -29,19 +29,20 @@
#include <QBluetoothUuid>
#include <QBluetoothSocket>
class ConnectionMultiplexer;
class MultiplexChannel;
class BluetoothDownloadJob
: public QObject
{
Q_OBJECT
public:
explicit BluetoothDownloadJob(const QBluetoothAddress& remoteAddress, const QVariantMap& transferInfo, QObject* parent = 0);
explicit BluetoothDownloadJob(ConnectionMultiplexer *connection, const QVariantMap& transferInfo, QObject* parent = 0);
QSharedPointer<QIODevice> payload() const;
void start();
private:
QBluetoothAddress mRemoteAddress;
QBluetoothUuid mTransferUuid;
QSharedPointer<QBluetoothSocket> mSocket;
QSharedPointer<MultiplexChannel> mSocket;
};
#endif // BLUETOOTHDOWNLOADJOB_H
......@@ -35,6 +35,8 @@
#include "../linkprovider.h"
class BluetoothDeviceLink;
class ConnectionMultiplexer;
class MultiplexChannel;
class KDECONNECTCORE_EXPORT BluetoothLinkProvider
: public LinkProvider
......@@ -45,7 +47,7 @@ public:
BluetoothLinkProvider();
virtual ~BluetoothLinkProvider();
QString name() override { return "BluetoothLinkProvider"; }
QString name() override { return QStringLiteral("BluetoothLinkProvider"); }
int priority() override { return PRIORITY_MEDIUM; }
public Q_SLOTS:
......@@ -53,16 +55,17 @@ public Q_SLOTS:
virtual void onStart() override;
virtual void onStop() override;
void connectError();
void serviceDiscoveryFinished();
private Q_SLOTS:
void deviceLinkDestroyed(QObject* destroyedDeviceLink);
void socketDisconnected();
void socketDisconnected(const QBluetoothAddress &peerAddress, MultiplexChannel *socket);
void serverNewConnection();
void serverDataReceived();
void clientConnected();
void clientIdentityReceived();
void serverDataReceived(const QBluetoothAddress &peerAddress, QSharedPointer<MultiplexChannel> socket);
void clientConnected(QPointer<QBluetoothSocket> socket);
void clientIdentityReceived(const QBluetoothAddress &peerAddress, QSharedPointer<MultiplexChannel> socket);
void serviceDiscovered(const QBluetoothServiceInfo &info);
private:
void addLink(BluetoothDeviceLink* deviceLink, const QString& deviceId);
......@@ -76,7 +79,7 @@ private:
QMap<QString, DeviceLink*> mLinks;
QMap<QBluetoothAddress, QBluetoothSocket*> mSockets;
QMap<QBluetoothAddress, ConnectionMultiplexer*> mSockets;
};
......
......@@ -42,7 +42,7 @@ void BluetoothPairingHandler::packetReceived(const NetworkPacket& np)
m_pairingTimeout.stop();
bool wantsPair = np.get<bool>("pair");
bool wantsPair = np.get<bool>(QStringLiteral("pair"));
if (wantsPair) {
......@@ -91,7 +91,7 @@ bool BluetoothPairingHandler::requestPairing()
}
NetworkPacket np(PACKET_TYPE_PAIR);
np.set("pair", true);
np.set(QStringLiteral("pair"), true);
bool success;
success = deviceLink()->sendPacket(np);
if (success) {
......@@ -106,7 +106,7 @@ bool BluetoothPairingHandler::acceptPairing()
qCDebug(KDECONNECT_CORE) << "User accepts pairing";
m_pairingTimeout.stop(); // Just in case it is started
NetworkPacket np(PACKET_TYPE_PAIR);
np.set("pair", true);
np.set(QStringLiteral("pair"), true);
bool success = deviceLink()->sendPacket(np);
if (success) {
setInternalPairStatus(Paired);
......@@ -118,14 +118,14 @@ void BluetoothPairingHandler::rejectPairing()
{
qCDebug(KDECONNECT_CORE) << "User rejects pairing";
NetworkPacket np(PACKET_TYPE_PAIR);
np.set("pair", false);
np.set(QStringLiteral("pair"), false);
deviceLink()->sendPacket(np);
setInternalPairStatus(NotPaired);
}