/* * Copyright (C) 2013 jonas.oreland@gmail.com * * This program 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. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package org.runnerup.view; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.ListActivity; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.os.Build; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.ImageView; import android.widget.TextView; import org.runnerup.R; import org.runnerup.common.util.Constants; import org.runnerup.db.DBHelper; import org.runnerup.db.entities.ActivityEntity; import org.runnerup.export.SyncManager; import org.runnerup.export.Synchronizer.Status; import org.runnerup.util.Formatter; import org.runnerup.util.SyncActivityItem; import org.runnerup.workout.Sport; import java.util.ArrayList; import java.util.List; @TargetApi(Build.VERSION_CODES.FROYO) public class UploadActivity extends ListActivity implements Constants { long synchronizerID = -1; String synchronizer = null; Integer synchronizerIcon = null; SyncManager.SyncMode syncMode = SyncManager.SyncMode.UPLOAD; SyncManager syncManager = null; SQLiteDatabase mDB = null; Formatter formatter = null; final List<SyncActivityItem> allSyncActivities = new ArrayList<SyncActivityItem>(); int syncCount = 0; Button actionButton = null; CharSequence actionButtonText = null; boolean fetching = false; final StringBuffer cancelSync = new StringBuffer(); /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.upload); Intent intent = getIntent(); synchronizer = intent.getStringExtra("synchronizer"); synchronizerID = intent.getLongExtra("synchronizerID", -1); syncMode = SyncManager.SyncMode.valueOf(intent.getStringExtra("mode")); if (intent.hasExtra("synchronizerIcon")) synchronizerIcon = intent.getIntExtra("synchronizerIcon", 0); mDB = DBHelper.getReadableDatabase(this); formatter = new Formatter(this); syncManager = new SyncManager(this); this.getListView().setDividerHeight(1); setListAdapter(new UploadListAdapter(this)); { Button btn = (Button) findViewById(R.id.account_upload_set_all); btn.setOnClickListener(setAllButtonClick); } { Button btn = (Button) findViewById(R.id.account_upload_clear_all); btn.setOnClickListener(clearAllButtonClick); } { Button dwbtn = (Button) findViewById(R.id.account_download_button); Button upbtn = (Button) findViewById(R.id.account_upload_button); if (syncMode.equals(SyncManager.SyncMode.DOWNLOAD)) { dwbtn.setOnClickListener(downloadButtonClick); actionButton = dwbtn; actionButtonText = dwbtn.getText(); upbtn.setVisibility(View.GONE); } else { upbtn.setOnClickListener(uploadButtonClick); actionButton = upbtn; actionButtonText = upbtn.getText(); dwbtn.setVisibility(View.GONE); } } { TextView tv = (TextView) findViewById(R.id.account_upload_list_name); ImageView im = (ImageView) findViewById(R.id.account_upload_list_icon); tv.setText(synchronizer); if (synchronizerIcon == null) { im.setVisibility(View.GONE); tv.setVisibility(View.VISIBLE); } else { im.setVisibility(View.VISIBLE); tv.setVisibility(View.GONE); im.setBackgroundResource(synchronizerIcon); } } fillData(); } @Override public void onBackPressed() { if (fetching == true) { /** * Cancel */ cancelSync.append("1"); return; } super.onBackPressed(); } @Override public void onDestroy() { super.onDestroy(); DBHelper.closeDB(mDB); syncManager.close(); } void fillData() { if (syncMode.equals(SyncManager.SyncMode.DOWNLOAD)) { syncManager.load(synchronizer); syncManager.loadActivityList(allSyncActivities, synchronizer, new SyncManager.Callback() { @Override public void run(String synchronizerName, Status status) { filterAlreadyPresentActivities(); requery(); } }); } else { // Fields from the database (projection) // Must include the _id column for the adapter to work final String[] from = new String[]{ DB.PRIMARY_KEY, DB.ACTIVITY.START_TIME, DB.ACTIVITY.DISTANCE, DB.ACTIVITY.TIME, DB.ACTIVITY.SPORT }; final String w = "NOT EXISTS (SELECT 1 FROM " + DB.EXPORT.TABLE + " r WHERE r." + DB.EXPORT.ACTIVITY + " = " + DB.ACTIVITY.TABLE + "._id " + " AND r." + DB.EXPORT.ACCOUNT + " = " + synchronizerID + ")"; Cursor c = mDB.query(DB.ACTIVITY.TABLE, from, " deleted == 0 AND " + w, null, null, null, "_id desc", "100"); allSyncActivities.clear(); if (c.moveToFirst()) { do { ActivityEntity ac = new ActivityEntity(c); SyncActivityItem ai = new SyncActivityItem(ac); allSyncActivities.add(ai); } while (c.moveToNext()); } c.close(); syncCount = allSyncActivities.size(); requery(); } } private void filterAlreadyPresentActivities() { List<SyncActivityItem> presentActivities = new ArrayList<SyncActivityItem>(); final String[] from = new String[]{ DB.PRIMARY_KEY, DB.ACTIVITY.START_TIME, DB.ACTIVITY.DISTANCE, DB.ACTIVITY.TIME, DB.ACTIVITY.SPORT }; Cursor c = mDB.query(DB.ACTIVITY.TABLE, from, " deleted = 0", null, null, null, "_id desc", null); if (c.moveToFirst()) { do { ActivityEntity av = new ActivityEntity(c); SyncActivityItem ai = new SyncActivityItem(av); presentActivities.add(ai); } while (c.moveToNext()); } c.close(); for (SyncActivityItem toDown : allSyncActivities) { for (SyncActivityItem present : presentActivities) { if (toDown.isSimilarTo(present)) { toDown.setPresentFlag(Boolean.TRUE); toDown.setSkipFlag(Boolean.FALSE); break; } } } updateSyncCount(); } private void updateSyncCount() { syncCount = 0; for (SyncActivityItem ai : allSyncActivities) { if (ai.synchronize(syncMode)) { syncCount++; } } } void requery() { ((BaseAdapter) this.getListAdapter()).notifyDataSetChanged(); if (syncCount > 0) { actionButton.setText(actionButtonText + " (" + syncCount + ")"); actionButton.setEnabled(true); } else { actionButton.setText(actionButtonText); actionButton.setEnabled(false); } } final OnClickListener onActivityClick = new OnClickListener() { @Override public void onClick(View arg0) { long id = (Long) arg0.getTag(); Intent intent = new Intent(UploadActivity.this, DetailActivity.class); intent.putExtra("ID", id); intent.putExtra("mode", "details"); startActivityForResult(intent, 100); } }; class UploadListAdapter extends BaseAdapter { final LayoutInflater inflater; public UploadListAdapter(Context context) { super(); inflater = LayoutInflater.from(context); } @Override public int getCount() { return allSyncActivities.size(); } @Override public Object getItem(int arg0) { return allSyncActivities.get(arg0); } @Override public long getItemId(int arg0) { return allSyncActivities.get(arg0).getId(); } private class ViewHolderUploadActivity { private TextView tvStartTime; private TextView tvDistance; private TextView tvTime; private TextView tvPace; private TextView tvSport; private CheckBox cb; } @SuppressLint("ObsoleteSdkInt") @Override public View getView(int arg0, View convertView, ViewGroup parent) { View view = convertView; ViewHolderUploadActivity viewHolder; if (view == null) { viewHolder = new ViewHolderUploadActivity(); view = inflater.inflate(R.layout.upload_row, parent, false); viewHolder.tvStartTime = (TextView) view.findViewById(R.id.upload_list_start_time); viewHolder.tvDistance = (TextView) view.findViewById(R.id.upload_list_distance); viewHolder.tvTime = (TextView) view.findViewById(R.id.upload_list_time); viewHolder.tvPace = (TextView) view.findViewById(R.id.upload_list_pace); viewHolder.tvSport = (TextView) view.findViewById(R.id.upload_list_sport); viewHolder.cb = (CheckBox) view.findViewById(R.id.upload_list_check); view.setTag(viewHolder); } else { viewHolder = (ViewHolderUploadActivity) view.getTag(); } SyncActivityItem ai = allSyncActivities.get(arg0); Float d = ai.getDistance(); Long t = ai.getDuration(); if (ai.getStartTime() != null) { viewHolder.tvStartTime.setText(formatter.formatDateTime(ai.getStartTime())); } else { viewHolder.tvStartTime.setText(""); } if (d != null) { viewHolder.tvDistance.setText(formatter.formatDistance(Formatter.Format.TXT_SHORT, d.longValue())); } else { viewHolder.tvDistance.setText(""); } if (t != null) { viewHolder.tvTime.setText(formatter.formatElapsedTime(Formatter.Format.TXT_SHORT, t)); } else { viewHolder.tvTime.setText(""); } if (d != null && t != null && d != 0 && t != 0) { viewHolder.tvPace.setText(formatter.formatPace(Formatter.Format.TXT_LONG, t / d)); } else { viewHolder.tvPace.setText(""); } if (ai.getSport() == null) { viewHolder.tvSport.setText(Sport.textOf(getResources(), DB.ACTIVITY.SPORT_RUNNING)); } else { int sport = Sport.valueOf(ai.getSport()).getDbValue(); viewHolder.tvSport.setText(Sport.textOf(getResources(), sport)); } viewHolder.cb.setTag(arg0); viewHolder.cb.setOnCheckedChangeListener(checkedChangeClick); viewHolder.cb.setChecked(!ai.skipActivity()); if (ai.isRelevantForSynch(syncMode)) { viewHolder.cb.setEnabled(Boolean.TRUE); } else { viewHolder.cb.setEnabled(Boolean.FALSE); } if (syncMode.equals(SyncManager.SyncMode.UPLOAD)) { view.setOnClickListener(onActivityClick); } else if (Build.VERSION.SDK_INT < 15 || view.hasOnClickListeners()) { view.setOnClickListener(null); } return view; } } final OnCheckedChangeListener checkedChangeClick = new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton arg0, boolean arg1) { int pos = (Integer) arg0.getTag(); SyncActivityItem tmp = allSyncActivities.get(pos); tmp.setSkipFlag(!arg1); updateSyncCount(); requery(); } }; final OnClickListener uploadButtonClick = new OnClickListener() { @Override public void onClick(View v) { if (allSyncActivities.isEmpty()) { return; } List<SyncActivityItem> upload = getSelectedActivities(); Log.i(Constants.LOG, "Start uploading " + upload.size()); fetching = true; cancelSync.delete(0, cancelSync.length()); syncManager.syncActivities(SyncManager.SyncMode.UPLOAD, syncCallback, synchronizer, upload, cancelSync); } }; final OnClickListener downloadButtonClick = new OnClickListener() { @Override public void onClick(View v) { if (allSyncActivities.isEmpty()) { return; } List<SyncActivityItem> download = getSelectedActivities(); Log.i(Constants.LOG, "Start downloading " + download.size()); fetching = true; cancelSync.delete(0, cancelSync.length()); syncManager.syncActivities(SyncManager.SyncMode.DOWNLOAD, syncCallback, synchronizer, download, cancelSync); } }; private List<SyncActivityItem> getSelectedActivities() { List<SyncActivityItem> selected = new ArrayList<SyncActivityItem>(); for (SyncActivityItem tmp : allSyncActivities) { if (tmp.synchronize(syncMode)) selected.add(tmp); } return selected; } final SyncManager.Callback syncCallback = new SyncManager.Callback() { @Override public void run(String synchronizerName, Status status) { fetching = false; if (cancelSync.length() > 0 || status == Status.CANCEL) { finish(); return; } if (syncMode.equals(SyncManager.SyncMode.UPLOAD)) { fillData(); } else { filterAlreadyPresentActivities(); requery(); } } }; final OnClickListener clearAllButtonClick = new OnClickListener() { @Override public void onClick(View v) { for (SyncActivityItem tmp : allSyncActivities) { if (tmp.isRelevantForSynch(syncMode)) { tmp.setSkipFlag(Boolean.TRUE); } } updateSyncCount(); requery(); } }; final OnClickListener setAllButtonClick = new OnClickListener() { @Override public void onClick(View v) { for (SyncActivityItem tmp : allSyncActivities) { if (tmp.isRelevantForSynch(syncMode)) { tmp.setSkipFlag(Boolean.FALSE); } } updateSyncCount(); requery(); } }; public void onActivityResult(int requestCode, int resultCode, Intent data) { fillData(); } }