diff --git a/applet/contents/ui/ConnectionItem.qml b/applet/contents/ui/ConnectionItem.qml --- a/applet/contents/ui/ConnectionItem.qml +++ b/applet/contents/ui/ConnectionItem.qml @@ -27,11 +27,13 @@ import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.networkmanagement 0.2 as PlasmaNM -PlasmaComponents.ListItem { +ListItem { id: connectionItem property bool activating: ConnectionState == PlasmaNM.Enums.Activating - property int baseHeight: Math.max(units.iconSizes.medium, connectionNameLabel.height + connectionStatusLabel.height) + Math.round(units.gridUnit / 2) + property bool deactivated: ConnectionState === PlasmaNM.Enums.Deactivated + property int baseHeight: Uuid ? connectionNameLabel.implicitHeight + connectionStatusLabel.implicitHeight + units.smallSpacing * 2 + : stateChangeButton.implicitHeight + units.smallSpacing * 2 property bool expanded: visibleDetails || visiblePasswordDialog property bool passwordIsStatic: (SecurityType == PlasmaNM.Enums.StaticWep || SecurityType == PlasmaNM.Enums.WpaPsk || SecurityType == PlasmaNM.Enums.Wpa2Psk || SecurityType == PlasmaNM.Enums.SAE) @@ -48,113 +50,126 @@ property real rxBytes: 0 property real txBytes: 0 - checked: connectionItem.containsMouse - enabled: true - height: expanded ? baseHeight + separator.height + expandableComponentLoader.height + (2 * Math.round(units.gridUnit / 3)) : baseHeight + height: expanded ? baseHeight + expandableComponentLoader.height + units.smallSpacing * (ConnectionState == PlasmaNM.Enums.Active ? 1 : Uuid ? 2 : 1) + : baseHeight + highlightRect: Qt.rect(mainColumn.x, mainColumn.y, mainColumn.width, baseHeight) ColumnLayout { + id: mainColumn anchors.fill: parent - RowLayout { + MouseArea { Layout.fillWidth: true - spacing: Math.round(units.gridUnit / 2) - - PlasmaCore.SvgItem { - id: connectionSvgIcon - Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft - Layout.preferredHeight: units.iconSizes.medium - Layout.preferredWidth: units.iconSizes.medium - elementId: ConnectionIcon - svg: PlasmaCore.Svg { - multipleImages: true - imagePath: "icons/network" - colorGroup: PlasmaCore.ColorScope.colorGroup - } + Layout.preferredHeight: mainRow.height + Layout.alignment: Qt.AlignTop + acceptedButtons: Qt.LeftButton | Qt.RightButton + hoverEnabled: true + + onEntered: { + connectionView.currentVisibleButtonIndex = index + connectionItem.checked = true } - ColumnLayout { - Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft - spacing: 0 + onExited: { + connectionItem.checked = false + } - PlasmaComponents.Label { - id: connectionNameLabel - Layout.fillWidth: true - height: paintedHeight - elide: Text.ElideRight - font.weight: ConnectionState == PlasmaNM.Enums.Activated ? Font.DemiBold : Font.Normal - font.italic: ConnectionState == PlasmaNM.Enums.Activating ? true : false - text: ItemUniqueName - textFormat: Text.PlainText + onPressed: { + if (mouse.button & Qt.LeftButton) { + changeExpanded() } - PlasmaComponents.Label { - id: connectionStatusLabel - Layout.fillWidth: true - height: paintedHeight - elide: Text.ElideRight - font.pointSize: theme.smallestFont.pointSize - opacity: 0.6 - text: itemText() + if (mouse.button & Qt.RightButton) { + contextMenu.visualParent = parent + contextMenu.prepare(); + contextMenu.open(mouse.x, mouse.y) } } - PlasmaComponents.BusyIndicator { - id: connectingIndicator - Layout.alignment: Qt.AlignVCenter | Qt.AlignRight - Layout.preferredHeight: units.iconSizes.medium - Layout.preferredWidth: units.iconSizes.medium - running: plasmoid.expanded && !stateChangeButton.visible && ConnectionState == PlasmaNM.Enums.Activating - visible: running - opacity: visible - } + RowLayout { + id: mainRow + spacing: units.smallSpacing * 2 + height: baseHeight + width: mainColumn.width + anchors { + left: parent.left + right: parent.right + leftMargin: units.smallSpacing + // Identical margins around the button. + rightMargin: Math.round((baseHeight - stateChangeButton.height) / 2) + } - PlasmaComponents.Button { - id: stateChangeButton - Layout.alignment: Qt.AlignVCenter | Qt.AlignRight - opacity: connectionView.currentVisibleButtonIndex == index ? 1 : 0 - visible: opacity != 0 - text: (ConnectionState == PlasmaNM.Enums.Deactivated) ? i18n("Connect") : i18n("Disconnect") + PlasmaCore.SvgItem { + id: connectionSvgIcon + Layout.preferredHeight: Uuid ? units.iconSizes.medium : units.iconSizes.smallMedium + Layout.preferredWidth: Layout.preferredHeight + Layout.leftMargin: units.smallSpacing + elementId: ConnectionIcon + svg: PlasmaCore.Svg { + multipleImages: true + imagePath: "icons/network" + colorGroup: PlasmaCore.ColorScope.colorGroup + } + } - Behavior on opacity { NumberAnimation { duration: units.shortDuration } } + // ColumnLayout with fillWidth in children, creates bind loop for width. + Column { + Layout.fillWidth: true + Layout.preferredHeight: connectionNameLabel.height + (connectionStatusLabel.visible ? connectionStatusLabel.height : 0) + spacing: 0 + + PlasmaComponents.Label { + id: connectionNameLabel + width: parent.width + elide: Text.ElideRight + height: undefined + font.weight: ConnectionState == PlasmaNM.Enums.Activated ? Font.DemiBold : Font.Normal + font.italic: ConnectionState == PlasmaNM.Enums.Activating ? true : false + text: ItemUniqueName + textFormat: Text.PlainText + } - onClicked: changeState() - } + PlasmaComponents.Label { + id: connectionStatusLabel + width: parent.width + elide: Text.ElideRight + height: undefined + font.pointSize: theme.smallestFont.pointSize + opacity: 0.6 + text: itemText() + visible: !!Uuid + } + } - MouseArea { - acceptedButtons: Qt.RightButton - Layout.alignment: Qt.AlignTop | Qt.AlignLeft - width: parent.width - height: parent.height - onPressed: { - contextMenu.visualParent = parent - contextMenu.prepare(); - contextMenu.open(mouse.x, mouse.y) + PlasmaComponents.BusyIndicator { + id: connectingIndicator + Layout.preferredHeight: units.iconSizes.medium + Layout.preferredWidth: Layout.preferredHeight + running: plasmoid.expanded && !stateChangeButton.visible && ConnectionState == PlasmaNM.Enums.Activating + visible: running + opacity: visible } - } - } - ColumnLayout { - Layout.fillHeight: true - PlasmaCore.SvgItem { - id: separator - height: lineSvg.elementSize("horizontal-line").height - Layout.fillWidth: true - Layout.maximumHeight: height - elementId: "horizontal-line" - svg: PlasmaCore.Svg { id: lineSvg; imagePath: "widgets/line" } - visible: connectionItem.expanded - opacity: visible - } + PlasmaComponents.Button { + id: stateChangeButton + opacity: connectionView.currentVisibleButtonIndex == index ? 1 : 0 + visible: opacity != 0 + text: (ConnectionState == PlasmaNM.Enums.Deactivated) ? i18n("Connect") : i18n("Disconnect") - Loader { - id: expandableComponentLoader - Layout.fillHeight: true - Layout.fillWidth: true - height: childrenRect.height + Behavior on opacity { NumberAnimation { duration: units.shortDuration } } + + onClicked: changeState() + } } } - } + Loader { + id: expandableComponentLoader + Layout.fillWidth: true + Layout.alignment: Qt.AlignBottom + Layout.bottomMargin: units.smallSpacing + } + } PlasmaComponents.Menu { id: contextMenu @@ -207,16 +222,15 @@ Component { id: detailsComponent - Item { - height: childrenRect.height + Column { + spacing: units.smallSpacing PlasmaComponents.TabBar { id: detailsTabBar anchors { left: parent.left right: parent.right - top: parent.top } height: visible ? implicitHeight : 0 visible: showSpeed @@ -241,10 +255,8 @@ DetailsText { anchors { left: parent.left - leftMargin: units.iconSizes.medium + leftMargin: units.iconSizes.smallMedium right: parent.right - top: detailsTabBar.visible ? detailsTabBar.bottom : parent.top - topMargin: Math.round(units.gridUnit / 3) } details: ConnectionDetails visible: detailsTabBar.currentTab == detailsTabButton @@ -254,8 +266,6 @@ anchors { left: parent.left right: parent.right - top: detailsTabBar.visible ? detailsTabBar.bottom : parent.top - topMargin: Math.round(units.gridUnit / 3) } rxBytes: RxBytes txBytes: TxBytes @@ -268,19 +278,15 @@ Component { id: passwordDialogComponent - Item { + ColumnLayout { property alias password: passwordField.text property alias passwordInput: passwordField - height: childrenRect.height - PasswordField { id: passwordField - anchors { - left: parent.left - right: parent.right - top: parent.top - } + Layout.leftMargin: units.iconSizes.smallMedium + units.smallSpacing * 2 + Layout.bottomMargin: units.smallSpacing + Layout.preferredWidth: units.gridUnit * 15 securityType: SecurityType onAccepted: { @@ -390,11 +396,8 @@ return VpnState else return DeviceState - } else if (ConnectionState == PlasmaNM.Enums.Deactivated) { - var result = LastUsed - if (SecurityType > PlasmaNM.Enums.NoneSecurity) - result += ", " + SecurityTypeString - return result + } else if (Uuid && ConnectionState == PlasmaNM.Enums.Deactivated) { + return LastUsed } else if (ConnectionState == PlasmaNM.Enums.Activated) { if (showSpeed) { var downloadColor = theme.highlightColor @@ -410,19 +413,10 @@ return i18n("Connected") } } + return "" } - onShowSpeedChanged: { - connectionModel.setDeviceStatisticsRefreshRateMs(DevicePath, showSpeed ? 2000 : 0) - } - - onActivatingChanged: { - if (ConnectionState == PlasmaNM.Enums.Activating) { - ListView.view.positionViewAtBeginning() - } - } - - onClicked: { + function changeExpanded() { if (visiblePasswordDialog) { appletProxyModel.dynamicSortFilter = true visiblePasswordDialog = false @@ -437,9 +431,33 @@ } } + onShowSpeedChanged: { + connectionModel.setDeviceStatisticsRefreshRateMs(DevicePath, showSpeed ? 2000 : 0) + } + + onActivatingChanged: { + if (ConnectionState == PlasmaNM.Enums.Activating) { + ListView.view.positionViewAtBeginning() + } + } + onContainsMouseChanged: { if (connectionItem.containsMouse) { connectionView.currentVisibleButtonIndex = index } } + + onDeactivatedChanged: { + /* Separator is part of section, which is visible only when available connections exist. Need to determine + if there is a connection in use, to show Separator. Otherwise need to hide it from the top of the list. + Connections in use are always on top, only need to check the first one. */ + if (appletProxyModel.data(appletProxyModel.index(0, 0), PlasmaNM.NetworkModel.SectionRole) !== "Available connections") { + if (connectionView.showSeparator != true) { + connectionView.showSeparator = true + } + return + } + connectionView.showSeparator = false + return + } } diff --git a/applet/contents/ui/DetailsText.qml b/applet/contents/ui/DetailsText.qml --- a/applet/contents/ui/DetailsText.qml +++ b/applet/contents/ui/DetailsText.qml @@ -73,6 +73,7 @@ font.pointSize: theme.smallestFont.pointSize horizontalAlignment: Text.AlignRight text: details[index*2] + ": " + opacity: 0.6 Component.onCompleted: { if (paintedWidth > repeater.longestString) { diff --git a/applet/contents/ui/Header.qml b/applet/contents/ui/Header.qml deleted file mode 100644 --- a/applet/contents/ui/Header.qml +++ /dev/null @@ -1,59 +0,0 @@ -/* - Copyright 2013-2017 Jan Grulich - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) version 3, or any - later version accepted by the membership of KDE e.V. (or its - successor approved by the membership of KDE e.V.), which shall - act as a proxy defined in Section 6 of version 3 of the license. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library. If not, see . -*/ - -import QtQuick 2.2 -import org.kde.plasma.components 2.0 as PlasmaComponents -import org.kde.plasma.core 2.0 as PlasmaCore -import org.kde.plasma.networkmanagement 0.2 as PlasmaNM - -PlasmaComponents.ListItem { - id: header - - property alias text: headerLabel.text - - height: headerLabel.height + units.gridUnit; width: parent.width - sectionDelegate: true - - PlasmaNM.EnabledConnections { - id: enabledConnections - } - - PlasmaComponents.Label { - id: headerLabel - - anchors.centerIn: parent - height: paintedHeight - font.weight: Font.DemiBold - } - - Component.onCompleted: { - if (header.text === i18n("Available connections")) { - connectionView.availableConnectionsVisible = true - } - } - - Component.onDestruction: { - connectionView.availableConnectionsVisible = false - } - - onVisibleChanged: { - connectionView.availableConnectionsVisible = visible - } -} diff --git a/applet/contents/ui/ListItem.qml b/applet/contents/ui/ListItem.qml new file mode 100644 --- /dev/null +++ b/applet/contents/ui/ListItem.qml @@ -0,0 +1,90 @@ +/* + Copyright 2010 Marco Martin + Copyright 2016 Jan Grulich + Copyright 2020 George Vogiatzis + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) version 3, or any + later version accepted by the membership of KDE e.V. (or its + successor approved by the membership of KDE e.V.), which shall + act as a proxy defined in Section 6 of version 3 of the license. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library. If not, see . +*/ + +import QtQuick 2.1 +import org.kde.plasma.core 2.0 as PlasmaCore + +/** + * Ignores the theme's listItem margins, and uses custom highlight(pressed) area. + * Could break some themes but the majority look fine. + * Also includes a separator to be used in sections. + */ +Item { + id: listItem + + signal clicked + + property alias containsMouse: itemMouse.containsMouse + property bool checked: false + property bool separator: false + property rect highlightRect: Qt.rect(0, 0, width, height) + + width: parent.width + + // Sections have spacing above but not below. Will use 2 of them below. + height: separator ? separatorLine.height + units.smallSpacing * 3 : parent.height + + PlasmaCore.Svg { + id: lineSvg + imagePath: "widgets/line" + } + PlasmaCore.SvgItem { + id: separatorLine + anchors { + horizontalCenter: parent.horizontalCenter + top: parent.top + topMargin: units.smallSpacing + } + elementId: "horizontal-line" + width: parent.width - units.gridUnit * 2 + svg: lineSvg + visible: separator + } + + PlasmaCore.FrameSvgItem { + id : background + imagePath: "widgets/listitem" + prefix: "normal" + anchors.fill: parent + visible: separator ? false : true + } + + PlasmaCore.FrameSvgItem { + id : pressed + imagePath: "widgets/listitem" + prefix: "pressed" + opacity: checked ? 1 : 0 + Behavior on opacity { NumberAnimation { duration: units.shortDuration } } + + x: highlightRect.x + y: highlightRect.y + height: highlightRect.height + width: highlightRect.width + } + + MouseArea { + id: itemMouse + anchors.fill: parent + hoverEnabled: true + onClicked: listItem.clicked() + } +} diff --git a/applet/contents/ui/PasswordField.qml b/applet/contents/ui/PasswordField.qml --- a/applet/contents/ui/PasswordField.qml +++ b/applet/contents/ui/PasswordField.qml @@ -25,7 +25,6 @@ PlasmaComponents.TextField { property int securityType - width: units.gridUnit * 15 echoMode: TextInput.Password revealPasswordButtonShown: true placeholderText: i18n("Password...") diff --git a/applet/contents/ui/PopupDialog.qml b/applet/contents/ui/PopupDialog.qml --- a/applet/contents/ui/PopupDialog.qml +++ b/applet/contents/ui/PopupDialog.qml @@ -102,16 +102,16 @@ ListView { id: connectionView - property bool availableConnectionsVisible: false property int currentVisibleButtonIndex: -1 + property bool showSeparator: false - anchors.fill: parent + spacing: units.smallSpacing clip: true model: appletProxyModel currentIndex: -1 boundsBehavior: Flickable.StopAtBounds - section.property: showSections ? "Section" : "" - section.delegate: Header { text: section } + section.property: showSeparator ? "Section" : "" + section.delegate: ListItem { separator: true } delegate: ConnectionItem { } } } diff --git a/applet/contents/ui/SwitchButton.qml b/applet/contents/ui/SwitchButton.qml --- a/applet/contents/ui/SwitchButton.qml +++ b/applet/contents/ui/SwitchButton.qml @@ -33,7 +33,7 @@ signal clicked height: Math.max(switchButtonCheckbox.height, switchButtonIcon.height) - width: switchButtonCheckbox.width + switchButtonIcon.width + units.gridUnit + width: switchButtonCheckbox.width + switchButtonIcon.width + units.smallSpacing * 3 PlasmaComponents.CheckBox { id: switchButtonCheckbox diff --git a/applet/contents/ui/Toolbar.qml b/applet/contents/ui/Toolbar.qml --- a/applet/contents/ui/Toolbar.qml +++ b/applet/contents/ui/Toolbar.qml @@ -26,8 +26,9 @@ import org.kde.plasma.networkmanagement 0.2 as PlasmaNM import org.kde.kquickcontrolsaddons 2.0 -GridLayout { +ColumnLayout { id: toolbar + spacing: units.smallSpacing readonly property var displayWifiMessage: !wifiSwitchButton.checked && wifiSwitchButton.visible readonly property var displayWwanMessage: !wwanSwitchButton.checked && wwanSwitchButton.visible @@ -37,9 +38,6 @@ searchToggleButton.checked = false } - rows: 2 - columns: 2 - PlasmaCore.Svg { id: lineSvg imagePath: "widgets/line" @@ -69,8 +67,8 @@ id: configuration } - Row { - Layout.fillWidth: true + RowLayout { + spacing: units.smallSpacing SwitchButton { id: wifiSwitchButton @@ -128,11 +126,10 @@ initialized = true } } - } - - Row { - Layout.column: 1 + Item { + Layout.fillWidth: true + } PlasmaComponents3.ToolButton { id: hotspotButton @@ -212,14 +209,21 @@ } } - PlasmaComponents.TextField { + PlasmaCore.SvgItem { + Layout.fillWidth: true + elementId: "horizontal-line" + Layout.leftMargin: - units.smallSpacing * 1.5 + Layout.rightMargin: - units.smallSpacing * 1.5 + svg: lineSvg + } + + PlasmaComponents.TextField { id: searchTextField - Layout.row: 1 - Layout.columnSpan: 2 Layout.fillWidth: true Layout.leftMargin: units.smallSpacing Layout.rightMargin: units.smallSpacing + Layout.topMargin: units.smallSpacing Layout.bottomMargin: units.smallSpacing focus: true diff --git a/applet/contents/ui/main.qml b/applet/contents/ui/main.qml --- a/applet/contents/ui/main.qml +++ b/applet/contents/ui/main.qml @@ -27,7 +27,6 @@ Item { id: mainWindow - property bool showSections: true readonly property string kcm: "kcm_networkmanagement.desktop" readonly property bool kcmAuthorized: KCMShell.authorize(kcm).length == 1 diff --git a/libs/models/networkmodel.h b/libs/models/networkmodel.h --- a/libs/models/networkmodel.h +++ b/libs/models/networkmodel.h @@ -71,6 +71,7 @@ RxBytesRole, TxBytesRole }; + Q_ENUMS(ItemRole) int rowCount(const QModelIndex &parent) const override; QVariant data(const QModelIndex &index, int role) const override; diff --git a/libs/models/networkmodelitem.cpp b/libs/models/networkmodelitem.cpp --- a/libs/models/networkmodelitem.cpp +++ b/libs/models/networkmodelitem.cpp @@ -327,10 +327,10 @@ QString NetworkModelItem::sectionType() const { - if (m_connectionState == NetworkManager::ActiveConnection::Activated) { - return i18n("Active connections"); + if (m_connectionState == NetworkManager::ActiveConnection::Deactivated) { + return "Available connections"; } else { - return i18n("Available connections"); + return QString(); } } @@ -585,9 +585,7 @@ if (m_mode == NetworkManager::WirelessSetting::Infrastructure) { m_details << i18n("Signal strength") << QStringLiteral("%1%").arg(m_signal); } - if (m_connectionState == NetworkManager::ActiveConnection::Activated) { - m_details << i18n("Security type") << UiUtils::labelFromWirelessSecurity(m_securityType); - } + m_details << i18n("Security type") << UiUtils::labelFromWirelessSecurity(m_securityType); if (wirelessDevice) { if (m_connectionState == NetworkManager::ActiveConnection::Activated) { m_details << i18n("Connection speed") << UiUtils::connectionSpeed(wirelessDevice->bitRate());