- TransdroidLite
+ Transdroid Core
diff --git a/lite/AndroidManifest.xml b/lite/AndroidManifest.xml
index 1b6f7500..e33579dd 100644
--- a/lite/AndroidManifest.xml
+++ b/lite/AndroidManifest.xml
@@ -1,13 +1,20 @@
+ android:versionName="2.0-alpha1" >
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lite/project.properties b/lite/project.properties
index 5f7d115e..b8863ad3 100644
--- a/lite/project.properties
+++ b/lite/project.properties
@@ -13,3 +13,4 @@
# Project target.
target=android-16
android.library.reference.1=../external/JakeWharton-ActionBarSherlock/library
+android.library.reference.2=../external/ColorPickerPreference
diff --git a/lite/res/drawable-hdpi/ic_priority_high.png b/lite/res/drawable-hdpi/ic_priority_high.png
new file mode 100644
index 00000000..43dd253b
Binary files /dev/null and b/lite/res/drawable-hdpi/ic_priority_high.png differ
diff --git a/lite/res/drawable-hdpi/ic_priority_low.png b/lite/res/drawable-hdpi/ic_priority_low.png
new file mode 100644
index 00000000..fa8e7bfb
Binary files /dev/null and b/lite/res/drawable-hdpi/ic_priority_low.png differ
diff --git a/lite/res/drawable-hdpi/ic_priority_normal.png b/lite/res/drawable-hdpi/ic_priority_normal.png
new file mode 100644
index 00000000..b59edc02
Binary files /dev/null and b/lite/res/drawable-hdpi/ic_priority_normal.png differ
diff --git a/lite/res/drawable-hdpi/ic_priority_off.png b/lite/res/drawable-hdpi/ic_priority_off.png
new file mode 100644
index 00000000..e44ea25a
Binary files /dev/null and b/lite/res/drawable-hdpi/ic_priority_off.png differ
diff --git a/lite/res/layout/list_item_torrent.xml b/lite/res/layout/list_item_torrent.xml
new file mode 100644
index 00000000..4041e535
--- /dev/null
+++ b/lite/res/layout/list_item_torrent.xml
@@ -0,0 +1,89 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lite/res/values/attrs.xml b/lite/res/values/attrs.xml
new file mode 100644
index 00000000..a19eb9b9
--- /dev/null
+++ b/lite/res/values/attrs.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lite/res/values/colors.xml b/lite/res/values/colors.xml
index ba2e342f..f4cdf7fa 100644
--- a/lite/res/values/colors.xml
+++ b/lite/res/values/colors.xml
@@ -1,4 +1,5 @@
#8acc12
+ #7dbb21
diff --git a/lite/res/values/strings.xml b/lite/res/values/strings.xml
index ce8d9e9b..780a7fcf 100644
--- a/lite/res/values/strings.xml
+++ b/lite/res/values/strings.xml
@@ -1,7 +1,7 @@
- Transdroid Lite
+ Transdroid
Add
From file
@@ -21,7 +21,6 @@
Ratio
Filter list
Settings
-
Start
Stop
Resume
@@ -41,7 +40,143 @@
SERVERS
STATUS
LABELS
+ All
+ Downloading
+ Uploading
+ Active
+ Inactive
Connected, but no torrent are active on the server
Select a torrent to view its details
-
+ Servers
+ Add new server
+ Search sites
+ Set default site
+ Add web search site
+ RSS feeds
+ Add RSS feed
+ Other settings
+
+ Name
+ Optional personal name
+ Direct search URL
+ %s will be replaced by the search query
+ Feed URL
+ Requires authentication
+ Opens links in the webbrowser for user login
+
+ Server type
+ IP or host name
+ Port number
+ User name
+ Password
+ Deluge web password
+ Advanced settings
+ Local IP or host
+ When connected to the specified local network
+ Local network
+ The server\'s local (wifi) network
+ Folder
+ Usually empty
+ SCGI mount point
+ Optional settings
+ Finished notification
+ Notify when a torrent finishes
+ New torrent notification
+ Nofity when a torrent was added
+ Server OS
+ Download directory
+ Manually set absolute path for remote connections
+ Connection timeout
+ Number of seconds before a connection attempt is aborted
+ Base (S)FTP url
+ For example ftp://me@server/downloads/
+ (S)FTP password
+ Use SSL
+ Connect using https
+ Custom SSL thumbprint (SHA-1)
+ Permit only connections to this specific certificate
+ Accept all SSL certificates
+ Allow all connections from any thumbprint
+
+ Background notifications
+ Enable notifications
+ Enables the background service
+ Interval
+ How often to check the server
+ Sound
+ Vibrate
+ LED colour
+ If supported by your device
+ Support AWD notifications
+ Show torrent counter in ADW Launcher
+
+ About Transdroid
+ Check for updates
+ Check transdroidorg for latest app version
+ Import settings
+ Export settings
+ Send error log
+ Get support or report a bug
+ About
+
+
+ - BitComet
+ - Bitflu 1.2+
+ - BitTorrent 6+
+ - Buffalo NAS -1.31
+ - Deluge 1.2+
+ - DLink Router BT
+ - Ktorrent
+ - qBittorrent
+ - rTorrent
+ - Torrentflux-b4rt
+ - Transmission
+ - µTorrent
+ - Vuze
+
+
+ - daemon_bitcomet
+ - daemon_bitflu
+ - daemon_bittorrent
+ - daemon_buffalonas
+ - daemon_deluge
+ - daemon_dlinkrouterbt
+ - daemon_ktorrent
+ - daemon_qbittorrent
+ - daemon_rtorrent
+ - daemon_tfb4rt
+ - daemon_transmission
+ - daemon_utorrent
+ - daemon_vuze
+
+
+ - Windows
+ - Mac
+ - Linux
+
+
+ - type_windows
+ - type_mac
+ - type_linux
+
+
+ - 1 minute
+ - 10 minutes
+ - 30 minutes
+ - 1 hour
+ - 3 hours
+ - 12 hours
+ - 1 day
+
+
+ - 60
+ - 600
+ - 1800
+ - 3600
+ - 10800
+ - 43200
+ - 86400
+
+
+
\ No newline at end of file
diff --git a/lite/res/xml/pref_about.xml b/lite/res/xml/pref_about.xml
new file mode 100644
index 00000000..eb4dad12
--- /dev/null
+++ b/lite/res/xml/pref_about.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lite/res/xml/pref_main.xml b/lite/res/xml/pref_main.xml
new file mode 100644
index 00000000..19f3bf36
--- /dev/null
+++ b/lite/res/xml/pref_main.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lite/res/xml/pref_notifications.xml b/lite/res/xml/pref_notifications.xml
new file mode 100644
index 00000000..4a7a1a16
--- /dev/null
+++ b/lite/res/xml/pref_notifications.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lite/res/xml/pref_rssfeed.xml b/lite/res/xml/pref_rssfeed.xml
new file mode 100644
index 00000000..401c5aea
--- /dev/null
+++ b/lite/res/xml/pref_rssfeed.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lite/res/xml/pref_server.xml b/lite/res/xml/pref_server.xml
new file mode 100644
index 00000000..9512a302
--- /dev/null
+++ b/lite/res/xml/pref_server.xml
@@ -0,0 +1,108 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lite/res/xml/pref_websearch.xml b/lite/res/xml/pref_websearch.xml
new file mode 100644
index 00000000..09674685
--- /dev/null
+++ b/lite/res/xml/pref_websearch.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/lite/src/com/actionbarsherlock/view/SherlockListView.java b/lite/src/com/actionbarsherlock/view/SherlockListView.java
new file mode 100644
index 00000000..3b2df828
--- /dev/null
+++ b/lite/src/com/actionbarsherlock/view/SherlockListView.java
@@ -0,0 +1,337 @@
+package com.actionbarsherlock.view;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.SparseBooleanArray;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.Checkable;
+import android.widget.ListView;
+
+import com.actionbarsherlock.app.SherlockActivity;
+import com.actionbarsherlock.app.SherlockFragmentActivity;
+import com.actionbarsherlock.view.ActionMode;
+import com.actionbarsherlock.view.Menu;
+import com.actionbarsherlock.view.MenuItem;
+
+/**
+ * Provides backwards compatible multiple choice ActionMode support on Froyo+ using ActionBarSherlock.
+ */
+public class SherlockListView extends ListView {
+ // API 11+ reference, but ok because the value will be inlined.
+ public static final int CHOICE_MODE_MULTIPLE_MODAL_COMPAT = CHOICE_MODE_MULTIPLE_MODAL;
+
+ /**
+ * Wrapper to intercept delegation of long click events, and pass to {@link #doLongPress}
+ */
+ class OnItemLongClickListenerWrapper implements OnItemLongClickListener {
+ private OnItemLongClickListener wrapped;
+
+ public void setWrapped(OnItemLongClickListener listener) {
+ this.wrapped = listener;
+ }
+
+ @Override
+ public boolean onItemLongClick(AdapterView> view, View child, int position, long id) {
+ // this would be easier if AbsListView.performLongPress wasn't package
+ // protected :-(
+ boolean handled = doLongPress(child, position, id);
+ if (!handled && wrapped != null) {
+ return wrapped.onItemLongClick(view, child, position, id);
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Hijack the onLongClickListener so we can intercept delegation.
+ */
+ @Override
+ public void setOnItemLongClickListener(OnItemLongClickListener listener) {
+ if (longClickListenerWrapper == null) {
+ longClickListenerWrapper = new OnItemLongClickListenerWrapper();
+ }
+ longClickListenerWrapper.setWrapped(listener);
+ super.setOnItemLongClickListener(longClickListenerWrapper);
+ }
+
+ /**
+ * A MultiChoiceModeListener receives events for {@link AbsListView#CHOICE_MODE_MULTIPLE_MODAL}. It acts as the
+ * {@link ActionMode.Callback} for the selection mode and also receives
+ * {@link #onItemCheckedStateChanged(ActionMode, int, long, boolean)} events when the user selects and deselects
+ * list items.
+ */
+ @SuppressWarnings("javadoc")
+ public interface MultiChoiceModeListenerCompat extends ActionMode.Callback {
+ /**
+ * Called when an item is checked or unchecked during selection mode.
+ * @param mode The {@link ActionMode} providing the selection mode
+ * @param position Adapter position of the item that was checked or unchecked
+ * @param id Adapter ID of the item that was checked or unchecked
+ * @param checked true
if the item is now checked, false
if the item is now unchecked.
+ */
+ public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked);
+ }
+
+ class MultiChoiceModeWrapper implements MultiChoiceModeListenerCompat {
+ private MultiChoiceModeListenerCompat wrapped;
+
+ public void setWrapped(MultiChoiceModeListenerCompat wrapped) {
+ this.wrapped = wrapped;
+ }
+
+ @Override
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ if (wrapped == null) {
+ return false;
+ }
+ if (wrapped.onCreateActionMode(mode, menu)) {
+ // Initialize checked graphic state?
+ setLongClickable(false);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ if (wrapped == null) {
+ return false;
+ }
+ return wrapped.onPrepareActionMode(mode, menu);
+ }
+
+ @Override
+ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+ if (wrapped == null) {
+ return false;
+ }
+ return wrapped.onActionItemClicked(mode, item);
+ }
+
+ @Override
+ public void onDestroyActionMode(ActionMode mode) {
+ if (wrapped == null) {
+ return;
+ }
+ wrapped.onDestroyActionMode(mode);
+ actionMode = null;
+
+ // Ending selection mode means deselecting everything.
+ clearChoices();
+ checkedItemCount = 0;
+ updateOnScreenCheckedViews();
+ invalidateViews();
+ setLongClickable(true);
+ requestLayout();
+ invalidate();
+ }
+
+ @Override
+ public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
+ if (wrapped == null) {
+ return;
+ }
+ wrapped.onItemCheckedStateChanged(mode, position, id, checked);
+
+ // If there are no items selected we no longer need the selection mode.
+ if (checkedItemCount == 0) {
+ mode.finish();
+ }
+ }
+ }
+
+ private com.actionbarsherlock.view.ActionMode actionMode;
+ private OnItemLongClickListenerWrapper longClickListenerWrapper;
+ private MultiChoiceModeWrapper choiceModeListener;
+ private int choiceMode;
+ private int checkedItemCount;
+
+ public SherlockListView(Context context) {
+ super(context);
+ init(context);
+ }
+
+ public SherlockListView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
+
+ public SherlockListView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ init(context);
+ }
+
+ void init(Context context) {
+ if (isInEditMode()) {
+ // Ignore when viewing in the UI designer
+ return;
+ }
+ if (!(context instanceof SherlockActivity || context instanceof SherlockFragmentActivity)) {
+ throw new IllegalStateException(
+ "This view must be hosted in a SherlockActivity or SherlockFragmentActivity");
+ }
+ setOnItemLongClickListener(null);
+ }
+
+ @Override
+ public void setChoiceMode(int mode) {
+ choiceMode = mode;
+ if (actionMode != null) {
+ actionMode.finish();
+ actionMode = null;
+ }
+ if (choiceMode != CHOICE_MODE_NONE) {
+ if (mode == CHOICE_MODE_MULTIPLE_MODAL_COMPAT) {
+ clearChoices();
+ checkedItemCount = 0;
+ setLongClickable(true);
+ updateOnScreenCheckedViews();
+ requestLayout();
+ invalidate();
+ mode = CHOICE_MODE_MULTIPLE;
+ }
+ super.setChoiceMode(mode);
+ }
+ }
+
+ @Override
+ public int getChoiceMode() {
+ return choiceMode;
+ }
+
+ public void setMultiChoiceModeListener(MultiChoiceModeListenerCompat listener) {
+ if (choiceModeListener == null) {
+ choiceModeListener = new MultiChoiceModeWrapper();
+ }
+ choiceModeListener.setWrapped(listener);
+ }
+
+ @Override
+ public boolean performItemClick(View view, int position, long id) {
+ boolean handled = false;
+ boolean dispatchItemClick = true;
+ boolean checkStateChanged = false;
+ if (choiceMode != CHOICE_MODE_NONE) {
+ handled = true;
+ if (choiceMode == CHOICE_MODE_MULTIPLE
+ || (choiceMode == CHOICE_MODE_MULTIPLE_MODAL_COMPAT && actionMode != null)) {
+ boolean newValue = !getCheckedItemPositions().get(position);
+ setItemChecked(position, newValue);
+ if (actionMode != null) {
+ choiceModeListener.onItemCheckedStateChanged(actionMode, position, id, newValue);
+ dispatchItemClick = false;
+ }
+ checkStateChanged = true;
+ return false;
+ } else if (choiceMode == CHOICE_MODE_SINGLE) {
+ boolean newValue = !getCheckedItemPositions().get(position);
+ setItemChecked(position, newValue);
+ checkStateChanged = true;
+ }
+ if (checkStateChanged) {
+ updateOnScreenCheckedViews();
+ }
+ }
+ if (dispatchItemClick) {
+ handled |= super.performItemClick(view, position, id);
+ }
+ return handled;
+ }
+
+ /**
+ * Perform a quick, in-place update of the checked or activated state on all visible item views. This should only be
+ * called when a valid choice mode is active.
+ *
+ * (Taken verbatim from AbsListView.java)
+ */
+ @TargetApi(11)
+ private void updateOnScreenCheckedViews() {
+ final int firstPos = getFirstVisiblePosition();
+ final int count = getChildCount();
+ final boolean useActivated = getContext().getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.HONEYCOMB;
+ for (int i = 0; i < count; i++) {
+ final View child = getChildAt(i);
+ final int position = firstPos + i;
+
+ if (child instanceof Checkable) {
+ ((Checkable) child).setChecked(getCheckedItemPositions().get(position));
+ } else if (useActivated) {
+ child.setActivated(getCheckedItemPositions().get(position));
+ }
+ }
+ }
+
+ public ActionMode startActionMode(ActionMode.Callback callback) {
+ if (actionMode != null) {
+ return actionMode;
+ }
+ Context context = getContext();
+ if (context instanceof SherlockActivity) {
+ actionMode = ((SherlockActivity) getContext()).startActionMode(callback);
+ } else if (context instanceof SherlockFragmentActivity) {
+ actionMode = ((SherlockFragmentActivity) context).startActionMode(callback);
+ } else {
+ throw new IllegalStateException(
+ "This view must be hosted in a SherlockActivity or SherlockFragmentActivity");
+ }
+ return actionMode;
+ }
+
+ boolean doLongPress(final View child, final int longPressPosition, final long longPressId) {
+ if (choiceMode == CHOICE_MODE_MULTIPLE_MODAL_COMPAT) {
+ if (actionMode == null && (actionMode = startActionMode(choiceModeListener)) != null) {
+ setItemChecked(longPressPosition, true);
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Sets the checked state of the specified position. The is only valid if the choice mode has been set to
+ * {@link #CHOICE_MODE_SINGLE} or {@link #CHOICE_MODE_MULTIPLE}.
+ * @param position The item whose checked state is to be checked
+ * @param value The new checked state for the item
+ */
+ @Override
+ public void setItemChecked(int position, boolean value) {
+ if (choiceMode == CHOICE_MODE_NONE) {
+ return;
+ }
+ SparseBooleanArray checkStates = getCheckedItemPositions();
+
+ // Start selection mode if needed. We don't need to if we're unchecking
+ // something.
+ if (value && choiceMode == CHOICE_MODE_MULTIPLE_MODAL_COMPAT && actionMode == null) {
+ actionMode = startActionMode(choiceModeListener);
+ }
+
+ if (choiceMode == CHOICE_MODE_MULTIPLE || choiceMode == CHOICE_MODE_MULTIPLE_MODAL) {
+ // boolean oldValue = checkStates.get(position);
+ checkStates.put(position, value);
+ if (value) {
+ checkedItemCount++;
+ } else {
+ checkedItemCount--;
+ }
+ if (actionMode != null) {
+ final long id = getAdapter().getItemId(position);
+ choiceModeListener.onItemCheckedStateChanged(actionMode, position, id, value);
+ }
+ } else {
+ if (value || isItemChecked(position)) {
+ checkStates.clear();
+ }
+ // this may end up selecting the value we just cleared but this way
+ // we ensure length of checkStates is 1, a fact getCheckedItemPosition
+ // relies on
+ if (value) {
+ checkStates.put(position, true);
+ }
+ }
+ requestLayout();
+ invalidate();
+ }
+}
diff --git a/lite/src/fr/marvinlabs/widget/CheckableRelativeLayout.java b/lite/src/fr/marvinlabs/widget/CheckableRelativeLayout.java
new file mode 100644
index 00000000..e8e92e9a
--- /dev/null
+++ b/lite/src/fr/marvinlabs/widget/CheckableRelativeLayout.java
@@ -0,0 +1,100 @@
+package fr.marvinlabs.widget;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Checkable;
+import android.widget.RelativeLayout;
+
+/**
+ * Extension of a relative layout to provide a checkable behaviour
+ *
+ * @author marvinlabs
+ */
+public class CheckableRelativeLayout extends RelativeLayout implements Checkable {
+
+ private boolean isChecked;
+ private List checkableViews;
+
+ public CheckableRelativeLayout(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ initialise(attrs);
+ }
+
+ public CheckableRelativeLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ initialise(attrs);
+ }
+
+ public CheckableRelativeLayout(Context context, int checkableId) {
+ super(context);
+ initialise(null);
+ }
+
+ /*
+ * @see android.widget.Checkable#isChecked()
+ */
+ public boolean isChecked() {
+ return isChecked;
+ }
+
+ /*
+ * @see android.widget.Checkable#setChecked(boolean)
+ */
+ public void setChecked(boolean isChecked) {
+ this.isChecked = isChecked;
+ for (Checkable c : checkableViews) {
+ c.setChecked(isChecked);
+ }
+ }
+
+ /*
+ * @see android.widget.Checkable#toggle()
+ */
+ public void toggle() {
+ this.isChecked = !this.isChecked;
+ for (Checkable c : checkableViews) {
+ c.toggle();
+ }
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ final int childCount = this.getChildCount();
+ for (int i = 0; i < childCount; ++i) {
+ findCheckableChildren(this.getChildAt(i));
+ }
+ }
+
+ /**
+ * Read the custom XML attributes
+ */
+ private void initialise(AttributeSet attrs) {
+ this.isChecked = false;
+ this.checkableViews = new ArrayList(5);
+ }
+
+ /**
+ * Add to our checkable list all the children of the view that implement the
+ * interface Checkable
+ */
+ private void findCheckableChildren(View v) {
+ if (v instanceof Checkable) {
+ this.checkableViews.add((Checkable) v);
+ }
+
+ if (v instanceof ViewGroup) {
+ final ViewGroup vg = (ViewGroup) v;
+ final int childCount = vg.getChildCount();
+ for (int i = 0; i < childCount; ++i) {
+ findCheckableChildren(vg.getChildAt(i));
+ }
+ }
+ }
+}
diff --git a/lite/src/fr/marvinlabs/widget/InertCheckBox.java b/lite/src/fr/marvinlabs/widget/InertCheckBox.java
new file mode 100644
index 00000000..5dd3080b
--- /dev/null
+++ b/lite/src/fr/marvinlabs/widget/InertCheckBox.java
@@ -0,0 +1,70 @@
+package fr.marvinlabs.widget;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.widget.CheckBox;
+
+/**
+ * CheckBox that does not react to any user event in order to let the container handle them.
+ */
+public class InertCheckBox extends CheckBox {
+
+ // Provide the same constructors as the superclass
+ public InertCheckBox(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ // Provide the same constructors as the superclass
+ public InertCheckBox(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ // Provide the same constructors as the superclass
+ public InertCheckBox(Context context) {
+ super(context);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ // Make the checkbox not respond to any user event
+ return false;
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ // Make the checkbox not respond to any user event
+ return false;
+ }
+
+ @Override
+ public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
+ // Make the checkbox not respond to any user event
+ return false;
+ }
+
+ @Override
+ public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+ // Make the checkbox not respond to any user event
+ return false;
+ }
+
+ @Override
+ public boolean onKeyShortcut(int keyCode, KeyEvent event) {
+ // Make the checkbox not respond to any user event
+ return false;
+ }
+
+ @Override
+ public boolean onKeyUp(int keyCode, KeyEvent event) {
+ // Make the checkbox not respond to any user event
+ return false;
+ }
+
+ @Override
+ public boolean onTrackballEvent(MotionEvent event) {
+ // Make the checkbox not respond to any user event
+ return false;
+ }
+}
diff --git a/lite/src/org/transdroid/lite/app/search/SearchHelper.java b/lite/src/org/transdroid/lite/app/search/SearchHelper.java
new file mode 100644
index 00000000..11244a19
--- /dev/null
+++ b/lite/src/org/transdroid/lite/app/search/SearchHelper.java
@@ -0,0 +1,109 @@
+package org.transdroid.lite.app.search;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.androidannotations.annotations.EBean;
+import org.androidannotations.annotations.EBean.Scope;
+import org.androidannotations.annotations.RootContext;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+
+@EBean(scope = Scope.Singleton)
+public class SearchHelper {
+
+ static final int CURSOR_SEARCH_ID = 0;
+ static final int CURSOR_SEARCH_NAME = 1;
+ static final int CURSOR_SEARCH_TORRENTURL = 2;
+ static final int CURSOR_SEARCH_DETAILSURL = 3;
+ static final int CURSOR_SEARCH_SIZE = 4;
+ static final int CURSOR_SEARCH_ADDED = 5;
+ static final int CURSOR_SEARCH_SEEDERS = 6;
+ static final int CURSOR_SEARCH_LEECHERS = 7;
+
+ static final int CURSOR_SITE_ID = 0;
+ static final int CURSOR_SITE_CODE = 1;
+ static final int CURSOR_SITE_NAME = 2;
+ static final int CURSOR_SITE_RSSURL = 3;
+
+ @RootContext
+ protected Context context;
+
+ public enum SearchSortOrder {
+ Combined, BySeeders
+ }
+
+ /**
+ * Return whether the Torrent Search package is installed and available to query against
+ * @return True if the available sites can be retrieved from the content provider, false otherwise
+ */
+ public boolean isTorrentSearchInstalled() {
+ return getAvailableSites() != null;
+ }
+
+ /**
+ * Queries the Torrent Search package for all available in-app search sites. This method is synchronous.
+ * @return A list of available search sites as POJOs, or null if the Torrent Search package is not installed
+ */
+ public List getAvailableSites() {
+
+ // Try to access the TorrentSitesProvider to retrieve all available in-app torrent search sites
+ Uri uri = Uri.parse("content://org.transdroid.search.torrentsitesprovider/sites");
+ Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
+ if (cursor.moveToFirst()) {
+ List sites = new ArrayList();
+ do {
+ // Read the cursor fields into the SearchSite object
+ sites.add(new SearchSite(cursor.getInt(CURSOR_SITE_ID), cursor.getString(CURSOR_SITE_CODE), cursor
+ .getString(CURSOR_SITE_NAME), cursor.getString(CURSOR_SITE_RSSURL)));
+ } while (cursor.moveToNext());
+ cursor.close();
+ return sites;
+ }
+
+ // Torrent Search package is not yet installed
+ return null;
+
+ }
+
+ /**
+ * Queries the Torrent Search module to search for torrents on the web. This method is synchornous and should always
+ * be called in a background thread.
+ * @param query The search query to pass to the torrent site
+ * @param site The site to search, as retrieved from the TorrentSitesProvider, or null if the Torrent Search package
+ * @param sortBy.name() The sort order to request from the torrent site, if supported
+ * @return A list of torrent search results as POJOs, or null if the Torrent Search package is not installed
+ */
+ public List search(String query, SearchSite site, SearchSortOrder sortBy) {
+
+ // Try to query the TorrentSearchProvider to search for torrents on the web
+ Uri uri = Uri.parse("content://org.transdroid.search.torrentsearchprovider/search/" + query);
+ Cursor cursor;
+ if (site == null) {
+ // If no explicit site was supplied, rely on the Torrent Search package's default
+ cursor = context.getContentResolver().query(uri, null, null, null, sortBy.name());
+ } else {
+ cursor = context.getContentResolver().query(uri, null, "SITE = ?", new String[] { site.getKey() },
+ sortBy.name());
+ }
+ if (cursor.moveToFirst()) {
+ List results = new ArrayList();
+ do {
+ // Read the cursor fields into the SearchResult object
+ results.add(new SearchResult(cursor.getInt(CURSOR_SEARCH_ID), cursor.getString(CURSOR_SEARCH_NAME),
+ cursor.getString(CURSOR_SEARCH_TORRENTURL), cursor.getString(CURSOR_SEARCH_DETAILSURL), cursor
+ .getString(CURSOR_SEARCH_SIZE), cursor.getLong(CURSOR_SEARCH_ADDED), cursor
+ .getString(CURSOR_SEARCH_SEEDERS), cursor.getString(CURSOR_SEARCH_LEECHERS)));
+ } while (cursor.moveToNext());
+ cursor.close();
+ return results;
+ }
+
+ // Torrent Search package is not yet installed
+ return null;
+
+ }
+
+}
diff --git a/lite/src/org/transdroid/lite/app/search/SearchResult.java b/lite/src/org/transdroid/lite/app/search/SearchResult.java
new file mode 100644
index 00000000..77594909
--- /dev/null
+++ b/lite/src/org/transdroid/lite/app/search/SearchResult.java
@@ -0,0 +1,64 @@
+package org.transdroid.lite.app.search;
+
+import java.util.Date;
+
+/**
+ * Represents a search result as retrieved by querying the Torrent Search package.
+ * @author Eric Kok
+ */
+public class SearchResult {
+
+ private final int id;
+ private final String name;
+ private final String torrentUrl;
+ private final String detailsUrl;
+ private final String size;
+ private final Date addedOn;
+ private final String seeders;
+ private final String leechers;
+
+ public SearchResult(int id, String name, String torrentUrl, String detailsUrl, String size, long addedOnTime,
+ String seeders, String leechers) {
+ this.id = id;
+ this.name = name;
+ this.torrentUrl = torrentUrl;
+ this.detailsUrl = detailsUrl;
+ this.size = size;
+ this.addedOn = (addedOnTime == -1L) ? null : new Date(addedOnTime);
+ this.seeders = seeders;
+ this.leechers = leechers;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getTorrentUrl() {
+ return torrentUrl;
+ }
+
+ public String getDetailsUrl() {
+ return detailsUrl;
+ }
+
+ public String getSize() {
+ return size;
+ }
+
+ public Date getAddedOn() {
+ return addedOn;
+ }
+
+ public String getSeeders() {
+ return seeders;
+ }
+
+ public String getLeechers() {
+ return leechers;
+ }
+
+}
diff --git a/lite/src/org/transdroid/lite/app/search/SearchSite.java b/lite/src/org/transdroid/lite/app/search/SearchSite.java
new file mode 100644
index 00000000..2d7910df
--- /dev/null
+++ b/lite/src/org/transdroid/lite/app/search/SearchSite.java
@@ -0,0 +1,40 @@
+package org.transdroid.lite.app.search;
+
+import org.transdroid.lite.gui.navigation.FilterItem;
+
+/**
+ * Represents an available torrent site that can be searched using the Torrent Search package.
+ * @author Eric Kok
+ */
+public class SearchSite implements FilterItem {
+
+ private final int id;
+ private final String key;
+ private final String name;
+ private final String rssFeedUrl;
+
+ public SearchSite(int id, String key, String name, String rssFeedUrl) {
+ this.id = id;
+ this.key = key;
+ this.name = name;
+ this.rssFeedUrl = rssFeedUrl;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ public String getRssFeedUrl() {
+ return rssFeedUrl;
+ }
+
+}
diff --git a/lite/src/org/transdroid/lite/app/settings/AboutSettings.java b/lite/src/org/transdroid/lite/app/settings/AboutSettings.java
new file mode 100644
index 00000000..9dd745c7
--- /dev/null
+++ b/lite/src/org/transdroid/lite/app/settings/AboutSettings.java
@@ -0,0 +1,30 @@
+package org.transdroid.lite.app.settings;
+
+import org.androidannotations.annotations.EBean;
+import org.androidannotations.annotations.RootContext;
+import org.androidannotations.annotations.EBean.Scope;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+
+/**
+ * Allows instantiation of the settings specified in R.xml.pref_about.
+ * @author Eric Kok
+ */
+@EBean(scope = Scope.Singleton)
+public class AboutSettings {
+
+ @RootContext
+ protected Context context;
+ private SharedPreferences prefs;
+
+ protected AboutSettings(Context context) {
+ prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ }
+
+ public boolean checkForUpdates() {
+ return prefs.getBoolean("about_checkupdates", true);
+ }
+
+}
diff --git a/lite/src/org/transdroid/lite/app/settings/ApplicationSettings.java b/lite/src/org/transdroid/lite/app/settings/ApplicationSettings.java
new file mode 100644
index 00000000..75a4c09e
--- /dev/null
+++ b/lite/src/org/transdroid/lite/app/settings/ApplicationSettings.java
@@ -0,0 +1,140 @@
+package org.transdroid.lite.app.settings;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.androidannotations.annotations.EBean;
+import org.androidannotations.annotations.EBean.Scope;
+import org.androidannotations.annotations.RootContext;
+import org.transdroid.daemon.Daemon;
+import org.transdroid.daemon.OS;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.preference.PreferenceManager;
+
+/**
+ * Singleton object to access all application settings, including stored servers, web search sites and RSS feeds.
+ * @author Eric Kok
+ */
+@EBean(scope = Scope.Singleton)
+public class ApplicationSettings {
+
+ @RootContext
+ protected Context context;
+ private SharedPreferences prefs;
+
+ protected ApplicationSettings(Context context) {
+ prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ }
+
+ /**
+ * Returns all available user-configured servers
+ * @return A list of all stored server settings objects
+ */
+ public List getServerSettings() {
+ List servers = new ArrayList();
+ for (int i = 0; i <= getMaxServer(); i++) {
+ servers.add(getServerSetting(i));
+ }
+ return servers;
+ }
+
+ /**
+ * Returns the order number/identifying key of the last server
+ * @return The zero-based order number (index) of the last stored server settings
+ */
+ public int getMaxServer() {
+ for (int i = 0; true; i++) {
+ if (prefs.getString("server_type_" + i, null) == null)
+ return i - 1;
+ }
+ }
+
+ /**
+ * Returns the user-specified server settings for a specific server
+ * @param order The order number/identifying key of the settings to retrieve
+ * @return The server settings object, loaded from shared preferences
+ */
+ public ServerSetting getServerSetting(int order) {
+ return new ServerSetting(order, prefs.getString("server_name_" + order, null), Daemon.fromCode(prefs.getString(
+ "server_type_" + order, null)), prefs.getString("server_address_" + order, null), prefs.getString(
+ "server_localaddress_" + order, null), prefs.getString("server_localnetwork_" + order, null),
+ prefs.getInt("server_port_" + order, -1), prefs.getBoolean("server_sslenabled_" + order, false),
+ prefs.getBoolean("server_ssltrustall_" + order, false), prefs.getString("server_ssltrustkey_" + order,
+ null), prefs.getString("server_folder_" + order, null), prefs.getBoolean("server_useauth_"
+ + order, true), prefs.getString("server_user_" + order, null), prefs.getString("server_pass_"
+ + order, null), prefs.getString("server_extrapass_" + order, null), OS.fromCode(prefs
+ .getString("server_os_" + order, null)), prefs.getString("server_downloaddir_" + order, null),
+ prefs.getString("server_ftpurl_" + order, null), prefs.getString("server_ftppass_" + order, null),
+ prefs.getInt("server_timeout_" + order, -1), prefs.getBoolean("server_alarmfinished_" + order, true),
+ prefs.getBoolean("server_alarmnew_" + order, false), false);
+ }
+
+ /**
+ * Returns all available user-configured web-based (as opped to in-app) search sites
+ * @return A list of all stored web search site settings objects
+ */
+ public List getWebsearchSettings() {
+ List websearches = new ArrayList();
+ for (int i = 0; i <= getMaxWebsearch(); i++) {
+ websearches.add(getWebsearchSetting(i));
+ }
+ return websearches;
+ }
+
+ /**
+ * Returns the order number/identifying key of the last web search site
+ * @return The zero-based order number (index) of the last stored web search site
+ */
+ public int getMaxWebsearch() {
+ for (int i = 0; true; i++) {
+ if (prefs.getString("websearch_url_" + i, null) == null)
+ return i - 1;
+ }
+ }
+
+ /**
+ * Returns the user-specified web-based search site setting for a specific site
+ * @param order The order number/identifying key of the settings to retrieve
+ * @return The web search site settings object, loaded from shared preferences
+ */
+ public WebsearchSetting getWebsearchSetting(int order) {
+ return new WebsearchSetting(order, prefs.getString("websearch_name_" + order, null), prefs.getString(
+ "websearch_url_" + order, null));
+ }
+
+ /**
+ * Returns all available user-configured RSS feeds
+ * @return A list of all stored RSS feed settings objects
+ */
+ public List getRssfeedSettings() {
+ List rssfeeds = new ArrayList();
+ for (int i = 0; i <= getMaxRssfeed(); i++) {
+ rssfeeds.add(getRssfeedSetting(i));
+ }
+ return rssfeeds;
+ }
+
+ /**
+ * Returns the order number/identifying key of the last stored RSS feed
+ * @return The zero-based order number (index) of the last stored RSS feed
+ */
+ public int getMaxRssfeed() {
+ for (int i = 0; true; i++) {
+ if (prefs.getString("rssfeed_feedurl_" + i, null) == null)
+ return i - 1;
+ }
+ }
+
+ /**
+ * Returns the user-specified RSS feed setting for a specific feed
+ * @param order The order number/identifying key of the settings to retrieve
+ * @return The RSS feed settings object, loaded from shared preferences
+ */
+ public RssfeedSetting getRssfeedSetting(int order) {
+ return new RssfeedSetting(order, prefs.getString("rssfeed_name_" + order, null), prefs.getString(
+ "rssfeed_feedurl_" + order, null), prefs.getBoolean("rssfeed_reqauth_" + order, false));
+ }
+
+}
diff --git a/lite/src/org/transdroid/lite/app/settings/NotificationSettings.java b/lite/src/org/transdroid/lite/app/settings/NotificationSettings.java
new file mode 100644
index 00000000..1a68aabd
--- /dev/null
+++ b/lite/src/org/transdroid/lite/app/settings/NotificationSettings.java
@@ -0,0 +1,97 @@
+package org.transdroid.lite.app.settings;
+
+import org.androidannotations.annotations.EBean;
+import org.androidannotations.annotations.EBean.Scope;
+import org.androidannotations.annotations.RootContext;
+import org.transdroid.core.R;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.net.Uri;
+import android.preference.PreferenceManager;
+import android.provider.Settings;
+
+/**
+ * Allows instantiation of the settings specified in R.xml.pref_notifications.
+ * @author Eric Kok
+ */
+@EBean(scope = Scope.Singleton)
+public class NotificationSettings {
+
+ @RootContext
+ protected Context context;
+ private SharedPreferences prefs;
+
+ protected NotificationSettings(Context context) {
+ prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ }
+
+ /**
+ * Whether the background service is enabled, i.e. whether the user want to receive notifications
+ * @return True if the server should be checked for torrent status updates
+ */
+ public boolean isEnabled() {
+ return prefs.getBoolean("notifications_enabled", true);
+ }
+
+ private String getRawInverval() {
+ return prefs.getString("notifications_interval", "10800");
+ }
+
+ /**
+ * Returns the interval between two server checks
+ * @return The interval, in milliseconds
+ */
+ public Long getInvervalInMilliseconds() {
+ return Long.parseLong(getRawInverval()) * 1000L;
+ }
+
+ private String getRawSound() {
+ return prefs.getString("notifications_sound", null);
+ }
+
+ /**
+ * Returns the sound (ring tone) to play on a new notification, or null if it should not play any
+ * @return Either the user-specified sound, null if the user specified 'Silent' or the system default notification sound
+ */
+ public Uri getSound() {
+ String raw = getRawSound();
+ if (raw == null)
+ return null;
+ if (raw.equals(""))
+ return Settings.System.DEFAULT_NOTIFICATION_URI;
+ return Uri.parse(raw);
+ }
+
+ /**
+ * Whether the device should vibrate on a new notification
+ * @return
+ */
+ public boolean shouldVibrate() {
+ return prefs.getBoolean("notifications_vibrate", false);
+ }
+
+ private int getRawLedColour() {
+ return prefs.getInt("notifications_ledcolour", -1);
+ }
+
+ /**
+ * Returns the LED colour to use on a new notification
+ * @return The integer value of the user-specified or default colour
+ */
+ public int getDesiredLedColour() {
+ int raw = getRawLedColour();
+ if (raw <= 0)
+ return context.getResources().getColor(R.color.ledgreen);
+ return raw;
+ }
+
+ /**
+ * Whether the background service should report to ADW Launcher
+ * @return True if the user want Transdroid to report to ADW Launcher
+ */
+ public boolean shouldReportToAdwLauncher() {
+ return prefs.getBoolean("notifications_adwnotify", false);
+ }
+
+}
diff --git a/lite/src/org/transdroid/lite/app/settings/RssfeedSetting.java b/lite/src/org/transdroid/lite/app/settings/RssfeedSetting.java
new file mode 100644
index 00000000..69ee3823
--- /dev/null
+++ b/lite/src/org/transdroid/lite/app/settings/RssfeedSetting.java
@@ -0,0 +1,67 @@
+package org.transdroid.lite.app.settings;
+
+import org.transdroid.lite.gui.navigation.FilterItem;
+
+import android.net.Uri;
+import android.text.TextUtils;
+
+/**
+ * Represents a user-specified RSS feed.
+ * @author Eric Kok
+ */
+public class RssfeedSetting implements FilterItem {
+
+ private static final String DEFAULT_NAME = "Default";
+
+ private final int order;
+ private final String name;
+ private final String url;
+ private final boolean requiresAuth;
+ private String lastNew;
+
+ public RssfeedSetting(int order, String name, String baseUrl, boolean needsAuth) {
+ this.order = order;
+ this.name = name;
+ this.url = baseUrl;
+ this.requiresAuth = needsAuth;
+ this.lastNew = null;
+ }
+
+ public int getOrder() {
+ return order;
+ }
+
+ @Override
+ public String getName() {
+ if (!TextUtils.isEmpty(name))
+ return name;
+ if (!TextUtils.isEmpty(url))
+ return Uri.parse(url).getHost();
+ return DEFAULT_NAME;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public boolean requiresExternalAuthentication() {
+ return requiresAuth;
+ }
+
+ /**
+ * Returns the URL of the item that was the newest last time we checked this feed
+ * @return The last new item's URL as URL-encoded string
+ */
+ public String getLastNew() {
+ return this.lastNew;
+ }
+
+ /**
+ * Record the URL of what is now the last item we retrieved
+ * @param lastNew The URL of the last new item as URL-encoded string
+ */
+ public void setLastNew(String lastNew) {
+ this.lastNew = lastNew;
+ }
+
+}
diff --git a/lite/src/org/transdroid/lite/app/settings/ServerSetting.java b/lite/src/org/transdroid/lite/app/settings/ServerSetting.java
new file mode 100644
index 00000000..164be4ad
--- /dev/null
+++ b/lite/src/org/transdroid/lite/app/settings/ServerSetting.java
@@ -0,0 +1,195 @@
+package org.transdroid.lite.app.settings;
+
+import org.transdroid.daemon.Daemon;
+import org.transdroid.daemon.OS;
+import org.transdroid.lite.gui.navigation.FilterItem;
+
+import android.text.TextUtils;
+
+/**
+ * Represents a user-configured remote server.
+ * @author Eric Kok
+ */
+public class ServerSetting implements FilterItem {
+
+ private static final String DEFAULT_NAME = "Default";
+
+ private final int key;
+ private final String name;
+ private final Daemon type;
+ private final String address;
+ private final String localAddress;
+ private final String localNetwork;
+ private final int port;
+ private final String folder;
+ private final boolean useAuthentication;
+ private final String username;
+ private final String password;
+ private final String extraPass;
+ private final OS os;
+ private final String downloadDir;
+ private final String ftpUrl;
+ private final String ftpPassword;
+ private final int timeout;
+ private final boolean alarmOnFinishedDownload;
+ private final boolean alarmOnNewTorrent;
+ private final boolean ssl;
+ private final boolean sslTrustAll;
+ private final String sslTrustKey;
+ private final boolean isAutoGenerated;
+
+ /**
+ * Creates a daemon settings instance, providing full connection details
+ * @param name A name used to identify this server to the user
+ * @param type The server daemon type
+ * @param address The server domain name or IP address
+ * @param localAddress The server domain or IP address when connected to the server's local network
+ * @param localNetwork The server's local network SSID
+ * @param port The port on which the server daemon is running
+ * @param sslTrustKey The specific key that will be accepted.
+ * @param folder The server folder (like a virtual sub-folder or an SCGI mount point)
+ * @param useAuthentication Whether to use basic authentication
+ * @param username The user name to provide during authentication
+ * @param password The password to provide during authentication
+ * @param extraPass The Deluge web interface password
+ * @param downloadDir The default download directory (which may also be used as base directory for file paths)
+ * @param ftpUrl The partial URL to connect to when requesting FTP-style transfers
+ * @param timeout The number of seconds to wait before timing out a connection attempt
+ * @param isAutoGenerated Whether this setting was generated rather than manually inputed by the user
+ */
+ public ServerSetting(int key, String name, Daemon type, String address, String localAddress, String localNetwork,
+ int port, boolean ssl, boolean sslTrustAll, String sslTrustKey, String folder, boolean useAuthentication,
+ String username, String password, String extraPass, OS os, String downloadDir, String ftpUrl,
+ String ftpPassword, int timeout, boolean alarmOnFinishedDownload, boolean alarmOnNewTorrent,
+ boolean isAutoGenerated) {
+ this.key = key;
+ this.name = name;
+ this.type = type;
+ this.address = address;
+ this.localAddress = localAddress;
+ this.localNetwork = localNetwork;
+ this.port = port;
+ this.ssl = ssl;
+ this.sslTrustAll = sslTrustAll;
+ this.sslTrustKey = sslTrustKey;
+ this.folder = folder;
+ this.useAuthentication = useAuthentication;
+ this.username = username;
+ this.password = password;
+ this.extraPass = extraPass;
+ this.os = os;
+ this.downloadDir = downloadDir;
+ this.ftpUrl = ftpUrl;
+ this.ftpPassword = ftpPassword;
+ this.timeout = timeout;
+ this.alarmOnFinishedDownload = alarmOnFinishedDownload;
+ this.alarmOnNewTorrent = alarmOnNewTorrent;
+ this.isAutoGenerated = isAutoGenerated;
+ }
+
+ @Override
+ public String getName() {
+ return (name == null || name.equals("") ? DEFAULT_NAME : name);
+ }
+
+ public Daemon getType() {
+ return type;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public String getLocalAddress() {
+ return localAddress;
+ }
+
+ public String getLocalNetwork() {
+ return localNetwork;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public boolean getSsl() {
+ return ssl;
+ }
+
+ public boolean getSslTrustAll() {
+ return sslTrustAll;
+ }
+
+ public String getSslTrustKey() {
+ return sslTrustKey;
+ }
+
+ public String getFolder() {
+ return folder;
+ }
+
+ public boolean shouldUseAuthentication() {
+ return useAuthentication;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public String getExtraPassword() {
+ return extraPass;
+ }
+
+ public OS getOS() {
+ return os;
+ }
+
+ public String getDownloadDir() {
+ return downloadDir;
+ }
+
+ public String getFtpUrl() {
+ return ftpUrl;
+ }
+
+ public String getFtpPassword() {
+ return ftpPassword;
+ }
+
+ public int getTimeoutInMilliseconds() {
+ return timeout * 1000;
+ }
+
+ public boolean shouldAlarmOnFinishedDownload() {
+ return alarmOnFinishedDownload;
+ }
+
+ public boolean shouldAlarmOnNewTorrent() {
+ return alarmOnNewTorrent;
+ }
+
+ public boolean isAutoGenerated() {
+ return isAutoGenerated;
+ }
+
+ public int getOrder() {
+ return this.key;
+ }
+
+ public String getHumanReadableIdentifier() {
+ if (isAutoGenerated) {
+ // Hide the 'implementation details'; just give the username and server
+ return (this.shouldUseAuthentication() && !TextUtils.isEmpty(this.getUsername()) ? this.getUsername() + "@"
+ : "") + getAddress();
+ }
+ return (this.ssl ? "https://" : "http://")
+ + (this.shouldUseAuthentication() && !TextUtils.isEmpty(this.getUsername()) ? this.getUsername() + "@"
+ : "") + getAddress() + ":" + getPort()
+ + (Daemon.supportsCustomFolder(getType()) && getFolder() != null ? getFolder() : "");
+ }
+
+}
diff --git a/lite/src/org/transdroid/lite/app/settings/WebsearchSetting.java b/lite/src/org/transdroid/lite/app/settings/WebsearchSetting.java
new file mode 100644
index 00000000..b4da7aed
--- /dev/null
+++ b/lite/src/org/transdroid/lite/app/settings/WebsearchSetting.java
@@ -0,0 +1,48 @@
+package org.transdroid.lite.app.settings;
+
+import org.transdroid.lite.gui.navigation.FilterItem;
+
+import android.net.Uri;
+import android.text.TextUtils;
+
+/**
+ * Represents a user-specified website that can be searched (by starting the browser, rather than in-app)
+ * @author Eric Kok
+ */
+public class WebsearchSetting implements FilterItem {
+
+ private static final String DEFAULT_NAME = "Default";
+ private static final String KEY_PREFIX = "websearch_";
+
+ private final int order;
+ private final String name;
+ private final String baseUrl;
+
+ public WebsearchSetting(int order, String name, String baseUrl) {
+ this.order = order;
+ this.name = name;
+ this.baseUrl = baseUrl;
+ }
+
+ public int getOrder() {
+ return order;
+ }
+
+ @Override
+ public String getName() {
+ if (!TextUtils.isEmpty(name))
+ return name;
+ if (!TextUtils.isEmpty(baseUrl))
+ return Uri.parse(baseUrl).getHost();
+ return DEFAULT_NAME;
+ }
+
+ public String getBaseUrl() {
+ return baseUrl;
+ }
+
+ public String getKey() {
+ return KEY_PREFIX + getOrder();
+ }
+
+}
diff --git a/lite/src/org/transdroid/lite/gui/DetailsFagment.java b/lite/src/org/transdroid/lite/gui/DetailsFagment.java
index 1b3c7e10..c43b8135 100644
--- a/lite/src/org/transdroid/lite/gui/DetailsFagment.java
+++ b/lite/src/org/transdroid/lite/gui/DetailsFagment.java
@@ -7,7 +7,7 @@ import org.androidannotations.annotations.InstanceState;
import org.androidannotations.annotations.ViewById;
import org.transdroid.daemon.Torrent;
import org.transdroid.daemon.TorrentDetails;
-import org.transdroid.lite.R;
+import org.transdroid.core.R;
import android.view.View;
import android.widget.TextView;
diff --git a/lite/src/org/transdroid/lite/gui/TorrentsActivity.java b/lite/src/org/transdroid/lite/gui/TorrentsActivity.java
index f368bc94..1af298df 100644
--- a/lite/src/org/transdroid/lite/gui/TorrentsActivity.java
+++ b/lite/src/org/transdroid/lite/gui/TorrentsActivity.java
@@ -4,15 +4,15 @@ import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Bean;
import org.androidannotations.annotations.EActivity;
import org.androidannotations.annotations.FragmentById;
-import org.androidannotations.annotations.FragmentByTag;
import org.androidannotations.annotations.ItemSelect;
import org.androidannotations.annotations.OptionsMenu;
import org.androidannotations.annotations.ViewById;
-import org.transdroid.lite.R;
+import org.transdroid.core.R;
+import org.transdroid.lite.app.settings.ApplicationSettings;
import org.transdroid.lite.gui.navigation.FilterAdapter;
import org.transdroid.lite.gui.navigation.FilterItem;
-import org.transdroid.lite.gui.navigation.FilterSeparatorView;
import org.transdroid.lite.gui.navigation.NavigationHelper;
+import org.transdroid.lite.gui.navigation.StatusType;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.OnNavigationListener;
@@ -30,6 +30,10 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi
protected SherlockListView filtersList;
protected FilterAdapter navigationListAdapter = null;
protected FilterAdapter navigationSpinnerAdapter = null;
+
+ // Settings
+ @Bean
+ protected ApplicationSettings applicationSettings;
// Torrents list components
@FragmentById(R.id.torrent_list)
@@ -42,17 +46,23 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi
@AfterViews
protected void init() {
- // Set up navigation
+ // Set up navigation, with an action bar spinner and possibly (if room) with a filter list
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
getSupportActionBar().setHomeButtonEnabled(false);
navigationSpinnerAdapter = new FilterAdapter(this);
+ // Servers are always added to the action bar spinner
+ navigationSpinnerAdapter.updateServers(applicationSettings.getServerSettings());
getSupportActionBar().setListNavigationCallbacks(navigationSpinnerAdapter, this);
if (filtersList != null) {
+ // There was room for a dedicated filter list; add the status types
navigationListAdapter = new FilterAdapter(this);
filtersList.setAdapter(navigationListAdapter);
+ navigationListAdapter.updateStatusTypes(StatusType.getAllStatusTypes(this));
+ } else {
+ // Add status types directly to the action bar spinner
+ navigationSpinnerAdapter.updateStatusTypes(StatusType.getAllStatusTypes(this));
}
- // Load settings
}
@@ -73,12 +83,12 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi
/**
* A new filter was selected; update the view over the current data
- * @param selected True if
- * @param item
+ * @param selected True if the filter item was selected, false if it was deselected
+ * @param item The touched filter item
*/
@ItemSelect(R.id.filters_list)
protected void filterSelected(boolean selected, FilterItem item) {
- // TODO: Update the view
+ // TODO: Update the torrent list view
}
}
diff --git a/lite/src/org/transdroid/lite/gui/TorrentsFragment.java b/lite/src/org/transdroid/lite/gui/TorrentsFragment.java
index f53a9e1d..5dd796bb 100644
--- a/lite/src/org/transdroid/lite/gui/TorrentsFragment.java
+++ b/lite/src/org/transdroid/lite/gui/TorrentsFragment.java
@@ -1,7 +1,7 @@
package org.transdroid.lite.gui;
import org.androidannotations.annotations.EFragment;
-import org.transdroid.lite.R;
+import org.transdroid.core.R;
import com.actionbarsherlock.app.SherlockFragment;
diff --git a/lite/src/org/transdroid/lite/gui/lists/TorrentProgressBar.java b/lite/src/org/transdroid/lite/gui/lists/TorrentProgressBar.java
new file mode 100644
index 00000000..0dbe8fc1
--- /dev/null
+++ b/lite/src/org/transdroid/lite/gui/lists/TorrentProgressBar.java
@@ -0,0 +1,110 @@
+package org.transdroid.lite.gui.lists;
+
+import org.transdroid.core.R;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.view.View;
+
+/**
+ * Draws a progress bar indicating the download progress as well as the torrent status.
+ *
+ * @author Eric Kok
+ */
+public class TorrentProgressBar extends View {
+
+ private final float scale = getContext().getResources().getDisplayMetrics().density;
+ private final int MINIMUM_HEIGHT = (int) (2 * scale + 0.5f);
+ // private final int RIGHT_MARGIN = (int)(3 * scale + 0.5f);
+
+ private int progress;
+ private boolean isActive;
+ private boolean isError;
+ private final Paint notdonePaint = new Paint();
+ 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 errorPaint = new Paint();
+ private final RectF fullRect = new RectF();
+ private final RectF progressRect = new RectF();
+
+ public void setProgress(int progress) {
+ this.progress = progress;
+ this.invalidate();
+ }
+
+ public void setActive(boolean isActive) {
+ this.isActive = isActive;
+ this.invalidate();
+ }
+
+ public void setError(boolean isError) {
+ this.isError = isError;
+ this.invalidate();
+ }
+
+ public TorrentProgressBar(Context context) {
+ super(context);
+ initPaints();
+ }
+
+ public TorrentProgressBar(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ initPaints();
+
+ // Parse any set attributes from XML
+ TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TorrentProgressBar);
+ if (a.hasValue(R.styleable.TorrentProgressBar_progress)) {
+ this.progress = a.getIndex(R.styleable.TorrentProgressBar_progress);
+ this.isActive = a.getBoolean(R.styleable.TorrentProgressBar_isActive, false);
+ }
+ a.recycle();
+ }
+
+ private void initPaints() {
+ notdonePaint.setColor(0xFFEEEEEE);
+ inactiveDonePaint.setColor(0xFFA759D4);
+ inactivePaint.setColor(0xFF9E9E9E);
+ progressPaint.setColor(0xFF42A8FA);
+ donePaint.setColor(0xFF8CCF29);
+ errorPaint.setColor(0xFFDE3939);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int ws = MeasureSpec.getSize(widthMeasureSpec);// - RIGHT_MARGIN;
+ int hs = Math.max(getHeight(), MINIMUM_HEIGHT);
+ setMeasuredDimension(ws, hs);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ int height = getHeight();
+ int width = getWidth();
+ fullRect.set(0, 0, width, height);
+
+ // Error?
+ if (isError) {
+ canvas.drawRect(fullRect, errorPaint);
+ } else {
+ // Background rounded rectangle
+ canvas.drawRect(fullRect, notdonePaint);
+
+ // Foreground progress indicator
+ if (progress > 0) {
+ progressRect.set(0, 0, width * ((float) progress / 100), height);
+ canvas.drawRect(progressRect, (isActive ? (progress == 100 ? donePaint : progressPaint)
+ : (progress == 100 ? inactiveDonePaint : inactivePaint)));
+ }
+ }
+
+ }
+
+}
diff --git a/lite/src/org/transdroid/lite/gui/navigation/FilterAdapter.java b/lite/src/org/transdroid/lite/gui/navigation/FilterAdapter.java
index 0ffb0b8e..22f9dbe6 100644
--- a/lite/src/org/transdroid/lite/gui/navigation/FilterAdapter.java
+++ b/lite/src/org/transdroid/lite/gui/navigation/FilterAdapter.java
@@ -2,7 +2,7 @@ package org.transdroid.lite.gui.navigation;
import java.util.List;
-import org.transdroid.lite.R;
+import org.transdroid.core.R;
import android.content.Context;
import android.view.View;
@@ -31,7 +31,7 @@ public class FilterAdapter extends MergeAdapter {
* Update the list of available servers.
* @param servers The new list of available servers
*/
- public void updateServers(List servers) {
+ public void updateServers(List extends FilterItem> servers) {
if (this.serverItems == null && servers != null) {
addView(FilterSeparatorView_.build(context).setText(context.getString(R.string.navigation_servers)), false);
this.serverItems = new FilterItemAdapter(context, servers);
@@ -47,7 +47,7 @@ public class FilterAdapter extends MergeAdapter {
* Update the list of available status types.
* @param statusTypes The new list of available status types
*/
- public void updateStatusTypes(List statusTypes) {
+ public void updateStatusTypes(List extends FilterItem> statusTypes) {
if (this.statusTypeItems == null && statusTypes != null) {
addView(FilterSeparatorView_.build(context).setText(context.getString(R.string.navigation_status)), false);
this.statusTypeItems = new FilterItemAdapter(context, statusTypes);
@@ -63,7 +63,7 @@ public class FilterAdapter extends MergeAdapter {
* Update the list of available labels.
* @param labels The new list of available labels
*/
- public void updateLabels(List labels) {
+ public void updateLabels(List extends FilterItem> labels) {
if (this.labelItems == null && labels != null) {
addView(FilterSeparatorView_.build(context).setText(context.getString(R.string.navigation_labels)), false);
this.labelItems = new FilterItemAdapter(context, labels);
@@ -78,9 +78,9 @@ public class FilterAdapter extends MergeAdapter {
protected class FilterItemAdapter extends BaseAdapter {
private final Context context;
- private List items;
+ private List extends FilterItem> items;
- public FilterItemAdapter(Context context, List items) {
+ public FilterItemAdapter(Context context, List extends FilterItem> items) {
this.context = context;
this.items = items;
}
@@ -89,7 +89,7 @@ public class FilterAdapter extends MergeAdapter {
* Allows updating of the full data list underlying this adapter, replacing all items
* @param newItems The new list of filter items to display
*/
- public void update(List newItems) {
+ public void update(List extends FilterItem> newItems) {
this.items = newItems;
notifyDataSetChanged();
}
diff --git a/lite/src/org/transdroid/lite/gui/navigation/FilterItemView.java b/lite/src/org/transdroid/lite/gui/navigation/FilterItemView.java
index e7f6dc82..532f85f3 100644
--- a/lite/src/org/transdroid/lite/gui/navigation/FilterItemView.java
+++ b/lite/src/org/transdroid/lite/gui/navigation/FilterItemView.java
@@ -2,7 +2,7 @@ package org.transdroid.lite.gui.navigation;
import org.androidannotations.annotations.EViewGroup;
import org.androidannotations.annotations.ViewById;
-import org.transdroid.lite.R;
+import org.transdroid.core.R;
import android.content.Context;
import android.widget.LinearLayout;
diff --git a/lite/src/org/transdroid/lite/gui/navigation/FilterSeparatorView.java b/lite/src/org/transdroid/lite/gui/navigation/FilterSeparatorView.java
index 09368d89..ea6deaff 100644
--- a/lite/src/org/transdroid/lite/gui/navigation/FilterSeparatorView.java
+++ b/lite/src/org/transdroid/lite/gui/navigation/FilterSeparatorView.java
@@ -2,7 +2,7 @@ package org.transdroid.lite.gui.navigation;
import org.androidannotations.annotations.EViewGroup;
import org.androidannotations.annotations.ViewById;
-import org.transdroid.lite.R;
+import org.transdroid.core.R;
import android.content.Context;
import android.widget.LinearLayout;
diff --git a/lite/src/org/transdroid/lite/gui/navigation/Label.java b/lite/src/org/transdroid/lite/gui/navigation/Label.java
new file mode 100644
index 00000000..6da5d20a
--- /dev/null
+++ b/lite/src/org/transdroid/lite/gui/navigation/Label.java
@@ -0,0 +1,20 @@
+package org.transdroid.lite.gui.navigation;
+
+/**
+ * Represents some label that is active or available on the server.
+ * @author Eric Kok
+ */
+public class Label implements FilterItem {
+
+ private final String name;
+
+ public Label(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getName() {
+ return this.name;
+ }
+
+}
diff --git a/lite/src/org/transdroid/lite/gui/navigation/StatusType.java b/lite/src/org/transdroid/lite/gui/navigation/StatusType.java
new file mode 100644
index 00000000..2aaac124
--- /dev/null
+++ b/lite/src/org/transdroid/lite/gui/navigation/StatusType.java
@@ -0,0 +1,75 @@
+package org.transdroid.lite.gui.navigation;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.transdroid.core.R;
+
+import android.content.Context;
+
+/**
+ * Enumeration of all status types, which filter the list of shown torrents based on transfer activity.
+ * @author Eric Kok
+ */
+public enum StatusType {
+
+ ShowAll {
+ StatusTypeFilter getFilterItem(Context context) {
+ return new StatusTypeFilter(context.getString(R.string.navigation_status_showall));
+ }
+ },
+ OnlyDownloading {
+ StatusTypeFilter getFilterItem(Context context) {
+ return new StatusTypeFilter(context.getString(R.string.navigation_status_onlydown));
+ }
+ },
+ OnlyUploading {
+ StatusTypeFilter getFilterItem(Context context) {
+ return new StatusTypeFilter(context.getString(R.string.navigation_status_onlyup));
+ }
+ },
+ OnlyActive {
+ StatusTypeFilter getFilterItem(Context context) {
+ return new StatusTypeFilter(context.getString(R.string.navigation_status_onlyactive));
+ }
+ },
+ OnlyInactive {
+ StatusTypeFilter getFilterItem(Context context) {
+ return new StatusTypeFilter(context.getString(R.string.navigation_status_onlyinactive));
+ }
+ };
+
+ /**
+ * Returns a list with all status types, represented as filter item that can be shown in the GUI.
+ * @param context The Android UI context, to access translations
+ * @return A list of filter items for all available status types
+ */
+ public static List getAllStatusTypes(Context context) {
+ return Arrays.asList(ShowAll.getFilterItem(context), OnlyDownloading.getFilterItem(context),
+ OnlyUploading.getFilterItem(context), OnlyActive.getFilterItem(context),
+ OnlyInactive.getFilterItem(context));
+ }
+
+ /**
+ * Every status type can return a filter item that represents it in the navigation
+ * @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 static class StatusTypeFilter implements FilterItem {
+
+ private final String name;
+
+ StatusTypeFilter(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ }
+
+}
diff --git a/lite/src/org/transdroid/lite/gui/settings/MainSettingsActivity.java b/lite/src/org/transdroid/lite/gui/settings/MainSettingsActivity.java
new file mode 100644
index 00000000..5240fee5
--- /dev/null
+++ b/lite/src/org/transdroid/lite/gui/settings/MainSettingsActivity.java
@@ -0,0 +1,164 @@
+package org.transdroid.lite.gui.settings;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.androidannotations.annotations.Bean;
+import org.androidannotations.annotations.EActivity;
+import org.transdroid.core.R;
+import org.transdroid.lite.app.search.SearchHelper;
+import org.transdroid.lite.app.search.SearchSite;
+import org.transdroid.lite.app.settings.ApplicationSettings;
+import org.transdroid.lite.app.settings.RssfeedSetting;
+import org.transdroid.lite.app.settings.ServerSetting;
+import org.transdroid.lite.app.settings.WebsearchSetting;
+import org.transdroid.lite.gui.settings.RssfeedPreference.OnRssfeedClickedListener;
+import org.transdroid.lite.gui.settings.ServerPreference.OnServerClickedListener;
+import org.transdroid.lite.gui.settings.WebsearchPreference.OnWebsearchClickedListener;
+
+import android.os.Bundle;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceClickListener;
+
+import com.actionbarsherlock.app.SherlockPreferenceActivity;
+
+/**
+ * The main activity that provides access to all application settings. It shows the configured serves, web search sites
+ * and RSS feeds along with other general settings.
+ * @author Eric Kok
+ */
+@EActivity
+public class MainSettingsActivity extends SherlockPreferenceActivity {
+
+ @Bean
+ protected ApplicationSettings applicationSettings;
+ @Bean
+ protected SearchHelper searchHelper;
+
+ @SuppressWarnings("deprecation")
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Load the preference menu and attack actions
+ addPreferencesFromResource(R.xml.pref_main);
+ findPreference("header_addserver").setOnPreferenceClickListener(onAddServer);
+ findPreference("header_addwebsearch").setOnPreferenceClickListener(onAddWebsearch);
+ findPreference("header_rssfeed").setOnPreferenceClickListener(onAddRssfeed);
+ findPreference("header_background").setOnPreferenceClickListener(onBackgroundSettings);
+ findPreference("header_system").setOnPreferenceClickListener(onSystemSettings);
+
+ // Add existing servers
+ List servers = applicationSettings.getServerSettings();
+ for (ServerSetting serverSetting : servers) {
+ getPreferenceScreen().addPreference(
+ new ServerPreference(this).setServerSetting(serverSetting).setOnServerClickedListener(
+ onServerClicked));
+ }
+
+ // Add existing websearch sites
+ List websearches = applicationSettings.getWebsearchSettings();
+ for (WebsearchSetting websearchSetting : websearches) {
+ getPreferenceScreen().addPreference(
+ new WebsearchPreference(this).setWebsearchSetting(websearchSetting).setOnWebsearchClickedListener(
+ onWebsearchClicked));
+ }
+
+ // Add existing RSS feeds
+ List rssfeeds = applicationSettings.getRssfeedSettings();
+ for (RssfeedSetting rssfeedSetting : rssfeeds) {
+ getPreferenceScreen().addPreference(
+ new RssfeedPreference(this).setRssfeedSetting(rssfeedSetting).setOnRssfeedClickedListener(
+ onRssfeedClicked));
+ }
+
+ // Construct list of all available search sites, in-app and web
+ ListPreference setSite = (ListPreference) findPreference("header_setsearchsite");
+ // Retrieve the available in-app search sites (using the Torrent Search package)
+ List searchsites = searchHelper.getAvailableSites();
+ List siteNames = new ArrayList(websearches.size() + searchsites.size());
+ List siteValues = new ArrayList(websearches.size() + searchsites.size());
+ for (SearchSite searchSite : searchsites) {
+ siteNames.add(searchSite.getName());
+ siteValues.add(searchSite.getKey());
+ }
+ for (WebsearchSetting websearch : websearches) {
+ siteNames.add(websearch.getName());
+ siteValues.add(websearch.getKey());
+ }
+ // Supply the Preference list names and values
+ setSite.setEntries(siteNames.toArray(new String[siteNames.size()]));
+ setSite.setEntryValues(siteValues.toArray(new String[siteValues.size()]));
+
+ }
+
+ @Override
+ public void onBuildHeaders(List target) {
+ // TODO: Add two-pane support in settings
+ super.onBuildHeaders(target);
+ }
+
+ private OnPreferenceClickListener onAddServer = new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ ServerSettingsActivity_.intent(MainSettingsActivity.this).start();
+ return true;
+ }
+ };
+
+ private OnPreferenceClickListener onAddWebsearch = new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ WebsearchSettingsActivity_.intent(MainSettingsActivity.this).start();
+ return true;
+ }
+ };
+
+ private OnPreferenceClickListener onAddRssfeed = new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ RssfeedSettingsActivity_.intent(MainSettingsActivity.this).start();
+ return true;
+ }
+ };
+
+ private OnPreferenceClickListener onBackgroundSettings = new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ OtherSettingsActivity_.intent(MainSettingsActivity.this).preferencesResourceID(R.xml.pref_notifications)
+ .start();
+ return true;
+ }
+ };
+
+ private OnPreferenceClickListener onSystemSettings = new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ OtherSettingsActivity_.intent(MainSettingsActivity.this).preferencesResourceID(R.xml.pref_about).start();
+ return true;
+ }
+ };
+
+ private OnServerClickedListener onServerClicked = new OnServerClickedListener() {
+ @Override
+ public void onServerClicked(ServerSetting serverSetting) {
+ ServerSettingsActivity_.intent(MainSettingsActivity.this).key(serverSetting.getOrder()).start();
+ }
+ };
+
+ private OnWebsearchClickedListener onWebsearchClicked = new OnWebsearchClickedListener() {
+ @Override
+ public void onWebsearchClicked(WebsearchSetting websearchSetting) {
+ WebsearchSettingsActivity_.intent(MainSettingsActivity.this).key(websearchSetting.getOrder()).start();
+ }
+ };
+
+ private OnRssfeedClickedListener onRssfeedClicked = new OnRssfeedClickedListener() {
+ @Override
+ public void onRssfeedClicked(RssfeedSetting rssfeedSetting) {
+ RssfeedSettingsActivity_.intent(MainSettingsActivity.this).key(rssfeedSetting.getOrder()).start();
+ }
+ };
+
+}
diff --git a/lite/src/org/transdroid/lite/gui/settings/OtherSettingsActivity.java b/lite/src/org/transdroid/lite/gui/settings/OtherSettingsActivity.java
new file mode 100644
index 00000000..5e23ee79
--- /dev/null
+++ b/lite/src/org/transdroid/lite/gui/settings/OtherSettingsActivity.java
@@ -0,0 +1,31 @@
+package org.transdroid.lite.gui.settings;
+
+import org.androidannotations.annotations.Bean;
+import org.androidannotations.annotations.EActivity;
+import org.androidannotations.annotations.Extra;
+import org.transdroid.lite.app.settings.ApplicationSettings;
+
+import android.os.Bundle;
+
+import com.actionbarsherlock.app.SherlockPreferenceActivity;
+
+@EActivity
+public class OtherSettingsActivity extends SherlockPreferenceActivity {
+
+ @Extra
+ protected int preferencesResourceID;
+
+ @Bean
+ protected ApplicationSettings applicationSettings;
+
+ @SuppressWarnings("deprecation")
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Just load the preferences from XML, of which the ID is supplied as extra
+ addPreferencesFromResource(preferencesResourceID);
+
+ }
+
+}
diff --git a/lite/src/org/transdroid/lite/gui/settings/RssfeedPreference.java b/lite/src/org/transdroid/lite/gui/settings/RssfeedPreference.java
new file mode 100644
index 00000000..49a81046
--- /dev/null
+++ b/lite/src/org/transdroid/lite/gui/settings/RssfeedPreference.java
@@ -0,0 +1,59 @@
+package org.transdroid.lite.gui.settings;
+
+import org.transdroid.lite.app.settings.RssfeedSetting;
+
+import android.content.Context;
+import android.preference.Preference;
+
+/**
+ * Represents a {@link RssfeedSetting} in a preferences screen.
+ * @author Eric Kok
+ */
+public class RssfeedPreference extends Preference {
+
+ private static final int ORDER_START = 201;
+
+ private RssfeedSetting rssfeedSetting;
+ private OnRssfeedClickedListener onRssfeedClickedListener = null;
+
+ public RssfeedPreference(Context context) {
+ super(context);
+ setOnPreferenceClickListener(onPreferenceClicked);
+ }
+
+ /**
+ * Set the RSS feed settings object that is bound to this preference item
+ * @param rssfeedSetting The RSS feed settings
+ * @return Itself, for method chaining
+ */
+ public RssfeedPreference setRssfeedSetting(RssfeedSetting rssfeedSetting) {
+ this.rssfeedSetting = rssfeedSetting;
+ setTitle(rssfeedSetting.getName());
+ setOrder(ORDER_START + rssfeedSetting.getOrder());
+ return this;
+ }
+
+ /**
+ * Set a listener that will be notified of click events on this preference
+ * @param onRssfeedClickedListener The click listener to register
+ * @return Itself, for method chaining
+ */
+ public RssfeedPreference setOnRssfeedClickedListener(OnRssfeedClickedListener onRssfeedClickedListener) {
+ this.onRssfeedClickedListener = onRssfeedClickedListener;
+ return this;
+ }
+
+ private OnPreferenceClickListener onPreferenceClicked = new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ if (onRssfeedClickedListener != null)
+ onRssfeedClickedListener.onRssfeedClicked(rssfeedSetting);
+ return true;
+ }
+ };
+
+ public interface OnRssfeedClickedListener {
+ public void onRssfeedClicked(RssfeedSetting rssfeedSetting);
+ }
+
+}
diff --git a/lite/src/org/transdroid/lite/gui/settings/RssfeedSettingsActivity.java b/lite/src/org/transdroid/lite/gui/settings/RssfeedSettingsActivity.java
new file mode 100644
index 00000000..2b83f52f
--- /dev/null
+++ b/lite/src/org/transdroid/lite/gui/settings/RssfeedSettingsActivity.java
@@ -0,0 +1,46 @@
+package org.transdroid.lite.gui.settings;
+
+import org.androidannotations.annotations.Bean;
+import org.androidannotations.annotations.EActivity;
+import org.androidannotations.annotations.Extra;
+import org.transdroid.core.R;
+import org.transdroid.lite.app.settings.ApplicationSettings;
+
+import android.os.Bundle;
+
+import com.actionbarsherlock.app.SherlockPreferenceActivity;
+
+/**
+ * Activity that allows for a configuration of some RSS feed. The key can be supplied to update an
+ * existing RSS feed setting instead of creating a new one.
+ * @author Eric Kok
+ */
+@EActivity
+public class RssfeedSettingsActivity extends SherlockPreferenceActivity {
+
+ @Extra
+ protected int key = -1;
+
+ @Bean
+ protected ApplicationSettings applicationSettings;
+
+ @SuppressWarnings("deprecation")
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Load the raw preferences to show in this screen
+ addPreferencesFromResource(R.xml.pref_rssfeed);
+
+ // Bind the preferences to the correct storage key, e.g. the first RSS feed setting stores its URL in the
+ // 'rssfeed_url_0' shared preferences field
+ if (key < 0) {
+ key = applicationSettings.getMaxRssfeed() + 1;
+ }
+ findPreference("rssfeed_name").setKey("rssfeed_name_" + key);
+ findPreference("rssfeed_url").setKey("rssfeed_url_" + key);
+ findPreference("rssfeed_reqauth").setKey("rssfeed_reqauth_" + key);
+
+ }
+
+}
diff --git a/lite/src/org/transdroid/lite/gui/settings/ServerPreference.java b/lite/src/org/transdroid/lite/gui/settings/ServerPreference.java
new file mode 100644
index 00000000..802873e3
--- /dev/null
+++ b/lite/src/org/transdroid/lite/gui/settings/ServerPreference.java
@@ -0,0 +1,59 @@
+package org.transdroid.lite.gui.settings;
+
+import org.transdroid.lite.app.settings.ServerSetting;
+
+import android.content.Context;
+import android.preference.Preference;
+
+/**
+ * Represents a {@link ServerSetting} in a preferences screen.
+ * @author Eric Kok
+ */
+public class ServerPreference extends Preference {
+
+ private static final int ORDER_START = 1;
+
+ private ServerSetting serverSetting;
+ private OnServerClickedListener onServerClickedListener = null;
+
+ public ServerPreference(Context context) {
+ super(context);
+ setOnPreferenceClickListener(onPreferenceClicked);
+ }
+
+ /**
+ * Set the server settings object that is bound to this preference item
+ * @param serverSetting The server settings
+ * @return Itself, for method chaining
+ */
+ public ServerPreference setServerSetting(ServerSetting serverSetting) {
+ this.serverSetting = serverSetting;
+ setTitle(serverSetting.getHumanReadableIdentifier());
+ setOrder(ORDER_START + serverSetting.getOrder());
+ return this;
+ }
+
+ /**
+ * Set a listener that will be notified of click events on this preference
+ * @param onServerClickedListener The click listener to register
+ * @return Itself, for method chaining
+ */
+ public ServerPreference setOnServerClickedListener(OnServerClickedListener onServerClickedListener) {
+ this.onServerClickedListener = onServerClickedListener;
+ return this;
+ }
+
+ private OnPreferenceClickListener onPreferenceClicked = new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ if (onServerClickedListener != null)
+ onServerClickedListener.onServerClicked(serverSetting);
+ return true;
+ }
+ };
+
+ public interface OnServerClickedListener {
+ public void onServerClicked(ServerSetting serverSetting);
+ }
+
+}
diff --git a/lite/src/org/transdroid/lite/gui/settings/ServerSettingsActivity.java b/lite/src/org/transdroid/lite/gui/settings/ServerSettingsActivity.java
new file mode 100644
index 00000000..148a8b56
--- /dev/null
+++ b/lite/src/org/transdroid/lite/gui/settings/ServerSettingsActivity.java
@@ -0,0 +1,94 @@
+package org.transdroid.lite.gui.settings;
+
+import org.androidannotations.annotations.Bean;
+import org.androidannotations.annotations.EActivity;
+import org.androidannotations.annotations.Extra;
+import org.transdroid.daemon.Daemon;
+import org.transdroid.core.R;
+import org.transdroid.lite.app.settings.ApplicationSettings;
+
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.PreferenceManager;
+
+import com.actionbarsherlock.app.SherlockPreferenceActivity;
+
+/**
+ * Activity that allows for a configuration of a server. The key can be supplied to update an existing server setting
+ * instead of creating a new one.
+ * @author Eric Kok
+ */
+@EActivity
+public class ServerSettingsActivity extends SherlockPreferenceActivity {
+
+ @Extra
+ protected int key = -1;
+
+ @Bean
+ protected ApplicationSettings applicationSettings;
+
+ @SuppressWarnings("deprecation")
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Load the raw preferences to show in this screen
+ addPreferencesFromResource(R.xml.pref_server);
+
+ // Bind the preferences to the correct storage key, e.g. the first server setting stores its address in the
+ // 'server_address_0' shared preferences field
+ if (key < 0) {
+ key = applicationSettings.getMaxWebsearch() + 1;
+ }
+ findPreference("server_name").setKey("server_name_" + key);
+ findPreference("server_type").setKey("server_type_" + key);
+ findPreference("server_address").setKey("server_address_" + key);
+ findPreference("server_port").setKey("server_port_" + key);
+ findPreference("server_user").setKey("server_user_" + key);
+ findPreference("server_pass").setKey("server_pass_" + key);
+ findPreference("server_extrapass").setKey("server_extrapass_" + key);
+ findPreference("server_localaddress").setKey("server_localaddress_" + key);
+ findPreference("server_localnetwork").setKey("server_localnetwork_" + key);
+ findPreference("server_folder").setKey("server_folder_" + key);
+ findPreference("server_timeout").setKey("server_timeout_" + key);
+ findPreference("server_alamrfinished").setKey("server_alamrfinished_" + key);
+ findPreference("server_alarnew").setKey("server_alarnew_" + key);
+ findPreference("server_os").setKey("server_os_" + key);
+ findPreference("server_downloaddir").setKey("server_downloaddir_" + key);
+ findPreference("server_ftpurl").setKey("server_ftpurl_" + key);
+ findPreference("server_ftppass").setKey("server_ftppass_" + key);
+ findPreference("server_sslenabled").setKey("server_sslenabled_" + key);
+ findPreference("server_ssltrustall").setKey("server_ssltrustall_" + key);
+ findPreference("server_ssltrustkey").setKey("server_ssltrustkey_" + key);
+
+ // Monitor preference changes
+ getPreferenceScreen().setOnPreferenceChangeListener(onPreferenceChangeListener);
+ }
+
+ private OnPreferenceChangeListener onPreferenceChangeListener = new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ updatePreferenceAvailability();
+ return true;
+ }
+ };
+
+ @SuppressWarnings("deprecation")
+ private void updatePreferenceAvailability() {
+
+ // Use daemon factory to see if the newly selected daemon supports the feature
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
+ Daemon daemonType = Daemon.fromCode(prefs.getString("server_type_" + key, null));
+ findPreference("server_extrapass_" + key).setEnabled(Daemon.supportsExtraPassword(daemonType));
+ findPreference("server_folder_" + key).setEnabled(daemonType == null? false: Daemon.supportsCustomFolder(daemonType));
+ findPreference("server_downloaddir_" + key).setEnabled(daemonType == null? false: Daemon.needsManualPathSpecified(daemonType));
+ //findPreference("server_ssltrustkey_" + key).setEnabled(sslValue && !sslTAValue);
+
+ // Adjust title texts accordingly
+ findPreference("server_folder_" + key).setTitle(daemonType == Daemon.rTorrent? R.string.pref_scgifolder: R.string.pref_folder);
+
+ }
+
+}
diff --git a/lite/src/org/transdroid/lite/gui/settings/WebsearchPreference.java b/lite/src/org/transdroid/lite/gui/settings/WebsearchPreference.java
new file mode 100644
index 00000000..929f66a9
--- /dev/null
+++ b/lite/src/org/transdroid/lite/gui/settings/WebsearchPreference.java
@@ -0,0 +1,59 @@
+package org.transdroid.lite.gui.settings;
+
+import org.transdroid.lite.app.settings.WebsearchSetting;
+
+import android.content.Context;
+import android.preference.Preference;
+
+/**
+ * Represents a {@link WebsearchSetting} in a preferences screen.
+ * @author Eric Kok
+ */
+public class WebsearchPreference extends Preference {
+
+ private static final int ORDER_START = 102;
+
+ private WebsearchSetting websearchSetting;
+ private OnWebsearchClickedListener onWebsearchClickedListener = null;
+
+ public WebsearchPreference(Context context) {
+ super(context);
+ setOnPreferenceClickListener(onPreferenceClicked);
+ }
+
+ /**
+ * Set the websearch settings object that is bound to this preference item
+ * @param websearchSetting The websearch settings
+ * @return Itself, for method chaining
+ */
+ public WebsearchPreference setWebsearchSetting(WebsearchSetting websearchSetting) {
+ this.websearchSetting = websearchSetting;
+ setTitle(websearchSetting.getName());
+ setOrder(ORDER_START + websearchSetting.getOrder());
+ return this;
+ }
+
+ /**
+ * Set a listener that will be notified of click events on this preference
+ * @param onWebsearchClickedListener The click listener to register
+ * @return Itself, for method chaining
+ */
+ public WebsearchPreference setOnWebsearchClickedListener(OnWebsearchClickedListener onWebsearchClickedListener) {
+ this.onWebsearchClickedListener = onWebsearchClickedListener;
+ return this;
+ }
+
+ private OnPreferenceClickListener onPreferenceClicked = new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ if (onWebsearchClickedListener != null)
+ onWebsearchClickedListener.onWebsearchClicked(websearchSetting);
+ return true;
+ }
+ };
+
+ public interface OnWebsearchClickedListener {
+ public void onWebsearchClicked(WebsearchSetting serverSetting);
+ }
+
+}
diff --git a/lite/src/org/transdroid/lite/gui/settings/WebsearchSettingsActivity.java b/lite/src/org/transdroid/lite/gui/settings/WebsearchSettingsActivity.java
new file mode 100644
index 00000000..d5daae2e
--- /dev/null
+++ b/lite/src/org/transdroid/lite/gui/settings/WebsearchSettingsActivity.java
@@ -0,0 +1,45 @@
+package org.transdroid.lite.gui.settings;
+
+import org.androidannotations.annotations.Bean;
+import org.androidannotations.annotations.EActivity;
+import org.androidannotations.annotations.Extra;
+import org.transdroid.core.R;
+import org.transdroid.lite.app.settings.ApplicationSettings;
+
+import android.os.Bundle;
+
+import com.actionbarsherlock.app.SherlockPreferenceActivity;
+
+/**
+ * Activity that allows for a configuration of a web search site. The key can be supplied to update an existing web
+ * search site setting instead of creating a new one.
+ * @author Eric Kok
+ */
+@EActivity
+public class WebsearchSettingsActivity extends SherlockPreferenceActivity {
+
+ @Extra
+ protected int key = -1;
+
+ @Bean
+ protected ApplicationSettings applicationSettings;
+
+ @SuppressWarnings("deprecation")
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ // Load the raw preferences to show in this screen
+ addPreferencesFromResource(R.xml.pref_websearch);
+
+ // Bind the preferences to the correct storage key, e.g. the first site setting stores its URL in the
+ // 'websearch_baseurl_0' shared preferences field
+ if (key < 0) {
+ key = applicationSettings.getMaxWebsearch() + 1;
+ }
+ findPreference("websearch_name").setKey("websearch_name_" + key);
+ findPreference("websearch_baseurl").setKey("websearch_baseurl_" + key);
+
+ }
+
+}