diff --git a/qml.qrc b/qml.qrc index e65945edecf4a9406861886556b0dcac84f3839b..f0cf552c3f5a99be69e2adafb5fc2517d6e5a45f 100644 --- a/qml.qrc +++ b/qml.qrc @@ -144,5 +144,7 @@ <file>src/commoncomponents/contextmenu/BaseContextMenu.qml</file> <file>src/commoncomponents/contextmenu/GeneralMenuItem.qml</file> <file>src/commoncomponents/contextmenu/GeneralMenuSeparator.qml</file> + <file>src/mainview/components/ParticipantOverlayButton.qml</file> + <file>src/mainview/components/ParticipantControlLayout.qml</file> </qresource> </RCC> diff --git a/src/mainview/components/ParticipantControlLayout.qml b/src/mainview/components/ParticipantControlLayout.qml new file mode 100644 index 0000000000000000000000000000000000000000..e41bd249db7357d4c6bd781836f379447919165d --- /dev/null +++ b/src/mainview/components/ParticipantControlLayout.qml @@ -0,0 +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 2.14 +import QtQuick.Layouts 1.14 + +import net.jami.Adapters 1.0 +import net.jami.Constants 1.0 + +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: "qrc:/images/icons/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? "qrc:/images/icons/mic-24px.svg" + : "qrc:/images/icons/mic_off-24px.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: "qrc:/images/icons/open_in_full-24px.svg" + onClicked: CallAdapter.maximizeParticipant(uri) + toolTipText: JamiStrings.maximizeParticipant + } + + ParticipantOverlayButton { + id: minimizeParticipant + + visible: showMinimize + preferredSize: iconButtonPreferredSize + Layout.preferredHeight: buttonPreferredSize + Layout.preferredWidth: buttonPreferredSize + source: "qrc:/images/icons/close_fullscreen-24px.svg" + onClicked: CallAdapter.minimizeParticipant(uri) + toolTipText: JamiStrings.minimizeParticipant + } + + ParticipantOverlayButton { + id: hangupParticipant + + visible: showHangup + preferredSize: iconButtonPreferredSize + Layout.preferredHeight: buttonPreferredSize + Layout.preferredWidth: buttonPreferredSize + source: "qrc:/images/icons/ic_hangup_participant-24px.svg" + onClicked: CallAdapter.hangupParticipant(uri) + toolTipText: JamiStrings.hangupParticipant + } +} diff --git a/src/mainview/components/ParticipantOverlay.qml b/src/mainview/components/ParticipantOverlay.qml index ea6004d1f0a035f6f8255758743ba53ff12ed5fe..cb64ddd700d29300f50c7069c3d626826000647d 100644 --- a/src/mainview/components/ParticipantOverlay.qml +++ b/src/mainview/components/ParticipantOverlay.qml @@ -49,7 +49,6 @@ Item { property bool participantIsModerator: false property bool participantIsMuted: false property bool participantIsModeratorMuted: false - property bool participantMenuActive: false z: 1 diff --git a/src/mainview/components/ParticipantOverlayButton.qml b/src/mainview/components/ParticipantOverlayButton.qml new file mode 100644 index 0000000000000000000000000000000000000000..3b7822612f9595b2f580a6700fbfe4858b16d2e4 --- /dev/null +++ b/src/mainview/components/ParticipantOverlayButton.qml @@ -0,0 +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.14 + +import net.jami.Constants 1.0 + +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/mainview/components/ParticipantOverlayMenu.qml b/src/mainview/components/ParticipantOverlayMenu.qml index 2535724a9c56ff6137e6e9808a5ced3e8475ce12..ccc4c0dc142b68492b26ab0b17459cfaca689677 100644 --- a/src/mainview/components/ParticipantOverlayMenu.qml +++ b/src/mainview/components/ParticipantOverlayMenu.qml @@ -18,9 +18,7 @@ import QtQuick 2.14 import QtQuick.Controls 2.14 -import QtGraphicalEffects 1.14 import QtQuick.Layouts 1.14 -import QtQuick.Shapes 1.14 import net.jami.Adapters 1.0 import net.jami.Models 1.0 @@ -29,7 +27,7 @@ import net.jami.Constants 1.0 import "../../commoncomponents" // Overlay menu for conference moderation -Control { +Item { id: root property string uri: "" @@ -43,342 +41,128 @@ Control { property bool showMinimize: false property bool showHangup: false + property int shapeHeight: 30 + property int shapeRadius: 8 + + property bool isBarLayout: root.width > 220 + property int isSmall: !isBarLayout && (root.height < 100 || root.width < 160) + property int buttonPreferredSize: 24 property int iconButtonPreferredSize: 16 - property int visibleButtons: toggleModerator.visible - + toggleMute.visible - + maximizeParticipant.visible - + minimizeParticipant.visible - + hangupParticipant.visible + property bool hovered: false - property int buttonsSize: visibleButtons * 24 + 8 * 2 + anchors.fill: parent - property int shapeWidth: bestNameLabel.contentWidth + (visibleButtons > 0 - ? buttonsSize : 0) + 32 - property int shapeHeight: 30 - property int shapeRadius: 8 - property string pathShape: "M0,0 h%1 v%2 q0,%3 -%3,%3 h-%4 z" - .arg(shapeWidth).arg(shapeHeight-shapeRadius).arg(shapeRadius). - arg(shapeWidth-shapeRadius) + Loader { sourceComponent: isBarLayout ? barComponent : rectComponent } - property bool isBarLayout: parent.width > 220 - property bool isOverlayRect: buttonsSize + 32 > parent.width + TextMetrics { + id: nameTextMetrics + text: bestName + font.pointSize: JamiTheme.participantFontSize + } - property int labelMaxWidth: isBarLayout? Math.max(parent.width - buttonsSize, 80) - : visibleButtons > 0? buttonsSize - : parent.width - 16 + Component { + id: rectComponent - property int isSmall: !isBarLayout && (height < 100 || width < 160) + Control { + width: root.width + height: root.height - width: isBarLayout? bestNameLabel.contentWidth + buttonsSize + 32 - : (isOverlayRect? buttonsSize + 32 : parent.width) - height: isBarLayout? shapeHeight : (isOverlayRect? 80 : parent.height) + onHoveredChanged: root.hovered = hovered - anchors.top: isBarLayout? parent.top : undefined - anchors.left: isBarLayout? parent.left : undefined - anchors.centerIn: isBarLayout? undefined : parent + background: Rectangle { + property int buttonsSize: buttonsRect.visibleButtons * 24 + 8 * 2 + property bool isOverlayRect: buttonsSize + 32 > root.width - background: Rectangle { - color: isBarLayout? "transparent" : JamiTheme.darkGreyColorOpacity - radius: (isBarLayout || !isOverlayRect)? 0 : 10 - } + color: JamiTheme.darkGreyColorOpacity + radius: isOverlayRect ? 10 : 0 - Item { - anchors.fill: parent - - Shape { - id: myShape - visible: isBarLayout - ShapePath { - id: backgroundShape - strokeColor: "transparent" - fillColor: JamiTheme.darkGreyColorOpacity - capStyle: ShapePath.RoundCap - PathSvg { path: pathShape } + anchors.fill: isOverlayRect ? undefined : parent + anchors.centerIn: parent + width: isOverlayRect ? buttonsSize + 32 : parent.width + height: isOverlayRect ? 80 : parent.height } - } - Text { - id: bestNameLabel - anchors { - left: isBarLayout? parent.left : undefined - leftMargin: isBarLayout? 8 : 0 - bottom: isBarLayout? parent.bottom : undefined - bottomMargin: isBarLayout? 8 : 0 - horizontalCenter: isBarLayout? undefined : parent.horizontalCenter - verticalCenter: parent.verticalCenter - verticalCenterOffset: - (isBarLayout || visibleButtons === 0)? 0 : (isSmall? -12 : -16) - } - TextMetrics { - id: participantMetricsColumn - text: bestName - elide: Text.ElideRight - elideWidth: labelMaxWidth - } + ColumnLayout { + + anchors.centerIn: parent + + Text { + id: bestNameLabel - text: participantMetricsColumn.elidedText - color: JamiTheme.whiteColor - font.pointSize: JamiTheme.participantFontSize - horizontalAlignment: isBarLayout? Text.AlignLeft : Text.AlignHCenter - verticalAlignment: Text.AlignVCenter + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + Layout.preferredWidth: Math.min(nameTextMetrics.boundingRect.width + 8, + root.width - 16) + Layout.preferredHeight: shapeHeight + + text: bestName + elide: Text.ElideRight + color: JamiTheme.whiteColor + font.pointSize: JamiTheme.participantFontSize + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter + } + ParticipantControlLayout { + id: buttonsRect + + Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter + Layout.preferredWidth: implicitWidth + Layout.preferredHeight: shapeHeight + } + } } + } - Rectangle { - color: "transparent" - width: buttonsSize + Component { + id: barComponent + + Control { + width: rowLayout.implicitWidth height: shapeHeight - anchors { - right: isBarLayout? parent.right : undefined - rightMargin: isBarLayout? 8 : 0 - horizontalCenter: isBarLayout? undefined : parent.horizontalCenter - verticalCenter: parent.verticalCenter - verticalCenterOffset: isBarLayout? 0 : (isSmall? 12 : 16) + + onHoveredChanged: root.hovered = hovered + + background: Item { + clip: true + Rectangle { + color: JamiTheme.darkGreyColorOpacity + radius: shapeRadius + width: parent.width + radius + height: parent.height + radius + anchors.fill: parent + anchors.leftMargin: -radius + anchors.topMargin: -radius + } } RowLayout { - id: rowLayoutButtons - anchors.centerIn: parent - anchors.fill: parent - - PushButton { - id: toggleModerator - - visible: (showSetModerator || showUnsetModerator) - Layout.preferredWidth: buttonPreferredSize - Layout.preferredHeight: buttonPreferredSize - preferredSize: iconButtonPreferredSize - normalColor: JamiTheme.buttonConference - hoveredColor: JamiTheme.buttonConferenceHovered - pressedColor: JamiTheme.buttonConferencePressed - - source: "qrc:/images/icons/moderator.svg" - imageColor: JamiTheme.whiteColor - - onClicked: CallAdapter.setModerator(uri, showSetModerator) - onHoveredChanged: - toggleModeratorToolTip.visible = hovered && !isSmall - - Rectangle { - id: toggleModeratorToolTip - height: 16 - width: toggleModeratorToolTipText.width + 8 - anchors { - horizontalCenter: parent.horizontalCenter - top: parent.bottom - topMargin: isBarLayout? 6 : 2 - } - color : isBarLayout? JamiTheme.darkGreyColorOpacity - : "transparent" - visible: false - radius: 2 - - Text { - id: toggleModeratorToolTipText - anchors.centerIn: parent - text: showSetModerator? JamiStrings.setModerator - : JamiStrings.unsetModerator - horizontalAlignment: Text.AlignHCenter - color: JamiTheme.whiteColor - font.pointSize: JamiTheme.tinyFontSize - } - } - } + id: rowLayout - PushButton { - id: toggleMute - - visible: showModeratorMute || showModeratorUnmute - Layout.preferredWidth: buttonPreferredSize - Layout.preferredHeight: buttonPreferredSize - Layout.alignment: Qt.AlignVCenter - preferredSize: iconButtonPreferredSize - - normalColor: JamiTheme.buttonConference - hoveredColor: JamiTheme.buttonConferenceHovered - pressedColor: JamiTheme.buttonConferencePressed - - source: showModeratorMute? "qrc:/images/icons/mic-24px.svg" - : "qrc:/images/icons/mic_off-24px.svg" - imageColor: JamiTheme.whiteColor - - onClicked: CallAdapter.muteParticipant(uri, showModeratorMute) - onHoveredChanged: - toggleMuteToolTip.visible = hovered && !isSmall - - Rectangle { - id: toggleMuteToolTip - height: localMutedText.visible? 28 : 16 - width: localMutedText.visible? localMutedText.width + 8 - : toggleMuteToolTipText.width + 8 - anchors { - horizontalCenter: parent.horizontalCenter - top: parent.bottom - topMargin: isBarLayout? 6 : 2 - } - color : isBarLayout? JamiTheme.darkGreyColorOpacity - : "transparent" - visible: false - radius: 2 - - Text { - id: toggleMuteToolTipText - text: (showModeratorMute? JamiStrings.muteParticipant - : JamiStrings.unmuteParticipant) - horizontalAlignment: Text.AlignHCenter - anchors { - horizontalCenter: parent.horizontalCenter - top: parent.top - } - - color: JamiTheme.whiteColor - font.pointSize: JamiTheme.tinyFontSize - } - - Text { - id: localMutedText - visible: isLocalMuted - text: "(" + JamiStrings.localMuted + ")" - horizontalAlignment: Text.AlignHCenter - anchors { - top: toggleMuteToolTipText.bottom - horizontalCenter: parent.horizontalCenter - } - color: JamiTheme.whiteColor - font.pointSize: JamiTheme.tinyFontSize - } - } - } + spacing: 8 - PushButton { - id: maximizeParticipant - - visible: showMaximize - Layout.preferredWidth: buttonPreferredSize - Layout.preferredHeight: buttonPreferredSize - preferredSize: iconButtonPreferredSize - - normalColor: JamiTheme.buttonConference - hoveredColor: JamiTheme.buttonConferenceHovered - pressedColor: JamiTheme.buttonConferencePressed - - source: "qrc:/images/icons/open_in_full-24px.svg" - imageColor: JamiTheme.whiteColor - - onClicked: CallAdapter.maximizeParticipant(uri) - onHoveredChanged: - maximizeParticipantToolTip.visible = hovered && !isSmall - - Rectangle { - id: maximizeParticipantToolTip - height: 16 - width: maximizeParticipantToolTipText.width + 8 - anchors { - horizontalCenter: parent.horizontalCenter - top: parent.bottom - topMargin: isBarLayout? 6 : 2 - } - color : isBarLayout? JamiTheme.darkGreyColorOpacity - : "transparent" - visible: false - radius: 2 - - Text { - id: maximizeParticipantToolTipText - text: JamiStrings.maximizeParticipant - horizontalAlignment: Text.AlignHCenter - anchors.centerIn: parent - color: JamiTheme.whiteColor - font.pointSize: JamiTheme.tinyFontSize - } - } - } + Text { + id: bestNameLabel + + Layout.leftMargin: 8 + Layout.preferredWidth: Math.min(nameTextMetrics.boundingRect.width + 8, + root.width - buttonsRect.implicitWidth - 16) + Layout.preferredHeight: shapeHeight - PushButton { - id: minimizeParticipant - - visible: showMinimize - Layout.preferredWidth: buttonPreferredSize - Layout.preferredHeight: buttonPreferredSize - preferredSize: iconButtonPreferredSize - - normalColor: JamiTheme.buttonConference - hoveredColor: JamiTheme.buttonConferenceHovered - pressedColor: JamiTheme.buttonConferencePressed - - source: "qrc:/images/icons/close_fullscreen-24px.svg" - imageColor: JamiTheme.whiteColor - onClicked: CallAdapter.minimizeParticipant(uri) - onHoveredChanged: - minimizeParticipantToolTip.visible = hovered && !isSmall - - Rectangle { - id: minimizeParticipantToolTip - height: 16 - width: minimizeParticipantToolTipText.width + 8 - anchors { - horizontalCenter: parent.horizontalCenter - top: parent.bottom - topMargin: isBarLayout? 6 : 2 - } - color : isBarLayout? JamiTheme.darkGreyColorOpacity - : "transparent" - visible: false - radius: 2 - - Text { - id: minimizeParticipantToolTipText - text: JamiStrings.minimizeParticipant - horizontalAlignment: Text.AlignHCenter - anchors.centerIn: parent - color: JamiTheme.whiteColor - font.pointSize: JamiTheme.tinyFontSize - } - } + text: bestName + elide: Text.ElideRight + color: JamiTheme.whiteColor + font.pointSize: JamiTheme.participantFontSize + horizontalAlignment: Text.AlignLeft + verticalAlignment: Text.AlignVCenter } - PushButton { - id: hangupParticipant - - visible: showHangup - Layout.preferredWidth: buttonPreferredSize - Layout.preferredHeight: buttonPreferredSize - preferredSize: iconButtonPreferredSize - - normalColor: JamiTheme.buttonConference - hoveredColor: JamiTheme.buttonConferenceHovered - pressedColor: JamiTheme.buttonConferencePressed - - source: "qrc:/images/icons/ic_hangup_participant-24px.svg" - imageColor: JamiTheme.whiteColor - onClicked: CallAdapter.hangupParticipant(uri) - onHoveredChanged: - hangupParticipantToolTip.visible = hovered && !isSmall - - Rectangle { - id: hangupParticipantToolTip - height: 16 - width: hangupParticipantToolTipText.width + 8 - anchors { - horizontalCenter: parent.horizontalCenter - top: parent.bottom - topMargin: isBarLayout? 6 : 2 - } - color : isBarLayout? JamiTheme.darkGreyColorOpacity - : "transparent" - visible: false - radius: 2 - - Text { - id: hangupParticipantToolTipText - text: JamiStrings.hangupParticipant - horizontalAlignment: Text.AlignHCenter - anchors.centerIn: parent - color: JamiTheme.whiteColor - font.pointSize: JamiTheme.tinyFontSize - } - } + ParticipantControlLayout { + id: buttonsRect + + Layout.rightMargin: 8 + Layout.preferredWidth: implicitWidth + Layout.preferredHeight: shapeHeight } } }