From ad0ddae5e6be645d945f35b4a3fc356fd4435ccb Mon Sep 17 00:00:00 2001 From: Christian Stimming Date: Fri, 19 Mar 2010 22:01:56 +0000 Subject: [PATCH] Cutecash: Implement entering new transactions in the register. Only the account selection is still missing. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18935 57a11ea4-9604-0410-9ed3-97b8803252fd --- src/gnc/CMakeLists.txt | 2 + src/gnc/Cmd.cpp | 219 ++++++++++++++++++++++++++++++++---- src/gnc/Cmd.hpp | 1 + src/gnc/Split.cpp | 8 +- src/gnc/SplitListModel.cpp | 153 ++++++++++++++++--------- src/gnc/SplitListModel.hpp | 16 +++ src/gnc/SplitListView.cpp | 75 ++++++++++++ src/gnc/SplitListView.hpp | 53 +++++++++ src/gnc/Transaction.cpp | 3 +- src/gnc/Transaction.hpp | 3 +- src/gnc/mainwindow-file.cpp | 4 +- src/gnc/mainwindow.cpp | 16 +-- src/gnc/mainwindow.ui | 24 ++-- 13 files changed, 477 insertions(+), 100 deletions(-) create mode 100644 src/gnc/SplitListView.cpp create mode 100644 src/gnc/SplitListView.hpp diff --git a/src/gnc/CMakeLists.txt b/src/gnc/CMakeLists.txt index 9676935b74..bf9ef22c19 100644 --- a/src/gnc/CMakeLists.txt +++ b/src/gnc/CMakeLists.txt @@ -19,6 +19,7 @@ SET (gnc_SOURCES Session.cpp Split.cpp SplitListModel.cpp + SplitListView.cpp Transaction.cpp main.cpp mainwindow.cpp @@ -29,6 +30,7 @@ SET (gnc_QOBJECT_HEADERS AccountItemModel.hpp RecentFileMenu.hpp SplitListModel.hpp + SplitListView.hpp mainwindow.hpp ) SET (gnc_HEADERS ${gnc_QOBJECT_HEADERS} diff --git a/src/gnc/Cmd.cpp b/src/gnc/Cmd.cpp index e5d157d5e5..00b4456221 100644 --- a/src/gnc/Cmd.cpp +++ b/src/gnc/Cmd.cpp @@ -41,14 +41,14 @@ QUndoCommand* setSplitMemo(Split& t, const QString& newValue) { return new Cmd(QObject::tr("Edit Split Memo"), t, &Split::setMemo, - &Split::getMemo, newValue); + t.getMemo(), newValue); } QUndoCommand* setSplitAction(Split& t, const QString& newValue) { return new Cmd(QObject::tr("Edit Split Action"), t, &Split::setAction, - &Split::getAction, newValue); + t.getAction(), newValue); } QUndoCommand* setSplitReconcile(Split& t, char newValue) @@ -58,21 +58,21 @@ QUndoCommand* setSplitReconcile(Split& t, char newValue) // must be given explicitly. return new Cmd(QObject::tr("Edit Split Reconcile"), t, &Split::setReconcile, - &Split::getReconcile, newValue); + t.getReconcile(), newValue); } QUndoCommand* setSplitAmount(Split& t, const Numeric& newValue) { return new Cmd(QObject::tr("Edit Split Amount"), t, &Split::setAmount, - &Split::getAmount, newValue); + t.getAmount(), newValue); } QUndoCommand* setSplitValue(Split& t, const Numeric& newValue) { return new Cmd(QObject::tr("Edit Split Value"), t, &Split::setValue, - &Split::getValue, newValue); + t.getValue(), newValue); } // //////////////////////////////////////////////////////////// @@ -100,17 +100,8 @@ public: Q_ASSERT(m_target); } - virtual void redo() - { - set(m_newValue); - } - - virtual void undo() - { - set(m_previousValue); - } - - + virtual void redo() { set(m_newValue); } + virtual void undo() { set(m_previousValue); } private: void set(const value_type& value) { @@ -226,28 +217,214 @@ QUndoCommand* destroyTransaction(Transaction& t) t); } +// //////////////////////////////////////////////////////////// + +/** This is another templated implementation of a QUndoCommand + * class, this time with keeping a direct reference to the target object. + * + * This implements the Command pattern: Any instance of this + * class represents the change of one member variable (of type ValueT) + * in an instance of a TargetT object. + * + * As we need to keep a reference to the original object, it is + * relevant who owns the life cycle of that original object. For + * simplicity, we constrain this current implementation only to + * classes which are implementations of a WeakPointer<...> which by + * definition keeps a C pointer to the original object, and we hope + * that one lives longer than we do. + */ +template +class CmdRef : public QUndoCommand +{ +public: + /// The base class + typedef QUndoCommand base_class; + + /// Type of the target object on which this command is applied + typedef TargetT target_type; + + /// Type of the value that is set by this command + typedef ValueT value_type; + + /// Type of the setter function to set the value in the target object + typedef SetterFunc setter_func; + + /** Constructor with the previous value given directly. + * + * @param text The QUndoCommand's text which will be displayed in the Undo action. + * @param targetRef Reference to the target object on which this command is applied. + * @param setter Pointer to function which sets the value in the target object + * @param previousValue The previous value, in case this command needs to be undone + * @param newValue The new value to be set + * @param parent The parent QUndoCommand instance, or NULL. + */ + CmdRef(const QString& text, + TargetT& targetRef, + setter_func setter, + const value_type& previousValue, + const value_type& newValue, + QUndoCommand *parent = 0) + : base_class(text, parent) + , m_target(targetRef) + , m_setter(setter) + , m_previousValue(previousValue) + , m_newValue(newValue) + { + Q_ASSERT(m_setter); + } + + virtual void redo() { set(m_newValue); } + virtual void undo() { set(m_previousValue); } + +private: + void set(const value_type& value) + { + // Call the pointer-to-member which is stored in m_setter. + (m_target.*m_setter)(value); + } + +protected: + target_type& m_target; + setter_func m_setter; + value_type m_previousValue; + value_type m_newValue; +}; + QUndoCommand* setSplitReconcile(TmpSplit& t, char newValue) { - return 0; + // Special third argument: The setter function takes a value + // directly, instead of a const-reference, so the template type + // must be given explicitly. + return new CmdRef(QObject::tr("Edit Split Reconcile"), + t, &TmpSplit::setReconcile, + t.getReconcile(), newValue); } QUndoCommand* setTransactionNum(TmpTransaction& t, const QString& newValue) { - return 0; + return new CmdRef(QObject::tr("Edit Transaction Number"), + t, &TmpTransaction::setNum, + t.getNum(), newValue); } QUndoCommand* setTransactionDescription(TmpTransaction& t, const QString& newValue) { - return 0; + return new CmdRef(QObject::tr("Edit Transaction Description"), + t, &TmpTransaction::setDescription, + t.getDescription(), newValue); } QUndoCommand* setTransactionDate(TmpTransaction& t, const QDate& newValue) { - return 0; + return new CmdRef(QObject::tr("Edit Transaction Date"), + t, &TmpTransaction::setDatePosted, + t.getDatePosted(), newValue); } + +// //////////////////////////////////////////////////////////// + +class TmpSplitValueAndAmountCmd : public QUndoCommand +{ +public: + typedef QUndoCommand base_class; + typedef TmpSplit target_type; + typedef Numeric value_type; + + /** Constructor without a getter-function but instead the previous + * value given directly. + */ + TmpSplitValueAndAmountCmd(const QString& text, + target_type& targetRef, + const value_type& previousValue, + const value_type& newValue, + QUndoCommand *parent = 0) + : base_class(text, parent) + , m_target(targetRef) + , m_previousValue(previousValue) + , m_newValue(newValue) + { + } + + virtual void redo() { set(m_newValue); } + virtual void undo() { set(m_previousValue); } +private: + void set(const value_type& value) + { + const TmpTransaction* p_trans = m_target.getParent(); +// if (trans.countSplits() != 2) +// return; +// Split other = m_target.getOtherSplit(); +// Q_ASSERT(other); +// Commodity originCommodity = m_target.getAccount().getCommodity(); +// Commodity transCommodity = trans.getCurrency(); +// Commodity otherCommodity = other.getAccount().getCommodity(); +// if (originCommodity != transCommodity +// || transCommodity != otherCommodity) +// return; + +// trans.beginEdit(); + m_target.setValue(value); + m_target.setAmount(value); +// Numeric valueNeg = value.neg(); +// other.setAmount(valueNeg); +// other.setValue(valueNeg); +// trans.commitEdit(); + } + +protected: + target_type& m_target; + value_type m_previousValue; + value_type m_newValue; + +}; + + QUndoCommand* setSplitValueAndAmount(TmpSplit& t, const Numeric& newValue) { - return 0; + return new TmpSplitValueAndAmountCmd(QObject::tr("Edit Transaction Value"), + t, t.getValue(), newValue); } +// //////////////////////////////////////////////////////////// + + + +class TransactionCreateCmd : public QUndoCommand +{ +public: + typedef QUndoCommand base_class; + typedef TmpTransaction target_type; + + /** Constructor + */ + TransactionCreateCmd(const QString& text, + const target_type target, + QUndoCommand *parent = 0) + : base_class(text, parent) + , m_template(target) + , m_created(NULL) + {} + + virtual void redo() + { + m_created = m_template.createAsReal(); + } + + virtual void undo() + { + xaccTransDestroy(m_created.get()); + m_created.reset(); + } + +protected: + target_type m_template; + Transaction m_created; +}; + +QUndoCommand* commitNewTransaction(const TmpTransaction& t) +{ + return new TransactionCreateCmd(QObject::tr("Create Transaction"), t); +} + + } // END namespace cmd diff --git a/src/gnc/Cmd.hpp b/src/gnc/Cmd.hpp index ea241b295a..4b2c5a9e67 100644 --- a/src/gnc/Cmd.hpp +++ b/src/gnc/Cmd.hpp @@ -174,6 +174,7 @@ QUndoCommand* setTransactionDate(TmpTransaction& t, const QDate& newValue); QUndoCommand* setSplitValueAndAmount(Split& t, const Numeric& newValue); QUndoCommand* setSplitValueAndAmount(TmpSplit& t, const Numeric& newValue); QUndoCommand* destroyTransaction(Transaction& t); +QUndoCommand* commitNewTransaction(const TmpTransaction& t); } // END namespace cmd diff --git a/src/gnc/Split.cpp b/src/gnc/Split.cpp index b0d7c15b65..77a005838b 100644 --- a/src/gnc/Split.cpp +++ b/src/gnc/Split.cpp @@ -48,14 +48,14 @@ TmpSplit::TmpSplit(const Split& s, const TmpTransaction* parent_trans) , value(s.getValue()) {} -TmpSplit::TmpSplit(::Account* account) +TmpSplit::TmpSplit(::Account* _account) { - clear(account); + clear(_account); } -void TmpSplit::clear(::Account* account) +void TmpSplit::clear(::Account* _account) { - account = account; + account = _account; parent = NULL; memo.clear(); action.clear(); diff --git a/src/gnc/SplitListModel.cpp b/src/gnc/SplitListModel.cpp index 6d9a62fa82..dce8b06445 100644 --- a/src/gnc/SplitListModel.cpp +++ b/src/gnc/SplitListModel.cpp @@ -127,7 +127,7 @@ int SplitListModel::columnCount(const QModelIndex& parent) const // if (!parent.isValid()) // return 0; // else - return 8; // Fixed number for now + return COLUMN_LAST; // Fixed number for now } Qt::ItemFlags SplitListModel::flags(const QModelIndex &index) const @@ -139,14 +139,16 @@ Qt::ItemFlags SplitListModel::flags(const QModelIndex &index) const Qt::ItemFlags result = Qt::ItemIsEnabled | Qt::ItemIsSelectable; switch (index.column()) { - case 0: - case 1: - case 2: - case 4: - case 5: - case 6: + case COLUMN_DATE: + case COLUMN_NUM: + case COLUMN_DESC: + case COLUMN_RECONCILE: + case COLUMN_INCREASE: + case COLUMN_DECREASE: // Allow write access as well return result | Qt::ItemIsEditable; + case COLUMN_ACCOUNT: + case COLUMN_BALANCE: default: // Ensure read-only access only return result; @@ -170,7 +172,7 @@ QVariant SplitListModel::data(const QModelIndex& index, int role) const PrintAmountInfo printInfo(m_account, false); switch (index.column()) { - case 0: + case COLUMN_DATE: switch (role) { case Qt::DisplayRole: @@ -179,7 +181,7 @@ QVariant SplitListModel::data(const QModelIndex& index, int role) const default: return QVariant(); } - case 1: + case COLUMN_NUM: switch (role) { case Qt::DisplayRole: @@ -188,7 +190,7 @@ QVariant SplitListModel::data(const QModelIndex& index, int role) const default: return QVariant(); } - case 2: + case COLUMN_DESC: switch (role) { case Qt::DisplayRole: @@ -197,7 +199,7 @@ QVariant SplitListModel::data(const QModelIndex& index, int role) const default: return QVariant(); } - case 3: + case COLUMN_ACCOUNT: switch (role) { // case Qt::DisplayRole: @@ -205,7 +207,7 @@ QVariant SplitListModel::data(const QModelIndex& index, int role) const default: return QVariant(); } - case 4: + case COLUMN_RECONCILE: switch (role) { case Qt::DisplayRole: @@ -214,31 +216,31 @@ QVariant SplitListModel::data(const QModelIndex& index, int role) const default: return QVariant(); } - case 5: + case COLUMN_INCREASE: switch (role) { case Qt::DisplayRole: case Qt::EditRole: - if (amount.positive_p()) + if (!amount.zero_p() && amount.positive_p()) return amount.printAmount(printInfo); else return QString(); default: return QVariant(); } - case 6: + case COLUMN_DECREASE: switch (role) { case Qt::DisplayRole: case Qt::EditRole: - if (amount.positive_p()) + if (amount.zero_p() || amount.positive_p()) return QString(); else return amount.neg().printAmount(printInfo); default: return QVariant(); } - case 7: + case COLUMN_BALANCE: default: return QVariant(); } @@ -257,7 +259,7 @@ QVariant SplitListModel::data(const QModelIndex& index, int role) const switch (index.column()) { - case 0: + case COLUMN_DATE: switch (role) { case Qt::DisplayRole: @@ -266,7 +268,7 @@ QVariant SplitListModel::data(const QModelIndex& index, int role) const default: return QVariant(); } - case 1: + case COLUMN_NUM: switch (role) { case Qt::DisplayRole: @@ -275,7 +277,7 @@ QVariant SplitListModel::data(const QModelIndex& index, int role) const default: return QVariant(); } - case 2: + case COLUMN_DESC: switch (role) { case Qt::DisplayRole: @@ -284,7 +286,7 @@ QVariant SplitListModel::data(const QModelIndex& index, int role) const default: return QVariant(); } - case 3: + case COLUMN_ACCOUNT: switch (role) { case Qt::DisplayRole: @@ -292,7 +294,7 @@ QVariant SplitListModel::data(const QModelIndex& index, int role) const default: return QVariant(); } - case 4: + case COLUMN_RECONCILE: switch (role) { case Qt::DisplayRole: @@ -301,7 +303,7 @@ QVariant SplitListModel::data(const QModelIndex& index, int role) const default: return QVariant(); } - case 5: + case COLUMN_INCREASE: switch (role) { case Qt::DisplayRole: @@ -313,7 +315,7 @@ QVariant SplitListModel::data(const QModelIndex& index, int role) const default: return QVariant(); } - case 6: + case COLUMN_DECREASE: switch (role) { case Qt::DisplayRole: @@ -325,7 +327,7 @@ QVariant SplitListModel::data(const QModelIndex& index, int role) const default: return QVariant(); } - case 7: + case COLUMN_BALANCE: switch (role) { case Qt::DisplayRole: @@ -352,21 +354,21 @@ QVariant SplitListModel::headerData(int section, Qt::Orientation orientation, in { switch (section) { - case 0: + case COLUMN_DATE: return tr("Date"); - case 1: + case COLUMN_NUM: return tr("Num"); - case 2: + case COLUMN_DESC: return tr("Description"); - case 3: + case COLUMN_ACCOUNT: return tr("Transfer"); - case 4: + case COLUMN_RECONCILE: return tr("R?"); - case 5: + case COLUMN_INCREASE: return tr("Increase"); - case 6: + case COLUMN_DECREASE: return tr("Decrease"); - case 7: + case COLUMN_BALANCE: return tr("Balance"); default: return QVariant(); @@ -396,7 +398,7 @@ bool SplitListModel::setData(const QModelIndex &index, const QVariant &value, in // spooky, doesn't it? switch (index.column()) { - case 0: + case COLUMN_DATE: { QDate date = value.toDate(); if (date.isValid()) @@ -405,13 +407,13 @@ bool SplitListModel::setData(const QModelIndex &index, const QVariant &value, in } break; } - case 1: + case COLUMN_NUM: cmd = cmd::setTransactionNum(trans, value.toString()); break; - case 2: + case COLUMN_DESC: cmd = cmd::setTransactionDescription(trans, value.toString()); break; - case 4: + case COLUMN_RECONCILE: { QString str(value.toString()); if (str.size() > 0) @@ -432,22 +434,22 @@ bool SplitListModel::setData(const QModelIndex &index, const QVariant &value, in } break; } - case 5: - case 6: + case COLUMN_INCREASE: + case COLUMN_DECREASE: { QString str(value.toString().simplified()); Numeric n; QString errmsg = n.parse(str); if (errmsg.isEmpty()) { - qDebug() << "Does setting numeric work? numeric=" << n.to_string(); - if (index.column() == 6) + qDebug() << "Successfully parsed string to numeric=" << n.to_string(); + if (index.column() == COLUMN_DECREASE) n = n.neg(); // Check whether we have the simple case here - if (trans.getSplits().size() != 1) + if (trans.countSplits() != 1) { QMessageBox::warning(NULL, tr("Unimplemented"), - tr("Sorry, but editing a transaction with more than two splits (here: %1) is not yet implemented.").arg(trans.getSplits().size())); + tr("Sorry, but editing a transaction with more than two splits (here: %1) is not yet implemented.").arg(trans.countSplits())); } else { @@ -490,7 +492,7 @@ bool SplitListModel::setData(const QModelIndex &index, const QVariant &value, in // spooky, doesn't it? switch (index.column()) { - case 0: + case COLUMN_DATE: { QDate date = value.toDate(); if (date.isValid()) @@ -499,16 +501,16 @@ bool SplitListModel::setData(const QModelIndex &index, const QVariant &value, in } break; } - case 1: + case COLUMN_NUM: cmd = cmd::setTransactionNum(trans, value.toString()); break; - case 2: + case COLUMN_DESC: cmd = cmd::setTransactionDescription(trans, value.toString()); break; - case 4: + case COLUMN_RECONCILE: { QString str(value.toString()); - if (str.size() > 0) + if (!str.isEmpty()) { char recn = str[0].toLatin1(); switch (recn) @@ -526,16 +528,16 @@ bool SplitListModel::setData(const QModelIndex &index, const QVariant &value, in } break; } - case 5: - case 6: + case COLUMN_INCREASE: + case COLUMN_DECREASE: { QString str(value.toString().simplified()); Numeric n; QString errmsg = n.parse(str); if (errmsg.isEmpty()) { - qDebug() << "Does setting numeric work? numeric=" << n.to_string(); - if (index.column() == 6) + qDebug() << "Successfully parsed string to numeric=" << n.to_string(); + if (index.column() == COLUMN_DECREASE) n = n.neg(); // Check whether we have the simple case here if (split.getParent().countSplits() != 2) @@ -620,4 +622,51 @@ void SplitListModel::accountEvent( ::Account* acc, QofEventId event_type) } } +void SplitListModel::editorClosed(const QModelIndex& index, + QAbstractItemDelegate::EndEditHint hint) +{ + if (!index.isValid()) + return; + + if (m_enableNewTransaction && index.row() == m_list.size()) + { + // Special case: The line with the new transaction + + switch (hint) + { + case QAbstractItemDelegate::SubmitModelCache: + switch (index.column()) + { + case COLUMN_DATE: + case COLUMN_NUM: + case COLUMN_DESC: + case COLUMN_ACCOUNT: + case COLUMN_RECONCILE: + break; // we want to do nothing + case COLUMN_INCREASE: + case COLUMN_DECREASE: + { + // Commit the new transaction + qDebug() << "Commit the new transaction as a real one"; + QUndoCommand* cmd = cmd::commitNewTransaction(m_tmpTransaction); + recreateTmpTrans(); + m_undoStack->push(cmd); + break; + } + default: + break; // nothing to do + } + case QAbstractItemDelegate::RevertModelCache: + recreateTmpTrans(); + break; + } + } + else + { + // We are in the line of an existing transaction - no function + // implemented yet. + } + +} + } // END namespace gnc diff --git a/src/gnc/SplitListModel.hpp b/src/gnc/SplitListModel.hpp index e0cf2c0a53..d946454456 100644 --- a/src/gnc/SplitListModel.hpp +++ b/src/gnc/SplitListModel.hpp @@ -34,6 +34,7 @@ extern "C" } #include +#include #include class QUndoStack; @@ -46,6 +47,20 @@ class SplitListModel : public QAbstractItemModel { Q_OBJECT public: + + enum ColumnNumbers + { + COLUMN_DATE = 0 + , COLUMN_NUM + , COLUMN_DESC + , COLUMN_ACCOUNT + , COLUMN_RECONCILE + , COLUMN_INCREASE + , COLUMN_DECREASE + , COLUMN_BALANCE + , COLUMN_LAST + }; + SplitListModel(const Account& acc, QUndoStack* undoStack, QObject *parent = 0); ~SplitListModel(); @@ -65,6 +80,7 @@ public: public slots: void transactionEvent( ::Transaction* trans, QofEventId event_type); void accountEvent( ::Account* trans, QofEventId event_type); + void editorClosed(const QModelIndex& index, QAbstractItemDelegate::EndEditHint hint); private: void recreateCache(); diff --git a/src/gnc/SplitListView.cpp b/src/gnc/SplitListView.cpp new file mode 100644 index 0000000000..4db0747661 --- /dev/null +++ b/src/gnc/SplitListView.cpp @@ -0,0 +1,75 @@ +/* + * SplitListView.cpp + * 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 "SplitListView.hpp" + +#include "gnc/Account.hpp" +#include "gnc/SplitListModel.hpp" + +#include +#include +#include + +namespace gnc +{ + +SplitListView::SplitListView(Account account, QUndoStack* undoStack, QWidget* parent) + : base_class(parent) +{ + SplitListModel *smodel = new SplitListModel(account, undoStack, this); + setModel(smodel); + connect(this, SIGNAL(editorClosed(const QModelIndex&,QAbstractItemDelegate::EndEditHint)), + smodel, SLOT(editorClosed(const QModelIndex&,QAbstractItemDelegate::EndEditHint))); + + setAlternatingRowColors(true); + + scrollToBottom(); + if (model()->rowCount() > 0) + setCurrentIndex(model()->index(model()->rowCount() - 1, 0)); +} + +void SplitListView::closeEditor(QWidget* editor, QAbstractItemDelegate::EndEditHint hint) +{ + base_class::closeEditor(editor, hint); + //qDebug() << "closeEditor, row=" << currentIndex().row() << "hint=" << hint; + QModelIndex index = currentIndex(); + if (hint != QAbstractItemDelegate::NoHint) + emit editorClosed(index, hint); + if (index.isValid() + && hint == QAbstractItemDelegate::SubmitModelCache + && index.row() < model()->rowCount() - 1) + { + switch (index.column()) + { + case SplitListModel::COLUMN_INCREASE: + case SplitListModel::COLUMN_DECREASE: + setCurrentIndex(model()->index(index.row() + 1, + SplitListModel::COLUMN_DATE, + index.parent())); + break; + default: + break; + } + } +} + +} diff --git a/src/gnc/SplitListView.hpp b/src/gnc/SplitListView.hpp new file mode 100644 index 0000000000..6230ae7d9d --- /dev/null +++ b/src/gnc/SplitListView.hpp @@ -0,0 +1,53 @@ +/* + * SplitListView.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_SPLITLISTVIEW_HPP +#define GNC_SPLITLISTVIEW_HPP + +#include "gnc/Account.hpp" +#include "gnc/SplitListModel.hpp" + +#include +#include +#include +#include + +namespace gnc +{ + +class SplitListView : public QTableView +{ + Q_OBJECT +public: + typedef QTableView base_class; + SplitListView(Account account, QUndoStack* undoStack, QWidget* parent = 0); + +signals: + void editorClosed(const QModelIndex& index, QAbstractItemDelegate::EndEditHint hint); + +public slots: + void closeEditor(QWidget* editor, QAbstractItemDelegate::EndEditHint hint); +}; + +} + +#endif diff --git a/src/gnc/Transaction.cpp b/src/gnc/Transaction.cpp index dbdfb3eac0..29f7172c9f 100644 --- a/src/gnc/Transaction.cpp +++ b/src/gnc/Transaction.cpp @@ -91,7 +91,7 @@ void TmpTransaction::copyTo(Transaction& t) const s.copyInto(t); } } -void TmpTransaction::createAsReal() const +Transaction TmpTransaction::createAsReal() const { Q_ASSERT (!splits.isEmpty()); Account acc(splits.front().getAccount()); @@ -102,6 +102,7 @@ void TmpTransaction::createAsReal() const trans.beginEdit(); copyTo(trans); trans.commitEdit(); + return trans; } void TmpTransaction::push_back(const TmpSplit& s) { diff --git a/src/gnc/Transaction.hpp b/src/gnc/Transaction.hpp index 61172d425b..ad9c5ddf60 100644 --- a/src/gnc/Transaction.hpp +++ b/src/gnc/Transaction.hpp @@ -108,7 +108,7 @@ public: void clear(); void copyTo(Transaction& t) const; - void createAsReal() const; + Transaction createAsReal() const; QString getNum() const { return num; } void setNum(const QString& v) { num = v; } @@ -119,6 +119,7 @@ public: void push_back(const TmpSplit& s); const TmpSplitQList& getSplits() const { return splits; } TmpSplitQList& getSplits() { return splits; } + int countSplits() const { return splits.size(); } Commodity getCommodity() const { return commodity; } void setCommodity(const Commodity& v) { commodity = v; } diff --git a/src/gnc/mainwindow-file.cpp b/src/gnc/mainwindow-file.cpp index 846be50c63..026c82922c 100644 --- a/src/gnc/mainwindow-file.cpp +++ b/src/gnc/mainwindow-file.cpp @@ -397,7 +397,9 @@ void MainWindow::loadFile(const QString &fileName) "or you may not have write permission for the directory. " "If you proceed you may not be able to save any changes. " "What would you like to do?")); - QMessageBox msgBox; + QMessageBox msgBox(this); + msgBox.setWindowTitle(fmt1); + msgBox.setText(fmt2); QPushButton *openAnyway = msgBox.addButton(tr("_Open Anyway"), QMessageBox::ActionRole); QPushButton *createNewFile = msgBox.addButton(tr("_Create New File"), QMessageBox::ActionRole); QPushButton *close = msgBox.addButton(QMessageBox::Close); diff --git a/src/gnc/mainwindow.cpp b/src/gnc/mainwindow.cpp index f27ae72536..55ce21638a 100644 --- a/src/gnc/mainwindow.cpp +++ b/src/gnc/mainwindow.cpp @@ -51,8 +51,7 @@ extern "C" #include "gnc/Split.hpp" #include "gnc/SplitListModel.hpp" #include "gnc/RecentFileMenu.hpp" - -#include "gnc/Cmd.hpp" +#include "gnc/SplitListView.hpp" namespace gnc { @@ -416,7 +415,7 @@ void MainWindow::accountItemActivated(const QModelIndex & index) if (index.model() != m_accountTreeModel && index.model() != m_accountListModel) { - qDebug() << "Wrong model"; + qDebug() << "Wrong model; row=" << (index.isValid()? index.row() : -1); return; } Account account(static_cast< ::Account*>(index.internalPointer())); @@ -428,14 +427,9 @@ void MainWindow::accountItemActivated(const QModelIndex & index) // We create a new model for this account which will query it for // its splits, and also a view widget for this list. - QTableView *tableView = new QTableView(ui->tabWidget); // FIXME: Is this parent correct? - SplitListModel *smodel = new SplitListModel(account, m_undoStack, tableView); - tableView->setModel(smodel); - tableView->setAlternatingRowColors(true); - tableView->scrollToBottom(); - if (smodel->rowCount() > 0) - tableView->setCurrentIndex(smodel->index(smodel->rowCount() - 1, 0)); - ui->actionCut->setEnabled(smodel->rowCount() > 0); + QTableView *tableView = + new SplitListView(account, m_undoStack, ui->tabWidget); + ui->actionCut->setEnabled(tableView->model()->rowCount() > 0); // Insert this as a new tab tableView->setProperty(PROPERTY_TAB_PREVIOUSPOS, ui->tabWidget->currentIndex()); diff --git a/src/gnc/mainwindow.ui b/src/gnc/mainwindow.ui index f3e82ad71f..06d205c592 100644 --- a/src/gnc/mainwindow.ui +++ b/src/gnc/mainwindow.ui @@ -68,11 +68,17 @@ p, li { white-space: pre-wrap; } <p style=" margin-top:18px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" 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-size:8pt;">Currently this is more or less a proof-of-concept for developers:</span></p> <ol style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-family:'Sans'; font-size:10pt;" 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=" font-family:'Sans'; font-size:10pt;" 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=" font-family:'Sans'; font-size:10pt;" style=" margin-top:0px; margin-bottom:0px; 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> -<li style=" font-family:'Sans'; font-size:10pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Double-click on any account in either view; it will open the list of splits in that account.</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:'Sans'; font-size:10pt;">The list of splits in the account is comparable to gnucash's single line view. The amounts are already there. The dates are still missing, but that can't be hard, too.</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:'Sans'; font-size:10pt;">This is all read-only access so far, although &quot;Save&quot; probably works but hasn't been tested.</span></p> +<li style=" font-family:'Sans'; font-size:10pt;" 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 tree view and also a list view </li> +<li style=" font-family:'Sans'; font-size:10pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Double-click on any account in either view; it will open the list of splits in that account.</li> +<li style=" font-family:'Sans'; font-size:10pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Save and Save-As works as normal.</li> +<li style=" font-family:'Sans'; font-size:10pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Edit any of the existing transaction/splits: Date, Description, or Amount. Click Undo. Click Redo. Click Undo. Etc. etc.</li> +<li style=" font-family:'Sans'; font-size:10pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Delete any of the existings transactions. Or entering a new one. Click Undo. Click Redo. Etc. etc.</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:'Sans'; font-size:10pt;">The list of splits in the account is comparable to gnucash's single line view. Amounts, balance, date, all there.</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:'Sans'; font-size:10pt;">The following parts are still missing:</span></p> +<ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" font-size:8pt;" style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> Currently the accout selection of a transaction cannot be edited. </li> +<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Editing or adding multi-split transactions are not yet supported (it shows only the string &quot;--Split Transaction--&quot;). </li> +<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Editing or adding multi-currency transactions are not yet supported. </li> +<li style=" font-size:8pt;" style=" margin-top:0px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Any of the more specialized account views are not yet implemented.</li></ul> <p style=" margin-top:12px; margin-bottom:12px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">The fun part is how easy it was to add this. Let's see how far we will get...</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-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> @@ -160,12 +166,12 @@ p, li { white-space: pre-wrap; } - - &Account - false + + &Account + @@ -400,7 +406,7 @@ p, li { white-space: pre-wrap; } - + :/gtk-icons/gtk-close.png:/gtk-icons/gtk-close.png