diff --git a/src/gnc/Account.hpp b/src/gnc/Account.hpp index 275cbd52c6..9f53e31d46 100644 --- a/src/gnc/Account.hpp +++ b/src/gnc/Account.hpp @@ -49,14 +49,32 @@ public: QString getName() const { return QString::fromUtf8(xaccAccountGetName(get())); } QString getCode() const { return QString::fromUtf8(xaccAccountGetCode(get())); } QString getDescription() const { return QString::fromUtf8(xaccAccountGetDescription(get())); } + Account get_parent() const { return gnc_account_get_parent(get()); } Account get_root() { return gnc_account_get_root(get()); } bool is_root() const { return gnc_account_is_root(get()); } gint n_children() const { return gnc_account_n_children(get()); } GList *get_children() const { return gnc_account_get_children(get()); } - GList * get_descendants () const { return gnc_account_get_descendants (get()); } + GList *get_descendants () const { return gnc_account_get_descendants (get()); } Account nth_child (gint num) const { return gnc_account_nth_child(get(), num); } + + /** Return the index of this account in the children's list of its + * parent account. + */ + gint child_index () const + { + Account parent(get_parent()); + if (parent.get()) + return gnc_account_child_index(parent.get(), get()); + else + return 0; + } + + gint get_current_depth () const { return gnc_account_get_current_depth(get()); } + gint get_tree_depth () const { return gnc_account_get_tree_depth(get()); } + + typedef QList< ::Account*> AccountQList; static AccountQList fromGList(GList* glist) { diff --git a/src/gnc/AccountItemModel.cpp b/src/gnc/AccountItemModel.cpp new file mode 100644 index 0000000000..d0a2e8a94b --- /dev/null +++ b/src/gnc/AccountItemModel.cpp @@ -0,0 +1,158 @@ +/* + * AccountItemModel.hpp + * Copyright (C) 2010 Christian Stimming + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, contact: + * + * Free Software Foundation Voice: +1-617-542-5942 + * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 + * Boston, MA 02110-1301, USA gnu@gnu.org + */ + +#include "AccountItemModel.hpp" +#include + +namespace gnc +{ + +AccountTreeModel::AccountTreeModel(Account rootaccount, QObject *parent) + : QAbstractItemModel(parent) + , m_root(rootaccount) +{ +} + +QModelIndex AccountTreeModel::index(int row, int column, + const QModelIndex &parent) const +{ + //qDebug() << "index(), " << row << column << parent; + if (!hasIndex(row, column, parent)) + return QModelIndex(); + + Account parentItem; + + if (!parent.isValid()) + parentItem = m_root; + else + parentItem.reset(static_cast< ::Account*>(parent.internalPointer())); + + Account childItem = parentItem.nth_child(row); + if (childItem.get()) + { + //qDebug() << "returning" << childItem.getName(); + return createIndex(row, column, childItem.get()); + } + else + return QModelIndex(); +} + +QModelIndex AccountTreeModel::parent(const QModelIndex &index) const +{ + //qDebug() << "parent()" << index; + if (!index.isValid()) + return QModelIndex(); + + Account childItem(static_cast< ::Account*>(index.internalPointer())); + Account parentItem(childItem.get_parent()); + + if (parentItem.get() == m_root.get()) + return QModelIndex(); + + return createIndex(parentItem.child_index(), 0, parentItem.get()); +} + +int AccountTreeModel::rowCount(const QModelIndex& parent) const +{ + //qDebug() << "rowCount()" << parent; + if (parent.column() > 0) + return 0; + // FIXME: Doesn't this just mean the nonzero columns don't have a + // tree? In that case it would be correct. + + Account parentItem; + if (!parent.isValid()) + parentItem = m_root; + else + parentItem.reset(static_cast< ::Account*>(parent.internalPointer())); + + //qDebug() << "Returning " << parentItem.n_children(); + return parentItem.n_children(); +} + +int AccountTreeModel::columnCount(const QModelIndex& parent) const +{ + //qDebug() << "columnCount()" << parent; +// if (!parent.isValid()) +// return 0; +// else + return 3; // Fixed number for now +} + +QVariant AccountTreeModel::data(const QModelIndex& index, int role) const +{ + //qDebug() << "data(), " << index; + if (!index.isValid()) + return QVariant(); + if (role == Qt::DisplayRole) + { + Account account(static_cast< ::Account*>(index.internalPointer())); + switch (index.column()) + { + case 0: + return account.getName(); + case 1: + return account.getCode(); + case 2: + return account.getDescription(); + default: + return QVariant(); + } + } + else + return QVariant(); +} + +Qt::ItemFlags AccountTreeModel::flags(const QModelIndex &index) const +{ + //qDebug() << "flags()" << index; + if (!index.isValid()) + return 0; + + // Ensure read-only access only + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; +} + +QVariant AccountTreeModel::headerData(int section, Qt::Orientation orientation, int role) const +{ + //qDebug() << "headerData()" << section; + if (role != Qt::DisplayRole) + return QVariant(); + if (orientation == Qt::Horizontal) + { + switch (section) + { + case 0: + return QString("Name"); + case 1: + return QString("Code"); + case 2: + return QString("Description"); + default: + return QVariant(); + } + } + else + return QString("%1").arg(1 + section); +} + +} // END namespace gnc diff --git a/src/gnc/AccountItemModel.hpp b/src/gnc/AccountItemModel.hpp index 7215bf1b9b..11c4f3f65b 100644 --- a/src/gnc/AccountItemModel.hpp +++ b/src/gnc/AccountItemModel.hpp @@ -93,6 +93,31 @@ private: Account::AccountQList m_acclist; }; + + + +class AccountTreeModel : public QAbstractItemModel +{ + Q_OBJECT +public: + AccountTreeModel(Account rootaccount, QObject *parent = 0); + + int rowCount(const QModelIndex& parent = QModelIndex()) const; + int columnCount(const QModelIndex& parent = QModelIndex()) const; + QModelIndex parent(const QModelIndex &index) const; + QModelIndex index(int row, int column, + const QModelIndex &parent = QModelIndex()) const; + Qt::ItemFlags flags(const QModelIndex &index) const; + + QVariant data(const QModelIndex& index, int role) const; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + +private: + Account m_root; + Account::AccountQList m_acclist; +}; + + } // END namespace gnc #endif diff --git a/src/gnc/CMakeLists.txt b/src/gnc/CMakeLists.txt index c89b39ffc8..23dfbd993a 100644 --- a/src/gnc/CMakeLists.txt +++ b/src/gnc/CMakeLists.txt @@ -10,6 +10,7 @@ LINK_DIRECTORIES (${GLIB2_LIBRARY_DIRS} ) SET (gnc_SOURCES + AccountItemModel.cpp Book.cpp Session.cpp main.cpp diff --git a/src/gnc/mainwindow.cpp b/src/gnc/mainwindow.cpp index ff14150049..655cf4255e 100644 --- a/src/gnc/mainwindow.cpp +++ b/src/gnc/mainwindow.cpp @@ -455,7 +455,11 @@ void MainWindow::loadFile(const QString &fileName) { m_accountItemModel = new AccountItemModel(root, this); ui->tableView->setModel(m_accountItemModel); - ui->tabWidget->setCurrentIndex(1); //setCurrentWidget(ui->tableView); + + m_accountTreeModel = new AccountTreeModel(root, this); + ui->treeView->setModel(m_accountTreeModel); + + ui->tabWidget->setCurrentWidget(ui->treeViewTab); } else { diff --git a/src/gnc/mainwindow.hpp b/src/gnc/mainwindow.hpp index 7808cd6bc4..b5413167ef 100644 --- a/src/gnc/mainwindow.hpp +++ b/src/gnc/mainwindow.hpp @@ -84,6 +84,7 @@ private: Session m_session; AccountItemModel *m_accountItemModel; + AccountTreeModel *m_accountTreeModel; }; } // END namespace gnc diff --git a/src/gnc/mainwindow.ui b/src/gnc/mainwindow.ui index 7f476a7fc8..6cbfa85dc1 100644 --- a/src/gnc/mainwindow.ui +++ b/src/gnc/mainwindow.ui @@ -36,7 +36,7 @@ 0 - + Example Welcome Page @@ -53,7 +53,11 @@ p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt; font-weight:600;">Cutecash</span></p> <p style=" margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt; font-weight:600;">Free Finance Software. Easy to develop, easy to use.</span></p> -<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Currently this is only a proof-of-concept for developers: You can load an existing gnucash XML file, and it will show the list of accounts as a flat table in a QTableView. The fun part is how easy it was to add this display of all accounts, so it will probably take only another 1-2 hours until the account list is a tree to be viewed in a QTreeView. And a QTableView with the splits of an account can't be far...</span></p> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">Currently this is just a proof-of-concept for developers:</span></p> +<ol style="-qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Load an existing gnucash XML file</li> +<li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">It will show the account tree in a QTreeView</li> +<li style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Additionally the accounts will be shown in a flat list in a QTableView</li></ol> +<p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">The fun part is how easy it was to add this display of all accounts. And a QTableView with the splits of an account can't be far...</span></p> <p style=" margin-top:16px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:600;">Images</span></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><img src=":/pixmaps/gnucash_splash.png" /></p> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">We can also embed images here in this compiled-in HTML page, as you can see above. Eventually, this page should explain what this software can do for the new user. Maybe a </span><a href="gnc:test"><span style=" text-decoration: underline; color:#0000ff;">hyperlink </span></a><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;">here?</span></p></body></html> @@ -65,7 +69,7 @@ p, li { white-space: pre-wrap; } - + Account List @@ -78,6 +82,19 @@ p, li { white-space: pre-wrap; } + + + Account Tree + + + + 0 + + + + + +