r18890 - gnucash/trunk - Cutecash: Enable entering of more cells in register. Some code cleanup. Add class documentation.
Christian Stimming
cstim at code.gnucash.org
Thu Mar 11 16:59:46 EST 2010
Author: cstim
Date: 2010-03-11 16:59:45 -0500 (Thu, 11 Mar 2010)
New Revision: 18890
Trac: http://svn.gnucash.org/trac/changeset/18890
Added:
gnucash/trunk/src/gnc/gtk-icons/gtk-close.png
Modified:
gnucash/trunk/CMakeLists.txt
gnucash/trunk/src/gnc/Account.hpp
gnucash/trunk/src/gnc/AccountItemModel.cpp
gnucash/trunk/src/gnc/Book.hpp
gnucash/trunk/src/gnc/Cmd.cpp
gnucash/trunk/src/gnc/Cmd.hpp
gnucash/trunk/src/gnc/Numeric.hpp
gnucash/trunk/src/gnc/Session.hpp
gnucash/trunk/src/gnc/Split.hpp
gnucash/trunk/src/gnc/SplitListModel.cpp
gnucash/trunk/src/gnc/Transaction.hpp
gnucash/trunk/src/gnc/WeakPointer.hpp
gnucash/trunk/src/gnc/gtk-icons.qrc
gnucash/trunk/src/gnc/mainwindow.cpp
gnucash/trunk/src/gnc/mainwindow.hpp
gnucash/trunk/src/gnc/mainwindow.ui
Log:
Cutecash: Enable entering of more cells in register. Some code cleanup. Add class documentation.
Modified: gnucash/trunk/CMakeLists.txt
===================================================================
--- gnucash/trunk/CMakeLists.txt 2010-03-10 21:40:58 UTC (rev 18889)
+++ gnucash/trunk/CMakeLists.txt 2010-03-11 21:59:45 UTC (rev 18890)
@@ -30,6 +30,10 @@
IF (MSVC)
MESSAGE (STATUS "Hint: To create the import libraries for the gnome DLLs (e.g. gconf-2.lib), use the dlltool as follows: pexports bin/libgconf-2-4.dll > lib/libgconf-2.def ; dlltool -d lib/libgconf-2.def -D bin/libgconf-2-4.dll -l lib/gconf-2.lib")
+
+ # Disable the obnoxious min/max macros in MSVC - we want to use the
+ # function versions of them.
+ ADD_DEFINITIONS ( -DNOMINMAX )
ENDIF (MSVC)
# Libxml2
Modified: gnucash/trunk/src/gnc/Account.hpp
===================================================================
--- gnucash/trunk/src/gnc/Account.hpp 2010-03-10 21:40:58 UTC (rev 18889)
+++ gnucash/trunk/src/gnc/Account.hpp 2010-03-11 21:59:45 UTC (rev 18890)
@@ -42,6 +42,13 @@
typedef QList< ::Account*> AccountQList;
+/** Wrapper around a gnucash ::Account pointer with C++ methods for
+ * easier setter and getter access.
+ *
+ * Unfortunately this object has no information about whether the
+ * underlying gnucash ::Account object is still alive or has been
+ * deleted.
+ */
class Account : public WeakPointer< ::Account >
{
public:
Modified: gnucash/trunk/src/gnc/AccountItemModel.cpp
===================================================================
--- gnucash/trunk/src/gnc/AccountItemModel.cpp 2010-03-10 21:40:58 UTC (rev 18889)
+++ gnucash/trunk/src/gnc/AccountItemModel.cpp 2010-03-11 21:59:45 UTC (rev 18890)
@@ -104,9 +104,10 @@
//qDebug() << "data(), " << index;
if (!index.isValid())
return QVariant();
+
+ Account account(static_cast< ::Account*>(index.internalPointer()));
if (role == Qt::DisplayRole)
{
- Account account(static_cast< ::Account*>(index.internalPointer()));
switch (index.column())
{
case 0:
Modified: gnucash/trunk/src/gnc/Book.hpp
===================================================================
--- gnucash/trunk/src/gnc/Book.hpp 2010-03-10 21:40:58 UTC (rev 18889)
+++ gnucash/trunk/src/gnc/Book.hpp 2010-03-11 21:59:45 UTC (rev 18890)
@@ -37,6 +37,13 @@
{
class Account;
+/** Wrapper around a gnucash ::QofBook pointer with C++ methods for
+ * easier setter and getter access.
+ *
+ * Unfortunately this object has no information about whether the
+ * underlying gnucash ::QofBook object is still alive or has been
+ * deleted.
+ */
class Book : public WeakPointer< ::QofBook >
{
public:
Modified: gnucash/trunk/src/gnc/Cmd.cpp
===================================================================
--- gnucash/trunk/src/gnc/Cmd.cpp 2010-03-10 21:40:58 UTC (rev 18889)
+++ gnucash/trunk/src/gnc/Cmd.cpp 2010-03-11 21:59:45 UTC (rev 18890)
@@ -35,6 +35,8 @@
namespace cmd
{
+// ////////////////////////////////////////////////////////////
+
QUndoCommand* setSplitMemo(Split& t, const QString& newValue)
{
return new Cmd<Split, QString>(QObject::tr("Edit Split Memo"),
@@ -51,11 +53,30 @@
QUndoCommand* setSplitReconcile(Split& t, char newValue)
{
- return new Cmd<Split, char>(QObject::tr("Edit Split Reconcile"),
- t, &Split::setReconcile,
- &Split::getReconcile, newValue);
+ // 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 Cmd<Split, char, void (Split::*)(char)>(QObject::tr("Edit Split Reconcile"),
+ t, &Split::setReconcile,
+ &Split::getReconcile, newValue);
}
+QUndoCommand* setSplitAmount(Split& t, const Numeric& newValue)
+{
+ return new Cmd<Split, Numeric>(QObject::tr("Edit Split Amount"),
+ t, &Split::setAmount,
+ &Split::getAmount, newValue);
+}
+
+QUndoCommand* setSplitValue(Split& t, const Numeric& newValue)
+{
+ return new Cmd<Split, Numeric>(QObject::tr("Edit Split Value"),
+ t, &Split::setValue,
+ &Split::getValue, newValue);
+}
+
+// ////////////////////////////////////////////////////////////
+
QUndoCommand* setTransactionNum(Transaction& t, const QString& newValue)
{
return new Cmd<Transaction, QString>(QObject::tr("Edit Transaction Number"),
Modified: gnucash/trunk/src/gnc/Cmd.hpp
===================================================================
--- gnucash/trunk/src/gnc/Cmd.hpp 2010-03-10 21:40:58 UTC (rev 18889)
+++ gnucash/trunk/src/gnc/Cmd.hpp 2010-03-11 21:59:45 UTC (rev 18890)
@@ -34,35 +34,58 @@
class Account;
class Transaction;
-template<class TargetT, class ValueT>
+/** This is a templated implementation of a QUndoCommand class. 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.
+ *
+ * The fun part is that we can pass pointers to the getter and setter
+ * functions into this class' constructor, and the redo()/undo()
+ * implementations follow naturally. Hence, this class is already
+ * sufficient for any Command that is executed by a particular Setter
+ * function.
+ *
+ * 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 TargetT, class ValueT, typename SetterFunc = void (TargetT::*)(const ValueT&)>
class Cmd : 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;
- typedef void (TargetT::*setter_func)(const value_type&);
+
+ /// Type of the setter function to set the value in the target object
+ typedef SetterFunc setter_func;
+
+ /// Type of the getter function to retrieve the current value from the target object
typedef value_type (TargetT::*getter_func)() const;
-// Cmd(const QString& text,
-// TargetT& target, setter_func setter,
-// const value_type& previousValue,
-// const value_type& newValue,
-// QUndoCommand *parent = 0)
-// : QUndoCommand(text, parent)
-// , m_target(target)
-// , m_setter(setter)
-// , m_previousValue(previousValue)
-// , m_newValue(newValue)
-// {
-// }
-
+ /** Constructor.
+ * @param text The QUndoCommand's text which will be displayed in the Undo action.
+ * @param targetPtr 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 getter Pointer to function which returns the current value from the target object
+ * @param newValue The new value to be set
+ * @param parent The parent QUndoCommand instance, or NULL.
+ */
Cmd(const QString& text,
WeakPointer<typename TargetT::element_type>& targetPtr,
setter_func setter,
getter_func getter,
const value_type& newValue,
QUndoCommand *parent = 0)
- : QUndoCommand(text, parent)
+ : base_class(text, parent)
, m_target(targetPtr.get())
, m_setter(setter)
, m_previousValue((m_target.*getter)())
@@ -70,23 +93,55 @@
{
}
+ /** Overloaded constructor without a getter-function but instead
+ * the previous value given directly.
+ *
+ * @param text The QUndoCommand's text which will be displayed in the Undo action.
+ * @param targetPtr 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.
+ */
+ Cmd(const QString& text,
+ WeakPointer<typename TargetT::element_type>& targetPtr,
+ setter_func setter,
+ const value_type& previousValue,
+ const value_type& newValue,
+ QUndoCommand *parent = 0)
+ : base_class(text, parent)
+ , m_target(targetPtr.get())
+ , m_setter(setter)
+ , m_previousValue(previousValue)
+ , m_newValue(newValue)
+ {
+ }
+
virtual void redo()
{
- // Uh oh. The calling syntax for pointer-to-member variables
- // (here: m_setter) looks rather weird:
- (m_target.*m_setter)(m_newValue);
+ set(m_newValue);
}
+
virtual void undo()
{
- (m_target.*m_setter)(m_previousValue);
+ set(m_previousValue);
}
+private:
+ void set(const value_type& value)
+ {
+ // Uh oh. The calling syntax for pointer-to-member
+ // variables (here: m_setter) looks rather weird:
+ (m_target.*m_setter)(value);
+ }
+
protected:
TargetT m_target;
setter_func m_setter;
value_type m_previousValue;
value_type m_newValue;
+
};
namespace cmd
@@ -100,6 +155,8 @@
QUndoCommand* setSplitMemo(Split& split, const QString& newValue);
QUndoCommand* setSplitAction(Split& t, const QString& newValue);
QUndoCommand* setSplitReconcile(Split& t, char newValue);
+QUndoCommand* setSplitAmount(Split& t, const Numeric& newValue);
+QUndoCommand* setSplitValue(Split& t, const Numeric& newValue);
QUndoCommand* setTransactionNum(Transaction& t, const QString& newValue);
QUndoCommand* setTransactionDescription(Transaction& t, const QString& newValue);
QUndoCommand* setTransactionNotes(Transaction& t, const QString& newValue);
Modified: gnucash/trunk/src/gnc/Numeric.hpp
===================================================================
--- gnucash/trunk/src/gnc/Numeric.hpp 2010-03-10 21:40:58 UTC (rev 18889)
+++ gnucash/trunk/src/gnc/Numeric.hpp 2010-03-11 21:59:45 UTC (rev 18890)
@@ -41,6 +41,12 @@
class Account;
class Split;
+/** Conversion of a newly allocated gchar* to QString, which will
+ * correctly g_free() the newly allocated gchar* as well.
+ *
+ * If a gchar* does not have to be freed again, QString::fromUtf8() is
+ * sufficient and we do not need to define an extra function here.
+ */
inline QString gchar_to_QString(gchar* tmp_string)
{
QString result = QString::fromUtf8(tmp_string);
@@ -65,6 +71,13 @@
+/** Wrapper around a gnucash ::GNCPrintAmountInfo structure with C++
+ * methods for easier setter and getter access.
+ *
+ * Since this class is a derived class of the original gnucash struct,
+ * it keeps the data by-value and its member variables will always
+ * exist as long as this object exists.
+ */
class PrintAmountInfo : public ::GNCPrintAmountInfo
{
public:
@@ -86,10 +99,23 @@
static PrintAmountInfo integral() { return gnc_integral_print_info(); }
};
+
+/** Wrapper around a gnucash ::gnc_numeric structure with C++ methods
+ * for easier setter and getter access.
+ *
+ * Since this class is a derived class of the original gnucash struct,
+ * it keeps the data by-value and its member variables will always
+ * exist as long as this object exists.
+ */
class Numeric : public ::gnc_numeric
{
public:
typedef ::gnc_numeric base_class;
+ Numeric()
+ {
+ base_class::num = 0;
+ base_class::denom = 1;
+ }
Numeric(gint64 num, gint64 denom)
{
base_class::num = num;
@@ -101,6 +127,8 @@
{
*this = double_to_gnc_numeric(in, denom, how);
}
+
+ // Watch out: This conversion never seems to work!
static bool string_to_numeric(const QString& str, Numeric& n)
{
return string_to_gnc_numeric(str.toUtf8(), &n);
@@ -147,6 +175,11 @@
return a.equal(b);
}
+inline bool operator!=(const Numeric& a, const Numeric& b)
+{
+ return !(a == b);
+}
+
} // END namespace gnc
#endif
Modified: gnucash/trunk/src/gnc/Session.hpp
===================================================================
--- gnucash/trunk/src/gnc/Session.hpp 2010-03-10 21:40:58 UTC (rev 18889)
+++ gnucash/trunk/src/gnc/Session.hpp 2010-03-11 21:59:45 UTC (rev 18890)
@@ -40,8 +40,12 @@
class Book;
-/** ScopedPointer object around a QofSession object, which also owns the
- * QofSession object.
+/** Wrapper around a gnucash ::QofSession pointer with C++ methods for
+ * easier setter and getter access.
+ *
+ * Unfortunately this object has no information about whether the
+ * underlying gnucash ::QofSession object is still alive or has been
+ * deleted.
*/
class Session : public WeakPointer< ::QofSession >
{
Modified: gnucash/trunk/src/gnc/Split.hpp
===================================================================
--- gnucash/trunk/src/gnc/Split.hpp 2010-03-10 21:40:58 UTC (rev 18889)
+++ gnucash/trunk/src/gnc/Split.hpp 2010-03-11 21:59:45 UTC (rev 18890)
@@ -46,6 +46,13 @@
typedef QList< ::Split*> SplitQList;
+/** Wrapper around a gnucash ::Split pointer with C++ methods for
+ * easier setter and getter access.
+ *
+ * Unfortunately this object has no information about whether the
+ * underlying gnucash ::Split object is still alive or has been
+ * deleted.
+ */
class Split : public WeakPointer< ::Split >
{
public:
@@ -68,7 +75,7 @@
void setAction(const QString& v) { xaccSplitSetAction(get(), v.toUtf8()); }
char getReconcile() const { return xaccSplitGetReconcile(get()); }
- void setReconcile(const char& v) { xaccSplitSetReconcile(get(), v); }
+ void setReconcile(char v) { xaccSplitSetReconcile(get(), v); }
Split getOtherSplit() const { return xaccSplitGetOtherSplit(get()); }
Modified: gnucash/trunk/src/gnc/SplitListModel.cpp
===================================================================
--- gnucash/trunk/src/gnc/SplitListModel.cpp 2010-03-10 21:40:58 UTC (rev 18889)
+++ gnucash/trunk/src/gnc/SplitListModel.cpp 2010-03-11 21:59:45 UTC (rev 18890)
@@ -59,7 +59,7 @@
// if (!parent.isValid())
// return 0;
// else
- return 6; // Fixed number for now
+ return 8; // Fixed number for now
}
QVariant SplitListModel::data(const QModelIndex& index, int role) const
@@ -67,10 +67,13 @@
//qDebug() << "data(), " << index;
if (!index.isValid())
return QVariant();
+
+ Split split(static_cast< ::Split*>(index.internalPointer()));
+ Transaction trans(split.getParent());
if (role == Qt::DisplayRole)
{
- Split split(static_cast< ::Split*>(index.internalPointer()));
- Transaction trans(split.getParent());
+ Numeric amount = split.getAmount(); // Alternatively: xaccSplitConvertAmount(split.get(), split.getAccount().get());
+ PrintAmountInfo printInfo(split.get(), false);
switch (index.column())
{
case 0:
@@ -84,11 +87,17 @@
case 4:
return QChar(split.getReconcile());
case 5:
- {
- Numeric amount = split.getAmount(); // Alternatively: xaccSplitConvertAmount(split.get(), split.getAccount().get());
- PrintAmountInfo printInfo(split.get(), true);
- return amount.printAmount(printInfo);
- }
+ if (amount.positive_p())
+ return amount.printAmount(printInfo);
+ else
+ return QString();
+ case 6:
+ if (amount.positive_p())
+ return QString();
+ else
+ return amount.neg().printAmount(printInfo);
+ case 7:
+ return split.getBalance().printAmount(printInfo);
default:
return QVariant();
}
@@ -106,7 +115,12 @@
Qt::ItemFlags result = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
switch (index.column())
{
+ case 0:
+ case 1:
case 2:
+ case 4:
+ //case 5:
+ //case 6:
// Allow write access as well
return result | Qt::ItemIsEditable;
default:
@@ -125,17 +139,21 @@
switch (section)
{
case 0:
- return QString("Date");
+ return tr("Date");
case 1:
- return QString("Num");
+ return tr("Num");
case 2:
- return QString("Description");
+ return tr("Description");
case 3:
- return QString("Account");
+ return tr("Transfer");
case 4:
- return QString("Reconciled?");
+ return tr("R?");
case 5:
- return QString("Amount");
+ return tr("Increase");
+ case 6:
+ return tr("Decrease");
+ case 7:
+ return tr("Balance");
default:
return QVariant();
}
@@ -146,25 +164,67 @@
bool SplitListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
+ QUndoCommand* cmd = NULL;
if (index.isValid() && role == Qt::EditRole)
{
Split split(static_cast< ::Split*>(index.internalPointer()));
Transaction trans(split.getParent());
+
+ // "Editing" is done by creating a Cmd-object and adding it to
+ // the undo stack. That's in fact all that was needed to
+ // create an *undoable* edit of this data cell. Seems almost
+ // spooky, doesn't it?
switch (index.column())
{
+ case 0:
+ {
+ QDateTime date = value.toDateTime();
+ if (date.isValid())
+ {
+ cmd = cmd::setTransactionDate(trans, date);
+ }
+ break;
+ }
+ case 1:
+ cmd = cmd::setTransactionNum(trans, value.toString());
+ break;
case 2:
- // We allow to edit column 2. "Editing" is done by
- // creating a Cmd-object and adding it to the undo
- // stack. That's in fact all that was needed to create an
- // *undoable* edit of this data cell. Seems almost spooky,
- // doesn't it?
- m_undoStack->push(cmd::setTransactionDescription(trans, value.toString()));
- emit dataChanged(index, index);
- return true;
+ cmd = cmd::setTransactionDescription(trans, value.toString());
+ break;
+ case 4:
+ cmd = cmd::setSplitReconcile(split, value.toChar().toLatin1());
+ break;
+ case 5:
+ {
+ bool x;
+ double v = value.toDouble(&x);
+ if (!x)
+ {
+ qDebug() << "Cannot convert string to gnc_numeric:" << value.toString();
+ }
+ else
+ {
+ Numeric n(v, 100, GNC_HOW_RND_ROUND);
+ qDebug() << "Does setting numeric work? numeric=" << n.to_string();
+ cmd = cmd::setSplitAmount(split, n);
+ }
+ // Sigh. This doesn't seem to work so far.
+ break;
+ }
+// case 6:
+// cmd = cmd::setSplitAmount(split, Numeric(value.toString()).neg());
+// break;
+
default:
- return false;
+ break;
}
}
+ if (cmd)
+ {
+ m_undoStack->push(cmd);
+ emit dataChanged(index, index);
+ return true;
+ }
return false;
}
Modified: gnucash/trunk/src/gnc/Transaction.hpp
===================================================================
--- gnucash/trunk/src/gnc/Transaction.hpp 2010-03-10 21:40:58 UTC (rev 18889)
+++ gnucash/trunk/src/gnc/Transaction.hpp 2010-03-11 21:59:45 UTC (rev 18890)
@@ -42,6 +42,13 @@
namespace gnc
{
+/** Wrapper around a gnucash ::Transaction pointer with C++ methods for
+ * easier setter and getter access.
+ *
+ * Unfortunately this object has no information about whether the
+ * underlying gnucash ::Transaction object is still alive or has been
+ * deleted.
+ */
class Transaction : public WeakPointer< ::Transaction >
{
public:
Modified: gnucash/trunk/src/gnc/WeakPointer.hpp
===================================================================
--- gnucash/trunk/src/gnc/WeakPointer.hpp 2010-03-10 21:40:58 UTC (rev 18889)
+++ gnucash/trunk/src/gnc/WeakPointer.hpp 2010-03-11 21:59:45 UTC (rev 18890)
@@ -31,9 +31,13 @@
/** A thin wrapper for a C object which is owned by someone else.
*
- * This copies the interface of the boost::scoped_ptr, but with the
- * boost::shared_ptr possiblity of a custom deleter function because
- * we need that.
+ * This copies the interface of the boost::scoped_ptr, but in contrast
+ * to the boost::scoped_ptr this class does not take on ownership of
+ * the given pointer. Instead, the pointer is owned by someone else,
+ * and we hope nobody accesses this object after the pointer's object
+ * was deleted somewhere else. Unfortunately currently we have no
+ * information about whether the pointed-to object is still alive or
+ * already deleted. Sorry for that.
*/
template<class T>
class WeakPointer
Added: gnucash/trunk/src/gnc/gtk-icons/gtk-close.png
===================================================================
--- gnucash/trunk/src/gnc/gtk-icons/gtk-close.png (rev 0)
+++ gnucash/trunk/src/gnc/gtk-icons/gtk-close.png 2010-03-11 21:59:45 UTC (rev 18890)
@@ -0,0 +1,14 @@
+PNG
+
++ûf«ó?ð4HÜH.·@0ÀQ@/ÇE`±FGb,|>Á' H+ðäãáÈÀ@tÝÝÝ+°W\ñúÖÉ,E£Ñþ $Õj<ÏZ
+ÏǺËU(L
+
+Ý|´¹¹yòÖ3ó¡¡÷e¿ßOÊetu¹Ín7týÐz×ëeõ²¯ÇÃB:¥â¥ÉÉÉnârþ>ø^DEñosMÓÄf¢ppppä`Ù6¯×ËË:<½ÖÉ9;u]DH&§WÎÀÕÎ=¥ ôq%½·Û
+UU[©ì_Éç¦i1~±,3ì÷¤¤Ð'ôË´C©Ôó+ü\µV
Ð'p)5u@/£æy
+àÐftc;»=!"«iZCËh»¿-ÝÏçóµ¦f³Ùz½~>jF r¹Ümv@{³\ No newline at end of file
Modified: gnucash/trunk/src/gnc/gtk-icons.qrc
===================================================================
--- gnucash/trunk/src/gnc/gtk-icons.qrc 2010-03-10 21:40:58 UTC (rev 18889)
+++ gnucash/trunk/src/gnc/gtk-icons.qrc 2010-03-11 21:59:45 UTC (rev 18890)
@@ -1,6 +1,7 @@
<RCC>
<qresource>
<file>gtk-icons/gtk-about.png</file>
+ <file>gtk-icons/gtk-close.png</file>
<file>gtk-icons/gtk-copy.png</file>
<file>gtk-icons/gtk-cut.png</file>
<file>gtk-icons/gtk-new.png</file>
Modified: gnucash/trunk/src/gnc/mainwindow.cpp
===================================================================
--- gnucash/trunk/src/gnc/mainwindow.cpp 2010-03-10 21:40:58 UTC (rev 18889)
+++ gnucash/trunk/src/gnc/mainwindow.cpp 2010-03-11 21:59:45 UTC (rev 18890)
@@ -69,6 +69,13 @@
/* This static indicates the debugging module that this .o belongs to. */
static QofLogModule log_module = GNC_MOD_GUI;
+static const char* PROPERTY_TAB_LABEL = "tab_label";
+static const char* PROPERTY_TAB_POSITION = "tab_position";
+static const char* PROPERTY_TAB_ISCURRENT = "tab_iscurrent";
+static const char* PROPERTY_TAB_PREVIOUSPOS = "tab_previouspos";
+
+// ////////////////////////////////////////////////////////////
+
MainWindow::MainWindow()
: ui(new Ui::MainWindow)
, m_undoStack(new QUndoStack(this))
@@ -125,13 +132,13 @@
// Auto-connected to ui->actionSave's signal triggered()
bool MainWindow::on_actionSave_triggered()
{
- if (curFile.isEmpty())
+ if (m_currentFilename.isEmpty())
{
return on_actionSave_as_triggered();
}
else
{
- return saveFile(curFile);
+ return saveFile(m_currentFilename);
}
}
@@ -183,21 +190,21 @@
ui->actionSave->setShortcuts(QKeySequence::Save);
ui->actionSave_as->setShortcuts(QKeySequence::SaveAs);
- QAction *redo = m_undoStack->createRedoAction(ui->menuEdit, tr("&Redo"));
- redo->setIcon(QIcon(":/gtk-icons/gtk-redo.png"));
- redo->setShortcuts(QKeySequence::Redo);
- QAction *undo = m_undoStack->createUndoAction(ui->menuEdit, tr("&Undo"));
- undo->setIcon(QIcon(":/gtk-icons/gtk-undo.png"));
- undo->setShortcuts(QKeySequence::Undo);
- ui->menuEdit->insertAction(ui->actionCut, undo);
- ui->menuEdit->insertAction(ui->actionCut, redo);
+ m_actionRedo = m_undoStack->createRedoAction(ui->menuEdit, tr("&Redo"));
+ m_actionRedo->setIcon(QIcon(":/gtk-icons/gtk-redo.png"));
+ m_actionRedo->setShortcuts(QKeySequence::Redo);
+ m_actionUndo = m_undoStack->createUndoAction(ui->menuEdit, tr("&Undo"));
+ m_actionUndo->setIcon(QIcon(":/gtk-icons/gtk-undo.png"));
+ m_actionUndo->setShortcuts(QKeySequence::Undo);
+ ui->menuEdit->insertAction(ui->actionCut, m_actionUndo);
+ ui->menuEdit->insertAction(ui->actionCut, m_actionRedo);
ui->menuEdit->insertSeparator(ui->actionCut);
ui->actionCut->setShortcuts(QKeySequence::Cut);
ui->actionCopy->setShortcuts(QKeySequence::Copy);
ui->actionPaste->setShortcuts(QKeySequence::Paste);
- ui->actionViewClose->setShortcuts(QKeySequence::Close);
+ ui->actionCloseTab->setShortcuts(QKeySequence::Close);
connect(ui->actionNew, SIGNAL(triggered()), this, SLOT(newFile()));
connect(ui->actionExit, SIGNAL(triggered()), this, SLOT(close()));
@@ -229,15 +236,18 @@
connect(menuRecentFiles, SIGNAL(fileSelected(const QString &)),
this, SLOT(loadFileMaybe(const QString&)));
- fileToolBar = addToolBar(tr("File"));
- fileToolBar->addAction(ui->actionNew);
- fileToolBar->addAction(ui->actionOpen);
- fileToolBar->addAction(ui->actionSave);
+ m_fileToolBar = addToolBar(tr("File"));
+ m_fileToolBar->addAction(ui->actionNew);
+ m_fileToolBar->addAction(ui->actionOpen);
+ m_fileToolBar->addAction(ui->actionSave);
+ m_fileToolBar->addAction(ui->actionCloseTab);
- editToolBar = addToolBar(tr("Edit"));
- editToolBar->addAction(ui->actionCut);
- editToolBar->addAction(ui->actionCopy);
- editToolBar->addAction(ui->actionPaste);
+ m_editToolBar = addToolBar(tr("Edit"));
+ m_editToolBar->addAction(m_actionUndo);
+ m_editToolBar->addAction(m_actionRedo);
+ m_editToolBar->addAction(ui->actionCut);
+ m_editToolBar->addAction(ui->actionCopy);
+ m_editToolBar->addAction(ui->actionPaste);
}
void MainWindow::createStatusBar()
@@ -283,7 +293,7 @@
void MainWindow::setCurrentFile(const QString &fileName)
{
menuRecentFiles->usingFile(fileName);
- curFile = fileName;
+ m_currentFilename = fileName;
// ui->textEdit->document()->setModified(false);
setWindowModified(false);
@@ -293,10 +303,10 @@
void MainWindow::updateWindowTitle()
{
QString shownName;
- if (curFile.isEmpty())
+ if (m_currentFilename.isEmpty())
shownName = "untitled.txt";
else
- shownName = strippedName(curFile);
+ shownName = strippedName(m_currentFilename);
setWindowTitle(tr("%1[*]%2 - %3").arg(shownName).arg(isWindowModified() ? "(*)" : "").arg(tr("Application")));
}
@@ -309,8 +319,8 @@
// ////////////////////////////////////////////////////////////
-// Auto-connected to ui->actionViewClose's signal triggered
-void MainWindow::on_actionViewClose_triggered()
+// Auto-connected to ui->actionCloseTab's signal triggered
+void MainWindow::on_actionCloseTab_triggered()
{
on_tabWidget_tabCloseRequested(ui->tabWidget->currentIndex());
}
@@ -336,6 +346,9 @@
}
else
{
+ QVariant prevPos = widget->property(PROPERTY_TAB_PREVIOUSPOS);
+ if (prevPos.isValid())
+ ui->tabWidget->setCurrentIndex(prevPos.toInt());
ui->tabWidget->removeTab(index);
delete widget;
}
@@ -363,14 +376,19 @@
{
if (checked)
{
- QVariant tabLabel = widget->property("tab_label");
+ QVariant tabLabel = widget->property(PROPERTY_TAB_LABEL);
Q_ASSERT(tabLabel.isValid());
- QVariant tabPosition = widget->property("tab_position");
+ QVariant tabPosition = widget->property(PROPERTY_TAB_POSITION);
Q_ASSERT(tabPosition.isValid());
- QVariant tabIsCurrent = widget->property("tab_iscurrent");
- Q_ASSERT(tabIsCurrent.isValid());
+ QVariant tabIsCurrentV = widget->property(PROPERTY_TAB_ISCURRENT);
+ Q_ASSERT(tabIsCurrentV.isValid());
+ bool tabIsCurrent = tabIsCurrentV.toBool();
+
+ if (tabIsCurrent)
+ widget->setProperty(PROPERTY_TAB_PREVIOUSPOS, ui->tabWidget->currentIndex());
+
ui->tabWidget->insertTab(tabPosition.toInt(), widget, tabLabel.toString());
- if (tabIsCurrent.toBool())
+ if (tabIsCurrent)
ui->tabWidget->setCurrentWidget(widget);
}
else
@@ -382,10 +400,13 @@
void MainWindow::reallyRemoveTab(int index)
{
QWidget *widget = ui->tabWidget->widget(index);
- widget->setProperty("tab_label", ui->tabWidget->tabText(index));
- widget->setProperty("tab_position", index);
- widget->setProperty("tab_iscurrent", (index == ui->tabWidget->currentIndex()));
+ widget->setProperty(PROPERTY_TAB_LABEL, ui->tabWidget->tabText(index));
+ widget->setProperty(PROPERTY_TAB_POSITION, index);
+ widget->setProperty(PROPERTY_TAB_ISCURRENT, (index == ui->tabWidget->currentIndex()));
ui->tabWidget->removeTab(index);
+ QVariant prevPos = widget->property(PROPERTY_TAB_PREVIOUSPOS);
+ if (prevPos.isValid())
+ ui->tabWidget->setCurrentIndex(prevPos.toInt());
}
// Auto-connected to ui->tabWidget's signal currentChanged(int)
@@ -422,6 +443,7 @@
tableView->setAlternatingRowColors(true);
// Insert this as a new tab
+ tableView->setProperty(PROPERTY_TAB_PREVIOUSPOS, ui->tabWidget->currentIndex());
ui->tabWidget->addTab(tableView, account.getName());
ui->tabWidget->setCurrentWidget(tableView);
}
@@ -565,7 +587,8 @@
"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? Open anyway? FIXME"));
- if (QMessageBox::question(this, fmt1, fmt2)
+ if (QMessageBox::question(this, fmt1, fmt2,
+ QMessageBox::Ok | QMessageBox::Cancel)
== QMessageBox::Ok)
{
/* user told us to ignore locks. So ignore them. */
@@ -585,7 +608,8 @@
(ERR_SQL_DB_TOO_OLD == io_err))
{
if (QMessageBox::question(this, tr("Create New File?"),
- tr("The file %1 does not exist. Do you want to create it?").arg(fileName))
+ tr("The file %1 does not exist. Do you want to create it?").arg(fileName),
+ QMessageBox::Ok | QMessageBox::Cancel)
== QMessageBox::Ok)
{
/* user told us to create a new database. Do it. */
@@ -613,7 +637,8 @@
tr("The file %1 has some errors: %2: %3. Open anyway?")
.arg(fileName)
.arg(errorToString(io_err))
- .arg(errorToDescription(io_err)))
+ .arg(errorToDescription(io_err)),
+ QMessageBox::Ok | QMessageBox::Cancel)
== QMessageBox::Ok);
}
}
@@ -655,10 +680,11 @@
if (io_err != ERR_BACKEND_NO_ERR)
{
we_are_in_error = !(QMessageBox::question(this, tr("Error on Open"),
- tr("There was an error opening the file %1: %2: %3. FIXME")
+ tr("There was an error opening the file %1: %2: %3. Continue? FIXME")
.arg(fileName)
.arg(errorToString(io_err))
- .arg(errorToDescription(io_err)))
+ .arg(errorToDescription(io_err)),
+ QMessageBox::Ok | QMessageBox::Cancel)
== QMessageBox::Ok);
}
}
@@ -690,6 +716,7 @@
m_accountTreeModel = new AccountTreeModel(root, this);
ui->treeView->setModel(m_accountTreeModel);
+ ui->treeViewTab->setProperty(PROPERTY_TAB_PREVIOUSPOS, ui->tabWidget->currentIndex());
ui->tabWidget->setCurrentWidget(ui->treeViewTab);
}
else
@@ -736,7 +763,8 @@
if (ERR_BACKEND_LOCKED == io_err || ERR_BACKEND_READONLY == io_err)
{
if (QMessageBox::question(this, tr("Ignore Lock?"),
- tr("The file %1 is locked. Should we ignore the lock?").arg(fileName))
+ tr("The file %1 is locked. Should we ignore the lock?").arg(fileName),
+ QMessageBox::Ok | QMessageBox::Cancel)
== QMessageBox::Ok)
{
/* user told us to ignore locks. So ignore them. */
@@ -750,7 +778,9 @@
(ERR_SQL_DB_TOO_OLD == io_err))
{
if (QMessageBox::question(this, tr("Create New File?"),
- tr("The file %1 does not exist. Should it be created?").arg(fileName)))
+ tr("The file %1 does not exist. Should it be created?").arg(fileName),
+ QMessageBox::Ok | QMessageBox::Cancel)
+ == QMessageBox::Ok)
{
/* user told us to create a new database. Do it. */
qof_session_begin (new_session, newfile, FALSE, TRUE);
Modified: gnucash/trunk/src/gnc/mainwindow.hpp
===================================================================
--- gnucash/trunk/src/gnc/mainwindow.hpp 2010-03-10 21:40:58 UTC (rev 18889)
+++ gnucash/trunk/src/gnc/mainwindow.hpp 2010-03-11 21:59:45 UTC (rev 18890)
@@ -44,6 +44,11 @@
class RecentFileMenu;
+/** The main window of Cutecash.
+ *
+ * Some of the action parts in here should probably be refactored into
+ * separate classes/functions.
+ */
class MainWindow : public QMainWindow
{
Q_OBJECT
@@ -66,13 +71,13 @@
bool on_actionSave_triggered();
void on_actionAbout_triggered();
bool on_actionSave_as_triggered();
+ void on_actionCloseTab_triggered();
void on_tabWidget_tabCloseRequested(int index);
void on_tabWidget_currentChanged(int index);
void on_textBrowser_anchorClicked(const QUrl &);
void on_actionViewAccountTree_triggered(bool checked);
void on_actionViewAccountList_triggered(bool checked);
void on_actionViewWelcomepage_triggered(bool checked);
- void on_actionViewClose_triggered();
void documentWasModified();
private:
@@ -92,10 +97,12 @@
Ui::MainWindow *ui;
- QString curFile;
+ QString m_currentFilename;
- QToolBar *fileToolBar;
- QToolBar *editToolBar;
+ QToolBar *m_fileToolBar;
+ QToolBar *m_editToolBar;
+ QAction *m_actionUndo;
+ QAction *m_actionRedo;
RecentFileMenu *menuRecentFiles;
QUndoStack *m_undoStack;
Modified: gnucash/trunk/src/gnc/mainwindow.ui
===================================================================
--- gnucash/trunk/src/gnc/mainwindow.ui 2010-03-10 21:40:58 UTC (rev 18889)
+++ gnucash/trunk/src/gnc/mainwindow.ui 2010-03-11 21:59:45 UTC (rev 18890)
@@ -148,6 +148,8 @@
<addaction name="actionSave"/>
<addaction name="actionSave_as"/>
<addaction name="separator"/>
+ <addaction name="actionCloseTab"/>
+ <addaction name="separator"/>
<addaction name="actionExit"/>
</widget>
<widget class="QMenu" name="menuHelp">
@@ -182,8 +184,6 @@
<property name="title">
<string>&View</string>
</property>
- <addaction name="actionViewClose"/>
- <addaction name="separator"/>
<addaction name="actionViewWelcomepage"/>
<addaction name="actionViewAccountList"/>
<addaction name="actionViewAccountTree"/>
@@ -398,7 +398,11 @@
<string>Account &Tree</string>
</property>
</action>
- <action name="actionViewClose">
+ <action name="actionCloseTab">
+ <property name="icon">
+ <iconset resource="gnucash.qrc">
+ <normaloff>:/gtk-icons/gtk-close.png</normaloff>:/gtk-icons/gtk-close.png</iconset>
+ </property>
<property name="text">
<string>&Close Current Tab</string>
</property>
More information about the gnucash-changes
mailing list