]> git.ktnx.net Git - mobile-ledger.git/blobdiff - app/src/main/java/net/ktnx/mobileledger/model/MobileLedgerProfile.java
more asynchronous account list (re-)loading
[mobile-ledger.git] / app / src / main / java / net / ktnx / mobileledger / model / MobileLedgerProfile.java
index 2de99c8f3b30f8880a250d0b628df52985004faa..fc940e9ad6f8850b33e4ee9dd118dafc746e1ac3 100644 (file)
@@ -24,11 +24,14 @@ import android.util.SparseArray;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
 
 import net.ktnx.mobileledger.App;
 import net.ktnx.mobileledger.R;
 import net.ktnx.mobileledger.async.DbOpQueue;
 import net.ktnx.mobileledger.async.SendTransactionTask;
+import net.ktnx.mobileledger.utils.Logger;
 import net.ktnx.mobileledger.utils.MLDB;
 import net.ktnx.mobileledger.utils.Misc;
 
@@ -61,6 +64,9 @@ public final class MobileLedgerProfile {
     private SendTransactionTask.API apiVersion = SendTransactionTask.API.auto;
     private Calendar firstTransactionDate;
     private Calendar lastTransactionDate;
+    private MutableLiveData<ArrayList<LedgerAccount>> accounts =
+            new MutableLiveData<>(new ArrayList<>());
+    private AccountListLoader loader = null;
     public MobileLedgerProfile() {
         this.uuid = String.valueOf(UUID.randomUUID());
     }
@@ -83,10 +89,12 @@ public final class MobileLedgerProfile {
         futureDates = origin.futureDates;
         apiVersion = origin.apiVersion;
         defaultCommodity = origin.defaultCommodity;
+        firstTransactionDate = origin.firstTransactionDate;
+        lastTransactionDate = origin.lastTransactionDate;
     }
     // loads all profiles into Data.profiles
     // returns the profile with the given UUID
-    public static MobileLedgerProfile loadAllFromDB(String currentProfileUUID) {
+    public static MobileLedgerProfile loadAllFromDB(@Nullable String currentProfileUUID) {
         MobileLedgerProfile result = null;
         ArrayList<MobileLedgerProfile> list = new ArrayList<>();
         SQLiteDatabase db = App.getDatabase();
@@ -139,6 +147,26 @@ public final class MobileLedgerProfile {
             db.endTransaction();
         }
     }
+    public LiveData<ArrayList<LedgerAccount>> getAccounts() {
+        return accounts;
+    }
+    synchronized public void scheduleAccountListReload() {
+        Logger.debug("async-acc", "scheduleAccountListReload() enter");
+        if ((loader != null) && loader.isAlive()) {
+            Logger.debug("async-acc", "returning early - loader already active");
+            return;
+        }
+
+        Logger.debug("async-acc", "Starting AccountListLoader");
+        loader = new AccountListLoader(this);
+        loader.start();
+    }
+    synchronized public void abortAccountListReload() {
+        if (loader == null)
+            return;
+        loader.interrupt();
+        loader = null;
+    }
     public boolean getShowCommentsByDefault() {
         return showCommentsByDefault;
     }
@@ -269,15 +297,14 @@ public final class MobileLedgerProfile {
     public void storeAccount(SQLiteDatabase db, LedgerAccount acc) {
         // replace into is a bad idea because it would reset hidden to its default value
         // we like the default, but for new accounts only
-        db.execSQL("update accounts set level = ?, keep = 1, hidden=?, expanded=? " +
+        db.execSQL("update accounts set level = ?, keep = 1, expanded=? " +
                    "where profile=? and name = ?",
-                new Object[]{acc.getLevel(), acc.isHiddenByStar(), acc.isExpanded(), uuid,
-                             acc.getName()
+                new Object[]{acc.getLevel(), acc.isExpanded(), uuid, acc.getName()
                 });
-        db.execSQL("insert into accounts(profile, name, name_upper, parent_name, level, hidden, " +
-                   "expanded, keep) " + "select ?,?,?,?,?,?,?,1 where (select changes() = 0)",
+        db.execSQL("insert into accounts(profile, name, name_upper, parent_name, level, " +
+                   "expanded, keep) " + "select ?,?,?,?,?,?,1 where (select changes() = 0)",
                 new Object[]{uuid, acc.getName(), acc.getName().toUpperCase(), acc.getParentName(),
-                             acc.getLevel(), acc.isHiddenByStar(), acc.isExpanded()
+                             acc.getLevel(), acc.isExpanded()
                 });
 //        debug("accounts", String.format("Stored account '%s' in DB [%s]", acc.getName(), uuid));
     }
@@ -293,13 +320,11 @@ public final class MobileLedgerProfile {
         db.execSQL("DELETE from transaction_accounts WHERE profile = ? and transaction_id=?",
                 new Object[]{uuid, tr.getId()});
 
-        db.execSQL(
-                "INSERT INTO transactions(profile, id, year, month, day, description, "+
-                "comment, data_hash, keep) " +
-                "values(?,?,?,?,?,?,?,?,1)",
+        db.execSQL("INSERT INTO transactions(profile, id, year, month, day, description, " +
+                   "comment, data_hash, keep) values(?,?,?,?,?,?,?,?,1)",
                 new Object[]{uuid, tr.getId(), tr.getDate().year, tr.getDate().month,
-                             tr.getDate().day, tr.getDescription(),
-                             tr.getComment(), tr.getDataHash()
+                             tr.getDate().day, tr.getDescription(), tr.getComment(),
+                             tr.getDataHash()
                 });
 
         for (LedgerTransactionAccount item : tr.getAccounts()) {
@@ -403,15 +428,16 @@ public final class MobileLedgerProfile {
     }
     @Nullable
     public LedgerAccount tryLoadAccount(SQLiteDatabase db, String accName) {
-        try (Cursor cursor = db.rawQuery(
-                "SELECT a.hidden, a.expanded, (select 1 from accounts a2 " +
-                "where a2.profile = a.profile and a2.name like a.name||':%' limit 1) " +
-                "FROM accounts a WHERE a.profile = ? and a.name=?", new String[]{uuid, accName}))
+        try (Cursor cursor = db.rawQuery("SELECT a.expanded, a.amounts_expanded, (select 1 from accounts a2 " +
+                                         "where a2.profile = a.profile and a2.name like a" +
+                                         ".name||':%' limit 1) " +
+                                         "FROM accounts a WHERE a.profile = ? and a.name=?",
+                new String[]{uuid, accName}))
         {
             if (cursor.moveToFirst()) {
-                LedgerAccount acc = new LedgerAccount(accName);
-                acc.setHiddenByStar(cursor.getInt(0) == 1);
-                acc.setExpanded(cursor.getInt(1) == 1);
+                LedgerAccount acc = new LedgerAccount(this, accName);
+                acc.setExpanded(cursor.getInt(0) == 1);
+                acc.setAmountsExpanded(cursor.getInt(1) == 1);
                 acc.setHasSubAccounts(cursor.getInt(2) == 1);
 
                 try (Cursor c2 = db.rawQuery(
@@ -574,6 +600,9 @@ public final class MobileLedgerProfile {
     public Calendar getLastTransactionDate() {
         return lastTransactionDate;
     }
+    public void setAccounts(ArrayList<LedgerAccount> list) {
+        accounts.postValue(list);
+    }
     public enum FutureDates {
         None(0), OneWeek(7), TwoWeeks(14), OneMonth(30), TwoMonths(60), ThreeMonths(90),
         SixMonths(180), OneYear(365), All(-1);
@@ -618,4 +647,42 @@ public final class MobileLedgerProfile {
             }
         }
     }
+
+    static class AccountListLoader extends Thread {
+        MobileLedgerProfile profile;
+        AccountListLoader(MobileLedgerProfile profile) {
+            this.profile = profile;
+        }
+        @Override
+        public void run() {
+            Logger.debug("async-acc", "AccountListLoader::run() entered");
+            String profileUUID = profile.getUuid();
+            ArrayList<LedgerAccount> newList = new ArrayList<>();
+
+            String sql = "SELECT a.name from accounts a WHERE a.profile = ?";
+            sql += " ORDER BY a.name";
+
+            SQLiteDatabase db = App.getDatabase();
+            try (Cursor cursor = db.rawQuery(sql, new String[]{profileUUID})) {
+                while (cursor.moveToNext()) {
+                    if (isInterrupted())
+                        return;
+
+                    final String accName = cursor.getString(0);
+//                    debug("accounts",
+//                            String.format("Read account '%s' from DB [%s]", accName,
+//                            profileUUID));
+                    LedgerAccount acc = profile.loadAccount(db, accName);
+                    if (acc.isVisible(newList))
+                        newList.add(acc);
+                }
+            }
+
+            if (isInterrupted())
+                return;
+
+            Logger.debug("async-acc", "AccountListLoader::run() posting new list");
+            profile.accounts.postValue(newList);
+        }
+    }
 }