testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
+ implementation 'org.jetbrains:annotations:15.0'
}
Resources.Theme theme = getTheme();
Globals.table_row_odd_bg = rm.getColor(R.color.table_row_odd_bg, theme);
Globals.table_row_even_bg = rm.getColor(R.color.table_row_even_bg, theme);
+ Globals.primaryDark = rm.getColor(R.color.design_default_color_primary_dark, theme);
+ Globals.defaultTextColor = rm.getColor(android.R.color.tab_indicator_text, theme);
}
else {
Globals.table_row_odd_bg = rm.getColor(R.color.table_row_odd_bg);
Globals.table_row_even_bg = rm.getColor(R.color.table_row_even_bg);
+ Globals.primaryDark = rm.getColor(R.color.design_default_color_primary_dark);
+ Globals.defaultTextColor = rm.getColor(android.R.color.tab_indicator_text);
}
}
}
package net.ktnx.mobileledger;
import android.arch.lifecycle.ViewModelProviders;
+import android.database.MatrixCursor;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.AdapterView;
+import android.widget.AutoCompleteTextView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
public class TransactionListActivity extends AppCompatActivity {
public TransactionListViewModel model;
+ private View bTransactionListCancelDownload;
+ private MenuItem menuTransactionListFilter;
+ private View vAccountFilter;
private SwipeRefreshLayout swiper;
private RecyclerView root;
private ProgressBar progressBar;
private TextView tvLastUpdate;
private TransactionListAdapter modelAdapter;
private RetrieveTransactionsTask retrieveTransactionsTask;
+ private AutoCompleteTextView accNameFilter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
swiper.setColorSchemeResources(R.color.colorPrimary, R.color.colorAccent);
+ vAccountFilter = findViewById(R.id.transaction_list_account_name_filter);
+ accNameFilter = findViewById(R.id.transaction_filter_account_name);
+ bTransactionListCancelDownload = findViewById(R.id.transaction_list_cancel_download);
+
+ MLDB.hook_autocompletion_adapter(this, accNameFilter, "accounts", "name");
+ TransactionListActivity me = this;
+ accNameFilter.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ Log.d("tmp", "direct onItemClick");
+ model.reloadTransactions(me);
+ MatrixCursor mc = (MatrixCursor) parent.getItemAtPosition(position);
+ modelAdapter.setBoldAccountName(mc.getString(1));
+ modelAdapter.notifyDataSetChanged();
+ me.hideSoftKeyboard();
+ }
+ });
+
updateLastUpdateText();
long last_update = MLDB.get_option_value(this, MLDB.OPT_TRANSACTION_LIST_STAMP, 0L);
Log.d("transactions", String.format("Last update = %d", last_update));
PreferenceManager.getDefaultSharedPreferences(this));
retrieveTransactionsTask.execute(params);
- findViewById(R.id.transaction_list_cancel_download).setEnabled(true);
+ bTransactionListCancelDownload.setEnabled(true);
}
public void onRetrieveStart() {
else progressBar.setProgress(0);
progressLayout.setVisibility(View.VISIBLE);
}
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.transaction_list, menu);
+ menuTransactionListFilter = menu.findItem(R.id.menu_transaction_list_filter);
+ if ((menuTransactionListFilter == null)) throw new AssertionError();
+
+ return true;
+ }
public void onRetrieveProgress(RetrieveTransactionsTask.Progress progress) {
if ((progress.getTotal() == RetrieveTransactionsTask.Progress.INDETERMINATE) ||
(progress.getTotal() == 0))
}
}
}
+ public void onClearAccountNameClick(View view) {
+ vAccountFilter.setVisibility(View.GONE);
+ menuTransactionListFilter.setVisible(true);
+ accNameFilter.setText(null);
+ model.reloadTransactions(this);
+ modelAdapter.resetBoldAccountName();
+ modelAdapter.notifyDataSetChanged();
+ hideSoftKeyboard();
+ }
+ private void hideSoftKeyboard() {
+ // hide the keyboard
+ View v = getCurrentFocus();
+ if (v != null) {
+ InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
+ }
+ }
+ public void onShowFilterClick(MenuItem menuItem) {
+ vAccountFilter.setVisibility(View.VISIBLE);
+ menuTransactionListFilter.setVisible(false);
+ accNameFilter.requestFocus();
+ InputMethodManager imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
+ imm.showSoftInput(accNameFilter, 0);
+ }
public void onStopTransactionRefreshClick(View view) {
Log.d("interactive", "Cancelling transactions refresh");
if (retrieveTransactionsTask != null) retrieveTransactionsTask.cancel(false);
- findViewById(R.id.transaction_list_cancel_download).setEnabled(false);
+ bTransactionListCancelDownload.setEnabled(false);
}
}
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
+import android.graphics.Typeface;
import android.support.annotation.NonNull;
import android.support.constraint.ConstraintLayout;
import android.support.v7.widget.AppCompatTextView;
class TransactionListAdapter
extends RecyclerView.Adapter<TransactionListAdapter.TransactionRowHolder> {
TransactionListViewModel model;
+ private String boldAccountName;
public TransactionListAdapter(TransactionListViewModel model) {
this.model = model;
}
row.setOrientation(LinearLayout.HORIZONTAL);
row.setPaddingRelative(dp2px(ctx, 8), 0, 0, 0);
accName = new AppCompatTextView(ctx);
- accName.setLayoutParams(new LinearLayout.LayoutParams(0,
- LinearLayout.LayoutParams.WRAP_CONTENT, 5f));
+ accName.setLayoutParams(
+ new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT,
+ 5f));
accName.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START);
row.addView(accName);
accAmount = new AppCompatTextView(ctx);
}
accName.setText(acc.getAccountName());
accAmount.setText(acc.toString());
+
+ if ((boldAccountName != null) && boldAccountName.equals(acc.getAccountName())) {
+ accName.setTypeface(null, Typeface.BOLD);
+ accAmount.setTypeface(null, Typeface.BOLD);
+ accName.setTextColor(Globals.primaryDark);
+ accAmount.setTextColor(Globals.primaryDark);
+ }
+ else {
+ accName.setTypeface(null, Typeface.NORMAL);
+ accAmount.setTypeface(null, Typeface.NORMAL);
+ accName.setTextColor(Globals.defaultTextColor);
+ accAmount.setTextColor(Globals.defaultTextColor);
+ }
+
}
if (holder.tableAccounts.getChildCount() > rowIndex) {
holder.tableAccounts
}
@Override
- public int getItemCount()
- {
+ public int getItemCount() {
return model.getTransactionCount();
}
+ public void setBoldAccountName(String boldAccountName) {
+ this.boldAccountName = boldAccountName;
+ }
+ public void resetBoldAccountName() {
+ this.boldAccountName = null;
+ }
class TransactionRowHolder extends RecyclerView.ViewHolder {
TextView tvDescription, tvDate;
LinearLayout tableAccounts;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
+import android.view.View;
+import android.widget.AutoCompleteTextView;
+import net.ktnx.mobileledger.R;
+import net.ktnx.mobileledger.TransactionListActivity;
import net.ktnx.mobileledger.model.LedgerTransaction;
import net.ktnx.mobileledger.utils.MLDB;
public void reloadTransactions(Context context) {
ArrayList<LedgerTransaction> newList = new ArrayList<>();
- String sql = "SELECT id FROM transactions ORDER BY date desc, id desc";
+ TransactionListActivity act = (TransactionListActivity) context;
+ boolean hasFilter =
+ act.findViewById(R.id.transaction_list_account_name_filter).getVisibility() ==
+ View.VISIBLE;
+ String sql;
+ String[] params;
+
+ sql = "SELECT id FROM transactions ORDER BY date desc, id desc";
+ params = null;
+
+ if (hasFilter) {
+ String filterAccName = String.valueOf(
+ ((AutoCompleteTextView) act.findViewById(R.id.transaction_filter_account_name))
+ .getText());
+
+ if (!filterAccName.isEmpty()) {
+ sql = "SELECT distinct tr.id from transactions tr JOIN transaction_accounts ta " +
+ "ON ta.transaction_id=tr.id WHERE ta.account_name LIKE ?||'%' AND ta" +
+ ".amount <> 0 ORDER BY tr.date desc, tr.id desc";
+ params = new String[]{filterAccName};
+ }
+ }
+
+ Log.d("tmp", sql);
try (SQLiteDatabase db = MLDB.getReadableDatabase(context)) {
- try (Cursor cursor = db.rawQuery(sql, null)) {
+ try (Cursor cursor = db.rawQuery(sql, params)) {
while (cursor.moveToNext()) {
newList.add(new LedgerTransaction(cursor.getInt(0)));
}
public static int table_row_even_bg;
@ColorInt
public static int table_row_odd_bg;
+ @ColorInt
+ public static int primaryDark, defaultTextColor;
}
\ No newline at end of file
--- /dev/null
+<!--
+ ~ Copyright Google Inc.
+ ~
+ ~ Licensed under the Apache License, version 2.0 ("the License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the license at:
+ ~
+ ~ https://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distribution under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissionsand
+ ~ limitations under the License.
+ -->
+
+<vector android:height="24dp" android:tint="#EEEEEE"
+ android:viewportHeight="24.0" android:viewportWidth="24.0"
+ android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
+ <path android:fillColor="#FF000000" android:pathData="M10,18h4v-2h-4v2zM3,6v2h18L21,6L3,6zM6,13h12v-2L6,11v2z"/>
+</vector>
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
+ <LinearLayout
+ android:id="@+id/transaction_list_account_name_filter"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal"
+ android:visibility="gone">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Account filter" />
+
+ <AutoCompleteTextView
+ android:id="@+id/transaction_filter_account_name"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+
+ <TextView
+ android:id="@+id/textView3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:background="@drawable/ic_clear_black_24dp"
+ android:clickable="true"
+ android:onClick="onClearAccountNameClick" />
+
+ </LinearLayout>
+
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright © 2018 Damyan Ivanov.
+ ~ This file is part of Mobile-Ledger.
+ ~ Mobile-Ledger is free software: you can distribute it and/or modify it
+ ~ under the term of the GNU General Public License as published by
+ ~ the Free Software Foundation, either version 3 of the License, or
+ ~ (at your opinion), any later version.
+ ~
+ ~ Mobile-Ledger 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 terms for details.
+ ~
+ ~ You should have received a copy of the GNU General Public License
+ ~ along with Mobile-Ledger. If not, see <https://www.gnu.org/licenses/>.
+ -->
+
+<menu xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item
+ android:id="@+id/menu_transaction_list_filter"
+ android:icon="@drawable/ic_filter_list_white_24dp"
+ android:onClick="onShowFilterClick"
+ android:title="Filter"
+ app:showAsAction="always" />
+</menu>
\ No newline at end of file