import android.database.sqlite.SQLiteDatabase;
import android.util.Log;
-import androidx.room.Room;
-
-import net.ktnx.mobileledger.db.DB;
import net.ktnx.mobileledger.model.Data;
import net.ktnx.mobileledger.ui.profiles.ProfileDetailModel;
import net.ktnx.mobileledger.utils.Globals;
private static ProfileDetailModel profileModel;
private MobileLedgerDatabase dbHelper;
private boolean monthNamesPrepared = false;
- private DB roomDatabase;
public static SQLiteDatabase getDatabase() {
if (instance == null)
throw new RuntimeException("Application not created yet");
return instance.getDB();
}
- public static DB getRoomDB() {
- if (instance == null)
- throw new RuntimeException("Application not created yet");
-
- return instance.getRoomDatabase();
- }
- public DB getRoomDatabase(){
- return roomDatabase;
- }
public static void prepareMonthNames() {
instance.prepareMonthNames(false);
}
Logger.debug("flow", "App onCreate()");
instance = this;
super.onCreate();
- roomDatabase = Room.databaseBuilder(this, DB.class, MobileLedgerDatabase.DB_NAME)
- .build();
Data.refreshCurrencyData(Locale.getDefault());
Authenticator.setDefault(new Authenticator() {
@Override
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
+import androidx.room.Transaction;
import androidx.room.Update;
import net.ktnx.mobileledger.db.PatternHeader;
+import net.ktnx.mobileledger.db.PatternWithAccounts;
import java.util.List;
@Query("SELECT * FROM patterns WHERE id = :id")
LiveData<PatternHeader> getPattern(Long id);
-// not useful for now
-// @Transaction
-// @Query("SELECT * FROM patterns")
-// List<PatternWithAccounts> getPatternsWithAccounts();
+ @Transaction
+ @Query("SELECT * FROM patterns WHERE id = :id")
+ LiveData<PatternWithAccounts> getPatternWithAccounts(Long id);
}
package net.ktnx.mobileledger.db;
import androidx.room.Database;
+import androidx.room.Room;
import androidx.room.RoomDatabase;
+import net.ktnx.mobileledger.App;
import net.ktnx.mobileledger.dao.CurrencyDAO;
import net.ktnx.mobileledger.dao.PatternAccountDAO;
import net.ktnx.mobileledger.dao.PatternHeaderDAO;
+import net.ktnx.mobileledger.utils.MobileLedgerDatabase;
@Database(version = 51, entities = {PatternHeader.class, PatternAccount.class, Currency.class})
abstract public class DB extends RoomDatabase {
+ private static DB instance;
+ public static DB get() {
+ if (instance != null)
+ return instance;
+ synchronized (DB.class) {
+ if (instance != null)
+ return instance;
+
+ return instance =
+ Room.databaseBuilder(App.instance, DB.class, MobileLedgerDatabase.DB_NAME)
+ .build();
+ }
+ }
public abstract PatternHeaderDAO getPatternDAO();
public abstract PatternAccountDAO getPatternAccountDAO();
public abstract CurrencyDAO getCurrencyDAO();
public void setPosition(@NonNull Long position) {
this.position = position;
}
+ public void setPosition(int position) {
+ this.position = (long) position;
+ }
public Integer getAccountNameMatchGroup() {
return accountNameMatchGroup;
}
package net.ktnx.mobileledger.db;
import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.Index;
import androidx.room.PrimaryKey;
+import net.ktnx.mobileledger.utils.Misc;
+
import org.jetbrains.annotations.NotNull;
@Entity(tableName = "patterns",
public void setDateDayMatchGroup(Integer dateDayMatchGroup) {
this.dateDayMatchGroup = dateDayMatchGroup;
}
+ @Override
+ public boolean equals(@Nullable Object obj) {
+ if (obj == null)
+ return false;
+ if (!(obj instanceof PatternHeader))
+ return false;
+
+ PatternHeader o = (PatternHeader) obj;
+
+ return Misc.equalLongs(id, o.id) && Misc.equalStrings(name, o.name) &&
+ Misc.equalStrings(regularExpression, o.regularExpression) &&
+ Misc.equalStrings(transactionDescription, o.transactionDescription) &&
+ Misc.equalStrings(transactionComment, o.transactionComment) &&
+ Misc.equalIntegers(transactionDescriptionMatchGroup,
+ o.transactionDescriptionMatchGroup) &&
+ Misc.equalIntegers(transactionCommentMatchGroup, o.transactionCommentMatchGroup) &&
+ Misc.equalIntegers(dateDay, o.dateDay) &&
+ Misc.equalIntegers(dateDayMatchGroup, o.dateDayMatchGroup) &&
+ Misc.equalIntegers(dateMonth, o.dateMonth) &&
+ Misc.equalIntegers(dateMonthMatchGroup, o.dateMonthMatchGroup) &&
+ Misc.equalIntegers(dateYear, o.dateYear) &&
+ Misc.equalIntegers(dateYearMatchGroup, o.dateYearMatchGroup);
+ }
}
--- /dev/null
+/*
+ * Copyright © 2021 Damyan Ivanov.
+ * This file is part of MoLe.
+ * MoLe 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.
+ *
+ * MoLe 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 MoLe. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package net.ktnx.mobileledger.db;
+
+import androidx.room.Embedded;
+import androidx.room.Relation;
+
+import java.util.List;
+
+public class PatternWithAccounts {
+ @Embedded
+ public PatternHeader header;
+ @Relation(parentColumn = "id", entityColumn = "pattern_id")
+ public List<PatternAccount> accounts;
+
+ public Long getId() {
+ return header.getId();
+ }
+}
abstract public class PatternDetailsItem {
private final Type type;
- protected long id;
- protected long position;
+ protected Long id;
+ protected Long position;
- protected PatternDetailsItem(Type type, long id, long position) {
+ protected PatternDetailsItem(Type type) {
this.type = type;
- this.id = (id <= 0) ? -position - 2 : id;
- this.position = position;
}
@Contract(" -> new")
public static @NotNull PatternDetailsItem.Header createHeader() {
public static @NotNull PatternDetailsItem.Header createHeader(Header origin) {
return new Header(origin);
}
- @Contract("_ -> new")
- public static @NotNull PatternDetailsItem.AccountRow createAccountRow(long position) {
- return new AccountRow(-1, position);
+ @Contract("-> new")
+ public static @NotNull PatternDetailsItem.AccountRow createAccountRow() {
+ return new AccountRow();
}
public static PatternDetailsItem fromRoomObject(PatternBase p) {
if (p instanceof PatternHeader) {
PatternHeader ph = (PatternHeader) p;
Header header = createHeader();
+ header.setId(ph.getId());
header.setName(ph.getName());
header.setPattern(ph.getRegularExpression());
- header.setTestText(null);
+ header.setTestText(ph.getTestText());
header.setTransactionDescription(ph.getTransactionDescription());
header.setTransactionComment(ph.getTransactionComment());
header.setDateDayMatchGroup(ph.getDateDayMatchGroup());
}
else if (p instanceof PatternAccount) {
PatternAccount pa = (PatternAccount) p;
- AccountRow acc = createAccountRow(pa.getPosition());
+ AccountRow acc = createAccountRow();
+ acc.setId(pa.getId());
- if (Misc.emptyIsNull(pa.getAccountName()) != null)
- acc.setAccountName(pa.getAccountName());
+ if (pa.getAccountNameMatchGroup() == null)
+ acc.setAccountName(Misc.nullIsEmpty(pa.getAccountName()));
else
acc.setAccountNameMatchGroup(pa.getAccountNameMatchGroup());
- if (Misc.emptyIsNull(pa.getAccountComment()) == null)
- acc.setAccountCommentMatchGroup(pa.getAccountCommentMatchGroup());
+ if (pa.getAccountCommentMatchGroup() == null)
+ acc.setAccountComment(Misc.nullIsEmpty(pa.getAccountComment()));
else
- acc.setAccountComment(pa.getAccountComment());
+ acc.setAccountCommentMatchGroup(pa.getAccountCommentMatchGroup());
- if (pa.getCurrency() == null) {
- acc.setCurrencyMatchGroup(pa.getCurrencyMatchGroup());
- }
- else {
- acc.setCurrency(Currency.loadById(pa.getCurrency()));
+ if (pa.getCurrencyMatchGroup() == null) {
+ final Integer currencyId = pa.getCurrency();
+ if (currencyId != null && currencyId > 0)
+ acc.setCurrency(Currency.loadById(currencyId));
}
+ else
+ acc.setCurrencyMatchGroup(pa.getCurrencyMatchGroup());
- if (pa.getAmount() == null)
- acc.setAmountMatchGroup(pa.getAmountMatchGroup());
+ final Integer amountMatchGroup = pa.getAmountMatchGroup();
+ if (amountMatchGroup != null && amountMatchGroup > 0)
+ acc.setAmountMatchGroup(amountMatchGroup);
else
acc.setAmount(pa.getAmount());
public long getId() {
return id;
}
- public void setId(int id) {
+ public void setId(Long id) {
this.id = id;
}
+ public void setId(int id) {
+ this.id = (long) id;
+ }
public long getPosition() {
return position;
}
- public void setPosition(int position) {
+ public void setPosition(Long position) {
this.position = position;
}
abstract public String getProblem(@NonNull Resources r, int patternGroupCount);
matchGroup = origin.matchGroup;
}
@NonNull
- public static PossiblyMatchedValue<Integer> withLiteralInt(int initialValue) {
+ public static PossiblyMatchedValue<Integer> withLiteralInt(Integer initialValue) {
PossiblyMatchedValue<Integer> result = new PossiblyMatchedValue<>();
result.setValue(initialValue);
return result;
}
@NonNull
- public static PossiblyMatchedValue<Float> withLiteralFloat(float initialValue) {
+ public static PossiblyMatchedValue<Float> withLiteralFloat(Float initialValue) {
PossiblyMatchedValue<Float> result = new PossiblyMatchedValue<>();
result.setValue(initialValue);
return result;
}
- public static PossiblyMatchedValue<Short> withLiteralShort(short initialValue) {
+ public static PossiblyMatchedValue<Short> withLiteralShort(Short initialValue) {
PossiblyMatchedValue<Short> result = new PossiblyMatchedValue<>();
result.setValue(initialValue);
return result;
public boolean equals(PossiblyMatchedValue<T> other) {
if (!other.literalValue == literalValue)
return false;
- if (literalValue)
+ if (literalValue) {
+ if (value == null)
+ return other.value == null;
return value.equals(other.value);
+ }
else
return matchGroup == other.matchGroup;
}
private final PossiblyMatchedValue<Float> amount =
PossiblyMatchedValue.withLiteralFloat(0f);
private final PossiblyMatchedValue<Currency> currency = new PossiblyMatchedValue<>();
- private AccountRow(long id, long position) {
- super(Type.ACCOUNT_ITEM, id, position);
+ private AccountRow() {
+ super(Type.ACCOUNT_ITEM);
}
public int getAccountCommentMatchGroup() {
return accountComment.getMatchGroup();
public void setAmountMatchGroup(int group) {
amount.setMatchGroup(group);
}
- public float getAmount() {
+ public Float getAmount() {
return amount.getValue();
}
- public void setAmount(float amount) {
+ public void setAmount(Float amount) {
this.amount.setValue(amount);
}
public String getProblem(@NonNull Resources r, int patternGroupCount) {
accountComment.switchToLiteral();
}
public PatternAccount toDBO(@NonNull Long patternId) {
- PatternAccount result = new PatternAccount((id <= 0L) ? null : id, patternId, position);
+ PatternAccount result = new PatternAccount(id, patternId, position);
if (accountName.hasLiteralValue())
result.setAccountName(accountName.getValue());
PossiblyMatchedValue.withLiteralString("");
private PossiblyMatchedValue<String> transactionComment =
PossiblyMatchedValue.withLiteralString("");
- private PossiblyMatchedValue<Short> dateYear =
- PossiblyMatchedValue.withLiteralShort((short) 0);
- private PossiblyMatchedValue<Short> dateMonth =
- PossiblyMatchedValue.withLiteralShort((short) 0);
- private PossiblyMatchedValue<Short> dateDay =
- PossiblyMatchedValue.withLiteralShort((short) 0);
+ private PossiblyMatchedValue<Integer> dateYear = PossiblyMatchedValue.withLiteralInt(null);
+ private PossiblyMatchedValue<Integer> dateMonth = PossiblyMatchedValue.withLiteralInt(null);
+ private PossiblyMatchedValue<Integer> dateDay = PossiblyMatchedValue.withLiteralInt(null);
private Header() {
- super(Type.HEADER, -1, -1);
+ super(Type.HEADER);
}
public Header(Header origin) {
this();
+ id = origin.id;
name = origin.name;
testText = origin.testText;
setPattern(origin.pattern);
public void setTransactionComment(String transactionComment) {
this.transactionComment.setValue(transactionComment);
}
- public short getDateYear() {
+ public Integer getDateYear() {
return dateYear.getValue();
}
- public void setDateYear(short dateYear) {
+ public void setDateYear(Integer dateYear) {
this.dateYear.setValue(dateYear);
}
- public short getDateMonth() {
+ public Integer getDateMonth() {
return dateMonth.getValue();
}
- public void setDateMonth(short dateMonth) {
+ public void setDateMonth(Integer dateMonth) {
this.dateMonth.setValue(dateMonth);
}
- public short getDateDay() {
+ public Integer getDateDay() {
return dateDay.getValue();
}
- public void setDateDay(short dateDay) {
+ public void setDateDay(Integer dateDay) {
this.dateDay.setValue(dateDay);
}
public int getDateYearMatchGroup() {
}
public void switchToLiteralDateDay() { dateDay.switchToLiteral(); }
public PatternHeader toDBO() {
- PatternHeader result =
- new PatternHeader((id <= 0) ? null : id, name, position, pattern);
+ PatternHeader result = new PatternHeader(id, name, pattern);
+
+ if (Misc.emptyIsNull(testText) != null)
+ result.setTestText(testText);
+
if (transactionDescription.hasLiteralValue())
result.setTransactionDescription(transactionDescription.getValue());
else
else
result.setTransactionCommentMatchGroup(transactionComment.getMatchGroup());
+ if (dateYear.hasLiteralValue())
+ result.setDateYear(dateYear.getValue());
+ else
+ result.setDateYearMatchGroup(dateYear.getMatchGroup());
+
+ if (dateMonth.hasLiteralValue())
+ result.setDateMonth(dateMonth.getValue());
+ else
+ result.setDateMonthMatchGroup(dateMonth.getMatchGroup());
+
+ if (dateDay.hasLiteralValue())
+ result.setDateDay(dateDay.getValue());
+ else
+ result.setDateDayMatchGroup(dateDay.getMatchGroup());
+
return result;
}
}
package net.ktnx.mobileledger.ui.patterns;
-import android.annotation.SuppressLint;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import net.ktnx.mobileledger.ui.PatternDetailSourceSelectorFragment;
import net.ktnx.mobileledger.ui.QRScanAbleFragment;
import net.ktnx.mobileledger.utils.Logger;
+import net.ktnx.mobileledger.utils.Misc;
+
+import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
-import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@NonNull PatternDetailsItem newItem) {
if (oldItem.getType() != newItem.getType())
return false;
- if (oldItem.getType() == PatternDetailsItem.Type.HEADER)
+ if (oldItem.getType()
+ .equals(PatternDetailsItem.Type.HEADER))
return true; // only one header item, ever
// the rest is comparing two account row items
return oldItem.asAccountRowItem()
.getId() == newItem.asAccountRowItem()
.getId();
}
- @SuppressLint("DiffUtilEquals")
@Override
public boolean areContentsTheSame(@NonNull PatternDetailsItem oldItem,
@NonNull PatternDetailsItem newItem) {
- if (oldItem.getType() == PatternDetailsItem.Type.HEADER) {
+ if (oldItem.getType()
+ .equals(PatternDetailsItem.Type.HEADER))
+ {
PatternDetailsItem.Header oldHeader = oldItem.asHeaderItem();
PatternDetailsItem.Header newHeader = newItem.asHeaderItem();
}
@Override
public long getItemId(int position) {
+ // header item is always first and IDs id may duplicate some of the account IDs
if (position == 0)
return -1;
PatternDetailsItem.AccountRow accRow = differ.getCurrentList()
public String getMatchGroupText(int groupNumber) {
PatternDetailsItem.Header header = getHeader();
Pattern p = header.getCompiledPattern();
- if (p == null) return null;
+ if (p == null)
+ return null;
- Matcher m = p.matcher(header.getTestText());
+ final String testText = Misc.nullIsEmpty(header.getTestText());
+ Matcher m = p.matcher(testText);
if (m.matches() && m.groupCount() >= groupNumber)
return m.group(groupNumber);
else
private enum AccDetail {ACCOUNT, COMMENT, AMOUNT}
public abstract static class ViewHolder extends RecyclerView.ViewHolder {
- protected int updateInProgress = 0;
ViewHolder(@NonNull View itemView) {
super(itemView);
}
- protected void startUpdate() {
- updateInProgress++;
- }
- protected void finishUpdate() {
- if (updateInProgress <= 0)
- throw new IllegalStateException(
- "Unexpected updateInProgress value " + updateInProgress);
-
- updateInProgress--;
- }
abstract void bind(PatternDetailsItem item);
}
public class Header extends ViewHolder {
private final PatternDetailsHeaderBinding b;
- private final TextWatcher patternNameWatcher = new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {}
- @Override
- public void afterTextChanged(Editable s) {
- Object tag = b.patternDetailsItemHead.getTag();
- if (tag != null) {
- final PatternDetailsItem.Header header =
- ((PatternDetailsItem) tag).asHeaderItem();
+ public Header(@NonNull PatternDetailsHeaderBinding binding) {
+ super(binding.getRoot());
+ b = binding;
+
+ TextWatcher patternNameWatcher = new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+ @Override
+ public void afterTextChanged(Editable s) {
+ final PatternDetailsItem.Header header = getItem();
Logger.debug(D_PATTERN_UI,
"Storing changed pattern name " + s + "; header=" + header);
header.setName(String.valueOf(s));
}
- }
- };
- private final TextWatcher patternWatcher = new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {}
- @Override
- public void afterTextChanged(Editable s) {
- Object tag = b.patternDetailsItemHead.getTag();
- if (tag != null) {
- final PatternDetailsItem.Header header =
- ((PatternDetailsItem) tag).asHeaderItem();
+ };
+ b.patternName.addTextChangedListener(patternNameWatcher);
+ TextWatcher patternWatcher = new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+ @Override
+ public void afterTextChanged(Editable s) {
+ final PatternDetailsItem.Header header = getItem();
Logger.debug(D_PATTERN_UI,
"Storing changed pattern " + s + "; header=" + header);
header.setPattern(String.valueOf(s));
}
- }
- };
- private final TextWatcher testTextWatcher = new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {}
- @Override
- public void afterTextChanged(Editable s) {
- Object tag = b.patternDetailsItemHead.getTag();
- if (tag != null) {
- final PatternDetailsItem.Header header =
- ((PatternDetailsItem) tag).asHeaderItem();
+ };
+ b.pattern.addTextChangedListener(patternWatcher);
+ TextWatcher testTextWatcher = new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+ @Override
+ public void afterTextChanged(Editable s) {
+ final PatternDetailsItem.Header header = getItem();
Logger.debug(D_PATTERN_UI,
"Storing changed test text " + s + "; header=" + header);
header.setTestText(String.valueOf(s));
}
- }
- };
- private final TextWatcher transactionDescriptionWatcher = new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
+ };
+ b.testText.addTextChangedListener(testTextWatcher);
+ TextWatcher transactionDescriptionWatcher = new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
- @Override
- public void afterTextChanged(Editable s) {
- PatternDetailsItem.Header header = ((PatternDetailsItem) Objects.requireNonNull(
- b.patternDetailsItemHead.getTag())).asHeaderItem();
- Logger.debug(D_PATTERN_UI,
- "Storing changed transaction description " + s + "; header=" + header);
- header.setTransactionDescription(String.valueOf(s));
- }
- };
- private final TextWatcher transactionCommentWatcher = new TextWatcher() {
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+ @Override
+ public void afterTextChanged(Editable s) {
+ final PatternDetailsItem.Header header = getItem();
+ Logger.debug(D_PATTERN_UI,
+ "Storing changed transaction description " + s + "; header=" + header);
+ header.setTransactionDescription(String.valueOf(s));
+ }
+ };
+ b.transactionDescription.addTextChangedListener(transactionDescriptionWatcher);
+ TextWatcher transactionCommentWatcher = new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
- }
- @Override
- public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
- }
- @Override
- public void afterTextChanged(Editable s) {
- PatternDetailsItem.Header header = ((PatternDetailsItem) Objects.requireNonNull(
- b.patternDetailsItemHead.getTag())).asHeaderItem();
- Logger.debug(D_PATTERN_UI,
- "Storing changed transaction description " + s + "; header=" + header);
- header.setTransactionComment(String.valueOf(s));
- }
- };
- public Header(@NonNull PatternDetailsHeaderBinding binding) {
- super(binding.getRoot());
- b = binding;
+ }
+ @Override
+ public void afterTextChanged(Editable s) {
+ final PatternDetailsItem.Header header = getItem();
+ Logger.debug(D_PATTERN_UI,
+ "Storing changed transaction description " + s + "; header=" + header);
+ header.setTransactionComment(String.valueOf(s));
+ }
+ };
+ b.transactionComment.addTextChangedListener(transactionCommentWatcher);
}
- Header(@NonNull View itemView) {
- super(itemView);
- throw new IllegalStateException("Should not be used");
+ @NotNull
+ private PatternDetailsItem.Header getItem() {
+ int pos = getAdapterPosition();
+ return differ.getCurrentList()
+ .get(pos)
+ .asHeaderItem();
}
- private void selectHeaderDetailSource(View v, PatternDetailsItem.Header header,
- HeaderDetail detail) {
+ private void selectHeaderDetailSource(View v, HeaderDetail detail) {
+ PatternDetailsItem.Header header = getItem();
Logger.debug(D_PATTERN_UI, "header is " + header);
PatternDetailSourceSelectorFragment sel =
PatternDetailSourceSelectorFragment.newInstance(1, header.getPattern(),
@Override
void bind(PatternDetailsItem item) {
PatternDetailsItem.Header header = item.asHeaderItem();
- startUpdate();
- try {
- Logger.debug(D_PATTERN_UI, "Binding to header " + header);
- b.patternName.setText(header.getName());
- b.pattern.setText(header.getPattern());
- b.testText.setText(header.getTestText());
-
- if (header.hasLiteralDateYear()) {
- b.patternDetailsYearSource.setText(R.string.pattern_details_source_literal);
- b.patternDetailsDateYear.setText(String.valueOf(header.getDateYear()));
- b.patternDetailsDateYearLayout.setVisibility(View.VISIBLE);
- }
- else {
- b.patternDetailsDateYearLayout.setVisibility(View.GONE);
- b.patternDetailsYearSource.setText(String.format(Locale.US, "Group %d (%s)",
- header.getDateYearMatchGroup(), getMatchGroupText(
- header.getDateYearMatchGroup())));
- }
- b.patternDetailsYearSourceLabel.setOnClickListener(
- v -> selectHeaderDetailSource(v, header, HeaderDetail.DATE_YEAR));
- b.patternDetailsYearSource.setOnClickListener(
- v -> selectHeaderDetailSource(v, header, HeaderDetail.DATE_YEAR));
-
- if (header.hasLiteralDateMonth()) {
- b.patternDetailsMonthSource.setText(R.string.pattern_details_source_literal);
- b.patternDetailsDateMonth.setText(String.valueOf(header.getDateMonth()));
- b.patternDetailsDateMonthLayout.setVisibility(View.VISIBLE);
- }
- else {
- b.patternDetailsDateMonthLayout.setVisibility(View.GONE);
- b.patternDetailsMonthSource.setText(String.format(Locale.US, "Group %d (%s)",
- header.getDateMonthMatchGroup(), getMatchGroupText(
- header.getDateMonthMatchGroup())));
- }
- b.patternDetailsMonthSourceLabel.setOnClickListener(
- v -> selectHeaderDetailSource(v, header, HeaderDetail.DATE_MONTH));
- b.patternDetailsMonthSource.setOnClickListener(
- v -> selectHeaderDetailSource(v, header, HeaderDetail.DATE_MONTH));
-
- if (header.hasLiteralDateDay()) {
- b.patternDetailsDaySource.setText(R.string.pattern_details_source_literal);
- b.patternDetailsDateDay.setText(String.valueOf(header.getDateDay()));
- b.patternDetailsDateDayLayout.setVisibility(View.VISIBLE);
- }
- else {
- b.patternDetailsDateDayLayout.setVisibility(View.GONE);
- b.patternDetailsDaySource.setText(String.format(Locale.US, "Group %d (%s)",
- header.getDateDayMatchGroup(), getMatchGroupText(
- header.getDateDayMatchGroup())));
- }
- b.patternDetailsDaySourceLabel.setOnClickListener(
- v -> selectHeaderDetailSource(v, header, HeaderDetail.DATE_DAY));
- b.patternDetailsDaySource.setOnClickListener(
- v -> selectHeaderDetailSource(v, header, HeaderDetail.DATE_DAY));
-
- if (header.hasLiteralTransactionDescription()) {
- b.patternTransactionDescriptionSource.setText(
- R.string.pattern_details_source_literal);
- b.transactionDescription.setText(header.getTransactionDescription());
- b.transactionDescriptionLayout.setVisibility(View.VISIBLE);
- }
- else {
- b.transactionDescriptionLayout.setVisibility(View.GONE);
- b.patternTransactionDescriptionSource.setText(
- String.format(Locale.US, "Group %d (%s)",
- header.getTransactionDescriptionMatchGroup(), getMatchGroupText(
- header.getTransactionDescriptionMatchGroup())));
+ Logger.debug(D_PATTERN_UI, "Binding to header " + header);
- }
- b.patternTransactionDescriptionSourceLabel.setOnClickListener(
- v -> selectHeaderDetailSource(v, header, HeaderDetail.DESCRIPTION));
- b.patternTransactionDescriptionSource.setOnClickListener(
- v -> selectHeaderDetailSource(v, header, HeaderDetail.DESCRIPTION));
-
- if (header.hasLiteralTransactionComment()) {
- b.patternTransactionCommentSource.setText(
- R.string.pattern_details_source_literal);
- b.transactionComment.setText(header.getTransactionComment());
- b.transactionCommentLayout.setVisibility(View.VISIBLE);
- }
- else {
- b.transactionCommentLayout.setVisibility(View.GONE);
- b.patternTransactionCommentSource.setText(
- String.format(Locale.US, "Group %d (%s)",
- header.getTransactionCommentMatchGroup(),
- getMatchGroupText(header.getTransactionCommentMatchGroup())));
+ b.patternName.setText(header.getName());
+ b.pattern.setText(header.getPattern());
+ b.testText.setText(header.getTestText());
- }
- b.patternTransactionCommentSourceLabel.setOnClickListener(
- v -> selectHeaderDetailSource(v, header, HeaderDetail.COMMENT));
- b.patternTransactionCommentSource.setOnClickListener(
- v -> selectHeaderDetailSource(v, header, HeaderDetail.COMMENT));
-
- b.patternDetailsHeadScanQrButton.setOnClickListener(this::scanTestQR);
-
- final Object prevTag = b.patternDetailsItemHead.getTag();
- if (!(prevTag instanceof PatternDetailsItem)) {
- Logger.debug(D_PATTERN_UI, "Hooked text change listeners");
-
- b.patternName.addTextChangedListener(patternNameWatcher);
- b.pattern.addTextChangedListener(patternWatcher);
- b.testText.addTextChangedListener(testTextWatcher);
- b.transactionDescription.addTextChangedListener(transactionDescriptionWatcher);
- b.transactionComment.addTextChangedListener(transactionCommentWatcher);
- }
+ if (header.hasLiteralDateYear()) {
+ b.patternDetailsYearSource.setText(R.string.pattern_details_source_literal);
+ b.patternDetailsDateYear.setText(String.valueOf(header.getDateYear()));
+ b.patternDetailsDateYearLayout.setVisibility(View.VISIBLE);
+ }
+ else {
+ b.patternDetailsDateYearLayout.setVisibility(View.GONE);
+ b.patternDetailsYearSource.setText(
+ String.format(Locale.US, "Group %d (%s)", header.getDateYearMatchGroup(),
+ getMatchGroupText(header.getDateYearMatchGroup())));
+ }
+ b.patternDetailsYearSourceLabel.setOnClickListener(
+ v -> selectHeaderDetailSource(v, HeaderDetail.DATE_YEAR));
+ b.patternDetailsYearSource.setOnClickListener(
+ v -> selectHeaderDetailSource(v, HeaderDetail.DATE_YEAR));
+
+ if (header.hasLiteralDateMonth()) {
+ b.patternDetailsMonthSource.setText(R.string.pattern_details_source_literal);
+ b.patternDetailsDateMonth.setText(String.valueOf(header.getDateMonth()));
+ b.patternDetailsDateMonthLayout.setVisibility(View.VISIBLE);
+ }
+ else {
+ b.patternDetailsDateMonthLayout.setVisibility(View.GONE);
+ b.patternDetailsMonthSource.setText(
+ String.format(Locale.US, "Group %d (%s)", header.getDateMonthMatchGroup(),
+ getMatchGroupText(header.getDateMonthMatchGroup())));
+ }
+ b.patternDetailsMonthSourceLabel.setOnClickListener(
+ v -> selectHeaderDetailSource(v, HeaderDetail.DATE_MONTH));
+ b.patternDetailsMonthSource.setOnClickListener(
+ v -> selectHeaderDetailSource(v, HeaderDetail.DATE_MONTH));
+
+ if (header.hasLiteralDateDay()) {
+ b.patternDetailsDaySource.setText(R.string.pattern_details_source_literal);
+ b.patternDetailsDateDay.setText(String.valueOf(header.getDateDay()));
+ b.patternDetailsDateDayLayout.setVisibility(View.VISIBLE);
+ }
+ else {
+ b.patternDetailsDateDayLayout.setVisibility(View.GONE);
+ b.patternDetailsDaySource.setText(
+ String.format(Locale.US, "Group %d (%s)", header.getDateDayMatchGroup(),
+ getMatchGroupText(header.getDateDayMatchGroup())));
+ }
+ b.patternDetailsDaySourceLabel.setOnClickListener(
+ v -> selectHeaderDetailSource(v, HeaderDetail.DATE_DAY));
+ b.patternDetailsDaySource.setOnClickListener(
+ v -> selectHeaderDetailSource(v, HeaderDetail.DATE_DAY));
- b.patternDetailsItemHead.setTag(item);
+ if (header.hasLiteralTransactionDescription()) {
+ b.patternTransactionDescriptionSource.setText(
+ R.string.pattern_details_source_literal);
+ b.transactionDescription.setText(header.getTransactionDescription());
+ b.transactionDescriptionLayout.setVisibility(View.VISIBLE);
}
- finally {
- finishUpdate();
+ else {
+ b.transactionDescriptionLayout.setVisibility(View.GONE);
+ b.patternTransactionDescriptionSource.setText(
+ String.format(Locale.US, "Group %d (%s)",
+ header.getTransactionDescriptionMatchGroup(),
+ getMatchGroupText(header.getTransactionDescriptionMatchGroup())));
+
+ }
+ b.patternTransactionDescriptionSourceLabel.setOnClickListener(
+ v -> selectHeaderDetailSource(v, HeaderDetail.DESCRIPTION));
+ b.patternTransactionDescriptionSource.setOnClickListener(
+ v -> selectHeaderDetailSource(v, HeaderDetail.DESCRIPTION));
+
+ if (header.hasLiteralTransactionComment()) {
+ b.patternTransactionCommentSource.setText(R.string.pattern_details_source_literal);
+ b.transactionComment.setText(header.getTransactionComment());
+ b.transactionCommentLayout.setVisibility(View.VISIBLE);
+ }
+ else {
+ b.transactionCommentLayout.setVisibility(View.GONE);
+ b.patternTransactionCommentSource.setText(String.format(Locale.US, "Group %d (%s)",
+ header.getTransactionCommentMatchGroup(),
+ getMatchGroupText(header.getTransactionCommentMatchGroup())));
+
}
+ b.patternTransactionCommentSourceLabel.setOnClickListener(
+ v -> selectHeaderDetailSource(v, HeaderDetail.COMMENT));
+ b.patternTransactionCommentSource.setOnClickListener(
+ v -> selectHeaderDetailSource(v, HeaderDetail.COMMENT));
+
+ b.patternDetailsHeadScanQrButton.setOnClickListener(this::scanTestQR);
+
}
private void scanTestQR(View view) {
QRScanAbleFragment.triggerQRScan();
public AccountRow(@NonNull PatternDetailsAccountBinding binding) {
super(binding.getRoot());
b = binding;
- }
- AccountRow(@NonNull View itemView) {
- super(itemView);
- throw new IllegalStateException("Should not be used");
+
+ TextWatcher accountNameWatcher = new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+ @Override
+ public void afterTextChanged(Editable s) {
+ PatternDetailsItem.AccountRow accRow = getItem();
+ Logger.debug(D_PATTERN_UI,
+ "Storing changed account name " + s + "; accRow=" + accRow);
+ accRow.setAccountName(String.valueOf(s));
+ }
+ };
+ b.patternDetailsAccountName.addTextChangedListener(accountNameWatcher);
+ TextWatcher accountCommentWatcher = new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {}
+ @Override
+ public void afterTextChanged(Editable s) {
+ PatternDetailsItem.AccountRow accRow = getItem();
+ Logger.debug(D_PATTERN_UI,
+ "Storing changed account comment " + s + "; accRow=" + accRow);
+ accRow.setAccountComment(String.valueOf(s));
+ }
+ };
+ b.patternDetailsAccountComment.addTextChangedListener(accountCommentWatcher);
}
@Override
void bind(PatternDetailsItem item) {
}
b.patternAccountNameSourceLabel.setOnClickListener(
- v -> selectAccountRowDetailSource(v, accRow, AccDetail.ACCOUNT));
+ v -> selectAccountRowDetailSource(v, AccDetail.ACCOUNT));
b.patternDetailsAccountNameSource.setOnClickListener(
- v -> selectAccountRowDetailSource(v, accRow, AccDetail.ACCOUNT));
+ v -> selectAccountRowDetailSource(v, AccDetail.ACCOUNT));
b.patternAccountCommentSourceLabel.setOnClickListener(
- v -> selectAccountRowDetailSource(v, accRow, AccDetail.COMMENT));
+ v -> selectAccountRowDetailSource(v, AccDetail.COMMENT));
b.patternDetailsAccountCommentSource.setOnClickListener(
- v -> selectAccountRowDetailSource(v, accRow, AccDetail.COMMENT));
+ v -> selectAccountRowDetailSource(v, AccDetail.COMMENT));
b.patternAccountAmountSourceLabel.setOnClickListener(
- v -> selectAccountRowDetailSource(v, accRow, AccDetail.AMOUNT));
+ v -> selectAccountRowDetailSource(v, AccDetail.AMOUNT));
b.patternDetailsAccountAmountSource.setOnClickListener(
- v -> selectAccountRowDetailSource(v, accRow, AccDetail.AMOUNT));
+ v -> selectAccountRowDetailSource(v, AccDetail.AMOUNT));
+ }
+ private @NotNull PatternDetailsItem.AccountRow getItem() {
+ return differ.getCurrentList()
+ .get(getAdapterPosition())
+ .asAccountRowItem();
}
- private void selectAccountRowDetailSource(View v, PatternDetailsItem.AccountRow accRow,
- AccDetail detail) {
+ private void selectAccountRowDetailSource(View v, AccDetail detail) {
+ PatternDetailsItem.AccountRow accRow = getItem();
final PatternDetailsItem.Header header = getHeader();
Logger.debug(D_PATTERN_UI, "header is " + header);
PatternDetailSourceSelectorFragment sel =
PatternDetailsFragmentBinding b;
private PatternDetailsViewModel mViewModel;
private int mColumnCount = 1;
- private int mPatternId = PatternDetailsViewModel.NEW_PATTERN;
+ private Long mPatternId;
public PatternDetailsFragment() {
}
public static PatternDetailsFragment newInstance(int columnCount, int patternId) {
final Bundle args = getArguments();
if (args != null) {
mColumnCount = args.getInt(ARG_COLUMN_COUNT, 1);
- mPatternId = args.getInt(ARG_PATTERN_ID, PatternDetailsViewModel.NEW_PATTERN);
+ mPatternId = args.getLong(ARG_PATTERN_ID, -1);
+ if (mPatternId == -1)
+ mPatternId = null;
}
- mViewModel.setPatternId(mPatternId);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
PatternDetailsAdapter adapter = new PatternDetailsAdapter();
b.patternDetailsRecyclerView.setAdapter(adapter);
- mViewModel.getItems()
+ mViewModel.getItems(mPatternId)
.observe(getViewLifecycleOwner(), adapter::setItems);
return b.getRoot();
}
@Override
protected void onQrScanned(String text) {
Logger.debug("PatDet_fr", String.format("Got scanned text '%s'", text));
- mViewModel.setTestText(text);
+ if (text != null)
+ mViewModel.setTestText(text);
}
public void onSavePattern() {
mViewModel.onSavePattern();
package net.ktnx.mobileledger.ui.patterns;
-import android.database.Cursor;
import android.os.AsyncTask;
-import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
+import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModel;
-import net.ktnx.mobileledger.App;
import net.ktnx.mobileledger.dao.PatternAccountDAO;
import net.ktnx.mobileledger.dao.PatternHeaderDAO;
import net.ktnx.mobileledger.db.DB;
import net.ktnx.mobileledger.db.PatternAccount;
import net.ktnx.mobileledger.db.PatternHeader;
-import net.ktnx.mobileledger.model.Currency;
+import net.ktnx.mobileledger.db.PatternWithAccounts;
import net.ktnx.mobileledger.model.PatternDetailsItem;
import net.ktnx.mobileledger.utils.Logger;
-import net.ktnx.mobileledger.utils.MLDB;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Locale;
import java.util.Objects;
public class PatternDetailsViewModel extends ViewModel {
- static final int NEW_PATTERN = -1;
- private final MutableLiveData<List<PatternDetailsItem>> items = new MutableLiveData<>();
- private long mPatternId;
+ private final MutableLiveData<List<PatternDetailsItem>> items =
+ new MutableLiveData<>(Collections.emptyList());
+ private Long mPatternId;
private String mDefaultPatternName;
public String getDefaultPatternName() {
return mDefaultPatternName;
public void setDefaultPatternName(String name) {
mDefaultPatternName = name;
}
- public LiveData<List<PatternDetailsItem>> getItems() {
- return items;
- }
public void resetItems() {
- items.setValue(Collections.emptyList());
- checkItemConsistency();
+ ArrayList<PatternDetailsItem> newList = new ArrayList<>();
+ final PatternDetailsItem.Header header = PatternDetailsItem.createHeader();
+ header.setName(mDefaultPatternName);
+ header.setId(1);
+ newList.add(header);
+
+ while (newList.size() < 3) {
+ final PatternDetailsItem.AccountRow aRow = PatternDetailsItem.createAccountRow();
+ aRow.setId(newList.size() + 1);
+ newList.add(aRow);
+ }
+
+ items.setValue(newList);
}
private void checkItemConsistency() {
ArrayList<PatternDetailsItem> newList = new ArrayList<>(items.getValue());
}
while (newList.size() < 3) {
- newList.add(PatternDetailsItem.createAccountRow(newList.size() - 1));
+ newList.add(PatternDetailsItem.createAccountRow());
changes = true;
}
if (changes)
items.setValue(newList);
}
- public void loadItems(long patternId) {
- DB db = App.getRoomDB();
- LiveData<PatternHeader> ph = db.getPatternDAO()
- .getPattern(patternId);
- ArrayList<PatternDetailsItem> list = new ArrayList<>();
-
- MLDB.queryInBackground(
- "SELECT name, regular_expression, transaction_description, transaction_comment, " +
- "date_year_match_group, date_month_match_group, date_day_match_group FROM " +
- "patterns WHERE id=?", new String[]{String.valueOf(patternId)},
- new MLDB.CallbackHelper() {
- @Override
- public void onDone() {
- super.onDone();
-
- MLDB.queryInBackground(
- "SELECT id, position, acc, acc_match_group, currency, " +
- "currency_match_group, amount, amount_match_group," +
- " comment, comment_match_group FROM " +
- "pattern_accounts WHERE pattern_id=? ORDER BY " + "position ASC",
- new String[]{String.valueOf(patternId)}, new MLDB.CallbackHelper() {
- @Override
- public void onDone() {
- super.onDone();
- items.postValue(list);
- }
- @Override
- public boolean onRow(@NonNull Cursor cursor) {
- PatternDetailsItem.AccountRow item =
- PatternDetailsItem.createAccountRow(
- cursor.getInt(1));
- list.add(item);
-
- item.setId(cursor.getInt(0));
-
- if (cursor.isNull(3)) {
- item.setAccountName(cursor.getString(2));
- }
- else {
- item.setAccountNameMatchGroup(cursor.getShort(3));
- }
-
- if (cursor.isNull(5)) {
- final int currId = cursor.getInt(4);
- if (currId > 0)
- item.setCurrency(Currency.loadById(currId));
- }
- else {
- item.setCurrencyMatchGroup(cursor.getShort(5));
- }
-
- if (cursor.isNull(7)) {
- item.setAmount(cursor.getFloat(6));
- }
- else {
- item.setAmountMatchGroup(cursor.getShort(7));
- }
-
- if (cursor.isNull(9)) {
- item.setAccountComment(cursor.getString(8));
- }
- else {
- item.setAccountCommentMatchGroup(cursor.getShort(9));
- }
-
- return true;
- }
- });
- }
- @Override
- public boolean onRow(@NonNull Cursor cursor) {
- PatternDetailsItem.Header header = PatternDetailsItem.createHeader();
- header.setName(cursor.getString(0));
- header.setPattern(cursor.getString(1));
- header.setTransactionDescription(cursor.getString(2));
- header.setTransactionComment(cursor.getString(3));
- header.setDateYearMatchGroup(cursor.getShort(4));
- header.setDateMonthMatchGroup(cursor.getShort(5));
- header.setDateDayMatchGroup(cursor.getShort(6));
-
- list.add(header);
-
- return false;
- }
- });
+ public LiveData<List<PatternDetailsItem>> getItems(Long patternId) {
+ if (patternId != null && patternId <= 0)
+ throw new IllegalArgumentException("Pattern ID " + patternId + " is invalid");
+
+ mPatternId = patternId;
+
+ if (mPatternId == null) {
+ resetItems();
+ return items;
+ }
+
+ DB db = DB.get();
+ LiveData<PatternWithAccounts> dbList = db.getPatternDAO()
+ .getPatternWithAccounts(mPatternId);
+ Observer<PatternWithAccounts> observer = new Observer<PatternWithAccounts>() {
+ @Override
+ public void onChanged(PatternWithAccounts src) {
+ ArrayList<PatternDetailsItem> l = new ArrayList<>();
+
+ PatternDetailsItem header = PatternDetailsItem.fromRoomObject(src.header);
+ l.add(header);
+ for (PatternAccount acc : src.accounts) {
+ l.add(PatternDetailsItem.fromRoomObject(acc));
+ }
+
+ for (PatternDetailsItem i : l) {
+ Logger.debug("patterns-db", "Loaded pattern item " + i);
+ }
+ items.postValue(l);
+
+ dbList.removeObserver(this);
+ }
+ };
+ dbList.observeForever(observer);
+
+ return items;
}
public void setTestText(String text) {
List<PatternDetailsItem> list = new ArrayList<>(items.getValue());
items.setValue(list);
}
- public void setPatternId(int patternId) {
- if (mPatternId != patternId) {
- if (patternId == NEW_PATTERN) {
- resetItems();
- }
- else {
- loadItems(patternId);
- }
- mPatternId = patternId;
- }
-
- }
public void onSavePattern() {
Logger.debug("flow", "PatternDetailsViewModel.onSavePattern(); model=" + this);
final List<PatternDetailsItem> list = Objects.requireNonNull(items.getValue());
AsyncTask.execute(() -> {
+ boolean newPattern = mPatternId == null || mPatternId <= 0;
+
PatternDetailsItem.Header modelHeader = list.get(0)
.asHeaderItem();
- PatternHeaderDAO headerDAO = App.getRoomDB()
- .getPatternDAO();
+ PatternHeaderDAO headerDAO = DB.get()
+ .getPatternDAO();
PatternHeader dbHeader = modelHeader.toDBO();
- if (mPatternId <= 0) {
+ if (newPattern) {
dbHeader.setId(mPatternId = headerDAO.insert(dbHeader));
}
else
headerDAO.update(dbHeader);
+ Logger.debug("pattern-db",
+ String.format(Locale.US, "Stored pattern header %d, item=%s", dbHeader.getId(),
+ modelHeader));
- PatternAccountDAO paDAO = App.getRoomDB()
- .getPatternAccountDAO();
+
+ PatternAccountDAO paDAO = DB.get()
+ .getPatternAccountDAO();
for (int i = 1; i < list.size(); i++) {
- PatternAccount dbAccount = list.get(i)
- .asAccountRowItem()
- .toDBO(dbHeader.getId());
+ final PatternDetailsItem.AccountRow accRowItem = list.get(i)
+ .asAccountRowItem();
+ PatternAccount dbAccount = accRowItem.toDBO(dbHeader.getId());
dbAccount.setPatternId(mPatternId);
- if (dbAccount.getId() == null || dbAccount.getId() <= 0)
+ dbAccount.setPosition(i);
+ if (newPattern)
dbAccount.setId(paDAO.insert(dbAccount));
else
paDAO.update(dbAccount);
+
+ Logger.debug("pattern-db", String.format(Locale.US,
+ "Stored pattern account %d, account=%s, comment=%s, item=%s",
+ dbAccount.getId(), dbAccount.getAccountName(),
+ dbAccount.getAccountComment(), accRowItem));
}
});
}
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleEventObserver;
import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LiveData;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
+import net.ktnx.mobileledger.dao.PatternHeaderDAO;
import net.ktnx.mobileledger.databinding.FragmentPatternListBinding;
+import net.ktnx.mobileledger.db.DB;
+import net.ktnx.mobileledger.db.PatternHeader;
import net.ktnx.mobileledger.utils.Logger;
import org.jetbrains.annotations.NotNull;
+import java.util.List;
+
/**
* A simple {@link Fragment} subclass.
* Use the {@link PatternListFragment#newInstance} factory method to
PatternsRecyclerViewAdapter modelAdapter = new PatternsRecyclerViewAdapter();
b.patternList.setAdapter(modelAdapter);
- PatternsModel.retrievePatterns(modelAdapter);
+ PatternHeaderDAO pDao = DB.get()
+ .getPatternDAO();
+ LiveData<List<PatternHeader>> patterns = pDao.getPatterns();
+ patterns.observe(getViewLifecycleOwner(), list -> {modelAdapter.setPatterns(list);});
LinearLayoutManager llm = new LinearLayoutManager(getContext());
llm.setOrientation(RecyclerView.VERTICAL);
b.patternList.setLayoutManager(llm);
if (mListener == null)
return;
- mListener.onNewPattern();
+ mListener.onEditPattern(null);
}
/**
* This interface must be implemented by activities that contain this
* >Communicating with Other Fragments</a> for more information.
*/
public interface OnPatternListFragmentInteractionListener {
- void onNewPattern();
void onSavePattern();
- void onEditPattern(int id);
+
+ void onEditPattern(Long id);
}
}
\ No newline at end of file
import androidx.recyclerview.widget.RecyclerView;
import net.ktnx.mobileledger.databinding.PatternLayoutBinding;
-import net.ktnx.mobileledger.model.PatternEntry;
+import net.ktnx.mobileledger.db.PatternHeader;
class PatternViewHolder extends RecyclerView.ViewHolder {
final PatternLayoutBinding b;
super(binding.getRoot());
b = binding;
}
- public void bindToItem(PatternEntry item) {
+ public void bindToItem(PatternHeader item) {
b.patternName.setText(item.getName());
b.editButon.setOnClickListener(v -> {
((PatternsActivity) v.getContext()).onEditPattern(item.getId());
b.toolbarLayout.setTitle(getString(R.string.title_activity_patterns));
- b.fabAdd.setOnClickListener(v -> onNewPattern());
+ b.fabAdd.setOnClickListener(v -> onEditPattern(null));
b.fabSave.setOnClickListener(v -> onSavePattern());
}
@Override
- public void onNewPattern() {
- navController.navigate(R.id.action_patternListFragment_to_patternDetailsFragment);
-// final Snackbar snackbar =
-// Snackbar.make(b.fragmentContainer, "New pattern action coming up soon",
-// Snackbar.LENGTH_INDEFINITE);
-// snackbar.setAction("Action", v -> snackbar.dismiss());
-// snackbar.show();
- }
- @Override
- public void onEditPattern(int id) {
- Bundle bundle = new Bundle();
- bundle.putInt(PatternDetailsFragment.ARG_PATTERN_ID, id);
- navController.navigate(R.id.action_patternListFragment_to_patternDetailsFragment, bundle);
+ public void onEditPattern(Long id) {
+ if (id == null){
+ navController.navigate(R.id.action_patternListFragment_to_patternDetailsFragment);
+ }
+ else{
+ Bundle bundle = new Bundle();
+ bundle.putLong(PatternDetailsFragment.ARG_PATTERN_ID, id);
+ navController.navigate(R.id.action_patternListFragment_to_patternDetailsFragment, bundle);
+ }
}
@Override
public void onSavePattern() {
import androidx.recyclerview.widget.RecyclerView;
import net.ktnx.mobileledger.databinding.PatternLayoutBinding;
-import net.ktnx.mobileledger.model.PatternEntry;
+import net.ktnx.mobileledger.db.PatternHeader;
import org.jetbrains.annotations.NotNull;
import java.util.List;
-import java.util.Objects;
public class PatternsRecyclerViewAdapter extends RecyclerView.Adapter<PatternViewHolder> {
- private final AsyncListDiffer<PatternEntry> listDiffer;
+ private final AsyncListDiffer<PatternHeader> listDiffer;
public PatternsRecyclerViewAdapter() {
- listDiffer = new AsyncListDiffer<>(this, new DiffUtil.ItemCallback<PatternEntry>() {
+ listDiffer = new AsyncListDiffer<>(this, new DiffUtil.ItemCallback<PatternHeader>() {
@Override
- public boolean areItemsTheSame(@NotNull PatternEntry oldItem,
- @NotNull PatternEntry newItem) {
- return oldItem.getId() == newItem.getId();
+ public boolean areItemsTheSame(@NotNull PatternHeader oldItem,
+ @NotNull PatternHeader newItem) {
+ return oldItem.getId()
+ .equals(newItem.getId());
}
@Override
- public boolean areContentsTheSame(@NotNull PatternEntry oldItem,
- @NotNull PatternEntry newItem) {
- return Objects.equals(oldItem.getName(), newItem.getName());
+ public boolean areContentsTheSame(@NotNull PatternHeader oldItem,
+ @NotNull PatternHeader newItem) {
+ return oldItem.equals(newItem);
}
});
}
return listDiffer.getCurrentList()
.size();
}
- public void setPatterns(List<PatternEntry> newList) {
+ public void setPatterns(List<PatternHeader> newList) {
listDiffer.submitList(newList);
}
}
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
+import org.jetbrains.annotations.Contract;
+
public class Misc {
public static boolean isZero(float f) {
return (f < 0.005) && (f > -0.005);
return string.trim();
}
+ @Contract(value = "null, null -> true; null, !null -> false; !null, null -> false", pure = true)
+ public static boolean equalIntegers(Integer a, Integer b) {
+ if ( a == null && b == null) return true;
+ if (a == null || b == null) return false;
+
+ return a.equals(b);
+ }
+ @Contract(value = "null, null -> true; null, !null -> false; !null, null -> false", pure = true)
+ public static boolean equalLongs(Long a, Long b) {
+ if ( a == null && b == null) return true;
+ if (a == null || b == null) return false;
+
+ return a.equals(b);
+ }
}