/** * Copyright 2010 Eric Taix * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package com.bigpupdev.synodroid.adapter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import com.bigpupdev.synodroid.Synodroid; import com.bigpupdev.synodroid.server.SynoServer; import com.bigpupdev.synodroid.data.Task; import com.bigpupdev.synodroid.data.TaskDetail; import com.bigpupdev.synodroid.data.TaskStatus; import com.bigpupdev.synodroid.ui.DownloadFragment; import com.bigpupdev.synodroid.ui.HomeActivity; import com.bigpupdev.synodroid.R; import com.bigpupdev.synodroid.utils.Utils; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.BitmapDrawable; import android.text.Html; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.ProgressBar; import android.widget.TextView; /** * An adaptor for torrents list. This adaptor aims to create a view for each item in the listView * * @author eric.taix at gmail.com */ public class TaskAdapter extends BaseAdapter implements AdapterView.OnItemClickListener, AdapterView.OnItemLongClickListener { // List of torrent private List<Task> tasks = new ArrayList<Task>(); // List of previous tasks private HashMap<Integer, Integer> uploadRatios = new HashMap<Integer, Integer>(); private HashMap<Integer, Long> uploadTimestamp = new HashMap<Integer, Long>(); private HashMap<Integer, Boolean> torrents = new HashMap<Integer, Boolean>(); // The XML view inflater private final LayoutInflater inflater; // The main activity private DownloadFragment fragment; // Bitmap which is used for unknown progress private BitmapDrawable unknownDrawable; private int filter = HomeActivity.FILTER_ALL; private Context c; private Activity a; static class ViewHolder{ public ImageView image; public TextView torrentName; public TextView torrentSize; public TextView torrentCurrentSize; public ProgressBar downProgress; public ProgressBar upProgress; public ProgressBar unknownProgress; public TextView torrentRates; public TextView torrentETA; } /** * Constructor * * @param activityP * The current activity * @param torrentsP * List of torrent */ public TaskAdapter(DownloadFragment fragmentP) { fragment = fragmentP; a = fragment.getActivity(); c = a.getApplicationContext(); inflater = (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE); Bitmap bitmap = BitmapFactory.decodeResource(fragmentP.getResources(), R.drawable.progress_unknown); bitmap = Utils.getRoundedCornerBitmap(bitmap, 4); unknownDrawable = new BitmapDrawable(bitmap); } public void setFilter(int pFilter){ filter = pFilter; } /** * Update the torrents list * * @param torrentsP */ public void clearTasksSelection() { // First update upload informations for (Task task : tasks) { task.selected = false; } notifyDataSetChanged(); } public boolean isFilteredInTask(int curFilter, String state){ switch(curFilter){ case HomeActivity.FILTER_DOWNLOADING: return TaskStatus.isStateDownloading(state); case HomeActivity.FILTER_COMPLETED: return TaskStatus.isStateCompleted(state); case HomeActivity.FILTER_ACTIVE: return TaskStatus.isStateActive(state); case HomeActivity.FILTER_INACTIVE: return TaskStatus.isStateInactive(state); case HomeActivity.FILTER_STOPPED: return TaskStatus.isStateStopped(state); default: return true; } } /** * Update the torrents list * * @param torrentsP */ public ArrayList<Integer> updateTasks(List<Task> tasksP, List<Integer> checked_tasks_id) { ArrayList<Integer> ret = new ArrayList<Integer>(); List<Task> filtered_tasks = new ArrayList<Task>(); // First update upload informations for (Task task : tasksP) { if (checked_tasks_id.contains(task.taskId)){ task.selected = true; } int taskId = task.taskId; Integer progress = uploadRatios.get(taskId); if (progress != null) { task.uploadProgress = progress; } Long timestamp = uploadTimestamp.get(taskId); if (timestamp != null) { task.uploadTimestamp = timestamp; } Boolean isTorrent = torrents.get(taskId); if (isTorrent != null) { task.isTorrent = isTorrent; } if (isFilteredInTask(filter, task.status)){ filtered_tasks.add(task); ret.add(taskId); } } tasks = filtered_tasks; notifyDataSetChanged(); return ret; } /** * Update a task with its details * * @param taskId * @param prorgessP */ public void updateFromDetail(TaskDetail detailP, List<Integer> checked_tasks_id) { Integer upPerc = Utils.computeUploadPercent(detailP); int up = (upPerc != null ? upPerc.intValue() : 0); // Affect the new upload's progress uploadRatios.put(detailP.taskId, up); // The upload ration has been updated: timestamp uploadTimestamp.put(detailP.taskId, System.currentTimeMillis()); // Update the torrent flag torrents.put(detailP.taskId, detailP.isTorrent); // Self update updateTasks(tasks, checked_tasks_id); } /** * Return the count of element * * @return The number of torrent in the list */ public int getCount() { if (tasks != null) { return tasks.size(); } else { return 0; } } /** * Return the torrent at the defined index * * @param indexP * The index to use starting from 0 * @return Instance of Torrent */ public Object getItem(int indexP) { if (tasks != null) { if (indexP < tasks.size()) { return tasks.get(indexP); } } return null; } /** * Return the item id of the item at index X * * @param indexP */ public long getItemId(int indexP) { try { return tasks.get(indexP).taskId; } catch (Exception e) { return 0; } } /** * Return the view used for the item at position indexP. Always try to reuse an old view */ public View getView(int positionP, View convertViewP, ViewGroup parentP) { View view = convertViewP; if (view == null) { view = inflater.inflate(R.layout.task_template, parentP, false); ViewHolder vh = new ViewHolder(); vh.image = (ImageView) view.findViewById(R.id.id_torrent_icon); vh.torrentName = (TextView) view.findViewById(R.id.id_torrent_name); vh.torrentSize = (TextView) view.findViewById(R.id.id_torrent_total_size); vh.torrentCurrentSize = (TextView) view.findViewById(R.id.id_torrent_username); vh.downProgress = (ProgressBar) view.findViewById(R.id.id_download_progress); vh.upProgress = (ProgressBar) view.findViewById(R.id.id_upload_progress); vh.unknownProgress = (ProgressBar) view.findViewById(R.id.id_unknow_progress); vh.torrentRates = (TextView) view.findViewById(R.id.id_torrent_speed); vh.torrentETA = (TextView) view.findViewById(R.id.id_torrent_eta); view.setTag(vh); } try{ bindView(view, tasks.get(positionP)); }catch (IndexOutOfBoundsException e){ view = inflater.inflate(R.layout.empty_task_template, parentP, false); } return view; } /** * Bind torrent's data with widget * * @param viewP * @param taskP */ private void bindView(View viewP, final Task taskP) { ViewHolder vh = (ViewHolder) viewP.getTag(); // Torrent's status icon IconFacade.bindTorrentStatus(c, vh.image, taskP); // The name of the torrent vh.torrentName.setText(taskP.fileName); // The torrent size vh.torrentSize.setText(taskP.totalSize); // The torrent's owner vh.torrentCurrentSize.setText(taskP.creator); // Get progress bar vh.unknownProgress.setBackgroundDrawable(unknownDrawable); // If state is DOWNLOADING or SEEDING or PAUSED if (taskP.status.equals(TaskStatus.TASK_DOWNLOADING.toString()) || taskP.status.equals(TaskStatus.TASK_SEEDING.toString()) || taskP.status.equals(TaskStatus.TASK_PAUSED.toString())) { vh.downProgress.setVisibility(View.VISIBLE); // If a known value if (taskP.downloadProgress != -1) { vh.downProgress.setProgress(taskP.downloadProgress); } else{ vh.downProgress.setProgress(0); } // According to the user's preferences AND if it is a Torrent SynoServer server = ((Synodroid) a.getApplication()).getServer(); if (server.getConnection().showUpload) { // If a known value if (taskP.uploadProgress != -1) { vh.upProgress.setVisibility(taskP.isTorrent ? View.VISIBLE : View.INVISIBLE); vh.unknownProgress.setVisibility(View.GONE); vh.upProgress.setProgress(taskP.uploadProgress); } // If no value then hide it ! else { vh.upProgress.setVisibility(View.GONE); // Show only for a torrent vh.unknownProgress.setVisibility(taskP.isTorrent ? View.VISIBLE : View.INVISIBLE); } } else { vh.upProgress.setVisibility(View.INVISIBLE); vh.unknownProgress.setVisibility(View.GONE); } } // Hide progress bars else { vh.downProgress.setVisibility(View.INVISIBLE); vh.upProgress.setVisibility(View.INVISIBLE); vh.unknownProgress.setVisibility(View.GONE); } // The current rates ColorFacade.bindTorrentStatus(c, vh.torrentRates, taskP); String rates = ""; if (taskP.downloadRate.length() > 0) { rates += "<font color=\"#009900\">D:" + taskP.downloadRate + "</font>    "; } if (taskP.uploadRate.length() > 0) { rates += "<font color=\"#AA6500\">U:" + taskP.uploadRate + "</font>"; } if (rates != ""){ vh.torrentRates.setText(Html.fromHtml(rates)); } else if (!(taskP.status.equals(TaskStatus.TASK_DOWNLOADING.toString()) || taskP.status.equals(TaskStatus.TASK_PRE_SEEDING.toString()) || taskP.status.equals(TaskStatus.TASK_SEEDING.toString()) ) ){ vh.torrentRates.setText(TaskStatus.getLabel(c, taskP.status)); } else{ vh.torrentRates.setText(""); } // The estimated time left vh.torrentETA.setText(taskP.eta); if (taskP.selected){ viewP.setBackgroundResource(R.drawable.list_item_selector_highlighted); } else{ viewP.setBackgroundResource(R.drawable.list_item_selector_default); } final View listItem = viewP; final Task curTask = taskP; vh.image.setOnClickListener(new OnClickListener(){ @Override public void onClick(View arg0) { fragment.checkView(curTask, listItem, !curTask.selected); }}); } /** * Return the tasks list * * @return */ public List<Task> getTaskList() { return tasks; } /** * Click on a item */ public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (fragment.mCurrentActionMode.isActionModeEnabled()){ this.onItemLongClick(parent, view, position, id); } else{ Task task = tasks.get(position); if (task != null) { fragment.onTaskClicked(task); } } } public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { Task task = tasks.get(position); if (task != null) { fragment.checkView(task, view, !task.selected); return true; } return false; } }