1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-12-26 01:28:50 -05:00

Extended *Settings classes to handle multiple versions

This commit is contained in:
cketti 2011-12-11 05:16:22 +01:00
parent 09fa9d406f
commit d57e684296
7 changed files with 496 additions and 179 deletions

View File

@ -4,6 +4,8 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.TreeMap;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import com.fsck.k9.Account; import com.fsck.k9.Account;
import com.fsck.k9.K9; import com.fsck.k9.K9;
@ -15,87 +17,198 @@ import com.fsck.k9.mail.store.StorageManager;
import com.fsck.k9.preferences.Settings.*; import com.fsck.k9.preferences.Settings.*;
public class AccountSettings { public class AccountSettings {
public static final Map<String, SettingsDescription> SETTINGS; public static final Map<String, TreeMap<Integer, SettingsDescription>> SETTINGS;
static { static {
Map<String, SettingsDescription> s = new LinkedHashMap<String, SettingsDescription>(); Map<String, TreeMap<Integer, SettingsDescription>> s =
new LinkedHashMap<String, TreeMap<Integer, SettingsDescription>>();
s.put("archiveFolderName", new StringSetting("Archive")); s.put("archiveFolderName", Settings.versions(
s.put("autoExpandFolderName", new StringSetting("INBOX")); new V(1, new StringSetting("Archive"))
s.put("automaticCheckIntervalMinutes", ));
new IntegerResourceSetting(-1, R.array.account_settings_check_frequency_values)); s.put("autoExpandFolderName", Settings.versions(
s.put("chipColor", new ColorSetting(0xFF0000FF)); new V(1, new StringSetting("INBOX"))
s.put("cryptoApp", new StringSetting(Apg.NAME)); ));
s.put("cryptoAutoSignature", new BooleanSetting(false)); s.put("automaticCheckIntervalMinutes", Settings.versions(
s.put("cryptoAutoEncrypt", new BooleanSetting(false)); // added to version 3 new V(1, new IntegerResourceSetting(-1,
s.put("defaultQuotedTextShown", new BooleanSetting(Account.DEFAULT_QUOTED_TEXT_SHOWN)); R.array.account_settings_check_frequency_values))
s.put("deletePolicy", new DeletePolicySetting(Account.DELETE_POLICY_NEVER)); ));
s.put("displayCount", new IntegerResourceSetting(K9.DEFAULT_VISIBLE_LIMIT, s.put("chipColor", Settings.versions(
R.array.account_settings_display_count_values)); new V(1, new ColorSetting(0xFF0000FF))
s.put("draftsFolderName", new StringSetting("Drafts")); ));
s.put("enableMoveButtons", new BooleanSetting(false)); s.put("cryptoApp", Settings.versions(
s.put("expungePolicy", new StringResourceSetting(Account.EXPUNGE_IMMEDIATELY, new V(1, new StringSetting(Apg.NAME))
R.array.account_setup_expunge_policy_values)); ));
s.put("folderDisplayMode", new EnumSetting(FolderMode.class, FolderMode.NOT_SECOND_CLASS)); s.put("cryptoAutoSignature", Settings.versions(
s.put("folderPushMode", new EnumSetting(FolderMode.class, FolderMode.FIRST_CLASS)); new V(1, new BooleanSetting(false))
s.put("folderSyncMode", new EnumSetting(FolderMode.class, FolderMode.FIRST_CLASS)); ));
s.put("folderTargetMode", new EnumSetting(FolderMode.class, FolderMode.NOT_SECOND_CLASS)); s.put("cryptoAutoEncrypt", Settings.versions(
s.put("goToUnreadMessageSearch", new BooleanSetting(false)); new V(3, new BooleanSetting(false)) // added to version 3
s.put("hideButtonsEnum", new EnumSetting(ScrollButtons.class, ScrollButtons.NEVER)); ));
s.put("hideMoveButtonsEnum", new EnumSetting(ScrollButtons.class, ScrollButtons.NEVER)); s.put("defaultQuotedTextShown", Settings.versions(
s.put("idleRefreshMinutes", new IntegerResourceSetting(24, new V(1, new BooleanSetting(Account.DEFAULT_QUOTED_TEXT_SHOWN))
R.array.idle_refresh_period_values)); ));
s.put("inboxFolderName", new StringSetting("INBOX")); s.put("deletePolicy", Settings.versions(
s.put("led", new BooleanSetting(true)); new V(1, new DeletePolicySetting(Account.DELETE_POLICY_NEVER))
s.put("ledColor", new ColorSetting(0xFF0000FF)); ));
s.put("localStorageProvider", new StorageProviderSetting()); s.put("displayCount", Settings.versions(
s.put("maxPushFolders", new IntegerRangeSetting(0, 100, 10)); new V(1, new IntegerResourceSetting(K9.DEFAULT_VISIBLE_LIMIT,
s.put("maximumAutoDownloadMessageSize", new IntegerResourceSetting(32768, R.array.account_settings_display_count_values))
R.array.account_settings_autodownload_message_size_values)); ));
s.put("maximumPolledMessageAge", new IntegerResourceSetting(-1, s.put("draftsFolderName", Settings.versions(
R.array.account_settings_message_age_values)); new V(1, new StringSetting("Drafts"))
s.put("messageFormat", ));
new EnumSetting(Account.MessageFormat.class, Account.DEFAULT_MESSAGE_FORMAT)); s.put("enableMoveButtons", Settings.versions(
s.put("messageFormatAuto", new BooleanSetting(Account.DEFAULT_MESSAGE_FORMAT_AUTO)); // added to version 2 new V(1, new BooleanSetting(false))
s.put("messageReadReceipt", new BooleanSetting(Account.DEFAULT_MESSAGE_READ_RECEIPT)); ));
s.put("notificationUnreadCount", new BooleanSetting(true)); s.put("expungePolicy", Settings.versions(
s.put("notifyMailCheck", new BooleanSetting(false)); new V(1, new StringResourceSetting(Account.EXPUNGE_IMMEDIATELY,
s.put("notifyNewMail", new BooleanSetting(false)); R.array.account_setup_expunge_policy_values))
s.put("notifySelfNewMail", new BooleanSetting(true)); ));
s.put("pushPollOnConnect", new BooleanSetting(true)); s.put("folderDisplayMode", Settings.versions(
s.put("quotePrefix", new StringSetting(Account.DEFAULT_QUOTE_PREFIX)); new V(1, new EnumSetting(FolderMode.class, FolderMode.NOT_SECOND_CLASS))
s.put("quoteStyle", ));
new EnumSetting(Account.QuoteStyle.class, Account.DEFAULT_QUOTE_STYLE)); s.put("folderPushMode", Settings.versions(
s.put("replyAfterQuote", new BooleanSetting(Account.DEFAULT_REPLY_AFTER_QUOTE)); new V(1, new EnumSetting(FolderMode.class, FolderMode.FIRST_CLASS))
s.put("stripSignature", new BooleanSetting(Account.DEFAULT_STRIP_SIGNATURE)); // added to version 2 ));
s.put("ring", new BooleanSetting(true)); s.put("folderSyncMode", Settings.versions(
s.put("ringtone", new RingtoneSetting("content://settings/system/notification_sound")); new V(1, new EnumSetting(FolderMode.class, FolderMode.FIRST_CLASS))
s.put("saveAllHeaders", new BooleanSetting(true)); ));
s.put("searchableFolders", s.put("folderTargetMode", Settings.versions(
new EnumSetting(Account.Searchable.class, Account.Searchable.ALL)); new V(1, new EnumSetting(FolderMode.class, FolderMode.NOT_SECOND_CLASS))
s.put("sentFolderName", new StringSetting("Sent")); ));
s.put("showPicturesEnum", s.put("goToUnreadMessageSearch", Settings.versions(
new EnumSetting(Account.ShowPictures.class, Account.ShowPictures.NEVER)); new V(1, new BooleanSetting(false))
s.put("signatureBeforeQuotedText", new BooleanSetting(false)); ));
s.put("spamFolderName", new StringSetting("Spam")); s.put("hideButtonsEnum", Settings.versions(
s.put("subscribedFoldersOnly", new BooleanSetting(false)); new V(1, new EnumSetting(ScrollButtons.class, ScrollButtons.NEVER))
s.put("syncRemoteDeletions", new BooleanSetting(true)); ));
s.put("trashFolderName", new StringSetting("Trash")); s.put("hideMoveButtonsEnum", Settings.versions(
s.put("useCompression.MOBILE", new BooleanSetting(true)); new V(1, new EnumSetting(ScrollButtons.class, ScrollButtons.NEVER))
s.put("useCompression.OTHER", new BooleanSetting(true)); ));
s.put("useCompression.WIFI", new BooleanSetting(true)); s.put("idleRefreshMinutes", Settings.versions(
s.put("vibrate", new BooleanSetting(false)); new V(1, new IntegerResourceSetting(24, R.array.idle_refresh_period_values))
s.put("vibratePattern", new IntegerResourceSetting(0, ));
R.array.account_settings_vibrate_pattern_values)); s.put("inboxFolderName", Settings.versions(
s.put("vibrateTimes", new IntegerResourceSetting(5, new V(1, new StringSetting("INBOX"))
R.array.account_settings_vibrate_times_label)); ));
s.put("led", Settings.versions(
new V(1, new BooleanSetting(true))
));
s.put("ledColor", Settings.versions(
new V(1, new ColorSetting(0xFF0000FF))
));
s.put("localStorageProvider", Settings.versions(
new V(1, new StorageProviderSetting())
));
s.put("maxPushFolders", Settings.versions(
new V(1, new IntegerRangeSetting(0, 100, 10))
));
s.put("maximumAutoDownloadMessageSize", Settings.versions(
new V(1, new IntegerResourceSetting(32768,
R.array.account_settings_autodownload_message_size_values))
));
s.put("maximumPolledMessageAge", Settings.versions(
new V(1, new IntegerResourceSetting(-1,
R.array.account_settings_message_age_values))
));
s.put("messageFormat", Settings.versions(
new V(1, new EnumSetting(Account.MessageFormat.class,
Account.DEFAULT_MESSAGE_FORMAT))
));
s.put("messageFormatAuto", Settings.versions(
new V(2, new BooleanSetting(Account.DEFAULT_MESSAGE_FORMAT_AUTO)) // added to version 2
));
s.put("messageReadReceipt", Settings.versions(
new V(1, new BooleanSetting(Account.DEFAULT_MESSAGE_READ_RECEIPT))
));
s.put("notificationUnreadCount", Settings.versions(
new V(1, new BooleanSetting(true))
));
s.put("notifyMailCheck", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("notifyNewMail", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("notifySelfNewMail", Settings.versions(
new V(1, new BooleanSetting(true))
));
s.put("pushPollOnConnect", Settings.versions(
new V(1, new BooleanSetting(true))
));
s.put("quotePrefix", Settings.versions(
new V(1, new StringSetting(Account.DEFAULT_QUOTE_PREFIX))
));
s.put("quoteStyle", Settings.versions(
new V(1, new EnumSetting(Account.QuoteStyle.class, Account.DEFAULT_QUOTE_STYLE))
));
s.put("replyAfterQuote", Settings.versions(
new V(1, new BooleanSetting(Account.DEFAULT_REPLY_AFTER_QUOTE))
));
s.put("stripSignature", Settings.versions(
new V(2, new BooleanSetting(Account.DEFAULT_STRIP_SIGNATURE)) // added to version 2
));
s.put("ring", Settings.versions(
new V(1, new BooleanSetting(true))
));
s.put("ringtone", Settings.versions(
new V(1, new RingtoneSetting("content://settings/system/notification_sound"))
));
s.put("saveAllHeaders", Settings.versions(
new V(1, new BooleanSetting(true))
));
s.put("searchableFolders", Settings.versions(
new V(1, new EnumSetting(Account.Searchable.class, Account.Searchable.ALL))
));
s.put("sentFolderName", Settings.versions(
new V(1, new StringSetting("Sent"))
));
s.put("showPicturesEnum", Settings.versions(
new V(1, new EnumSetting(Account.ShowPictures.class, Account.ShowPictures.NEVER))
));
s.put("signatureBeforeQuotedText", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("spamFolderName", Settings.versions(
new V(1, new StringSetting("Spam"))
));
s.put("subscribedFoldersOnly", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("syncRemoteDeletions", Settings.versions(
new V(1, new BooleanSetting(true))
));
s.put("trashFolderName", Settings.versions(
new V(1, new StringSetting("Trash"))
));
s.put("useCompression.MOBILE", Settings.versions(
new V(1, new BooleanSetting(true))
));
s.put("useCompression.OTHER", Settings.versions(
new V(1, new BooleanSetting(true))
));
s.put("useCompression.WIFI", Settings.versions(
new V(1, new BooleanSetting(true))
));
s.put("vibrate", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("vibratePattern", Settings.versions(
new V(1, new IntegerResourceSetting(0,
R.array.account_settings_vibrate_pattern_values))
));
s.put("vibrateTimes", Settings.versions(
new V(1, new IntegerResourceSetting(5,
R.array.account_settings_vibrate_times_label))
));
SETTINGS = Collections.unmodifiableMap(s); SETTINGS = Collections.unmodifiableMap(s);
} }
public static Map<String, String> validate(Map<String, String> importedSettings, public static Map<String, String> validate(int version, Map<String, String> importedSettings,
boolean useDefaultValues) { boolean useDefaultValues) {
return Settings.validate(SETTINGS, importedSettings, useDefaultValues); return Settings.validate(version, SETTINGS, importedSettings, useDefaultValues);
} }
public static Map<String, String> getAccountSettings(SharedPreferences storage, String uuid) { public static Map<String, String> getAccountSettings(SharedPreferences storage, String uuid) {

View File

@ -4,29 +4,42 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.TreeMap;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import com.fsck.k9.mail.Folder.FolderClass; import com.fsck.k9.mail.Folder.FolderClass;
import com.fsck.k9.preferences.Settings.*; import com.fsck.k9.preferences.Settings.*;
public class FolderSettings { public class FolderSettings {
public static final Map<String, SettingsDescription> SETTINGS; public static final Map<String, TreeMap<Integer, SettingsDescription>> SETTINGS;
static { static {
Map<String, SettingsDescription> s = new LinkedHashMap<String, SettingsDescription>(); Map<String, TreeMap<Integer, SettingsDescription>> s =
new LinkedHashMap<String, TreeMap<Integer, SettingsDescription>>();
s.put("displayMode", new EnumSetting(FolderClass.class, FolderClass.NO_CLASS)); s.put("displayMode", Settings.versions(
s.put("syncMode", new EnumSetting(FolderClass.class, FolderClass.INHERITED)); new V(1, new EnumSetting(FolderClass.class, FolderClass.NO_CLASS))
s.put("pushMode", new EnumSetting(FolderClass.class, FolderClass.INHERITED)); ));
s.put("inTopGroup", new BooleanSetting(false)); s.put("syncMode", Settings.versions(
s.put("integrate", new BooleanSetting(false)); new V(1, new EnumSetting(FolderClass.class, FolderClass.INHERITED))
));
s.put("pushMode", Settings.versions(
new V(1, new EnumSetting(FolderClass.class, FolderClass.INHERITED))
));
s.put("inTopGroup", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("integrate", Settings.versions(
new V(1, new BooleanSetting(false))
));
SETTINGS = Collections.unmodifiableMap(s); SETTINGS = Collections.unmodifiableMap(s);
} }
public static Map<String, String> validate(Map<String, String> importedSettings, public static Map<String, String> validate(int version, Map<String, String> importedSettings,
boolean useDefaultValues) { boolean useDefaultValues) {
return Settings.validate(SETTINGS, importedSettings, useDefaultValues); return Settings.validate(version, SETTINGS, importedSettings, useDefaultValues);
} }
public static Map<String, String> getFolderSettings(SharedPreferences storage, String uuid, public static Map<String, String> getFolderSettings(SharedPreferences storage, String uuid,

View File

@ -6,6 +6,8 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.TreeMap;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Environment; import android.os.Environment;
@ -16,74 +18,183 @@ import com.fsck.k9.helper.DateFormatter;
import com.fsck.k9.preferences.Settings.*; import com.fsck.k9.preferences.Settings.*;
public class GlobalSettings { public class GlobalSettings {
public static final Map<String, SettingsDescription> SETTINGS; public static final Map<String, TreeMap<Integer, SettingsDescription>> SETTINGS;
static { static {
Map<String, SettingsDescription> s = new LinkedHashMap<String, SettingsDescription>(); Map<String, TreeMap<Integer, SettingsDescription>> s =
new LinkedHashMap<String, TreeMap<Integer, SettingsDescription>>();
s.put("animations", new BooleanSetting(false)); s.put("animations", Settings.versions(
s.put("attachmentdefaultpath", new V(1, new BooleanSetting(false))
new DirectorySetting(Environment.getExternalStorageDirectory().toString())); ));
s.put("backgroundOperations", s.put("attachmentdefaultpath", Settings.versions(
new EnumSetting(K9.BACKGROUND_OPS.class, K9.BACKGROUND_OPS.WHEN_CHECKED)); new V(1, new DirectorySetting(Environment.getExternalStorageDirectory().toString()))
s.put("changeRegisteredNameColor", new BooleanSetting(false)); ));
s.put("compactLayouts", new BooleanSetting(false)); s.put("backgroundOperations", Settings.versions(
s.put("confirmDelete", new BooleanSetting(false)); new V(1, new EnumSetting(K9.BACKGROUND_OPS.class, K9.BACKGROUND_OPS.WHEN_CHECKED))
s.put("confirmDeleteStarred", new BooleanSetting(false)); // added to version 2 ));
s.put("confirmMarkAllAsRead", new BooleanSetting(false)); s.put("changeRegisteredNameColor", Settings.versions(
s.put("confirmSpam", new BooleanSetting(false)); new V(1, new BooleanSetting(false))
s.put("countSearchMessages", new BooleanSetting(false)); ));
s.put("dateFormat", new DateFormatSetting(DateFormatter.DEFAULT_FORMAT)); s.put("compactLayouts", Settings.versions(
s.put("enableDebugLogging", new BooleanSetting(false)); new V(1, new BooleanSetting(false))
s.put("enableSensitiveLogging", new BooleanSetting(false)); ));
s.put("fontSizeAccountDescription", new FontSizeSetting(FontSizes.SMALL)); s.put("confirmDelete", Settings.versions(
s.put("fontSizeAccountName", new FontSizeSetting(FontSizes.MEDIUM)); new V(1, new BooleanSetting(false))
s.put("fontSizeFolderName", new FontSizeSetting(FontSizes.LARGE)); ));
s.put("fontSizeFolderStatus", new FontSizeSetting(FontSizes.SMALL)); s.put("confirmDeleteStarred", Settings.versions(
s.put("fontSizeMessageListDate", new FontSizeSetting(FontSizes.SMALL)); new V(2, new BooleanSetting(false)) // added to version 2
s.put("fontSizeMessageListPreview", new FontSizeSetting(FontSizes.SMALL)); ));
s.put("fontSizeMessageListSender", new FontSizeSetting(FontSizes.SMALL)); s.put("confirmMarkAllAsRead", Settings.versions(
s.put("fontSizeMessageListSubject", new FontSizeSetting(FontSizes.FONT_16DIP)); new V(1, new BooleanSetting(false))
s.put("fontSizeMessageViewAdditionalHeaders", new FontSizeSetting(FontSizes.FONT_12DIP)); ));
s.put("fontSizeMessageViewCC", new FontSizeSetting(FontSizes.FONT_12DIP)); s.put("confirmSpam", Settings.versions(
s.put("fontSizeMessageViewContent", new WebFontSizeSetting(3)); new V(1, new BooleanSetting(false))
s.put("fontSizeMessageViewDate", new FontSizeSetting(FontSizes.FONT_10DIP)); ));
s.put("fontSizeMessageViewSender", new FontSizeSetting(FontSizes.SMALL)); s.put("countSearchMessages", Settings.versions(
s.put("fontSizeMessageViewSubject", new FontSizeSetting(FontSizes.FONT_12DIP)); new V(1, new BooleanSetting(false))
s.put("fontSizeMessageViewTime", new FontSizeSetting(FontSizes.FONT_10DIP)); ));
s.put("fontSizeMessageViewTo", new FontSizeSetting(FontSizes.FONT_12DIP)); s.put("dateFormat", Settings.versions(
s.put("gesturesEnabled", new BooleanSetting(true)); new V(1, new DateFormatSetting(DateFormatter.DEFAULT_FORMAT))
s.put("hideSpecialAccounts", new BooleanSetting(false)); ));
s.put("keyguardPrivacy", new BooleanSetting(false)); s.put("enableDebugLogging", Settings.versions(
s.put("language", new LanguageSetting()); new V(1, new BooleanSetting(false))
s.put("manageBack", new BooleanSetting(false)); ));
s.put("measureAccounts", new BooleanSetting(true)); s.put("enableSensitiveLogging", Settings.versions(
s.put("messageListCheckboxes", new BooleanSetting(false)); new V(1, new BooleanSetting(false))
s.put("messageListPreviewLines", new IntegerRangeSetting(1, 100, 2)); ));
s.put("messageListStars", new BooleanSetting(true)); s.put("fontSizeAccountDescription", Settings.versions(
s.put("messageListTouchable", new BooleanSetting(false)); new V(1, new FontSizeSetting(FontSizes.SMALL))
s.put("messageViewFixedWidthFont", new BooleanSetting(false)); ));
s.put("messageViewReturnToList", new BooleanSetting(false)); s.put("fontSizeAccountName", Settings.versions(
s.put("messageViewShowNext", new BooleanSetting(false)); new V(1, new FontSizeSetting(FontSizes.MEDIUM))
s.put("mobileOptimizedLayout", new BooleanSetting(false)); ));
s.put("quietTimeEnabled", new BooleanSetting(false)); s.put("fontSizeFolderName", Settings.versions(
s.put("quietTimeEnds", new TimeSetting("7:00")); new V(1, new FontSizeSetting(FontSizes.LARGE))
s.put("quietTimeStarts", new TimeSetting("21:00")); ));
s.put("registeredNameColor", new ColorSetting(0xFF00008F)); s.put("fontSizeFolderStatus", Settings.versions(
s.put("showContactName", new BooleanSetting(false)); new V(1, new FontSizeSetting(FontSizes.SMALL))
s.put("showCorrespondentNames", new BooleanSetting(true)); ));
s.put("startIntegratedInbox", new BooleanSetting(false)); s.put("fontSizeMessageListDate", Settings.versions(
s.put("theme", new ThemeSetting(android.R.style.Theme_Light)); new V(1, new FontSizeSetting(FontSizes.SMALL))
s.put("useGalleryBugWorkaround", new GalleryBugWorkaroundSetting()); ));
s.put("useVolumeKeysForListNavigation", new BooleanSetting(false)); s.put("fontSizeMessageListPreview", Settings.versions(
s.put("useVolumeKeysForNavigation", new BooleanSetting(false)); new V(1, new FontSizeSetting(FontSizes.SMALL))
s.put("zoomControlsEnabled", new BooleanSetting(false)); ));
s.put("fontSizeMessageListSender", Settings.versions(
new V(1, new FontSizeSetting(FontSizes.SMALL))
));
s.put("fontSizeMessageListSubject", Settings.versions(
new V(1, new FontSizeSetting(FontSizes.FONT_16DIP))
));
s.put("fontSizeMessageViewAdditionalHeaders", Settings.versions(
new V(1, new FontSizeSetting(FontSizes.FONT_12DIP))
));
s.put("fontSizeMessageViewCC", Settings.versions(
new V(1, new FontSizeSetting(FontSizes.FONT_12DIP))
));
s.put("fontSizeMessageViewContent", Settings.versions(
new V(1, new WebFontSizeSetting(3))
));
s.put("fontSizeMessageViewDate", Settings.versions(
new V(1, new FontSizeSetting(FontSizes.FONT_10DIP))
));
s.put("fontSizeMessageViewSender", Settings.versions(
new V(1, new FontSizeSetting(FontSizes.SMALL))
));
s.put("fontSizeMessageViewSubject", Settings.versions(
new V(1, new FontSizeSetting(FontSizes.FONT_12DIP))
));
s.put("fontSizeMessageViewTime", Settings.versions(
new V(1, new FontSizeSetting(FontSizes.FONT_10DIP))
));
s.put("fontSizeMessageViewTo", Settings.versions(
new V(1, new FontSizeSetting(FontSizes.FONT_12DIP))
));
s.put("gesturesEnabled", Settings.versions(
new V(1, new BooleanSetting(true))
));
s.put("hideSpecialAccounts", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("keyguardPrivacy", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("language", Settings.versions(
new V(1, new LanguageSetting())
));
s.put("manageBack", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("measureAccounts", Settings.versions(
new V(1, new BooleanSetting(true))
));
s.put("messageListCheckboxes", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("messageListPreviewLines", Settings.versions(
new V(1, new IntegerRangeSetting(1, 100, 2))
));
s.put("messageListStars", Settings.versions(
new V(1, new BooleanSetting(true))
));
s.put("messageListTouchable", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("messageViewFixedWidthFont", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("messageViewReturnToList", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("messageViewShowNext", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("mobileOptimizedLayout", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("quietTimeEnabled", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("quietTimeEnds", Settings.versions(
new V(1, new TimeSetting("7:00"))
));
s.put("quietTimeStarts", Settings.versions(
new V(1, new TimeSetting("21:00"))
));
s.put("registeredNameColor", Settings.versions(
new V(1, new ColorSetting(0xFF00008F))
));
s.put("showContactName", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("showCorrespondentNames", Settings.versions(
new V(1, new BooleanSetting(true))
));
s.put("startIntegratedInbox", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("theme", Settings.versions(
new V(1, new ThemeSetting(android.R.style.Theme_Light))
));
s.put("useGalleryBugWorkaround", Settings.versions(
new V(1, new GalleryBugWorkaroundSetting())
));
s.put("useVolumeKeysForListNavigation", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("useVolumeKeysForNavigation", Settings.versions(
new V(1, new BooleanSetting(false))
));
s.put("zoomControlsEnabled", Settings.versions(
new V(1, new BooleanSetting(false))
));
SETTINGS = Collections.unmodifiableMap(s); SETTINGS = Collections.unmodifiableMap(s);
} }
public static Map<String, String> validate(Map<String, String> importedSettings) { public static Map<String, String> validate(int version, Map<String, String> importedSettings) {
return Settings.validate(SETTINGS, importedSettings, false); return Settings.validate(version, SETTINGS, importedSettings, false);
} }
public static Map<String, String> getGlobalSettings(SharedPreferences storage) { public static Map<String, String> getGlobalSettings(SharedPreferences storage) {

View File

@ -4,6 +4,8 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.TreeMap;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import com.fsck.k9.EmailAddressValidator; import com.fsck.k9.EmailAddressValidator;
@ -12,21 +14,28 @@ import com.fsck.k9.R;
import com.fsck.k9.preferences.Settings.*; import com.fsck.k9.preferences.Settings.*;
public class IdentitySettings { public class IdentitySettings {
public static final Map<String, SettingsDescription> SETTINGS; public static final Map<String, TreeMap<Integer, SettingsDescription>> SETTINGS;
static { static {
Map<String, SettingsDescription> s = new LinkedHashMap<String, SettingsDescription>(); Map<String, TreeMap<Integer, SettingsDescription>> s =
new LinkedHashMap<String, TreeMap<Integer, SettingsDescription>>();
s.put("signature", new SignatureSetting()); s.put("signature", Settings.versions(
s.put("signatureUse", new BooleanSetting(true)); new V(1, new SignatureSetting())
s.put("replyTo", new OptionalEmailAddressSetting()); ));
s.put("signatureUse", Settings.versions(
new V(1, new BooleanSetting(true))
));
s.put("replyTo", Settings.versions(
new V(1, new OptionalEmailAddressSetting())
));
SETTINGS = Collections.unmodifiableMap(s); SETTINGS = Collections.unmodifiableMap(s);
} }
public static Map<String, String> validate(Map<String, String> importedSettings, public static Map<String, String> validate(int version, Map<String, String> importedSettings,
boolean useDefaultValues) { boolean useDefaultValues) {
return Settings.validate(SETTINGS, importedSettings, useDefaultValues); return Settings.validate(version, SETTINGS, importedSettings, useDefaultValues);
} }
public static Map<String, String> getIdentitySettings(SharedPreferences storage, String uuid, public static Map<String, String> getIdentitySettings(SharedPreferences storage, String uuid,

View File

@ -3,6 +3,7 @@ package com.fsck.k9.preferences;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.TreeMap;
import java.util.Map.Entry; import java.util.Map.Entry;
import android.util.Log; import android.util.Log;
@ -34,12 +35,22 @@ public class Settings {
*/ */
public static final int VERSION = 3; public static final int VERSION = 3;
public static Map<String, String> validate(Map<String, SettingsDescription> settings, public static Map<String, String> validate(int version, Map<String,
TreeMap<Integer, SettingsDescription>> settings,
Map<String, String> importedSettings, boolean useDefaultValues) { Map<String, String> importedSettings, boolean useDefaultValues) {
Map<String, String> validatedSettings = new HashMap<String, String>(); Map<String, String> validatedSettings = new HashMap<String, String>();
for (Map.Entry<String, SettingsDescription> setting : settings.entrySet()) { for (Map.Entry<String, TreeMap<Integer, SettingsDescription>> versionedSetting :
String key = setting.getKey(); settings.entrySet()) {
Entry<Integer, SettingsDescription> setting =
versionedSetting.getValue().floorEntry(version);
if (setting == null) {
continue;
}
String key = versionedSetting.getKey();
SettingsDescription desc = setting.getValue(); SettingsDescription desc = setting.getValue();
boolean useDefaultValue; boolean useDefaultValue;
@ -72,6 +83,31 @@ public class Settings {
return validatedSettings; return validatedSettings;
} }
/**
* Creates a {@link TreeMap} linking version numbers to {@link SettingsDescription} instances.
*
* <p>
* This {@code TreeMap} is used to quickly find the {@code SettingsDescription} belonging to a
* content version as read by {@link SettingsImporter}. See e.g.
* {@link Settings#validate(int, Map, Map, boolean)}.
* </p>
*
* @param versionDescriptions
* A list of descriptions for a specific setting mapped to version numbers. Never
* {@code null}.
*
* @return A {@code TreeMap} using the version number as key, the {@code SettingsDescription}
* as value.
*/
public static TreeMap<Integer, SettingsDescription> versions(
V... versionDescriptions) {
TreeMap<Integer, SettingsDescription> map = new TreeMap<Integer, SettingsDescription>();
for (V v : versionDescriptions) {
map.put(v.version, v.description);
}
return map;
}
/** /**
* Indicates an invalid setting value. * Indicates an invalid setting value.
@ -183,6 +219,22 @@ public class Settings {
} }
} }
/**
* Container to hold a {@link SettingsDescription} instance and a version number.
*
* @see Settings#versions(V...)
*/
public static class V {
public final Integer version;
public final SettingsDescription description;
public V(Integer version, SettingsDescription description) {
this.version = version;
this.description = description;
}
}
/** /**
* A string setting. * A string setting.
*/ */

View File

@ -167,11 +167,14 @@ public class SettingsExporter {
private static void writeSettings(XmlSerializer serializer, private static void writeSettings(XmlSerializer serializer,
Map<String, Object> prefs) throws IOException { Map<String, Object> prefs) throws IOException {
for (String key : GlobalSettings.SETTINGS.keySet()) { for (Entry<String, TreeMap<Integer, SettingsDescription>> versionedSetting :
GlobalSettings.SETTINGS.entrySet()) {
String key = versionedSetting.getKey();
String valueString = (String) prefs.get(key); String valueString = (String) prefs.get(key);
SettingsDescription setting = versionedSetting.getValue().lastEntry().getValue();
if (valueString != null) { if (valueString != null) {
try { try {
SettingsDescription setting = GlobalSettings.SETTINGS.get(key);
Object value = setting.fromString(valueString); Object value = setting.fromString(valueString);
String outputValue = setting.toPrettyString(value); String outputValue = setting.toPrettyString(value);
writeKeyValue(serializer, key, outputValue); writeKeyValue(serializer, key, outputValue);
@ -185,7 +188,6 @@ public class SettingsExporter {
"Using default value."); "Using default value.");
} }
SettingsDescription setting = GlobalSettings.SETTINGS.get(key);
Object value = setting.getDefaultValue(); Object value = setting.getDefaultValue();
String outputValue = setting.toPrettyString(value); String outputValue = setting.toPrettyString(value);
writeKeyValue(serializer, key, outputValue); writeKeyValue(serializer, key, outputValue);
@ -311,8 +313,12 @@ public class SettingsExporter {
keyPart = secondPart; keyPart = secondPart;
} }
SettingsDescription setting = AccountSettings.SETTINGS.get(keyPart); TreeMap<Integer, SettingsDescription> versionedSetting =
if (setting != null) { AccountSettings.SETTINGS.get(keyPart);
if (versionedSetting != null) {
SettingsDescription setting = versionedSetting.lastEntry().getValue();
// Only export account settings that can be found in AccountSettings.SETTINGS // Only export account settings that can be found in AccountSettings.SETTINGS
try { try {
Object value = setting.fromString(valueString); Object value = setting.fromString(valueString);
@ -399,8 +405,12 @@ public class SettingsExporter {
continue; continue;
} }
SettingsDescription setting = IdentitySettings.SETTINGS.get(identityKey); TreeMap<Integer, SettingsDescription> versionedSetting =
if (setting != null) { IdentitySettings.SETTINGS.get(identityKey);
if (versionedSetting != null) {
SettingsDescription setting = versionedSetting.lastEntry().getValue();
// Only write settings that have an entry in IdentitySettings.SETTINGS // Only write settings that have an entry in IdentitySettings.SETTINGS
try { try {
Object value = setting.fromString(valueString); Object value = setting.fromString(valueString);
@ -444,8 +454,12 @@ public class SettingsExporter {
continue; continue;
} }
SettingsDescription setting = FolderSettings.SETTINGS.get(folderKey); TreeMap<Integer, SettingsDescription> versionedSetting =
if (setting != null) { FolderSettings.SETTINGS.get(folderKey);
if (versionedSetting != null) {
SettingsDescription setting = versionedSetting.lastEntry().getValue();
// Only write settings that have an entry in FolderSettings.SETTINGS // Only write settings that have an entry in FolderSettings.SETTINGS
try { try {
Object value = setting.fromString(valueString); Object value = setting.fromString(valueString);

View File

@ -191,7 +191,8 @@ public class SettingsImporter {
try { try {
SharedPreferences.Editor editor = storage.edit(); SharedPreferences.Editor editor = storage.edit();
if (imported.globalSettings != null) { if (imported.globalSettings != null) {
importGlobalSettings(storage, editor, imported.globalSettings); importGlobalSettings(storage, editor, imported.contentVersion,
imported.globalSettings);
} else { } else {
Log.w(K9.LOG_TAG, "Was asked to import global settings but none found."); Log.w(K9.LOG_TAG, "Was asked to import global settings but none found.");
} }
@ -222,7 +223,7 @@ public class SettingsImporter {
SharedPreferences.Editor editor = storage.edit(); SharedPreferences.Editor editor = storage.edit();
AccountDescriptionPair importResult = importAccount(context, AccountDescriptionPair importResult = importAccount(context,
editor, account, overwrite); editor, imported.contentVersion, account, overwrite);
String newUuid = importResult.imported.uuid; String newUuid = importResult.imported.uuid;
if (!importResult.overwritten) { if (!importResult.overwritten) {
@ -300,9 +301,10 @@ public class SettingsImporter {
} }
private static void importGlobalSettings(SharedPreferences storage, private static void importGlobalSettings(SharedPreferences storage,
SharedPreferences.Editor editor, ImportedSettings settings) { SharedPreferences.Editor editor, int contentVersion, ImportedSettings settings) {
Map<String, String> validatedSettings = GlobalSettings.validate(settings.settings); Map<String, String> validatedSettings = GlobalSettings.validate(contentVersion,
settings.settings);
// Use current global settings as base and overwrite with validated settings read from the // Use current global settings as base and overwrite with validated settings read from the
// import file. // import file.
@ -318,8 +320,8 @@ public class SettingsImporter {
} }
private static AccountDescriptionPair importAccount(Context context, private static AccountDescriptionPair importAccount(Context context,
SharedPreferences.Editor editor, ImportedAccount account, boolean overwrite) SharedPreferences.Editor editor, int contentVersion, ImportedAccount account,
throws InvalidSettingValueException { boolean overwrite) throws InvalidSettingValueException {
AccountDescription original = new AccountDescription(account.name, account.uuid); AccountDescription original = new AccountDescription(account.name, account.uuid);
@ -391,7 +393,8 @@ public class SettingsImporter {
// Validate account settings // Validate account settings
Map<String, String> validatedSettings = Map<String, String> validatedSettings =
AccountSettings.validate(account.settings.settings, !mergeImportedAccount); AccountSettings.validate(contentVersion, account.settings.settings,
!mergeImportedAccount);
// Merge account settings if necessary // Merge account settings if necessary
Map<String, String> writeSettings; Map<String, String> writeSettings;
@ -418,7 +421,8 @@ public class SettingsImporter {
// Write identities // Write identities
if (account.identities != null) { if (account.identities != null) {
importIdentities(editor, uuid, account, overwrite, existingAccount, prefs); importIdentities(editor, contentVersion, uuid, account, overwrite, existingAccount,
prefs);
} else if (!mergeImportedAccount) { } else if (!mergeImportedAccount) {
// Require accounts to at least have one identity // Require accounts to at least have one identity
throw new InvalidSettingValueException(); throw new InvalidSettingValueException();
@ -427,7 +431,7 @@ public class SettingsImporter {
// Write folder settings // Write folder settings
if (account.folders != null) { if (account.folders != null) {
for (ImportedFolder folder : account.folders) { for (ImportedFolder folder : account.folders) {
importFolder(editor, uuid, folder, mergeImportedAccount, prefs); importFolder(editor, contentVersion, uuid, folder, mergeImportedAccount, prefs);
} }
} }
@ -437,12 +441,12 @@ public class SettingsImporter {
return new AccountDescriptionPair(original, imported, mergeImportedAccount); return new AccountDescriptionPair(original, imported, mergeImportedAccount);
} }
private static void importFolder(SharedPreferences.Editor editor, String uuid, private static void importFolder(SharedPreferences.Editor editor, int contentVersion,
ImportedFolder folder, boolean overwrite, Preferences prefs) { String uuid, ImportedFolder folder, boolean overwrite, Preferences prefs) {
// Validate folder settings // Validate folder settings
Map<String, String> validatedSettings = Map<String, String> validatedSettings =
FolderSettings.validate(folder.settings.settings, !overwrite); FolderSettings.validate(contentVersion, folder.settings.settings, !overwrite);
// Merge folder settings if necessary // Merge folder settings if necessary
Map<String, String> writeSettings; Map<String, String> writeSettings;
@ -463,8 +467,8 @@ public class SettingsImporter {
} }
} }
private static void importIdentities(SharedPreferences.Editor editor, String uuid, private static void importIdentities(SharedPreferences.Editor editor, int contentVersion,
ImportedAccount account, boolean overwrite, Account existingAccount, String uuid, ImportedAccount account, boolean overwrite, Account existingAccount,
Preferences prefs) throws InvalidSettingValueException { Preferences prefs) throws InvalidSettingValueException {
String accountKeyPrefix = uuid + "."; String accountKeyPrefix = uuid + ".";
@ -531,7 +535,7 @@ public class SettingsImporter {
if (identity.settings != null) { if (identity.settings != null) {
// Validate identity settings // Validate identity settings
Map<String, String> validatedSettings = IdentitySettings.validate( Map<String, String> validatedSettings = IdentitySettings.validate(
identity.settings.settings, !mergeSettings); contentVersion, identity.settings.settings, !mergeSettings);
// Merge identity settings if necessary // Merge identity settings if necessary
Map<String, String> writeSettings; Map<String, String> writeSettings;
@ -677,7 +681,7 @@ public class SettingsImporter {
String contentVersionString = xpp.getAttributeValue(null, String contentVersionString = xpp.getAttributeValue(null,
SettingsExporter.VERSION_ATTRIBUTE); SettingsExporter.VERSION_ATTRIBUTE);
validateContentVersion(contentVersionString); result.contentVersion = validateContentVersion(contentVersionString);
int eventType = xpp.next(); int eventType = xpp.next();
while (!(eventType == XmlPullParser.END_TAG && while (!(eventType == XmlPullParser.END_TAG &&
@ -756,7 +760,7 @@ public class SettingsImporter {
versionString); versionString);
} }
if (version != Settings.VERSION) { if (version < 1 || version > Settings.VERSION) {
throw new SettingsImportExportException("Unsupported content version: " + throw new SettingsImportExportException("Unsupported content version: " +
versionString); versionString);
} }
@ -1066,6 +1070,7 @@ public class SettingsImporter {
} }
private static class Imported { private static class Imported {
public int contentVersion;
public ImportedSettings globalSettings; public ImportedSettings globalSettings;
public Map<String, ImportedAccount> accounts; public Map<String, ImportedAccount> accounts;
} }