diff --git a/core/AndroidManifest.xml b/core/AndroidManifest.xml index 1bb75454..80c57969 100644 --- a/core/AndroidManifest.xml +++ b/core/AndroidManifest.xml @@ -17,8 +17,8 @@ --> + android:versionCode="6" + android:versionName="2.0" > - - - - - - - - - - + + + + + \ No newline at end of file diff --git a/core/res/layout-v11/activity_widgetconfig.xml b/core/res/layout-v11/activity_widgetconfig.xml new file mode 100644 index 00000000..9cf2564f --- /dev/null +++ b/core/res/layout-v11/activity_widgetconfig.xml @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/res/layout-v11/list_item_widget_dark.xml b/core/res/layout-v11/list_item_widget_dark.xml new file mode 100644 index 00000000..0b1aa4a0 --- /dev/null +++ b/core/res/layout-v11/list_item_widget_dark.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/res/layout-v11/list_item_widget_light.xml b/core/res/layout-v11/list_item_widget_light.xml new file mode 100644 index 00000000..3e7fdd21 --- /dev/null +++ b/core/res/layout-v11/list_item_widget_light.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/res/layout-v11/widget_torrents_dark.xml b/core/res/layout-v11/widget_torrents_dark.xml new file mode 100644 index 00000000..31b51077 --- /dev/null +++ b/core/res/layout-v11/widget_torrents_dark.xml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/res/layout-v11/widget_torrents_light.xml b/core/res/layout-v11/widget_torrents_light.xml new file mode 100644 index 00000000..63f9b868 --- /dev/null +++ b/core/res/layout-v11/widget_torrents_light.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/core/res/values-sw600dp/dimens.xml b/core/res/values-sw600dp/dimens.xml index 268734c6..4f9b8522 100644 --- a/core/res/values-sw600dp/dimens.xml +++ b/core/res/values-sw600dp/dimens.xml @@ -16,11 +16,6 @@ --> - - 16dp - 8dp - 16dp - 14sp 17sp @@ -40,4 +35,10 @@ 14sp 63dp + + 0 + 30dp + -1dp + 300dp + diff --git a/core/res/layout/actionbar_progressitem.xml b/core/res/values-v11/bools.xml similarity index 50% rename from core/res/layout/actionbar_progressitem.xml rename to core/res/values-v11/bools.xml index 540be947..2ea1c4b9 100644 --- a/core/res/layout/actionbar_progressitem.xml +++ b/core/res/values-v11/bools.xml @@ -15,26 +15,7 @@ You should have received a copy of the GNU General Public License along with Transdroid. If not, see . --> - - - - - - - - - - + + + true + diff --git a/core/res/values-v14/dimens.xml b/core/res/values-v14/dimens.xml new file mode 100644 index 00000000..54dfd51f --- /dev/null +++ b/core/res/values-v14/dimens.xml @@ -0,0 +1,21 @@ + + + + 0dp + + diff --git a/core/res/values/attrs.xml b/core/res/values/attrs.xml index 5bd9fc95..64c2f81e 100644 --- a/core/res/values/attrs.xml +++ b/core/res/values/attrs.xml @@ -42,6 +42,7 @@ + diff --git a/core/res/values/bools.xml b/core/res/values/bools.xml index 07368b72..a79e6d70 100644 --- a/core/res/values/bools.xml +++ b/core/res/values/bools.xml @@ -18,4 +18,6 @@ true + + false diff --git a/core/res/values/changelog.xml b/core/res/values/changelog.xml index 000c8fdd..b4483df1 100644 --- a/core/res/values/changelog.xml +++ b/core/res/values/changelog.xml @@ -18,6 +18,7 @@ Transdroid 2.0.0\n +- Scrollable home screen widget (Android 3+)\n - Allow changing of storage location (Deluge and Transmission)\n - Allow file downloads via AndFTP\n - UI improvements for Lite version\n diff --git a/core/res/values/colors.xml b/core/res/values/colors.xml index 3b390f16..d9096474 100644 --- a/core/res/values/colors.xml +++ b/core/res/values/colors.xml @@ -16,8 +16,22 @@ along with Transdroid. If not, see . --> + + #8acc12 #7dbb21 #c81113 #aada62 + + + #42a8fa + #a759d4 + #8acc12 + #de3939 + #9e9e9e + #c8e88e + #8acc12 + #4b6617 + #9e9e9e + diff --git a/core/res/values/dimens.xml b/core/res/values/dimens.xml index 21633559..a7e05008 100644 --- a/core/res/values/dimens.xml +++ b/core/res/values/dimens.xml @@ -20,6 +20,7 @@ 16dp 8dp 16dp + 8dp 12sp @@ -40,4 +41,15 @@ 13sp 53dp + + 1 + 20dp + 200dp + -1dp + 46dp + 6dp + 54dp + 6dp + 12dp + diff --git a/core/res/values/strings.xml b/core/res/values/strings.xml index 92e97c81..0d90b8cb 100644 --- a/core/res/values/strings.xml +++ b/core/res/values/strings.xml @@ -190,6 +190,15 @@ New torrents for %1$s + Loading… + Open Transdroid + SERVER VIEW + LOOK & FEEL + SORT ORDER + Reversed sort order + Use dark theme (no preview) + DONE + Servers Add new server Search sites diff --git a/core/res/values/styles.xml b/core/res/values/styles.xml index bf67e11f..4e0cbf9a 100644 --- a/core/res/values/styles.xml +++ b/core/res/values/styles.xml @@ -17,11 +17,12 @@ - + + + + + - + - - + + \ No newline at end of file diff --git a/core/res/xml/appwidget_info.xml b/core/res/xml/appwidget_info.xml new file mode 100644 index 00000000..7846f411 --- /dev/null +++ b/core/res/xml/appwidget_info.xml @@ -0,0 +1,29 @@ + + + diff --git a/core/src/org/transdroid/core/app/settings/ApplicationSettings.java b/core/src/org/transdroid/core/app/settings/ApplicationSettings.java index 3fc0eeec..75a21031 100644 --- a/core/src/org/transdroid/core/app/settings/ApplicationSettings.java +++ b/core/src/org/transdroid/core/app/settings/ApplicationSettings.java @@ -16,6 +16,7 @@ */ package org.transdroid.core.app.settings; +import java.security.InvalidParameterException; import java.util.ArrayList; import java.util.Collections; import java.util.Date; @@ -29,7 +30,9 @@ import org.json.JSONArray; import org.json.JSONException; import org.transdroid.core.app.search.SearchHelper; import org.transdroid.core.app.search.SearchSite; +import org.transdroid.core.gui.navigation.StatusType; import org.transdroid.core.gui.search.SearchSetting; +import org.transdroid.core.widget.WidgetConfig; import org.transdroid.daemon.Daemon; import org.transdroid.daemon.OS; import org.transdroid.daemon.TorrentsSortBy; @@ -412,7 +415,7 @@ public class ApplicationSettings { all.addAll(getWebsearchSettings()); return Collections.unmodifiableList(all); } - + /** * Returns the settings of the search site that was last used by the user or was selected by the user as default * site in the main settings. As opposed to getLastUsedSearchSiteKey(int), this method checks whether a site was @@ -438,7 +441,7 @@ public class ApplicationSettings { } return null; } - + if (lastWebsearch >= 0) { // The last used site should be a user-configured web search site int max = getMaxWebsearch(); // Zero-based index, so with max == 0 there is 1 server @@ -448,7 +451,7 @@ public class ApplicationSettings { } return getWebsearchSetting(lastWebsearch); } - + // Should be an in-app search key if (allsites != null) { for (SearchSite searchSite : allsites) { @@ -459,7 +462,7 @@ public class ApplicationSettings { // Not found at all; probably a no longer existing web search; return the first in-app one return allsites.get(0); } - + return null; } @@ -507,5 +510,56 @@ public class ApplicationSettings { public void setServerLastStats(ServerSetting server, JSONArray lastStats) { prefs.edit().putString(server.getUniqueIdentifier(), lastStats.toString()).commit(); } - + + /** + * Returns the user configuration for some specific app widget, if the widget is known at all. + * @param appWidgetId The unique ID of the app widget to retrieve settings for, as supplied by the AppWidgetManager + * @return A widget configuration object, or null if no settings were stored for the widget ID + */ + public WidgetConfig getWidgetConfig(int appWidgetId) { + if (!prefs.contains("widget_server_" + appWidgetId)) + return null; + // @formatter:off + return new WidgetConfig( + prefs.getInt("widget_server_" + appWidgetId, -1), + StatusType.valueOf(prefs.getString("widget_status_" + appWidgetId, StatusType.ShowAll.name())), + TorrentsSortBy.valueOf(prefs.getString("widget_sortby_" + appWidgetId, TorrentsSortBy.Alphanumeric.name())), + prefs.getBoolean("widget_reverse_" + appWidgetId, false), + prefs.getBoolean("widget_darktheme_" + appWidgetId, false)); + // @formatter:on + } + + /** + * Stores the user settings for some specific app widget. Existing settings for the supplied app widget ID will be + * overridden. + * @param appWidgetId The unique ID of the app widget to store settings for, as supplied by the AppWidgetManager + * @param settings A widget configuration object, which may not be null + */ + public void setWidgetConfig(int appWidgetId, WidgetConfig settings) { + if (settings == null) + throw new InvalidParameterException( + "The widget setting may not be null. Use removeWidgetConfig instead to remove existing settings for some app widget."); + Editor edit = prefs.edit(); + edit.putInt("widget_server_" + appWidgetId, settings.getServerId()); + edit.putString("widget_status_" + appWidgetId, settings.getStatusType().name()); + edit.putString("widget_sortby_" + appWidgetId, settings.getSortBy().name()); + edit.putBoolean("widget_reverse_" + appWidgetId, settings.shouldReserveSort()); + edit.putBoolean("widget_darktheme_" + appWidgetId, settings.shouldUseDarkTheme()); + edit.commit(); + } + + /** + * Remove the setting for some specific app widget. + * @param appWidgetId The unique ID of the app widget to store settings for, as supplied by the AppWidgetManager + */ + public void removeWidgetConfig(int appWidgetId) { + Editor edit = prefs.edit(); + edit.remove("widget_server_" + appWidgetId); + edit.remove("widget_status_" + appWidgetId); + edit.remove("widget_sortby_" + appWidgetId); + edit.remove("widget_reverse_" + appWidgetId); + edit.remove("widget_darktheme_" + appWidgetId); + edit.commit(); + } + } diff --git a/core/src/org/transdroid/core/gui/FilterEntryDialog.java b/core/src/org/transdroid/core/gui/FilterEntryDialog.java index 8e9c2425..01c45c1b 100644 --- a/core/src/org/transdroid/core/gui/FilterEntryDialog.java +++ b/core/src/org/transdroid/core/gui/FilterEntryDialog.java @@ -16,6 +16,7 @@ */ package org.transdroid.core.gui; +import android.annotation.SuppressLint; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; @@ -32,6 +33,7 @@ public class FilterEntryDialog { * torrents. * @param activity The activity that opens (and owns) this dialog */ + @SuppressLint("ValidFragment") public static void startFilterEntry(final TorrentsActivity activity) { new DialogFragment() { public android.app.Dialog onCreateDialog(android.os.Bundle savedInstanceState) { diff --git a/core/src/org/transdroid/core/gui/TorrentsActivity.java b/core/src/org/transdroid/core/gui/TorrentsActivity.java index 0fc45c09..5f09ef4f 100644 --- a/core/src/org/transdroid/core/gui/TorrentsActivity.java +++ b/core/src/org/transdroid/core/gui/TorrentsActivity.java @@ -56,6 +56,7 @@ import org.transdroid.core.gui.search.UrlEntryDialog; import org.transdroid.core.gui.settings.*; import org.transdroid.core.service.BootReceiver; import org.transdroid.core.service.ConnectivityHelper; +import org.transdroid.core.widget.WidgetProvider; import org.transdroid.daemon.Daemon; import org.transdroid.daemon.IDaemonAdapter; import org.transdroid.daemon.Priority; @@ -212,9 +213,19 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi // No server settings yet; return; } - if (getIntent().getExtras() == null && getIntent().hasExtra("org.transdroid.START_SERVER")) { - lastUsed = applicationSettings.getServerSetting(getIntent().getExtras().getInt( - "org.transdroid.START_SERVER")); + Torrent startTorrent = null; + if (getIntent().getAction() != null && getIntent().getAction().equals(WidgetProvider.INTENT_STARTSERVER) + && getIntent().getExtras() == null && getIntent().hasExtra(WidgetProvider.EXTRA_SERVER)) { + // A server settings order ID was provided in this org.transdroid.START_SERVER action intent + int serverId = getIntent().getExtras().getInt(WidgetProvider.EXTRA_SERVER); + if (serverId < 0 || serverId > applicationSettings.getMaxServer()) { + Log.e(this, "Tried to start with " + WidgetProvider.EXTRA_SERVER + " intent but " + serverId + + " is not an existing server order id"); + } else { + lastUsed = applicationSettings.getServerSetting(serverId); + if (getIntent().hasExtra(WidgetProvider.EXTRA_TORRENT)) + startTorrent = getIntent().getParcelableExtra(WidgetProvider.EXTRA_TORRENT); + } } // Set this as selection in the action bar spinner; we can use the server setting key since we have stable ids @@ -222,7 +233,10 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi skipNextOnNavigationItemSelectedCall = true; // Handle any start up intents - if (firstStart && getIntent() != null) { + if (startTorrent != null) { + openDetails(startTorrent); + startTorrent = null; + } else if (firstStart && getIntent() != null) { currentConnection = lastUsed.createServerAdapter(connectivityHelper.getConnectedNetworkName()); handleStartIntent(); } @@ -495,7 +509,7 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi } return true; } - + @OptionsItem(resName = "action_add_fromurl") protected void startUrlEntryDialog() { UrlEntryDialog.startUrlEntry(this); diff --git a/core/src/org/transdroid/core/gui/lists/SimpleListItemSpinnerAdapter.java b/core/src/org/transdroid/core/gui/lists/SimpleListItemSpinnerAdapter.java new file mode 100644 index 00000000..0d33e654 --- /dev/null +++ b/core/src/org/transdroid/core/gui/lists/SimpleListItemSpinnerAdapter.java @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2013 Eric Kok et al. + * + * Transdroid 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 3 of the License, or + * (at your option) any later version. + * + * Transdroid 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 Transdroid. If not, see . + */ +package org.transdroid.core.gui.lists; + +import java.util.List; + +import android.content.Context; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ArrayAdapter; +import android.widget.TextView; + +/** + * A wrapper around {@link ArrayAdapter} that contains {@link SimpleListItem}s which simply show their name in the + * Spinner. The standard Android spinner resources are used for the layout. + * @author Eric Kok + */ +public class SimpleListItemSpinnerAdapter extends ArrayAdapter { + + /** + * Constructs the adapter, supplying the {@link SimpleListItem}s to show in the spinner. The given resource will be + * ignored as the standard Android Spinner layout is used instead. + * @param context The UI context to inflate the layout in + * @param resource This is ignored; android.R.layout.simple_spinner_item is always used instead + * @param objects The items to show in the spinner, which can simply display some name + */ + public SimpleListItemSpinnerAdapter(Context context, int resource, List objects) { + super(context, android.R.layout.simple_spinner_item, objects); + setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + } + + @Override + public View getView(int position, View convertView, ViewGroup parent) { + // This relies on the ArrayAdapter implementation and the used standard xml layouts that simply return a + // TextView; this can then be filled with the SimpleListItem's name instead of the standard toString() + // implementation + TextView text = (TextView) super.getView(position, convertView, parent); + text.setText(getItem(position).getName()); + return text; + } + + @Override + public View getDropDownView(int position, View convertView, ViewGroup parent) { + // This relies on the ArrayAdapter implementation and the used standard xml layouts that simply return a + // TextView; this can then be filled with the SimpleListItem's name instead of the standard toString() + // implementation + TextView text = (TextView) super.getDropDownView(position, convertView, parent); + text.setText(getItem(position).getName()); + return text; + } + +} diff --git a/core/src/org/transdroid/core/gui/lists/SortByListItem.java b/core/src/org/transdroid/core/gui/lists/SortByListItem.java new file mode 100644 index 00000000..90e6110d --- /dev/null +++ b/core/src/org/transdroid/core/gui/lists/SortByListItem.java @@ -0,0 +1,70 @@ +/* + * Copyright 2010-2013 Eric Kok et al. + * + * Transdroid 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 3 of the License, or + * (at your option) any later version. + * + * Transdroid 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 Transdroid. If not, see . + */ +package org.transdroid.core.gui.lists; + +import org.transdroid.core.R; +import org.transdroid.daemon.TorrentsSortBy; + +import android.content.Context; + +/** + * Represents a way in which a torrents list can be sorted. + * @author Eric Kok + */ +public class SortByListItem implements SimpleListItem { + + private final TorrentsSortBy sortBy; + private final String name; + + public SortByListItem(Context context, TorrentsSortBy sortBy) { + this.sortBy = sortBy; + switch (sortBy) { + case DateAdded: + this.name = context.getString(R.string.action_sort_added); + break; + case DateDone: + this.name = context.getString(R.string.action_sort_done); + break; + case Ratio: + this.name = context.getString(R.string.action_sort_ratio); + break; + case Status: + this.name = context.getString(R.string.action_sort_status); + break; + case UploadSpeed: + this.name = context.getString(R.string.action_sort_upspeed); + break; + default: + this.name = context.getString(R.string.action_sort_alpha); + break; + } + } + + /** + * Returns the contained represented sort order. + * @return The sort by order as its enumeration value + */ + public TorrentsSortBy getSortBy() { + return sortBy; + } + + @Override + public String getName() { + return name; + } + +} diff --git a/core/src/org/transdroid/core/gui/lists/TorrentFilePriorityLayout.java b/core/src/org/transdroid/core/gui/lists/TorrentFilePriorityLayout.java index 1e88ce48..480dfdaa 100644 --- a/core/src/org/transdroid/core/gui/lists/TorrentFilePriorityLayout.java +++ b/core/src/org/transdroid/core/gui/lists/TorrentFilePriorityLayout.java @@ -16,6 +16,7 @@ */ package org.transdroid.core.gui.lists; +import org.transdroid.core.R; import org.transdroid.daemon.Priority; import android.content.Context; @@ -56,10 +57,10 @@ public class TorrentFilePriorityLayout extends CheckableRelativeLayout { } private void initPaints() { - offPaint.setColor(0xFF9E9E9E); // Grey - lowPaint.setColor(0xFFC8E88E); // Light green - normalPaint.setColor(0xFF8ACC12); // Normal green - highPaint.setColor(0xFF4B6617); // Dark green + offPaint.setColor(getResources().getColor(R.color.file_off)); + lowPaint.setColor(getResources().getColor(R.color.file_low)); + normalPaint.setColor(getResources().getColor(R.color.file_normal)); + highPaint.setColor(getResources().getColor(R.color.file_high)); } public void setPriority(Priority priority) { diff --git a/core/src/org/transdroid/core/gui/lists/TorrentStatusLayout.java b/core/src/org/transdroid/core/gui/lists/TorrentStatusLayout.java index e6cf1767..7b9f6954 100644 --- a/core/src/org/transdroid/core/gui/lists/TorrentStatusLayout.java +++ b/core/src/org/transdroid/core/gui/lists/TorrentStatusLayout.java @@ -16,6 +16,7 @@ */ package org.transdroid.core.gui.lists; +import org.transdroid.core.R; import org.transdroid.daemon.TorrentStatus; import android.content.Context; @@ -37,10 +38,10 @@ public class TorrentStatusLayout extends CheckableRelativeLayout { private final int WIDTH = (int) (6 * scale + 0.5f); private TorrentStatus status = null; - private final Paint inactiveDonePaint = new Paint(); - private final Paint inactivePaint = new Paint(); - private final Paint progressPaint = new Paint(); - private final Paint donePaint = new Paint(); + private final Paint pausedPaint = new Paint(); + private final Paint otherPaint = new Paint(); + private final Paint downloadingPaint = new Paint(); + private final Paint seedingPaint = new Paint(); private final Paint errorPaint = new Paint(); private final RectF fullRect = new RectF(); @@ -57,11 +58,11 @@ public class TorrentStatusLayout extends CheckableRelativeLayout { } private void initPaints() { - inactiveDonePaint.setColor(0xFFA759D4); // Purple - inactivePaint.setColor(0xFF9E9E9E); // Grey - progressPaint.setColor(0xFF42A8FA); // Blue - donePaint.setColor(0xFF8ACC12); // Green - errorPaint.setColor(0xFFDE3939); // Red + pausedPaint.setColor(getResources().getColor(R.color.torrent_paused)); + otherPaint.setColor(getResources().getColor(R.color.torrent_other)); + downloadingPaint.setColor(getResources().getColor(R.color.torrent_downloading)); + seedingPaint.setColor(getResources().getColor(R.color.torrent_seeding)); + errorPaint.setColor(getResources().getColor(R.color.torrent_error)); } /** @@ -85,22 +86,22 @@ public class TorrentStatusLayout extends CheckableRelativeLayout { if (status == null) { return; } - + switch (status) { case Downloading: - canvas.drawRect(fullRect, progressPaint); + canvas.drawRect(fullRect, downloadingPaint); break; case Paused: - canvas.drawRect(fullRect, inactiveDonePaint); + canvas.drawRect(fullRect, pausedPaint); break; case Seeding: - canvas.drawRect(fullRect, donePaint); + canvas.drawRect(fullRect, seedingPaint); break; case Error: canvas.drawRect(fullRect, errorPaint); break; default: // Checking, Waiting, Queued, Unknown - canvas.drawRect(fullRect, inactivePaint); + canvas.drawRect(fullRect, otherPaint); break; } diff --git a/core/src/org/transdroid/core/gui/navigation/StatusType.java b/core/src/org/transdroid/core/gui/navigation/StatusType.java index 74b26190..58d7c11d 100644 --- a/core/src/org/transdroid/core/gui/navigation/StatusType.java +++ b/core/src/org/transdroid/core/gui/navigation/StatusType.java @@ -35,27 +35,27 @@ import android.os.Parcelable; public enum StatusType { ShowAll { - StatusTypeFilter getFilterItem(Context context) { + public StatusTypeFilter getFilterItem(Context context) { return new StatusTypeFilter(StatusType.ShowAll, context.getString(R.string.navigation_status_showall)); } }, OnlyDownloading { - StatusTypeFilter getFilterItem(Context context) { + public StatusTypeFilter getFilterItem(Context context) { return new StatusTypeFilter(StatusType.OnlyDownloading, context.getString(R.string.navigation_status_onlydown)); } }, OnlyUploading { - StatusTypeFilter getFilterItem(Context context) { + public StatusTypeFilter getFilterItem(Context context) { return new StatusTypeFilter(StatusType.OnlyUploading, context.getString(R.string.navigation_status_onlyup)); } }, OnlyActive { - StatusTypeFilter getFilterItem(Context context) { + public StatusTypeFilter getFilterItem(Context context) { return new StatusTypeFilter(StatusType.OnlyActive, context.getString(R.string.navigation_status_onlyactive)); } }, OnlyInactive { - StatusTypeFilter getFilterItem(Context context) { + public StatusTypeFilter getFilterItem(Context context) { return new StatusTypeFilter(StatusType.OnlyInactive, context.getString(R.string.navigation_status_onlyinactive)); } }; @@ -85,7 +85,7 @@ public enum StatusType { * @param context The Android UI context, to access translations * @return A filter item object to show in the GUI */ - abstract StatusTypeFilter getFilterItem(Context context); + public abstract StatusTypeFilter getFilterItem(Context context); public static class StatusTypeFilter implements SimpleListItem, NavigationFilter { @@ -97,6 +97,10 @@ public enum StatusType { this.name = name; } + public StatusType getStatusType() { + return statusType; + } + @Override public String getName() { return name; diff --git a/core/src/org/transdroid/core/gui/search/BarcodeHelper.java b/core/src/org/transdroid/core/gui/search/BarcodeHelper.java index c4e89e30..e5397368 100644 --- a/core/src/org/transdroid/core/gui/search/BarcodeHelper.java +++ b/core/src/org/transdroid/core/gui/search/BarcodeHelper.java @@ -19,6 +19,7 @@ package org.transdroid.core.gui.search; import org.transdroid.core.R; import org.transdroid.core.app.search.GoogleWebSearchBarcodeResolver; +import android.annotation.SuppressLint; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; @@ -41,6 +42,7 @@ public class BarcodeHelper { * @param activity The calling activity, to which the result is returned or a dialog is bound that asks to install * the bar code scanner */ + @SuppressLint("ValidFragment") public static void startBarcodeScanner(final SherlockFragmentActivity activity) { try { // Start a bar code scanner that can handle the SCAN intent (specifically ZXing) diff --git a/core/src/org/transdroid/core/gui/search/FilePickerHelper.java b/core/src/org/transdroid/core/gui/search/FilePickerHelper.java index d203d0fa..8d15e397 100644 --- a/core/src/org/transdroid/core/gui/search/FilePickerHelper.java +++ b/core/src/org/transdroid/core/gui/search/FilePickerHelper.java @@ -18,6 +18,7 @@ package org.transdroid.core.gui.search; import org.transdroid.core.R; +import android.annotation.SuppressLint; import android.app.AlertDialog; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; @@ -38,6 +39,7 @@ public class FilePickerHelper { * @param activity The calling activity, to which the result is returned or a dialog is bound that asks to install * the file picker */ + @SuppressLint("ValidFragment") public static void startFilePicker(final SherlockFragmentActivity activity) { try { // Start a file manager that can handle the PICK_FILE intent (specifically IO File Manager) diff --git a/core/src/org/transdroid/core/gui/search/UrlEntryDialog.java b/core/src/org/transdroid/core/gui/search/UrlEntryDialog.java index 77410540..c3c6906b 100644 --- a/core/src/org/transdroid/core/gui/search/UrlEntryDialog.java +++ b/core/src/org/transdroid/core/gui/search/UrlEntryDialog.java @@ -19,6 +19,7 @@ package org.transdroid.core.gui.search; import org.transdroid.core.gui.TorrentsActivity; import org.transdroid.core.gui.navigation.NavigationHelper; +import android.annotation.SuppressLint; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; @@ -37,6 +38,7 @@ public class UrlEntryDialog { * activity's {@link TorrentsActivity#addTorrentByUrl(String, String) method}. * @param activity The activity that opens (and owns) this dialog */ + @SuppressLint("ValidFragment") public static void startUrlEntry(final TorrentsActivity activity) { new DialogFragment() { public android.app.Dialog onCreateDialog(android.os.Bundle savedInstanceState) { diff --git a/core/src/org/transdroid/core/widget/WidgetConfig.java b/core/src/org/transdroid/core/widget/WidgetConfig.java new file mode 100644 index 00000000..aea02cb8 --- /dev/null +++ b/core/src/org/transdroid/core/widget/WidgetConfig.java @@ -0,0 +1,63 @@ +/* + * Copyright 2010-2013 Eric Kok et al. + * + * Transdroid 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 3 of the License, or + * (at your option) any later version. + * + * Transdroid 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 Transdroid. If not, see . + */ +package org.transdroid.core.widget; + +import org.transdroid.core.gui.navigation.StatusType; +import org.transdroid.daemon.TorrentsSortBy; + +/** + * Represents a set of settings that define how the user configured a specific app widget. + * @author Eric Kok + */ +public class WidgetConfig { + + private final int serverId; + private final StatusType statusType; + private final TorrentsSortBy sortBy; + private final boolean reserveSort; + private final boolean useDarkTheme; + + public WidgetConfig(int serverId, StatusType statusType, TorrentsSortBy sortBy, boolean reverseSort, + boolean useDarkTheme) { + this.serverId = serverId; + this.statusType = statusType; + this.sortBy = sortBy; + this.reserveSort = reverseSort; + this.useDarkTheme = useDarkTheme; + } + + public int getServerId() { + return serverId; + } + + public StatusType getStatusType() { + return statusType; + } + + public TorrentsSortBy getSortBy() { + return sortBy; + } + + public boolean shouldReserveSort() { + return reserveSort; + } + + public boolean shouldUseDarkTheme() { + return useDarkTheme; + } + +} diff --git a/core/src/org/transdroid/core/widget/WidgetConfigActivity.java b/core/src/org/transdroid/core/widget/WidgetConfigActivity.java new file mode 100644 index 00000000..01d8276f --- /dev/null +++ b/core/src/org/transdroid/core/widget/WidgetConfigActivity.java @@ -0,0 +1,262 @@ +/* + * Copyright 2010-2013 Eric Kok et al. + * + * Transdroid 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 3 of the License, or + * (at your option) any later version. + * + * Transdroid 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 Transdroid. If not, see . + */ +package org.transdroid.core.widget; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.androidannotations.annotations.AfterViews; +import org.androidannotations.annotations.Background; +import org.androidannotations.annotations.Bean; +import org.androidannotations.annotations.EActivity; +import org.androidannotations.annotations.ItemSelect; +import org.androidannotations.annotations.UiThread; +import org.androidannotations.annotations.ViewById; +import org.transdroid.core.R; +import org.transdroid.core.app.settings.ApplicationSettings; +import org.transdroid.core.app.settings.ServerSetting; +import org.transdroid.core.gui.lists.SimpleListItemSpinnerAdapter; +import org.transdroid.core.gui.lists.SortByListItem; +import org.transdroid.core.gui.lists.TorrentsAdapter; +import org.transdroid.core.gui.navigation.StatusType; +import org.transdroid.core.gui.navigation.StatusType.StatusTypeFilter; +import org.transdroid.core.service.ConnectivityHelper; +import org.transdroid.daemon.Daemon; +import org.transdroid.daemon.IDaemonAdapter; +import org.transdroid.daemon.Label; +import org.transdroid.daemon.Torrent; +import org.transdroid.daemon.TorrentsComparator; +import org.transdroid.daemon.TorrentsSortBy; +import org.transdroid.daemon.task.DaemonTaskResult; +import org.transdroid.daemon.task.RetrieveTask; +import org.transdroid.daemon.task.RetrieveTaskSuccessResult; + +import android.annotation.TargetApi; +import android.appwidget.AppWidgetManager; +import android.content.Intent; +import android.os.Build; +import android.os.Bundle; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.CompoundButton.OnCheckedChangeListener; +import android.widget.ListView; +import android.widget.Spinner; +import android.widget.TextView; + +import com.actionbarsherlock.app.ActionBar; +import com.actionbarsherlock.app.SherlockActivity; + +@TargetApi(Build.VERSION_CODES.HONEYCOMB) +@EActivity(resName = "activity_widgetconfig") +public class WidgetConfigActivity extends SherlockActivity { + + // Views and adapters + @ViewById + protected Spinner serverSpinner, filterSpinner, sortSpinner; + @ViewById + protected CheckBox reverseorderCheckBox, darkthemeCheckBox; + @ViewById + protected TextView filterText, serverText, errorText; + @ViewById + protected ListView torrentsList; + @Bean + protected TorrentsAdapter previewTorrentsAdapter; + private List previewTorrents = null; + + // Settings and helpers + @Bean + protected ConnectivityHelper connectivityHelper; + @Bean + protected ApplicationSettings applicationSettings; + private int appWidgetId; + + @Override + protected void onCreate(Bundle savedInstanceState) { + + super.onCreate(savedInstanceState); + if (getIntent() == null || getIntent().getExtras() == null + || !getIntent().hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID)) { + // Invalid configuration; return canceled result + setResult(RESULT_CANCELED, + new Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID)); + finish(); + } + + // Get the appwidget ID we are configuring + appWidgetId = getIntent().getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, + AppWidgetManager.INVALID_APPWIDGET_ID); + // Set preliminary canceled result and continue with the initialisation + setResult(RESULT_CANCELED, new Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId)); + + } + + @AfterViews + protected void init() { + + // Populate the selection spinners with custom array adapters + List sortOrders = new ArrayList(); + for (TorrentsSortBy order : TorrentsSortBy.values()) { + sortOrders.add(new SortByListItem(this, order)); + } + serverSpinner.setAdapter(new SimpleListItemSpinnerAdapter(this, 0, applicationSettings + .getServerSettings())); + filterSpinner.setAdapter(new SimpleListItemSpinnerAdapter(this, 0, StatusType + .getAllStatusTypes(this))); + sortSpinner.setAdapter(new SimpleListItemSpinnerAdapter(this, 0, sortOrders)); + // TODO: Update to AndroidAnnotations 3.0 and use @CheckedChanged + reverseorderCheckBox.setOnCheckedChangeListener(reverseorderCheckedChanged); + torrentsList.setAdapter(previewTorrentsAdapter); + torrentsList.setEmptyView(errorText); + + // Set up action bar with a done button + // Inspired by NoNonsenseNotes's ListWidgetConfig.java (Apache License, Version 2.0) + getSupportActionBar().setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, + ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_SHOW_TITLE); + View doneButtonFrame = getLayoutInflater().inflate(R.layout.actionbar_donebutton, null); + doneButtonFrame.findViewById(R.id.actionbar_done).setOnClickListener(doneClicked); + getSupportActionBar().setCustomView(doneButtonFrame); + + } + + @ItemSelect + protected void serverSpinnerItemSelected(boolean selected, ServerSetting server) { + serverText.setText(server.getName()); + loadTorrents(); + } + + @ItemSelect + protected void filterSpinnerItemSelected(boolean selected, StatusTypeFilter statusTypeFilter) { + filterText.setText(statusTypeFilter.getName()); + filterTorrents(); + } + + @ItemSelect + protected void sortSpinnerItemSelected(boolean selected, SortByListItem sortByListItem) { + filterTorrents(); + } + + protected OnCheckedChangeListener reverseorderCheckedChanged = new OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + filterTorrents(); + } + }; + + @Background + protected void loadTorrents() { + + if (serverSpinner.getSelectedItem() == null) + return; + + // Create a connection object and retrieve the live torrents + IDaemonAdapter connection = ((ServerSetting) serverSpinner.getSelectedItem()) + .createServerAdapter(connectivityHelper.getConnectedNetworkName()); + DaemonTaskResult result = RetrieveTask.create(connection).execute(); + if (result instanceof RetrieveTaskSuccessResult) { + // Success; show the active torrents in the widget preview + onTorrentsRetrieved(((RetrieveTaskSuccessResult) result).getTorrents(), + ((RetrieveTaskSuccessResult) result).getLabels()); + } else { + // Can't connect right now; provide a nice error message + showError(false); + } + + } + + @UiThread + protected void onTorrentsRetrieved(List torrents, List \ No newline at end of file diff --git a/lite/AndroidManifest.xml b/lite/AndroidManifest.xml index 4148509e..18fa9c1a 100644 --- a/lite/AndroidManifest.xml +++ b/lite/AndroidManifest.xml @@ -17,8 +17,8 @@ --> + android:versionCode="6" + android:versionName="2.0" > @@ -68,6 +69,11 @@ + + + + + @@ -193,6 +199,34 @@ android:value="android.intent.action.BOOT_COMPLETED" /> + + + + + + + + + + + + + + + + + - + \ No newline at end of file