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«ó‚?ð4‘H܇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
+àÐf™tc;»=!Š"«iZCËh»¿-ÝÏç󵦎f³Ù“z½~Ÿ‚>jF r¹ÜŽm›v@{³‚\ 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>&amp;View</string>
     </property>
-    <addaction name="actionViewClose"/>
-    <addaction name="separator"/>
     <addaction name="actionViewWelcomepage"/>
     <addaction name="actionViewAccountList"/>
     <addaction name="actionViewAccountTree"/>
@@ -398,7 +398,11 @@
     <string>Account &amp;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>&amp;Close Current Tab</string>
    </property>



More information about the gnucash-changes mailing list