diff --git a/src/commoncomponents/MaterialToolTip.qml b/src/commoncomponents/MaterialToolTip.qml index 79506ccabc6d31d687179ccc39848f2593ef2fe3..c0e6609f4a013023f8006d3719e2753274f4d431 100644 --- a/src/commoncomponents/MaterialToolTip.qml +++ b/src/commoncomponents/MaterialToolTip.qml @@ -1,57 +1,57 @@ -/* - * Copyright (C) 2021 by Savoir-faire Linux - * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> - * - * 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 3 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 <http://www.gnu.org/licenses/>. - */ - -import QtQuick 2.0 -import QtQuick.Controls 2.15 - -import net.jami.Constants 1.1 - -ToolTip { - id: root - - onVisibleChanged: { - if (visible) - animation.start() - } - - contentItem: Text { - id: label - text: root.text - font: root.font - color: "white" - } - - background: Rectangle { - color: "#c4272727" - radius: 5 - } - - ParallelAnimation { - id: animation - NumberAnimation { - target: background; properties: "opacity" - from: 0; to: 1.0 - duration: JamiTheme.shortFadeDuration - } - NumberAnimation { - target: background; properties: "scale" - from: 0.5; to: 1.0 - duration: JamiTheme.shortFadeDuration * 0.5 - } - } -} +/* + * Copyright (C) 2021 by Savoir-faire Linux + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> + * + * 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 3 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 <http://www.gnu.org/licenses/>. + */ + +import QtQuick 2.0 +import QtQuick.Controls 2.15 + +import net.jami.Constants 1.1 + +ToolTip { + id: root + + onVisibleChanged: { + if (visible) + animation.start() + } + + contentItem: Text { + id: label + text: root.text + font: root.font + color: "white" + } + + background: Rectangle { + color: "#c4272727" + radius: 5 + } + + ParallelAnimation { + id: animation + NumberAnimation { + target: background; properties: "opacity" + from: 0; to: 1.0 + duration: JamiTheme.shortFadeDuration + } + NumberAnimation { + target: background; properties: "scale" + from: 0.5; to: 1.0 + duration: JamiTheme.shortFadeDuration * 0.5 + } + } +} diff --git a/src/commoncomponents/PresenceIndicator.qml b/src/commoncomponents/PresenceIndicator.qml index 73bc4860088e2217acae9941df4f00ef07ace5ba..c798967f7d090ef6b592b6350e4c3412d18f22a0 100644 --- a/src/commoncomponents/PresenceIndicator.qml +++ b/src/commoncomponents/PresenceIndicator.qml @@ -1,48 +1,48 @@ -/* - * Copyright (C) 2020 by Savoir-faire Linux - * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> - * - * 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 3 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 <https://www.gnu.org/licenses/>. - */ - -import QtQuick 2.15 - -import net.jami.Models 1.1 -import net.jami.Constants 1.1 - -// Serves as either account or contact presence indicator. -// TODO: this should be part of an avatar component at some point. -Rectangle { - id: root - - // This is set to REGISTERED for contact presence - // as status is not currently tracked for contact items. - property int status: Account.Status.REGISTERED - property int size: 15 - - width: size - height: size - radius: size * 0.5 - border { - color: JamiTheme.backgroundColor - width: 2 - } - color: { - if (status === Account.Status.REGISTERED) - return JamiTheme.presenceGreen - else if (status === Account.Status.TRYING) - return JamiTheme.unPresenceOrange - return JamiTheme.notificationRed - } -} +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> + * + * 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 3 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 <https://www.gnu.org/licenses/>. + */ + +import QtQuick 2.15 + +import net.jami.Models 1.1 +import net.jami.Constants 1.1 + +// Serves as either account or contact presence indicator. +// TODO: this should be part of an avatar component at some point. +Rectangle { + id: root + + // This is set to REGISTERED for contact presence + // as status is not currently tracked for contact items. + property int status: Account.Status.REGISTERED + property int size: 15 + + width: size + height: size + radius: size * 0.5 + border { + color: JamiTheme.backgroundColor + width: 2 + } + color: { + if (status === Account.Status.REGISTERED) + return JamiTheme.presenceGreen + else if (status === Account.Status.TRYING) + return JamiTheme.unPresenceOrange + return JamiTheme.notificationRed + } +} diff --git a/src/commoncomponents/ResponsiveImage.qml b/src/commoncomponents/ResponsiveImage.qml index efabdd92c5f1c622a570d5613f81926db6dc3f8b..1e00cd52a51917e89e40bef99e220f848e064c0f 100644 --- a/src/commoncomponents/ResponsiveImage.qml +++ b/src/commoncomponents/ResponsiveImage.qml @@ -1,83 +1,83 @@ -/* - * Copyright (C) 2020 by Savoir-faire Linux - * Author: Andreas Tracyk <andreas.traczyk@savoirfairelinux.com> - * - * 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 3 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 <https://www.gnu.org/licenses/>. - */ - -import QtQuick 2.15 -import QtGraphicalEffects 1.15 - -import net.jami.Constants 1.1 -import net.jami.Helpers 1.1 - -Item { - id: root - - property real containerWidth: 30 - property real containerHeight: 30 - - property int padding: 0 - property point offset: Qt.point(0, 0) - - property alias source: image.source - property alias status: image.status - property string color: "transparent" - - property bool isSvg: { - var match = /[^.]+$/.exec(source) - return match !== null && match[0] === 'svg' - } - - anchors.horizontalCenterOffset: offset.x - anchors.verticalCenterOffset: offset.y - - // works out to 24 if containerWidth is 30 - width: Math.trunc(containerWidth * Math.sqrt(2) * 0.5) + 3 - padding - height: Math.trunc(containerHeight * Math.sqrt(2) * 0.5) + 3 - padding - - Connections { - target: ScreenInfo - - function onDevicePixelRatioChanged() { - image.setSourceSize() - } - } - - Image { - id: image - - anchors.fill: root - - fillMode: Image.PreserveAspectFit - smooth: true - antialiasing: true - asynchronous: true - visible: false - - function setSourceSize() { - sourceSize = undefined - if (isSvg) - sourceSize = Qt.size(width, height) - } - - Component.onCompleted: setSourceSize() - } - - ColorOverlay { - anchors.fill: image - source: image - color: root.color - } -} +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Andreas Tracyk <andreas.traczyk@savoirfairelinux.com> + * + * 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 3 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 <https://www.gnu.org/licenses/>. + */ + +import QtQuick 2.15 +import QtGraphicalEffects 1.15 + +import net.jami.Constants 1.1 +import net.jami.Helpers 1.1 + +Item { + id: root + + property real containerWidth: 30 + property real containerHeight: 30 + + property int padding: 0 + property point offset: Qt.point(0, 0) + + property alias source: image.source + property alias status: image.status + property string color: "transparent" + + property bool isSvg: { + var match = /[^.]+$/.exec(source) + return match !== null && match[0] === 'svg' + } + + anchors.horizontalCenterOffset: offset.x + anchors.verticalCenterOffset: offset.y + + // works out to 24 if containerWidth is 30 + width: Math.trunc(containerWidth * Math.sqrt(2) * 0.5) + 3 - padding + height: Math.trunc(containerHeight * Math.sqrt(2) * 0.5) + 3 - padding + + Connections { + target: ScreenInfo + + function onDevicePixelRatioChanged() { + image.setSourceSize() + } + } + + Image { + id: image + + anchors.fill: root + + fillMode: Image.PreserveAspectFit + smooth: true + antialiasing: true + asynchronous: true + visible: false + + function setSourceSize() { + sourceSize = undefined + if (isSvg) + sourceSize = Qt.size(width, height) + } + + Component.onCompleted: setSourceSize() + } + + ColorOverlay { + anchors.fill: image + source: image + color: root.color + } +} diff --git a/src/currentaccount.cpp b/src/currentaccount.cpp index 1d6459607d7542f37df0a3fcc921597844145b20..ef0fb46c0867a580d7e4330f541ed9c9dadf466f 100644 --- a/src/currentaccount.cpp +++ b/src/currentaccount.cpp @@ -1,65 +1,65 @@ -/* - * Copyright (C) 2021 by Savoir-faire Linux - * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> - * - * 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 3 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 <https://www.gnu.org/licenses/>. - */ - -#include "currentaccount.h" - -CurrentAccount::CurrentAccount(LRCInstance* lrcInstance, QObject* parent) - : QObject(parent) - , lrcInstance_(lrcInstance) -{ - connect(&lrcInstance_->accountModel(), - &NewAccountModel::accountStatusChanged, - this, - &CurrentAccount::onAccountUpdated); - - connect(&lrcInstance_->accountModel(), - &NewAccountModel::profileUpdated, - this, - &CurrentAccount::onAccountUpdated); - - connect(lrcInstance_, &LRCInstance::currentAccountIdChanged, [this] { updateData(); }); - updateData(); -} - -void -CurrentAccount::onAccountUpdated(const QString& id) -{ - // filter for our currently set id - if (id_ != id) - return; - updateData(); -} - -void -CurrentAccount::updateData() -{ - set_id(lrcInstance_->get_currentAccountId()); - try { - const auto& accInfo = lrcInstance_->getAccountInfo(id_); - set_uri(accInfo.profileInfo.uri); - set_registeredName(accInfo.registeredName); - set_alias(accInfo.profileInfo.alias); - set_bestId(lrcInstance_->accountModel().bestIdForAccount(id_)); - set_bestName(lrcInstance_->accountModel().bestNameForAccount(id_)); - set_hasAvatarSet(!accInfo.profileInfo.avatar.isEmpty()); - set_status(accInfo.status); - set_type(accInfo.profileInfo.type); - } catch (...) { - qWarning() << "Can't update current account data for" << id_; - } -} +/* + * Copyright (C) 2021 by Savoir-faire Linux + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> + * + * 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 3 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 <https://www.gnu.org/licenses/>. + */ + +#include "currentaccount.h" + +CurrentAccount::CurrentAccount(LRCInstance* lrcInstance, QObject* parent) + : QObject(parent) + , lrcInstance_(lrcInstance) +{ + connect(&lrcInstance_->accountModel(), + &NewAccountModel::accountStatusChanged, + this, + &CurrentAccount::onAccountUpdated); + + connect(&lrcInstance_->accountModel(), + &NewAccountModel::profileUpdated, + this, + &CurrentAccount::onAccountUpdated); + + connect(lrcInstance_, &LRCInstance::currentAccountIdChanged, [this] { updateData(); }); + updateData(); +} + +void +CurrentAccount::onAccountUpdated(const QString& id) +{ + // filter for our currently set id + if (id_ != id) + return; + updateData(); +} + +void +CurrentAccount::updateData() +{ + set_id(lrcInstance_->get_currentAccountId()); + try { + const auto& accInfo = lrcInstance_->getAccountInfo(id_); + set_uri(accInfo.profileInfo.uri); + set_registeredName(accInfo.registeredName); + set_alias(accInfo.profileInfo.alias); + set_bestId(lrcInstance_->accountModel().bestIdForAccount(id_)); + set_bestName(lrcInstance_->accountModel().bestNameForAccount(id_)); + set_hasAvatarSet(!accInfo.profileInfo.avatar.isEmpty()); + set_status(accInfo.status); + set_type(accInfo.profileInfo.type); + } catch (...) { + qWarning() << "Can't update current account data for" << id_; + } +} diff --git a/src/currentaccount.h b/src/currentaccount.h index a20fce987f833277f1f01ec1fb8a99b65f0a6a0b..30fbecbf24b87a932255888e230935c859f0f25b 100644 --- a/src/currentaccount.h +++ b/src/currentaccount.h @@ -1,49 +1,49 @@ -/* - * Copyright (C) 2021 by Savoir-faire Linux - * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> - * - * 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 3 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 <https://www.gnu.org/licenses/>. - */ - -#pragma once - -#include "lrcinstance.h" - -#include <QObject> -#include <QString> - -class CurrentAccount final : public QObject -{ - Q_OBJECT - QML_RO_PROPERTY(QString, id) - QML_RO_PROPERTY(QString, uri) - QML_RO_PROPERTY(QString, registeredName) - QML_RO_PROPERTY(QString, alias) - QML_RO_PROPERTY(QString, bestId) - QML_RO_PROPERTY(QString, bestName) - QML_RO_PROPERTY(bool, hasAvatarSet) - QML_RO_PROPERTY(lrc::api::account::Status, status) - QML_RO_PROPERTY(lrc::api::profile::Type, type) - -public: - explicit CurrentAccount(LRCInstance* lrcInstance, QObject* parent = nullptr); - ~CurrentAccount() = default; - -private Q_SLOTS: - void updateData(); - void onAccountUpdated(const QString& id); - -private: - LRCInstance* lrcInstance_; -}; +/* + * Copyright (C) 2021 by Savoir-faire Linux + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> + * + * 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 3 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 <https://www.gnu.org/licenses/>. + */ + +#pragma once + +#include "lrcinstance.h" + +#include <QObject> +#include <QString> + +class CurrentAccount final : public QObject +{ + Q_OBJECT + QML_RO_PROPERTY(QString, id) + QML_RO_PROPERTY(QString, uri) + QML_RO_PROPERTY(QString, registeredName) + QML_RO_PROPERTY(QString, alias) + QML_RO_PROPERTY(QString, bestId) + QML_RO_PROPERTY(QString, bestName) + QML_RO_PROPERTY(bool, hasAvatarSet) + QML_RO_PROPERTY(lrc::api::account::Status, status) + QML_RO_PROPERTY(lrc::api::profile::Type, type) + +public: + explicit CurrentAccount(LRCInstance* lrcInstance, QObject* parent = nullptr); + ~CurrentAccount() = default; + +private Q_SLOTS: + void updateData(); + void onAccountUpdated(const QString& id); + +private: + LRCInstance* lrcInstance_; +}; diff --git a/src/mainview/components/ConversationAvatar.qml b/src/mainview/components/ConversationAvatar.qml index 28322fa76a30394c4b11aef32384b61d9aab9b36..1a42e1165679d9d999abdcae2b8565a0c8b0f81a 100644 --- a/src/mainview/components/ConversationAvatar.qml +++ b/src/mainview/components/ConversationAvatar.qml @@ -1,49 +1,49 @@ -/* - * Copyright (C) 2021 by Savoir-faire Linux - * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> - * - * 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 3 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 <https://www.gnu.org/licenses/>. - */ - -import QtQuick 2.15 -import QtQuick.Controls 2.15 - -import net.jami.Adapters 1.1 - -import "../../commoncomponents" - -Item { - id: root - - property alias imageId: avatar.imageId - property alias showPresenceIndicator: avatar.showPresenceIndicator - property alias animationMode: animation.mode - - SpinningAnimation { - id: animation - - anchors.fill: root - } - - Avatar { - id: avatar - - anchors.fill: root - anchors.margins: animation.mode === SpinningAnimation.Mode.Disabled ? - 0 : - animation.spinningAnimationWidth - - mode: Avatar.Mode.Conversation - } -} +/* + * Copyright (C) 2021 by Savoir-faire Linux + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> + * + * 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 3 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 <https://www.gnu.org/licenses/>. + */ + +import QtQuick 2.15 +import QtQuick.Controls 2.15 + +import net.jami.Adapters 1.1 + +import "../../commoncomponents" + +Item { + id: root + + property alias imageId: avatar.imageId + property alias showPresenceIndicator: avatar.showPresenceIndicator + property alias animationMode: animation.mode + + SpinningAnimation { + id: animation + + anchors.fill: root + } + + Avatar { + id: avatar + + anchors.fill: root + anchors.margins: animation.mode === SpinningAnimation.Mode.Disabled ? + 0 : + animation.spinningAnimationWidth + + mode: Avatar.Mode.Conversation + } +} diff --git a/src/mainview/components/FilterTabButton.qml b/src/mainview/components/FilterTabButton.qml index d7a08bf5103531bb7f2856616c4a1ea9d6bc0c53..fa3271b9e7678b35d6d37fca303e35e320e691e5 100644 --- a/src/mainview/components/FilterTabButton.qml +++ b/src/mainview/components/FilterTabButton.qml @@ -1,85 +1,85 @@ -/* - * Copyright (C) 2020-2021 by Savoir-faire Linux - * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> - * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> - * - * 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 3 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 <https://www.gnu.org/licenses/>. - */ - -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 - -import net.jami.Constants 1.1 - -import "../../commoncomponents" - -TabButton { - id: root - - property var tabBar: undefined - property alias labelText: label.text - property alias acceleratorSequence: accelerator.sequence - property alias badgeCount: badge.count - signal selected - - hoverEnabled: true - onClicked: selected() - - Rectangle { - id: rect - - width: tabBar.width / 2 + 1 - height: tabBar.height - color: root.hovered ? - JamiTheme.hoverColor : - JamiTheme.backgroundColor - - RowLayout { - anchors.horizontalCenter: rect.horizontalCenter - anchors.verticalCenter: rect.verticalCenter - - Text { - id: label - - Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter - Layout.bottomMargin: 1 - - font.pointSize: JamiTheme.filterItemFontSize - color: JamiTheme.textColor - opacity: root.down ? 1.0 : 0.5 - } - - BadgeNotifier { - id: badge - size: 20 - Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter - } - } - } - - Rectangle { - width: rect.width - anchors.bottom: rect.bottom - height: 2 - color: root.down ? JamiTheme.textColor : "transparent" - } - - Shortcut { - id: accelerator - context: Qt.ApplicationShortcut - enabled: rect.visible - onActivated: selected() - } -} +/* + * Copyright (C) 2020-2021 by Savoir-faire Linux + * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> + * + * 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 3 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 <https://www.gnu.org/licenses/>. + */ + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import net.jami.Constants 1.1 + +import "../../commoncomponents" + +TabButton { + id: root + + property var tabBar: undefined + property alias labelText: label.text + property alias acceleratorSequence: accelerator.sequence + property alias badgeCount: badge.count + signal selected + + hoverEnabled: true + onClicked: selected() + + Rectangle { + id: rect + + width: tabBar.width / 2 + 1 + height: tabBar.height + color: root.hovered ? + JamiTheme.hoverColor : + JamiTheme.backgroundColor + + RowLayout { + anchors.horizontalCenter: rect.horizontalCenter + anchors.verticalCenter: rect.verticalCenter + + Text { + id: label + + Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter + Layout.bottomMargin: 1 + + font.pointSize: JamiTheme.filterItemFontSize + color: JamiTheme.textColor + opacity: root.down ? 1.0 : 0.5 + } + + BadgeNotifier { + id: badge + size: 20 + Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter + } + } + } + + Rectangle { + width: rect.width + anchors.bottom: rect.bottom + height: 2 + color: root.down ? JamiTheme.textColor : "transparent" + } + + Shortcut { + id: accelerator + context: Qt.ApplicationShortcut + enabled: rect.visible + onActivated: selected() + } +} diff --git a/src/mainview/components/MainOverlay.qml b/src/mainview/components/MainOverlay.qml index c05d1c45b0b46849f899413e75d6c35e684a7855..3ea664357794e57a10fa4e8527b6142a1727e5de 100644 --- a/src/mainview/components/MainOverlay.qml +++ b/src/mainview/components/MainOverlay.qml @@ -1,249 +1,249 @@ -/* - * Copyright (C) 2020-2021 by Savoir-faire Linux - * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> - * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> - * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> - * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> - * - * 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 3 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 <https://www.gnu.org/licenses/>. - */ - -import QtQuick 2.15 -import QtQuick.Layouts 1.15 - -import net.jami.Models 1.1 -import net.jami.Adapters 1.1 -import net.jami.Constants 1.1 - -import "../../commoncomponents" - -Item { - id: root - - property string timeText: "00:00" - property string remoteRecordingLabel: "" - - property string bestName: "" - - property alias recordingVisible: recordingRect.visible - property alias callActionBar: __callActionBar - - property bool frozen: callActionBar.overflowOpen || - callActionBar.hovered || - callActionBar.subMenuOpen || - participantCallInStatusView.visible - - opacity: 0 - - // (un)subscribe to an app-wide mouse move event trap filtered - // for the overlay's geometry - onVisibleChanged: visible ? CallOverlayModel.registerFilter( - appWindow, - this) : CallOverlayModel.unregisterFilter( - appWindow, this) - - Connections { - target: CallOverlayModel - - function onMouseMoved(item) { - if (item === root) { - root.opacity = 1 - fadeOutTimer.restart() - } - } - } - - // control overlay fade out. - Timer { - id: fadeOutTimer - interval: JamiTheme.overlayFadeDelay - onTriggered: { - if (frozen) - return - root.opacity = 0 - resetLabelsTimer.restart() - } - } - - // Timer to reset recording label and call duration time - Timer { - id: resetLabelsTimer - interval: 1000 - running: root.visible - repeat: true - onTriggered: { - root.timeText = CallAdapter.getCallDurationTime( - LRCInstance.currentAccountId, - LRCInstance.selectedConvUid) - if (root.opacity === 0 && !callViewContextMenu.peerIsRecording) - root.remoteRecordingLabel = "" - } - } - - Item { - id: overlayUpperPartRect - - anchors.top: parent.top - - width: parent.width - height: 50 - - RowLayout { - anchors.fill: parent - - spacing: 0 - - Text { - id: jamiBestNameText - - Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft - Layout.preferredWidth: overlayUpperPartRect.width / 2 - Layout.preferredHeight: 50 - - leftPadding: 16 - - horizontalAlignment: Text.AlignLeft - verticalAlignment: Text.AlignVCenter - - font.pointSize: JamiTheme.textFontSize - text: { - if (!root.isAudioOnly) { - if (remoteRecordingLabel === "") { - return root.bestName - } else { - return remoteRecordingLabel - } - } - return "" - } - color: JamiTheme.whiteColor - elide: Qt.ElideRight - } - - PushButton { - id: mosaicButton - - Layout.alignment: Qt.AlignVCenter | Qt.AlignRight - Layout.preferredWidth: JamiTheme.mosaicButtonPreferredWidth - Layout.preferredHeight: 30 - Layout.rightMargin: 5 - - visible: isConferenceCall && !isGrid - - preferredMargin: JamiTheme.mosaicButtonPreferredMargin - radius: JamiTheme.mosaicButtonRadius - opacity: JamiTheme.mosaicButtonOpacity - - buttonText: JamiStrings.mosaic - buttonTextColor: JamiTheme.whiteColor - buttonTextHeight: JamiTheme.mosaicButtonTextPreferredHeight - buttonTextFont.weight: Font.DemiBold - buttonTextFont.pointSize: JamiTheme.mosaicButtonTextPointSize - textHAlign: Text.AlignLeft - - imageColor: JamiTheme.whiteColor - imageContainerHeight: 20 - imageContainerWidth: 20 - source: JamiResources.mosaic_black_24dp_svg - - normalColor: JamiTheme.mosaicButtonNormalColor - onButtonTextWidthChanged: { - if (buttonTextWidth > JamiTheme.mosaicButtonTextPreferredWidth) { - if (mosaicButton.Layout.preferredWidth + buttonTextWidth - - JamiTheme.mosaicButtonTextPreferredWidth - > JamiTheme.mosaicButtonMaxWidth) { - mosaicButton.Layout.preferredWidth = JamiTheme.mosaicButtonMaxWidth - buttonTextEnableElide = true - } else - mosaicButton.Layout.preferredWidth += buttonTextWidth - - JamiTheme.mosaicButtonTextPreferredWidth - } - } - - onClicked: CallAdapter.showGridConferenceLayout() - } - - Text { - id: callTimerText - - Layout.alignment: Qt.AlignVCenter | Qt.AlignRight - Layout.preferredHeight: 48 - Layout.rightMargin: recordingRect.visible ? 0 : JamiTheme.preferredMarginSize - - font.pointSize: JamiTheme.textFontSize - horizontalAlignment: Text.AlignRight - verticalAlignment: Text.AlignVCenter - - text: timeText - color: JamiTheme.whiteColor - elide: Qt.ElideRight - } - - Rectangle { - id: recordingRect - - Layout.alignment: Qt.AlignVCenter | Qt.AlignRight - Layout.rightMargin: JamiTheme.preferredMarginSize - - height: 16 - width: 16 - - radius: height / 2 - color: JamiTheme.recordIconColor - - SequentialAnimation on color { - loops: Animation.Infinite - running: true - ColorAnimation { - from: JamiTheme.recordIconColor - to: "transparent" - duration: JamiTheme.recordBlinkDuration - } - ColorAnimation { - from: "transparent" - to: JamiTheme.recordIconColor - duration: JamiTheme.recordBlinkDuration - } - } - } - } - } - - ParticipantCallInStatusView { - id: participantCallInStatusView - - anchors.right: root.right - anchors.rightMargin: 10 - anchors.bottom: __callActionBar.top - anchors.bottomMargin: 20 - } - - CallActionBar { - id: __callActionBar - - anchors { - bottom: parent.bottom - bottomMargin: 26 - } - - width: parent.width - height: 55 - } - - Behavior on opacity { - NumberAnimation { - duration: JamiTheme.overlayFadeDuration - } - } -} +/* + * Copyright (C) 2020-2021 by Savoir-faire Linux + * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> + * Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com> + * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> + * + * 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 3 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 <https://www.gnu.org/licenses/>. + */ + +import QtQuick 2.15 +import QtQuick.Layouts 1.15 + +import net.jami.Models 1.1 +import net.jami.Adapters 1.1 +import net.jami.Constants 1.1 + +import "../../commoncomponents" + +Item { + id: root + + property string timeText: "00:00" + property string remoteRecordingLabel: "" + + property string bestName: "" + + property alias recordingVisible: recordingRect.visible + property alias callActionBar: __callActionBar + + property bool frozen: callActionBar.overflowOpen || + callActionBar.hovered || + callActionBar.subMenuOpen || + participantCallInStatusView.visible + + opacity: 0 + + // (un)subscribe to an app-wide mouse move event trap filtered + // for the overlay's geometry + onVisibleChanged: visible ? CallOverlayModel.registerFilter( + appWindow, + this) : CallOverlayModel.unregisterFilter( + appWindow, this) + + Connections { + target: CallOverlayModel + + function onMouseMoved(item) { + if (item === root) { + root.opacity = 1 + fadeOutTimer.restart() + } + } + } + + // control overlay fade out. + Timer { + id: fadeOutTimer + interval: JamiTheme.overlayFadeDelay + onTriggered: { + if (frozen) + return + root.opacity = 0 + resetLabelsTimer.restart() + } + } + + // Timer to reset recording label and call duration time + Timer { + id: resetLabelsTimer + interval: 1000 + running: root.visible + repeat: true + onTriggered: { + root.timeText = CallAdapter.getCallDurationTime( + LRCInstance.currentAccountId, + LRCInstance.selectedConvUid) + if (root.opacity === 0 && !callViewContextMenu.peerIsRecording) + root.remoteRecordingLabel = "" + } + } + + Item { + id: overlayUpperPartRect + + anchors.top: parent.top + + width: parent.width + height: 50 + + RowLayout { + anchors.fill: parent + + spacing: 0 + + Text { + id: jamiBestNameText + + Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft + Layout.preferredWidth: overlayUpperPartRect.width / 2 + Layout.preferredHeight: 50 + + leftPadding: 16 + + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + + font.pointSize: JamiTheme.textFontSize + text: { + if (!root.isAudioOnly) { + if (remoteRecordingLabel === "") { + return root.bestName + } else { + return remoteRecordingLabel + } + } + return "" + } + color: JamiTheme.whiteColor + elide: Qt.ElideRight + } + + PushButton { + id: mosaicButton + + Layout.alignment: Qt.AlignVCenter | Qt.AlignRight + Layout.preferredWidth: JamiTheme.mosaicButtonPreferredWidth + Layout.preferredHeight: 30 + Layout.rightMargin: 5 + + visible: isConferenceCall && !isGrid + + preferredMargin: JamiTheme.mosaicButtonPreferredMargin + radius: JamiTheme.mosaicButtonRadius + opacity: JamiTheme.mosaicButtonOpacity + + buttonText: JamiStrings.mosaic + buttonTextColor: JamiTheme.whiteColor + buttonTextHeight: JamiTheme.mosaicButtonTextPreferredHeight + buttonTextFont.weight: Font.DemiBold + buttonTextFont.pointSize: JamiTheme.mosaicButtonTextPointSize + textHAlign: Text.AlignLeft + + imageColor: JamiTheme.whiteColor + imageContainerHeight: 20 + imageContainerWidth: 20 + source: JamiResources.mosaic_black_24dp_svg + + normalColor: JamiTheme.mosaicButtonNormalColor + onButtonTextWidthChanged: { + if (buttonTextWidth > JamiTheme.mosaicButtonTextPreferredWidth) { + if (mosaicButton.Layout.preferredWidth + buttonTextWidth + - JamiTheme.mosaicButtonTextPreferredWidth + > JamiTheme.mosaicButtonMaxWidth) { + mosaicButton.Layout.preferredWidth = JamiTheme.mosaicButtonMaxWidth + buttonTextEnableElide = true + } else + mosaicButton.Layout.preferredWidth += buttonTextWidth + - JamiTheme.mosaicButtonTextPreferredWidth + } + } + + onClicked: CallAdapter.showGridConferenceLayout() + } + + Text { + id: callTimerText + + Layout.alignment: Qt.AlignVCenter | Qt.AlignRight + Layout.preferredHeight: 48 + Layout.rightMargin: recordingRect.visible ? 0 : JamiTheme.preferredMarginSize + + font.pointSize: JamiTheme.textFontSize + horizontalAlignment: Text.AlignRight + verticalAlignment: Text.AlignVCenter + + text: timeText + color: JamiTheme.whiteColor + elide: Qt.ElideRight + } + + Rectangle { + id: recordingRect + + Layout.alignment: Qt.AlignVCenter | Qt.AlignRight + Layout.rightMargin: JamiTheme.preferredMarginSize + + height: 16 + width: 16 + + radius: height / 2 + color: JamiTheme.recordIconColor + + SequentialAnimation on color { + loops: Animation.Infinite + running: true + ColorAnimation { + from: JamiTheme.recordIconColor + to: "transparent" + duration: JamiTheme.recordBlinkDuration + } + ColorAnimation { + from: "transparent" + to: JamiTheme.recordIconColor + duration: JamiTheme.recordBlinkDuration + } + } + } + } + } + + ParticipantCallInStatusView { + id: participantCallInStatusView + + anchors.right: root.right + anchors.rightMargin: 10 + anchors.bottom: __callActionBar.top + anchors.bottomMargin: 20 + } + + CallActionBar { + id: __callActionBar + + anchors { + bottom: parent.bottom + bottomMargin: 26 + } + + width: parent.width + height: 55 + } + + Behavior on opacity { + NumberAnimation { + duration: JamiTheme.overlayFadeDuration + } + } +} diff --git a/src/mainview/components/ParticipantControlLayout.qml b/src/mainview/components/ParticipantControlLayout.qml index 61ab031cf7a871cfb108599c7245ee0436d53763..e88061257d5caf90434d99932a201c5336bdb809 100644 --- a/src/mainview/components/ParticipantControlLayout.qml +++ b/src/mainview/components/ParticipantControlLayout.qml @@ -1,98 +1,98 @@ -/* - * Copyright (C) 2020 by Savoir-faire Linux - * Author: Albert Babà <albert.babi@savoirfairelinux.com> - * - * 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 3 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 <https://www.gnu.org/licenses/>. - */ - -import QtQuick.Layouts 1.15 - -import net.jami.Adapters 1.1 -import net.jami.Constants 1.1 - -import "../../commoncomponents" - -RowLayout { - id: buttonsRect - - property int visibleButtons: toggleModerator.visible - + toggleMute.visible - + maximizeParticipant.visible - + minimizeParticipant.visible - + hangupParticipant.visible - - ParticipantOverlayButton { - id: toggleModerator - - visible: showSetModerator || showUnsetModerator - preferredSize: iconButtonPreferredSize - Layout.preferredHeight: buttonPreferredSize - Layout.preferredWidth: buttonPreferredSize - source: JamiResources.moderator_svg - onClicked: CallAdapter.setModerator(uri, showSetModerator) - toolTipText: showSetModerator? JamiStrings.setModerator - : JamiStrings.unsetModerator - } - - ParticipantOverlayButton { - id: toggleMute - - visible: showModeratorMute || showModeratorUnmute - preferredSize: iconButtonPreferredSize - Layout.preferredHeight: buttonPreferredSize - Layout.preferredWidth: buttonPreferredSize - source: showModeratorMute ? - JamiResources.mic_24dp_svg : - JamiResources.mic_off_24dp_svg - onClicked: CallAdapter.muteParticipant(uri, showModeratorMute) - toolTipText: showModeratorMute? JamiStrings.muteParticipant - : JamiStrings.unmuteParticipant - } - - ParticipantOverlayButton { - id: maximizeParticipant - - visible: showMaximize - preferredSize: iconButtonPreferredSize - Layout.preferredHeight: buttonPreferredSize - Layout.preferredWidth: buttonPreferredSize - source: JamiResources.open_in_full_24dp_svg - onClicked: CallAdapter.maximizeParticipant(uri) - toolTipText: JamiStrings.maximizeParticipant - } - - ParticipantOverlayButton { - id: minimizeParticipant - - visible: showMinimize - preferredSize: iconButtonPreferredSize - Layout.preferredHeight: buttonPreferredSize - Layout.preferredWidth: buttonPreferredSize - source: JamiResources.close_fullscreen_24dp_svg - onClicked: CallAdapter.minimizeParticipant(uri) - toolTipText: JamiStrings.minimizeParticipant - } - - ParticipantOverlayButton { - id: hangupParticipant - - visible: showHangup - preferredSize: iconButtonPreferredSize - Layout.preferredHeight: buttonPreferredSize - Layout.preferredWidth: buttonPreferredSize - source: JamiResources.ic_hangup_participant_24dp_svg - onClicked: CallAdapter.hangupParticipant(uri) - toolTipText: JamiStrings.hangupParticipant - } -} +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Albert Babà <albert.babi@savoirfairelinux.com> + * + * 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 3 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 <https://www.gnu.org/licenses/>. + */ + +import QtQuick.Layouts 1.15 + +import net.jami.Adapters 1.1 +import net.jami.Constants 1.1 + +import "../../commoncomponents" + +RowLayout { + id: buttonsRect + + property int visibleButtons: toggleModerator.visible + + toggleMute.visible + + maximizeParticipant.visible + + minimizeParticipant.visible + + hangupParticipant.visible + + ParticipantOverlayButton { + id: toggleModerator + + visible: showSetModerator || showUnsetModerator + preferredSize: iconButtonPreferredSize + Layout.preferredHeight: buttonPreferredSize + Layout.preferredWidth: buttonPreferredSize + source: JamiResources.moderator_svg + onClicked: CallAdapter.setModerator(uri, showSetModerator) + toolTipText: showSetModerator? JamiStrings.setModerator + : JamiStrings.unsetModerator + } + + ParticipantOverlayButton { + id: toggleMute + + visible: showModeratorMute || showModeratorUnmute + preferredSize: iconButtonPreferredSize + Layout.preferredHeight: buttonPreferredSize + Layout.preferredWidth: buttonPreferredSize + source: showModeratorMute ? + JamiResources.mic_24dp_svg : + JamiResources.mic_off_24dp_svg + onClicked: CallAdapter.muteParticipant(uri, showModeratorMute) + toolTipText: showModeratorMute? JamiStrings.muteParticipant + : JamiStrings.unmuteParticipant + } + + ParticipantOverlayButton { + id: maximizeParticipant + + visible: showMaximize + preferredSize: iconButtonPreferredSize + Layout.preferredHeight: buttonPreferredSize + Layout.preferredWidth: buttonPreferredSize + source: JamiResources.open_in_full_24dp_svg + onClicked: CallAdapter.maximizeParticipant(uri) + toolTipText: JamiStrings.maximizeParticipant + } + + ParticipantOverlayButton { + id: minimizeParticipant + + visible: showMinimize + preferredSize: iconButtonPreferredSize + Layout.preferredHeight: buttonPreferredSize + Layout.preferredWidth: buttonPreferredSize + source: JamiResources.close_fullscreen_24dp_svg + onClicked: CallAdapter.minimizeParticipant(uri) + toolTipText: JamiStrings.minimizeParticipant + } + + ParticipantOverlayButton { + id: hangupParticipant + + visible: showHangup + preferredSize: iconButtonPreferredSize + Layout.preferredHeight: buttonPreferredSize + Layout.preferredWidth: buttonPreferredSize + source: JamiResources.ic_hangup_participant_24dp_svg + onClicked: CallAdapter.hangupParticipant(uri) + toolTipText: JamiStrings.hangupParticipant + } +} diff --git a/src/mainview/components/ParticipantOverlayButton.qml b/src/mainview/components/ParticipantOverlayButton.qml index 37ea84180ed726ba06a095b329b289fe5bca8e24..ec646cdfece601445d9879f3be976eef5fe35dfe 100644 --- a/src/mainview/components/ParticipantOverlayButton.qml +++ b/src/mainview/components/ParticipantOverlayButton.qml @@ -1,58 +1,58 @@ -/* - * Copyright (C) 2020 by Savoir-faire Linux - * Author: Albert Babà <albert.babi@savoirfairelinux.com> - * - * 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 3 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 <https://www.gnu.org/licenses/>. - */ - -import QtQuick 2.15 - -import net.jami.Constants 1.1 - -import "../../commoncomponents" - -PushButton { - id: root - - property alias toolTipText: toolTip.text - - normalColor: JamiTheme.buttonConference - hoveredColor: JamiTheme.buttonConferenceHovered - pressedColor: JamiTheme.buttonConferencePressed - - imageColor: JamiTheme.whiteColor - - Rectangle { - id: toolTipRect - height: 16 - width: toolTip.width + 8 - anchors { - horizontalCenter: parent.horizontalCenter - top: parent.bottom - topMargin: isBarLayout? 6 : 2 - } - color : isBarLayout? JamiTheme.darkGreyColorOpacity - : "transparent" - visible: root.hovered && !isSmall - radius: 2 - - Text { - id: toolTip - anchors.centerIn: parent - horizontalAlignment: Text.AlignHCenter - color: JamiTheme.whiteColor - font.pointSize: JamiTheme.tinyFontSize - } - } -} +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Albert Babà <albert.babi@savoirfairelinux.com> + * + * 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 3 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 <https://www.gnu.org/licenses/>. + */ + +import QtQuick 2.15 + +import net.jami.Constants 1.1 + +import "../../commoncomponents" + +PushButton { + id: root + + property alias toolTipText: toolTip.text + + normalColor: JamiTheme.buttonConference + hoveredColor: JamiTheme.buttonConferenceHovered + pressedColor: JamiTheme.buttonConferencePressed + + imageColor: JamiTheme.whiteColor + + Rectangle { + id: toolTipRect + height: 16 + width: toolTip.width + 8 + anchors { + horizontalCenter: parent.horizontalCenter + top: parent.bottom + topMargin: isBarLayout? 6 : 2 + } + color : isBarLayout? JamiTheme.darkGreyColorOpacity + : "transparent" + visible: root.hovered && !isSmall + radius: 2 + + Text { + id: toolTip + anchors.centerIn: parent + horizontalAlignment: Text.AlignHCenter + color: JamiTheme.whiteColor + font.pointSize: JamiTheme.tinyFontSize + } + } +} diff --git a/src/networkmanager.cpp b/src/networkmanager.cpp index 34567802b1e61b684135e56004997e7b5054da96..d82c3d3d25c7136c1bdd50d3fb1919f335a16da8 100644 --- a/src/networkmanager.cpp +++ b/src/networkmanager.cpp @@ -1,177 +1,177 @@ -/*! - * Copyright (C) 2019-2020 by Savoir-faire Linux - * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> - * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> - * - * 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 3 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 <http://www.gnu.org/licenses/>. - */ - -#include "networkmanager.h" - -#include "connectivitymonitor.h" -#include "utils.h" - -#include <QMetaEnum> -#include <QtNetwork> - -NetWorkManager::NetWorkManager(ConnectivityMonitor* cm, QObject* parent) - : QObject(parent) - , manager_(new QNetworkAccessManager(this)) - , reply_(nullptr) - , connectivityMonitor_(cm) - , lastConnectionState_(cm->isOnline()) -{ - Q_EMIT statusChanged(GetStatus::IDLE); - - connect(connectivityMonitor_, &ConnectivityMonitor::connectivityChanged, [this] { - cancelRequest(); - - auto connected = connectivityMonitor_->isOnline(); - if (connected && !lastConnectionState_) { - manager_->deleteLater(); - manager_ = new QNetworkAccessManager(this); - qWarning() << "connectivity changed, reset QNetworkAccessManager"; - } - lastConnectionState_ = connected; - }); -} - -void -NetWorkManager::get(const QUrl& url, const DoneCallBack& doneCb, const QString& path) -{ - if (!connectivityMonitor_->isOnline()) { - Q_EMIT errorOccured(GetError::DISCONNECTED); - return; - } - - if (reply_ && reply_->isRunning()) { - qWarning() << Q_FUNC_INFO << "currently downloading"; - return; - } else if (url.isEmpty()) { - qWarning() << Q_FUNC_INFO << "missing url"; - return; - } - - if (!path.isEmpty()) { - QFileInfo fileInfo(url.path()); - QString fileName = fileInfo.fileName(); - - file_.reset(new QFile(path + "/" + fileName)); - if (!file_->open(QIODevice::WriteOnly)) { - Q_EMIT errorOccured(GetError::ACCESS_DENIED); - file_.reset(nullptr); - return; - } - } - - QNetworkRequest request(url); - reply_ = manager_->get(request); - - Q_EMIT statusChanged(GetStatus::STARTED); - - connect(reply_, -#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) - QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::errorOccurred), -#else - QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error), -#endif - [this, doneCb, path](QNetworkReply::NetworkError error) { - reply_->disconnect(); - reset(true); - qWarning() << Q_FUNC_INFO << "NetworkError: " - << QMetaEnum::fromType<QNetworkReply::NetworkError>().valueToKey(error); - Q_EMIT errorOccured(GetError::NETWORK_ERROR); - }); - - connect(reply_, &QNetworkReply::finished, [this, doneCb, path]() { - reply_->disconnect(); - QString response = {}; - if (path.isEmpty()) - response = QString(reply_->readAll()); - reset(!path.isEmpty()); - Q_EMIT statusChanged(GetStatus::FINISHED); - if (doneCb) - doneCb(response); - }); - - connect(reply_, - &QNetworkReply::downloadProgress, - this, - &NetWorkManager::downloadProgressChanged); - - connect(reply_, &QNetworkReply::readyRead, this, &NetWorkManager::onHttpReadyRead); - -#if QT_CONFIG(ssl) - connect(reply_, - SIGNAL(sslErrors(const QList<QSslError>&)), - this, - SLOT(onSslErrors(QList<QSslError>)), - Qt::UniqueConnection); -#endif -} - -void -NetWorkManager::reset(bool flush) -{ - reply_->deleteLater(); - reply_ = nullptr; - if (file_ && flush) { - file_->flush(); - file_->close(); - file_.reset(nullptr); - } -} - -void -NetWorkManager::onSslErrors(const QList<QSslError>& sslErrors) -{ -#if QT_CONFIG(ssl) - reply_->disconnect(); - reset(true); - - QString errorsString; - for (const QSslError& error : sslErrors) { - if (errorsString.length() > 0) { - errorsString += "\n"; - } - errorsString += error.errorString(); - } - Q_EMIT errorOccured(GetError::SSL_ERROR, errorsString); - return; -#else - Q_UNUSED(sslErrors); -#endif -} - -void -NetWorkManager::onHttpReadyRead() -{ - /* - * This slot gets called every time the QNetworkReply has new data. - * We read all of its new data and write it into the file. - * That way we use less RAM than when reading it at the finished() - * signal of the QNetworkReply - */ - if (file_) - file_->write(reply_->readAll()); -} - -void -NetWorkManager::cancelRequest() -{ - if (reply_) { - reply_->abort(); - Q_EMIT errorOccured(GetError::CANCELED); - } -} +/*! + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> + * + * 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 3 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 <http://www.gnu.org/licenses/>. + */ + +#include "networkmanager.h" + +#include "connectivitymonitor.h" +#include "utils.h" + +#include <QMetaEnum> +#include <QtNetwork> + +NetWorkManager::NetWorkManager(ConnectivityMonitor* cm, QObject* parent) + : QObject(parent) + , manager_(new QNetworkAccessManager(this)) + , reply_(nullptr) + , connectivityMonitor_(cm) + , lastConnectionState_(cm->isOnline()) +{ + Q_EMIT statusChanged(GetStatus::IDLE); + + connect(connectivityMonitor_, &ConnectivityMonitor::connectivityChanged, [this] { + cancelRequest(); + + auto connected = connectivityMonitor_->isOnline(); + if (connected && !lastConnectionState_) { + manager_->deleteLater(); + manager_ = new QNetworkAccessManager(this); + qWarning() << "connectivity changed, reset QNetworkAccessManager"; + } + lastConnectionState_ = connected; + }); +} + +void +NetWorkManager::get(const QUrl& url, const DoneCallBack& doneCb, const QString& path) +{ + if (!connectivityMonitor_->isOnline()) { + Q_EMIT errorOccured(GetError::DISCONNECTED); + return; + } + + if (reply_ && reply_->isRunning()) { + qWarning() << Q_FUNC_INFO << "currently downloading"; + return; + } else if (url.isEmpty()) { + qWarning() << Q_FUNC_INFO << "missing url"; + return; + } + + if (!path.isEmpty()) { + QFileInfo fileInfo(url.path()); + QString fileName = fileInfo.fileName(); + + file_.reset(new QFile(path + "/" + fileName)); + if (!file_->open(QIODevice::WriteOnly)) { + Q_EMIT errorOccured(GetError::ACCESS_DENIED); + file_.reset(nullptr); + return; + } + } + + QNetworkRequest request(url); + reply_ = manager_->get(request); + + Q_EMIT statusChanged(GetStatus::STARTED); + + connect(reply_, +#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0) + QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::errorOccurred), +#else + QOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::error), +#endif + [this, doneCb, path](QNetworkReply::NetworkError error) { + reply_->disconnect(); + reset(true); + qWarning() << Q_FUNC_INFO << "NetworkError: " + << QMetaEnum::fromType<QNetworkReply::NetworkError>().valueToKey(error); + Q_EMIT errorOccured(GetError::NETWORK_ERROR); + }); + + connect(reply_, &QNetworkReply::finished, [this, doneCb, path]() { + reply_->disconnect(); + QString response = {}; + if (path.isEmpty()) + response = QString(reply_->readAll()); + reset(!path.isEmpty()); + Q_EMIT statusChanged(GetStatus::FINISHED); + if (doneCb) + doneCb(response); + }); + + connect(reply_, + &QNetworkReply::downloadProgress, + this, + &NetWorkManager::downloadProgressChanged); + + connect(reply_, &QNetworkReply::readyRead, this, &NetWorkManager::onHttpReadyRead); + +#if QT_CONFIG(ssl) + connect(reply_, + SIGNAL(sslErrors(const QList<QSslError>&)), + this, + SLOT(onSslErrors(QList<QSslError>)), + Qt::UniqueConnection); +#endif +} + +void +NetWorkManager::reset(bool flush) +{ + reply_->deleteLater(); + reply_ = nullptr; + if (file_ && flush) { + file_->flush(); + file_->close(); + file_.reset(nullptr); + } +} + +void +NetWorkManager::onSslErrors(const QList<QSslError>& sslErrors) +{ +#if QT_CONFIG(ssl) + reply_->disconnect(); + reset(true); + + QString errorsString; + for (const QSslError& error : sslErrors) { + if (errorsString.length() > 0) { + errorsString += "\n"; + } + errorsString += error.errorString(); + } + Q_EMIT errorOccured(GetError::SSL_ERROR, errorsString); + return; +#else + Q_UNUSED(sslErrors); +#endif +} + +void +NetWorkManager::onHttpReadyRead() +{ + /* + * This slot gets called every time the QNetworkReply has new data. + * We read all of its new data and write it into the file. + * That way we use less RAM than when reading it at the finished() + * signal of the QNetworkReply + */ + if (file_) + file_->write(reply_->readAll()); +} + +void +NetWorkManager::cancelRequest() +{ + if (reply_) { + reply_->abort(); + Q_EMIT errorOccured(GetError::CANCELED); + } +} diff --git a/src/networkmanager.h b/src/networkmanager.h index 20295f58d05b8d443816785fa8b6d8b508b303f0..251532e9a590e5217eccad317039a0042760edf2 100644 --- a/src/networkmanager.h +++ b/src/networkmanager.h @@ -1,76 +1,76 @@ -/*! - * Copyright (C) 2019-2020 by Savoir-faire Linux - * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> - * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> - * - * 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 3 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 <http://www.gnu.org/licenses/>. - */ - -#pragma once - -#include <QObject> -#include <QFile> -#include <QSslError> -#include <QNetworkReply> - -class QNetworkAccessManager; -class ConnectivityMonitor; - -class NetWorkManager : public QObject -{ - Q_OBJECT -public: - explicit NetWorkManager(ConnectivityMonitor* cm, QObject* parent = nullptr); - virtual ~NetWorkManager() = default; - - enum GetStatus { IDLE, STARTED, FINISHED }; - - enum GetError { DISCONNECTED, NETWORK_ERROR, ACCESS_DENIED, SSL_ERROR, CANCELED }; - Q_ENUM(GetError) - - using DoneCallBack = std::function<void(const QString&)>; - - /*! - * using qt get request to store the reply in file - * @param url - network address - * @param doneCb - done callback - * @param path - optional file saving path, if empty - * a string will be passed as the second paramter of doneCb - */ - void get(const QUrl& url, const DoneCallBack& doneCb = {}, const QString& path = {}); - - /*! - * manually abort the current request - */ - Q_INVOKABLE void cancelRequest(); - -Q_SIGNALS: - void statusChanged(GetStatus error); - void downloadProgressChanged(qint64 bytesRead, qint64 totalBytes); - void errorOccured(GetError error, const QString& msg = {}); - -private Q_SLOTS: - void onSslErrors(const QList<QSslError>& sslErrors); - void onHttpReadyRead(); - -private: - void reset(bool flush = true); - - QNetworkAccessManager* manager_; - QNetworkReply* reply_; - QScopedPointer<QFile> file_; - ConnectivityMonitor* connectivityMonitor_; - bool lastConnectionState_; -}; -Q_DECLARE_METATYPE(NetWorkManager*) +/*! + * Copyright (C) 2019-2020 by Savoir-faire Linux + * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> + * + * 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 3 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 <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <QObject> +#include <QFile> +#include <QSslError> +#include <QNetworkReply> + +class QNetworkAccessManager; +class ConnectivityMonitor; + +class NetWorkManager : public QObject +{ + Q_OBJECT +public: + explicit NetWorkManager(ConnectivityMonitor* cm, QObject* parent = nullptr); + virtual ~NetWorkManager() = default; + + enum GetStatus { IDLE, STARTED, FINISHED }; + + enum GetError { DISCONNECTED, NETWORK_ERROR, ACCESS_DENIED, SSL_ERROR, CANCELED }; + Q_ENUM(GetError) + + using DoneCallBack = std::function<void(const QString&)>; + + /*! + * using qt get request to store the reply in file + * @param url - network address + * @param doneCb - done callback + * @param path - optional file saving path, if empty + * a string will be passed as the second paramter of doneCb + */ + void get(const QUrl& url, const DoneCallBack& doneCb = {}, const QString& path = {}); + + /*! + * manually abort the current request + */ + Q_INVOKABLE void cancelRequest(); + +Q_SIGNALS: + void statusChanged(GetStatus error); + void downloadProgressChanged(qint64 bytesRead, qint64 totalBytes); + void errorOccured(GetError error, const QString& msg = {}); + +private Q_SLOTS: + void onSslErrors(const QList<QSslError>& sslErrors); + void onHttpReadyRead(); + +private: + void reset(bool flush = true); + + QNetworkAccessManager* manager_; + QNetworkReply* reply_; + QScopedPointer<QFile> file_; + ConnectivityMonitor* connectivityMonitor_; + bool lastConnectionState_; +}; +Q_DECLARE_METATYPE(NetWorkManager*) diff --git a/src/qtutils.h b/src/qtutils.h index f42a929df83f0391db648b6e360fa4ac76b67d9d..72a28ef900c88e070933f0da29609c19bd5d1b90 100644 --- a/src/qtutils.h +++ b/src/qtutils.h @@ -1,173 +1,173 @@ -/* - * Copyright (C) 2015-2020 by Savoir-faire Linux - * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com> - * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> - * Author: Isa Nanic <isa.nanic@savoirfairelinux.com> - * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> - * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> - * - * 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 3 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 <http://www.gnu.org/licenses/>. - */ - -#pragma once - -#include <QObject> - -#define PROPERTY_BASE(type, prop) \ - type prop##_ {}; \ -\ -public: \ - Q_SIGNAL void prop##Changed(); \ - type get_##prop() \ - { \ - return prop##_; \ - } \ - void set_##prop(const type& x = {}) \ - { \ - if (prop##_ != x) { \ - prop##_ = x; \ - Q_EMIT prop##Changed(); \ - } \ - } - -#define QML_RO_PROPERTY(type, prop) \ -private: \ - Q_PROPERTY(type prop READ get_##prop NOTIFY prop##Changed); \ - PROPERTY_BASE(type, prop) - -#define QML_PROPERTY(type, prop) \ -private: \ - Q_PROPERTY(type prop MEMBER prop##_ NOTIFY prop##Changed); \ - PROPERTY_BASE(type, prop) - -namespace Utils { - -template<typename Func1, typename Func2> -void -oneShotConnect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender, - Func1 signal, - Func2 slot) -{ - QMetaObject::Connection* const connection = new QMetaObject::Connection; - *connection = QObject::connect(sender, signal, slot); - QMetaObject::Connection* const disconnectConnection = new QMetaObject::Connection; - *disconnectConnection = QObject::connect(sender, signal, [connection, disconnectConnection] { - if (connection) { - QObject::disconnect(*connection); - delete connection; - } - if (disconnectConnection) { - QObject::disconnect(*disconnectConnection); - delete disconnectConnection; - } - }); -} - -template<typename Func1, typename Func2, typename Func3> -void -oneShotConnect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender, - Func1 signal, - Func2 slot, - const typename QtPrivate::FunctionPointer<Func3>::Object* interrupter, - Func3 interrupterSignal) -{ - QMetaObject::Connection* const connection = new QMetaObject::Connection; - QMetaObject::Connection* const disconnectConnection = new QMetaObject::Connection; - QMetaObject::Connection* const interruptConnection = new QMetaObject::Connection; - - auto disconnectFunc = [connection, disconnectConnection, interruptConnection] { - if (connection) { - QObject::disconnect(*connection); - delete connection; - } - if (disconnectConnection) { - QObject::disconnect(*disconnectConnection); - delete disconnectConnection; - } - if (interruptConnection) { - QObject::disconnect(*interruptConnection); - delete interruptConnection; - } - }; - *connection = QObject::connect(sender, signal, slot); - *disconnectConnection = QObject::connect(sender, signal, disconnectFunc); - *interruptConnection = QObject::connect(interrupter, interrupterSignal, disconnectFunc); -} - -template<typename Func1, typename Func2> -void -oneShotConnect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender, - Func1 signal, - const typename QtPrivate::FunctionPointer<Func2>::Object* receiver, - Func2 slot) -{ - QMetaObject::Connection* const connection = new QMetaObject::Connection; - *connection = QObject::connect(sender, signal, receiver, slot); - QMetaObject::Connection* const disconnectConnection = new QMetaObject::Connection; - *disconnectConnection = QObject::connect(sender, signal, [connection, disconnectConnection] { - if (connection) { - QObject::disconnect(*connection); - delete connection; - } - if (disconnectConnection) { - QObject::disconnect(*disconnectConnection); - delete disconnectConnection; - } - }); -} - -class OneShotConnection final : public QObject -{ - Q_OBJECT -public: - explicit OneShotConnection(const QObject* sender, - const char* signal, - QMetaObject::Connection* connection, - QObject* parent = nullptr) - : QObject(parent) - { - connection_ = connection; - disconnectConnection_ = new QMetaObject::Connection; - *disconnectConnection_ = QObject::connect(sender, signal, this, SLOT(onTriggered())); - } - ~OneShotConnection() = default; - -public Q_SLOTS: - void onTriggered() - { - if (connection_) { - QObject::disconnect(*connection_); - delete connection_; - } - if (disconnectConnection_) { - QObject::disconnect(*disconnectConnection_); - delete disconnectConnection_; - } - deleteLater(); - } - -private: - QMetaObject::Connection* connection_; - QMetaObject::Connection* disconnectConnection_; -}; - -inline void -oneShotConnect(const QObject* sender, const char* signal, const QObject* receiver, const char* slot) -{ - QMetaObject::Connection* const connection = new QMetaObject::Connection; - *connection = QObject::connect(sender, signal, receiver, slot); - new OneShotConnection(sender, signal, connection); -} - -} // namespace Utils +/* + * Copyright (C) 2015-2020 by Savoir-faire Linux + * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com> + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> + * Author: Isa Nanic <isa.nanic@savoirfairelinux.com> + * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> + * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> + * + * 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 3 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 <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <QObject> + +#define PROPERTY_BASE(type, prop) \ + type prop##_ {}; \ +\ +public: \ + Q_SIGNAL void prop##Changed(); \ + type get_##prop() \ + { \ + return prop##_; \ + } \ + void set_##prop(const type& x = {}) \ + { \ + if (prop##_ != x) { \ + prop##_ = x; \ + Q_EMIT prop##Changed(); \ + } \ + } + +#define QML_RO_PROPERTY(type, prop) \ +private: \ + Q_PROPERTY(type prop READ get_##prop NOTIFY prop##Changed); \ + PROPERTY_BASE(type, prop) + +#define QML_PROPERTY(type, prop) \ +private: \ + Q_PROPERTY(type prop MEMBER prop##_ NOTIFY prop##Changed); \ + PROPERTY_BASE(type, prop) + +namespace Utils { + +template<typename Func1, typename Func2> +void +oneShotConnect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender, + Func1 signal, + Func2 slot) +{ + QMetaObject::Connection* const connection = new QMetaObject::Connection; + *connection = QObject::connect(sender, signal, slot); + QMetaObject::Connection* const disconnectConnection = new QMetaObject::Connection; + *disconnectConnection = QObject::connect(sender, signal, [connection, disconnectConnection] { + if (connection) { + QObject::disconnect(*connection); + delete connection; + } + if (disconnectConnection) { + QObject::disconnect(*disconnectConnection); + delete disconnectConnection; + } + }); +} + +template<typename Func1, typename Func2, typename Func3> +void +oneShotConnect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender, + Func1 signal, + Func2 slot, + const typename QtPrivate::FunctionPointer<Func3>::Object* interrupter, + Func3 interrupterSignal) +{ + QMetaObject::Connection* const connection = new QMetaObject::Connection; + QMetaObject::Connection* const disconnectConnection = new QMetaObject::Connection; + QMetaObject::Connection* const interruptConnection = new QMetaObject::Connection; + + auto disconnectFunc = [connection, disconnectConnection, interruptConnection] { + if (connection) { + QObject::disconnect(*connection); + delete connection; + } + if (disconnectConnection) { + QObject::disconnect(*disconnectConnection); + delete disconnectConnection; + } + if (interruptConnection) { + QObject::disconnect(*interruptConnection); + delete interruptConnection; + } + }; + *connection = QObject::connect(sender, signal, slot); + *disconnectConnection = QObject::connect(sender, signal, disconnectFunc); + *interruptConnection = QObject::connect(interrupter, interrupterSignal, disconnectFunc); +} + +template<typename Func1, typename Func2> +void +oneShotConnect(const typename QtPrivate::FunctionPointer<Func1>::Object* sender, + Func1 signal, + const typename QtPrivate::FunctionPointer<Func2>::Object* receiver, + Func2 slot) +{ + QMetaObject::Connection* const connection = new QMetaObject::Connection; + *connection = QObject::connect(sender, signal, receiver, slot); + QMetaObject::Connection* const disconnectConnection = new QMetaObject::Connection; + *disconnectConnection = QObject::connect(sender, signal, [connection, disconnectConnection] { + if (connection) { + QObject::disconnect(*connection); + delete connection; + } + if (disconnectConnection) { + QObject::disconnect(*disconnectConnection); + delete disconnectConnection; + } + }); +} + +class OneShotConnection final : public QObject +{ + Q_OBJECT +public: + explicit OneShotConnection(const QObject* sender, + const char* signal, + QMetaObject::Connection* connection, + QObject* parent = nullptr) + : QObject(parent) + { + connection_ = connection; + disconnectConnection_ = new QMetaObject::Connection; + *disconnectConnection_ = QObject::connect(sender, signal, this, SLOT(onTriggered())); + } + ~OneShotConnection() = default; + +public Q_SLOTS: + void onTriggered() + { + if (connection_) { + QObject::disconnect(*connection_); + delete connection_; + } + if (disconnectConnection_) { + QObject::disconnect(*disconnectConnection_); + delete disconnectConnection_; + } + deleteLater(); + } + +private: + QMetaObject::Connection* connection_; + QMetaObject::Connection* disconnectConnection_; +}; + +inline void +oneShotConnect(const QObject* sender, const char* signal, const QObject* receiver, const char* slot) +{ + QMetaObject::Connection* const connection = new QMetaObject::Connection; + *connection = QObject::connect(sender, signal, receiver, slot); + new OneShotConnection(sender, signal, connection); +} + +} // namespace Utils diff --git a/src/screensaver.cpp b/src/screensaver.cpp index 9122a2c9f21e447978b99795d4478d35de31d4ad..6f3e42102d96f1fb08b7733058240624b22a6828 100644 --- a/src/screensaver.cpp +++ b/src/screensaver.cpp @@ -1,124 +1,124 @@ -/*! - * Copyright (C) 2021 by Savoir-faire Linux - * Author: Albert Babà <albert.babi@savoirfairelinux.com> - * - * 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 3 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 <http://www.gnu.org/licenses/>. - */ - -#include "screensaver.h" - -#include <QDebug> - -ScreenSaver::ScreenSaver(QObject* parent) -#ifdef Q_OS_LINUX - : QObject(parent) - , sessionBus_(QDBusConnection::sessionBus()) - , screenSaverInterface_(nullptr) -{ - request_ = 0u; - createInterface(); -} -#else - : QObject(parent) -{} -#endif - -#ifdef Q_OS_LINUX -bool -ScreenSaver::createInterface(void) -{ - if (!sessionBus_.isConnected()) { - qWarning() << "dbus not connected"; - return false; - } - - for (int i = 0; i < N_SERVICES; i++) { - screenSaverInterface_ = new QDBusInterface(services_[i], - paths_[i], - services_[i], - sessionBus_); - if (screenSaverInterface_ && screenSaverInterface_->isValid()) { - qDebug() << "Screen saver dbus interface: " << services_[i]; - return true; - } - } - qWarning() << "Cannot find dbus interface for screen saver"; - screenSaverInterface_ = nullptr; - return false; -} -#endif - -bool -ScreenSaver::inhibit(void) -{ - if (isInhibited()) { - qDebug() << "Screen saver already inhibited"; - return false; - } -#ifdef Q_OS_LINUX - if (!screenSaverInterface_) { - if (!createInterface()) { - return false; - } - } - - QDBusReply<uint> reply = screenSaverInterface_->call("Inhibit", "jami-qt", "In a call"); - if (reply.isValid()) { - qDebug() << "Screen saver inhibited"; - request_ = static_cast<uint>(reply.value()); - return true; - } else { - QDBusError error = reply.error(); - qDebug() << "Error inhibiting screen saver: " << error.message() << error.name(); - } -#endif - return false; -} - -bool -ScreenSaver::uninhibit(void) -{ - if (!isInhibited()) { - qDebug() << "Screen saver is not inhibited"; - return false; - } -#ifdef Q_OS_LINUX - if (!screenSaverInterface_) { - if (!createInterface()) { - return false; - } - } - - QDBusReply<void> reply = screenSaverInterface_->call("UnInhibit", static_cast<uint>(request_)); - if (reply.isValid()) { - qDebug() << "Screen saver uninhibited"; - request_ = 0u; - return true; - } else { - QDBusError error = reply.error(); - qDebug() << "Error uninhibiting screen saver: " << error.message() << error.name(); - } - request_ = 0u; -#endif - return false; -} - -bool -ScreenSaver::isInhibited(void) -{ -#ifdef Q_OS_LINUX - return request_ != 0u; -#endif - return false; -} +/*! + * Copyright (C) 2021 by Savoir-faire Linux + * Author: Albert Babà <albert.babi@savoirfairelinux.com> + * + * 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 3 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 <http://www.gnu.org/licenses/>. + */ + +#include "screensaver.h" + +#include <QDebug> + +ScreenSaver::ScreenSaver(QObject* parent) +#ifdef Q_OS_LINUX + : QObject(parent) + , sessionBus_(QDBusConnection::sessionBus()) + , screenSaverInterface_(nullptr) +{ + request_ = 0u; + createInterface(); +} +#else + : QObject(parent) +{} +#endif + +#ifdef Q_OS_LINUX +bool +ScreenSaver::createInterface(void) +{ + if (!sessionBus_.isConnected()) { + qWarning() << "dbus not connected"; + return false; + } + + for (int i = 0; i < N_SERVICES; i++) { + screenSaverInterface_ = new QDBusInterface(services_[i], + paths_[i], + services_[i], + sessionBus_); + if (screenSaverInterface_ && screenSaverInterface_->isValid()) { + qDebug() << "Screen saver dbus interface: " << services_[i]; + return true; + } + } + qWarning() << "Cannot find dbus interface for screen saver"; + screenSaverInterface_ = nullptr; + return false; +} +#endif + +bool +ScreenSaver::inhibit(void) +{ + if (isInhibited()) { + qDebug() << "Screen saver already inhibited"; + return false; + } +#ifdef Q_OS_LINUX + if (!screenSaverInterface_) { + if (!createInterface()) { + return false; + } + } + + QDBusReply<uint> reply = screenSaverInterface_->call("Inhibit", "jami-qt", "In a call"); + if (reply.isValid()) { + qDebug() << "Screen saver inhibited"; + request_ = static_cast<uint>(reply.value()); + return true; + } else { + QDBusError error = reply.error(); + qDebug() << "Error inhibiting screen saver: " << error.message() << error.name(); + } +#endif + return false; +} + +bool +ScreenSaver::uninhibit(void) +{ + if (!isInhibited()) { + qDebug() << "Screen saver is not inhibited"; + return false; + } +#ifdef Q_OS_LINUX + if (!screenSaverInterface_) { + if (!createInterface()) { + return false; + } + } + + QDBusReply<void> reply = screenSaverInterface_->call("UnInhibit", static_cast<uint>(request_)); + if (reply.isValid()) { + qDebug() << "Screen saver uninhibited"; + request_ = 0u; + return true; + } else { + QDBusError error = reply.error(); + qDebug() << "Error uninhibiting screen saver: " << error.message() << error.name(); + } + request_ = 0u; +#endif + return false; +} + +bool +ScreenSaver::isInhibited(void) +{ +#ifdef Q_OS_LINUX + return request_ != 0u; +#endif + return false; +} diff --git a/src/screensaver.h b/src/screensaver.h index f1de7a511ca2187713f9a01ae6407cac9798a9e0..592d4bc779bbb42d5825c358dc8496c9de191db9 100644 --- a/src/screensaver.h +++ b/src/screensaver.h @@ -1,55 +1,55 @@ -/*! - * Copyright (C) 2021 by Savoir-faire Linux - * Author: Albert Babà <albert.babi@savoirfairelinux.com> - * - * 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 3 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 <http://www.gnu.org/licenses/>. - */ - -#pragma once - -#include <QObject> - -#ifdef Q_OS_LINUX -#include <QDBusInterface> -#include <QDBusReply> -#define N_SERVICES 3 -#endif - -class ScreenSaver : public QObject -{ - Q_OBJECT -public: - explicit ScreenSaver(QObject* parent = nullptr); - virtual ~ScreenSaver() = default; - - bool inhibit(void); - bool uninhibit(void); - bool isInhibited(void); - -#ifdef Q_OS_LINUX -private: - bool createInterface(void); - QString services_[N_SERVICES] = { "org.freedesktop.ScreenSaver", - "org.gnome.ScreenSaver", - "org.mate.ScreenSaver" }; - - QString paths_[N_SERVICES] = { "/org/freedesktop/ScreenSaver", - "/org/gnome/ScreenSaver", - "/org/mate/ScreenSaver" }; - - uint request_; - QDBusConnection sessionBus_; - QDBusInterface* screenSaverInterface_; -#endif -}; +/*! + * Copyright (C) 2021 by Savoir-faire Linux + * Author: Albert Babà <albert.babi@savoirfairelinux.com> + * + * 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 3 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 <http://www.gnu.org/licenses/>. + */ + +#pragma once + +#include <QObject> + +#ifdef Q_OS_LINUX +#include <QDBusInterface> +#include <QDBusReply> +#define N_SERVICES 3 +#endif + +class ScreenSaver : public QObject +{ + Q_OBJECT +public: + explicit ScreenSaver(QObject* parent = nullptr); + virtual ~ScreenSaver() = default; + + bool inhibit(void); + bool uninhibit(void); + bool isInhibited(void); + +#ifdef Q_OS_LINUX +private: + bool createInterface(void); + QString services_[N_SERVICES] = { "org.freedesktop.ScreenSaver", + "org.gnome.ScreenSaver", + "org.mate.ScreenSaver" }; + + QString paths_[N_SERVICES] = { "/org/freedesktop/ScreenSaver", + "/org/gnome/ScreenSaver", + "/org/mate/ScreenSaver" }; + + uint request_; + QDBusConnection sessionBus_; + QDBusInterface* screenSaverInterface_; +#endif +}; diff --git a/src/settingsview/components/RevokeDevicePasswordDialog.qml b/src/settingsview/components/RevokeDevicePasswordDialog.qml index eb14391f70369ebde8e3b5d94d3538eb9718081c..cc983f5b91b0123d6f5e770ee888eab5d423fbb1 100644 --- a/src/settingsview/components/RevokeDevicePasswordDialog.qml +++ b/src/settingsview/components/RevokeDevicePasswordDialog.qml @@ -1,136 +1,136 @@ -/* - * Copyright (C) 2020 by Savoir-faire Linux - * Author: Yang Wang <yang.wang@savoirfairelinux.com> - * Author: Albert Babà <albert.babi@savoirfairelinux.com> - * - * 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 3 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 <https://www.gnu.org/licenses/>. - */ - -import QtQuick 2.15 -import QtQuick.Controls 2.15 -import QtQuick.Layouts 1.15 - -import net.jami.Constants 1.1 - -import "../../commoncomponents" - -BaseDialog { - id: root - - property string deviceId : "" - - signal revokeDeviceWithPassword(string idOfDevice, string password) - - function openRevokeDeviceDialog(deviceIdIn) { - deviceId = deviceIdIn - passwordEdit.clear() - open() - } - - title: qsTr("Remove device") - - contentItem: Rectangle { - id: revokeDeviceContentRect - - implicitWidth: JamiTheme.preferredDialogWidth - implicitHeight: JamiTheme.preferredDialogHeight - - ColumnLayout { - anchors.centerIn: parent - anchors.fill: parent - anchors.margins: JamiTheme.preferredMarginSize - spacing: 16 - - Label { - id: labelDeletion - - Layout.alignment: Qt.AlignHCenter - Layout.preferredWidth: revokeDeviceContentRect.width - JamiTheme.preferredMarginSize * 2 - - text: qsTr("Enter this account's password to confirm the removal of this device") - font.pointSize: JamiTheme.textFontSize - font.kerning: true - wrapMode: Text.Wrap - - horizontalAlignment: Text.AlignHCenter - verticalAlignment: Text.AlignVCenter - } - - MaterialLineEdit { - id: passwordEdit - - Layout.alignment: Qt.AlignHCenter - Layout.preferredWidth: JamiTheme.preferredFieldWidth - Layout.preferredHeight: visible ? 48 : 0 - - echoMode: TextInput.Password - placeholderText: JamiStrings.enterCurrentPassword - - onTextChanged: { - btnRemove.enabled = text.length > 0 - } - } - - RowLayout { - spacing: 16 - Layout.alignment: Qt.AlignHCenter - - Layout.fillWidth: true - - MaterialButton { - id: btnRemove - - Layout.alignment: Qt.AlignHCenter - - preferredWidth: JamiTheme.preferredFieldWidth / 2 - 8 - preferredHeight: JamiTheme.preferredFieldHeight - - color: enabled? JamiTheme.buttonTintedBlack : JamiTheme.buttonTintedGrey - hoveredColor: JamiTheme.buttonTintedBlackHovered - pressedColor: JamiTheme.buttonTintedBlackPressed - outlined: true - enabled: false - - text: qsTr("Remove") - - onClicked: { - revokeDeviceWithPassword(deviceId, passwordEdit.text) - close() - } - } - - MaterialButton { - id: btnCancel - - Layout.alignment: Qt.AlignHCenter - - preferredWidth: JamiTheme.preferredFieldWidth / 2 - 8 - preferredHeight: JamiTheme.preferredFieldHeight - - color: JamiTheme.buttonTintedBlack - hoveredColor: JamiTheme.buttonTintedBlackHovered - pressedColor: JamiTheme.buttonTintedBlackPressed - outlined: true - enabled: true - - text: qsTr("Cancel") - - onClicked: { - close() - } - } - } - } - } -} +/* + * Copyright (C) 2020 by Savoir-faire Linux + * Author: Yang Wang <yang.wang@savoirfairelinux.com> + * Author: Albert Babà <albert.babi@savoirfairelinux.com> + * + * 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 3 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 <https://www.gnu.org/licenses/>. + */ + +import QtQuick 2.15 +import QtQuick.Controls 2.15 +import QtQuick.Layouts 1.15 + +import net.jami.Constants 1.1 + +import "../../commoncomponents" + +BaseDialog { + id: root + + property string deviceId : "" + + signal revokeDeviceWithPassword(string idOfDevice, string password) + + function openRevokeDeviceDialog(deviceIdIn) { + deviceId = deviceIdIn + passwordEdit.clear() + open() + } + + title: qsTr("Remove device") + + contentItem: Rectangle { + id: revokeDeviceContentRect + + implicitWidth: JamiTheme.preferredDialogWidth + implicitHeight: JamiTheme.preferredDialogHeight + + ColumnLayout { + anchors.centerIn: parent + anchors.fill: parent + anchors.margins: JamiTheme.preferredMarginSize + spacing: 16 + + Label { + id: labelDeletion + + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: revokeDeviceContentRect.width - JamiTheme.preferredMarginSize * 2 + + text: qsTr("Enter this account's password to confirm the removal of this device") + font.pointSize: JamiTheme.textFontSize + font.kerning: true + wrapMode: Text.Wrap + + horizontalAlignment: Text.AlignHCenter + verticalAlignment: Text.AlignVCenter + } + + MaterialLineEdit { + id: passwordEdit + + Layout.alignment: Qt.AlignHCenter + Layout.preferredWidth: JamiTheme.preferredFieldWidth + Layout.preferredHeight: visible ? 48 : 0 + + echoMode: TextInput.Password + placeholderText: JamiStrings.enterCurrentPassword + + onTextChanged: { + btnRemove.enabled = text.length > 0 + } + } + + RowLayout { + spacing: 16 + Layout.alignment: Qt.AlignHCenter + + Layout.fillWidth: true + + MaterialButton { + id: btnRemove + + Layout.alignment: Qt.AlignHCenter + + preferredWidth: JamiTheme.preferredFieldWidth / 2 - 8 + preferredHeight: JamiTheme.preferredFieldHeight + + color: enabled? JamiTheme.buttonTintedBlack : JamiTheme.buttonTintedGrey + hoveredColor: JamiTheme.buttonTintedBlackHovered + pressedColor: JamiTheme.buttonTintedBlackPressed + outlined: true + enabled: false + + text: qsTr("Remove") + + onClicked: { + revokeDeviceWithPassword(deviceId, passwordEdit.text) + close() + } + } + + MaterialButton { + id: btnCancel + + Layout.alignment: Qt.AlignHCenter + + preferredWidth: JamiTheme.preferredFieldWidth / 2 - 8 + preferredHeight: JamiTheme.preferredFieldHeight + + color: JamiTheme.buttonTintedBlack + hoveredColor: JamiTheme.buttonTintedBlackHovered + pressedColor: JamiTheme.buttonTintedBlackPressed + outlined: true + enabled: true + + text: qsTr("Cancel") + + onClicked: { + close() + } + } + } + } + } +} diff --git a/src/utilsadapter.cpp b/src/utilsadapter.cpp index a417e17b832b29e8892098e998019f855693b0cb..bdcb20c7a038b8dee7ce7818a8a307939483b3fb 100644 --- a/src/utilsadapter.cpp +++ b/src/utilsadapter.cpp @@ -1,321 +1,321 @@ -/*! - * Copyright (C) 2015-2020 by Savoir-faire Linux - * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com> - * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> - * Author: Isa Nanic <isa.nanic@savoirfairelinux.com> - * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> - * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> - * - * 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 3 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 <http://www.gnu.org/licenses/>. - */ - -#include "utilsadapter.h" - -#include "lrcinstance.h" -#include "systemtray.h" -#include "utils.h" -#include "version.h" - -#include "api/pluginmodel.h" - -#include <QApplication> -#include <QClipboard> -#include <QFileInfo> - -UtilsAdapter::UtilsAdapter(SystemTray* systemTray, LRCInstance* instance, QObject* parent) - : QmlAdapterBase(instance, parent) - , clipboard_(QApplication::clipboard()) - , systemTray_(systemTray) -{} - -const QString -UtilsAdapter::getProjectCredits() -{ - return Utils::getProjectCredits(); -} - -const QString -UtilsAdapter::getVersionStr() -{ - return QString(VERSION_STRING); -} - -void -UtilsAdapter::setClipboardText(QString text) -{ - clipboard_->setText(text, QClipboard::Clipboard); -} - -const QString -UtilsAdapter::qStringFromFile(const QString& filename) -{ - return Utils::QByteArrayFromFile(filename); -} - -const QString -UtilsAdapter::getStyleSheet(const QString& name, const QString& source) -{ - auto simplifiedCSS = source.simplified().replace("'", "\""); - QString s = QString::fromLatin1("(function() {" - " var node = document.createElement('style');" - " node.id = '%1';" - " node.innerHTML = '%2';" - " document.head.appendChild(node);" - "})()") - .arg(name) - .arg(simplifiedCSS); - return s; -} - -const QString -UtilsAdapter::getCachePath() -{ - QDir dataDir(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)); - dataDir.cdUp(); - return dataDir.absolutePath() + "/jami"; -} -bool -UtilsAdapter::createStartupLink() -{ - return Utils::CreateStartupLink(L"Jami"); -} - -QString -UtilsAdapter::GetRingtonePath() -{ - return Utils::GetRingtonePath(); -} - -bool -UtilsAdapter::checkStartupLink() -{ - return Utils::CheckStartupLink(L"Jami"); -} - -const QString -UtilsAdapter::getBestName(const QString& accountId, const QString& uid) -{ - const auto& conv = lrcInstance_->getConversationFromConvUid(uid); - if (!conv.participants.isEmpty()) - return lrcInstance_->getAccountInfo(accountId).contactModel->bestNameForContact( - conv.participants[0]); - return QString(); -} - -const QString -UtilsAdapter::getPeerUri(const QString& accountId, const QString& uid) -{ - try { - auto* convModel = lrcInstance_->getAccountInfo(accountId).conversationModel.get(); - const auto& convInfo = convModel->getConversationForUid(uid).value(); - return convInfo.get().participants.front(); - } catch (const std::out_of_range& e) { - qDebug() << e.what(); - return ""; - } -} - -QString -UtilsAdapter::getBestId(const QString& accountId) -{ - if (accountId.isEmpty()) - return {}; - return lrcInstance_->accountModel().bestIdForAccount(accountId); -} - -const QString -UtilsAdapter::getBestId(const QString& accountId, const QString& uid) -{ - const auto& conv = lrcInstance_->getConversationFromConvUid(uid); - if (!conv.participants.isEmpty()) - return lrcInstance_->getAccountInfo(accountId).contactModel->bestIdForContact( - conv.participants[0]); - return QString(); -} - -void -UtilsAdapter::setConversationFilter(const QString& filter) -{ - lrcInstance_->getCurrentConversationModel()->setFilter(filter); -} - -const QStringList -UtilsAdapter::getCurrAccList() -{ - return lrcInstance_->accountModel().getAccountList(); -} - -int -UtilsAdapter::getAccountListSize() -{ - return getCurrAccList().size(); -} - -bool -UtilsAdapter::hasCall(const QString& accountId) -{ - auto activeCalls = lrcInstance_->getActiveCalls(); - for (const auto& callId : activeCalls) { - auto& accountInfo = lrcInstance_->accountModel().getAccountInfo(accountId); - if (accountInfo.callModel->hasCall(callId)) { - return true; - } - } - return false; -} - -const QString -UtilsAdapter::getCallConvForAccount(const QString& accountId) -{ - // TODO: Currently returning first call, establish priority according to state? - for (const auto& callId : lrcInstance_->getActiveCalls()) { - auto& accountInfo = lrcInstance_->accountModel().getAccountInfo(accountId); - if (accountInfo.callModel->hasCall(callId)) { - return lrcInstance_->getConversationFromCallId(callId, accountId).uid; - } - } - return ""; -} - -const QString -UtilsAdapter::getCallId(const QString& accountId, const QString& convUid) -{ - auto const& convInfo = lrcInstance_->getConversationFromConvUid(convUid, accountId); - if (convInfo.uid.isEmpty()) { - return {}; - } - - if (auto* call = lrcInstance_->getCallInfoForConversation(convInfo, false)) { - return call->id; - } - - return {}; -} - -int -UtilsAdapter::getCallStatus(const QString& callId) -{ - const auto callStatus = lrcInstance_->getCallInfo(callId, lrcInstance_->get_currentAccountId()); - return static_cast<int>(callStatus->status); -} - -const QString -UtilsAdapter::getCallStatusStr(int statusInt) -{ - const auto status = static_cast<lrc::api::call::Status>(statusInt); - return lrc::api::call::to_string(status); -} - -// returns true if name is valid registered name -bool -UtilsAdapter::validateRegNameForm(const QString& regName) -{ - QRegularExpression regExp(" "); - - if (regName.size() > 2 && !regName.contains(regExp)) { - return true; - - } else { - return false; - } -} - -QString -UtilsAdapter::getStringUTF8(QString string) -{ - return string.toUtf8(); -} - -QString -UtilsAdapter::getRecordQualityString(int value) -{ - return value ? QString::number(static_cast<float>(value) / 100, 'f', 1) + " Mbps" : "Default"; -} - -QString -UtilsAdapter::getCurrentPath() -{ - return QDir::currentPath(); -} - -QString -UtilsAdapter::stringSimplifier(QString input) -{ - return input.simplified(); -} - -QString -UtilsAdapter::toNativeSeparators(QString inputDir) -{ - return QDir::toNativeSeparators(inputDir); -} - -QString -UtilsAdapter::toFileInfoName(QString inputFileName) -{ - QFileInfo fi(inputFileName); - return fi.fileName(); -} - -QString -UtilsAdapter::toFileAbsolutepath(QString inputFileName) -{ - QFileInfo fi(inputFileName); - return fi.absolutePath(); -} - -QString -UtilsAdapter::getAbsPath(QString path) -{ - // Note: this function is used on urls returned from qml-FileDialogs which - // contain 'file:///' for reasons we don't understand. - // TODO: this logic can be refactored into the JamiFileDialog component. -#ifdef Q_OS_WIN - return path.replace(QRegExp("^file:\\/{2,3}"), "").replace("\n", "").replace("\r", ""); -#else - return path.replace(QRegExp("^file:\\/{2,3}"), "/").replace("\n", "").replace("\r", ""); -#endif -} - -QString -UtilsAdapter::fileName(const QString& path) -{ - QFileInfo fi(path); - return fi.fileName(); -} - -QString -UtilsAdapter::getExt(const QString& path) -{ - QFileInfo fi(path); - return fi.completeSuffix(); -} - -bool -UtilsAdapter::isImage(const QString& fileExt) -{ - return Utils::isImage(fileExt); -} - -QString -UtilsAdapter::humanFileSize(qint64 fileSize) -{ - return Utils::humanFileSize(fileSize); -} - -void -UtilsAdapter::setSystemTrayIconVisible(bool visible) -{ - systemTray_->setVisible(visible); -} +/*! + * Copyright (C) 2015-2020 by Savoir-faire Linux + * Author: Edric Ladent Milaret <edric.ladent-milaret@savoirfairelinux.com> + * Author: Andreas Traczyk <andreas.traczyk@savoirfairelinux.com> + * Author: Isa Nanic <isa.nanic@savoirfairelinux.com> + * Author: Mingrui Zhang <mingrui.zhang@savoirfairelinux.com> + * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> + * + * 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 3 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 <http://www.gnu.org/licenses/>. + */ + +#include "utilsadapter.h" + +#include "lrcinstance.h" +#include "systemtray.h" +#include "utils.h" +#include "version.h" + +#include "api/pluginmodel.h" + +#include <QApplication> +#include <QClipboard> +#include <QFileInfo> + +UtilsAdapter::UtilsAdapter(SystemTray* systemTray, LRCInstance* instance, QObject* parent) + : QmlAdapterBase(instance, parent) + , clipboard_(QApplication::clipboard()) + , systemTray_(systemTray) +{} + +const QString +UtilsAdapter::getProjectCredits() +{ + return Utils::getProjectCredits(); +} + +const QString +UtilsAdapter::getVersionStr() +{ + return QString(VERSION_STRING); +} + +void +UtilsAdapter::setClipboardText(QString text) +{ + clipboard_->setText(text, QClipboard::Clipboard); +} + +const QString +UtilsAdapter::qStringFromFile(const QString& filename) +{ + return Utils::QByteArrayFromFile(filename); +} + +const QString +UtilsAdapter::getStyleSheet(const QString& name, const QString& source) +{ + auto simplifiedCSS = source.simplified().replace("'", "\""); + QString s = QString::fromLatin1("(function() {" + " var node = document.createElement('style');" + " node.id = '%1';" + " node.innerHTML = '%2';" + " document.head.appendChild(node);" + "})()") + .arg(name) + .arg(simplifiedCSS); + return s; +} + +const QString +UtilsAdapter::getCachePath() +{ + QDir dataDir(QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation)); + dataDir.cdUp(); + return dataDir.absolutePath() + "/jami"; +} +bool +UtilsAdapter::createStartupLink() +{ + return Utils::CreateStartupLink(L"Jami"); +} + +QString +UtilsAdapter::GetRingtonePath() +{ + return Utils::GetRingtonePath(); +} + +bool +UtilsAdapter::checkStartupLink() +{ + return Utils::CheckStartupLink(L"Jami"); +} + +const QString +UtilsAdapter::getBestName(const QString& accountId, const QString& uid) +{ + const auto& conv = lrcInstance_->getConversationFromConvUid(uid); + if (!conv.participants.isEmpty()) + return lrcInstance_->getAccountInfo(accountId).contactModel->bestNameForContact( + conv.participants[0]); + return QString(); +} + +const QString +UtilsAdapter::getPeerUri(const QString& accountId, const QString& uid) +{ + try { + auto* convModel = lrcInstance_->getAccountInfo(accountId).conversationModel.get(); + const auto& convInfo = convModel->getConversationForUid(uid).value(); + return convInfo.get().participants.front(); + } catch (const std::out_of_range& e) { + qDebug() << e.what(); + return ""; + } +} + +QString +UtilsAdapter::getBestId(const QString& accountId) +{ + if (accountId.isEmpty()) + return {}; + return lrcInstance_->accountModel().bestIdForAccount(accountId); +} + +const QString +UtilsAdapter::getBestId(const QString& accountId, const QString& uid) +{ + const auto& conv = lrcInstance_->getConversationFromConvUid(uid); + if (!conv.participants.isEmpty()) + return lrcInstance_->getAccountInfo(accountId).contactModel->bestIdForContact( + conv.participants[0]); + return QString(); +} + +void +UtilsAdapter::setConversationFilter(const QString& filter) +{ + lrcInstance_->getCurrentConversationModel()->setFilter(filter); +} + +const QStringList +UtilsAdapter::getCurrAccList() +{ + return lrcInstance_->accountModel().getAccountList(); +} + +int +UtilsAdapter::getAccountListSize() +{ + return getCurrAccList().size(); +} + +bool +UtilsAdapter::hasCall(const QString& accountId) +{ + auto activeCalls = lrcInstance_->getActiveCalls(); + for (const auto& callId : activeCalls) { + auto& accountInfo = lrcInstance_->accountModel().getAccountInfo(accountId); + if (accountInfo.callModel->hasCall(callId)) { + return true; + } + } + return false; +} + +const QString +UtilsAdapter::getCallConvForAccount(const QString& accountId) +{ + // TODO: Currently returning first call, establish priority according to state? + for (const auto& callId : lrcInstance_->getActiveCalls()) { + auto& accountInfo = lrcInstance_->accountModel().getAccountInfo(accountId); + if (accountInfo.callModel->hasCall(callId)) { + return lrcInstance_->getConversationFromCallId(callId, accountId).uid; + } + } + return ""; +} + +const QString +UtilsAdapter::getCallId(const QString& accountId, const QString& convUid) +{ + auto const& convInfo = lrcInstance_->getConversationFromConvUid(convUid, accountId); + if (convInfo.uid.isEmpty()) { + return {}; + } + + if (auto* call = lrcInstance_->getCallInfoForConversation(convInfo, false)) { + return call->id; + } + + return {}; +} + +int +UtilsAdapter::getCallStatus(const QString& callId) +{ + const auto callStatus = lrcInstance_->getCallInfo(callId, lrcInstance_->get_currentAccountId()); + return static_cast<int>(callStatus->status); +} + +const QString +UtilsAdapter::getCallStatusStr(int statusInt) +{ + const auto status = static_cast<lrc::api::call::Status>(statusInt); + return lrc::api::call::to_string(status); +} + +// returns true if name is valid registered name +bool +UtilsAdapter::validateRegNameForm(const QString& regName) +{ + QRegularExpression regExp(" "); + + if (regName.size() > 2 && !regName.contains(regExp)) { + return true; + + } else { + return false; + } +} + +QString +UtilsAdapter::getStringUTF8(QString string) +{ + return string.toUtf8(); +} + +QString +UtilsAdapter::getRecordQualityString(int value) +{ + return value ? QString::number(static_cast<float>(value) / 100, 'f', 1) + " Mbps" : "Default"; +} + +QString +UtilsAdapter::getCurrentPath() +{ + return QDir::currentPath(); +} + +QString +UtilsAdapter::stringSimplifier(QString input) +{ + return input.simplified(); +} + +QString +UtilsAdapter::toNativeSeparators(QString inputDir) +{ + return QDir::toNativeSeparators(inputDir); +} + +QString +UtilsAdapter::toFileInfoName(QString inputFileName) +{ + QFileInfo fi(inputFileName); + return fi.fileName(); +} + +QString +UtilsAdapter::toFileAbsolutepath(QString inputFileName) +{ + QFileInfo fi(inputFileName); + return fi.absolutePath(); +} + +QString +UtilsAdapter::getAbsPath(QString path) +{ + // Note: this function is used on urls returned from qml-FileDialogs which + // contain 'file:///' for reasons we don't understand. + // TODO: this logic can be refactored into the JamiFileDialog component. +#ifdef Q_OS_WIN + return path.replace(QRegExp("^file:\\/{2,3}"), "").replace("\n", "").replace("\r", ""); +#else + return path.replace(QRegExp("^file:\\/{2,3}"), "/").replace("\n", "").replace("\r", ""); +#endif +} + +QString +UtilsAdapter::fileName(const QString& path) +{ + QFileInfo fi(path); + return fi.fileName(); +} + +QString +UtilsAdapter::getExt(const QString& path) +{ + QFileInfo fi(path); + return fi.completeSuffix(); +} + +bool +UtilsAdapter::isImage(const QString& fileExt) +{ + return Utils::isImage(fileExt); +} + +QString +UtilsAdapter::humanFileSize(qint64 fileSize) +{ + return Utils::humanFileSize(fileSize); +} + +void +UtilsAdapter::setSystemTrayIconVisible(bool visible) +{ + systemTray_->setVisible(visible); +}