mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Cutecash: Add QUndoStack to implement all editing through the Command pattern and make it undoable.
git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18887 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
parent
4bb186ef14
commit
0f09fc5e32
100
src/gnc/Cmd.hpp
Normal file
100
src/gnc/Cmd.hpp
Normal file
@ -0,0 +1,100 @@
|
||||
/*
|
||||
* Cmd.hpp
|
||||
* Copyright (C) 2010 Christian Stimming
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, contact:
|
||||
*
|
||||
* Free Software Foundation Voice: +1-617-542-5942
|
||||
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
|
||||
* Boston, MA 02110-1301, USA gnu@gnu.org
|
||||
*/
|
||||
|
||||
#ifndef GNC_CMD_HPP
|
||||
#define GNC_CMD_HPP
|
||||
|
||||
#include <QUndoCommand>
|
||||
#include <gnc/Split.hpp>
|
||||
|
||||
namespace gnc
|
||||
{
|
||||
|
||||
template<class TargetT, class ValueT>
|
||||
class Cmd : public QUndoCommand
|
||||
{
|
||||
public:
|
||||
typedef TargetT target_type;
|
||||
typedef ValueT value_type;
|
||||
typedef void (TargetT::*setter_func)(const value_type&);
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
Cmd(const QString& text,
|
||||
TargetT& target, setter_func setter,
|
||||
getter_func getter,
|
||||
const value_type& newValue,
|
||||
QUndoCommand *parent = 0)
|
||||
: QUndoCommand(text, parent)
|
||||
, m_target(target)
|
||||
, m_setter(setter)
|
||||
, m_previousValue((m_target.*getter)())
|
||||
, 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);
|
||||
}
|
||||
virtual void undo()
|
||||
{
|
||||
(m_target.*m_setter)(m_previousValue);
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
TargetT& m_target;
|
||||
setter_func m_setter;
|
||||
value_type m_previousValue;
|
||||
value_type m_newValue;
|
||||
};
|
||||
|
||||
namespace cmd
|
||||
{
|
||||
|
||||
QUndoCommand* setSplitMemo(Split& split, const QString& newValue)
|
||||
{
|
||||
return new Cmd<Split, QString>(QWidget::tr("Edit Split Memo"),
|
||||
split, &Split::setMemo,
|
||||
&Split::getMemo, newValue);
|
||||
}
|
||||
|
||||
} // END namespace cmd
|
||||
|
||||
} // END namespace gnc
|
||||
|
||||
#endif
|
@ -26,6 +26,7 @@
|
||||
#include <QtGui/QMessageBox>
|
||||
#include <QtGui/QToolBar>
|
||||
#include <QtGui/QProgressBar>
|
||||
#include <QtGui/QUndoStack>
|
||||
#include <QDebug>
|
||||
|
||||
#include "config.h"
|
||||
@ -51,9 +52,14 @@ extern "C"
|
||||
#include "gnc/SplitListModel.hpp"
|
||||
#include "gnc/RecentFileMenu.hpp"
|
||||
|
||||
#include "gnc/Cmd.hpp"
|
||||
|
||||
namespace gnc
|
||||
{
|
||||
|
||||
// Explicit instantiations to check for compiler errors
|
||||
template class Cmd<Account, QString>;
|
||||
|
||||
inline QString errorToString(QofBackendError err)
|
||||
{
|
||||
return errorToStringPair(err).first;
|
||||
@ -68,6 +74,7 @@ static QofLogModule log_module = GNC_MOD_GUI;
|
||||
|
||||
MainWindow::MainWindow()
|
||||
: ui(new Ui::MainWindow)
|
||||
, m_undoStack(new QUndoStack(this))
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
@ -79,6 +86,8 @@ MainWindow::MainWindow()
|
||||
|
||||
// connect(ui->labelMain, SIGNAL(linkActivated(const QString&)),
|
||||
// this, SLOT(documentWasModified()));
|
||||
connect(m_undoStack, SIGNAL(cleanChanged(bool)),
|
||||
this, SLOT(documentCleanStateChanged(bool)));
|
||||
|
||||
setWindowIcon(QIcon(":/pixmaps/gnucash-icon-32x32.png"));
|
||||
|
||||
@ -150,7 +159,16 @@ void MainWindow::on_actionAbout_triggered()
|
||||
|
||||
void MainWindow::documentWasModified()
|
||||
{
|
||||
// setWindowModified(ui->textEdit->document()->isModified());
|
||||
setWindowModified(true);
|
||||
}
|
||||
|
||||
void MainWindow::documentCleanStateChanged(bool clean)
|
||||
{
|
||||
bool unchanged = (clean == isWindowModified());
|
||||
|
||||
setWindowModified(!clean);
|
||||
if (!unchanged)
|
||||
updateWindowTitle();
|
||||
}
|
||||
|
||||
// Auto-connected to ui->textBrowser's signal anchorClicked()
|
||||
@ -167,6 +185,21 @@ void MainWindow::createActions()
|
||||
ui->actionOpen->setShortcuts(QKeySequence::Open);
|
||||
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);
|
||||
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);
|
||||
|
||||
connect(ui->actionNew, SIGNAL(triggered()), this, SLOT(newFile()));
|
||||
@ -257,13 +290,18 @@ void MainWindow::setCurrentFile(const QString &fileName)
|
||||
// ui->textEdit->document()->setModified(false);
|
||||
setWindowModified(false);
|
||||
|
||||
updateWindowTitle();
|
||||
}
|
||||
|
||||
void MainWindow::updateWindowTitle()
|
||||
{
|
||||
QString shownName;
|
||||
if (curFile.isEmpty())
|
||||
shownName = "untitled.txt";
|
||||
else
|
||||
shownName = strippedName(curFile);
|
||||
|
||||
setWindowTitle(tr("%1[*] - %2").arg(shownName).arg(tr("Application")));
|
||||
setWindowTitle(tr("%1[*]%2 - %3").arg(shownName).arg(isWindowModified() ? "(*)" : "").arg(tr("Application")));
|
||||
}
|
||||
|
||||
QString MainWindow::strippedName(const QString &fullFileName)
|
||||
|
@ -32,6 +32,7 @@ class QMenu;
|
||||
class QPlainTextEdit;
|
||||
class QTextEdit;
|
||||
class QTabWidget;
|
||||
class QUndoStack;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
@ -54,6 +55,7 @@ public:
|
||||
public slots:
|
||||
void accountItemActivated(const QModelIndex & index);
|
||||
void loadFileMaybe(const QString &fileName);
|
||||
void documentCleanStateChanged(bool clean);
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent *event);
|
||||
@ -86,6 +88,7 @@ private:
|
||||
QString strippedName(const QString &fullFileName);
|
||||
void viewOrHideTab(bool checkedView, QWidget *widget);
|
||||
void reallyRemoveTab(int index);
|
||||
void updateWindowTitle();
|
||||
|
||||
Ui::MainWindow *ui;
|
||||
|
||||
@ -94,6 +97,7 @@ private:
|
||||
QToolBar *fileToolBar;
|
||||
QToolBar *editToolBar;
|
||||
RecentFileMenu *menuRecentFiles;
|
||||
QUndoStack *m_undoStack;
|
||||
|
||||
Session m_session;
|
||||
AccountListModel *m_accountListModel;
|
||||
|
@ -174,9 +174,6 @@ p, li { white-space: pre-wrap; }
|
||||
<property name="title">
|
||||
<string>&Edit</string>
|
||||
</property>
|
||||
<addaction name="action_Undo"/>
|
||||
<addaction name="action_Redo"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionCut"/>
|
||||
<addaction name="actionCopy"/>
|
||||
<addaction name="actionPaste"/>
|
||||
@ -368,30 +365,6 @@ p, li { white-space: pre-wrap; }
|
||||
<string>About Qt</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Undo">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="gtk-icons.qrc">
|
||||
<normaloff>:/gtk-icons/gtk-undo.png</normaloff>:/gtk-icons/gtk-undo.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Undo</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Redo">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="gtk-icons.qrc">
|
||||
<normaloff>:/gtk-icons/gtk-redo.png</normaloff>:/gtk-icons/gtk-redo.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Redo</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionViewWelcomepage">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
|
Loading…
Reference in New Issue
Block a user