diff --git a/components/mobileshell/qml/actiondrawer/private/QuickSettings.qml b/components/mobileshell/qml/actiondrawer/private/QuickSettings.qml index e9d44909..6a5385a9 100644 --- a/components/mobileshell/qml/actiondrawer/private/QuickSettings.qml +++ b/components/mobileshell/qml/actiondrawer/private/QuickSettings.qml @@ -29,12 +29,12 @@ Item { required property QS.QuickSettingsModel quickSettingsModel - readonly property real columns: Math.round(Math.min(6, Math.max(ShellSettings.Settings.quickSettingsColumns, width / intendedColumnWidth))) - readonly property real columnWidth: Math.floor(width / columns) - readonly property int minimizedColumns: Math.round(Math.min(8, Math.max(5, width / intendedMinimizedColumnWidth))) - readonly property real minimizedColumnWidth: Math.floor(width / minimizedColumns) + readonly property int columns: Math.max(1, Math.round(Math.min(6, Math.max(ShellSettings.Settings.quickSettingsColumns, width / intendedColumnWidth)))) + readonly property real columnWidth: Math.max(1, Math.floor(width / columns)) + readonly property int minimizedColumns: Math.max(1, Math.round(Math.min(8, Math.max(5, width / intendedMinimizedColumnWidth)))) + readonly property real minimizedColumnWidth: Math.max(1, Math.floor(width / minimizedColumns)) - readonly property real rowHeight: columnWidth * 0.7 + readonly property real rowHeight: Math.max(1, columnWidth * 0.7) readonly property real fullHeight: fullView.implicitHeight readonly property real intendedColumnWidth: Kirigami.Units.gridUnit * 7 @@ -43,16 +43,17 @@ Item { property real fullViewProgress: 1 - readonly property int columnCount: Math.floor(width/columnWidth) + readonly property int columnCount: Math.max(1, Math.floor(width / columnWidth)) readonly property int rowCount: { let totalRows = Math.ceil(quickSettingsCount / columnCount); let maxRows = root.isConvergence ? 3 : 5; // more than 5 is just disorienting - let targetRows = Math.floor(Window.height * (root.isConvergence ? 0.42 : 0.65) / rowHeight); + let targetRows = Math.max(1, Math.floor(Window.height * (root.isConvergence ? 0.42 : 0.65) / rowHeight)); return Math.max(1, Math.min(maxRows, Math.min(totalRows, targetRows))); } - readonly property int pageSize: rowCount * columnCount - readonly property int quickSettingsCount: quickSettingsModel.count + readonly property int pageSize: Math.max(1, rowCount * columnCount) + readonly property int quickSettingsCount: Math.max(0, quickSettingsModel.count) + readonly property int pageCount: Math.max(1, Math.ceil(quickSettingsCount / pageSize)) // Management tiles — promoted to full-width status rows in convergence. readonly property var __managementCommands: ({ @@ -279,7 +280,7 @@ Item { Layout.maximumHeight: visible ? rowCount * rowHeight : 0 Repeater { - model: Math.ceil(quickSettingsCount / pageSize) + model: root.isConvergence ? 0 : root.pageCount delegate: Flow { id: flow spacing: 0 diff --git a/components/mobileshell/qml/actiondrawer/private/QuickSettingsDelegate.qml b/components/mobileshell/qml/actiondrawer/private/QuickSettingsDelegate.qml index 908da0a7..6bcfecf7 100644 --- a/components/mobileshell/qml/actiondrawer/private/QuickSettingsDelegate.qml +++ b/components/mobileshell/qml/actiondrawer/private/QuickSettingsDelegate.qml @@ -26,7 +26,6 @@ MobileShell.BaseItem { required property string text required property string status required property string icon - required property bool enabled required property string settingsCommand required property var toggleFunction diff --git a/components/mobileshell/qml/actiondrawer/private/QuickSettingsStatusRow.qml b/components/mobileshell/qml/actiondrawer/private/QuickSettingsStatusRow.qml index 887afbf0..0729f8dc 100644 --- a/components/mobileshell/qml/actiondrawer/private/QuickSettingsStatusRow.qml +++ b/components/mobileshell/qml/actiondrawer/private/QuickSettingsStatusRow.qml @@ -18,7 +18,6 @@ Item { required property string text required property string status required property string icon - required property bool enabled required property var toggleFunction property bool compact: false diff --git a/components/mobileshell/qml/popups/volumeosd/ListItemBase.qml b/components/mobileshell/qml/popups/volumeosd/ListItemBase.qml index 240f91e6..bf6b94ff 100644 --- a/components/mobileshell/qml/popups/volumeosd/ListItemBase.qml +++ b/components/mobileshell/qml/popups/volumeosd/ListItemBase.qml @@ -32,12 +32,19 @@ Controls.AbstractButton { property string type // sink, source, source-output property bool onlyOne: false + property bool useVolumeObject: true // Whether this item is selected readonly property bool supportsSelection: (baseItem.type == "sink" || baseItem.type == "source") - readonly property bool selected: supportsSelection && (model.PulseObject.hasOwnProperty("default") ? model.PulseObject.default : false) + readonly property bool hasPulseObject: model.PulseObject !== null && model.PulseObject !== undefined + readonly property bool hasVolumeObject: useVolumeObject && hasPulseObject + readonly property bool selected: supportsSelection && hasPulseObject && (model.PulseObject.hasOwnProperty("default") ? model.PulseObject.default : false) onClicked: { + if (!hasPulseObject || !model.PulseObject.hasOwnProperty("default")) { + return; + } + // Set as the default audio device model.PulseObject.default = true } @@ -175,7 +182,7 @@ Controls.AbstractButton { visible: model.HasVolume !== false // Devices always have volume but Streams don't necessarily enabled: model.VolumeWritable muted: model.Muted - volumeObject: model.PulseObject + volumeObject: baseItem.hasVolumeObject ? model.PulseObject : null activeFocusOnTab: false // access from delegate value: to, model.Volume @@ -215,7 +222,7 @@ Controls.AbstractButton { } PlasmaComponents.Label { id: percentText - readonly property real value: model.PulseObject.volume > slider.to ? model.PulseObject.volume : slider.value + readonly property real value: baseItem.hasVolumeObject && model.PulseObject.volume > slider.to ? model.PulseObject.volume : slider.value readonly property real displayValue: Math.round(value / PulseAudio.NormalVolume * 100.0) Layout.alignment: Qt.AlignHCenter Layout.minimumWidth: percentMetrics.advanceWidth diff --git a/components/mobileshell/qml/popups/volumeosd/StreamListItem.qml b/components/mobileshell/qml/popups/volumeosd/StreamListItem.qml index f066e6c4..1d87807e 100644 --- a/components/mobileshell/qml/popups/volumeosd/StreamListItem.qml +++ b/components/mobileshell/qml/popups/volumeosd/StreamListItem.qml @@ -15,6 +15,7 @@ ListItemBase { property QtObject devicesModel readonly property bool isEventStream: Name == "sink-input-by-media-role:event" + useVolumeObject: !isEventStream label: { if (isEventStream) { diff --git a/components/mobileshell/qml/popups/volumeosd/VolumeChangedPopup.qml b/components/mobileshell/qml/popups/volumeosd/VolumeChangedPopup.qml index ef052ec8..0998856a 100644 --- a/components/mobileshell/qml/popups/volumeosd/VolumeChangedPopup.qml +++ b/components/mobileshell/qml/popups/volumeosd/VolumeChangedPopup.qml @@ -157,11 +157,13 @@ Window { anchors.leftMargin: Kirigami.Units.smallSpacing * 2 anchors.rightMargin: Kirigami.Units.smallSpacing - property int volumePercent: PreferredDevice.sink.volume / PulseAudio.NormalVolume * 100.0 + readonly property bool hasSink: PreferredDevice.sink !== null + property int volumePercent: hasSink ? PreferredDevice.sink.volume / PulseAudio.NormalVolume * 100.0 : 0 PlasmaComponents.ToolButton { - icon.name: !PreferredDevice.sink || (PreferredDevice.sink.muted ? "audio-volume-muted" : MobileShell.AudioInfo.icon) - text: !PreferredDevice.sink || (PreferredDevice.sink.muted ? i18n("Unmute") : i18n("Mute")) + enabled: containerLayout.hasSink + icon.name: containerLayout.hasSink ? (PreferredDevice.sink.muted ? "audio-volume-muted" : MobileShell.AudioInfo.icon) : "audio-volume-muted" + text: containerLayout.hasSink && PreferredDevice.sink.muted ? i18n("Unmute") : i18n("Mute") display: Controls.AbstractButton.IconOnly Layout.alignment: Qt.AlignVCenter Layout.preferredWidth: Kirigami.Units.iconSizes.medium @@ -169,6 +171,9 @@ Window { Layout.rightMargin: Kirigami.Units.smallSpacing onClicked: { + if (!containerLayout.hasSink) { + return; + } hideTimer.restart(); PreferredDevice.sink.muted = !PreferredDevice.sink.muted; } @@ -185,11 +190,15 @@ Window { to: PulseAudio.NormalVolume stepSize: to / (to / PulseAudio.NormalVolume * 100.0) - volumeObject: PreferredDevice.sink - muted: PreferredDevice.sink.muted - value: PreferredDevice.sink.volume + enabled: containerLayout.hasSink + volumeObject: containerLayout.hasSink ? PreferredDevice.sink : null + muted: containerLayout.hasSink ? PreferredDevice.sink.muted : false + value: containerLayout.hasSink ? PreferredDevice.sink.volume : PulseAudio.MinimalVolume onMoved: { + if (!containerLayout.hasSink) { + return; + } PreferredDevice.sink.volume = value; PreferredDevice.sink.muted = value === 0; } @@ -202,7 +211,7 @@ Window { // Otherwise it might be that the slider is at v10 // whereas PA rejected the volume change and is // still at v15 (e.g.). - value = Qt.binding(() => PreferredDevice.sink.volume); + value = Qt.binding(() => containerLayout.hasSink ? PreferredDevice.sink.volume : PulseAudio.MinimalVolume); hideTimer.restart(); } } diff --git a/components/mobileshell/qml/popups/volumeosd/VolumeOSD.qml b/components/mobileshell/qml/popups/volumeosd/VolumeOSD.qml index c07a0e65..79ccdb61 100644 --- a/components/mobileshell/qml/popups/volumeosd/VolumeOSD.qml +++ b/components/mobileshell/qml/popups/volumeosd/VolumeOSD.qml @@ -201,7 +201,7 @@ Window { } PlasmaComponents.Label { text: i18n("Open audio settings") - anchors.verticalCenter: parent.verticalCenter + Layout.alignment: Qt.AlignVCenter } } } diff --git a/components/quicksettingsplugin/paginatemodel.cpp b/components/quicksettingsplugin/paginatemodel.cpp index 704ce29c..6cda643d 100644 --- a/components/quicksettingsplugin/paginatemodel.cpp +++ b/components/quicksettingsplugin/paginatemodel.cpp @@ -119,7 +119,7 @@ QHash PaginateModel::roleNames() const int PaginateModel::rowsByPageSize(int size) const { - return d->m_hasStaticRowCount ? size : !d->m_sourceModel ? 0 : qMin(d->m_sourceModel->rowCount() - d->m_firstItem, size); + return d->m_hasStaticRowCount ? qMax(size, 0) : !d->m_sourceModel ? 0 : qMax(qMin(d->m_sourceModel->rowCount() - d->m_firstItem, size), 0); } int PaginateModel::rowCount(const QModelIndex &parent) const