diff --git a/core/res/layout/actionbar_donebutton.xml b/core/res/layout-v11/actionbar_donebutton.xml
similarity index 100%
rename from core/res/layout/actionbar_donebutton.xml
rename to core/res/layout-v11/actionbar_donebutton.xml
diff --git a/core/res/layout/activity_widgetconfig.xml b/core/res/layout-v11/activity_widgetconfig.xml
similarity index 100%
rename from core/res/layout/activity_widgetconfig.xml
rename to core/res/layout-v11/activity_widgetconfig.xml
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..c4734674
--- /dev/null
+++ b/core/res/layout-v11/list_item_widget_dark.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
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..860ef687
--- /dev/null
+++ b/core/res/layout-v11/list_item_widget_light.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/res/layout/widget_torrents_dark.xml b/core/res/layout-v11/widget_torrents_dark.xml
similarity index 100%
rename from core/res/layout/widget_torrents_dark.xml
rename to core/res/layout-v11/widget_torrents_dark.xml
diff --git a/core/res/layout/widget_torrents_light.xml b/core/res/layout-v11/widget_torrents_light.xml
similarity index 97%
rename from core/res/layout/widget_torrents_light.xml
rename to core/res/layout-v11/widget_torrents_light.xml
index 8b606768..4194cfa9 100644
--- a/core/res/layout/widget_torrents_light.xml
+++ b/core/res/layout-v11/widget_torrents_light.xml
@@ -45,7 +45,7 @@
android:layout_alignParentBottom="true"
android:background="@color/green" />
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/core/res/layout-v14/actionbar_progressitem.xml b/core/res/values-v11/bools.xml
similarity index 50%
rename from core/res/layout-v14/actionbar_progressitem.xml
rename to core/res/values-v11/bools.xml
index 810f2aa9..2ea1c4b9 100644
--- a/core/res/layout-v14/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/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/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/xml/appwidget_info.xml b/core/res/xml/appwidget_info.xml
index 57d66929..a236ffa0 100644
--- a/core/res/xml/appwidget_info.xml
+++ b/core/res/xml/appwidget_info.xml
@@ -25,5 +25,5 @@
android:minWidth="180dp"
android:previewImage="@drawable/ic_launcher"
android:resizeMode="horizontal|vertical"
- android:updatePeriodMillis="86400000"
+ android:updatePeriodMillis="3600000"
android:widgetCategory="home_screen|keyguard" />
diff --git a/core/src/org/transdroid/core/app/settings/ApplicationSettings.java b/core/src/org/transdroid/core/app/settings/ApplicationSettings.java
index ec13a23e..62a7fc67 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;
@@ -31,7 +32,7 @@ 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.WidgetSettings;
+import org.transdroid.core.widget.WidgetConfig;
import org.transdroid.daemon.Daemon;
import org.transdroid.daemon.OS;
import org.transdroid.daemon.TorrentsSortBy;
@@ -511,11 +512,11 @@ public class ApplicationSettings {
* @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 WidgetSettings getWidgetConfig(int appWidgetId) {
+ public WidgetConfig getWidgetConfig(int appWidgetId) {
if (!prefs.contains("widget_server_" + appWidgetId))
return null;
// @formatter:off
- return new WidgetSettings(
+ 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())),
@@ -524,7 +525,16 @@ public class ApplicationSettings {
// @formatter:on
}
- public void setWidgetConfig(int appWidgetId, WidgetSettings settings) {
+ /**
+ * 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());
@@ -534,4 +544,18 @@ public class ApplicationSettings {
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/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 08c74e58..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 {
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/WidgetSettings.java b/core/src/org/transdroid/core/widget/WidgetConfig.java
similarity index 92%
rename from core/src/org/transdroid/core/widget/WidgetSettings.java
rename to core/src/org/transdroid/core/widget/WidgetConfig.java
index 6d036325..aea02cb8 100644
--- a/core/src/org/transdroid/core/widget/WidgetSettings.java
+++ b/core/src/org/transdroid/core/widget/WidgetConfig.java
@@ -23,7 +23,7 @@ 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 WidgetSettings {
+public class WidgetConfig {
private final int serverId;
private final StatusType statusType;
@@ -31,7 +31,7 @@ public class WidgetSettings {
private final boolean reserveSort;
private final boolean useDarkTheme;
- public WidgetSettings(int serverId, StatusType statusType, TorrentsSortBy sortBy, boolean reverseSort,
+ public WidgetConfig(int serverId, StatusType statusType, TorrentsSortBy sortBy, boolean reverseSort,
boolean useDarkTheme) {
this.serverId = serverId;
this.statusType = statusType;
diff --git a/core/src/org/transdroid/core/widget/WidgetConfigActivity.java b/core/src/org/transdroid/core/widget/WidgetConfigActivity.java
index abaa2f2e..204250e2 100644
--- a/core/src/org/transdroid/core/widget/WidgetConfigActivity.java
+++ b/core/src/org/transdroid/core/widget/WidgetConfigActivity.java
@@ -25,7 +25,6 @@ import org.androidannotations.annotations.Background;
import org.androidannotations.annotations.Bean;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.ItemSelect;
-import org.androidannotations.annotations.SystemService;
import org.androidannotations.annotations.UiThread;
import org.androidannotations.annotations.ViewById;
import org.transdroid.core.R;
@@ -49,10 +48,11 @@ 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.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.CheckBox;
@@ -65,6 +65,7 @@ import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.SherlockActivity;
import com.actionbarsherlock.view.SherlockListView;
+@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@EActivity(resName = "activity_widgetconfig")
public class WidgetConfigActivity extends SherlockActivity {
@@ -82,10 +83,6 @@ public class WidgetConfigActivity extends SherlockActivity {
private List previewTorrents = null;
// Settings and helpers
- @SystemService
- protected AppWidgetManager appWidgetManager;
- @SystemService
- protected LayoutInflater layoutInflater;
@Bean
protected ConnectivityHelper connectivityHelper;
@Bean
@@ -136,7 +133,7 @@ public class WidgetConfigActivity extends SherlockActivity {
// 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 = layoutInflater.inflate(R.layout.actionbar_donebutton, null);
+ View doneButtonFrame = getLayoutInflater().inflate(R.layout.actionbar_donebutton, null);
doneButtonFrame.findViewById(R.id.actionbar_done).setOnClickListener(doneClicked);
getSupportActionBar().setCustomView(doneButtonFrame);
@@ -252,11 +249,13 @@ public class WidgetConfigActivity extends SherlockActivity {
TorrentsSortBy sortBy = ((SortByListItem) sortSpinner.getSelectedItem()).getSortBy();
boolean reverseSort = reverseorderCheckBox.isChecked();
boolean useDarkTheme = darkthemeCheckBox.isChecked();
- applicationSettings.setWidgetConfig(appWidgetId, new WidgetSettings(server, statusType, sortBy,
- reverseSort, useDarkTheme));
+ WidgetConfig config = new WidgetConfig(server, statusType, sortBy, reverseSort, useDarkTheme);
+ applicationSettings.setWidgetConfig(appWidgetId, config);
// Return the widget configuration result
- appWidgetManager.updateAppWidget(appWidgetId, null);
+ AppWidgetManager manager = AppWidgetManager.getInstance(WidgetConfigActivity.this);
+ manager.updateAppWidget(appWidgetId, WidgetProvider.buildRemoteViews(getApplicationContext(), appWidgetId, config));
+ manager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.torrents_list);
setResult(RESULT_OK, new Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId));
finish();
diff --git a/core/src/org/transdroid/core/widget/WidgetProvider.java b/core/src/org/transdroid/core/widget/WidgetProvider.java
index 0f7b996d..e599d7ab 100644
--- a/core/src/org/transdroid/core/widget/WidgetProvider.java
+++ b/core/src/org/transdroid/core/widget/WidgetProvider.java
@@ -16,19 +16,116 @@
*/
package org.transdroid.core.widget;
+import org.androidannotations.annotations.Bean;
import org.androidannotations.annotations.EReceiver;
+import org.transdroid.core.R;
+import org.transdroid.core.app.settings.*;
+import org.transdroid.core.app.settings.ServerSetting;
+import org.transdroid.core.gui.log.Log;
+import android.annotation.TargetApi;
+import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Build;
+import android.widget.RemoteViews;
+@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@EReceiver
public class WidgetProvider extends AppWidgetProvider {
+ public static final String INTENT_STARTSERVER = "org.transdroid.START_SERVER";
+ public static final String EXTRA_TORRENT = "extra_torrent";
+ public static final String EXTRA_SERVER = "extra_server";
+
+ @Bean
+ protected ApplicationSettings applicationSettings;
+
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
+ for (int appWidgetId : appWidgetIds) {
+ appWidgetManager.updateAppWidget(appWidgetId,
+ buildRemoteViews(context, appWidgetId, applicationSettings.getWidgetConfig(appWidgetId)));
+ }
+ }
+
+ @Override
+ public void onDeleted(Context context, int[] appWidgetIds) {
+ super.onDeleted(context, appWidgetIds);
+ for (int appWidgetId : appWidgetIds) {
+ applicationSettings.removeWidgetConfig(appWidgetId);
+ }
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+
+ if (intent == null || intent.getAction() == null || intent.getExtras() == null
+ || !intent.hasExtra(EXTRA_SERVER))
+ return;
+
+ // Launch an Intent to start Transdroid on some specific server; and possibly a specific torrent too
+ Intent start = new Intent(INTENT_STARTSERVER);
+ start.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ start.putExtra(EXTRA_SERVER, intent.getIntExtra(EXTRA_SERVER, -1));
+ if (intent.getAction().equals(EXTRA_TORRENT)) {
+ start.putExtra(EXTRA_TORRENT, intent.getParcelableExtra(EXTRA_TORRENT));
+ }
+ context.startActivity(start);
+
+ super.onReceive(context, intent);
+
+ }
+
+ /**
+ * Loads and sets up the layout for some specific app widget given the user's widget settings. Note that the views
+ * for the list view rows are loaded separately in the {@link WidgetViewsFactory}.
+ * @param context The app widget context, with access to resources
+ * @param appWidgetId The specific ID of the app widget to load
+ * @param config The user widget configuration, with filter and theme preferences
+ * @return A fully initialised set of remote views to update the widget with the AppWidgetManager
+ */
+ @SuppressWarnings("deprecation")
+ public static RemoteViews buildRemoteViews(Context context, int appWidgetId, WidgetConfig config) {
+
+ // Does the server to show and its widget settings actually still exist?
+ if (context == null || config == null)
+ return null;
+ ApplicationSettings appSettings = ApplicationSettings_.getInstance_(context);
+ if (config.getServerId() < 0 || config.getServerId() > appSettings.getMaxServer()) {
+ Log.e(context, "Tried to set up widget " + appWidgetId + " but the bound server ID " + config.getServerId()
+ + " no longer exists.");
+ return null;
+ }
+
+ // Load the dark or light widget layout xml
+ RemoteViews rv = new RemoteViews(context.getPackageName(),
+ config.shouldUseDarkTheme() ? R.layout.list_item_widget_dark : R.layout.list_item_widget_light);
+
+ // Set up the widget's list view loading service which refers to the WidgetViewsFactory
+ // Use a unique data URI next to the extra to make sure the intents are unique form each widget
+ Intent intent = new Intent(context, WidgetService.class);
+ intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME) + "//widget/" + appWidgetId + "/server/"
+ + config.getServerId()));
+ intent.putExtra(EXTRA_SERVER, config.getServerId());
+ rv.setRemoteAdapter(appWidgetId, R.id.torrents_list, intent);
+ rv.setPendingIntentTemplate(R.id.torrents_list,
+ PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
+ rv.setEmptyView(R.id.torrents_list, R.id.error_text);
+ rv.setTextViewText(R.id.error_text, context.getString(R.string.navigation_emptytorrents));
+
+ // Show the server and status type filter from the widget configuration
+ ServerSetting server = appSettings.getServerSetting(config.getServerId());
+ rv.setTextViewText(R.id.server_text, server.getName());
+ rv.setTextViewText(R.id.filter_text, config.getStatusType().getFilterItem(context).getName());
+ rv.setOnClickPendingIntent(R.id.icon_image,
+ PendingIntent.getActivity(context, 0, intent.cloneFilter(), PendingIntent.FLAG_UPDATE_CURRENT));
+
+ return rv;
- // TODO
-
}
+
}
diff --git a/core/src/org/transdroid/core/widget/WidgetService.java b/core/src/org/transdroid/core/widget/WidgetService.java
new file mode 100644
index 00000000..915bebd9
--- /dev/null
+++ b/core/src/org/transdroid/core/widget/WidgetService.java
@@ -0,0 +1,198 @@
+/*
+ * 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.EService;
+import org.transdroid.core.R;
+import org.transdroid.core.app.settings.*;
+import org.transdroid.core.app.settings.ServerSetting;
+import org.transdroid.core.gui.lists.LocalTorrent;
+import org.transdroid.core.gui.log.Log;
+import org.transdroid.core.service.*;
+import org.transdroid.daemon.Daemon;
+import org.transdroid.daemon.IDaemonAdapter;
+import org.transdroid.daemon.Torrent;
+import org.transdroid.daemon.TorrentsComparator;
+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.Context;
+import android.content.Intent;
+import android.content.res.Resources;
+import android.os.Build;
+import android.widget.RemoteViews;
+import android.widget.RemoteViewsService;
+
+@TargetApi(Build.VERSION_CODES.HONEYCOMB)
+@EService
+public class WidgetService extends RemoteViewsService {
+
+ @Override
+ public RemoteViewsFactory onGetViewFactory(Intent intent) {
+ return new WidgetViewsFactory(this.getApplicationContext(), intent);
+ }
+
+}
+
+@TargetApi(Build.VERSION_CODES.HONEYCOMB)
+class WidgetViewsFactory implements RemoteViewsService.RemoteViewsFactory {
+
+ private final Context context;
+ private final int appWidgetId;
+ private List torrents = null;
+ private WidgetConfig config = null;
+
+ public WidgetViewsFactory(Context applicationContext, Intent intent) {
+ this.context = applicationContext;
+ this.appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
+ AppWidgetManager.INVALID_APPWIDGET_ID);
+ }
+
+ @Override
+ public void onCreate() {
+ // Nothing to do here (wait for onDataSetChanged)
+ }
+
+ @Override
+ public void onDataSetChanged() {
+
+ // Load the widget settings
+ ApplicationSettings settings = ApplicationSettings_.getInstance_(context);
+ config = settings.getWidgetConfig(appWidgetId);
+ if (config == null || config.getServerId() < 0) {
+ Log.e(context, "Looking for widget data while the widget wasn't yet configured");
+ return;
+ }
+ ServerSetting server = settings.getServerSetting(config.getServerId());
+ if (server == null) {
+ // TODO: Show error text some how in the remote view, perhaps via the EmptyView's text?
+ Log.e(context, "The server for which this widget was created no longer exists");
+ if (torrents != null)
+ torrents.clear();
+ return;
+ }
+
+ // Load the torrents; synchronously
+ IDaemonAdapter connection = server.createServerAdapter(ConnectivityHelper_.getInstance_(context)
+ .getConnectedNetworkName());
+ DaemonTaskResult result = RetrieveTask.create(connection).execute();
+ if (!(result instanceof RetrieveTaskSuccessResult)) {
+ // TODO: Show error text somehow in the remote view, perhaps via the EmptyView's text?
+ Log.e(context, "The torrents could not be retrieved at this time; probably a connection issue");
+ if (torrents != null)
+ torrents.clear();
+ return;
+ }
+
+ // We have data; filter, sort and store it to use later when getViewAt gets called
+ ArrayList filteredTorrents = new ArrayList();
+ for (Torrent torrent : ((RetrieveTaskSuccessResult) result).getTorrents()) {
+ if (config.getStatusType().getFilterItem(context).matches(torrent))
+ filteredTorrents.add(torrent);
+ }
+ if (filteredTorrents.size() > 0) {
+ // Only sort when there are actually torrents left after filtering
+ Daemon serverType = filteredTorrents.get(0).getDaemon();
+ Collections.sort(filteredTorrents,
+ new TorrentsComparator(serverType, config.getSortBy(), config.shouldReserveSort()));
+ }
+ torrents = filteredTorrents;
+
+ }
+
+ @Override
+ public RemoteViews getViewAt(int position) {
+
+ // Load the dark or light widget list item layout xml
+ RemoteViews rv = new RemoteViews(context.getPackageName(),
+ config.shouldUseDarkTheme() ? R.layout.list_item_widget_dark : R.layout.list_item_widget_light);
+
+ // Bind the torrent details texts and status colour
+ Torrent torrent = torrents.get(position);
+ LocalTorrent local = LocalTorrent.fromTorrent(torrent);
+ Resources r = context.getResources();
+ rv.setTextViewText(R.id.name_text, torrent.getName());
+ rv.setTextViewText(R.id.progress_text, local.getProgressSizeText(r, false));
+ rv.setTextViewText(R.id.ratio_text, local.getProgressEtaRatioText(r));
+ int statusColour;
+ switch (torrent.getStatusCode()) {
+ case Downloading:
+ statusColour = r.getColor(r.getColor(R.color.torrent_downloading));
+ break;
+ case Paused:
+ statusColour = r.getColor(r.getColor(R.color.torrent_paused));
+ break;
+ case Seeding:
+ statusColour = r.getColor(r.getColor(R.color.torrent_seeding));
+ break;
+ case Error:
+ statusColour = r.getColor(r.getColor(R.color.torrent_error));
+ break;
+ default: // Checking, Waiting, Queued, Unknown
+ statusColour = r.getColor(r.getColor(R.color.torrent_other));
+ break;
+ }
+ rv.setInt(R.id.status_view, "setBackgroundColor", r.getColor(statusColour));
+ Intent startIntent = new Intent();
+ startIntent.putExtra(WidgetProvider.EXTRA_SERVER, config.getServerId());
+ startIntent.putExtra(WidgetProvider.EXTRA_TORRENT, torrent);
+ rv.setOnClickFillInIntent(R.id.widget_line_layout, startIntent);
+
+ return rv;
+
+ }
+
+ @Override
+ public RemoteViews getLoadingView() {
+ return null;
+ }
+
+ @Override
+ public void onDestroy() {
+ torrents.clear();
+ }
+
+ @Override
+ public int getViewTypeCount() {
+ return 1;
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return true;
+ }
+
+ @Override
+ public int getCount() {
+ if (torrents == null)
+ return 0;
+ return torrents.size();
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+}
diff --git a/full/AndroidManifest.xml b/full/AndroidManifest.xml
index e9c276e4..2a400a74 100644
--- a/full/AndroidManifest.xml
+++ b/full/AndroidManifest.xml
@@ -69,6 +69,11 @@
+
+
+
+
+
@@ -243,13 +248,23 @@
-
+
-
+
+
+
diff --git a/lite/AndroidManifest.xml b/lite/AndroidManifest.xml
index 7b1a47dc..d86c892b 100644
--- a/lite/AndroidManifest.xml
+++ b/lite/AndroidManifest.xml
@@ -69,6 +69,11 @@
+
+
+
+
+
@@ -194,6 +199,33 @@
android:value="android.intent.action.BOOT_COMPLETED" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file