db: Create a new Model class
This inherits from the Table, but also implements the Gio.ListModel interface with sorting for use in the sidebar Gtk.ListView Implements: Issue #1 (Have SQLite sort our sidebar tables) Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
parent
427b9fb925
commit
feeee8809d
43
db/table.py
43
db/table.py
|
@ -1,4 +1,6 @@
|
|||
# Copyright 2021 (c) Anna Schumaker.
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gio
|
||||
from . import sql
|
||||
|
||||
class Table:
|
||||
|
@ -44,3 +46,44 @@ class Table:
|
|||
self.do_drop()
|
||||
self.cache.clear()
|
||||
self.do_create()
|
||||
|
||||
|
||||
class Model(GObject.GObject, Gio.ListModel, Table):
|
||||
def __init__(self, table, order):
|
||||
GObject.GObject.__init__(self)
|
||||
Table.__init__(self, table)
|
||||
self.order = order
|
||||
|
||||
def do_get_item_type(self):
|
||||
return GObject.TYPE_PYOBJECT
|
||||
|
||||
def do_get_n_items(self):
|
||||
return sql.execute(f"SELECT COUNT(*) FROM {self.table}").fetchone()[0]
|
||||
|
||||
def do_get_item(self, n):
|
||||
cur = sql.execute(f"SELECT * FROM {self.table} ORDER BY {self.order} "
|
||||
"LIMIT 1 OFFSET ?", [ n ])
|
||||
return self.factory(cur.fetchone())
|
||||
|
||||
def get_item_index(self, item):
|
||||
cur = sql.execute("SELECT * FROM (SELECT rowid,ROW_NUMBER() "
|
||||
f"OVER (ORDER BY {self.order}) "
|
||||
f"FROM {self.table}) "
|
||||
"WHERE rowid=?", [ item.rowid ])
|
||||
return cur.fetchone()[1] - 1
|
||||
|
||||
def delete(self, item):
|
||||
pos = self.get_item_index(item)
|
||||
super().delete(item)
|
||||
self.emit("items-changed", pos, 1, 0)
|
||||
|
||||
def insert(self, *args):
|
||||
row = super().insert(*args)
|
||||
pos = self.get_item_index(row)
|
||||
self.emit("items-changed", pos, 0, 1)
|
||||
return row
|
||||
|
||||
def reset(self):
|
||||
n = self.get_n_items()
|
||||
super().reset()
|
||||
self.emit("items-changed", 0, n, self.get_n_items())
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
# Copyright 2021 (c) Anna Schumaker.
|
||||
import unittest
|
||||
from gi.repository import GObject
|
||||
from gi.repository import Gio
|
||||
from . import sql
|
||||
from . import table
|
||||
|
||||
class FakeRow:
|
||||
class FakeRow(GObject.GObject):
|
||||
def __init__(self, data):
|
||||
GObject.GObject.__init__(self)
|
||||
self.rowid = data["fakeid"]
|
||||
self.name = data["name"]
|
||||
|
||||
|
@ -26,6 +29,13 @@ class FakeTable(table.Table):
|
|||
def do_lookup(self, name):
|
||||
return sql.execute("SELECT * FROM fake_table WHERE name=?", [ name ])
|
||||
|
||||
class FakeModel(table.Model, FakeTable):
|
||||
def __init__(self):
|
||||
table.Model.__init__(self, "fake_table", "lower(name)")
|
||||
self.reset()
|
||||
|
||||
|
||||
|
||||
class TestTable(unittest.TestCase):
|
||||
def test_init(self):
|
||||
fake = FakeTable()
|
||||
|
@ -76,3 +86,56 @@ class TestTable(unittest.TestCase):
|
|||
|
||||
fake.reset()
|
||||
self.assertEqual(fake.cache, { })
|
||||
|
||||
|
||||
class TestModel(unittest.TestCase):
|
||||
def items_changed(self, table, pos, rm, add):
|
||||
self.changed = (pos, rm, add)
|
||||
|
||||
def setUp(self):
|
||||
self.changed = None
|
||||
|
||||
def test_init(self):
|
||||
fake = FakeModel()
|
||||
self.assertIsInstance(fake, GObject.GObject)
|
||||
self.assertIsInstance(fake, Gio.ListModel)
|
||||
self.assertIsInstance(fake, table.Table)
|
||||
self.assertEqual(fake.order, "lower(name)")
|
||||
|
||||
def test_insert_delete(self):
|
||||
fake = FakeModel()
|
||||
fake.connect("items-changed", self.items_changed)
|
||||
|
||||
row = fake.insert("Test Row")
|
||||
self.assertEqual(self.changed, (0, 0, 1))
|
||||
|
||||
fake.delete(row)
|
||||
self.assertEqual(self.changed, (0, 1, 0))
|
||||
|
||||
def test_model(self):
|
||||
fake = FakeModel()
|
||||
self.assertEqual(fake.get_item_type(), GObject.TYPE_PYOBJECT)
|
||||
self.assertEqual(fake.get_n_items(), 0)
|
||||
|
||||
c = fake.insert("C")
|
||||
self.assertEqual(fake.get_n_items(), 1)
|
||||
self.assertEqual(fake.get_item(0), c)
|
||||
|
||||
b = fake.insert("B")
|
||||
self.assertEqual(fake.get_n_items(), 2)
|
||||
self.assertEqual(fake.get_item(0), b)
|
||||
self.assertEqual(fake.get_item(1), c)
|
||||
|
||||
a = fake.insert("A")
|
||||
self.assertEqual(fake.get_n_items(), 3)
|
||||
self.assertEqual(fake.get_item(0), a)
|
||||
self.assertEqual(fake.get_item(1), b)
|
||||
self.assertEqual(fake.get_item(2), c)
|
||||
|
||||
def test_reset(self):
|
||||
fake = FakeModel()
|
||||
fake.insert("Test Row")
|
||||
fake.insert("Test Row 2")
|
||||
fake.connect("items-changed", self.items_changed)
|
||||
fake.reset()
|
||||
self.assertEqual(self.changed, (0, 2, 0))
|
||||
|
|
Loading…
Reference in New Issue