/** ** Copyright (c) 2010 Ushahidi Inc ** All rights reserved ** Contact: team@ushahidi.com ** Website: http://www.ushahidi.com ** ** GNU Lesser General Public License Usage ** This file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: http://www.gnu.org/licenses/lgpl.html. ** ** ** If you have questions regarding the use of this file, please contact ** Ushahidi developers at team@ushahidi.com. ** **/ package com.ushahidi.android.app; import java.util.ArrayList; import java.util.List; import java.util.Vector; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.os.Bundle; import android.os.Handler; import android.text.TextUtils; import android.view.ContextMenu; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ArrayAdapter; import android.widget.Spinner; import android.widget.TextView; import com.ushahidi.android.app.data.Database; import com.ushahidi.android.app.data.IncidentsData; import com.ushahidi.android.app.ui.PullToRefreshListView; import com.ushahidi.android.app.ui.PullToRefreshListView.OnRefreshListener; import com.ushahidi.android.app.util.ApiUtils; import com.ushahidi.android.app.util.Util; public class IncidentList extends Activity { /** Called when the activity is first created. */ private PullToRefreshListView listIncidents = null; private IncidentAdapter ila; private static final int HOME = Menu.FIRST + 1; private static final int ADD_INCIDENT = Menu.FIRST + 2; private static final int INCIDENT_MAP = Menu.FIRST + 3; private static final int INCIDENT_REFRESH = Menu.FIRST + 4; private static final int SETTINGS = Menu.FIRST + 5; private static final int ABOUT = Menu.FIRST + 6; private static final int GOTOHOME = 0; private static final int POST_INCIDENT = 1; private static final int INCIDENTS_MAP = 2; private static final int VIEW_INCIDENT = 3; private static final int REQUEST_CODE_SETTINGS = 1; private static final int REQUEST_CODE_ABOUT = 2; private Spinner spinner = null; private ArrayAdapter<String> spinnerArrayAdapter; private Bundle incidentsBundle = new Bundle(); private final Handler mHandler = new Handler(); public static Database mDb; private List<IncidentsData> mOldIncidents; private Vector<String> vectorCategories = new Vector<String>(); private TextView emptyListText; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.incident_list); listIncidents = (PullToRefreshListView)findViewById(R.id.view_incidents); emptyListText = (TextView) findViewById(R.id.empty_list_for_reports); mOldIncidents = new ArrayList<IncidentsData>(); ila = new IncidentAdapter(this); listIncidents.setOnItemClickListener(new OnItemClickListener() { public void onItemClick(AdapterView<?> arg0, View view, int positions, long id) { //It seems pull to refresh list is buggy; The list item position is by 1 higher //TODO Look into fixing this. int position = positions - 1; incidentsBundle.putInt("id", mOldIncidents.get(position).getIncidentId()); incidentsBundle.putString("title", mOldIncidents.get(position).getIncidentTitle()); incidentsBundle.putString("desc", mOldIncidents.get(position).getIncidentDesc()); incidentsBundle.putString("longitude", mOldIncidents.get(position) .getIncidentLocLongitude()); incidentsBundle.putString("latitude", mOldIncidents.get(position) .getIncidentLocLatitude()); incidentsBundle.putString("category", mOldIncidents.get(position) .getIncidentCategories()); incidentsBundle.putString("location", mOldIncidents.get(position) .getIncidentLocation()); incidentsBundle.putString("date", mOldIncidents.get(position).getIncidentDate()); incidentsBundle.putString("media", mOldIncidents.get(position) .getIncidentThumbnail()); incidentsBundle.putString("image", mOldIncidents.get(position).getIncidentImage()); incidentsBundle.putString("status", "" + mOldIncidents.get(position).getIncidentVerified()); Intent intent = new Intent(IncidentList.this, IncidentView.class); intent.putExtra("incidents", incidentsBundle); startActivityForResult(intent, VIEW_INCIDENT); setResult(RESULT_OK, intent); } }); listIncidents.setOnRefreshListener(new OnRefreshListener() { public void onRefresh() { refreshForReports(); } }); spinner = (Spinner)findViewById(R.id.incident_cat); mHandler.post(mDisplayIncidents); mHandler.post(mDisplayCategories); // mark all incidents as read MainApplication.mDb.markAllIncidentssRead(); MainApplication.mDb.markAllCategoriesRead(); displayEmptyListText(); } @Override protected void onResume() { super.onResume(); if (ila.getCount() == 0) { mHandler.post(mDisplayIncidents); mHandler.post(mDisplayCategories); // mark all incidents as read MainApplication.mDb.markAllIncidentssRead(); MainApplication.mDb.markAllCategoriesRead(); } } public void displayEmptyListText() { if (ila.getCount() == 0) { emptyListText.setVisibility(View.VISIBLE); } else { emptyListText.setVisibility(View.GONE); } } @Override public void onDestroy() { super.onDestroy(); } final Runnable mDisplayIncidents = new Runnable() { public void run() { setProgressBarIndeterminateVisibility(true); showIncidents(getString(R.string.all_categories)); showCategories(); try { setProgressBarIndeterminateVisibility(false); } catch (Exception e) { return; // means that the dialog is not showing, ignore please! } } }; final Runnable mDisplayCategories = new Runnable() { public void run() { showCategories(); } }; public void refreshForReports() { ReportsTask reportsTask = new ReportsTask(); reportsTask.appContext = this; reportsTask.execute(); } // menu stuff @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { populateMenu(menu); } @Override public boolean onCreateOptionsMenu(Menu menu) { populateMenu(menu); return (super.onCreateOptionsMenu(menu)); } @Override public boolean onOptionsItemSelected(MenuItem item) { // applyMenuChoice(item); return (applyMenuChoice(item) || super.onOptionsItemSelected(item)); } @Override public boolean onContextItemSelected(MenuItem item) { return (applyMenuChoice(item) || super.onContextItemSelected(item)); } private void populateMenu(Menu menu) { MenuItem i; i = menu.add(Menu.NONE, HOME, Menu.NONE, R.string.menu_home); i.setIcon(R.drawable.menu_home); i = menu.add(Menu.NONE, ADD_INCIDENT, Menu.NONE, R.string.incident_menu_add); i.setIcon(R.drawable.menu_add); i = menu.add(Menu.NONE, INCIDENT_MAP, Menu.NONE, R.string.incident_menu_map); i.setIcon(R.drawable.menu_map); i = menu.add(Menu.NONE, INCIDENT_REFRESH, Menu.NONE, R.string.menu_sync); i.setIcon(R.drawable.menu_refresh); i = menu.add(Menu.NONE, SETTINGS, Menu.NONE, R.string.menu_settings); i.setIcon(R.drawable.menu_settings); i = menu.add(Menu.NONE, ABOUT, Menu.NONE, R.string.menu_about); i.setIcon(R.drawable.menu_about); } private boolean applyMenuChoice(MenuItem item) { Intent intent; switch (item.getItemId()) { case HOME: intent = new Intent(IncidentList.this, Dashboard.class); startActivityForResult(intent, GOTOHOME); return true; case INCIDENT_REFRESH: refreshForReports(); return (true); case INCIDENT_MAP: incidentsBundle.putInt("tab_index", 1); intent = new Intent(IncidentList.this, IncidentTab.class); intent.putExtra("tab", incidentsBundle); startActivityForResult(intent, INCIDENTS_MAP); return (true); case ADD_INCIDENT: intent = new Intent(IncidentList.this, IncidentAdd.class); startActivityForResult(intent, POST_INCIDENT); return (true); case ABOUT: intent = new Intent(IncidentList.this, About.class); startActivityForResult(intent, REQUEST_CODE_ABOUT); setResult(RESULT_OK); return true; case SETTINGS: intent = new Intent(IncidentList.this, Settings.class); // Make it a subactivity so we know when it returns startActivityForResult(intent, REQUEST_CODE_SETTINGS); return (true); } return (false); } // thread class private class ReportsTask extends AsyncTask<Void, Void, Integer> { protected Integer status; protected Context appContext; @Override protected void onPreExecute() { setProgressBarIndeterminateVisibility(true); } @Override protected Integer doInBackground(Void... params) { status = ApiUtils.processReports(appContext); return status; } @Override protected void onPostExecute(Integer result) { if (result == 4) { Util.showToast(appContext, R.string.internet_connection); } else if (result == 3) { Util.showToast(appContext, R.string.invalid_ushahidi_instance); } else if (result == 2) { Util.showToast(appContext, R.string.could_not_fetch_reports); } else if (result == 1) { Util.showToast(appContext, R.string.could_not_fetch_reports); } else if (result == 0) { showIncidents(getString(R.string.all_categories)); showCategories(); Util.showToast(appContext, R.string.reports_successfully_fetched); } listIncidents.onRefreshComplete(); } } // get incidents from the db public void showIncidents(String by) { Cursor cursor; if (by.equals(getString(R.string.all_categories))) cursor = MainApplication.mDb.fetchAllIncidents(); else cursor = MainApplication.mDb.fetchIncidentsByCategories(by); String title; String status; String date; String description; String location; String categories; String media; String image; String thumbnails[]; Drawable d = null; if (cursor.moveToFirst()) { int idIndex = cursor.getColumnIndexOrThrow(Database.INCIDENT_ID); int titleIndex = cursor.getColumnIndexOrThrow(Database.INCIDENT_TITLE); int dateIndex = cursor.getColumnIndexOrThrow(Database.INCIDENT_DATE); int verifiedIndex = cursor.getColumnIndexOrThrow(Database.INCIDENT_VERIFIED); int locationIndex = cursor.getColumnIndexOrThrow(Database.INCIDENT_LOC_NAME); int descIndex = cursor.getColumnIndexOrThrow(Database.INCIDENT_DESC); int categoryIndex = cursor.getColumnIndexOrThrow(Database.INCIDENT_CATEGORIES); int mediaIndex = cursor.getColumnIndexOrThrow(Database.INCIDENT_MEDIA); int imageIndex = cursor.getColumnIndexOrThrow(Database.INCIDENT_IMAGE); int latitudeIndex = cursor .getColumnIndexOrThrow(Database.INCIDENT_LOC_LATITUDE); int longitudeIndex = cursor .getColumnIndexOrThrow(Database.INCIDENT_LOC_LONGITUDE); ila.removeItems(); ila.notifyDataSetChanged(); mOldIncidents.clear(); do { IncidentsData incidentData = new IncidentsData(); mOldIncidents.add(incidentData); IncidentItem incidentItem = new IncidentItem(); int id = Util.toInt(cursor.getString(idIndex)); incidentData.setIncidentId(id); incidentData.setIncidentLocLatitude(cursor.getString(latitudeIndex)); incidentData.setIncidentLocLongitude(cursor.getString(longitudeIndex)); title = cursor.getString(titleIndex); incidentData.setIncidentTitle(title); incidentItem.setTitle(Util.capitalize(title)); description = cursor.getString(descIndex); incidentData.setIncidentDesc(description); incidentItem.setDesc(description); categories = cursor.getString(categoryIndex); incidentData.setIncidentCategories(categories); incidentItem.setCategories(Util.capitalize(categories)); location = cursor.getString(locationIndex); incidentData.setIncidentLocation(location); incidentItem.setLocation(Util.capitalize(location)); date = Util.formatDate("yyyy-MM-dd HH:mm:ss", cursor.getString(dateIndex), "MMMM dd, yyyy 'at' hh:mm:ss aaa"); incidentData.setIncidentDate(date); incidentItem.setDate(date); media = cursor.getString(mediaIndex); incidentData.setIncidentThumbnail(media); incidentItem.setMedia(media); thumbnails = media.split(","); // TODO do a proper check for thumbnails if (!TextUtils.isEmpty(thumbnails[0])) { d = ImageManager.getImages(Preferences.savePath,thumbnails[0]); } else { d = null; } if (d != null) { incidentItem.setThumbnail(d); } else { incidentItem.setThumbnail(getResources().getDrawable(R.drawable.report_icon)); } image = cursor.getString(imageIndex); incidentData.setIncidentImage(image); status = Util.toInt(cursor.getString(verifiedIndex)) == 0 ? getString(R.string.report_unverified) : getString(R.string.report_verified); incidentData.setIncidentVerified(Util.toInt(cursor.getString(verifiedIndex))); incidentItem.setStatus(status); incidentItem.setId(id); incidentItem.setArrow(getResources().getDrawable(R.drawable.menu_arrow)); ila.addItem(incidentItem); } while (cursor.moveToNext()); } cursor.close(); ila.notifyDataSetChanged(); listIncidents.setAdapter(ila); displayEmptyListText(); } public void showCategories() { Cursor cursor = MainApplication.mDb.fetchAllCategories(); MainApplication.mDb.fetchCategoriesCount(); vectorCategories.clear(); vectorCategories.add(getString(R.string.all_categories)); if (cursor.moveToFirst()) { int titleIndex = cursor.getColumnIndexOrThrow(Database.CATEGORY_TITLE); do { vectorCategories.add(cursor.getString(titleIndex)); } while (cursor.moveToNext()); } cursor.close(); spinnerArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, vectorCategories); spinnerArrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(spinnerArrayAdapter); spinner.setOnItemSelectedListener(spinnerListener); } // spinner listener Spinner.OnItemSelectedListener spinnerListener = new Spinner.OnItemSelectedListener() { public void onItemSelected(AdapterView<?> parent, View v, int position, long id) { // clear data in the list ila.removeItems(); ila.notifyDataSetChanged(); mOldIncidents.clear(); showIncidents(vectorCategories.get(position)); } public void onNothingSelected(AdapterView<?> parent) { } }; @Override protected void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); } }