From 4efa743e8b95a5c30be200ae5f23ca0694b8032f Mon Sep 17 00:00:00 2001 From: Oleksandr Tyshkovets Date: Tue, 19 May 2015 20:53:08 +0300 Subject: [PATCH 01/16] Display expenses sub accounts as stacked bars --- .../android/ui/chart/BarChartActivity.java | 44 ++++++++++++++----- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java b/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java index 3a7cefa0e..dbb138c1b 100644 --- a/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java +++ b/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java @@ -70,8 +70,13 @@ public class BarChartActivity extends PassLockActivity implements OnChartValueSe private static final int NO_DATA_COLOR = Color.LTGRAY; private static final int NO_DATA_BAR_COUNTS = 3; private static final int[] COLORS = { - Color.parseColor("#68F1AF"), Color.parseColor("#CC1f09"), Color.parseColor("#EE8600"), - Color.parseColor("#1469EB"), Color.parseColor("#B304AD"), + Color.parseColor("#17ee4e"), Color.parseColor("#cc1f09"), Color.parseColor("#3940f7"), + Color.parseColor("#f9cd04"), Color.parseColor("#5f33a8"), Color.parseColor("#e005b6"), + Color.parseColor("#17d6ed"), Color.parseColor("#e4a9a2"), Color.parseColor("#8fe6cd"), + Color.parseColor("#8b48fb"), Color.parseColor("#343a36"), Color.parseColor("#6decb1"), + Color.parseColor("#a6dcfd"), Color.parseColor("#5c3378"), Color.parseColor("#a6dcfd"), + Color.parseColor("#ba037c"), Color.parseColor("#708809"), Color.parseColor("#32072c"), + Color.parseColor("#fddef8"), Color.parseColor("#fa0e6e"), Color.parseColor("#d9e7b5") }; private BarChart mChart; @@ -140,27 +145,44 @@ private BarData getData(List accountTypeList) { List dataSets = new ArrayList<>(); List values = new ArrayList<>(); + List labels = new ArrayList<>(); + List colors = new ArrayList<>(); List xValues = new ArrayList<>(); for (int i = 0; i <= months; i++) { xValues.add(startDate.toString(X_AXIS_PATTERN)); long start = startDate.dayOfMonth().withMinimumValue().millisOfDay().withMinimumValue().toDate().getTime(); long end = startDate.dayOfMonth().withMaximumValue().millisOfDay().withMaximumValue().toDate().getTime(); - float stack[] = new float[accountTypeList.size()]; - int j = 0; - for (Map.Entry> entry : getAccountTypeToAccountUidMap(accountTypeList).entrySet()) { - stack[j++] = (float) mAccountsDbAdapter.getAccountsBalance(entry.getValue(), start, end).absolute().asDouble(); - Log.d(TAG, entry.getKey() + startDate.toString(" MMMM yyyy") + ", balance = " + stack[j - 1]); + List stack = new ArrayList<>(); + for (Account account : mAccountsDbAdapter.getSimpleAccountList()) { + if (account.getAccountType() == AccountType.EXPENSE + && !account.isPlaceholderAccount() && account.getCurrency() == mCurrency) { + + float balance = (float) mAccountsDbAdapter.getAccountsBalance( + Collections.singletonList(account.getUID()), start, end).asDouble(); + if (balance != 0) { + stack.add(balance); + labels.add(account.getName()); + colors.add(COLORS[(colors.size()) % COLORS.length]); + Log.i(TAG, "EXPENSE" + startDate.toString(" MMMM yyyy ") + account.getName() + + " = " + stack.get(stack.size() - 1) + ", color = " + colors.get(colors.size() - 1)); + } + } } - values.add(new BarEntry(stack, i)); + + float array[] = new float[stack.size()]; + for (int k = 0; k < stack.size(); k++) { + array[k] = stack.get(k); + } + + values.add(new BarEntry(array, i)); startDate = startDate.plusMonths(1); } BarDataSet set = new BarDataSet(values, ""); - // conversion an enum list to a string array - set.setStackLabels(accountTypeList.toString().substring(1, accountTypeList.toString().length() - 1).split(", ")); - set.setColors(Arrays.copyOfRange(COLORS, 0, accountTypeList.size())); + set.setStackLabels(labels.toArray(new String[labels.size()])); + set.setColors(colors); dataSets.add(set); if (set.getYValueSum() == 0) { From 0d630188375c21e7d6e69bd069b69fb979f5c9f4 Mon Sep 17 00:00:00 2001 From: Oleksandr Tyshkovets Date: Wed, 20 May 2015 21:16:07 +0300 Subject: [PATCH 02/16] Workaround to bypass legend restrictions --- .../android/ui/chart/BarChartActivity.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java b/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java index dbb138c1b..e0deabdf2 100644 --- a/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java +++ b/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java @@ -52,9 +52,11 @@ import java.util.Currency; import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.Set; /** * Activity used for drawing a bar chart @@ -89,6 +91,9 @@ public class BarChartActivity extends PassLockActivity implements OnChartValueSe private boolean mChartDataPresent = true; private Currency mCurrency; + private Set mLegendLabels; + private Set mLegendColors; + @Override protected void onCreate(Bundle savedInstanceState) { //it is necessary to set the view first before calling super because of the nav drawer in BaseDrawerActivity @@ -109,14 +114,13 @@ protected void onCreate(Bundle savedInstanceState) { mChart.setDrawValuesForWholeStack(false); mChart.getAxisLeft().setValueFormatter(new LargeValueFormatter(mCurrency.getSymbol(Locale.getDefault()))); mChart.getAxisRight().setEnabled(false); + mChart.getLegend().setEnabled(false); + mChart.getLegend().setForm(Legend.LegendForm.CIRCLE); + mChart.getLegend().setPosition(Legend.LegendPosition.RIGHT_OF_CHART_INSIDE); // below we can add/remove displayed account's types mChart.setData(getData(new ArrayList<>(Arrays.asList(AccountType.INCOME, AccountType.EXPENSE)))); - Legend legend = mChart.getLegend(); - legend.setForm(Legend.LegendForm.CIRCLE); - legend.setPosition(Legend.LegendPosition.RIGHT_OF_CHART_INSIDE); - if (!mChartDataPresent) { mChart.getAxisLeft().setAxisMaxValue(10); mChart.getAxisLeft().setDrawLabels(false); @@ -180,6 +184,9 @@ private BarData getData(List accountTypeList) { startDate = startDate.plusMonths(1); } + mLegendColors = new LinkedHashSet<>(colors); + mLegendLabels = new LinkedHashSet<>(labels); + BarDataSet set = new BarDataSet(values, ""); set.setStackLabels(labels.toArray(new String[labels.size()])); set.setColors(colors); @@ -282,7 +289,11 @@ public boolean onPrepareOptionsMenu(Menu menu) { public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_toggle_legend: - mChart.getLegend().setEnabled(!mChart.getLegend().isEnabled()); + // workaround for buggy legend + Legend legend = mChart.getLegend(); + legend.setEnabled(!mChart.getLegend().isEnabled()); + legend.setLabels(mLegendLabels.toArray(new String[mLegendLabels.size()])); + legend.setColors(Arrays.asList(mLegendColors.toArray(new Integer[mLegendLabels.size()]))); mChart.invalidate(); break; From 3a1859542d3c87706b5d662ff769a3f0ed98e4ca Mon Sep 17 00:00:00 2001 From: Oleksandr Tyshkovets Date: Wed, 20 May 2015 21:53:28 +0300 Subject: [PATCH 03/16] Added account type spinner --- .../android/ui/chart/BarChartActivity.java | 68 ++++++++++++++----- .../main/res/layout/activity_bar_chart.xml | 59 ++++++++++++++++ 2 files changed, 109 insertions(+), 18 deletions(-) create mode 100644 app/src/main/res/layout/activity_bar_chart.xml diff --git a/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java b/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java index e0deabdf2..677d090e4 100644 --- a/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java +++ b/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java @@ -20,7 +20,11 @@ import android.os.Bundle; import android.preference.PreferenceManager; import android.util.Log; +import android.view.View; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; import android.widget.LinearLayout; +import android.widget.Spinner; import android.widget.TextView; import android.widget.Toast; @@ -94,10 +98,12 @@ public class BarChartActivity extends PassLockActivity implements OnChartValueSe private Set mLegendLabels; private Set mLegendColors; + private AccountType mAccountType = AccountType.EXPENSE; + @Override protected void onCreate(Bundle savedInstanceState) { //it is necessary to set the view first before calling super because of the nav drawer in BaseDrawerActivity - setContentView(R.layout.activity_line_chart); + setContentView(R.layout.activity_bar_chart); super.onCreate(savedInstanceState); getSupportActionBar().setTitle(R.string.title_bar_chart); @@ -105,7 +111,7 @@ protected void onCreate(Bundle savedInstanceState) { .getString(getString(R.string.key_report_currency), Money.DEFAULT_CURRENCY_CODE)); mChart = new BarChart(this); - ((LinearLayout) findViewById(R.id.chart)).addView(mChart); + ((LinearLayout) findViewById(R.id.bar_chart)).addView(mChart); mChart.setOnChartValueSelectedListener(this); mChart.setDescription(""); mChart.getXAxis().setDrawGridLines(false); @@ -118,19 +124,7 @@ protected void onCreate(Bundle savedInstanceState) { mChart.getLegend().setForm(Legend.LegendForm.CIRCLE); mChart.getLegend().setPosition(Legend.LegendPosition.RIGHT_OF_CHART_INSIDE); - // below we can add/remove displayed account's types - mChart.setData(getData(new ArrayList<>(Arrays.asList(AccountType.INCOME, AccountType.EXPENSE)))); - - if (!mChartDataPresent) { - mChart.getAxisLeft().setAxisMaxValue(10); - mChart.getAxisLeft().setDrawLabels(false); - mChart.getXAxis().setDrawLabels(false); - mChart.setTouchEnabled(false); - ((TextView) findViewById(R.id.selected_chart_slice)).setText(getResources().getString(R.string.label_chart_no_data)); - } else { - mChart.animateY(ANIMATION_DURATION); - } - mChart.invalidate(); + setUpSpinner(); } /** @@ -159,8 +153,9 @@ private BarData getData(List accountTypeList) { long end = startDate.dayOfMonth().withMaximumValue().millisOfDay().withMaximumValue().toDate().getTime(); List stack = new ArrayList<>(); for (Account account : mAccountsDbAdapter.getSimpleAccountList()) { - if (account.getAccountType() == AccountType.EXPENSE - && !account.isPlaceholderAccount() && account.getCurrency() == mCurrency) { + if (account.getAccountType() == mAccountType + && !account.isPlaceholderAccount() + && account.getCurrency() == mCurrency) { float balance = (float) mAccountsDbAdapter.getAccountsBalance( Collections.singletonList(account.getUID()), start, end).asDouble(); @@ -168,7 +163,7 @@ private BarData getData(List accountTypeList) { stack.add(balance); labels.add(account.getName()); colors.add(COLORS[(colors.size()) % COLORS.length]); - Log.i(TAG, "EXPENSE" + startDate.toString(" MMMM yyyy ") + account.getName() + Log.i(TAG, mAccountType + startDate.toString(" MMMM yyyy ") + account.getName() + " = " + stack.get(stack.size() - 1) + ", color = " + colors.get(colors.size() - 1)); } } @@ -268,6 +263,43 @@ private BarData getEmptyData() { return new BarData(xValues, Collections.singletonList(set)); } + /** + * Sets up settings and data for the account type spinner. Currently used only {@code EXPENSE} and {@code INCOME} + * account types. + */ + private void setUpSpinner() { + Spinner spinner = (Spinner) findViewById(R.id.chart_data_spinner); + ArrayAdapter dataAdapter = new ArrayAdapter<>(this, + android.R.layout.simple_spinner_item, + Arrays.asList(AccountType.EXPENSE, AccountType.INCOME)); + dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); + spinner.setAdapter(dataAdapter); + spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView adapterView, View view, int i, long l) { + mAccountType = (AccountType) ((Spinner) findViewById(R.id.chart_data_spinner)).getSelectedItem(); + + // below we can add/remove displayed account's types + mChart.setData(getData(new ArrayList<>(Arrays.asList(AccountType.INCOME, AccountType.EXPENSE)))); + + if (!mChartDataPresent) { + mChart.getAxisLeft().setAxisMaxValue(10); + mChart.getAxisLeft().setDrawLabels(false); + mChart.getXAxis().setDrawLabels(false); + mChart.setTouchEnabled(false); + ((TextView) findViewById(R.id.selected_chart_slice)).setText(getResources().getString(R.string.label_chart_no_data)); + } else { + mChart.animateY(ANIMATION_DURATION); + } + mChart.invalidate(); + } + + @Override + public void onNothingSelected(AdapterView adapterView) { + } + }); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getSupportMenuInflater().inflate(R.menu.chart_actions, menu); diff --git a/app/src/main/res/layout/activity_bar_chart.xml b/app/src/main/res/layout/activity_bar_chart.xml new file mode 100644 index 000000000..288124eb4 --- /dev/null +++ b/app/src/main/res/layout/activity_bar_chart.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 4eb80ed03103764e56db27a33525d1e40caa238f Mon Sep 17 00:00:00 2001 From: Oleksandr Tyshkovets Date: Fri, 22 May 2015 18:12:53 +0300 Subject: [PATCH 04/16] Fixed x-axis calculating --- .../android/ui/chart/BarChartActivity.java | 69 +++++++++---------- 1 file changed, 33 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java b/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java index 677d090e4..694f8e0ab 100644 --- a/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java +++ b/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java @@ -87,10 +87,6 @@ public class BarChartActivity extends PassLockActivity implements OnChartValueSe private BarChart mChart; private AccountsDbAdapter mAccountsDbAdapter = AccountsDbAdapter.getInstance(); - private Map mEarliestTimestampsMap = new HashMap<>(); - private Map mLatestTimestampsMap = new HashMap<>(); - private long mEarliestTransactionTimestamp; - private long mLatestTransactionTimestamp; private boolean mTotalPercentageMode = true; private boolean mChartDataPresent = true; private Currency mCurrency; @@ -100,6 +96,9 @@ public class BarChartActivity extends PassLockActivity implements OnChartValueSe private AccountType mAccountType = AccountType.EXPENSE; + private LocalDateTime mEarliestTransactionDate; + private LocalDateTime mLatestTransactionDate; + @Override protected void onCreate(Bundle savedInstanceState) { //it is necessary to set the view first before calling super because of the nav drawer in BaseDrawerActivity @@ -132,13 +131,21 @@ protected void onCreate(Bundle savedInstanceState) { * @param accountTypeList account's types which will be displayed * @return a {@code BarData} instance that represents a user data */ - private BarData getData(List accountTypeList) { - calculateEarliestAndLatestTimestamps(accountTypeList); + private BarData getData(AccountType accountType) { +// setEarliestAndLatestDates(accountType); + + TransactionsDbAdapter adapter = TransactionsDbAdapter.getInstance(); + String code = mCurrency.getCurrencyCode(); + LocalDateTime startDate = new LocalDateTime(adapter.getTimestampOfEarliestTransaction(accountType, code)) + .withDayOfMonth(1) + .withMillisOfDay(0); + LocalDateTime endDate = new LocalDateTime(adapter.getTimestampOfLatestTransaction(accountType, code)) + .withDayOfMonth(1) + .withMillisOfDay(0); + Log.d(TAG, accountType + " X-axis star date: " + mEarliestTransactionDate.toString("dd MM yyyy")); + Log.d(TAG, accountType + " X-axis end date: " + mLatestTransactionDate.toString("dd MM yyyy")); +// int months = Months.monthsBetween(mEarliestTransactionDate, mLatestTransactionDate).getMonths(); - LocalDateTime startDate = new LocalDateTime(mEarliestTransactionTimestamp).withDayOfMonth(1).withMillisOfDay(0); - LocalDateTime endDate = new LocalDateTime(mLatestTransactionTimestamp).withDayOfMonth(1).withMillisOfDay(0); - Log.d(TAG, "X-axis star date: " + startDate.toString("dd MM yyyy")); - Log.d(TAG, "X-axis end date: " + endDate.toString("dd MM yyyy")); int months = Months.monthsBetween(startDate, endDate).getMonths(); List dataSets = new ArrayList<>(); @@ -195,32 +202,23 @@ private BarData getData(List accountTypeList) { } /** - * Calculates the earliest and latest transaction's timestamps of the specified account types + * Sets the earliest and latest transaction's dates of the specified account type * @param accountTypeList account's types which will be processed */ - private void calculateEarliestAndLatestTimestamps(List accountTypeList) { - TransactionsDbAdapter dbAdapter = TransactionsDbAdapter.getInstance(); - for (Iterator iter = accountTypeList.iterator(); iter.hasNext();) { - AccountType type = iter.next(); - long earliest = dbAdapter.getTimestampOfEarliestTransaction(type, mCurrency.getCurrencyCode()); - long latest = dbAdapter.getTimestampOfLatestTransaction(type, mCurrency.getCurrencyCode()); - if (earliest > 0 && latest > 0) { - mEarliestTimestampsMap.put(type, earliest); - mLatestTimestampsMap.put(type, latest); - } else { - iter.remove(); - } - } - - if (mEarliestTimestampsMap.isEmpty() || mLatestTimestampsMap.isEmpty()) { - return; - } - - List timestamps = new ArrayList<>(mEarliestTimestampsMap.values()); - timestamps.addAll(mLatestTimestampsMap.values()); - Collections.sort(timestamps); - mEarliestTransactionTimestamp = timestamps.get(0); - mLatestTransactionTimestamp = timestamps.get(timestamps.size() - 1); + private int setEarliestAndLatestDates(AccountType accountType) { + TransactionsDbAdapter adapter = TransactionsDbAdapter.getInstance(); + String code = mCurrency.getCurrencyCode(); + mEarliestTransactionDate = new LocalDateTime(adapter.getTimestampOfEarliestTransaction(accountType, code)) + .withDayOfMonth(1) + .withMillisOfDay(0); + mLatestTransactionDate = new LocalDateTime(adapter.getTimestampOfLatestTransaction(accountType, code)) + .withDayOfMonth(1) + .withMillisOfDay(0); + Log.d(TAG, accountType + " X-axis star date: " + mEarliestTransactionDate.toString("dd MM yyyy")); + Log.d(TAG, accountType + " X-axis end date: " + mLatestTransactionDate.toString("dd MM yyyy")); + int months = Months.monthsBetween(mEarliestTransactionDate, mLatestTransactionDate).getMonths(); + Log.w(TAG, "DIFF: " + months); + return months; } /** @@ -279,8 +277,7 @@ private void setUpSpinner() { public void onItemSelected(AdapterView adapterView, View view, int i, long l) { mAccountType = (AccountType) ((Spinner) findViewById(R.id.chart_data_spinner)).getSelectedItem(); - // below we can add/remove displayed account's types - mChart.setData(getData(new ArrayList<>(Arrays.asList(AccountType.INCOME, AccountType.EXPENSE)))); + mChart.setData(getData(mAccountType)); if (!mChartDataPresent) { mChart.getAxisLeft().setAxisMaxValue(10); From 8832972045dd04e71a146cb424a279cbe2a502b0 Mon Sep 17 00:00:00 2001 From: Oleksandr Tyshkovets Date: Fri, 22 May 2015 20:53:09 +0300 Subject: [PATCH 05/16] Use the same color for the same account in different bars --- .../android/ui/chart/BarChartActivity.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java b/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java index 694f8e0ab..2156b286e 100644 --- a/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java +++ b/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java @@ -55,7 +55,7 @@ import java.util.Collections; import java.util.Currency; import java.util.HashMap; -import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; @@ -99,6 +99,8 @@ public class BarChartActivity extends PassLockActivity implements OnChartValueSe private LocalDateTime mEarliestTransactionDate; private LocalDateTime mLatestTransactionDate; + private Map accountToColorMap = new LinkedHashMap<>(); + @Override protected void onCreate(Bundle savedInstanceState) { //it is necessary to set the view first before calling super because of the nav drawer in BaseDrawerActivity @@ -142,8 +144,8 @@ private BarData getData(AccountType accountType) { LocalDateTime endDate = new LocalDateTime(adapter.getTimestampOfLatestTransaction(accountType, code)) .withDayOfMonth(1) .withMillisOfDay(0); - Log.d(TAG, accountType + " X-axis star date: " + mEarliestTransactionDate.toString("dd MM yyyy")); - Log.d(TAG, accountType + " X-axis end date: " + mLatestTransactionDate.toString("dd MM yyyy")); + Log.d(TAG, accountType + " X-axis star date: " + startDate.toString("dd MM yyyy")); + Log.d(TAG, accountType + " X-axis end date: " + endDate.toString("dd MM yyyy")); // int months = Months.monthsBetween(mEarliestTransactionDate, mLatestTransactionDate).getMonths(); int months = Months.monthsBetween(startDate, endDate).getMonths(); @@ -167,9 +169,17 @@ private BarData getData(AccountType accountType) { float balance = (float) mAccountsDbAdapter.getAccountsBalance( Collections.singletonList(account.getUID()), start, end).asDouble(); if (balance != 0) { + + if (!accountToColorMap.containsKey(account.getUID())) { + Integer color = (account.getColorHexCode() != null) + ? Color.parseColor(account.getColorHexCode()) + : COLORS[accountToColorMap.size()]; + accountToColorMap.put(account.getUID(), color); + } + stack.add(balance); labels.add(account.getName()); - colors.add(COLORS[(colors.size()) % COLORS.length]); + colors.add(accountToColorMap.get(account.getUID())); Log.i(TAG, mAccountType + startDate.toString(" MMMM yyyy ") + account.getName() + " = " + stack.get(stack.size() - 1) + ", color = " + colors.get(colors.size() - 1)); } From 710c2a95c813b4f4b14f3daac7dafe9864597e78 Mon Sep 17 00:00:00 2001 From: Yongxin Wang Date: Sat, 23 May 2015 23:55:17 +0800 Subject: [PATCH 06/16] remove static, diffenrent adapter should have different tag --- app/src/main/java/org/gnucash/android/db/DatabaseAdapter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/gnucash/android/db/DatabaseAdapter.java b/app/src/main/java/org/gnucash/android/db/DatabaseAdapter.java index f10c315da..e63ccb95d 100644 --- a/app/src/main/java/org/gnucash/android/db/DatabaseAdapter.java +++ b/app/src/main/java/org/gnucash/android/db/DatabaseAdapter.java @@ -42,7 +42,7 @@ public abstract class DatabaseAdapter { /** * Tag for logging */ - protected static String LOG_TAG = "DatabaseAdapter"; + protected String LOG_TAG = "DatabaseAdapter"; /** * SQLite database From ba4438ce24bd34171029b364986129bca81715c9 Mon Sep 17 00:00:00 2001 From: Yongxin Wang Date: Sun, 24 May 2015 00:01:21 +0800 Subject: [PATCH 07/16] ROOT account's parent should be null --- app/src/main/java/org/gnucash/android/db/DatabaseHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/gnucash/android/db/DatabaseHelper.java b/app/src/main/java/org/gnucash/android/db/DatabaseHelper.java index 412f04866..d7ed8750e 100644 --- a/app/src/main/java/org/gnucash/android/db/DatabaseHelper.java +++ b/app/src/main/java/org/gnucash/android/db/DatabaseHelper.java @@ -451,7 +451,7 @@ private int upgradeDbToVersion8(SQLiteDatabase db) { //assign a root account to all accounts which had null as parent (top-level accounts) String rootAccountUID = accountsDbAdapter.getOrCreateGnuCashRootAccountUID(); contentValues.put(AccountEntry.COLUMN_PARENT_ACCOUNT_UID, rootAccountUID); - db.update(AccountEntry.TABLE_NAME, contentValues, AccountEntry.COLUMN_PARENT_ACCOUNT_UID + " IS NULL", null); + db.update(AccountEntry.TABLE_NAME, contentValues, AccountEntry.COLUMN_PARENT_ACCOUNT_UID + " IS NULL AND " + AccountEntry.COLUMN_TYPE + " != ?", new String[]{"ROOT"}); Log.i(LOG_TAG, "Migrating existing recurring transactions"); Cursor cursor = db.query(TransactionEntry.TABLE_NAME + "_bak", null, "recurrence_period > 0", null, null, null, null); From 2fc46fa31c34efccd40aeb7d13619c5785917e31 Mon Sep 17 00:00:00 2001 From: Yongxin Wang Date: Sun, 24 May 2015 00:02:21 +0800 Subject: [PATCH 08/16] rewrite autobalancing in migration --- .../gnucash/android/db/DatabaseHelper.java | 67 ++++++++++++++----- 1 file changed, 52 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/org/gnucash/android/db/DatabaseHelper.java b/app/src/main/java/org/gnucash/android/db/DatabaseHelper.java index d7ed8750e..39e2e6de2 100644 --- a/app/src/main/java/org/gnucash/android/db/DatabaseHelper.java +++ b/app/src/main/java/org/gnucash/android/db/DatabaseHelper.java @@ -28,15 +28,15 @@ import org.gnucash.android.app.GnuCashApplication; import org.gnucash.android.export.Exporter; -import org.gnucash.android.model.Account; import org.gnucash.android.model.AccountType; -import org.gnucash.android.model.Money; import org.gnucash.android.model.ScheduledAction; -import org.gnucash.android.model.Split; import org.gnucash.android.model.Transaction; import java.io.File; +import java.math.BigDecimal; import java.sql.Timestamp; +import java.util.Currency; +import java.util.UUID; import static org.gnucash.android.db.DatabaseSchema.AccountEntry; import static org.gnucash.android.db.DatabaseSchema.ScheduledActionEntry; @@ -485,20 +485,57 @@ private int upgradeDbToVersion8(SQLiteDatabase db) { //auto-balance existing splits Log.i(LOG_TAG, "Auto-balancing existing transaction splits"); - cursor = transactionsDbAdapter.fetchAllRecords(); - while (cursor.moveToNext()){ - Transaction transaction = transactionsDbAdapter.buildTransactionInstance(cursor); - if (transaction.isTemplate()) - continue; - Money imbalance = transaction.getImbalance(); - if (!imbalance.isAmountZero()){ - Split split = new Split(imbalance.negate(), - accountsDbAdapter.getOrCreateImbalanceAccountUID(imbalance.getCurrency())); - split.setTransactionUID(transaction.getUID()); - splitsDbAdapter.addSplit(split); +// cursor = transactionsDbAdapter.fetchAllRecords(); +// while (cursor.moveToNext()){ +// Transaction transaction = transactionsDbAdapter.buildTransactionInstance(cursor); +// if (transaction.isTemplate()) +// continue; +// Money imbalance = transaction.getImbalance(); +// if (!imbalance.isAmountZero()){ +// Split split = new Split(imbalance.negate(), +// accountsDbAdapter.getOrCreateImbalanceAccountUID(imbalance.getCurrency())); +// split.setTransactionUID(transaction.getUID()); +// splitsDbAdapter.addSplit(split); +// } +// } +// cursor.close(); + cursor = db.query( + "trans_extra_info , " + TransactionEntry.TABLE_NAME + " ON " + + TransactionEntry.TABLE_NAME + "." + TransactionEntry.COLUMN_UID + + " = trans_extra_info.trans_acct_t_uid", + new String[]{ + TransactionEntry.TABLE_NAME + "." + TransactionEntry.COLUMN_UID + " AS trans_uid", + TransactionEntry.TABLE_NAME + "." + TransactionEntry.COLUMN_CURRENCY + " AS trans_currency", + "trans_extra_info.trans_acct_balance AS trans_acct_balance", + "trans_extra_info.trans_currency_count AS trans_currency_count", + }, "trans_acct_balance != 0 AND trans_currency_count = 1 AND " + + TransactionEntry.TABLE_NAME + "." + TransactionEntry.COLUMN_TEMPLATE + " == 0", null, null, null, null); + try { + String timestamp = (new Timestamp(System.currentTimeMillis())).toString(); + while (cursor.moveToNext()){ + double imbalance = cursor.getDouble(cursor.getColumnIndexOrThrow("trans_acct_balance")); + BigDecimal decimalImbalance = BigDecimal.valueOf(imbalance).setScale(2, BigDecimal.ROUND_HALF_UP); + if (decimalImbalance.compareTo(BigDecimal.ZERO) != 0) { + String currencyCode = cursor.getString(cursor.getColumnIndexOrThrow("trans_currency")); + String TransactionUID = cursor.getString(cursor.getColumnIndexOrThrow("trans_uid")); + contentValues.clear(); + contentValues.put(DatabaseSchema.CommonColumns.COLUMN_UID, UUID.randomUUID().toString().replaceAll("-", "")); + contentValues.put(DatabaseSchema.CommonColumns.COLUMN_CREATED_AT, timestamp); + contentValues.put(SplitEntry.COLUMN_AMOUNT, decimalImbalance.abs().toPlainString()); + contentValues.put(SplitEntry.COLUMN_TYPE, decimalImbalance.compareTo(BigDecimal.ZERO) > 0 ? "DEBIT" : "CREDIT"); + contentValues.put(SplitEntry.COLUMN_MEMO, ""); + contentValues.put(SplitEntry.COLUMN_ACCOUNT_UID, accountsDbAdapter.getOrCreateImbalanceAccountUID(Currency.getInstance(currencyCode))); + contentValues.put(SplitEntry.COLUMN_TRANSACTION_UID, TransactionUID); + db.insert(SplitEntry.TABLE_NAME, null, contentValues); + contentValues.clear(); + contentValues.put(TransactionEntry.COLUMN_MODIFIED_AT, timestamp); + db.update(TransactionEntry.TABLE_NAME, contentValues, TransactionEntry.COLUMN_UID + " == ?", + new String[]{TransactionUID}); + } } + } finally { + cursor.close(); } - cursor.close(); Log.i(LOG_TAG, "Dropping temporary migration tables"); db.execSQL("DROP TABLE " + SplitEntry.TABLE_NAME + "_bak"); From 6217b94ddc5a5358cc14c3c1a2131fd541bcbbb9 Mon Sep 17 00:00:00 2001 From: Oleksandr Tyshkovets Date: Sat, 23 May 2015 21:04:07 +0300 Subject: [PATCH 09/16] Show stack label on chart value selected --- .../org/gnucash/android/ui/chart/BarChartActivity.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java b/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java index 2156b286e..e91e14601 100644 --- a/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java +++ b/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java @@ -191,7 +191,8 @@ private BarData getData(AccountType accountType) { array[k] = stack.get(k); } - values.add(new BarEntry(array, i)); + String stackLabels = labels.subList(labels.size() - stack.size(), labels.size()).toString(); + values.add(new BarEntry(array, i, stackLabels)); startDate = startDate.plusMonths(1); } @@ -287,6 +288,9 @@ private void setUpSpinner() { public void onItemSelected(AdapterView adapterView, View view, int i, long l) { mAccountType = (AccountType) ((Spinner) findViewById(R.id.chart_data_spinner)).getSelectedItem(); + ((TextView) findViewById(R.id.selected_chart_slice)).setText(""); + mChart.highlightValues(null); + mChart.setData(getData(mAccountType)); if (!mChartDataPresent) { @@ -354,7 +358,9 @@ public boolean onOptionsItemSelected(MenuItem item) { public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { if (e == null) return; BarEntry entry = (BarEntry) e; - String label = mChart.getData().getXVals().get(entry.getXIndex()); + String stackLabels = entry.getData().toString(); + String label = mChart.getData().getXVals().get(entry.getXIndex()) + ", " + + stackLabels.substring(1, stackLabels.length() - 1).split(",")[h.getStackIndex()]; double value = entry.getVals()[ h.getStackIndex() == -1 ? 0 : h.getStackIndex() ]; double sum = mTotalPercentageMode ? mChart.getData().getDataSetByIndex(dataSetIndex).getYValueSum() : entry.getVal(); ((TextView) findViewById(R.id.selected_chart_slice)) From aba96cb4d8acb998bb0ccbca72aac3b6cbfb0c5b Mon Sep 17 00:00:00 2001 From: Yongxin Wang Date: Sun, 24 May 2015 14:05:55 +0800 Subject: [PATCH 10/16] remove use of adapters --- .../gnucash/android/db/DatabaseHelper.java | 147 ++++++++++++++---- .../gnucash/android/db/MigrationHelper.java | 6 + 2 files changed, 122 insertions(+), 31 deletions(-) diff --git a/app/src/main/java/org/gnucash/android/db/DatabaseHelper.java b/app/src/main/java/org/gnucash/android/db/DatabaseHelper.java index 39e2e6de2..a46486730 100644 --- a/app/src/main/java/org/gnucash/android/db/DatabaseHelper.java +++ b/app/src/main/java/org/gnucash/android/db/DatabaseHelper.java @@ -26,17 +26,16 @@ import android.database.sqlite.SQLiteOpenHelper; import android.util.Log; +import org.gnucash.android.R; import org.gnucash.android.app.GnuCashApplication; import org.gnucash.android.export.Exporter; import org.gnucash.android.model.AccountType; -import org.gnucash.android.model.ScheduledAction; +import org.gnucash.android.model.Money; import org.gnucash.android.model.Transaction; import java.io.File; import java.math.BigDecimal; import java.sql.Timestamp; -import java.util.Currency; -import java.util.UUID; import static org.gnucash.android.db.DatabaseSchema.AccountEntry; import static org.gnucash.android.db.DatabaseSchema.ScheduledActionEntry; @@ -439,36 +438,84 @@ private int upgradeDbToVersion8(SQLiteDatabase db) { //================================ END TABLE MIGRATIONS ================================ + // String timestamp to be used for all new created entities in migration + String timestamp = (new Timestamp(System.currentTimeMillis())).toString(); - - ScheduledActionDbAdapter scheduledActionDbAdapter = new ScheduledActionDbAdapter(db); - SplitsDbAdapter splitsDbAdapter = new SplitsDbAdapter(db); - TransactionsDbAdapter transactionsDbAdapter = new TransactionsDbAdapter(db, splitsDbAdapter); - AccountsDbAdapter accountsDbAdapter = new AccountsDbAdapter(db,transactionsDbAdapter); + //ScheduledActionDbAdapter scheduledActionDbAdapter = new ScheduledActionDbAdapter(db); + //SplitsDbAdapter splitsDbAdapter = new SplitsDbAdapter(db); + //TransactionsDbAdapter transactionsDbAdapter = new TransactionsDbAdapter(db, splitsDbAdapter); + //AccountsDbAdapter accountsDbAdapter = new AccountsDbAdapter(db,transactionsDbAdapter); Log.i(LOG_TAG, "Creating default root account if none exists"); ContentValues contentValues = new ContentValues(); - //assign a root account to all accounts which had null as parent (top-level accounts) - String rootAccountUID = accountsDbAdapter.getOrCreateGnuCashRootAccountUID(); + //assign a root account to all accounts which had null as parent except ROOT (top-level accounts) + String rootAccountUID; + Cursor cursor = db.query(AccountEntry.TABLE_NAME, + new String[]{AccountEntry.COLUMN_UID}, + AccountEntry.COLUMN_TYPE + "= ?", + new String[]{AccountType.ROOT.name()}, null, null, null); + try { + if (cursor.moveToFirst()) { + rootAccountUID = cursor.getString(cursor.getColumnIndexOrThrow(AccountEntry.COLUMN_UID)); + } + else + { + rootAccountUID = MigrationHelper.generateUUID(); + contentValues.clear(); + contentValues.put(DatabaseSchema.CommonColumns.COLUMN_UID, rootAccountUID); + contentValues.put(DatabaseSchema.CommonColumns.COLUMN_CREATED_AT, timestamp); + contentValues.put(AccountEntry.COLUMN_NAME, "ROOT"); + contentValues.put(AccountEntry.COLUMN_TYPE, "ROOT"); + contentValues.put(AccountEntry.COLUMN_CURRENCY, Money.DEFAULT_CURRENCY_CODE); + contentValues.put(AccountEntry.COLUMN_PLACEHOLDER, 0); + contentValues.put(AccountEntry.COLUMN_HIDDEN, 1); + contentValues.putNull(AccountEntry.COLUMN_COLOR_CODE); + contentValues.put(AccountEntry.COLUMN_FAVORITE, 0); + contentValues.put(AccountEntry.COLUMN_FULL_NAME, " "); + contentValues.putNull(AccountEntry.COLUMN_PARENT_ACCOUNT_UID); + contentValues.putNull(AccountEntry.COLUMN_DEFAULT_TRANSFER_ACCOUNT_UID); + db.insert(AccountEntry.TABLE_NAME, null, contentValues); + } + } finally { + cursor.close(); + } + //String rootAccountUID = accountsDbAdapter.getOrCreateGnuCashRootAccountUID(); + contentValues.clear(); contentValues.put(AccountEntry.COLUMN_PARENT_ACCOUNT_UID, rootAccountUID); db.update(AccountEntry.TABLE_NAME, contentValues, AccountEntry.COLUMN_PARENT_ACCOUNT_UID + " IS NULL AND " + AccountEntry.COLUMN_TYPE + " != ?", new String[]{"ROOT"}); Log.i(LOG_TAG, "Migrating existing recurring transactions"); - Cursor cursor = db.query(TransactionEntry.TABLE_NAME + "_bak", null, "recurrence_period > 0", null, null, null, null); + cursor = db.query(TransactionEntry.TABLE_NAME + "_bak", null, "recurrence_period > 0", null, null, null, null); + long lastRun = System.currentTimeMillis(); while (cursor.moveToNext()){ contentValues.clear(); - Timestamp timestamp = new Timestamp(cursor.getLong(cursor.getColumnIndexOrThrow(TransactionEntry.COLUMN_TIMESTAMP))); - contentValues.put(TransactionEntry.COLUMN_CREATED_AT, timestamp.toString()); + Timestamp timestampT = new Timestamp(cursor.getLong(cursor.getColumnIndexOrThrow(TransactionEntry.COLUMN_TIMESTAMP))); + contentValues.put(TransactionEntry.COLUMN_CREATED_AT, timestampT.toString()); long transactionId = cursor.getLong(cursor.getColumnIndexOrThrow(TransactionEntry._ID)); db.update(TransactionEntry.TABLE_NAME, contentValues, TransactionEntry._ID + "=" + transactionId, null); - ScheduledAction scheduledAction = new ScheduledAction(ScheduledAction.ActionType.TRANSACTION); - scheduledAction.setActionUID(cursor.getString(cursor.getColumnIndexOrThrow(TransactionEntry.COLUMN_UID))); - long period = cursor.getLong(cursor.getColumnIndexOrThrow("recurrence_period")); - scheduledAction.setPeriod(period); - scheduledAction.setStartTime(timestamp.getTime()); //the start time is when the transaction was created - scheduledAction.setLastRun(System.currentTimeMillis()); //prevent this from being executed at the end of migration - scheduledActionDbAdapter.addScheduledAction(scheduledAction); + //ScheduledAction scheduledAction = new ScheduledAction(ScheduledAction.ActionType.TRANSACTION); + //scheduledAction.setActionUID(cursor.getString(cursor.getColumnIndexOrThrow(TransactionEntry.COLUMN_UID))); + //long period = cursor.getLong(cursor.getColumnIndexOrThrow("recurrence_period")); + //scheduledAction.setPeriod(period); + //scheduledAction.setStartTime(timestampT.getTime()); //the start time is when the transaction was created + //scheduledAction.setLastRun(System.currentTimeMillis()); //prevent this from being executed at the end of migration + + contentValues.clear(); + contentValues.put(DatabaseSchema.CommonColumns.COLUMN_UID, MigrationHelper.generateUUID()); + contentValues.put(DatabaseSchema.CommonColumns.COLUMN_CREATED_AT, timestamp); + contentValues.put(ScheduledActionEntry.COLUMN_ACTION_UID, cursor.getString(cursor.getColumnIndexOrThrow(TransactionEntry.COLUMN_UID))); + contentValues.put(ScheduledActionEntry.COLUMN_PERIOD, cursor.getLong(cursor.getColumnIndexOrThrow("recurrence_period"))); + contentValues.put(ScheduledActionEntry.COLUMN_START_TIME, timestampT.getTime()); + contentValues.put(ScheduledActionEntry.COLUMN_END_TIME, 0); + contentValues.put(ScheduledActionEntry.COLUMN_LAST_RUN, lastRun); + contentValues.put(ScheduledActionEntry.COLUMN_TYPE, "TRANSACTION"); + contentValues.put(ScheduledActionEntry.COLUMN_TAG, ""); + contentValues.put(ScheduledActionEntry.COLUMN_ENABLED, 1); + contentValues.put(ScheduledActionEntry.COLUMN_TOTAL_FREQUENCY, 0); + contentValues.put(ScheduledActionEntry.COLUMN_EXECUTION_COUNT, 0); + //scheduledActionDbAdapter.addScheduledAction(scheduledAction); + db.insert(ScheduledActionEntry.TABLE_NAME, null, contentValues); //build intent for recurring transactions in the database Intent intent = new Intent(Intent.ACTION_INSERT); @@ -500,31 +547,69 @@ private int upgradeDbToVersion8(SQLiteDatabase db) { // } // cursor.close(); cursor = db.query( - "trans_extra_info , " + TransactionEntry.TABLE_NAME + " ON " - + TransactionEntry.TABLE_NAME + "." + TransactionEntry.COLUMN_UID + - " = trans_extra_info.trans_acct_t_uid", + TransactionEntry.TABLE_NAME + " , " + SplitEntry.TABLE_NAME + " ON " + + TransactionEntry.TABLE_NAME + "." + TransactionEntry.COLUMN_UID + "=" + SplitEntry.TABLE_NAME + "." + SplitEntry.COLUMN_TRANSACTION_UID + + " , " + AccountEntry.TABLE_NAME + " ON " + + SplitEntry.TABLE_NAME + "." + SplitEntry.COLUMN_ACCOUNT_UID + "=" + AccountEntry.TABLE_NAME + "." + AccountEntry.COLUMN_UID, new String[]{ TransactionEntry.TABLE_NAME + "." + TransactionEntry.COLUMN_UID + " AS trans_uid", TransactionEntry.TABLE_NAME + "." + TransactionEntry.COLUMN_CURRENCY + " AS trans_currency", - "trans_extra_info.trans_acct_balance AS trans_acct_balance", - "trans_extra_info.trans_currency_count AS trans_currency_count", - }, "trans_acct_balance != 0 AND trans_currency_count = 1 AND " + - TransactionEntry.TABLE_NAME + "." + TransactionEntry.COLUMN_TEMPLATE + " == 0", null, null, null, null); + "TOTAL ( CASE WHEN " + + SplitEntry.TABLE_NAME + "." + SplitEntry.COLUMN_TYPE + " = 'DEBIT' THEN " + + SplitEntry.TABLE_NAME + "." + SplitEntry.COLUMN_AMOUNT + " ELSE - " + + SplitEntry.TABLE_NAME + "." + SplitEntry.COLUMN_AMOUNT + " END ) AS trans_acct_balance", + "COUNT ( DISTINCT " + + AccountEntry.TABLE_NAME + "." + AccountEntry.COLUMN_CURRENCY + + " ) AS trans_currency_count" + }, + TransactionEntry.TABLE_NAME + "." + TransactionEntry.COLUMN_TEMPLATE + " == 0", + null, + TransactionEntry.TABLE_NAME + "." + TransactionEntry.COLUMN_UID, + "trans_acct_balance != 0 AND trans_currency_count = 1", + null); try { - String timestamp = (new Timestamp(System.currentTimeMillis())).toString(); while (cursor.moveToNext()){ double imbalance = cursor.getDouble(cursor.getColumnIndexOrThrow("trans_acct_balance")); BigDecimal decimalImbalance = BigDecimal.valueOf(imbalance).setScale(2, BigDecimal.ROUND_HALF_UP); if (decimalImbalance.compareTo(BigDecimal.ZERO) != 0) { String currencyCode = cursor.getString(cursor.getColumnIndexOrThrow("trans_currency")); + String imbalanceAccountName = GnuCashApplication.getAppContext().getString(R.string.imbalance_account_name) + "-" + currencyCode; + String imbalanceAccountUID; + Cursor c = db.query(AccountEntry.TABLE_NAME, new String[]{AccountEntry.COLUMN_UID}, + AccountEntry.COLUMN_FULL_NAME + "= ?", new String[]{imbalanceAccountName}, + null, null, null); + try { + if (c.moveToFirst()) { + imbalanceAccountUID = c.getString(c.getColumnIndexOrThrow(AccountEntry.COLUMN_UID)); + } + else { + imbalanceAccountUID = MigrationHelper.generateUUID(); + contentValues.clear(); + contentValues.put(DatabaseSchema.CommonColumns.COLUMN_UID, imbalanceAccountUID); + contentValues.put(DatabaseSchema.CommonColumns.COLUMN_CREATED_AT, timestamp); + contentValues.put(AccountEntry.COLUMN_NAME, imbalanceAccountName); + contentValues.put(AccountEntry.COLUMN_TYPE, "BANK"); + contentValues.put(AccountEntry.COLUMN_CURRENCY, currencyCode); + contentValues.put(AccountEntry.COLUMN_PLACEHOLDER, 0); + contentValues.put(AccountEntry.COLUMN_HIDDEN, GnuCashApplication.isDoubleEntryEnabled() ? 0 : 1); + contentValues.putNull(AccountEntry.COLUMN_COLOR_CODE); + contentValues.put(AccountEntry.COLUMN_FAVORITE, 0); + contentValues.put(AccountEntry.COLUMN_FULL_NAME, imbalanceAccountName); + contentValues.put(AccountEntry.COLUMN_PARENT_ACCOUNT_UID, rootAccountUID); + contentValues.putNull(AccountEntry.COLUMN_DEFAULT_TRANSFER_ACCOUNT_UID); + db.insert(AccountEntry.TABLE_NAME, null, contentValues); + } + } finally { + c.close(); + } String TransactionUID = cursor.getString(cursor.getColumnIndexOrThrow("trans_uid")); contentValues.clear(); - contentValues.put(DatabaseSchema.CommonColumns.COLUMN_UID, UUID.randomUUID().toString().replaceAll("-", "")); + contentValues.put(DatabaseSchema.CommonColumns.COLUMN_UID, MigrationHelper.generateUUID()); contentValues.put(DatabaseSchema.CommonColumns.COLUMN_CREATED_AT, timestamp); contentValues.put(SplitEntry.COLUMN_AMOUNT, decimalImbalance.abs().toPlainString()); - contentValues.put(SplitEntry.COLUMN_TYPE, decimalImbalance.compareTo(BigDecimal.ZERO) > 0 ? "DEBIT" : "CREDIT"); + contentValues.put(SplitEntry.COLUMN_TYPE, decimalImbalance.compareTo(BigDecimal.ZERO) < 0 ? "DEBIT" : "CREDIT"); contentValues.put(SplitEntry.COLUMN_MEMO, ""); - contentValues.put(SplitEntry.COLUMN_ACCOUNT_UID, accountsDbAdapter.getOrCreateImbalanceAccountUID(Currency.getInstance(currencyCode))); + contentValues.put(SplitEntry.COLUMN_ACCOUNT_UID, imbalanceAccountUID); contentValues.put(SplitEntry.COLUMN_TRANSACTION_UID, TransactionUID); db.insert(SplitEntry.TABLE_NAME, null, contentValues); contentValues.clear(); diff --git a/app/src/main/java/org/gnucash/android/db/MigrationHelper.java b/app/src/main/java/org/gnucash/android/db/MigrationHelper.java index 60cabf63b..5b90ebca2 100644 --- a/app/src/main/java/org/gnucash/android/db/MigrationHelper.java +++ b/app/src/main/java/org/gnucash/android/db/MigrationHelper.java @@ -33,6 +33,7 @@ import java.io.IOError; import java.io.IOException; import java.nio.channels.FileChannel; +import java.util.UUID; import static org.gnucash.android.db.DatabaseSchema.AccountEntry; @@ -187,4 +188,9 @@ public void run() { oldExportFolder.delete(); } }; + + public static String generateUUID() + { + return UUID.randomUUID().toString().replaceAll("-", ""); + } } From c46f8a2fdf038002c1f97247afe3a66a464ced7f Mon Sep 17 00:00:00 2001 From: Oleksandr Tyshkovets Date: Sun, 24 May 2015 20:43:34 +0300 Subject: [PATCH 11/16] Code documentation and refactoring --- .../android/ui/chart/BarChartActivity.java | 224 ++++++++---------- 1 file changed, 100 insertions(+), 124 deletions(-) diff --git a/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java b/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java index e91e14601..6e8137d13 100644 --- a/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java +++ b/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java @@ -47,6 +47,7 @@ import org.gnucash.android.model.AccountType; import org.gnucash.android.model.Money; import org.gnucash.android.ui.passcode.PassLockActivity; +import org.joda.time.LocalDate; import org.joda.time.LocalDateTime; import org.joda.time.Months; @@ -54,13 +55,11 @@ import java.util.Arrays; import java.util.Collections; import java.util.Currency; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.Set; /** * Activity used for drawing a bar chart @@ -85,21 +84,16 @@ public class BarChartActivity extends PassLockActivity implements OnChartValueSe Color.parseColor("#fddef8"), Color.parseColor("#fa0e6e"), Color.parseColor("#d9e7b5") }; - private BarChart mChart; private AccountsDbAdapter mAccountsDbAdapter = AccountsDbAdapter.getInstance(); - private boolean mTotalPercentageMode = true; - private boolean mChartDataPresent = true; - private Currency mCurrency; - private Set mLegendLabels; - private Set mLegendColors; + private TextView selectedValueTextView; - private AccountType mAccountType = AccountType.EXPENSE; + private BarChart mChart; - private LocalDateTime mEarliestTransactionDate; - private LocalDateTime mLatestTransactionDate; + private Currency mCurrency; - private Map accountToColorMap = new LinkedHashMap<>(); + private boolean mTotalPercentageMode = true; + private boolean mChartDataPresent = true; @Override protected void onCreate(Bundle savedInstanceState) { @@ -108,6 +102,8 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getSupportActionBar().setTitle(R.string.title_bar_chart); + selectedValueTextView = (TextView) findViewById(R.id.selected_chart_slice); + mCurrency = Currency.getInstance(PreferenceManager.getDefaultSharedPreferences(this) .getString(getString(R.string.key_report_currency), Money.DEFAULT_CURRENCY_CODE)); @@ -115,13 +111,11 @@ protected void onCreate(Bundle savedInstanceState) { ((LinearLayout) findViewById(R.id.bar_chart)).addView(mChart); mChart.setOnChartValueSelectedListener(this); mChart.setDescription(""); + mChart.setDrawValuesForWholeStack(false); mChart.getXAxis().setDrawGridLines(false); mChart.getAxisRight().setEnabled(false); mChart.getAxisLeft().enableGridDashedLine(4.0f, 4.0f, 0); - mChart.setDrawValuesForWholeStack(false); mChart.getAxisLeft().setValueFormatter(new LargeValueFormatter(mCurrency.getSymbol(Locale.getDefault()))); - mChart.getAxisRight().setEnabled(false); - mChart.getLegend().setEnabled(false); mChart.getLegend().setForm(Legend.LegendForm.CIRCLE); mChart.getLegend().setPosition(Legend.LegendPosition.RIGHT_OF_CHART_INSIDE); @@ -130,128 +124,61 @@ protected void onCreate(Bundle savedInstanceState) { /** * Returns a data object that represents a user data of the specified account types - * @param accountTypeList account's types which will be displayed + * @param accountType account's type which will be displayed * @return a {@code BarData} instance that represents a user data */ private BarData getData(AccountType accountType) { -// setEarliestAndLatestDates(accountType); - - TransactionsDbAdapter adapter = TransactionsDbAdapter.getInstance(); - String code = mCurrency.getCurrencyCode(); - LocalDateTime startDate = new LocalDateTime(adapter.getTimestampOfEarliestTransaction(accountType, code)) - .withDayOfMonth(1) - .withMillisOfDay(0); - LocalDateTime endDate = new LocalDateTime(adapter.getTimestampOfLatestTransaction(accountType, code)) - .withDayOfMonth(1) - .withMillisOfDay(0); - Log.d(TAG, accountType + " X-axis star date: " + startDate.toString("dd MM yyyy")); - Log.d(TAG, accountType + " X-axis end date: " + endDate.toString("dd MM yyyy")); -// int months = Months.monthsBetween(mEarliestTransactionDate, mLatestTransactionDate).getMonths(); - - int months = Months.monthsBetween(startDate, endDate).getMonths(); - - List dataSets = new ArrayList<>(); List values = new ArrayList<>(); List labels = new ArrayList<>(); List colors = new ArrayList<>(); + Map accountToColorMap = new LinkedHashMap<>(); List xValues = new ArrayList<>(); - for (int i = 0; i <= months; i++) { - xValues.add(startDate.toString(X_AXIS_PATTERN)); - - long start = startDate.dayOfMonth().withMinimumValue().millisOfDay().withMinimumValue().toDate().getTime(); - long end = startDate.dayOfMonth().withMaximumValue().millisOfDay().withMaximumValue().toDate().getTime(); + LocalDateTime tmpDate = new LocalDateTime(getStartDate(accountType).toDate().getTime()); + for (int i = 0; i <= Months.monthsBetween(getStartDate(accountType), getEndDate(accountType)).getMonths(); i++) { + long start = tmpDate.dayOfMonth().withMinimumValue().millisOfDay().withMinimumValue().toDate().getTime(); + long end = tmpDate.dayOfMonth().withMaximumValue().millisOfDay().withMaximumValue().toDate().getTime(); List stack = new ArrayList<>(); for (Account account : mAccountsDbAdapter.getSimpleAccountList()) { - if (account.getAccountType() == mAccountType + if (account.getAccountType() == accountType && !account.isPlaceholderAccount() && account.getCurrency() == mCurrency) { - float balance = (float) mAccountsDbAdapter.getAccountsBalance( + double balance = mAccountsDbAdapter.getAccountsBalance( Collections.singletonList(account.getUID()), start, end).asDouble(); if (balance != 0) { - if (!accountToColorMap.containsKey(account.getUID())) { Integer color = (account.getColorHexCode() != null) ? Color.parseColor(account.getColorHexCode()) - : COLORS[accountToColorMap.size()]; + : COLORS[accountToColorMap.size() % COLORS.length]; accountToColorMap.put(account.getUID(), color); } - stack.add(balance); + stack.add((float) balance); labels.add(account.getName()); colors.add(accountToColorMap.get(account.getUID())); - Log.i(TAG, mAccountType + startDate.toString(" MMMM yyyy ") + account.getName() - + " = " + stack.get(stack.size() - 1) + ", color = " + colors.get(colors.size() - 1)); + Log.d(TAG, accountType + tmpDate.toString(" MMMM yyyy ") + account.getName() + " = " + stack.get(stack.size() - 1)); } } } - float array[] = new float[stack.size()]; - for (int k = 0; k < stack.size(); k++) { - array[k] = stack.get(k); - } - String stackLabels = labels.subList(labels.size() - stack.size(), labels.size()).toString(); - values.add(new BarEntry(array, i, stackLabels)); + values.add(new BarEntry(floatListToArray(stack), i, stackLabels)); - startDate = startDate.plusMonths(1); - } + xValues.add(tmpDate.toString(X_AXIS_PATTERN)); - mLegendColors = new LinkedHashSet<>(colors); - mLegendLabels = new LinkedHashSet<>(labels); + tmpDate = tmpDate.plusMonths(1); + } BarDataSet set = new BarDataSet(values, ""); set.setStackLabels(labels.toArray(new String[labels.size()])); set.setColors(colors); - dataSets.add(set); if (set.getYValueSum() == 0) { mChartDataPresent = false; return getEmptyData(); } - return new BarData(xValues, dataSets); - } - - /** - * Sets the earliest and latest transaction's dates of the specified account type - * @param accountTypeList account's types which will be processed - */ - private int setEarliestAndLatestDates(AccountType accountType) { - TransactionsDbAdapter adapter = TransactionsDbAdapter.getInstance(); - String code = mCurrency.getCurrencyCode(); - mEarliestTransactionDate = new LocalDateTime(adapter.getTimestampOfEarliestTransaction(accountType, code)) - .withDayOfMonth(1) - .withMillisOfDay(0); - mLatestTransactionDate = new LocalDateTime(adapter.getTimestampOfLatestTransaction(accountType, code)) - .withDayOfMonth(1) - .withMillisOfDay(0); - Log.d(TAG, accountType + " X-axis star date: " + mEarliestTransactionDate.toString("dd MM yyyy")); - Log.d(TAG, accountType + " X-axis end date: " + mLatestTransactionDate.toString("dd MM yyyy")); - int months = Months.monthsBetween(mEarliestTransactionDate, mLatestTransactionDate).getMonths(); - Log.w(TAG, "DIFF: " + months); - return months; - } - - /** - * Returns a map with an account type as key and correspond accounts UIDs as value - * from a specified list of account types - * @param accountTypeList account's types which will be used as keys - * @return a map with an account type as key and correspond accounts UIDs as value - */ - private Map> getAccountTypeToAccountUidMap(List accountTypeList) { - Map> accountMap = new HashMap<>(); - for (AccountType accountType : accountTypeList) { - List accountUIDList = new ArrayList<>(); - for (Account account : mAccountsDbAdapter.getSimpleAccountList()) { - if (account.getAccountType() == accountType - && !account.isPlaceholderAccount() - && account.getCurrency() == mCurrency) { - accountUIDList.add(account.getUID()); - } - accountMap.put(accountType, accountUIDList); - } - } - return accountMap; + mChartDataPresent = true; + return new BarData(xValues, set); } /** @@ -263,13 +190,52 @@ private BarData getEmptyData() { List yValues = new ArrayList<>(); for (int i = 0; i < NO_DATA_BAR_COUNTS; i++) { xValues.add(""); - yValues.add(new BarEntry(i % 2 == 0 ? 5f : 4.5f, i)); + yValues.add(new BarEntry(i + 1, i)); } BarDataSet set = new BarDataSet(yValues, getResources().getString(R.string.label_chart_no_data)); set.setDrawValues(false); set.setColor(NO_DATA_COLOR); - return new BarData(xValues, Collections.singletonList(set)); + return new BarData(xValues, set); + } + + /** + * Returns the start data of x-axis for the specified account type + * @param accountType account type + * @return the start data + */ + private LocalDate getStartDate(AccountType accountType) { + TransactionsDbAdapter adapter = TransactionsDbAdapter.getInstance(); + String code = mCurrency.getCurrencyCode(); + LocalDate startDate = new LocalDate(adapter.getTimestampOfEarliestTransaction(accountType, code)).withDayOfMonth(1); + Log.d(TAG, accountType + " X-axis star date: " + startDate.toString("dd MM yyyy")); + return startDate; + } + + /** + * Returns the end data of x-axis for the specified account type + * @param accountType account type + * @return the end data + */ + private LocalDate getEndDate(AccountType accountType) { + TransactionsDbAdapter adapter = TransactionsDbAdapter.getInstance(); + String code = mCurrency.getCurrencyCode(); + LocalDate endDate = new LocalDate(adapter.getTimestampOfLatestTransaction(accountType, code)).withDayOfMonth(1); + Log.d(TAG, accountType + " X-axis end date: " + endDate.toString("dd MM yyyy")); + return endDate; + } + + /** + * Converts the specified list of floats to an array + * @param list a list of floats + * @return a float array + */ + private float[] floatListToArray(List list) { + float array[] = new float[list.size()]; + for (int i = 0; i < list.size(); i++) { + array[i] = list.get(i); + } + return array; } /** @@ -277,7 +243,7 @@ private BarData getEmptyData() { * account types. */ private void setUpSpinner() { - Spinner spinner = (Spinner) findViewById(R.id.chart_data_spinner); + final Spinner spinner = (Spinner) findViewById(R.id.chart_data_spinner); ArrayAdapter dataAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, Arrays.asList(AccountType.EXPENSE, AccountType.INCOME)); @@ -286,23 +252,8 @@ private void setUpSpinner() { spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView adapterView, View view, int i, long l) { - mAccountType = (AccountType) ((Spinner) findViewById(R.id.chart_data_spinner)).getSelectedItem(); - - ((TextView) findViewById(R.id.selected_chart_slice)).setText(""); - mChart.highlightValues(null); - - mChart.setData(getData(mAccountType)); - - if (!mChartDataPresent) { - mChart.getAxisLeft().setAxisMaxValue(10); - mChart.getAxisLeft().setDrawLabels(false); - mChart.getXAxis().setDrawLabels(false); - mChart.setTouchEnabled(false); - ((TextView) findViewById(R.id.selected_chart_slice)).setText(getResources().getString(R.string.label_chart_no_data)); - } else { - mChart.animateY(ANIMATION_DURATION); - } - mChart.invalidate(); + mChart.setData(getData((AccountType) spinner.getSelectedItem())); + displayChart(); } @Override @@ -311,6 +262,29 @@ public void onNothingSelected(AdapterView adapterView) { }); } + /** + * Displays the stacked bar chart + */ + private void displayChart() { + mChart.highlightValues(null); + mChart.getLegend().setEnabled(false); + + mChart.getAxisLeft().setDrawLabels(mChartDataPresent); + mChart.getXAxis().setDrawLabels(mChartDataPresent); + mChart.setTouchEnabled(mChartDataPresent); + + selectedValueTextView.setText(""); + + if (mChartDataPresent) { + mChart.getAxisLeft().resetAxisMaxValue(); + mChart.animateY(ANIMATION_DURATION); + } else { + selectedValueTextView.setText(getResources().getString(R.string.label_chart_no_data)); + } + + mChart.invalidate(); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getSupportMenuInflater().inflate(R.menu.chart_actions, menu); @@ -335,8 +309,11 @@ public boolean onOptionsItemSelected(MenuItem item) { // workaround for buggy legend Legend legend = mChart.getLegend(); legend.setEnabled(!mChart.getLegend().isEnabled()); - legend.setLabels(mLegendLabels.toArray(new String[mLegendLabels.size()])); - legend.setColors(Arrays.asList(mLegendColors.toArray(new Integer[mLegendLabels.size()]))); + BarDataSet dataSet = mChart.getData().getDataSetByIndex(0); + LinkedHashSet labels = new LinkedHashSet<>(Arrays.asList(dataSet.getStackLabels())); + legend.setLabels(labels.toArray(new String[labels.size()])); + LinkedHashSet colors = new LinkedHashSet<>(dataSet.getColors()); + legend.setColors(Arrays.asList(colors.toArray(new Integer[colors.size()]))); mChart.invalidate(); break; @@ -363,12 +340,11 @@ public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { + stackLabels.substring(1, stackLabels.length() - 1).split(",")[h.getStackIndex()]; double value = entry.getVals()[ h.getStackIndex() == -1 ? 0 : h.getStackIndex() ]; double sum = mTotalPercentageMode ? mChart.getData().getDataSetByIndex(dataSetIndex).getYValueSum() : entry.getVal(); - ((TextView) findViewById(R.id.selected_chart_slice)) - .setText(String.format(SELECTED_VALUE_PATTERN, label, value, value / sum * 100)); + selectedValueTextView.setText(String.format(SELECTED_VALUE_PATTERN, label, value, value / sum * 100)); } @Override public void onNothingSelected() { - ((TextView) findViewById(R.id.selected_chart_slice)).setText(""); + selectedValueTextView.setText(""); } } From ecfeeef01688a07a319cc346f740677b01173f87 Mon Sep 17 00:00:00 2001 From: Oleksandr Tyshkovets Date: Sun, 24 May 2015 20:47:29 +0300 Subject: [PATCH 12/16] Fix for animation --- .../main/java/org/gnucash/android/ui/chart/BarChartActivity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java b/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java index 6e8137d13..750a32886 100644 --- a/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java +++ b/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java @@ -279,6 +279,7 @@ private void displayChart() { mChart.getAxisLeft().resetAxisMaxValue(); mChart.animateY(ANIMATION_DURATION); } else { + mChart.clearAnimation(); selectedValueTextView.setText(getResources().getString(R.string.label_chart_no_data)); } From b6643e8af1c5a5b89531e3085225e37768c5c04c Mon Sep 17 00:00:00 2001 From: Ngewi Fet Date: Sun, 24 May 2015 23:10:27 +0200 Subject: [PATCH 13/16] Updated version for beta 5 release --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 28a494651..a59dddabf 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,7 +6,7 @@ apply plugin: 'crashlytics' def versionMajor = 1 def versionMinor = 6 def versionPatch = 0 -def versionBuild = 4 +def versionBuild = 5 def buildTime() { def df = new SimpleDateFormat("yyyyMMdd") From a4072c785f6f9b7d857dff43dd1fbacdc544c90e Mon Sep 17 00:00:00 2001 From: Oleksandr Tyshkovets Date: Mon, 25 May 2015 17:41:50 +0300 Subject: [PATCH 14/16] Use account color in the bar chart --- .../android/ui/chart/BarChartActivity.java | 18 +++++++++++++----- app/src/main/res/values-de/strings.xml | 2 +- app/src/main/res/values-el/strings.xml | 2 +- app/src/main/res/values-es-rMX/strings.xml | 2 +- app/src/main/res/values-es/strings.xml | 2 +- app/src/main/res/values-fr/strings.xml | 2 +- app/src/main/res/values-hu/strings.xml | 2 +- app/src/main/res/values-it/strings.xml | 2 +- app/src/main/res/values-nl/strings.xml | 2 +- app/src/main/res/values-pt-rBR/strings.xml | 2 +- app/src/main/res/values-zh/strings.xml | 2 +- app/src/main/res/values/strings.xml | 2 +- 12 files changed, 24 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java b/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java index 750a32886..01fc8b277 100644 --- a/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java +++ b/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java @@ -92,6 +92,7 @@ public class BarChartActivity extends PassLockActivity implements OnChartValueSe private Currency mCurrency; + private boolean mUseAccountColor = true; private boolean mTotalPercentageMode = true; private boolean mChartDataPresent = true; @@ -104,6 +105,9 @@ protected void onCreate(Bundle savedInstanceState) { selectedValueTextView = (TextView) findViewById(R.id.selected_chart_slice); + mUseAccountColor = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()) + .getBoolean(getString(R.string.key_use_account_color), false); + mCurrency = Currency.getInstance(PreferenceManager.getDefaultSharedPreferences(this) .getString(getString(R.string.key_report_currency), Money.DEFAULT_CURRENCY_CODE)); @@ -147,9 +151,14 @@ private BarData getData(AccountType accountType) { Collections.singletonList(account.getUID()), start, end).asDouble(); if (balance != 0) { if (!accountToColorMap.containsKey(account.getUID())) { - Integer color = (account.getColorHexCode() != null) - ? Color.parseColor(account.getColorHexCode()) - : COLORS[accountToColorMap.size() % COLORS.length]; + Integer color; + if (mUseAccountColor) { + color = (account.getColorHexCode() != null) + ? Color.parseColor(account.getColorHexCode()) + : COLORS[accountToColorMap.size() % COLORS.length]; + } else { + color = COLORS[accountToColorMap.size() % COLORS.length]; + } accountToColorMap.put(account.getUID(), color); } @@ -162,7 +171,7 @@ private BarData getData(AccountType accountType) { } String stackLabels = labels.subList(labels.size() - stack.size(), labels.size()).toString(); - values.add(new BarEntry(floatListToArray(stack), i, stackLabels)); + values.add(new BarEntry(floatListToArray(stack), i, stackLabels)); xValues.add(tmpDate.toString(X_AXIS_PATTERN)); @@ -276,7 +285,6 @@ private void displayChart() { selectedValueTextView.setText(""); if (mChartDataPresent) { - mChart.getAxisLeft().resetAxisMaxValue(); mChart.animateY(ANIMATION_DURATION); } else { mChart.clearAnimation(); diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 7b21687a6..c9a6b399b 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -490,7 +490,7 @@ No user-identifiable information will be collected as part of this process!Reports Select currency Account color in reports - Use account color in the pie chart + Use account color in the bar/pie chart Please confirm your passcode Enter your new passcode Enter your old passcode diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 05aaf65e1..e503637a1 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -509,7 +509,7 @@ No user-identifiable information will be collected as part of this process! Reports Select currency Account color in reports - Use account color in the pie chart + Use account color in the bar/pie chart Please confirm your passcode Enter your new passcode Enter your old passcode diff --git a/app/src/main/res/values-es-rMX/strings.xml b/app/src/main/res/values-es-rMX/strings.xml index 92d04e0f5..67aa4efad 100644 --- a/app/src/main/res/values-es-rMX/strings.xml +++ b/app/src/main/res/values-es-rMX/strings.xml @@ -494,7 +494,7 @@ No user-identifiable information will be collected as part of this process! Reports Select currency Account color in reports - Use account color in the pie chart + Use account color in the bar/pie chart Please confirm your passcode Enter your new passcode Enter your old passcode diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 961d8d9c9..2ff2c2a05 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -491,7 +491,7 @@ Este proceso solo recoge información que no permite identificar al usuario< Reports Select currency Account color in reports - Use account color in the pie chart + Use account color in the bar/pie chart Confirme su contraseña Enter your new passcode Enter your old passcode diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 38c9ca45d..1eed10dcb 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -491,7 +491,7 @@ Aucune information permettant d\'identifier l\'utilisateur ne sera recueillis da Rapports Sélectionnez la monnaie Couleur du compte dans les rapports - utiliser la couleur du compte dans le diagramme circulaire + utiliser la couleur du compte dans le diagramme bandes/circulaire Veuillez confirmer vorte code Entrez votre nouveau code Entrez votre ancien mot de passe diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index 7f732dbf2..eba5056a0 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -495,7 +495,7 @@ No user-identifiable information will be collected as part of this process! Reports Select currency Account color in reports - Use account color in the pie chart + Use account color in the bar/pie chart Please confirm your passcode Enter your new passcode Enter your old passcode diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index a2529151a..7cb3f3aa4 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -495,7 +495,7 @@ No user-identifiable information will be collected as part of this process! Reports Select currency Account color in reports - Use account color in the pie chart + Use account color in the bar/pie chart Please confirm your passcode Enter your new passcode Enter your old passcode diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 532626776..ac4f421a3 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -496,7 +496,7 @@ No user-identifiable information will be collected as part of this process! Reports Select currency Account color in reports - Use account color in the pie chart + Use account color in the bar/pie chart Please confirm your passcode Enter your new passcode Enter your old passcode diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index afb38b01f..8714b7c22 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -497,7 +497,7 @@ Nenhuma informação de identificação do usuário será coletada neste proces Relatórios Selecionar moeda Cor de contas nos relatórios - Utilizar cor de contas no gráfico de pizza + Utilizar cor de contas no gráfico de barras/pizza Backups agendados Exportações agendadas Sem exportações agendadas para mostrar diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 7ccfacb65..bc94f448b 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -492,7 +492,7 @@ No user-identifiable information will be collected as part of this process! Reports Select currency Account color in reports - Use account color in the pie chart + Use account color in the bar/pie chart 请再输入一次 Enter your new passcode Enter your old passcode diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3545d22db..a6391dc3e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -437,7 +437,7 @@ Report Preferences Select currency Account color in reports - Use account color in the pie chart + Use account color in the bar/pie chart Reports Order by size Toggle legend From 4eda8cb738d162711491e0d15c1eb018ace73abc Mon Sep 17 00:00:00 2001 From: Oleksandr Tyshkovets Date: Tue, 26 May 2015 19:00:26 +0300 Subject: [PATCH 15/16] Fix for empty bars --- .../org/gnucash/android/ui/chart/BarChartActivity.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java b/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java index 01fc8b277..b66478969 100644 --- a/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java +++ b/app/src/main/java/org/gnucash/android/ui/chart/BarChartActivity.java @@ -342,12 +342,13 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override public void onValueSelected(Entry e, int dataSetIndex, Highlight h) { - if (e == null) return; + if (e == null || ((BarEntry) e).getVals().length == 0) return; BarEntry entry = (BarEntry) e; + int index = h.getStackIndex() == -1 ? 0 : h.getStackIndex(); String stackLabels = entry.getData().toString(); String label = mChart.getData().getXVals().get(entry.getXIndex()) + ", " - + stackLabels.substring(1, stackLabels.length() - 1).split(",")[h.getStackIndex()]; - double value = entry.getVals()[ h.getStackIndex() == -1 ? 0 : h.getStackIndex() ]; + + stackLabels.substring(1, stackLabels.length() - 1).split(",")[index]; + double value = entry.getVals()[index]; double sum = mTotalPercentageMode ? mChart.getData().getDataSetByIndex(dataSetIndex).getYValueSum() : entry.getVal(); selectedValueTextView.setText(String.format(SELECTED_VALUE_PATTERN, label, value, value / sum * 100)); } From 18a35b5efddd06f9f1de3f5ddd976ea9090e1274 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=80lex=20Magaz=20Gra=C3=A7a?= Date: Mon, 15 Jun 2015 20:48:54 +0200 Subject: [PATCH 16/16] Fix crash if no application is selected to choose a file to import accounts. Fixes #341 --- .../android/ui/settings/SettingsActivity.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/gnucash/android/ui/settings/SettingsActivity.java b/app/src/main/java/org/gnucash/android/ui/settings/SettingsActivity.java index 5f351e854..a4ef751e5 100644 --- a/app/src/main/java/org/gnucash/android/ui/settings/SettingsActivity.java +++ b/app/src/main/java/org/gnucash/android/ui/settings/SettingsActivity.java @@ -573,12 +573,14 @@ public void onClick(DialogInterface dialog, int which) { public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case AccountsActivity.REQUEST_PICK_ACCOUNTS_FILE: - try { - InputStream accountInputStream = getContentResolver().openInputStream(data.getData()); - new ImportAsyncTask(this).execute(accountInputStream); - } catch (FileNotFoundException e) { - Crashlytics.logException(e); - Toast.makeText(this, R.string.toast_error_importing_accounts, Toast.LENGTH_SHORT).show(); + if (resultCode == Activity.RESULT_OK && data != null) { + try { + InputStream accountInputStream = getContentResolver().openInputStream(data.getData()); + new ImportAsyncTask(this).execute(accountInputStream); + } catch (FileNotFoundException e) { + Crashlytics.logException(e); + Toast.makeText(this, R.string.toast_error_importing_accounts, Toast.LENGTH_SHORT).show(); + } } break; case PasscodePreferenceFragment.PASSCODE_REQUEST_CODE: