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:
Christian Stimming 2010-03-11 21:59:45 +00:00
parent 81ec044f82
commit 4212c0c786
17 changed files with 359 additions and 105 deletions

View File

@ -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

View File

@ -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:

View File

@ -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:

View File

@ -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:

View File

@ -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"),

View File

@ -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);

View File

@ -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

View File

@ -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 >
{

View File

@ -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()); }

View File

@ -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;
}

View File

@ -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:

View File

@ -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

View File

@ -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>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@ -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);

View File

@ -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;

View File

@ -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>&amp;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 &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>