You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
448 lines
16 KiB
448 lines
16 KiB
11 years ago
|
/*
|
||
|
* Copyright 2010-2013 Eric Kok et al.
|
||
|
*
|
||
|
* Transdroid is free software: you can redistribute it and/or modify
|
||
|
* it under the terms of the GNU General Public License as published by
|
||
|
* the Free Software Foundation, either version 3 of the License, or
|
||
|
* (at your option) any later version.
|
||
|
*
|
||
|
* Transdroid is distributed in the hope that it will be useful,
|
||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
* GNU General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with Transdroid. If not, see <http://www.gnu.org/licenses/>.
|
||
|
*/
|
||
11 years ago
|
package org.transdroid.core.gui;
|
||
|
|
||
|
import java.util.ArrayList;
|
||
11 years ago
|
import java.util.Collections;
|
||
11 years ago
|
import java.util.Iterator;
|
||
|
import java.util.Locale;
|
||
11 years ago
|
|
||
|
import org.androidannotations.annotations.AfterViews;
|
||
11 years ago
|
import org.androidannotations.annotations.Bean;
|
||
11 years ago
|
import org.androidannotations.annotations.Click;
|
||
11 years ago
|
import org.androidannotations.annotations.EFragment;
|
||
|
import org.androidannotations.annotations.InstanceState;
|
||
|
import org.androidannotations.annotations.ItemClick;
|
||
|
import org.androidannotations.annotations.ViewById;
|
||
10 years ago
|
import org.transdroid.R;
|
||
11 years ago
|
import org.transdroid.core.app.settings.ApplicationSettings;
|
||
11 years ago
|
import org.transdroid.core.app.settings.SystemSettings;
|
||
11 years ago
|
import org.transdroid.core.gui.lists.TorrentsAdapter;
|
||
|
import org.transdroid.core.gui.lists.TorrentsAdapter_;
|
||
11 years ago
|
import org.transdroid.core.gui.navigation.Label;
|
||
11 years ago
|
import org.transdroid.core.gui.navigation.NavigationFilter;
|
||
11 years ago
|
import org.transdroid.core.gui.navigation.RefreshableActivity;
|
||
11 years ago
|
import org.transdroid.core.gui.navigation.SelectionManagerMode;
|
||
11 years ago
|
import org.transdroid.core.gui.navigation.SetLabelDialog;
|
||
|
import org.transdroid.core.gui.navigation.SetLabelDialog.OnLabelPickedListener;
|
||
11 years ago
|
import org.transdroid.daemon.Daemon;
|
||
11 years ago
|
import org.transdroid.daemon.Torrent;
|
||
11 years ago
|
import org.transdroid.daemon.TorrentsComparator;
|
||
|
import org.transdroid.daemon.TorrentsSortBy;
|
||
11 years ago
|
|
||
10 years ago
|
import android.app.Fragment;
|
||
|
import android.view.ActionMode;
|
||
|
import android.view.Menu;
|
||
|
import android.view.MenuItem;
|
||
11 years ago
|
import android.view.View;
|
||
10 years ago
|
import android.widget.AbsListView.MultiChoiceModeListener;
|
||
|
import android.widget.ListView;
|
||
11 years ago
|
import android.widget.ProgressBar;
|
||
11 years ago
|
import android.widget.TextView;
|
||
|
|
||
11 years ago
|
/**
|
||
|
* Fragment that shows a list of torrents that are active on the server. It supports sorting and filtering and can show
|
||
|
* connection progress and issues. However, actual task starting and execution and overall navigation elements are part
|
||
|
* of the containing activity, not this fragment.
|
||
|
* @author Eric Kok
|
||
|
*/
|
||
11 years ago
|
@EFragment(resName = "fragment_torrents")
|
||
10 years ago
|
public class TorrentsFragment extends Fragment implements OnLabelPickedListener {
|
||
11 years ago
|
|
||
|
// Local data
|
||
11 years ago
|
@Bean
|
||
|
protected ApplicationSettings applicationSettings;
|
||
11 years ago
|
@Bean
|
||
|
protected SystemSettings systemSettings;
|
||
11 years ago
|
@InstanceState
|
||
|
protected ArrayList<Torrent> torrents = null;
|
||
11 years ago
|
@InstanceState
|
||
11 years ago
|
protected ArrayList<Torrent> lastMultiSelectedTorrents;
|
||
|
@InstanceState
|
||
|
protected ArrayList<Label> currentLabels;
|
||
|
@InstanceState
|
||
11 years ago
|
protected NavigationFilter currentNavigationFilter = null;
|
||
11 years ago
|
@InstanceState
|
||
11 years ago
|
protected TorrentsSortBy currentSortOrder = TorrentsSortBy.Alphanumeric;
|
||
|
@InstanceState
|
||
|
protected boolean currentSortDescending = false;
|
||
|
@InstanceState
|
||
11 years ago
|
protected String currentTextFilter = null;
|
||
|
@InstanceState
|
||
11 years ago
|
protected boolean hasAConnection = false;
|
||
|
@InstanceState
|
||
11 years ago
|
protected boolean isLoading = true;
|
||
|
@InstanceState
|
||
|
protected String connectionErrorMessage = null;
|
||
11 years ago
|
@InstanceState
|
||
|
protected Daemon daemonType;
|
||
11 years ago
|
|
||
11 years ago
|
// Views
|
||
10 years ago
|
@ViewById(resName = "torrents_list")
|
||
|
protected ListView torrentsList;
|
||
11 years ago
|
@ViewById
|
||
|
protected TextView emptyText;
|
||
11 years ago
|
@ViewById
|
||
|
protected TextView nosettingsText;
|
||
11 years ago
|
@ViewById
|
||
11 years ago
|
protected TextView errorText;
|
||
|
@ViewById
|
||
11 years ago
|
protected ProgressBar loadingProgress;
|
||
11 years ago
|
|
||
11 years ago
|
@AfterViews
|
||
|
protected void init() {
|
||
11 years ago
|
|
||
|
// Load the requested sort order from the user settings
|
||
11 years ago
|
this.currentSortOrder = applicationSettings.getLastUsedSortOrder();
|
||
|
this.currentSortDescending = applicationSettings.getLastUsedSortDescending();
|
||
11 years ago
|
|
||
|
// Set up the list adapter, which allows multi-select and fast scrolling
|
||
11 years ago
|
torrentsList.setAdapter(TorrentsAdapter_.getInstance_(getActivity()));
|
||
|
torrentsList.setMultiChoiceModeListener(onTorrentsSelected);
|
||
11 years ago
|
torrentsList.setFastScrollEnabled(true);
|
||
11 years ago
|
if (torrents != null)
|
||
11 years ago
|
updateTorrents(torrents, currentLabels);
|
||
11 years ago
|
// Allow pulls on the list view to refresh the torrents
|
||
|
if (getActivity() != null && getActivity() instanceof RefreshableActivity) {
|
||
|
((RefreshableActivity) getActivity()).addRefreshableView(torrentsList);
|
||
|
}
|
||
11 years ago
|
nosettingsText.setText(getString(R.string.navigation_nosettings, getString(R.string.app_name)));
|
||
11 years ago
|
|
||
11 years ago
|
}
|
||
11 years ago
|
|
||
11 years ago
|
/**
|
||
|
* Updates the list adapter to show a new list of torrent objects, replacing the old torrents completely
|
||
|
* @param newTorrents The new, updated list of torrents
|
||
|
*/
|
||
11 years ago
|
public void updateTorrents(ArrayList<Torrent> newTorrents, ArrayList<Label> currentLabels) {
|
||
|
this.torrents = newTorrents;
|
||
|
this.currentLabels = currentLabels;
|
||
|
applyAllFilters();
|
||
11 years ago
|
}
|
||
|
|
||
11 years ago
|
/**
|
||
|
* Just look for a specific torrent in the currently shown list (by its unique id) and update only this
|
||
|
* @param affected The affected torrent to update
|
||
|
* @param wasRemoved Whether the affected torrent was indeed removed; otherwise it was updated somehow
|
||
|
*/
|
||
|
public void quickUpdateTorrent(Torrent affected, boolean wasRemoved) {
|
||
|
// Remove the old torrent object first
|
||
|
Iterator<Torrent> iter = this.torrents.iterator();
|
||
|
while (iter.hasNext()) {
|
||
|
Torrent torrent = iter.next();
|
||
|
if (torrent.getUniqueID().equals(affected.getUniqueID())) {
|
||
|
iter.remove();
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
// In case it was an update, add the updated torrent object
|
||
|
if (!wasRemoved)
|
||
|
this.torrents.add(affected);
|
||
|
// Now refresh the screen
|
||
|
applyAllFilters();
|
||
|
}
|
||
|
|
||
11 years ago
|
/**
|
||
11 years ago
|
* Clears the currently visible list of torrents.
|
||
11 years ago
|
* @param b
|
||
11 years ago
|
*/
|
||
11 years ago
|
public void clear(boolean clearError, boolean clearFilter) {
|
||
11 years ago
|
this.torrents = null;
|
||
11 years ago
|
if (clearError)
|
||
|
this.connectionErrorMessage = null;
|
||
11 years ago
|
if (clearFilter) {
|
||
|
this.currentTextFilter = null;
|
||
|
this.currentNavigationFilter = null;
|
||
|
}
|
||
11 years ago
|
applyAllFilters();
|
||
11 years ago
|
}
|
||
|
|
||
11 years ago
|
/**
|
||
|
* Stores the new sort order (for future refreshes) and sorts the current visible list. If the given new sort
|
||
|
* property equals the existing property, the list sort order is reversed instead.
|
||
|
* @param newSortOrder The sort order that the user selected.
|
||
|
*/
|
||
|
public void sortBy(TorrentsSortBy newSortOrder) {
|
||
|
// Update the sort order property and direction and store this last used setting
|
||
|
if (this.currentSortOrder == newSortOrder) {
|
||
|
this.currentSortDescending = !this.currentSortDescending;
|
||
|
} else {
|
||
|
this.currentSortOrder = newSortOrder;
|
||
|
this.currentSortDescending = false;
|
||
|
}
|
||
|
applicationSettings.setLastUsedSortOrder(this.currentSortOrder, this.currentSortDescending);
|
||
11 years ago
|
applyAllFilters();
|
||
|
}
|
||
11 years ago
|
|
||
11 years ago
|
public void applyTextFilter(String newTextFilter) {
|
||
|
this.currentTextFilter = newTextFilter;
|
||
|
// Show the new filtered list
|
||
|
applyAllFilters();
|
||
11 years ago
|
}
|
||
11 years ago
|
|
||
11 years ago
|
/**
|
||
|
* Apply a filter on the current list of all torrents, showing the appropriate sublist of torrents only
|
||
11 years ago
|
* @param newFilter The new filter to apply to the local list of torrents
|
||
11 years ago
|
*/
|
||
11 years ago
|
public void applyNavigationFilter(NavigationFilter newFilter) {
|
||
|
this.currentNavigationFilter = newFilter;
|
||
|
applyAllFilters();
|
||
|
}
|
||
11 years ago
|
|
||
11 years ago
|
private void applyAllFilters() {
|
||
11 years ago
|
|
||
|
// No torrents? Directly update views accordingly
|
||
11 years ago
|
if (torrents == null) {
|
||
|
updateViewVisibility();
|
||
|
return;
|
||
|
}
|
||
11 years ago
|
|
||
11 years ago
|
// Filter the list of torrents to show according to navigation and text filters
|
||
11 years ago
|
ArrayList<Torrent> filteredTorrents = new ArrayList<Torrent>(torrents);
|
||
|
if (filteredTorrents != null && currentNavigationFilter != null) {
|
||
11 years ago
|
// Remove torrents that do not match the selected navigation filter
|
||
11 years ago
|
for (Iterator<Torrent> torrentIter = filteredTorrents.iterator(); torrentIter.hasNext();) {
|
||
11 years ago
|
if (!currentNavigationFilter.matches(torrentIter.next(), systemSettings.treatDormantAsInactive()))
|
||
11 years ago
|
torrentIter.remove();
|
||
|
}
|
||
|
}
|
||
11 years ago
|
if (filteredTorrents != null && currentTextFilter != null) {
|
||
11 years ago
|
// Remove torrent that do not contain the text filter string
|
||
11 years ago
|
for (Iterator<Torrent> torrentIter = filteredTorrents.iterator(); torrentIter.hasNext();) {
|
||
11 years ago
|
if (!torrentIter.next().getName().toLowerCase(Locale.getDefault())
|
||
|
.contains(currentTextFilter.toLowerCase(Locale.getDefault())))
|
||
|
torrentIter.remove();
|
||
11 years ago
|
}
|
||
|
}
|
||
11 years ago
|
|
||
|
// Sort the list of filtered torrents
|
||
11 years ago
|
Collections.sort(filteredTorrents, new TorrentsComparator(daemonType, this.currentSortOrder,
|
||
11 years ago
|
this.currentSortDescending));
|
||
|
|
||
11 years ago
|
((TorrentsAdapter) torrentsList.getAdapter()).update(filteredTorrents);
|
||
11 years ago
|
updateViewVisibility();
|
||
|
}
|
||
11 years ago
|
|
||
10 years ago
|
private MultiChoiceModeListener onTorrentsSelected = new MultiChoiceModeListener() {
|
||
11 years ago
|
|
||
11 years ago
|
SelectionManagerMode selectionManagerMode;
|
||
11 years ago
|
|
||
11 years ago
|
@Override
|
||
|
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||
|
// Show contextual action bar to start/stop/remove/etc. torrents in batch mode
|
||
|
mode.getMenuInflater().inflate(R.menu.fragment_torrents_cab, menu);
|
||
11 years ago
|
selectionManagerMode = new SelectionManagerMode(torrentsList, R.plurals.navigation_torrentsselected);
|
||
|
selectionManagerMode.onCreateActionMode(mode, menu);
|
||
11 years ago
|
return true;
|
||
|
}
|
||
11 years ago
|
|
||
11 years ago
|
@Override
|
||
11 years ago
|
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
|
||
11 years ago
|
selectionManagerMode.onPrepareActionMode(mode, menu);
|
||
|
// Hide/show options depending on the type of server we are connected to
|
||
|
if (daemonType != null) {
|
||
|
menu.findItem(R.id.action_start).setVisible(Daemon.supportsStoppingStarting(daemonType));
|
||
|
menu.findItem(R.id.action_stop).setVisible(Daemon.supportsStoppingStarting(daemonType));
|
||
|
menu.findItem(R.id.action_setlabel).setVisible(Daemon.supportsSetLabel(daemonType));
|
||
|
}
|
||
11 years ago
|
// Pause autorefresh
|
||
10 years ago
|
if (getActivity() != null && getActivity() instanceof TorrentsActivity) {
|
||
|
((TorrentsActivity) getActivity()).stopRefresh = true;
|
||
|
((TorrentsActivity) getActivity()).stopAutoRefresh();
|
||
|
}
|
||
11 years ago
|
return true;
|
||
11 years ago
|
}
|
||
|
|
||
11 years ago
|
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
||
11 years ago
|
|
||
11 years ago
|
// Get checked torrents
|
||
11 years ago
|
ArrayList<Torrent> checked = new ArrayList<Torrent>();
|
||
11 years ago
|
for (int i = 0; i < torrentsList.getCheckedItemPositions().size(); i++) {
|
||
11 years ago
|
if (torrentsList.getCheckedItemPositions().valueAt(i) && i < torrentsList.getAdapter().getCount())
|
||
11 years ago
|
checked.add((Torrent) torrentsList.getAdapter().getItem(
|
||
|
torrentsList.getCheckedItemPositions().keyAt(i)));
|
||
11 years ago
|
}
|
||
11 years ago
|
|
||
11 years ago
|
int itemId = item.getItemId();
|
||
|
if (itemId == R.id.action_resume) {
|
||
11 years ago
|
for (Torrent torrent : checked) {
|
||
|
getTasksExecutor().resumeTorrent(torrent);
|
||
|
}
|
||
|
mode.finish();
|
||
|
return true;
|
||
11 years ago
|
} else if (itemId == R.id.action_pause) {
|
||
11 years ago
|
for (Torrent torrent : checked) {
|
||
|
getTasksExecutor().pauseTorrent(torrent);
|
||
|
}
|
||
|
mode.finish();
|
||
|
return true;
|
||
11 years ago
|
} else if (itemId == R.id.action_start) {
|
||
|
for (Torrent torrent : checked) {
|
||
|
getTasksExecutor().startTorrent(torrent, false);
|
||
|
}
|
||
|
mode.finish();
|
||
|
return true;
|
||
|
} else if (itemId == R.id.action_stop) {
|
||
|
for (Torrent torrent : checked) {
|
||
|
getTasksExecutor().stopTorrent(torrent);
|
||
|
}
|
||
|
mode.finish();
|
||
|
return true;
|
||
11 years ago
|
} else if (itemId == R.id.action_remove_default) {
|
||
11 years ago
|
for (Torrent torrent : checked) {
|
||
|
getTasksExecutor().removeTorrent(torrent, false);
|
||
|
}
|
||
|
mode.finish();
|
||
|
return true;
|
||
11 years ago
|
} else if (itemId == R.id.action_remove_withdata) {
|
||
11 years ago
|
for (Torrent torrent : checked) {
|
||
|
getTasksExecutor().removeTorrent(torrent, true);
|
||
|
}
|
||
|
mode.finish();
|
||
|
return true;
|
||
11 years ago
|
} else if (itemId == R.id.action_setlabel) {
|
||
11 years ago
|
lastMultiSelectedTorrents = checked;
|
||
10 years ago
|
if (currentLabels != null)
|
||
|
new SetLabelDialog().setOnLabelPickedListener(TorrentsFragment.this).setCurrentLabels(currentLabels)
|
||
11 years ago
|
.show(getFragmentManager(), "SetLabelDialog");
|
||
11 years ago
|
mode.finish();
|
||
|
return true;
|
||
11 years ago
|
} else {
|
||
11 years ago
|
return false;
|
||
|
}
|
||
|
}
|
||
11 years ago
|
|
||
11 years ago
|
@Override
|
||
|
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
|
||
11 years ago
|
selectionManagerMode.onItemCheckedStateChanged(mode, position, id, checked);
|
||
11 years ago
|
}
|
||
11 years ago
|
|
||
11 years ago
|
@Override
|
||
|
public void onDestroyActionMode(ActionMode mode) {
|
||
11 years ago
|
// Resume autorefresh
|
||
10 years ago
|
if (getActivity() != null && getActivity() instanceof TorrentsActivity) {
|
||
|
((TorrentsActivity) getActivity()).stopRefresh = false;
|
||
|
((TorrentsActivity) getActivity()).startAutoRefresh();
|
||
|
}
|
||
11 years ago
|
selectionManagerMode.onDestroyActionMode(mode);
|
||
11 years ago
|
}
|
||
11 years ago
|
|
||
11 years ago
|
};
|
||
|
|
||
11 years ago
|
@Click
|
||
|
protected void emptyTextClicked() {
|
||
|
// Refresh the activity (that contains this fragment) when the empty view gear is clicked
|
||
|
if (getActivity() != null && getActivity() instanceof RefreshableActivity) {
|
||
|
((RefreshableActivity) getActivity()).refreshScreen();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Click
|
||
|
protected void errorTextClicked() {
|
||
|
// Refresh the activity (that contains this fragment) when the error view gear is clicked
|
||
|
if (getActivity() != null && getActivity() instanceof RefreshableActivity) {
|
||
|
((RefreshableActivity) getActivity()).refreshScreen();
|
||
|
}
|
||
|
}
|
||
|
|
||
10 years ago
|
@ItemClick(resName = "torrents_list")
|
||
11 years ago
|
protected void torrentsListClicked(Torrent torrent) {
|
||
11 years ago
|
// Show the torrent details fragment
|
||
11 years ago
|
((TorrentsActivity) getActivity()).openDetails(torrent);
|
||
11 years ago
|
}
|
||
|
|
||
11 years ago
|
@Override
|
||
|
public void onLabelPicked(String newLabel) {
|
||
|
for (Torrent torrent : lastMultiSelectedTorrents) {
|
||
|
getTasksExecutor().updateLabel(torrent, newLabel);
|
||
|
}
|
||
|
}
|
||
|
|
||
11 years ago
|
/**
|
||
|
* Updates the shown screen depending on whether we have a connection (so torrents can be shown) or not (in case we
|
||
11 years ago
|
* need to show a message suggesting help). This should only ever be called on the UI thread.
|
||
11 years ago
|
* @param hasAConnection True if the user has servers configured and therefore has a connection that can be used
|
||
11 years ago
|
*/
|
||
11 years ago
|
public void updateConnectionStatus(boolean hasAConnection, Daemon daemonType) {
|
||
11 years ago
|
this.hasAConnection = hasAConnection;
|
||
11 years ago
|
this.daemonType = daemonType;
|
||
11 years ago
|
if (!hasAConnection) {
|
||
11 years ago
|
torrentsList.setVisibility(View.GONE);
|
||
|
emptyText.setVisibility(View.GONE);
|
||
|
loadingProgress.setVisibility(View.GONE);
|
||
|
errorText.setVisibility(View.GONE);
|
||
|
nosettingsText.setVisibility(View.VISIBLE);
|
||
11 years ago
|
clear(true, true); // Indirectly also calls updateViewVisibility()
|
||
11 years ago
|
} else {
|
||
|
updateViewVisibility();
|
||
|
}
|
||
11 years ago
|
}
|
||
11 years ago
|
|
||
|
/**
|
||
11 years ago
|
* Updates the shown screen depending on whether the torrents are loading. This should only ever be called on the UI
|
||
|
* thread.
|
||
11 years ago
|
* @param isLoading True if the list of torrents is (re)loading, false otherwise
|
||
|
*/
|
||
|
public void updateIsLoading(boolean isLoading) {
|
||
|
this.isLoading = isLoading;
|
||
11 years ago
|
if (isLoading) {
|
||
11 years ago
|
clear(true, false); // Indirectly also calls updateViewVisibility()
|
||
11 years ago
|
} else {
|
||
|
updateViewVisibility();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
11 years ago
|
* Updates the shown screen depending on whether a connection error occurred. This should only ever be called on the
|
||
|
* UI thread.
|
||
11 years ago
|
* @param connectionErrorMessage The error message from the last failed connection attempt, or null to clear the
|
||
|
* visible error text
|
||
|
*/
|
||
|
public void updateError(String connectionErrorMessage) {
|
||
|
this.connectionErrorMessage = connectionErrorMessage;
|
||
|
errorText.setText(connectionErrorMessage);
|
||
|
if (connectionErrorMessage != null) {
|
||
11 years ago
|
clear(false, false); // Indirectly also calls updateViewVisibility()
|
||
11 years ago
|
} else {
|
||
|
updateViewVisibility();
|
||
|
}
|
||
11 years ago
|
}
|
||
|
|
||
11 years ago
|
private void updateViewVisibility() {
|
||
11 years ago
|
if (!hasAConnection) {
|
||
|
return;
|
||
11 years ago
|
}
|
||
11 years ago
|
boolean isEmpty = torrents == null || torrentsList.getAdapter().isEmpty();
|
||
11 years ago
|
boolean hasError = connectionErrorMessage != null;
|
||
11 years ago
|
nosettingsText.setVisibility(View.GONE);
|
||
11 years ago
|
errorText.setVisibility(hasError ? View.VISIBLE : View.GONE);
|
||
|
torrentsList.setVisibility(!hasError && !isLoading && !isEmpty ? View.VISIBLE : View.GONE);
|
||
11 years ago
|
loadingProgress.setVisibility(!hasError && isLoading ? View.VISIBLE : View.GONE);
|
||
|
emptyText.setVisibility(!hasError && !isLoading && isEmpty ? View.VISIBLE : View.GONE);
|
||
11 years ago
|
}
|
||
11 years ago
|
|
||
11 years ago
|
/**
|
||
|
* 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();
|
||
11 years ago
|
}
|
||
|
|
||
11 years ago
|
}
|