mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Cutecash: Enable entering of more cells in register. Some code cleanup. Add class documentation.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18890 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
81ec044f82
commit
4212c0c786
@ -30,6 +30,10 @@ PKG_CHECK_MODULES (GTHREAD gthread-2.0>=2.12.0)
|
||||
|
||||
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
|
||||
|
@ -42,6 +42,13 @@ namespace gnc
|
||||
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:
|
||||
|
@ -104,9 +104,10 @@ QVariant AccountTreeModel::data(const QModelIndex& index, int role) const
|
||||
//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:
|
||||
|
@ -37,6 +37,13 @@ namespace gnc
|
||||
{
|
||||
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:
|
||||
|
@ -35,6 +35,8 @@ template class Cmd<Account, QString>;
|
||||
namespace cmd
|
||||
{
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
|
||||
QUndoCommand* setSplitMemo(Split& t, const QString& newValue)
|
||||
{
|
||||
return new Cmd<Split, QString>(QObject::tr("Edit Split Memo"),
|
||||
@ -51,11 +53,30 @@ QUndoCommand* setSplitAction(Split& t, const QString& newValue)
|
||||
|
||||
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"),
|
||||
|
105
src/gnc/Cmd.hpp
105
src/gnc/Cmd.hpp
@ -34,35 +34,58 @@ class Split;
|
||||
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 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
virtual void redo()
|
||||
/** 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)
|
||||
{
|
||||
// Uh oh. The calling syntax for pointer-to-member variables
|
||||
// (here: m_setter) looks rather weird:
|
||||
(m_target.*m_setter)(m_newValue);
|
||||
}
|
||||
virtual void undo()
|
||||
{
|
||||
(m_target.*m_setter)(m_previousValue);
|
||||
}
|
||||
|
||||
virtual void redo()
|
||||
{
|
||||
set(m_newValue);
|
||||
}
|
||||
|
||||
virtual void undo()
|
||||
{
|
||||
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 @@ namespace cmd
|
||||
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);
|
||||
|
@ -41,6 +41,12 @@ namespace gnc
|
||||
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 @@ inline ::Timespec toTimespec(const QDateTime& qdt)
|
||||
|
||||
|
||||
|
||||
/** 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 @@ public:
|
||||
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 @@ public:
|
||||
{
|
||||
*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 @@ inline bool operator==(const Numeric& a, const Numeric& b)
|
||||
return a.equal(b);
|
||||
}
|
||||
|
||||
inline bool operator!=(const Numeric& a, const Numeric& b)
|
||||
{
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
} // END namespace gnc
|
||||
|
||||
#endif
|
||||
|
@ -40,8 +40,12 @@ namespace gnc
|
||||
|
||||
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 >
|
||||
{
|
||||
|
@ -46,6 +46,13 @@ class Transaction;
|
||||
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 @@ public:
|
||||
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()); }
|
||||
|
||||
|
@ -59,7 +59,7 @@ int SplitListModel::columnCount(const QModelIndex& parent) const
|
||||
// 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 @@ QVariant SplitListModel::data(const QModelIndex& index, int role) const
|
||||
//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 @@ QVariant SplitListModel::data(const QModelIndex& index, int role) const
|
||||
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 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:
|
||||
// Allow write access as well
|
||||
return result | Qt::ItemIsEditable;
|
||||
default:
|
||||
@ -125,17 +139,21 @@ QVariant SplitListModel::headerData(int section, Qt::Orientation orientation, in
|
||||
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,24 +164,66 @@ QVariant SplitListModel::headerData(int section, Qt::Orientation orientation, in
|
||||
|
||||
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 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;
|
||||
default:
|
||||
return false;
|
||||
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:
|
||||
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:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cmd)
|
||||
{
|
||||
m_undoStack->push(cmd);
|
||||
emit dataChanged(index, index);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -42,6 +42,13 @@ extern "C"
|
||||
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:
|
||||
|
@ -31,9 +31,13 @@ namespace gnc
|
||||
|
||||
/** 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
|
||||
|
@ -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>
|
||||
|
BIN
src/gnc/gtk-icons/gtk-close.png
Normal file
BIN
src/gnc/gtk-icons/gtk-close.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
@ -69,6 +69,13 @@ inline QString errorToDescription(QofBackendError err)
|
||||
/* 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 @@ void MainWindow::loadFileMaybe(const QString &fileName)
|
||||
// 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 @@ void MainWindow::createActions()
|
||||
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 @@ void MainWindow::createToolBars()
|
||||
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 @@ bool MainWindow::maybeSave()
|
||||
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::setCurrentFile(const QString &fileName)
|
||||
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 @@ QString MainWindow::strippedName(const QString &fullFileName)
|
||||
|
||||
// ////////////////////////////////////////////////////////////
|
||||
|
||||
// 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 @@ void MainWindow::on_tabWidget_tabCloseRequested(int index)
|
||||
}
|
||||
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 @@ void MainWindow::viewOrHideTab(bool checked, QWidget *widget)
|
||||
{
|
||||
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::viewOrHideTab(bool checked, QWidget *widget)
|
||||
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 @@ void MainWindow::accountItemActivated(const QModelIndex & index)
|
||||
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 @@ 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? 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 @@ void MainWindow::loadFile(const QString &fileName)
|
||||
(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 @@ void MainWindow::loadFile(const QString &fileName)
|
||||
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 @@ void MainWindow::loadFile(const QString &fileName)
|
||||
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 @@ void MainWindow::loadFile(const QString &fileName)
|
||||
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 @@ bool MainWindow::saveFile(const QString &fileName)
|
||||
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 @@ bool MainWindow::saveFile(const QString &fileName)
|
||||
(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);
|
||||
|
@ -44,6 +44,11 @@ namespace gnc
|
||||
|
||||
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 @@ private slots:
|
||||
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 @@ private:
|
||||
|
||||
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;
|
||||
|
||||
|
@ -148,6 +148,8 @@ p, li { white-space: pre-wrap; }
|
||||
<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 @@ p, li { white-space: pre-wrap; }
|
||||
<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 @@ p, li { white-space: pre-wrap; }
|
||||
<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>
|
||||
|
Loading…
Reference in New Issue
Block a user