Что первым делом должна делать программа для учета личных финансов? Конечно, показывать нам эти самые финансы. Или говоря другими словами, показывать состояние счета и транзакции по нему.
Счета у нас внутри базы представляют собой классическое дерево, где у каждой веточки есть свой id и id ветки, из которой она растет. Или id и parent_id. Если parent_id=0, то считаем, что этот счет “корневой” и находится на самом верху.
Методов отображения таких деревьев – уйма. Но я на свою голову решил попробовать применить QTreeView. Обложился документацией, нашел парочку хороших статей на хабре … Казалось бы, бери и делай.
Но фигу. QTreeView в Qt – один из немногих компонентов, который сделан “наотъебись”. Практически нулевая документация, какие-то шаманские пляски для выполнения тривиальнейших вещей и так далее и тому подобное. А практически все примеры в интернете написаны в духе “это просто, берем готовую модель и вуаля!”. А как работает эта модель и почему надо это делать так – ноль.
В общем, потратив впустую пару дней с этими морделями, я плюнул на эту хренотень, взял обычный QTreeWidget и банальным рекурсивным поиском заполнил виджет. На всякие заморочки со скоростью я решил начихать, ибо я не верю, что у обычного пользователя будет больше 100-200 счетов, а на этом уровне сходится все. На тестах виджет вполне нормально крутил 10000 счетов без каких-либо пожираний памяти или тормозов процессора.
Что касается размазывания логики по коду, то вроде этого удалось избежать. Все необходимое уместилось в одном классе. В общем, с моделью тут гораздо больше мороки и код получается гораздо более нечитаемым и не поддерживаемым.
Из того, что не было в предыдущих стадиях так это только то, что добавилась синхронизация таблички rate, в которой хранятся курсы валют. Тут же всплыла проблема: при синхронизации на немощных компьютерах программа сваливается в Application Not Responding. Надо будет куда-нибудь в синхронизацию воткнуть вызов диспетчера очередей. Сменить алгоритм не предлагать, ибо потом некоторые таблички будут расти и расти …
А вот с окошком отображения транзакций получилось все как по книжкам. Там обычная плоская таблица, поэтому QSqlTableModel пришлась впору. И так как документации, примеров и прочего на порядок больше, то и проблем никаких не было. Почти, но об этом позже.
Через некоторое время я переехал на QSqlRelationalTableModel по одной простой причине: у каждой транзакции есть currency_id, которое отвечает за валюту, в которой сделана транзакция. И что бы не мучаться, проще заставить модельку саму выбирать с помощью join нужные значения из таблицы currency.
Во всем этом великолепии меня поджидало только две засады.
Первая заключалась в именах таблиц. Все-таки transaction является ключевым словом и просто так qtшный sql не хотел использовать эту таблицу. Попытка заэскепить имя таблицы как [transaction] не увенчалась успехом. Но на мою радость оказалось, что “transaction” вполне себе хороший идентификатор для qt.
Вторая заключалась в том, что поле для join задается его порядковым номером. То есть мне надо считать, под каким порядковым номером выводится нужное мне поле и задавать его. А функции типа findColumn(name) я не нашел. Можно конечно поизвращаться самому (db.tables никто не отменял), но пока оставлю в качестве todo на будущее.
Наконец, сделал последний штрих: заставил выводить только те транзакции, которые относятся к выделенному счету. Мелочь через setfilter.
В принципе, максимально минимальный клиент готов. Он умеет логиниться и показывать необходимое. Да, коряво, да, даже без капельки дизайна, но умеет.
Что следующее? А следующим будет причесывание внешнего вида и начало эпопеи по разработке интерфейса. Например, надо сделать так, что бы на планшетах, десктопах и телефонах в ландшафтной ориентации отображалось как “счета-транзакции”. А вот на телефонах в портретной ориентации надо выводить “счета”, при тапе на счете выводить отдельное окно с транзакциями. И реализовать “назад”.
И тулбарчик на андроидах сверху, а на айфонах снизу! И еще ..
Короче, в следующей серии будет гламуризация полученного.