/*
* Copyright (C) 2012-2016 The Android Money Manager Ex Project Team
*
* 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 com.money.manager.ex.currency.list;
import android.app.Activity;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.text.TextUtils;
import android.view.ContextMenu;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import com.mikepenz.google_material_typeface_library.GoogleMaterial;
import com.mikepenz.mmex_icon_font_typeface_library.MMXIconFont;
import com.money.manager.ex.Constants;
import com.money.manager.ex.MoneyManagerApplication;
import com.money.manager.ex.R;
import com.money.manager.ex.common.MmxCursorLoader;
import com.money.manager.ex.common.BaseListFragment;
import com.money.manager.ex.core.UIHelper;
import com.money.manager.ex.currency.CurrencyChartActivity;
import com.money.manager.ex.currency.CurrencyRepository;
import com.money.manager.ex.currency.CurrencyService;
import com.money.manager.ex.currency.CurrencyUIFeatures;
import com.money.manager.ex.currency.events.CurrencyDeletionConfirmedEvent;
import com.money.manager.ex.currency.events.ExchangeRateUpdateConfirmedEvent;
import com.money.manager.ex.datalayer.Select;
import com.money.manager.ex.domainmodel.Account;
import com.money.manager.ex.domainmodel.Currency;
import com.money.manager.ex.investment.events.PriceDownloadedEvent;
import com.money.manager.ex.settings.AppSettings;
import com.money.manager.ex.utils.ActivityUtils;
import com.money.manager.ex.utils.MmxDatabaseUtils;
import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import java.util.ArrayList;
import java.util.List;
/**
* Currency list.
*/
public class CurrencyListFragment
extends BaseListFragment {
private static final int ID_LOADER_CURRENCY = 0;
// Store previous device orientation when showing other screens (chart, etc.)
public int mPreviousOrientation = Constants.NOT_SET;
// @Inject Lazy<CurrencyService> mCurrencyService;
private CurrencyService mCurrencyService;
private String mAction = Intent.ACTION_EDIT;
private String mCurFilter;
private boolean mShowOnlyUsedCurrencies;
private LoaderManager.LoaderCallbacks<Cursor> loaderCallbacks;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MoneyManagerApplication.getApp().iocComponent.inject(this);
mAction = getActivity().getIntent().getAction();
if (mAction.equals(Intent.ACTION_MAIN)) {
mAction = Intent.ACTION_EDIT;
}
// Filter currencies only if in the standalone Currencies list. Do not filter in pickers.
mShowOnlyUsedCurrencies = !mAction.equals(Intent.ACTION_PICK);
loaderCallbacks = initLoaderCallbacks();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// todo initializeSwipeToRefresh();
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
@Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setSearchMenuVisible(true);
// Focus on search menu if set in preferences.
AppSettings settings = new AppSettings(getActivity());
boolean focusOnSearch = settings.getBehaviourSettings().getFilterInSelectors();
setMenuItemSearchIconified(!focusOnSearch);
setEmptyText(getActivity().getResources().getString(R.string.currencies_empty));
setHasOptionsMenu(true);
// create and link the adapter
CurrencyListAdapter adapter = new CurrencyListAdapter(getActivity(), null);
setListAdapter(adapter);
getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
setListShown(false);
loadData();
setFloatingActionButtonVisible(true);
attachFloatingActionButtonToListView();
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
registerForContextMenu(getListView());
}
// Menu.
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.menu_currency_formats_list_activity, menu);
UIHelper ui = new UIHelper(getActivity());
MenuItem item = menu.findItem(R.id.menu_update_exchange_rate);
item.setIcon(ui.getIcon(GoogleMaterial.Icon.gmd_file_download));
// Customize with font icon, if needed.
item = menu.findItem(R.id.menu_import_all_currencies);
item.setIcon(ui.getIcon(MMXIconFont.Icon.mmx_share_square));
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
MenuItem showOnlyUsed = menu.findItem(R.id.menu_show_used);
if (showOnlyUsed != null) {
showOnlyUsed.setChecked(mShowOnlyUsedCurrencies);
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
CurrencyUIFeatures ui = new CurrencyUIFeatures(getActivity());
switch (item.getItemId()) {
case R.id.menu_import_all_currencies:
ui.showDialogImportAllCurrencies();
return true;
case R.id.menu_update_exchange_rate:
ui.showDialogUpdateExchangeRates();
break;
case R.id.menu_show_used:
if (item.isChecked()) {
item.setChecked(false);
// list all accounts
mShowOnlyUsedCurrencies = false;
reloadData();
} else {
item.setChecked(true);
// list only used accounts
mShowOnlyUsedCurrencies = true;
reloadData();
}
break;
}
return super.onOptionsItemSelected(item);
}
// Context menu
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
// take cursor and move into position
Cursor cursor = ((CurrencyListAdapter) getListAdapter()).getCursor();
cursor.moveToPosition(info.position);
// set currency name
menu.setHeaderTitle(cursor.getString(cursor.getColumnIndex(Currency.CURRENCYNAME)));
// compose context menu
String[] menuItems = getResources().getStringArray(R.array.context_menu_currencies);
for (int i = 0; i < menuItems.length; i++) {
menu.add(Menu.NONE, i, i, menuItems[i]);
}
}
@Override
public boolean onContextItemSelected(android.view.MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
// take cursor and move to position
Cursor cursor = ((CurrencyListAdapter) getListAdapter()).getCursor();
cursor.moveToPosition(info.position);
int currencyId = cursor.getInt(cursor.getColumnIndex(Currency.CURRENCYID));
CurrencyUIFeatures ui = new CurrencyUIFeatures(getActivity());
// check item selected
int selectedItem = item.getItemId();
switch (selectedItem) {
case 0: //EDIT
ui.startCurrencyEditActivity(currencyId);
break;
case 1: // Chart
// remember the device orientation and return to it after the chart.
this.mPreviousOrientation = ActivityUtils.forceCurrentOrientation(getActivity());
// add the currency information.
String symbol = cursor.getString(cursor.getColumnIndex(Currency.CURRENCY_SYMBOL));
CurrencyService currencyService = this.getService();
String baseCurrencyCode = currencyService.getBaseCurrencyCode();
Intent intent = new Intent(getActivity(), CurrencyChartActivity.class);
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra(Currency.CURRENCY_SYMBOL, symbol);
intent.putExtra(CurrencyChartActivity.BASE_CURRENCY_SYMBOL, baseCurrencyCode);
startActivity(intent);
break;
case 2: // Update exchange rate
getService().updateExchangeRate(currencyId);
break;
case 3: //DELETE
CurrencyService service = new CurrencyService(getActivity());
boolean used = service.isCurrencyUsed(currencyId);
if (used) {
ui.notifyCurrencyCanNotBeDeleted();
} else {
ContentValues contentValues = new ContentValues();
contentValues.put(Account.CURRENCYID, currencyId);
ui.showDialogDeleteCurrency(currencyId, info.position);
}
break;
}
return false;
}
// Search
@Override
public boolean onQueryTextChange(String newText) {
// Called when the action bar search text has changed. Update
// the search filter, and restart the loader to do a new query
// with this filter.
mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
reloadData();
return true;
}
@Override
protected void setResult() {
Intent result;
if (Intent.ACTION_PICK.equals(mAction)) {
// create intent
Cursor cursor = ((CurrencyListAdapter) getListAdapter()).getCursor();
for (int i = 0; i < getListView().getCount(); i++) {
if (getListView().isItemChecked(i)) {
cursor.moveToPosition(i);
result = new Intent();
result.putExtra(CurrencyListActivity.INTENT_RESULT_CURRENCYID,
cursor.getInt(cursor.getColumnIndex(Currency.CURRENCYID)));
result.putExtra(CurrencyListActivity.INTENT_RESULT_CURRENCYNAME,
cursor.getString(cursor.getColumnIndex(Currency.CURRENCYNAME)));
getActivity().setResult(Activity.RESULT_OK, result);
return;
}
}
}
getActivity().setResult(CurrencyListActivity.RESULT_CANCELED);
}
@Override
public void onFloatingActionButtonClicked() {
CurrencyUIFeatures ui = new CurrencyUIFeatures(getActivity());
ui.startCurrencyEditActivity(null);
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
// Show context menu only if we are displaying the list of currencies
// but not in selection mode.
if (mAction.equals(Intent.ACTION_EDIT)) {
getActivity().openContextMenu(v);
} else {
// we are picking a currency. Select one.
setResultAndFinish();
}
}
@Override
public String getSubTitle() {
String result;
// if (mShowOnlyUsedCurrencies) {
// result = getString(R.string.currencies_used);
// } else {
result = getString(R.string.currencies);
// }
return result;
}
@Subscribe
public void onEvent(PriceDownloadedEvent event) {
CurrencyUIFeatures ui = new CurrencyUIFeatures(getContext());
ui.onPriceDownloaded(event.symbol, event.price, event.date);
}
@Subscribe
public void onEvent(ExchangeRateUpdateConfirmedEvent event) {
// proceed with rate update
// todo: use event.updateAll parameter
// Update only the visible currencies.
List<Currency> currencies = getVisibleCurrencies();
getService().updateExchangeRates(currencies);
}
@Subscribe
public void onEvent(CurrencyDeletionConfirmedEvent event) {
CurrencyRepository repo = new CurrencyRepository(getContext());
boolean success = repo.delete(event.currencyId);
if (success) {
Toast.makeText(getContext(), R.string.delete_success, Toast.LENGTH_SHORT).show();
}
// restart loader
reloadData();
}
// Private methods.
private List<Currency> getVisibleCurrencies() {
CurrencyListAdapter adapter = (CurrencyListAdapter) getListAdapter();
if (adapter == null) return null;
Cursor cursor = adapter.getCursor();
if (cursor == null) return null;
cursor.moveToPosition(Constants.NOT_SET);
List<Currency> currencies = new ArrayList<>();
while (cursor.moveToNext()) {
Currency currency = Currency.fromCursor(cursor);
currencies.add(currency);
}
return currencies;
}
private CurrencyService getService() {
// todo: redo the currency service to remove any UI interaction (dialog) and then use IoC.
// return mCurrencyService.get();
if (mCurrencyService == null) {
mCurrencyService = new CurrencyService(getActivity());
}
return mCurrencyService;
}
private LoaderManager.LoaderCallbacks<Cursor> initLoaderCallbacks() {
LoaderManager.LoaderCallbacks<Cursor> callbacks = new LoaderManager.LoaderCallbacks<Cursor>() {
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
switch (id) {
case ID_LOADER_CURRENCY:
String whereClause = "";
ArrayList<String> arguments = new ArrayList<>();
// filter only used accounts?
if (mShowOnlyUsedCurrencies) {
// get the list of used currencies.
CurrencyService currencyService = getService();
List<Currency> usedCurrencies = currencyService.getUsedCurrencies();
if (usedCurrencies != null && usedCurrencies.size() > 0) {
ArrayList<String> symbols = new ArrayList<>();
for (Currency currency : usedCurrencies) {
if (currency == null) {
new UIHelper(getActivity()).showToast(R.string.currency_not_found);
} else {
symbols.add(currency.getCode());
}
}
MmxDatabaseUtils databaseUtils = new MmxDatabaseUtils(getActivity());
whereClause = Currency.CURRENCY_SYMBOL + " IN (" +
databaseUtils.makePlaceholders(usedCurrencies.size()) + ")";
arguments.addAll(symbols);
}
}
if (!TextUtils.isEmpty(mCurFilter)) {
if (!TextUtils.isEmpty(whereClause)) {
whereClause += " AND ";
}
whereClause += Currency.CURRENCYNAME + " LIKE ?";
arguments.add(mCurFilter + "%");
// selectionArgs = new String[]{ mCurFilter + "%"};
}
String selectionArgs[] = new String[arguments.size()];
selectionArgs = arguments.toArray(selectionArgs);
CurrencyRepository repo = new CurrencyRepository(getActivity());
Select query = new Select(repo.getAllColumns())
.where(whereClause, selectionArgs)
.orderBy("upper(" + Currency.CURRENCYNAME + ")");
return new MmxCursorLoader(getActivity(), repo.getUri(), query);
}
return null;
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
switch (loader.getId()) {
case ID_LOADER_CURRENCY:
CurrencyListAdapter adapter = (CurrencyListAdapter) getListAdapter();
// adapter.swapCursor(null);
adapter.changeCursor(null);
break;
}
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
switch (loader.getId()) {
case ID_LOADER_CURRENCY:
CurrencyListAdapter adapter = (CurrencyListAdapter) getListAdapter();
// adapter.swapCursor(data);
adapter.changeCursor(data);
if (isResumed()) {
setListShown(true);
if (data != null && data.getCount() <= 0 && getFloatingActionButton() != null)
getFloatingActionButton().show(true);
} else {
setListShownNoAnimation(true);
}
break;
}
}
};
return callbacks;
}
private void initializeSwipeToRefresh() {
}
private void loadData() {
getLoaderManager().initLoader(ID_LOADER_CURRENCY, null, this.loaderCallbacks);
}
private void reloadData() {
getLoaderManager().restartLoader(ID_LOADER_CURRENCY, null, this.loaderCallbacks);
}
}