Browse Source

Merge pull request #517 from H3mul/piece-progress-view

Piece progress view
pull/527/head
Eric Kok 5 years ago committed by GitHub
parent
commit
dd067354c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      app/src/main/java/org/transdroid/core/gui/DetailsFragment.java
  2. 32
      app/src/main/java/org/transdroid/core/gui/lists/DetailsAdapter.java
  3. 150
      app/src/main/java/org/transdroid/core/gui/lists/PiecesMapView.java
  4. 14
      app/src/main/java/org/transdroid/daemon/Qbittorrent/QbittorrentAdapter.java
  5. 27
      app/src/main/java/org/transdroid/daemon/TorrentDetails.java
  6. 1
      app/src/main/res/values/strings.xml

2
app/src/main/java/org/transdroid/core/gui/DetailsFragment.java

@ -203,6 +203,8 @@ public class DetailsFragment extends Fragment implements OnTrackersUpdatedListen @@ -203,6 +203,8 @@ public class DetailsFragment extends Fragment implements OnTrackersUpdatedListen
.updateTrackers(SimpleListItemAdapter.SimpleStringItem.wrapStringsList(newTorrentDetails.getTrackers()));
((DetailsAdapter) detailsList.getAdapter())
.updateErrors(SimpleListItemAdapter.SimpleStringItem.wrapStringsList(newTorrentDetails.getErrors()));
((DetailsAdapter) detailsList.getAdapter())
.updatePieces(newTorrentDetails.getPieces());
}
/**

32
app/src/main/java/org/transdroid/core/gui/lists/DetailsAdapter.java

@ -21,6 +21,7 @@ import java.util.List; @@ -21,6 +21,7 @@ import java.util.List;
import org.transdroid.R;
import org.transdroid.core.gui.navigation.*;
import org.transdroid.core.gui.lists.PiecesMapView;
import org.transdroid.daemon.Torrent;
import org.transdroid.daemon.TorrentFile;
@ -38,6 +39,9 @@ public class DetailsAdapter extends MergeAdapter { @@ -38,6 +39,9 @@ public class DetailsAdapter extends MergeAdapter {
private ViewHolderAdapter torrentDetailsViewAdapter = null;
private TorrentDetailsView torrentDetailsView = null;
private ViewHolderAdapter piecesSeparatorAdapter = null;
private ViewHolderAdapter piecesMapViewAdapter = null;
private PiecesMapView piecesMapView = null;
private ViewHolderAdapter trackersSeparatorAdapter = null;
private SimpleListItemAdapter trackersAdapter = null;
private ViewHolderAdapter errorsSeparatorAdapter = null;
@ -56,6 +60,18 @@ public class DetailsAdapter extends MergeAdapter { @@ -56,6 +60,18 @@ public class DetailsAdapter extends MergeAdapter {
torrentDetailsViewAdapter.setViewVisibility(View.GONE);
addAdapter(torrentDetailsViewAdapter);
// Pieces map
piecesSeparatorAdapter = new ViewHolderAdapter(FilterSeparatorView_.build(context).setText(
context.getString(R.string.status_pieces)));
piecesSeparatorAdapter.setViewEnabled(false);
piecesSeparatorAdapter.setViewVisibility(View.GONE);
addAdapter(piecesSeparatorAdapter);
piecesMapView = new PiecesMapView(context);
piecesMapViewAdapter = new ViewHolderAdapter(piecesMapView);
piecesMapViewAdapter.setViewEnabled(false);
piecesMapViewAdapter.setViewVisibility(View.GONE);
addAdapter(piecesMapViewAdapter);
// Tracker errors
errorsSeparatorAdapter = new ViewHolderAdapter(FilterSeparatorView_.build(context).setText(
context.getString(R.string.status_errors)));
@ -137,6 +153,22 @@ public class DetailsAdapter extends MergeAdapter { @@ -137,6 +153,22 @@ public class DetailsAdapter extends MergeAdapter {
}
}
public void updatePieces(List<Integer> pieces) {
if (pieces == null || pieces.isEmpty()) {
piecesSeparatorAdapter.setViewEnabled(false);
piecesSeparatorAdapter.setViewVisibility(View.GONE);
piecesMapViewAdapter.setViewEnabled(false);
piecesMapViewAdapter.setViewVisibility(View.GONE);
} else {
piecesMapView.setPieces(pieces);
piecesMapViewAdapter.setViewEnabled(true);
piecesMapViewAdapter.setViewVisibility(View.VISIBLE);
piecesSeparatorAdapter.setViewEnabled(true);
piecesSeparatorAdapter.setViewVisibility(View.VISIBLE);
}
}
/**
* Clear currently visible torrent, including header and shown lists
*/

150
app/src/main/java/org/transdroid/core/gui/lists/PiecesMapView.java

@ -0,0 +1,150 @@ @@ -0,0 +1,150 @@
package org.transdroid.core.gui.lists;
import org.transdroid.R;
import android.content.Context;
import android.view.View;
import android.graphics.Canvas;
import android.graphics.Paint;
import java.util.ArrayList;
import java.util.List;
import java.lang.Math;
class PiecesMapView extends View {
private final float scale = getContext().getResources().getDisplayMetrics().density;
private final int MINIMUM_HEIGHT = (int) (25 * scale);
private final int MINIMUM_PIECE_WIDTH = (int) (2 * scale);
private ArrayList<Integer> pieces = null;
private final Paint downloadingPaint = new Paint();
private final Paint donePaint = new Paint();
private final Paint partialDonePaint = new Paint();
public PiecesMapView(Context context) {
super(context);
initPaints();
}
private void initPaints() {
downloadingPaint.setColor(getResources().getColor(R.color.torrent_downloading));
donePaint.setColor(getResources().getColor(R.color.torrent_seeding));
partialDonePaint.setColor(getResources().getColor(R.color.file_low));
}
public void setPieces(List<Integer> pieces) {
this.pieces = new ArrayList<Integer>(pieces);
invalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int ws = MeasureSpec.getSize(widthMeasureSpec);
int hs = Math.max(getHeight(), MINIMUM_HEIGHT);
setMeasuredDimension(ws, hs);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (this.pieces == null) {
return;
}
int height = getHeight();
int width = getWidth();
// downscale
ArrayList<Integer> piecesScaled;
int pieceWidth;
pieceWidth = MINIMUM_PIECE_WIDTH;
piecesScaled = new ArrayList<Integer>();
int bucketCount = (int) Math.ceil((double) width / (double) pieceWidth);
int bucketSize = (int) Math.floor((double)this.pieces.size() / (double) bucketCount);
// loop buckets
for (int i = 0; i < bucketCount; i++) {
// Get segment of pieces that fall into bucket
int start = i * bucketSize;
// If this is the last bucket, throw the remainder of the pieces array into it
int end = (i == bucketCount-1) ? this.pieces.size() : (i+1) * bucketSize;
ArrayList<Integer> bucket = new ArrayList<Integer>(this.pieces.subList(start, end));
int doneCount = 0;
int downloadingCount = 0;
// loop pieces in bucket
for(int j = 0; j < bucket.size(); j++) {
// Count downloading pieces
if (bucket.get(j) == 1) {
downloadingCount++;
}
// Count finished pieces
else if (bucket.get(j) == 2) {
doneCount++;
}
}
int state;
// If a piece is downloading show bucket as downloading
if (downloadingCount > 0) {
state = 1;
}
// If all pieces are done, show bucket as done
else if (doneCount == bucket.size()) {
state = 2;
}
// Some done pieces, show bucket as partially done
else if (doneCount > 0) {
state = 3;
}
// bucket is not downloaded
else {
state = 0;
}
piecesScaled.add(state);
}
String scaledPiecesString = "";
for (int s : piecesScaled)
{
scaledPiecesString += s;
}
// Draw downscaled peices
for (int i = 0; i < piecesScaled.size(); i++) {
int piece = piecesScaled.get(i);
if (piece == 0) {
continue;
}
Paint paint = new Paint();
switch (piece) {
case 1:
paint = downloadingPaint;
break;
case 2:
paint = donePaint;
break;
case 3:
paint = partialDonePaint;
break;
}
int x = i * pieceWidth;
canvas.drawRect(x, 0, x + pieceWidth, height, paint);
}
}
}

14
app/src/main/java/org/transdroid/daemon/Qbittorrent/QbittorrentAdapter.java

@ -204,7 +204,8 @@ public class QbittorrentAdapter implements IDaemonAdapter { @@ -204,7 +204,8 @@ public class QbittorrentAdapter implements IDaemonAdapter {
String mhash = task.getTargetTorrent().getUniqueID();
JSONArray messages =
new JSONArray(makeRequest(log, (version >= 30200 ? "/query/propertiesTrackers/" : "/json/propertiesTrackers/") + mhash));
return new GetTorrentDetailsTaskSuccessResult((GetTorrentDetailsTask) task, parseJsonTorrentDetails(messages));
JSONArray pieces = new JSONArray(makeRequest(log, "/query/getPieceStates/" + mhash));
return new GetTorrentDetailsTaskSuccessResult((GetTorrentDetailsTask) task, parseJsonTorrentDetails(messages, pieces));
case GetFileList:
@ -451,7 +452,7 @@ public class QbittorrentAdapter implements IDaemonAdapter { @@ -451,7 +452,7 @@ public class QbittorrentAdapter implements IDaemonAdapter {
return (settings.getSsl() ? "https://" : "http://") + settings.getAddress() + ":" + settings.getPort() + proxyFolder + path;
}
private TorrentDetails parseJsonTorrentDetails(JSONArray messages) throws JSONException {
private TorrentDetails parseJsonTorrentDetails(JSONArray messages, JSONArray pieceStates) throws JSONException {
ArrayList<String> trackers = new ArrayList<>();
ArrayList<String> errors = new ArrayList<>();
@ -467,8 +468,15 @@ public class QbittorrentAdapter implements IDaemonAdapter { @@ -467,8 +468,15 @@ public class QbittorrentAdapter implements IDaemonAdapter {
}
}
ArrayList<Integer> pieces = new ArrayList<>();
if (pieceStates.length() > 0) {
for (int i = 0; i < pieceStates.length(); i++) {
pieces.add(pieceStates.getInt(i));
}
}
// Return the list
return new TorrentDetails(trackers, errors);
return new TorrentDetails(trackers, errors, pieces);
}

27
app/src/main/java/org/transdroid/daemon/TorrentDetails.java

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
package org.transdroid.daemon;
import java.util.List;
import java.util.ArrayList;
import android.os.Parcel;
import android.os.Parcelable;
@ -32,15 +33,29 @@ public final class TorrentDetails implements Parcelable { @@ -32,15 +33,29 @@ public final class TorrentDetails implements Parcelable {
private final List<String> trackers;
private final List<String> errors;
private final List<Integer> pieces;
public TorrentDetails(List<String> trackers, List<String> errors) {
this.trackers = trackers;
this.errors = errors;
this.pieces = null;
}
public TorrentDetails(List<String> trackers, List<String> errors, List<Integer> pieces) {
this.trackers = trackers;
this.errors = errors;
this.pieces = pieces;
}
private TorrentDetails(Parcel in) {
this.trackers = in.createStringArrayList();
this.errors = in.createStringArrayList();
int[] piecesarray = in.createIntArray();
this.pieces = new ArrayList<Integer>(piecesarray.length);
for (int i : piecesarray) {
this.pieces.add(i);
}
}
public List<String> getTrackers() {
@ -77,6 +92,10 @@ public final class TorrentDetails implements Parcelable { @@ -77,6 +92,10 @@ public final class TorrentDetails implements Parcelable {
return errorsText;
}
public List<Integer> getPieces() {
return this.pieces;
}
public static final Parcelable.Creator<TorrentDetails> CREATOR = new Parcelable.Creator<TorrentDetails>() {
public TorrentDetails createFromParcel(Parcel in) {
return new TorrentDetails(in);
@ -96,6 +115,14 @@ public final class TorrentDetails implements Parcelable { @@ -96,6 +115,14 @@ public final class TorrentDetails implements Parcelable {
public void writeToParcel(Parcel dest, int flags) {
dest.writeStringList(trackers);
dest.writeStringList(errors);
int[] piecesarray = new int[this.pieces.size()];
for(int i = 0; i < this.pieces.size(); i++) {
if (this.pieces.get(i) != null) {
piecesarray[i] = this.pieces.get(i);
}
}
dest.writeIntArray(piecesarray);
}
}

1
app/src/main/res/values/strings.xml

@ -131,6 +131,7 @@ @@ -131,6 +131,7 @@
<string name="status_priority_low">Low priority</string>
<string name="status_priority_normal">Normal priority</string>
<string name="status_priority_high">High priority</string>
<string name="status_pieces">PIECES</string>
<string name="status_trackers">TRACKERS</string>
<string name="status_errors">ERRORS</string>
<string name="status_files">FILES</string>

Loading…
Cancel
Save