From cad5dc6214295254bbf47dca9001013c50f38e65 Mon Sep 17 00:00:00 2001 From: Christian Stimming Date: Sun, 7 Mar 2010 17:51:37 +0000 Subject: [PATCH] Implement a table widget with the list of the splits of one account, and open this if an account in the tree is double-clicked. Date and values/amounts can follow next, once those types are suitably wrapped into C++ as well. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18868 57a11ea4-9604-0410-9ed3-97b8803252fd --- src/gnc/Account.hpp | 6 ++ src/gnc/AccountItemModel.cpp | 41 ++++++------ src/gnc/AccountItemModel.hpp | 8 +-- src/gnc/CMakeLists.txt | 4 ++ src/gnc/Split.hpp | 103 +++++++++++++++++++++++++++++ src/gnc/SplitListModel.cpp | 124 +++++++++++++++++++++++++++++++++++ src/gnc/SplitListModel.hpp | 57 ++++++++++++++++ src/gnc/Transaction.hpp | 68 +++++++++++++++++++ src/gnc/mainwindow.cpp | 71 +++++++++++++++----- src/gnc/mainwindow.hpp | 1 + 10 files changed, 440 insertions(+), 43 deletions(-) create mode 100644 src/gnc/Split.hpp create mode 100644 src/gnc/SplitListModel.cpp create mode 100644 src/gnc/SplitListModel.hpp create mode 100644 src/gnc/Transaction.hpp diff --git a/src/gnc/Account.hpp b/src/gnc/Account.hpp index 9f53e31d46..995739f565 100644 --- a/src/gnc/Account.hpp +++ b/src/gnc/Account.hpp @@ -50,6 +50,11 @@ public: QString getCode() const { return QString::fromUtf8(xaccAccountGetCode(get())); } QString getDescription() const { return QString::fromUtf8(xaccAccountGetDescription(get())); } + ::SplitList* getSplitList() const { return xaccAccountGetSplitList(get()); } + + /** @name Account tree traversal */ + //@{ + 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()); } @@ -73,6 +78,7 @@ public: 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; diff --git a/src/gnc/AccountItemModel.cpp b/src/gnc/AccountItemModel.cpp index ebc80b3337..971cd1f23b 100644 --- a/src/gnc/AccountItemModel.cpp +++ b/src/gnc/AccountItemModel.cpp @@ -27,8 +27,8 @@ namespace gnc { AccountTreeModel::AccountTreeModel(Account rootaccount, QObject *parent) - : QAbstractItemModel(parent) - , m_root(rootaccount) + : QAbstractItemModel(parent) + , m_root(rootaccount) { } @@ -108,14 +108,14 @@ QVariant AccountTreeModel::data(const QModelIndex& index, int role) const 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(); + case 0: + return account.getName(); + case 1: + return account.getCode(); + case 2: + return account.getDescription(); + default: + return QVariant(); } } else @@ -141,14 +141,14 @@ QVariant AccountTreeModel::headerData(int section, Qt::Orientation orientation, { switch (section) { - case 0: - return QString("Name"); - case 1: - return QString("Code"); - case 2: - return QString("Description"); - default: - return QVariant(); + case 0: + return QString("Name"); + case 1: + return QString("Code"); + case 2: + return QString("Description"); + default: + return QVariant(); } } else @@ -162,11 +162,10 @@ QModelIndex AccountListModel::index(int row, int column, const QModelIndex &parent) const { //qDebug() << "index(), " << row << column << parent; - if (!hasIndex(row, column, parent) - || row >= m_acclist.size()) + if (!hasIndex(row, column, parent) || row >= m_list.size()) return QModelIndex(); - Account childItem = m_acclist.at(row); + Account childItem = m_list.at(row); if (childItem.get()) { //qDebug() << "returning" << childItem.getName(); diff --git a/src/gnc/AccountItemModel.hpp b/src/gnc/AccountItemModel.hpp index 716e496aa7..24730c2ae6 100644 --- a/src/gnc/AccountItemModel.hpp +++ b/src/gnc/AccountItemModel.hpp @@ -72,12 +72,12 @@ class AccountListModel : public AccountTreeModel Q_OBJECT public: AccountListModel(Account rootaccount, QObject *parent = 0) - : AccountTreeModel(rootaccount, parent) - , m_acclist(Account::fromGList(rootaccount.get_descendants())) + : AccountTreeModel(rootaccount, parent) + , m_list(Account::fromGList(rootaccount.get_descendants())) { } - int rowCount(const QModelIndex& parent = QModelIndex()) const { return m_acclist.size(); } + int rowCount(const QModelIndex& parent = QModelIndex()) const { return m_list.size(); } QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; @@ -85,7 +85,7 @@ public: QModelIndex parent(const QModelIndex &index) const { return QModelIndex(); } private: - Account::AccountQList m_acclist; + Account::AccountQList m_list; }; diff --git a/src/gnc/CMakeLists.txt b/src/gnc/CMakeLists.txt index 23dfbd993a..1309a466f1 100644 --- a/src/gnc/CMakeLists.txt +++ b/src/gnc/CMakeLists.txt @@ -13,18 +13,22 @@ SET (gnc_SOURCES AccountItemModel.cpp Book.cpp Session.cpp + SplitListModel.cpp main.cpp mainwindow.cpp ) SET (gnc_QOBJECT_HEADERS AccountItemModel.hpp + SplitListModel.hpp mainwindow.hpp ) SET (gnc_HEADERS ${gnc_QOBJECT_HEADERS} Account.hpp Book.hpp Session.hpp + Split.hpp + Transaction.hpp WeakPointer.hpp ) diff --git a/src/gnc/Split.hpp b/src/gnc/Split.hpp new file mode 100644 index 0000000000..c35962d3b5 --- /dev/null +++ b/src/gnc/Split.hpp @@ -0,0 +1,103 @@ +/* + * Split.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 + */ + +#ifndef GNC_SPLIT_HPP +#define GNC_SPLIT_HPP + +// gnucash includes +#include "config.h" +extern "C" +{ +#include "qof.h" +#include "engine/Split.h" +} + +#include +#include + +namespace gnc +{ +class Split; +typedef QList< ::Split*> SplitQList; +} + +#include "gnc/WeakPointer.hpp" +#include "gnc/Account.hpp" +#include "gnc/Book.hpp" +#include "gnc/Transaction.hpp" + +namespace gnc +{ + +class Split : public WeakPointer< ::Split > +{ +public: + typedef WeakPointer< ::Split > base_class; + Split(element_type* ptr = 0) + : base_class(ptr) + { } + + Book getBook() const { return xaccSplitGetBook(get()); } + Account getAccount() const { return xaccSplitGetAccount(get()); } + void setAccount(Account& acc) { xaccSplitSetAccount(get(), acc.get()); } + + Transaction getParent() const { return xaccSplitGetParent(get()); } + void setParent(Transaction& trans) { xaccSplitSetParent(get(), trans.get()); } + + QString getMemo() const { return QString::fromUtf8(xaccSplitGetMemo(get())); } + void setMemo(const QString& v) { xaccSplitSetMemo(get(), v.toUtf8()); } + + QString getAction() const { return QString::fromUtf8(xaccSplitGetAction(get())); } + void setAction(const QString& v) { xaccSplitSetAction(get(), v.toUtf8()); } + + char getReconcile() const { return xaccSplitGetReconcile(get()); } + void setReconcile(char v) { xaccSplitSetReconcile(get(), v); } + + Split getOtherSplit() const { return xaccSplitGetOtherSplit(get()); } + + QString getCorrAccountFullName() const + { + char * r = xaccSplitGetCorrAccountFullName(get()); + QString result = QString::fromUtf8(r); + g_free (r); + return result; + } + QString getCorrAccountName() const { return QString::fromUtf8(xaccSplitGetCorrAccountName(get())); } + QString getCorrAccountCode() const { return QString::fromUtf8(xaccSplitGetCorrAccountCode(get())); } + + + static SplitQList fromGList(GList* glist) + { + SplitQList result; + GList* list = glist; + while (list) + { + result.append(reinterpret_cast< ::Split*>(list->data)); + list = g_list_next(list); + } + return result; + } +}; + +} // END namespace gnc + +#endif diff --git a/src/gnc/SplitListModel.cpp b/src/gnc/SplitListModel.cpp new file mode 100644 index 0000000000..a867f9f949 --- /dev/null +++ b/src/gnc/SplitListModel.cpp @@ -0,0 +1,124 @@ +/* + * SplitListModel.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 "SplitListModel.hpp" +#include + +namespace gnc +{ + +SplitListModel::SplitListModel(const SplitQList splits, QObject *parent) + : QAbstractItemModel(parent) + , m_list(splits) +{ +} + +QModelIndex SplitListModel::index(int row, int column, + const QModelIndex &parent) const +{ + //qDebug() << "index(), " << row << column << parent; + if (!hasIndex(row, column, parent) || row >= m_list.size()) + return QModelIndex(); + + Split childItem = m_list.at(row); + if (childItem.get()) + { + //qDebug() << "returning" << childItem.getName(); + return createIndex(row, column, childItem.get()); + } + else + return QModelIndex(); +} + +int SplitListModel::columnCount(const QModelIndex& parent) const +{ + //qDebug() << "columnCount()" << parent; +// if (!parent.isValid()) +// return 0; +// else + return 4; // Fixed number for now +} + +QVariant SplitListModel::data(const QModelIndex& index, int role) const +{ + //qDebug() << "data(), " << index; + if (!index.isValid()) + return QVariant(); + if (role == Qt::DisplayRole) + { + Split split(static_cast< ::Split*>(index.internalPointer())); + Transaction trans(split.getParent()); + switch (index.column()) + { + case 0: + return trans.getNum(); + case 1: + return trans.getDescription(); + case 2: + return split.getCorrAccountFullName(); + case 3: + return QChar(split.getReconcile()); + default: + return QVariant(); + } + } + else + return QVariant(); +} + +Qt::ItemFlags SplitListModel::flags(const QModelIndex &index) const +{ + //qDebug() << "flags()" << index; + if (!index.isValid()) + return 0; + + // Ensure read-only access only + return Qt::ItemIsEnabled | Qt::ItemIsSelectable; +} + +QVariant SplitListModel::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("Num"); + case 1: + return QString("Description"); + case 2: + return QString("Account"); + case 3: + return QString("Reconciled?"); + default: + return QVariant(); + } + } + else + return QString("%1").arg(1 + section); +} + + +} // END namespace gnc diff --git a/src/gnc/SplitListModel.hpp b/src/gnc/SplitListModel.hpp new file mode 100644 index 0000000000..5637855e0c --- /dev/null +++ b/src/gnc/SplitListModel.hpp @@ -0,0 +1,57 @@ +/* + * SplitListModel.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 + */ + +#ifndef GNC_SPLITLISTMODEL_HPP +#define GNC_SPLITLISTMODEL_HPP + +#include "gnc/Split.hpp" + +#include + +namespace gnc +{ + +/** This is the data model for a list of splits. + */ +class SplitListModel : public QAbstractItemModel +{ + Q_OBJECT +public: + SplitListModel(const SplitQList splits, QObject *parent = 0); + + QModelIndex parent(const QModelIndex &index) const { return QModelIndex(); } + int rowCount(const QModelIndex& parent = QModelIndex()) const { return m_list.size(); } + int columnCount(const QModelIndex& parent = QModelIndex()) 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; + +protected: + SplitQList m_list; +}; + +} // END namespace gnc + +#endif diff --git a/src/gnc/Transaction.hpp b/src/gnc/Transaction.hpp new file mode 100644 index 0000000000..8b0cd9e816 --- /dev/null +++ b/src/gnc/Transaction.hpp @@ -0,0 +1,68 @@ +/* + * Transaction.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 + */ + +#ifndef GNC_TRANSACTION_HPP +#define GNC_TRANSACTION_HPP + +// gnucash includes +#include "config.h" +extern "C" +{ +#include "qof.h" +#include "engine/Transaction.h" +} + +#include "gnc/WeakPointer.hpp" +#include "gnc/Account.hpp" +#include "gnc/Book.hpp" + +#include +#include + +namespace gnc +{ + +class Transaction : public WeakPointer< ::Transaction > +{ +public: + typedef WeakPointer< ::Transaction > base_class; + Transaction(element_type* ptr = 0) + : base_class(ptr) + { } + + QString getNum() const { return QString::fromUtf8(xaccTransGetNum(get())); } + void setNum(const QString& v) { xaccTransSetNum(get(), v.toUtf8()); } + + QString getDescription() const { return QString::fromUtf8(xaccTransGetDescription(get())); } + void setDescription(const QString& v) { xaccTransSetDescription(get(), v.toUtf8()); } + + QString getNotes() const { return QString::fromUtf8(xaccTransGetNotes(get())); } + void setNotes(const QString& v) { xaccTransSetNotes(get(), v.toUtf8()); } + + int countSplits() const { return xaccTransCountSplits(get()); } + + +}; + +} // END namespace gnc + +#endif diff --git a/src/gnc/mainwindow.cpp b/src/gnc/mainwindow.cpp index 80f2f993ed..087ebdcfd0 100644 --- a/src/gnc/mainwindow.cpp +++ b/src/gnc/mainwindow.cpp @@ -46,6 +46,8 @@ extern "C" #include "gnc/Account.hpp" #include "gnc/AccountItemModel.hpp" #include "gnc/Book.hpp" +#include "gnc/Split.hpp" +#include "gnc/SplitListModel.hpp" namespace gnc { @@ -173,6 +175,9 @@ void MainWindow::createActions() // ui->actionCut, SLOT(setEnabled(bool))); // connect(ui->textEdit, SIGNAL(copyAvailable(bool)), // ui->actionCopy, SLOT(setEnabled(bool))); + + connect(ui->treeView, SIGNAL(activated(const QModelIndex &)), + this, SLOT(activatedAccount(const QModelIndex&))); } void MainWindow::createToolBars() @@ -246,6 +251,36 @@ QString MainWindow::strippedName(const QString &fullFileName) return QFileInfo(fullFileName).fileName(); } +void MainWindow::activatedAccount(const QModelIndex & index) +{ + if (index.model() != m_accountTreeModel) + { + qDebug() << "Wrong model"; + return; + } + Account account(static_cast< ::Account*>(index.internalPointer())); + if (!account) + { + qDebug() << "Account is null; why?"; + return; + } + + // We have an account, so obtains its list of splits now. + ::SplitList* slist = account.getSplitList(); + + // We create a new model for this list of splits and also a view + // widget for this list. + QTableView *tableView = new QTableView(this); // FIXME: Parent object unclear + SplitListModel *smodel = new SplitListModel(Split::fromGList(slist), tableView); + tableView->setModel(smodel); + + // Insert this as a new tab + ui->tabWidget->addTab(tableView, account.getName()); + ui->tabWidget->setCurrentWidget(tableView); + + // Right now it cannot be deleted - this will be implemented later. +} + // //////////////////////////////////////////////////////////// void MainWindow::closeEvent(QCloseEvent *event) @@ -320,24 +355,24 @@ namespace * are in use simultaneously */ class progress_functor { - public: - progress_functor(QProgressBar *progressBar) - { - m_progressBar = progressBar; - } - ~progress_functor() - { - m_progressBar = NULL; - } - static void static_func(const char *message, double percent) - { - assert(m_progressBar); - m_progressBar->setValue(int(percent)); - // Give the Qt event loop some time - qApp->processEvents(); - } - private: - static QProgressBar *m_progressBar; +public: + progress_functor(QProgressBar *progressBar) + { + m_progressBar = progressBar; + } + ~progress_functor() + { + m_progressBar = NULL; + } + static void static_func(const char *message, double percent) + { + assert(m_progressBar); + m_progressBar->setValue(int(percent)); + // Give the Qt event loop some time + qApp->processEvents(); + } +private: + static QProgressBar *m_progressBar; }; QProgressBar *progress_functor::m_progressBar = NULL; diff --git a/src/gnc/mainwindow.hpp b/src/gnc/mainwindow.hpp index 01354c6e31..dce1c0a669 100644 --- a/src/gnc/mainwindow.hpp +++ b/src/gnc/mainwindow.hpp @@ -51,6 +51,7 @@ public: public slots: void anchorClicked(const QUrl &); + void activatedAccount(const QModelIndex & index); protected: void closeEvent(QCloseEvent *event);