Browse Source

Working on task execution and navigation list.

pull/11/head
Eric Kok 12 years ago
parent
commit
d46bf03eeb
  1. 10
      android/res/values/changelog.xml
  2. 5
      lite/res/drawable/loading_progress.xml
  3. 2
      lite/res/layout/fragment_details.xml
  4. 7
      lite/res/layout/fragment_torrents.xml
  5. 22
      lite/res/layout/list_item_navigation.xml
  6. 11
      lite/res/menu/fragment_details.xml
  7. 10
      lite/res/values/strings.xml
  8. 143
      lite/src/org/transdroid/core/gui/DetailsActivity.java
  9. 74
      lite/src/org/transdroid/core/gui/DetailsFragment.java
  10. 16
      lite/src/org/transdroid/core/gui/TorrentTasksExecutor.java
  11. 211
      lite/src/org/transdroid/core/gui/TorrentsActivity.java
  12. 109
      lite/src/org/transdroid/core/gui/TorrentsFragment.java
  13. 9
      lite/src/org/transdroid/core/gui/lists/DetailsAdapter.java
  14. 1
      lite/src/org/transdroid/core/gui/lists/SimpleListItem.java
  15. 2
      lite/src/org/transdroid/core/gui/lists/SimpleListItemAdapter.java
  16. 10
      lite/src/org/transdroid/core/gui/lists/TorrentDetailsView.java
  17. 30
      lite/src/org/transdroid/core/gui/navigation/FilterListAdapter.java
  18. 35
      lite/src/org/transdroid/core/gui/navigation/Label.java
  19. 27
      lite/src/org/transdroid/core/gui/navigation/NavigationFilter.java
  20. 52
      lite/src/org/transdroid/core/gui/navigation/NavigationSelectionView.java
  21. 77
      lite/src/org/transdroid/core/gui/navigation/StatusType.java

10
android/res/values/changelog.xml

@ -1,6 +1,16 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="changes"> <string name="changes">
Transdroid 1.1.12\n
- Option to disable app update checking\n
- Transmission: support non-Western characters in directories\n
- Deluge: don\'t treat trackers errors as blocking\n
- Added Pirate Bay mirror search support\n
\n
Transdroid 1.1.11\n
- rTorrent: fix crash with creationtime and non-i8 dialect\n
- Fixed picking up local .torrent files\n
\n
Transdroid 1.1.10\n Transdroid 1.1.10\n
- Updated translations (thanks to all translators)\n - Updated translations (thanks to all translators)\n
- Special thanks Tom Briden for the following contributions:\n - Special thanks Tom Briden for the following contributions:\n

5
lite/res/drawable/loading_progress.xml

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/ic_empty_details"
android:pivotX="50%"
android:pivotY="50%" />

2
lite/res/layout/fragment_details.xml

@ -23,6 +23,6 @@
android:text="@string/navigation_emptydetails" android:text="@string/navigation_emptydetails"
android:gravity="center" android:gravity="center"
android:textIsSelectable="false" android:textIsSelectable="false"
android:visibility="gone" /> android:visibility="visible" />
</FrameLayout> </FrameLayout>

7
lite/res/layout/fragment_torrents.xml

@ -11,6 +11,13 @@
android:listSelector="@drawable/selectable_background_transdroid" android:listSelector="@drawable/selectable_background_transdroid"
android:visibility="gone" /> android:visibility="gone" />
<ProgressBar
android:id="@+id/loading_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:indeterminateDrawable="@drawable/loading_progress" />
<TextView <TextView
android:id="@+id/empty_text" android:id="@+id/empty_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"

22
lite/res/layout/list_item_navigation.xml

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingTop="4dip"
android:paddingBottom="4dip"
android:paddingLeft="@dimen/margin_default"
android:paddingRight="@dimen/margin_default" >
<TextView
android:id="@+id/filter_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textIsSelectable="false" />
<TextView
android:id="@+id/server_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textIsSelectable="false" />
</LinearLayout>

11
lite/res/menu/fragment_details.xml

@ -13,12 +13,17 @@
<item <item
android:id="@+id/action_start" android:id="@+id/action_start"
android:icon="@drawable/ic_action_start" android:icon="@drawable/ic_action_start"
android:showAsAction="always" android:showAsAction="ifRoom"
android:title="@string/action_start" /> android:title="@string/action_start">
<menu>
<item android:id="@+id/action_start_default" android:title="@string/action_start_default" />
<item android:id="@+id/action_start_forced" android:title="@string/action_start_forced" />
</menu>
</item>
<item <item
android:id="@+id/action_stop" android:id="@+id/action_stop"
android:icon="@drawable/ic_action_stop" android:icon="@drawable/ic_action_stop"
android:showAsAction="always" android:showAsAction="ifRoom"
android:title="@string/action_stop" /> android:title="@string/action_stop" />
<item <item
android:id="@+id/action_remove" android:id="@+id/action_remove"

10
lite/res/values/strings.xml

@ -23,6 +23,8 @@
<string name="action_settings">Settings</string> <string name="action_settings">Settings</string>
<string name="action_help">Help</string> <string name="action_help">Help</string>
<string name="action_start">Start</string> <string name="action_start">Start</string>
<string name="action_start_default">Normal start</string>
<string name="action_start_forced">Force start</string>
<string name="action_stop">Stop</string> <string name="action_stop">Stop</string>
<string name="action_resume">Resume</string> <string name="action_resume">Resume</string>
<string name="action_pause">Pause</string> <string name="action_pause">Pause</string>
@ -39,6 +41,9 @@
<string name="action_download">Download using (S)FTP</string> <string name="action_download">Download using (S)FTP</string>
<string name="action_removesettings">Remove settings</string> <string name="action_removesettings">Remove settings</string>
<string name="navigation_nosettings">Transdroid allows you to monitor and manage the torrent client you run at home or on your seedbox. Setting things up can be a bit tricky, but we offer step-by-step guides and promise it\'ll be worth it!</string>
<string name="navigation_emptytorrents">Connected, but no torrent are active within the current filter</string>
<string name="navigation_emptydetails">Select a torrent to view its details</string>
<string name="navigation_servers">SERVERS</string> <string name="navigation_servers">SERVERS</string>
<string name="navigation_status">STATUS</string> <string name="navigation_status">STATUS</string>
<string name="navigation_labels">LABELS</string> <string name="navigation_labels">LABELS</string>
@ -47,10 +52,8 @@
<string name="navigation_status_onlyup">Uploading</string> <string name="navigation_status_onlyup">Uploading</string>
<string name="navigation_status_onlyactive">Active</string> <string name="navigation_status_onlyactive">Active</string>
<string name="navigation_status_onlyinactive">Inactive</string> <string name="navigation_status_onlyinactive">Inactive</string>
<string name="navigation_emptytorrents">Connected, but no torrent are active within the current filter</string>
<string name="navigation_emptydetails">Select a torrent to view its details</string>
<string name="navigation_nosettings">Transdroid allows you to monitor and manage the torrent client you run at home or on your seedbox. Setting things up can be a bit tricky, but we offer step-by-step guides and promise it\'ll be worth it!</string>
<string name="status_status">Status: %1%s</string>
<string name="status_waiting">Waiting to check&#8230;</string> <string name="status_waiting">Waiting to check&#8230;</string>
<string name="status_checking">Verifying local data&#8230;</string> <string name="status_checking">Verifying local data&#8230;</string>
<string name="status_waitingtodl">Waiting to download %s</string> <string name="status_waitingtodl">Waiting to download %s</string>
@ -96,6 +99,7 @@
<string name="result_stopped_all">Torrents stopped</string> <string name="result_stopped_all">Torrents stopped</string>
<string name="result_started_all">Torrents started (refreshing)</string> <string name="result_started_all">Torrents started (refreshing)</string>
<string name="result_trackersupdated">Trackers updated</string> <string name="result_trackersupdated">Trackers updated</string>
<string name="result_labelset">Label set to \'%1$s\'</string>
<string name="result_locationset">Torrent moved to \'%1$s\'</string> <string name="result_locationset">Torrent moved to \'%1$s\'</string>
<string name="search_torrentsearch">Torrent search</string> <string name="search_torrentsearch">Torrent search</string>

143
lite/src/org/transdroid/core/gui/DetailsActivity.java

@ -24,12 +24,21 @@ import org.transdroid.daemon.TorrentDetails;
import org.transdroid.daemon.TorrentFile; import org.transdroid.daemon.TorrentFile;
import org.transdroid.daemon.task.DaemonTaskFailureResult; import org.transdroid.daemon.task.DaemonTaskFailureResult;
import org.transdroid.daemon.task.DaemonTaskResult; import org.transdroid.daemon.task.DaemonTaskResult;
import org.transdroid.daemon.task.DaemonTaskSuccessResult;
import org.transdroid.daemon.task.GetFileListTask; import org.transdroid.daemon.task.GetFileListTask;
import org.transdroid.daemon.task.GetFileListTaskSuccessResult; import org.transdroid.daemon.task.GetFileListTaskSuccessResult;
import org.transdroid.daemon.task.GetTorrentDetailsTask; import org.transdroid.daemon.task.GetTorrentDetailsTask;
import org.transdroid.daemon.task.GetTorrentDetailsTaskSuccessResult; import org.transdroid.daemon.task.GetTorrentDetailsTaskSuccessResult;
import org.transdroid.daemon.task.PauseTask;
import org.transdroid.daemon.task.RemoveTask;
import org.transdroid.daemon.task.ResumeTask;
import org.transdroid.daemon.task.RetrieveTask; import org.transdroid.daemon.task.RetrieveTask;
import org.transdroid.daemon.task.RetrieveTaskSuccessResult; import org.transdroid.daemon.task.RetrieveTaskSuccessResult;
import org.transdroid.daemon.task.SetDownloadLocationTask;
import org.transdroid.daemon.task.SetLabelTask;
import org.transdroid.daemon.task.SetTrackersTask;
import org.transdroid.daemon.task.StartTask;
import org.transdroid.daemon.task.StopTask;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.content.Intent; import android.content.Intent;
@ -40,7 +49,7 @@ import com.actionbarsherlock.app.SherlockFragmentActivity;
@EActivity(R.layout.activity_details) @EActivity(R.layout.activity_details)
@OptionsMenu(R.menu.activity_details) @OptionsMenu(R.menu.activity_details)
public class DetailsActivity extends SherlockFragmentActivity { public class DetailsActivity extends SherlockFragmentActivity implements TorrentTasksExecutor {
@Extra @Extra
@InstanceState @InstanceState
@ -102,12 +111,6 @@ public class DetailsActivity extends SherlockFragmentActivity {
} }
} }
@UiThread
protected void onTorrentsRetrieved(List<Torrent> torrents, List<org.transdroid.daemon.Label> labels) {
// Update the details fragment
fragmentDetails.perhapsUpdateTorrent(torrents);
}
@Background @Background
protected void refreshTorrentDetails() { protected void refreshTorrentDetails() {
if (!Daemon.supportsFineDetails(torrent.getDaemon())) if (!Daemon.supportsFineDetails(torrent.getDaemon()))
@ -120,12 +123,6 @@ public class DetailsActivity extends SherlockFragmentActivity {
} }
} }
@UiThread
protected void onTorrentDetailsRetrieved(TorrentDetails torrentDetails) {
// Update the details fragment with the new fine details for the shown torrent
fragmentDetails.updateTorrentDetails(torrentDetails);
}
@Background @Background
protected void refreshTorrentFiles() { protected void refreshTorrentFiles() {
if (!Daemon.supportsFileListing(torrent.getDaemon())) if (!Daemon.supportsFileListing(torrent.getDaemon()))
@ -138,12 +135,106 @@ public class DetailsActivity extends SherlockFragmentActivity {
} }
} }
@Background
@Override
public void resumeTorrent(Torrent torrent) {
torrent.mimicResume();
DaemonTaskResult result = ResumeTask.create(currentConnection, torrent).execute();
if (result instanceof DaemonTaskResult) {
onTaskSucceeded((DaemonTaskSuccessResult) result, R.string.result_resumed);
} else {
onCommunicationError((DaemonTaskFailureResult) result);
}
}
@Background
@Override
public void pauseTorrent(Torrent torrent) {
torrent.mimicPause();
DaemonTaskResult result = PauseTask.create(currentConnection, torrent).execute();
if (result instanceof DaemonTaskResult) {
onTaskSucceeded((DaemonTaskSuccessResult) result, R.string.result_paused);
} else {
onCommunicationError((DaemonTaskFailureResult) result);
}
}
@Background
@Override
public void startTorrent(Torrent torrent, boolean forced) {
torrent.mimicStart();
DaemonTaskResult result = StartTask.create(currentConnection, torrent, forced).execute();
if (result instanceof DaemonTaskResult) {
onTaskSucceeded((DaemonTaskSuccessResult) result, R.string.result_started);
} else {
onCommunicationError((DaemonTaskFailureResult) result);
}
}
@Background
@Override
public void stopTorrent(Torrent torrent) {
torrent.mimicStop();
DaemonTaskResult result = StopTask.create(currentConnection, torrent).execute();
if (result instanceof DaemonTaskResult) {
onTaskSucceeded((DaemonTaskSuccessResult) result, R.string.result_stopped);
} else {
onCommunicationError((DaemonTaskFailureResult) result);
}
}
@Background
@Override
public void removeTorrent(Torrent torrent, boolean withData) {
DaemonTaskResult result = RemoveTask.create(currentConnection, torrent, withData).execute();
if (result instanceof DaemonTaskResult) {
onTaskSucceeded((DaemonTaskSuccessResult) result, withData ? R.string.result_removed_with_data
: R.string.result_removed);
} else {
onCommunicationError((DaemonTaskFailureResult) result);
}
}
@Background
@Override
public void updateLabel(Torrent torrent, String newLabel) {
torrent.mimicNewLabel(newLabel);
DaemonTaskResult result = SetLabelTask.create(currentConnection, torrent, newLabel).execute();
if (result instanceof DaemonTaskResult) {
onTaskSucceeded((DaemonTaskSuccessResult) result, R.string.result_labelset, newLabel);
} else {
onCommunicationError((DaemonTaskFailureResult) result);
}
}
@Background
@Override
public void updateTrackers(Torrent torrent, List<String> newTrackers) {
DaemonTaskResult result = SetTrackersTask.create(currentConnection, torrent, newTrackers).execute();
if (result instanceof DaemonTaskResult) {
onTaskSucceeded((DaemonTaskSuccessResult) result, R.string.result_trackersupdated);
} else {
onCommunicationError((DaemonTaskFailureResult) result);
}
}
@Background
@Override
public void updateLocation(Torrent torrent, String newLocation) {
DaemonTaskResult result = SetDownloadLocationTask.create(currentConnection, torrent, newLocation).execute();
if (result instanceof DaemonTaskResult) {
onTaskSucceeded((DaemonTaskSuccessResult) result, R.string.result_locationset, newLocation);
} else {
onCommunicationError((DaemonTaskFailureResult) result);
}
}
@UiThread @UiThread
protected void onTorrentFilesRetrieved(List<TorrentFile> torrentFiles) { protected void onTaskSucceeded(DaemonTaskSuccessResult result, int successMessageId, String... messageParams) {
// Update the details fragment with the newly retrieved list of files // TODO: Properly report this success
fragmentDetails.updateTorrentFiles(new ArrayList<TorrentFile>(torrentFiles)); Toast.makeText(this, getString(successMessageId, (Object[]) messageParams), Toast.LENGTH_LONG).show();
} }
@UiThread @UiThread
protected void onCommunicationError(DaemonTaskFailureResult result) { protected void onCommunicationError(DaemonTaskFailureResult result) {
// TODO: Properly report this error // TODO: Properly report this error
@ -151,4 +242,22 @@ public class DetailsActivity extends SherlockFragmentActivity {
Toast.LENGTH_LONG).show(); Toast.LENGTH_LONG).show();
} }
@UiThread
protected void onTorrentsRetrieved(List<Torrent> torrents, List<org.transdroid.daemon.Label> labels) {
// Update the details fragment
fragmentDetails.perhapsUpdateTorrent(torrents);
}
@UiThread
protected void onTorrentDetailsRetrieved(TorrentDetails torrentDetails) {
// Update the details fragment with the new fine details for the shown torrent
fragmentDetails.updateTorrentDetails(torrentDetails);
}
@UiThread
protected void onTorrentFilesRetrieved(List<TorrentFile> torrentFiles) {
// Update the details fragment with the newly retrieved list of files
fragmentDetails.updateTorrentFiles(new ArrayList<TorrentFile>(torrentFiles));
}
} }

74
lite/src/org/transdroid/core/gui/DetailsFragment.java

@ -17,6 +17,7 @@ import org.transdroid.daemon.Torrent;
import org.transdroid.daemon.TorrentDetails; import org.transdroid.daemon.TorrentDetails;
import org.transdroid.daemon.TorrentFile; import org.transdroid.daemon.TorrentFile;
import android.view.View;
import android.widget.TextView; import android.widget.TextView;
import com.actionbarsherlock.app.SherlockFragment; import com.actionbarsherlock.app.SherlockFragment;
@ -50,7 +51,6 @@ public class DetailsFragment extends SherlockFragment {
protected void init() { protected void init() {
detailsList.setAdapter(new DetailsAdapter(getActivity())); detailsList.setAdapter(new DetailsAdapter(getActivity()));
detailsList.setEmptyView(emptyText);
if (torrent != null) if (torrent != null)
updateTorrent(torrent); updateTorrent(torrent);
if (torrentDetails != null) if (torrentDetails != null)
@ -68,6 +68,9 @@ public class DetailsFragment extends SherlockFragment {
clear(); clear();
this.torrent = newTorrent; this.torrent = newTorrent;
((DetailsAdapter) detailsList.getAdapter()).updateTorrent(newTorrent); ((DetailsAdapter) detailsList.getAdapter()).updateTorrent(newTorrent);
// Make the list (with detials header) visible
detailsList.setVisibility(View.VISIBLE);
emptyText.setVisibility(View.INVISIBLE);
// Also update the available actions in the action bar // Also update the available actions in the action bar
getActivity().supportInvalidateOptionsMenu(); getActivity().supportInvalidateOptionsMenu();
} }
@ -112,7 +115,9 @@ public class DetailsFragment extends SherlockFragment {
* Clear the screen by fully clearing the internal merge list (with header and other lists) * Clear the screen by fully clearing the internal merge list (with header and other lists)
*/ */
public void clear() { public void clear() {
((DetailsAdapter)detailsList.getAdapter()).clear(); detailsList.setAdapter(new DetailsAdapter(getActivity()));
detailsList.setVisibility(View.INVISIBLE);
emptyText.setVisibility(View.VISIBLE);
torrent = null; torrent = null;
torrentDetails = null; torrentDetails = null;
torrentFiles = null; torrentFiles = null;
@ -136,20 +141,59 @@ public class DetailsFragment extends SherlockFragment {
menu.findItem(R.id.action_updatetrackers).setVisible(setTrackers); menu.findItem(R.id.action_updatetrackers).setVisible(setTrackers);
} }
@OptionsItem(R.id.action_start) @OptionsItem(R.id.action_resume)
protected void startTorrent() { protected void resumeTorrent() {
getTasksExecutor().resumeTorrent(torrent);
} }
public interface DetailsTasksExecutor { @OptionsItem(R.id.action_pause)
void resumeTorrent(Torrent torrent); protected void pauseTorrent() {
void pauseTorrent(Torrent torrent); getTasksExecutor().pauseTorrent(torrent);
void startTorrent(Torrent torrent); }
void stopTorrent(Torrent torrent);
void removeTorrent(Torrent torrent, boolean withData); @OptionsItem(R.id.action_start_default)
void setLabel(Torrent torrent); protected void startTorrentDefault() {
void updateTrackers(Torrent torrent); getTasksExecutor().startTorrent(torrent, false);
}
@OptionsItem(R.id.action_start_forced)
protected void startTorrentForced() {
getTasksExecutor().startTorrent(torrent, true);
}
@OptionsItem(R.id.action_stop)
protected void stopTorrent() {
getTasksExecutor().stopTorrent(torrent);
}
@OptionsItem(R.id.action_remove_default)
protected void removeTorrentDefault() {
getTasksExecutor().removeTorrent(torrent, false);
}
@OptionsItem(R.id.action_remove_withdata)
protected void removeTorrentWithData() {
getTasksExecutor().removeTorrent(torrent, true);
}
@OptionsItem(R.id.action_setlabel)
protected void setLabel() {
// TODO: Show label selection dialog
}
@OptionsItem(R.id.action_updatetrackers)
protected void updateTrackers() {
// TODO: Show trackers edit dialog
}
/**
* Returns the object responsible for executing torrent tasks against a connected server
* @return The executor for tasks on some torrent
*/
private TorrentTasksExecutor getTasksExecutor() {
// NOTE: Assumes the activity implements all the required torrent tasks
return (TorrentTasksExecutor) getActivity();
} }
} }

16
lite/src/org/transdroid/core/gui/TorrentTasksExecutor.java

@ -0,0 +1,16 @@
package org.transdroid.core.gui;
import java.util.List;
import org.transdroid.daemon.Torrent;
public interface TorrentTasksExecutor {
void resumeTorrent(Torrent torrent);
void pauseTorrent(Torrent torrent);
void startTorrent(Torrent torrent, boolean forced);
void stopTorrent(Torrent torrent);
void removeTorrent(Torrent torrent, boolean withData);
void updateLabel(Torrent torrent, String newLabel);
void updateTrackers(Torrent torrent, List<String> newTrackers);
void updateLocation(Torrent torrent, String newLocation);
}

211
lite/src/org/transdroid/core/gui/TorrentsActivity.java

@ -17,16 +17,14 @@ import org.androidannotations.annotations.ViewById;
import org.transdroid.core.R; import org.transdroid.core.R;
import org.transdroid.core.app.settings.ApplicationSettings; import org.transdroid.core.app.settings.ApplicationSettings;
import org.transdroid.core.app.settings.ServerSetting; import org.transdroid.core.app.settings.ServerSetting;
import org.transdroid.core.gui.DetailsFragment.DetailsTasksExecutor;
import org.transdroid.core.gui.TorrentsFragment.TorrentsTasksExecutor;
import org.transdroid.core.gui.lists.LocalTorrent; import org.transdroid.core.gui.lists.LocalTorrent;
import org.transdroid.core.gui.lists.SimpleListItem; import org.transdroid.core.gui.lists.SimpleListItem;
import org.transdroid.core.gui.navigation.FilterListAdapter; import org.transdroid.core.gui.navigation.FilterListAdapter;
import org.transdroid.core.gui.navigation.FilterListAdapter_; import org.transdroid.core.gui.navigation.FilterListAdapter_;
import org.transdroid.core.gui.navigation.Label; import org.transdroid.core.gui.navigation.NavigationFilter;
import org.transdroid.core.gui.navigation.NavigationHelper; import org.transdroid.core.gui.navigation.NavigationHelper;
import org.transdroid.core.gui.navigation.NavigationSelectionView.NavigationFilterManager;
import org.transdroid.core.gui.navigation.StatusType; import org.transdroid.core.gui.navigation.StatusType;
import org.transdroid.core.gui.navigation.StatusType.StatusTypeFilter;
import org.transdroid.core.gui.settings.MainSettingsActivity_; import org.transdroid.core.gui.settings.MainSettingsActivity_;
import org.transdroid.daemon.Daemon; import org.transdroid.daemon.Daemon;
import org.transdroid.daemon.IDaemonAdapter; import org.transdroid.daemon.IDaemonAdapter;
@ -34,9 +32,19 @@ import org.transdroid.daemon.Torrent;
import org.transdroid.daemon.task.DaemonTaskFailureResult; import org.transdroid.daemon.task.DaemonTaskFailureResult;
import org.transdroid.daemon.task.DaemonTaskResult; import org.transdroid.daemon.task.DaemonTaskResult;
import org.transdroid.daemon.task.DaemonTaskSuccessResult; import org.transdroid.daemon.task.DaemonTaskSuccessResult;
import org.transdroid.daemon.task.GetStatsTask;
import org.transdroid.daemon.task.GetStatsTaskSuccessResult;
import org.transdroid.daemon.task.PauseTask;
import org.transdroid.daemon.task.RemoveTask;
import org.transdroid.daemon.task.ResumeTask; import org.transdroid.daemon.task.ResumeTask;
import org.transdroid.daemon.task.RetrieveTask; import org.transdroid.daemon.task.RetrieveTask;
import org.transdroid.daemon.task.RetrieveTaskSuccessResult; import org.transdroid.daemon.task.RetrieveTaskSuccessResult;
import org.transdroid.daemon.task.SetAlternativeModeTask;
import org.transdroid.daemon.task.SetDownloadLocationTask;
import org.transdroid.daemon.task.SetLabelTask;
import org.transdroid.daemon.task.SetTrackersTask;
import org.transdroid.daemon.task.StartTask;
import org.transdroid.daemon.task.StopTask;
import android.annotation.TargetApi; import android.annotation.TargetApi;
import android.app.SearchManager; import android.app.SearchManager;
@ -56,7 +64,7 @@ import com.actionbarsherlock.widget.SearchView;
@EActivity(R.layout.activity_torrents) @EActivity(R.layout.activity_torrents)
@OptionsMenu(R.menu.activity_torrents) @OptionsMenu(R.menu.activity_torrents)
public class TorrentsActivity extends SherlockFragmentActivity implements OnNavigationListener, DetailsTasksExecutor, TorrentsTasksExecutor { public class TorrentsActivity extends SherlockFragmentActivity implements OnNavigationListener, TorrentTasksExecutor, NavigationFilterManager {
// Navigation components // Navigation components
@Bean @Bean
@ -75,6 +83,8 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi
boolean firstStart = true; boolean firstStart = true;
private IDaemonAdapter currentConnection = null; private IDaemonAdapter currentConnection = null;
@InstanceState @InstanceState
protected NavigationFilter currentFilter = null;
@InstanceState
protected boolean turleModeEnabled = false; protected boolean turleModeEnabled = false;
// Torrents list components // Torrents list components
@ -91,7 +101,7 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi
// Set up navigation, with an action bar spinner and possibly (if room) with a filter list // Set up navigation, with an action bar spinner and possibly (if room) with a filter list
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
getSupportActionBar().setHomeButtonEnabled(false); getSupportActionBar().setHomeButtonEnabled(false);
navigationSpinnerAdapter = FilterListAdapter_.getInstance_(this); navigationSpinnerAdapter = FilterListAdapter_.getInstance_(this).setNavigationFilterManager(this);
// Servers are always added to the action bar spinner // Servers are always added to the action bar spinner
navigationSpinnerAdapter.updateServers(applicationSettings.getServerSettings()); navigationSpinnerAdapter.updateServers(applicationSettings.getServerSettings());
getSupportActionBar().setListNavigationCallbacks(navigationSpinnerAdapter, this); getSupportActionBar().setListNavigationCallbacks(navigationSpinnerAdapter, this);
@ -240,21 +250,35 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi
// Update connection to the newly selected server and refresh // Update connection to the newly selected server and refresh
currentConnection = server.createServerAdapter(); currentConnection = server.createServerAdapter();
applicationSettings.setLastUsedServer(server);
clearScreens(); clearScreens();
refreshTorrents(); refreshTorrents();
return;
} }
if (item instanceof StatusTypeFilter) { // Status type or label selection - both of which are navigation filters
// TODO: Update the torrent list view if (item instanceof NavigationFilter) {
} currentFilter = (NavigationFilter) item;
fragmentTorrents.applyFilter(currentFilter);
if (item instanceof Label) { // Clear the details view
// TODO: Update the torrent list view if (fragmentDetails != null) {
fragmentDetails.clear();
}
} }
} }
@Override
public String getActiveFilterText() {
return currentFilter.getName();
}
@Override
public String getActiveServerText() {
return currentConnection.getSettings().getName();
}
/** /**
* If required, add torrents, switch to a specific server, etc. * If required, add torrents, switch to a specific server, etc.
*/ */
@ -265,7 +289,17 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi
@OptionsItem(R.id.action_refresh) @OptionsItem(R.id.action_refresh)
protected void refreshScreen() { protected void refreshScreen() {
refreshTorrents(); refreshTorrents();
// TODO: Retrieve turtle mode status getAdditionalStats();
}
@OptionsItem(R.id.action_enableturtle)
protected void enableTurtleMode() {
updateTurtleMode(true);
}
@OptionsItem(R.id.action_disableturtle)
protected void disableTurtleMode() {
updateTurtleMode(false);
} }
@OptionsItem(R.id.action_settings) @OptionsItem(R.id.action_settings)
@ -291,28 +325,25 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi
} }
} }
@UiThread @Background
protected void onTorrentsRetrieved(List<Torrent> torrents, List<org.transdroid.daemon.Label> labels) { protected void getAdditionalStats() {
// Report the newly retrieved list of torrents to the torrents fragment DaemonTaskResult result = GetStatsTask.create(currentConnection).execute();
fragmentTorrents.updateTorrents(new ArrayList<Torrent>(torrents)); if (result instanceof GetStatsTaskSuccessResult) {
// Update the details fragment if the currently shown torrent is in the newly retrieved list onTurtleModeRetrieved(((GetStatsTaskSuccessResult) result).isAlternativeModeEnabled());
if (fragmentDetails != null) { } else {
fragmentDetails.perhapsUpdateTorrent(torrents); onCommunicationError((DaemonTaskFailureResult)result);
} }
// TODO: Update local list of labels
}
@UiThread
protected void onTaskSucceeded(DaemonTaskSuccessResult result, int successMessageId, Torrent target) {
// TODO: Properly report this success
Toast.makeText(this, getString(successMessageId, target.getName()),Toast.LENGTH_LONG).show();
} }
@UiThread @Background
protected void onCommunicationError(DaemonTaskFailureResult result) { protected void updateTurtleMode(boolean enable) {
// TODO: Properly report this error DaemonTaskResult result = SetAlternativeModeTask.create(currentConnection, enable).execute();
Toast.makeText(this, getString(LocalTorrent.getResourceForDaemonException(result.getException())), if (result instanceof GetStatsTaskSuccessResult) {
Toast.LENGTH_LONG).show(); // Success; no need to retrieve it again - just update the visual indicator
onTurtleModeRetrieved(enable);
} else {
onCommunicationError((DaemonTaskFailureResult)result);
}
} }
@Background @Background
@ -321,70 +352,122 @@ public class TorrentsActivity extends SherlockFragmentActivity implements OnNavi
torrent.mimicResume(); torrent.mimicResume();
DaemonTaskResult result = ResumeTask.create(currentConnection, torrent).execute(); DaemonTaskResult result = ResumeTask.create(currentConnection, torrent).execute();
if (result instanceof DaemonTaskResult) { if (result instanceof DaemonTaskResult) {
onTaskSucceeded((DaemonTaskSuccessResult) result, R.string.result_resumed, torrent); onTaskSucceeded((DaemonTaskSuccessResult) result, R.string.result_resumed);
} else { } else {
onCommunicationError((DaemonTaskFailureResult) result); onCommunicationError((DaemonTaskFailureResult) result);
} }
} }
@Background
@Override @Override
public void pauseTorrent(Torrent torrent) { public void pauseTorrent(Torrent torrent) {
// TODO Auto-generated method stub torrent.mimicPause();
DaemonTaskResult result = PauseTask.create(currentConnection, torrent).execute();
if (result instanceof DaemonTaskResult) {
onTaskSucceeded((DaemonTaskSuccessResult) result, R.string.result_paused);
} else {
onCommunicationError((DaemonTaskFailureResult) result);
}
} }
@Background
@Override @Override
public void startTorrent(Torrent torrent) { public void startTorrent(Torrent torrent, boolean forced) {
// TODO Auto-generated method stub torrent.mimicStart();
DaemonTaskResult result = StartTask.create(currentConnection, torrent, forced).execute();
if (result instanceof DaemonTaskResult) {
onTaskSucceeded((DaemonTaskSuccessResult) result, R.string.result_started);
} else {
onCommunicationError((DaemonTaskFailureResult) result);
}
} }
@Background
@Override @Override
public void stopTorrent(Torrent torrent) { public void stopTorrent(Torrent torrent) {
// TODO Auto-generated method stub torrent.mimicStop();
DaemonTaskResult result = StopTask.create(currentConnection, torrent).execute();
if (result instanceof DaemonTaskResult) {
onTaskSucceeded((DaemonTaskSuccessResult) result, R.string.result_stopped);
} else {
onCommunicationError((DaemonTaskFailureResult) result);
}
} }
@Background
@Override @Override
public void removeTorrent(Torrent torrent, boolean withData) { public void removeTorrent(Torrent torrent, boolean withData) {
// TODO Auto-generated method stub DaemonTaskResult result = RemoveTask.create(currentConnection, torrent, withData).execute();
if (result instanceof DaemonTaskResult) {
onTaskSucceeded((DaemonTaskSuccessResult) result, withData ? R.string.result_removed_with_data
: R.string.result_removed);
} else {
onCommunicationError((DaemonTaskFailureResult) result);
}
} }
@Background
@Override @Override
public void setLabel(Torrent torrent) { public void updateLabel(Torrent torrent, String newLabel) {
// TODO Auto-generated method stub torrent.mimicNewLabel(newLabel);
DaemonTaskResult result = SetLabelTask.create(currentConnection, torrent, newLabel).execute();
if (result instanceof DaemonTaskResult) {
onTaskSucceeded((DaemonTaskSuccessResult) result, R.string.result_labelset, newLabel);
} else {
onCommunicationError((DaemonTaskFailureResult) result);
}
} }
@Background
@Override @Override
public void updateTrackers(Torrent torrent) { public void updateTrackers(Torrent torrent, List<String> newTrackers) {
// TODO Auto-generated method stub DaemonTaskResult result = SetTrackersTask.create(currentConnection, torrent, newTrackers).execute();
if (result instanceof DaemonTaskResult) {
onTaskSucceeded((DaemonTaskSuccessResult) result, R.string.result_trackersupdated);
} else {
onCommunicationError((DaemonTaskFailureResult) result);
}
} }
@Background
@Override @Override
public void resumeTorrents(List<Torrent> torrents) { public void updateLocation(Torrent torrent, String newLocation) {
// TODO Auto-generated method stub DaemonTaskResult result = SetDownloadLocationTask.create(currentConnection, torrent, newLocation).execute();
if (result instanceof DaemonTaskResult) {
onTaskSucceeded((DaemonTaskSuccessResult) result, R.string.result_locationset, newLocation);
} else {
onCommunicationError((DaemonTaskFailureResult) result);
}
} }
@Override @UiThread
public void pauseTorrents(List<Torrent> torrents) { protected void onTaskSucceeded(DaemonTaskSuccessResult result, int successMessageId, String... messageParams) {
// TODO Auto-generated method stub // TODO: Properly report this success
Toast.makeText(this, getString(successMessageId, (Object[]) messageParams), Toast.LENGTH_LONG).show();
} }
@Override @UiThread
public void removeTorrents(List<Torrent> torrents, boolean withData) { protected void onCommunicationError(DaemonTaskFailureResult result) {
// TODO Auto-generated method stub // TODO: Properly report this error
Toast.makeText(this, getString(LocalTorrent.getResourceForDaemonException(result.getException())),
Toast.LENGTH_LONG).show();
} }
@Override @UiThread
public void setLabels(List<Torrent> torrents) { protected void onTorrentsRetrieved(List<Torrent> torrents, List<org.transdroid.daemon.Label> labels) {
// TODO Auto-generated method stub // Report the newly retrieved list of torrents to the torrents fragment
fragmentTorrents.updateTorrents(new ArrayList<Torrent>(torrents));
// Update the details fragment if the currently shown torrent is in the newly retrieved list
if (fragmentDetails != null) {
fragmentDetails.perhapsUpdateTorrent(torrents);
}
// TODO: Update local list of labels
}
@UiThread
protected void onTurtleModeRetrieved(boolean turtleModeEnabled) {
turleModeEnabled = turtleModeEnabled;
supportInvalidateOptionsMenu();
} }
} }

109
lite/src/org/transdroid/core/gui/TorrentsFragment.java

@ -4,7 +4,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.AfterViews;
import org.androidannotations.annotations.Background;
import org.androidannotations.annotations.EFragment; import org.androidannotations.annotations.EFragment;
import org.androidannotations.annotations.InstanceState; import org.androidannotations.annotations.InstanceState;
import org.androidannotations.annotations.ItemClick; import org.androidannotations.annotations.ItemClick;
@ -12,9 +11,12 @@ import org.androidannotations.annotations.ViewById;
import org.transdroid.core.R; import org.transdroid.core.R;
import org.transdroid.core.gui.lists.TorrentsAdapter; import org.transdroid.core.gui.lists.TorrentsAdapter;
import org.transdroid.core.gui.lists.TorrentsAdapter_; import org.transdroid.core.gui.lists.TorrentsAdapter_;
import org.transdroid.core.gui.navigation.NavigationFilter;
import org.transdroid.core.gui.navigation.StatusType;
import org.transdroid.daemon.Torrent; import org.transdroid.daemon.Torrent;
import android.view.View; import android.view.View;
import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import com.actionbarsherlock.app.SherlockFragment; import com.actionbarsherlock.app.SherlockFragment;
@ -30,6 +32,12 @@ public class TorrentsFragment extends SherlockFragment {
// Local data // Local data
@InstanceState @InstanceState
protected ArrayList<Torrent> torrents = null; protected ArrayList<Torrent> torrents = null;
@InstanceState
protected NavigationFilter currentFilter = null;
@InstanceState
protected boolean hasAConnection = false;
@InstanceState
protected boolean isLoading = false;
// Views // Views
@ViewById(R.id.torrent_list) @ViewById(R.id.torrent_list)
@ -38,11 +46,12 @@ public class TorrentsFragment extends SherlockFragment {
protected TextView emptyText; protected TextView emptyText;
@ViewById @ViewById
protected TextView nosettingsText; protected TextView nosettingsText;
@ViewById
protected ProgressBar loadingProgress;
@AfterViews @AfterViews
protected void init() { protected void init() {
torrentsList.setAdapter(TorrentsAdapter_.getInstance_(getActivity())); torrentsList.setAdapter(TorrentsAdapter_.getInstance_(getActivity()));
torrentsList.setEmptyView(emptyText);
torrentsList.setMultiChoiceModeListener(onTorrentsSelected); torrentsList.setMultiChoiceModeListener(onTorrentsSelected);
if (torrents != null) if (torrents != null)
updateTorrents(torrents); updateTorrents(torrents);
@ -54,14 +63,7 @@ public class TorrentsFragment extends SherlockFragment {
*/ */
public void updateTorrents(ArrayList<Torrent> newTorrents) { public void updateTorrents(ArrayList<Torrent> newTorrents) {
torrents = newTorrents; torrents = newTorrents;
if (newTorrents == null) { applyFilter(null); // Resets the filter and shown list of torrents
// Hide list adapter as well as empty text
torrentsList.setVisibility(View.GONE);
emptyText.setVisibility(View.GONE);
} else {
((TorrentsAdapter) torrentsList.getAdapter()).update(newTorrents);
// NOTE: This will also make visible again the list or empty view
}
} }
/** /**
@ -71,6 +73,26 @@ public class TorrentsFragment extends SherlockFragment {
updateTorrents(null); updateTorrents(null);
} }
/**
* Apply a filter on the current list of all torrents, showing the appropriate sublist of torrents only
* @param currentFilter
*/
public void applyFilter(NavigationFilter currentFilter) {
this.currentFilter = currentFilter;
if (this.currentFilter == null)
this.currentFilter = StatusType.getShowAllType(getActivity());
if (torrents != null) {
// Build a local list of torrents that match the selected navigation filter
ArrayList<Torrent> filteredTorrents = new ArrayList<Torrent>();
for (Torrent torrent : torrents) {
if (currentFilter.matches(torrent))
filteredTorrents.add(torrent);
}
((TorrentsAdapter) torrentsList.getAdapter()).update(filteredTorrents);
}
updateViewVisibility();
}
private MultiChoiceModeListenerCompat onTorrentsSelected = new MultiChoiceModeListenerCompat() { private MultiChoiceModeListenerCompat onTorrentsSelected = new MultiChoiceModeListenerCompat() {
@Override @Override
@ -91,10 +113,33 @@ public class TorrentsFragment extends SherlockFragment {
} }
// Execute the requested action // Execute the requested action
// TODO: Add the other actions
switch (item.getItemId()) { switch (item.getItemId()) {
case R.id.action_start: case R.id.action_resume:
startTorrents(checked); for (Torrent torrent : checked) {
getTasksExecutor().resumeTorrent(torrent);
}
mode.finish();
return true;
case R.id.action_pause:
for (Torrent torrent : checked) {
getTasksExecutor().pauseTorrent(torrent);
}
mode.finish();
return true;
case R.id.action_remove_default:
for (Torrent torrent : checked) {
getTasksExecutor().removeTorrent(torrent, false);
}
mode.finish();
return true;
case R.id.action_remove_withdata:
for (Torrent torrent : checked) {
getTasksExecutor().removeTorrent(torrent, true);
}
mode.finish();
return true;
case R.id.action_setlabel:
// TODO: Open label selection dialogue
mode.finish(); mode.finish();
return true; return true;
default: default:
@ -126,31 +171,37 @@ public class TorrentsFragment extends SherlockFragment {
/** /**
* Updates the shown screen depending on whether we have a connection (so torrents can be shown) or not (in case we * Updates the shown screen depending on whether we have a connection (so torrents can be shown) or not (in case we
* need to show a message suggesting help) * need to show a message suggesting help)
* @param hasAConnection True if the user has servers configured and therefor has a conenction that can be used * @param hasAConnection True if the user has servers configured and therefore has a connection that can be used
*/ */
public void updateConnectionStatus(boolean hasAConnection) { public void updateConnectionStatus(boolean hasAConnection) {
if (!hasAConnection) { this.hasAConnection = hasAConnection;
if (!hasAConnection)
clear(); clear();
updateViewVisibility();
}
private void updateViewVisibility() {
if (!hasAConnection) {
torrentsList.setVisibility(View.GONE); torrentsList.setVisibility(View.GONE);
emptyText.setVisibility(View.GONE); emptyText.setVisibility(View.GONE);
loadingProgress.setVisibility(View.GONE);
nosettingsText.setVisibility(View.VISIBLE); nosettingsText.setVisibility(View.VISIBLE);
} else { return;
nosettingsText.setVisibility(View.GONE);
torrentsList.setVisibility(torrentsList.getAdapter().isEmpty()? View.GONE: View.VISIBLE);
emptyText.setVisibility(torrentsList.getAdapter().isEmpty()? View.VISIBLE: View.GONE);
} }
boolean isEmpty = torrents == null || torrentsList.getAdapter().isEmpty();
nosettingsText.setVisibility(View.GONE);
torrentsList.setVisibility(!isLoading && !isEmpty? View.GONE: View.VISIBLE);
loadingProgress.setVisibility(isLoading? View.VISIBLE: View.GONE);
emptyText.setVisibility(!isLoading && isEmpty? View.VISIBLE: View.GONE);
} }
@Background /**
protected void startTorrents(List<Torrent> torrents) { * Returns the object responsible for executing torrent tasks against a connected server
// TODO: Implement action * @return The executor for tasks on some torrent
*/
private TorrentTasksExecutor getTasksExecutor() {
// NOTE: Assumes the activity implements all the required torrent tasks
return (TorrentTasksExecutor) getActivity();
} }
public interface TorrentsTasksExecutor {
void resumeTorrents(List<Torrent> torrents);
void pauseTorrents(List<Torrent> torrents);
void removeTorrents(List<Torrent> torrents, boolean withData);
void setLabels(List<Torrent> torrents);
}
} }

9
lite/src/org/transdroid/core/gui/lists/DetailsAdapter.java

@ -113,15 +113,6 @@ public class DetailsAdapter extends MergeAdapter {
} }
} }
/**
* The details adapter is empty if it is not showing any torrent (regardless of errors, trackers and files)
*/
@Override
public boolean isEmpty() {
//return torrentDetailsView.isBound();
return false;
}
/** /**
* Clear currently visible torrent, including header and shown lists * Clear currently visible torrent, including header and shown lists
*/ */

1
lite/src/org/transdroid/core/gui/lists/SimpleListItem.java

@ -1,5 +1,6 @@
package org.transdroid.core.gui.lists; package org.transdroid.core.gui.lists;
/** /**
* Represents a filter item as shown in the navigation list or spinner. * Represents a filter item as shown in the navigation list or spinner.
* *

2
lite/src/org/transdroid/core/gui/lists/SimpleListItemAdapter.java

@ -45,7 +45,7 @@ public class SimpleListItemAdapter extends BaseAdapter {
@Override @Override
public View getView(int position, View convertView, ViewGroup parent) { public View getView(int position, View convertView, ViewGroup parent) {
SimpleListItemView filterItemView; SimpleListItemView filterItemView;
if (convertView == null) { if (convertView == null || !(convertView instanceof SimpleListItemView)) {
filterItemView = SimpleListItemView_.build(context); filterItemView = SimpleListItemView_.build(context);
} else { } else {
filterItemView = (SimpleListItemView) convertView; filterItemView = (SimpleListItemView) convertView;

10
lite/src/org/transdroid/core/gui/lists/TorrentDetailsView.java

@ -21,8 +21,6 @@ import android.widget.TextView;
@EViewGroup(R.layout.fragment_details_header) @EViewGroup(R.layout.fragment_details_header)
public class TorrentDetailsView extends RelativeLayout { public class TorrentDetailsView extends RelativeLayout {
private boolean isShowingData = false;
@ViewById @ViewById
protected TextView labelText, dateaddedText, uploadedText, uploadedunitText, ratioText, upspeedText, seedersText, protected TextView labelText, dateaddedText, uploadedText, uploadedunitText, ratioText, upspeedText, seedersText,
downloadedunitText, downloadedText, totalsizeText, downspeedText, leechersText, statusText; downloadedunitText, downloadedText, totalsizeText, downspeedText, leechersText, statusText;
@ -38,11 +36,9 @@ public class TorrentDetailsView extends RelativeLayout {
public void update(Torrent torrent) { public void update(Torrent torrent) {
if (torrent == null) { if (torrent == null) {
isShowingData = false;
return; return;
} }
isShowingData = true;
LocalTorrent local = LocalTorrent.fromTorrent(torrent); LocalTorrent local = LocalTorrent.fromTorrent(torrent);
// Set label text // Set label text
@ -67,7 +63,7 @@ public class TorrentDetailsView extends RelativeLayout {
} else { } else {
dateaddedText.setVisibility(View.INVISIBLE); dateaddedText.setVisibility(View.INVISIBLE);
} }
statusText.setText(local.getProgressStatusEta(getResources())); statusText.setText(getResources().getString(R.string.status_status, local.getProgressStatusEta(getResources())));
ratioText.setText(getResources().getString(R.string.status_ratio, local.getRatioString())); ratioText.setText(getResources().getString(R.string.status_ratio, local.getRatioString()));
// TODO: Implement separate numbers of seeders and leechers // TODO: Implement separate numbers of seeders and leechers
seedersText.setText(getResources().getString(R.string.status_peers, torrent.getPeersSendingToUs(), seedersText.setText(getResources().getString(R.string.status_peers, torrent.getPeersSendingToUs(),
@ -90,8 +86,4 @@ public class TorrentDetailsView extends RelativeLayout {
} }
public boolean isBound() {
return isShowingData ;
}
} }

30
lite/src/org/transdroid/core/gui/navigation/FilterListAdapter.java

@ -7,9 +7,12 @@ import org.androidannotations.annotations.RootContext;
import org.transdroid.core.R; import org.transdroid.core.R;
import org.transdroid.core.gui.lists.SimpleListItem; import org.transdroid.core.gui.lists.SimpleListItem;
import org.transdroid.core.gui.lists.SimpleListItemAdapter; import org.transdroid.core.gui.lists.SimpleListItemAdapter;
import org.transdroid.core.gui.navigation.FilterSeparatorView_; import org.transdroid.core.gui.navigation.NavigationSelectionView.NavigationFilterManager;
import android.content.Context; import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SpinnerAdapter;
import com.commonsware.cwac.merge.MergeAdapter; import com.commonsware.cwac.merge.MergeAdapter;
@ -19,14 +22,25 @@ import com.commonsware.cwac.merge.MergeAdapter;
* @author Eric Kok * @author Eric Kok
*/ */
@EBean @EBean
public class FilterListAdapter extends MergeAdapter { public class FilterListAdapter extends MergeAdapter implements SpinnerAdapter {
@RootContext @RootContext
protected Context context; protected Context context;
private SimpleListItemAdapter serverItems = null; private SimpleListItemAdapter serverItems = null;
private SimpleListItemAdapter statusTypeItems = null; private SimpleListItemAdapter statusTypeItems = null;
private SimpleListItemAdapter labelItems = null; private SimpleListItemAdapter labelItems = null;
private NavigationFilterManager navigationFilterManager;
/**
* Stores which screen, or manager, handles navigation selection and display
* @param manager The navigation manager, which knows about the currently selected filter and server
* @return Itself, for method chaining
*/
public FilterListAdapter setNavigationFilterManager(NavigationFilterManager manager) {
this.navigationFilterManager = manager;
return this;
}
/** /**
* Update the list of available servers * Update the list of available servers
* @param servers The new list of available servers * @param servers The new list of available servers
@ -75,4 +89,16 @@ public class FilterListAdapter extends MergeAdapter {
} }
} }
@Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
NavigationSelectionView filterItemView;
if (convertView == null || !(convertView instanceof NavigationSelectionView)) {
filterItemView = NavigationSelectionView_.build(context).setNavigationFilterManager(navigationFilterManager);
} else {
filterItemView = (NavigationSelectionView) convertView;
}
filterItemView.bind();
return filterItemView;
}
} }

35
lite/src/org/transdroid/core/gui/navigation/Label.java

@ -1,12 +1,16 @@
package org.transdroid.core.gui.navigation; package org.transdroid.core.gui.navigation;
import org.transdroid.core.gui.lists.SimpleListItem; import org.transdroid.core.gui.lists.SimpleListItem;
import org.transdroid.daemon.Torrent;
import android.os.Parcel;
import android.os.Parcelable;
/** /**
* Represents some label that is active or available on the server. * Represents some label that is active or available on the server.
* @author Eric Kok * @author Eric Kok
*/ */
public class Label implements SimpleListItem { public class Label implements SimpleListItem, NavigationFilter {
private final String name; private final String name;
@ -19,4 +23,33 @@ public class Label implements SimpleListItem {
return this.name; return this.name;
} }
@Override
public boolean matches(Torrent torrent) {
return torrent.getLabelName() != null && torrent.getLabelName().equals(name);
}
private Label(Parcel in) {
this.name = in.readString();
}
public static final Parcelable.Creator<Label> CREATOR = new Parcelable.Creator<Label>() {
public Label createFromParcel(Parcel in) {
return new Label(in);
}
public Label[] newArray(int size) {
return new Label[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
}
} }

27
lite/src/org/transdroid/core/gui/navigation/NavigationFilter.java

@ -0,0 +1,27 @@
package org.transdroid.core.gui.navigation;
import org.transdroid.daemon.Torrent;
import android.os.Parcelable;
/**
* Represents a filter, used in the app navigation, that can check if some torrent matches the user-set filter
* @author Eric Kok
*/
public interface NavigationFilter extends Parcelable {
/**
* Implementations should check if the supplied torrent matches the filter; for example a label filter should return
* true if the torrent's label equals this items label name.
* @param torrent The torrent to check for matches
* @return True if the torrent matches the filter and should be shown in the current screen, false otherwise
*/
boolean matches(Torrent torrent);
/**
* Implementations should return a name that can be shown to indicate the active filter
* @return The name of the filter item as string
*/
String getName();
}

52
lite/src/org/transdroid/core/gui/navigation/NavigationSelectionView.java

@ -0,0 +1,52 @@
package org.transdroid.core.gui.navigation;
import org.androidannotations.annotations.EViewGroup;
import org.androidannotations.annotations.ViewById;
import org.transdroid.core.R;
import android.content.Context;
import android.widget.LinearLayout;
import android.widget.TextView;
/**
* View that displays the user-selected server and display filter inside the action bar list navigation spinner
* @author Eric Kok
*/
@EViewGroup(R.layout.list_item_navigation)
public class NavigationSelectionView extends LinearLayout {
@ViewById
protected TextView filterText;
@ViewById
protected TextView serverText;
private NavigationFilterManager navigationFilterManager;
public NavigationSelectionView(Context context) {
super(context);
}
/**
* Stores which screen, or manager, handles navigation selection and display
* @param manager The navigation manager, which knows about the currently selected filter and server
* @return Itself, for method chaining
*/
public NavigationSelectionView setNavigationFilterManager(NavigationFilterManager manager) {
this.navigationFilterManager = manager;
return this;
}
public void bind() {
filterText.setText(navigationFilterManager.getActiveFilterText());
serverText.setText(navigationFilterManager.getActiveServerText());
}
/**
* Interface that the manager of navigation (selecting servers and filters) should implement
*/
public interface NavigationFilterManager {
String getActiveFilterText();
String getActiveServerText();
}
}

77
lite/src/org/transdroid/core/gui/navigation/StatusType.java

@ -5,8 +5,12 @@ import java.util.List;
import org.transdroid.core.R; import org.transdroid.core.R;
import org.transdroid.core.gui.lists.SimpleListItem; import org.transdroid.core.gui.lists.SimpleListItem;
import org.transdroid.daemon.Torrent;
import org.transdroid.daemon.TorrentStatus;
import android.content.Context; import android.content.Context;
import android.os.Parcel;
import android.os.Parcelable;
/** /**
* Enumeration of all status types, which filter the list of shown torrents based on transfer activity. * Enumeration of all status types, which filter the list of shown torrents based on transfer activity.
@ -16,30 +20,39 @@ public enum StatusType {
ShowAll { ShowAll {
StatusTypeFilter getFilterItem(Context context) { StatusTypeFilter getFilterItem(Context context) {
return new StatusTypeFilter(context.getString(R.string.navigation_status_showall)); return new StatusTypeFilter(StatusType.ShowAll, context.getString(R.string.navigation_status_showall));
} }
}, },
OnlyDownloading { OnlyDownloading {
StatusTypeFilter getFilterItem(Context context) { StatusTypeFilter getFilterItem(Context context) {
return new StatusTypeFilter(context.getString(R.string.navigation_status_onlydown)); return new StatusTypeFilter(StatusType.OnlyDownloading, context.getString(R.string.navigation_status_onlydown));
} }
}, },
OnlyUploading { OnlyUploading {
StatusTypeFilter getFilterItem(Context context) { StatusTypeFilter getFilterItem(Context context) {
return new StatusTypeFilter(context.getString(R.string.navigation_status_onlyup)); return new StatusTypeFilter(StatusType.OnlyUploading, context.getString(R.string.navigation_status_onlyup));
} }
}, },
OnlyActive { OnlyActive {
StatusTypeFilter getFilterItem(Context context) { StatusTypeFilter getFilterItem(Context context) {
return new StatusTypeFilter(context.getString(R.string.navigation_status_onlyactive)); return new StatusTypeFilter(StatusType.OnlyActive, context.getString(R.string.navigation_status_onlyactive));
} }
}, },
OnlyInactive { OnlyInactive {
StatusTypeFilter getFilterItem(Context context) { StatusTypeFilter getFilterItem(Context context) {
return new StatusTypeFilter(context.getString(R.string.navigation_status_onlyinactive)); return new StatusTypeFilter(StatusType.OnlyInactive, context.getString(R.string.navigation_status_onlyinactive));
} }
}; };
/**
* Returns the status type to show all torrents, represented as filter item to show in the navigation list.
* @param context The Android UI context, to access translations
* @return The show ShowAll status type filter item
*/
public static StatusTypeFilter getShowAllType(Context context) {
return ShowAll.getFilterItem(context);
}
/** /**
* Returns a list with all status types, represented as filter item that can be shown in the GUI. * 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 * @param context The Android UI context, to access translations
@ -58,11 +71,13 @@ public enum StatusType {
*/ */
abstract StatusTypeFilter getFilterItem(Context context); abstract StatusTypeFilter getFilterItem(Context context);
public static class StatusTypeFilter implements SimpleListItem { public static class StatusTypeFilter implements SimpleListItem, NavigationFilter {
private final StatusType statusType;
private final String name; private final String name;
StatusTypeFilter(String name) { StatusTypeFilter(StatusType statusType, String name) {
this.statusType = statusType;
this.name = name; this.name = name;
} }
@ -71,6 +86,54 @@ public enum StatusType {
return name; return name;
} }
@Override
public boolean matches(Torrent torrent) {
switch (statusType) {
case OnlyDownloading:
return torrent.getStatusCode() == TorrentStatus.Downloading;
case OnlyUploading:
return torrent.getStatusCode() == TorrentStatus.Seeding;
case OnlyActive:
return torrent.getStatusCode() == TorrentStatus.Downloading
|| torrent.getStatusCode() == TorrentStatus.Seeding;
case OnlyInactive:
return torrent.getStatusCode() == TorrentStatus.Checking
|| torrent.getStatusCode() == TorrentStatus.Error
|| torrent.getStatusCode() == TorrentStatus.Paused
|| torrent.getStatusCode() == TorrentStatus.Queued
|| torrent.getStatusCode() == TorrentStatus.Unknown
|| torrent.getStatusCode() == TorrentStatus.Waiting;
default:
return true;
}
}
private StatusTypeFilter(Parcel in) {
this.statusType = StatusType.valueOf(in.readString());
this.name = in.readString();
}
public static final Parcelable.Creator<StatusTypeFilter> CREATOR = new Parcelable.Creator<StatusTypeFilter>() {
public StatusTypeFilter createFromParcel(Parcel in) {
return new StatusTypeFilter(in);
}
public StatusTypeFilter[] newArray(int size) {
return new StatusTypeFilter[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(statusType.name());
dest.writeString(name);
}
} }
} }

Loading…
Cancel
Save