/*
* 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.home;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteQueryBuilder;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.ContextCompat;
import android.support.v4.content.Loader;
import android.text.Html;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;
import com.money.manager.ex.R;
import com.money.manager.ex.common.MmxCursorLoader;
import com.money.manager.ex.core.Core;
import com.money.manager.ex.core.UIHelper;
import com.money.manager.ex.currency.CurrencyService;
import com.money.manager.ex.database.QueryBillDeposits;
import com.money.manager.ex.database.QueryReportIncomeVsExpenses;
import com.money.manager.ex.database.SQLDataSet;
import com.money.manager.ex.database.ViewMobileData;
import com.money.manager.ex.datalayer.Select;
import com.money.manager.ex.reports.IncomeVsExpensesChartFragment;
import com.money.manager.ex.utils.MmxDate;
import com.money.manager.ex.view.RobotoTextView;
import com.money.manager.ex.viewmodels.IncomeVsExpenseReportEntity;
import java.util.Calendar;
import info.javaperformance.money.MoneyFactory;
/**
* This fragment is not used (?).
*/
public class DashboardFragment
extends Fragment
implements LoaderManager.LoaderCallbacks<Cursor> {
// ID LOADER
private static final int ID_LOADER_SCREEN1 = 0x000;
private static final int ID_LOADER_SCREEN2 = 0x001;
private static final int ID_LOADER_SCREEN3 = 0x002;
private static final int ID_LOADER_SCREEN4 = 0x003;
// Padding
final int padding_in_dp = 6; // 6 dps
double scale;
int padding_in_px;
// array of part screen
LinearLayout[] linearScreens;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//set has option menu to close dashboard item
setHasOptionsMenu(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (container == null) return null;
// parse layout
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.dashboard_fragment, container, false);
if (layout == null)
return null;
linearScreens = new LinearLayout[ID_LOADER_SCREEN4 + 1];
// get sub linearlayout
linearScreens[ID_LOADER_SCREEN1] = (LinearLayout) layout.findViewById(R.id.linearLayoutScreen1);
linearScreens[ID_LOADER_SCREEN2] = (LinearLayout) layout.findViewById(R.id.linearLayoutScreen2);
linearScreens[ID_LOADER_SCREEN3] = (LinearLayout) layout.findViewById(R.id.linearLayoutScreen3);
linearScreens[ID_LOADER_SCREEN4] = (LinearLayout) layout.findViewById(R.id.linearLayoutScreen4);
// calculate padding
scale = getResources().getDisplayMetrics().density;
padding_in_px = (int) (padding_in_dp * scale + 0.5f);
return layout;
}
@Override
public void onResume() {
super.onResume();
loadData();
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
//find menu dashboard
MenuItem itemDashboard = menu.findItem(R.id.menu_dashboard);
if (itemDashboard != null)
itemDashboard.setVisible(false);
}
public void loadData() {
// restart loader
if (linearScreens[ID_LOADER_SCREEN1].getVisibility() == View.VISIBLE)
getLoaderManager().restartLoader(ID_LOADER_SCREEN1, null, this);
if (linearScreens[ID_LOADER_SCREEN2].getVisibility() == View.VISIBLE)
getLoaderManager().restartLoader(ID_LOADER_SCREEN2, null, this);
if (linearScreens[ID_LOADER_SCREEN3].getVisibility() == View.VISIBLE)
getLoaderManager().restartLoader(ID_LOADER_SCREEN3, null, this);
if (linearScreens[ID_LOADER_SCREEN4].getVisibility() == View.VISIBLE)
getLoaderManager().restartLoader(ID_LOADER_SCREEN4, null, this);
}
@Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// add progress bar
ProgressBar progressBar = new ProgressBar(getActivity());
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
layoutParams.gravity = Gravity.CENTER;
progressBar.setLayoutParams(layoutParams);
progressBar.setIndeterminate(true);
if (id <= ID_LOADER_SCREEN4) {
linearScreens[id].removeAllViews();
// add view
linearScreens[id].addView(progressBar);
}
Select query;
// start loader
switch (id) {
case ID_LOADER_SCREEN1:
QueryReportIncomeVsExpenses report = new QueryReportIncomeVsExpenses(getActivity());
query = new Select(report.getAllColumns())
.where(IncomeVsExpenseReportEntity.Month + "=" + Integer.toString(Calendar.getInstance().get(Calendar.MONTH) + 1) +
" AND " +
IncomeVsExpenseReportEntity.YEAR + "=" + Integer.toString(Calendar.getInstance().get(Calendar.YEAR)));
return new MmxCursorLoader(getActivity(), report.getUri(), query);
case ID_LOADER_SCREEN2:
query = new Select().where(prepareQueryTopWithdrawals());
return new MmxCursorLoader(getActivity(), new SQLDataSet().getUri(), query);
case ID_LOADER_SCREEN3:
query = new Select().where(prepareQueryTopPayees());
return new MmxCursorLoader(getActivity(), new SQLDataSet().getUri(), query);
case ID_LOADER_SCREEN4:
QueryBillDeposits billDeposits = new QueryBillDeposits(getActivity());
query = new Select(billDeposits.getAllColumns())
.where(QueryBillDeposits.DAYSLEFT + "<=10")
.orderBy(QueryBillDeposits.DAYSLEFT);
return new MmxCursorLoader(getActivity(), billDeposits.getUri(), query);
}
return null;
}
@Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
if (loader.getId() <= ID_LOADER_SCREEN4)
linearScreens[loader.getId()].removeAllViews();
switch (loader.getId()) {
case ID_LOADER_SCREEN1:
showChartIncomeVsExpensesCurrentMonth(data);
break;
case ID_LOADER_SCREEN2:
linearScreens[loader.getId()].addView(showTableLayoutTopWithdrawals(data));
break;
case ID_LOADER_SCREEN3:
linearScreens[loader.getId()].addView(showTableLayoutTopPayees(data));
break;
case ID_LOADER_SCREEN4:
linearScreens[loader.getId()].addView(showTableLayoutUpComingTransactions(data));
break;
}
}
@Override
public void onLoaderReset(Loader<Cursor> loader) {
}
// End loader
//@SuppressWarnings("deprecation")
private String prepareQueryTopWithdrawals() {
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
ViewMobileData mobileData = new ViewMobileData(getContext());
// data to compose builder
String[] projectionIn = new String[]{"ROWID AS _id", ViewMobileData.CATEGID, ViewMobileData.Category, ViewMobileData.SubcategID,
ViewMobileData.Subcategory, "SUM(" + ViewMobileData.AmountBaseConvRate + ") AS TOTAL", "COUNT(*) AS NUM"};
String selection = ViewMobileData.Status + "<>'V' AND " + ViewMobileData.TransactionType + " IN ('Withdrawal')"
+ " AND (julianday(date('now')) - julianday(" + ViewMobileData.Date + ") <= 30)";
String groupBy = ViewMobileData.CATEGID + ", " + ViewMobileData.Category + ", " + ViewMobileData.SubcategID + ", " + ViewMobileData.Subcategory;
String having = "SUM(" + ViewMobileData.AmountBaseConvRate + ") < 0";
String sortOrder = "ABS(SUM(" + ViewMobileData.AmountBaseConvRate + ")) DESC";
String limit = "10";
// compose builder
builder.setTables(mobileData.getSource());
// return query
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
return builder.buildQuery(projectionIn, selection, groupBy, having, sortOrder, limit);
} else {
return builder.buildQuery(projectionIn, selection, null, groupBy, having, sortOrder, limit);
}
}
@SuppressWarnings("deprecation")
private String prepareQueryTopPayees() {
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
ViewMobileData mobileData = new ViewMobileData(getContext());
// data to compose builder
String[] projectionIn = new String[]{"ROWID AS _id",
ViewMobileData.PAYEEID, ViewMobileData.PAYEE,
"ABS(SUM(" + ViewMobileData.AmountBaseConvRate + ")) AS TOTAL",
"COUNT(*) AS NUM"};
String selection = ViewMobileData.Status + "<>'V' AND " + ViewMobileData.TransactionType
+ " IN ('Withdrawal', 'Deposit') AND (julianday(date('now')) - julianday(" + ViewMobileData.Date + ") <= 30)";
String groupBy = ViewMobileData.PAYEEID + ", " + ViewMobileData.PAYEE;
String having = null;
String sortOrder = "ABS(SUM(" + ViewMobileData.AmountBaseConvRate + ")) DESC";
String limit = "10";
// compose builder
builder.setTables(mobileData.getSource());
// return query
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
return builder.buildQuery(projectionIn, selection, groupBy, having, sortOrder, limit);
} else {
return builder.buildQuery(projectionIn, selection, null, groupBy, having, sortOrder, limit);
}
}
/*
* Show Chart of Income Vs. Expenses Cur
*/
private void showChartIncomeVsExpensesCurrentMonth(Cursor cursor) {
// move to first
if (!cursor.moveToFirst())
return;
// arrays
double[] incomes = new double[3];
double[] expenses = new double[3];
String[] titles = new String[3];
// incomes and expenses
incomes[1] = cursor.getDouble(cursor.getColumnIndex(IncomeVsExpenseReportEntity.Income));
expenses[1] = Math.abs(cursor.getDouble(cursor.getColumnIndex(IncomeVsExpenseReportEntity.Expenses)));
// titles
int year = cursor.getInt(cursor.getColumnIndex(IncomeVsExpenseReportEntity.YEAR));
int month = cursor.getInt(cursor.getColumnIndex(IncomeVsExpenseReportEntity.Month));
// format month
// Calendar calendar = Calendar.getInstance();
// calendar.set(year, month - 1, 1);
MmxDate dateTime = new MmxDate(year, month - 1, 1);
// titles
// titles[1] = Integer.toString(year) + "-" + new SimpleDateFormat("MMM").format(calendar.getTime());
titles[1] = Integer.toString(year) + "-" + dateTime.toString("MMM");
// compose bundle for arguments
Bundle args = new Bundle();
args.putDoubleArray(IncomeVsExpensesChartFragment.KEY_EXPENSES_VALUES, expenses);
args.putDoubleArray(IncomeVsExpensesChartFragment.KEY_INCOME_VALUES, incomes);
args.putStringArray(IncomeVsExpensesChartFragment.KEY_XTITLES, titles);
args.putString(IncomeVsExpensesChartFragment.KEY_TITLE, getString(R.string.income_vs_expenses_current_month));
args.putBoolean(IncomeVsExpensesChartFragment.KEY_DISPLAY_AS_UP_ENABLED, false);
// get fragment manager
FragmentManager fragmentManager = getChildFragmentManager();
if (fragmentManager != null) {
IncomeVsExpensesChartFragment fragment;
fragment = new IncomeVsExpensesChartFragment();
fragment.setChartArguments(args);
if (fragment.isVisible())
fragment.onResume();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.replace(R.id.linearLayoutScreen1, fragment, IncomeVsExpensesChartFragment.class.getSimpleName());
fragmentTransaction.commit();
}
}
private View showTableLayoutTopWithdrawals(Cursor cursor) {
LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout layout = (LinearLayout) inflater.inflate(R.layout.dashboard_summary_layout, null);
CurrencyService currencyService = new CurrencyService(getActivity().getApplicationContext());
// Textview Title
TextView title = (TextView) layout.findViewById(R.id.textViewTitle);
title.setText(R.string.top_withdrawals_last_30_days);
// Table
TableLayout tableLayout = (TableLayout) layout.findViewById(R.id.tableLayoutSummary);
// Create Title
tableLayout.addView(createTableRow(new String[]{"<small><b>" + getString(R.string.category) + "</b></small>",
"<small><b>" + getString(R.string.quantity) + "</b></small>", "<small><b>" + getString(R.string.summary) + "</b></small>"}, new Float[]{1f,
null, null}, new Integer[]{null, Gravity.RIGHT, Gravity.RIGHT}, new Integer[][]{null, {0, 0, padding_in_px, 0}, null}));
// add rows
while (cursor.moveToNext()) {
// load values
String category = "<b>" + cursor.getString(cursor.getColumnIndex(ViewMobileData.Category)) + "</b>";
if (!TextUtils.isEmpty(cursor.getString(cursor.getColumnIndex(ViewMobileData.Subcategory)))) {
category += " : " + cursor.getString(cursor.getColumnIndex(ViewMobileData.Subcategory));
}
double total = cursor.getDouble(cursor.getColumnIndex("TOTAL"));
int num = cursor.getInt(cursor.getColumnIndex("NUM"));
// Add Row
tableLayout.addView(createTableRow(new String[]{"<small>" + category + "</small>",
"<small><i>" + Integer.toString(num) + "</i></small>",
"<small>" + currencyService.getCurrencyFormatted(
currencyService.getBaseCurrencyId(), MoneyFactory.fromDouble(total)) + "</small>"},
new Float[]{1f, null, null},
new Integer[]{null, Gravity.RIGHT, Gravity.RIGHT}, new Integer[][]{null, {0, 0, padding_in_px, 0}, null}));
}
// return Layout
return layout;
}
private View showTableLayoutTopPayees(Cursor cursor) {
LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout layout = (LinearLayout) inflater.inflate(R.layout.dashboard_summary_layout, null);
CurrencyService currencyService = new CurrencyService(getActivity().getApplicationContext());
// Textview Title
TextView title = (TextView) layout.findViewById(R.id.textViewTitle);
title.setText(R.string.top_payees_last_30_days);
// Table
TableLayout tableLayout = (TableLayout) layout.findViewById(R.id.tableLayoutSummary);
// Create Title
tableLayout.addView(createTableRow(new String[]{"<small><b>" + getString(R.string.payee) + "</b></small>",
"<small><b>" + getString(R.string.quantity) + "</b></small>", "<small><b>" + getString(R.string.summary) + "</b></small>"}, new Float[]{1f,
null, null}, new Integer[]{null, Gravity.RIGHT, Gravity.RIGHT}, new Integer[][]{null, {0, 0, padding_in_px, 0}, null}));
// add rows
while (cursor.moveToNext()) {
// load values
String payee = cursor.getString(cursor.getColumnIndex(ViewMobileData.PAYEE));
double total = cursor.getDouble(cursor.getColumnIndex("TOTAL"));
int num = cursor.getInt(cursor.getColumnIndex("NUM"));
// Add Row
tableLayout.addView(createTableRow(new String[]{"<small>" + payee + "</small>",
"<small><i>" + Integer.toString(num) + "</i></small>",
"<small>" + currencyService.getCurrencyFormatted(
currencyService.getBaseCurrencyId(), MoneyFactory.fromDouble(total)) + "</small>"},
new Float[]{1f, null, null},
new Integer[]{null, Gravity.RIGHT, Gravity.RIGHT},
new Integer[][]{null, {0, 0, padding_in_px, 0}, null}));
}
// return Layout
return layout;
}
private View showTableLayoutUpComingTransactions(Cursor cursor) {
LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
LinearLayout layout = (LinearLayout) inflater.inflate(R.layout.dashboard_summary_layout, null);
CurrencyService currencyService = new CurrencyService(getActivity().getApplicationContext());
Core core = new Core(getActivity().getApplicationContext());
// Textview Title
TextView title = (TextView) layout.findViewById(R.id.textViewTitle);
title.setText(R.string.upcoming_transactions);
// Table
TableLayout tableLayout = (TableLayout) layout.findViewById(R.id.tableLayoutSummary);
// add rows
while (cursor.moveToNext()) {
// load values
String payee = "<i>" + cursor.getString(cursor.getColumnIndex(QueryBillDeposits.PAYEENAME)) + "</i>";
double total = cursor.getDouble(cursor.getColumnIndex(QueryBillDeposits.AMOUNT));
int daysLeft = cursor.getInt(cursor.getColumnIndex(QueryBillDeposits.DAYSLEFT));
int currencyId = cursor.getInt(cursor.getColumnIndex(QueryBillDeposits.CURRENCYID));
String daysLeftText = "";
daysLeftText = Integer.toString(Math.abs(daysLeft)) + " " + getString(daysLeft >= 0 ? R.string.days_remaining : R.string.days_overdue);
TableRow row = createTableRow(new String[]{"<small>" + payee + "</small>",
"<small>" + currencyService.getCurrencyFormatted(currencyId, MoneyFactory.fromDouble(total)) + "</small>",
"<small>" + daysLeftText + "</small>"}, new Float[]{1f, null, 1f},
new Integer[]{null, Gravity.RIGHT, Gravity.RIGHT}, new Integer[][]{null, {0, 0, padding_in_px, 0}, null});
TextView txt = (TextView) row.getChildAt(2);
UIHelper uiHelper = new UIHelper(getActivity());
int color = daysLeft >= 0
? uiHelper.resolveAttribute(R.attr.holo_green_color_theme)
: uiHelper.resolveAttribute(R.attr.holo_red_color_theme);
txt.setTextColor(ContextCompat.getColor(getActivity(), color));
// Add Row
tableLayout.addView(row);
}
// return Layout
return layout;
}
private TableRow createTableRow(String[] fields, Float[] weight, Integer[] gravity, Integer[][] margin) {
// create row
TableRow row = new TableRow(getActivity());
row.setLayoutParams(new TableLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT));
for (int i = 0; i < fields.length; i++) {
RobotoTextView txtField = new RobotoTextView(getActivity(), null);
TableRow.LayoutParams layoutParams;
if (weight[i] != null) {
layoutParams = new TableRow.LayoutParams(0, LayoutParams.WRAP_CONTENT, weight[i]);
} else {
layoutParams = new TableRow.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
// set margin
if (margin[i] != null)
layoutParams.setMargins(margin[i][0], margin[i][1], margin[i][2], margin[i][3]);
txtField.setLayoutParams(layoutParams);
if (gravity[i] != null)
txtField.setGravity(gravity[i]);
// set text
txtField.setText(Html.fromHtml(fields[i]));
// set singleline
txtField.setSingleLine(true);
// add field
row.addView(txtField);
}
// return row
return row;
}
}