Merge pull request #2027 from triplem/ext_statusline

Add extended statuslight to overview fragment
This commit is contained in:
Milos Kozak 2019-09-07 22:38:11 +02:00 committed by GitHub
commit c57a6335d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 204 additions and 85 deletions

View file

@ -93,12 +93,22 @@ public class CareportalEvent implements DataPointWithLabelInterface, Interval {
return (System.currentTimeMillis() - date) / (60 * 60 * 1000.0); return (System.currentTimeMillis() - date) / (60 * 60 * 1000.0);
} }
public String age() { public String age(boolean useShortText) {
Map<TimeUnit, Long> diff = computeDiff(date, System.currentTimeMillis()); Map<TimeUnit, Long> diff = computeDiff(date, System.currentTimeMillis());
if (OverviewFragment.shorttextmode)
return diff.get(TimeUnit.DAYS) + "d" + diff.get(TimeUnit.HOURS) + "h"; String days = " " + MainApp.gs(R.string.days) + " ";
else String hours = " " + MainApp.gs(R.string.hours) + " ";
return diff.get(TimeUnit.DAYS) + " " + MainApp.gs(R.string.days) + " " + diff.get(TimeUnit.HOURS) + " " + MainApp.gs(R.string.hours);
if (useShortText) {
days = "d";
hours = "h";
}
return diff.get(TimeUnit.DAYS) + days + diff.get(TimeUnit.HOURS) + hours;
}
public String age() {
return age(OverviewFragment.shorttextmode);
} }
public boolean isOlderThan(double hours) { public boolean isOlderThan(double hours) {

View file

@ -22,12 +22,16 @@ import info.nightscout.androidaps.R;
import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.data.ProfileStore;
import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.events.EventCareportalEventChange; import info.nightscout.androidaps.events.EventCareportalEventChange;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.general.careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.general.careportal.Dialogs.NewNSTreatmentDialog;
import info.nightscout.androidaps.plugins.common.SubscriberFragment; import info.nightscout.androidaps.plugins.common.SubscriberFragment;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus; import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus;
import info.nightscout.androidaps.plugins.general.overview.OverviewFragment; import info.nightscout.androidaps.plugins.general.overview.OverviewFragment;
import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.FabricPrivacy; import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.SP;
import info.nightscout.androidaps.utils.SetWarnColor;
public class CareportalFragment extends SubscriberFragment implements View.OnClickListener { public class CareportalFragment extends SubscriberFragment implements View.OnClickListener {
private static Logger log = LoggerFactory.getLogger(CareportalFragment.class); private static Logger log = LoggerFactory.getLogger(CareportalFragment.class);
@ -91,15 +95,15 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli
view.findViewById(R.id.careportal_openapsoffline).setOnClickListener(this); view.findViewById(R.id.careportal_openapsoffline).setOnClickListener(this);
view.findViewById(R.id.careportal_temporarytarget).setOnClickListener(this); view.findViewById(R.id.careportal_temporarytarget).setOnClickListener(this);
iage = (TextView) view.findViewById(R.id.careportal_insulinage); iage = view.findViewById(R.id.careportal_insulinage);
cage = (TextView) view.findViewById(R.id.careportal_canulaage); cage = view.findViewById(R.id.careportal_canulaage);
sage = (TextView) view.findViewById(R.id.careportal_sensorage); sage = view.findViewById(R.id.careportal_sensorage);
pbage = (TextView) view.findViewById(R.id.careportal_pbage); pbage = view.findViewById(R.id.careportal_pbage);
statsLayout = view.findViewById(R.id.careportal_stats); statsLayout = view.findViewById(R.id.careportal_stats);
noProfileView = view.findViewById(R.id.profileview_noprofile); noProfileView = view.findViewById(R.id.profileview_noprofile);
butonsLayout = (LinearLayout) view.findViewById(R.id.careportal_buttons); butonsLayout = view.findViewById(R.id.careportal_buttons);
ProfileStore profileStore = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() != null ? ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile() : null; ProfileStore profileStore = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() != null ? ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile() : null;
if (profileStore == null) { if (profileStore == null) {
@ -249,13 +253,17 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli
} }
private static TextView handleAge(final TextView age, String eventType, double warnThreshold, double urgentThreshold) { private static TextView handleAge(final TextView age, String eventType, double warnThreshold, double urgentThreshold) {
String notavailable = OverviewFragment.shorttextmode ? "-" : MainApp.gs(R.string.notavailable); return handleAge(age, "", eventType, warnThreshold, urgentThreshold, OverviewFragment.shorttextmode);
}
public static TextView handleAge(final TextView age, String prefix, String eventType, double warnThreshold, double urgentThreshold, boolean useShortText) {
String notavailable = useShortText ? "-" : MainApp.gs(R.string.notavailable);
if (age != null) { if (age != null) {
CareportalEvent careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(eventType); CareportalEvent careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(eventType);
if (careportalEvent != null) { if (careportalEvent != null) {
age.setTextColor(CareportalFragment.determineTextColor(careportalEvent, warnThreshold, urgentThreshold)); age.setTextColor(CareportalFragment.determineTextColor(careportalEvent, warnThreshold, urgentThreshold));
age.setText(careportalEvent.age()); age.setText(prefix + careportalEvent.age(useShortText));
} else { } else {
age.setText(notavailable); age.setText(notavailable);
} }

View file

@ -4,8 +4,6 @@ import android.annotation.SuppressLint;
import android.app.Activity; import android.app.Activity;
import android.app.NotificationManager; import android.app.NotificationManager;
import androidx.arch.core.util.Function;
import android.content.ActivityNotFoundException; import android.content.ActivityNotFoundException;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -60,7 +58,6 @@ import info.nightscout.androidaps.data.IobTotal;
import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.QuickWizardEntry; import info.nightscout.androidaps.data.QuickWizardEntry;
import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.BgReading;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.DatabaseHelper;
import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.Source;
@ -92,7 +89,6 @@ import info.nightscout.androidaps.plugins.general.careportal.Dialogs.NewNSTreatm
import info.nightscout.androidaps.plugins.general.careportal.OptionsToShow; import info.nightscout.androidaps.plugins.general.careportal.OptionsToShow;
import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; import info.nightscout.androidaps.plugins.general.nsclient.NSUpload;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus; import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus;
import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity; import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity;
import info.nightscout.androidaps.plugins.general.overview.dialogs.CalibrationDialog; import info.nightscout.androidaps.plugins.general.overview.dialogs.CalibrationDialog;
import info.nightscout.androidaps.plugins.general.overview.dialogs.NewCarbsDialog; import info.nightscout.androidaps.plugins.general.overview.dialogs.NewCarbsDialog;
@ -258,17 +254,17 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
apsModeView = (TextView) view.findViewById(R.id.overview_apsmode); apsModeView = (TextView) view.findViewById(R.id.overview_apsmode);
tempTargetView = (TextView) view.findViewById(R.id.overview_temptarget); tempTargetView = (TextView) view.findViewById(R.id.overview_temptarget);
iage = (TextView) view.findViewById(R.id.careportal_insulinage); iage = view.findViewById(R.id.careportal_insulinage);
cage = (TextView) view.findViewById(R.id.careportal_canulaage); cage = view.findViewById(R.id.careportal_canulaage);
sage = (TextView) view.findViewById(R.id.careportal_sensorage); sage = view.findViewById(R.id.careportal_sensorage);
pbage = (TextView) view.findViewById(R.id.careportal_pbage); pbage = view.findViewById(R.id.careportal_pbage);
iageView = (TextView) view.findViewById(R.id.overview_insulinage); iageView = view.findViewById(R.id.overview_insulinage);
cageView = (TextView) view.findViewById(R.id.overview_canulaage); cageView = view.findViewById(R.id.overview_canulaage);
reservoirView = (TextView) view.findViewById(R.id.overview_reservoirlevel); reservoirView = view.findViewById(R.id.overview_reservoirlevel);
sageView = (TextView) view.findViewById(R.id.overview_sensorage); sageView = view.findViewById(R.id.overview_sensorage);
batteryView = (TextView) view.findViewById(R.id.overview_batterylevel); batteryView = view.findViewById(R.id.overview_batterylevel);
statuslightsLayout = (LinearLayout) view.findViewById(R.id.overview_statuslights); statuslightsLayout = view.findViewById(R.id.overview_statuslights);
bgGraph = (GraphView) view.findViewById(R.id.overview_bggraph); bgGraph = (GraphView) view.findViewById(R.id.overview_bggraph);
iobGraph = (GraphView) view.findViewById(R.id.overview_iobgraph); iobGraph = (GraphView) view.findViewById(R.id.overview_iobgraph);
@ -1327,54 +1323,22 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
cobView.setText(cobText); cobView.setText(cobText);
} }
if (statuslightsLayout != null) { if (statuslightsLayout != null && SP.getBoolean(R.string.key_show_statuslights, false)) {
if (SP.getBoolean(R.string.key_show_statuslights, false)) { StatuslightHandler handler = new StatuslightHandler();
CareportalEvent careportalEvent;
NSSettingsStatus nsSettings = new NSSettingsStatus().getInstance();
double iageUrgent = nsSettings.getExtendedWarnValue("iage", "urgent", 96);
double iageWarn = nsSettings.getExtendedWarnValue("iage", "warn", 72);
double cageUrgent = nsSettings.getExtendedWarnValue("cage", "urgent", 72);
double cageWarn = nsSettings.getExtendedWarnValue("cage", "warn", 48);
double sageUrgent = nsSettings.getExtendedWarnValue("sage", "urgent", 166);
double sageWarn = nsSettings.getExtendedWarnValue("sage", "warn", 164);
//double pbageUrgent = nsSettings.getExtendedWarnValue("pgage", "urgent", 360);
//double pbageWarn = nsSettings.getExtendedWarnValue("pgage", "warn", 240);
double batUrgent = SP.getDouble(R.string.key_statuslights_bat_critical, 5.0);
double batWarn = SP.getDouble(R.string.key_statuslights_bat_warning, 25.0);
double resUrgent = SP.getDouble(R.string.key_statuslights_res_critical, 10.0);
double resWarn = SP.getDouble(R.string.key_statuslights_res_warning, 80.0);
if (cageView != null) { if (SP.getBoolean(R.string.key_show_statuslights_easy, false)) {
careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SITECHANGE); handler.statuslight(cageView, iageView, reservoirView, sageView, batteryView);
double canAge = careportalEvent != null ? careportalEvent.getHoursFromStart() : Double.MAX_VALUE;
applyStatuslight(cageView, "CAN", canAge, cageWarn, cageUrgent, Double.MAX_VALUE, true);
}
if (iageView != null) { statuslightsLayout.setVisibility(View.VISIBLE);
careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.INSULINCHANGE); } else if (SP.getBoolean(R.string.key_show_statuslights_extended, false)) {
double insulinAge = careportalEvent != null ? careportalEvent.getHoursFromStart() : Double.MAX_VALUE; handler.extendedStatuslight(cageView, iageView, reservoirView, sageView, batteryView);
applyStatuslight(iageView, "INS", insulinAge, iageWarn, iageUrgent, Double.MAX_VALUE, true);
}
if (reservoirView != null) {
double reservoirLevel = pump.isInitialized() ? pump.getReservoirLevel() : -1;
applyStatuslight(reservoirView, "RES", reservoirLevel, resWarn, resUrgent, -1, false);
}
if (sageView != null) {
careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SENSORCHANGE);
double sensorAge = careportalEvent != null ? careportalEvent.getHoursFromStart() : Double.MAX_VALUE;
applyStatuslight(sageView, "SEN", sensorAge, sageWarn, sageUrgent, Double.MAX_VALUE, true);
}
if (batteryView != null) {
double batteryLevel = pump.isInitialized() ? pump.getBatteryLevel() : -1;
applyStatuslight(batteryView, "BAT", batteryLevel, batWarn, batUrgent, -1, false);
}
statuslightsLayout.setVisibility(View.VISIBLE); statuslightsLayout.setVisibility(View.VISIBLE);
} else { } else {
statuslightsLayout.setVisibility(View.GONE); statuslightsLayout.setVisibility(View.GONE);
} }
} else if (statuslightsLayout != null) {
statuslightsLayout.setVisibility(View.GONE);
} }
boolean predictionsAvailable; boolean predictionsAvailable;
@ -1562,21 +1526,5 @@ public class OverviewFragment extends Fragment implements View.OnClickListener,
Profiler.log(log, from, updateGUIStart); Profiler.log(log, from, updateGUIStart);
} }
public static void applyStatuslight(TextView view, String text, double value, double warnThreshold, double urgentThreshold, double invalid, boolean checkAscending) {
Function<Double, Boolean> check = checkAscending ? (Double threshold) -> value >= threshold : (Double threshold) -> value <= threshold;
if (value != invalid) {
view.setText(text);
if (check.apply(urgentThreshold)) {
view.setTextColor(MainApp.gc(R.color.ribbonCritical));
} else if (check.apply(warnThreshold)) {
view.setTextColor(MainApp.gc(R.color.ribbonWarning));
} else {
view.setTextColor(MainApp.gc(R.color.ribbonDefault));
}
view.setVisibility(View.VISIBLE);
} else {
view.setVisibility(View.GONE);
}
}
} }

View file

@ -0,0 +1,135 @@
package info.nightscout.androidaps.plugins.general.overview;
import android.view.View;
import android.widget.TextView;
import androidx.arch.core.util.Function;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
import info.nightscout.androidaps.db.CareportalEvent;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
import info.nightscout.androidaps.plugins.general.careportal.CareportalFragment;
import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus;
import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.SP;
import info.nightscout.androidaps.utils.SetWarnColor;
class StatuslightHandler {
/**
* applies the statuslight subview on the overview fragement
*/
void statuslight(TextView cageView, TextView iageView, TextView reservoirView,
TextView sageView, TextView batteryView) {
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
applyStatuslight("cage", CareportalEvent.SITECHANGE, cageView, "CAN", 48, 72);
applyStatuslight("iage", CareportalEvent.INSULINCHANGE, iageView, "INS", 72, 96);
double reservoirLevel = pump.isInitialized() ? pump.getReservoirLevel() : -1;
applyStatuslightLevel(R.string.key_statuslights_res_critical, 10.0,
R.string.key_statuslights_res_warning, 80.0, reservoirView, "RES", reservoirLevel);
applyStatuslight("sage", CareportalEvent.SENSORCHANGE, sageView, "SEN", 164, 166);
double batteryLevel = pump.isInitialized() ? pump.getBatteryLevel() : -1;
applyStatuslightLevel(R.string.key_statuslights_bat_critical, 5.0,
R.string.key_statuslights_bat_warning, 22.0,
batteryView, "BAT", batteryLevel);
}
void applyStatuslight(String nsSettingPlugin, String eventName, TextView view, String text,
int defaultWarnThreshold, int defaultUrgentThreshold) {
NSSettingsStatus nsSettings = NSSettingsStatus.getInstance();
if (view != null) {
double urgent = nsSettings.getExtendedWarnValue(nsSettingPlugin, "urgent", defaultUrgentThreshold);
double warn = nsSettings.getExtendedWarnValue(nsSettingPlugin, "warn", defaultWarnThreshold);
CareportalEvent event = MainApp.getDbHelper().getLastCareportalEvent(eventName);
double age = event != null ? event.getHoursFromStart() : Double.MAX_VALUE;
applyStatuslight(view, text, age, warn, urgent, Double.MAX_VALUE, true);
}
}
void applyStatuslightLevel(int criticalSetting, double criticalDefaultValue,
int warnSetting, double warnDefaultValue,
TextView view, String text, double level) {
if (view != null) {
double resUrgent = SP.getDouble(criticalSetting, criticalDefaultValue);
double resWarn = SP.getDouble(warnSetting, warnDefaultValue);
applyStatuslight(view, text, level, resWarn, resUrgent, -1, false);
}
}
void applyStatuslight(TextView view, String text, double value, double warnThreshold,
double urgentThreshold, double invalid, boolean checkAscending) {
Function<Double, Boolean> check = checkAscending ? (Double threshold) -> value >= threshold :
(Double threshold) -> value <= threshold;
if (value != invalid) {
view.setText(text);
if (check.apply(urgentThreshold)) {
view.setTextColor(MainApp.gc(R.color.ribbonCritical));
} else if (check.apply(warnThreshold)) {
view.setTextColor(MainApp.gc(R.color.ribbonWarning));
} else {
view.setTextColor(MainApp.gc(R.color.ribbonDefault));
}
view.setVisibility(View.VISIBLE);
} else {
view.setVisibility(View.GONE);
}
}
/**
* applies the extended statuslight subview on the overview fragement
*/
void extendedStatuslight(TextView cageView, TextView iageView,
TextView reservoirView, TextView sageView,
TextView batteryView) {
PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump();
handleAge("cage", CareportalEvent.SITECHANGE, cageView, "CAN ",
48, 72);
handleAge("iage", CareportalEvent.INSULINCHANGE, iageView, "INS ",
72, 96);
handleLevel(R.string.key_statuslights_res_critical, 10.0,
R.string.key_statuslights_res_warning, 80.0,
reservoirView, "RES ", pump.getReservoirLevel());
handleAge("sage", CareportalEvent.SENSORCHANGE, sageView, "SEN ",
164, 166);
handleLevel(R.string.key_statuslights_bat_critical, 26.0,
R.string.key_statuslights_bat_warning, 51.0,
batteryView, "BAT ", pump.getBatteryLevel());
}
void handleAge(String nsSettingPlugin, String eventName, TextView view, String text,
int defaultUrgentThreshold, int defaultWarnThreshold) {
NSSettingsStatus nsSettings = new NSSettingsStatus().getInstance();
if (view != null) {
double urgent = nsSettings.getExtendedWarnValue(nsSettingPlugin, "urgent", defaultUrgentThreshold);
double warn = nsSettings.getExtendedWarnValue(nsSettingPlugin, "warn", defaultWarnThreshold);
CareportalFragment.handleAge(view, text, eventName, warn, urgent, true);
}
}
void handleLevel(int criticalSetting, double criticalDefaultValue,
int warnSetting, double warnDefaultValue,
TextView view, String text, double level) {
if (view != null) {
double resUrgent = SP.getDouble(criticalSetting, criticalDefaultValue);
double resWarn = SP.getDouble(warnSetting, warnDefaultValue);
view.setText(text + DecimalFormatter.to0Decimal(level));
SetWarnColor.setColorInverse(view, level, resWarn, resUrgent);
}
}
}

View file

@ -623,8 +623,13 @@
<string name="enablesuperbolus">Enable superbolus in wizard</string> <string name="enablesuperbolus">Enable superbolus in wizard</string>
<string name="enablesuperbolus_summary">Enable superbolus functionality in wizard. Do not enable until you learn what it really does. IT MAY CAUSE INSULIN OVERDOSE IF USED BLINDLY!</string> <string name="enablesuperbolus_summary">Enable superbolus functionality in wizard. Do not enable until you learn what it really does. IT MAY CAUSE INSULIN OVERDOSE IF USED BLINDLY!</string>
<string name="key_show_statuslights" translatable="false">key_show_statuslights</string> <string name="key_show_statuslights" translatable="false">key_show_statuslights</string>
<string name="key_show_statuslights_easy" translatable="false">key_show_statuslights_easy</string>
<string name="key_show_statuslights_extended" translatable="false">key_show_statuslights_extended</string>
<string name="show_statuslights">Show status lights on home screen</string> <string name="show_statuslights">Show status lights on home screen</string>
<string name="show_statuslights_summary">Enable status lights for cage, iage, sage, reservoir and battery level on home screen.</string> <string name="show_statuslights_easy">Show original status lights on home screen</string>
<string name="show_statuslights_easy_summary">Enable original status lights for cage, iage, sage, reservoir and battery level on home screen.</string>
<string name="show_statuslights_extended">Show extended status lights on home screen</string>
<string name="show_statuslights_extended_summary">Enable extended status lights for cage, iage, sage, reservoir and battery level on home screen.</string>
<string name="key_statuslights_res_warning" translatable="false">key_statuslights_res_warning</string> <string name="key_statuslights_res_warning" translatable="false">key_statuslights_res_warning</string>
<string name="statuslights_res_warning">Threshold warning reservoir level [U]</string> <string name="statuslights_res_warning">Threshold warning reservoir level [U]</string>
<string name="key_statuslights_res_critical" translatable="false">key_statuslights_res_critical</string> <string name="key_statuslights_res_critical" translatable="false">key_statuslights_res_critical</string>

View file

@ -165,9 +165,22 @@
<SwitchPreference <SwitchPreference
android:defaultValue="false" android:defaultValue="false"
android:key="@string/key_show_statuslights" android:key="@string/key_show_statuslights"
android:summary="@string/show_statuslights_summary"
android:title="@string/show_statuslights" /> android:title="@string/show_statuslights" />
<SwitchPreference
android:defaultValue="false"
android:dependency="@string/key_show_statuslights"
android:key="@string/key_show_statuslights_easy"
android:summary="@string/show_statuslights_easy_summary"
android:title="@string/show_statuslights_easy" />
<SwitchPreference
android:defaultValue="false"
android:dependency="@string/key_show_statuslights"
android:key="@string/key_show_statuslights_extended"
android:summary="@string/show_statuslights_extended_summary"
android:title="@string/show_statuslights_extended" />
<com.andreabaccega.widget.ValidatingEditTextPreference <com.andreabaccega.widget.ValidatingEditTextPreference
android:defaultValue="80" android:defaultValue="80"
android:dependency="@string/key_show_statuslights" android:dependency="@string/key_show_statuslights"