OmniControl: add qs settings grid item
Change-Id: I540eb2359c83dc3bcd789b982802624a79b48976
diff --git a/.idea/misc.xml b/.idea/misc.xml
index b7a738d..753add3 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -28,6 +28,8 @@
<entry key="app/src/main/res/drawable/ic_launcher_background.xml" value="0.3067708333333333" />
<entry key="app/src/main/res/drawable/ic_launcher_foreground.xml" value="0.2869791666666667" />
<entry key="app/src/main/res/drawable/ic_lockscreen_tile.xml" value="0.5130208333333334" />
+ <entry key="app/src/main/res/drawable/ic_qs_tile.xml" value="0.4231111111111111" />
+ <entry key="app/src/main/res/drawable/ic_quickbar.xml" value="0.4231111111111111" />
<entry key="app/src/main/res/drawable/ic_remote.xml" value="0.4436936936936937" />
<entry key="app/src/main/res/drawable/ic_settings_buttons.xml" value="0.3078125" />
<entry key="app/src/main/res/drawable/ic_settings_leds.xml" value="4.979166666666667E15" />
diff --git a/app/src/main/java/org/omnirom/control/GridViewFragment.kt b/app/src/main/java/org/omnirom/control/GridViewFragment.kt
index cb9777f..0054a7d 100644
--- a/app/src/main/java/org/omnirom/control/GridViewFragment.kt
+++ b/app/src/main/java/org/omnirom/control/GridViewFragment.kt
@@ -126,6 +126,14 @@
OverlaysFragment()
)
)
+ gridItems.add(
+ FragmentGridItem(
+ R.string.qs_settings_title,
+ R.string.qs_settings_summary,
+ R.drawable.ic_qs_tile,
+ QSSettingsFragment()
+ )
+ )
if (Utils.isAvailableApp(requireContext(), "org.omnirom.omnistyle")) {
val intent = Intent()
intent.component = ComponentName(
diff --git a/app/src/main/java/org/omnirom/control/QSSettingsFragment.kt b/app/src/main/java/org/omnirom/control/QSSettingsFragment.kt
new file mode 100644
index 0000000..bb4ce2e
--- /dev/null
+++ b/app/src/main/java/org/omnirom/control/QSSettingsFragment.kt
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2021 The OmniROM Project
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) 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/>.
+ *
+ */
+package org.omnirom.control
+
+import android.os.Bundle
+import android.provider.Settings
+import androidx.preference.Preference
+import org.omnirom.omnilib.preference.SeekBarPreference
+
+
+class QSSettingsFragment : AbstractSettingsFragment() {
+
+ override fun getFragmentTitle(): String {
+ return resources.getString(R.string.qs_settings_title)
+ }
+
+ override fun getFragmentSummary(): String {
+ return resources.getString(R.string.qs_settings_summary)
+ }
+
+ override fun getFragmentIcon(): Int {
+ return R.drawable.ic_qs_tile
+ }
+
+ override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
+ setPreferencesFromResource(R.xml.qs_settings_preferences, rootKey)
+
+ val pm = requireContext().packageManager
+ val resources = pm.getResourcesForApplication("com.android.systemui")
+
+ var defPortraitColumns = 2
+ val portraitColumns = findPreference<SeekBarPreference>("qs_layout_columns")
+ if (portraitColumns != null) {
+ var id =
+ resources.getIdentifier(
+ "quick_settings_num_columns",
+ "integer",
+ "com.android.systemui"
+ )
+ if (id != 0) {
+ defPortraitColumns = resources.getInteger(id)
+ }
+ val settingsPortraitColumns = Settings.System.getInt(
+ requireContext().contentResolver, Settings.System.OMNI_QS_LAYOUT_COLUMNS,
+ defPortraitColumns
+ )
+ portraitColumns.setValue(settingsPortraitColumns)
+ portraitColumns.onPreferenceChangeListener =
+ Preference.OnPreferenceChangeListener { _, newValue ->
+ Settings.System.putInt(
+ requireContext().contentResolver, Settings.System.OMNI_QS_LAYOUT_COLUMNS,
+ newValue as Int
+ )
+ true
+ }
+ }
+ val landscapeColumns = findPreference<SeekBarPreference>("qs_layout_columns_landscape")
+ if (landscapeColumns != null) {
+ var defLandspaceColumns = defPortraitColumns
+ var id =
+ resources.getIdentifier(
+ "quick_settings_num_columns_landscape",
+ "integer",
+ "com.android.systemui"
+ )
+ if (id != 0) {
+ defLandspaceColumns = resources.getInteger(id)
+ }
+ val settingsLandscapeColumns = Settings.System.getInt(
+ requireContext().contentResolver, Settings.System.OMNI_QS_LAYOUT_COLUMNS_LANDSCAPE,
+ defLandspaceColumns
+ )
+ landscapeColumns.setValue(settingsLandscapeColumns)
+ landscapeColumns.onPreferenceChangeListener =
+ Preference.OnPreferenceChangeListener { _, newValue ->
+ Settings.System.putInt(
+ requireContext().contentResolver, Settings.System.OMNI_QS_LAYOUT_COLUMNS_LANDSCAPE,
+ newValue as Int
+ )
+ true
+ }
+ }
+ }
+
+ override fun onPreferenceTreeClick(preference: Preference?): Boolean {
+ return super.onPreferenceTreeClick(preference)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/omnirom/omnilib/preference/SeekBarPreference.java b/app/src/main/java/org/omnirom/omnilib/preference/SeekBarPreference.java
new file mode 100644
index 0000000..49b62ca
--- /dev/null
+++ b/app/src/main/java/org/omnirom/omnilib/preference/SeekBarPreference.java
@@ -0,0 +1,221 @@
+/*
+ ** Copyright 2013, The ChameleonOS Open Source Project
+ ** Copyright 2016, The OmniROM Project
+ **
+ ** Licensed under the Apache License, Version 2.0 (the "License");
+ ** you may not use this file except in compliance with the License.
+ ** You may obtain a copy of the License at
+ **
+ ** http://www.apache.org/licenses/LICENSE-2.0
+ **
+ ** Unless required by applicable law or agreed to in writing, software
+ ** distributed under the License is distributed on an "AS IS" BASIS,
+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ** See the License for the specific language governing permissions and
+ ** limitations under the License.
+ */
+package org.omnirom.omnilib.preference;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.TypedValue;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewParent;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.TextView;
+
+import org.omnirom.omnilib.R;
+
+public class SeekBarPreference extends Preference implements OnSeekBarChangeListener {
+
+ private final String TAG = getClass().getName();
+
+ private static final String ANDROIDNS = "http://schemas.android.com/apk/res/android";
+ private static final int DEFAULT_VALUE = 50;
+
+ private int mMaxValue = 100;
+ private int mMinValue = 0;
+ private int mInterval = 1;
+ private int mCurrentValue;
+ private String mUnitsLeft = "";
+ private String mUnitsRight = "";
+ private SeekBar mSeekBar;
+ private TextView mStatusText;
+
+ public SeekBarPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ initPreference(context, attrs);
+ }
+
+ public SeekBarPreference(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ initPreference(context, attrs);
+ }
+
+ private void initPreference(Context context, AttributeSet attrs) {
+ setValuesFromXml(context, attrs);
+ setLayoutResource(R.layout.preference_seek_bar);
+ }
+
+ private void setValuesFromXml(Context context, AttributeSet attrs) {
+ mMaxValue = attrs.getAttributeIntValue(ANDROIDNS, "max", 100);
+
+ final TypedArray attributes = context.obtainStyledAttributes(attrs,
+ R.styleable.SeekBarPreference);
+
+ TypedValue minAttr =
+ attributes.peekValue(R.styleable.SeekBarPreference_min);
+ if (minAttr != null && minAttr.type == TypedValue.TYPE_INT_DEC) {
+ mMinValue = minAttr.data;
+ }
+
+ TypedValue unitsLeftAttr =
+ attributes.peekValue(R.styleable.SeekBarPreference_unitsLeft);
+ CharSequence data = null;
+ if (unitsLeftAttr != null && unitsLeftAttr.type == TypedValue.TYPE_STRING) {
+ if (unitsLeftAttr.resourceId != 0) {
+ data = context.getText(unitsLeftAttr.resourceId);
+ } else {
+ data = unitsLeftAttr.string;
+ }
+ }
+ mUnitsLeft = (data == null) ? "" : data.toString();
+
+ TypedValue unitsRightAttr =
+ attributes.peekValue(R.styleable.SeekBarPreference_unitsRight);
+ data = null;
+ if (unitsRightAttr != null && unitsRightAttr.type == TypedValue.TYPE_STRING) {
+ if (unitsRightAttr.resourceId != 0) {
+ data = context.getText(unitsRightAttr.resourceId);
+ } else {
+ data = unitsRightAttr.string;
+ }
+ }
+ mUnitsRight = (data == null) ? "" : data.toString();
+
+ TypedValue intervalAttr =
+ attributes.peekValue(R.styleable.SeekBarPreference_interval);
+ if (intervalAttr != null && intervalAttr.type == TypedValue.TYPE_INT_DEC) {
+ mInterval = intervalAttr.data;
+ }
+
+ attributes.recycle();
+ }
+
+ @Override
+ public void onDependencyChanged(Preference dependency, boolean disableDependent) {
+ super.onDependencyChanged(dependency, disableDependent);
+ this.setShouldDisableView(true);
+ if (mSeekBar != null) {
+ mSeekBar.setEnabled(!disableDependent);
+ }
+ }
+
+ @Override
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+
+ mSeekBar = (SeekBar) holder.findViewById(R.id.seekbar);
+ mSeekBar.setMax(mMaxValue - mMinValue);
+ mSeekBar.setProgress(mCurrentValue - mMinValue);
+ mSeekBar.setOnSeekBarChangeListener(this);
+ mSeekBar.setEnabled(isEnabled());
+
+ mStatusText = (TextView) holder.findViewById(R.id.seekBarPrefValue);
+ mStatusText.setText(String.valueOf(mCurrentValue));
+ mStatusText.setMinimumWidth(30);
+
+ TextView unitsRight = (TextView) holder.findViewById(R.id.seekBarPrefUnitsRight);
+ unitsRight.setText(mUnitsRight);
+ TextView unitsLeft = (TextView) holder.findViewById(R.id.seekBarPrefUnitsLeft);
+ unitsLeft.setText(mUnitsLeft);
+ }
+
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ int newValue = progress + mMinValue;
+
+ if (newValue > mMaxValue) {
+ newValue = mMaxValue;
+ } else if (newValue < mMinValue) {
+ newValue = mMinValue;
+ } else if (mInterval != 1 && newValue % mInterval != 0) {
+ newValue = Math.round(((float) newValue) / mInterval) * mInterval;
+ }
+
+ // change rejected, revert to the previous value
+ if (!callChangeListener(newValue)) {
+ seekBar.setProgress(mCurrentValue - mMinValue);
+ return;
+ }
+
+ // change accepted, store it
+ mCurrentValue = newValue;
+ mStatusText.setText(String.valueOf(newValue));
+ persistInt(newValue);
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ notifyChanged();
+ }
+
+ @Override
+ protected Object onGetDefaultValue(TypedArray ta, int index) {
+ int defaultValue = ta.getInt(index, DEFAULT_VALUE);
+ return defaultValue;
+ }
+
+ @Override
+ protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
+ if (restoreValue) {
+ mCurrentValue = getPersistedInt(mCurrentValue);
+ } else {
+ int temp = 0;
+ try {
+ temp = (Integer) defaultValue;
+ } catch (Exception ex) {
+ Log.e(TAG, "Invalid default value: " + defaultValue.toString());
+ }
+ persistInt(temp);
+ mCurrentValue = temp;
+ }
+ }
+
+ public void setValue(int value) {
+ mCurrentValue = value;
+ }
+
+ public void setMaxValue(int value) {
+ mMaxValue = value;
+ if (mSeekBar != null) {
+ mSeekBar.setMax(mMaxValue - mMinValue);
+ }
+ }
+
+ public void setMinValue(int value) {
+ mMinValue = value;
+ if (mSeekBar != null) {
+ mSeekBar.setMax(mMaxValue - mMinValue);
+ }
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ if (mSeekBar != null) {
+ mSeekBar.setEnabled(enabled);
+ }
+ super.setEnabled(enabled);
+ }
+}
diff --git a/app/src/main/res/drawable/ic_qs_tile.xml b/app/src/main/res/drawable/ic_qs_tile.xml
new file mode 100644
index 0000000..657260a
--- /dev/null
+++ b/app/src/main/res/drawable/ic_qs_tile.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Copyright (C) 2018 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:tint="?android:textColorPrimary"
+ android:viewportWidth="24"
+ android:viewportHeight="24">
+ <path
+ android:fillColor="@android:color/white"
+ android:pathData="M4,5v13h17L21,5L4,5zM14,7v3.5h-3L11,7h3zM6,7h3v3.5L6,10.5L6,7zM6,16v-3.5h3L9,16L6,16zM11,16v-3.5h3L14,16h-3zM19,16h-3v-3.5h3L19,16zM16,10.5L16,7h3v3.5h-3z" />
+</vector>
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index a1a6494..161a88e 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -102,4 +102,19 @@
<string name="status_bar_bt_battery_title">Show Bluetooth battery level</string>
<string name="status_bar_bt_battery_summary">For supported devices show battery level also in status bar</string>
+
+ <string name="qs_settings_title">Quick settings</string>
+ <string name="qs_settings_summary">Layout options</string>
+ <string name="qs_layout_title">Layout</string>
+ <string name="qs_contents_title">Contents</string>
+ <string name="qs_tile_vertical_layout_title">Vertical layout</string>
+ <string name="qs_tile_vertical_layout_summary">Align icon and text vertical</string>
+ <string name="qs_show_brightness_title">Brightness slider</string>
+ <string name="qs_show_brightness_summary">Show brightness slider in expanded quick settings</string>
+ <string name="qs_layout_columns_title">Portrait columns</string>
+ <string name="qs_layout_columns_summary"></string>
+ <string name="qs_layout_columns_landscape_title">Landscape columns</string>
+ <string name="qs_layout_columns_landscape_summary"></string>
+ <string name="qs_tile_label_hide_title">Hide labels</string>
+ <string name="qs_tile_label_hide_summary">Do not show text</string>
</resources>
\ No newline at end of file
diff --git a/app/src/main/res/xml/qs_settings_preferences.xml b/app/src/main/res/xml/qs_settings_preferences.xml
new file mode 100644
index 0000000..ac049e6
--- /dev/null
+++ b/app/src/main/res/xml/qs_settings_preferences.xml
@@ -0,0 +1,51 @@
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:key="bars_settings">
+ <PreferenceCategory
+ android:key="qs_layout_category"
+ android:title="@string/qs_layout_title">
+
+ <org.omnirom.omnilib.preference.SystemSettingSwitchPreference
+ android:key="qs_tile_vertical_layout"
+ android:title="@string/qs_tile_vertical_layout_title"
+ android:summary="@string/qs_tile_vertical_layout_summary"
+ android:defaultValue="false" />
+
+ <org.omnirom.omnilib.preference.SystemSettingSwitchPreference
+ android:key="qs_tile_label_hide"
+ android:title="@string/qs_tile_label_hide_title"
+ android:summary="@string/qs_tile_label_hide_summary"
+ android:defaultValue="false" />
+
+ <org.omnirom.omnilib.preference.SeekBarPreference
+ android:key="qs_layout_columns"
+ android:title="@string/qs_layout_columns_title"
+ android:summary="@string/qs_layout_columns_summary"
+ android:max="10"
+ app:min="2"
+ android:persistent="false" />
+
+ <org.omnirom.omnilib.preference.SeekBarPreference
+ android:key="qs_layout_columns_landscape"
+ android:title="@string/qs_layout_columns_landscape_title"
+ android:summary="@string/qs_layout_columns_landscape_summary"
+ android:max="10"
+ app:min="2"
+ android:persistent="false" />
+
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:key="qs_contents_category"
+ android:title="@string/qs_contents_title">
+
+ <org.omnirom.omnilib.preference.SecureSettingSwitchPreference
+ android:key="qs_show_brightness"
+ android:title="@string/qs_show_brightness_title"
+ android:summary="@string/qs_show_brightness_summary"
+ android:defaultValue="true"/>
+
+ </PreferenceCategory>
+</PreferenceScreen>
+
+