mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-26 09:35:28 +00:00
factored out command creation from table view into a separate class
This commit is contained in:
parent
a28a2bc2fe
commit
83d5f2aaeb
@ -18,7 +18,7 @@ opencs_hdrs_noqt (model/doc
|
|||||||
|
|
||||||
|
|
||||||
opencs_units (model/world
|
opencs_units (model/world
|
||||||
idtable idtableproxymodel regionmap data
|
idtable idtableproxymodel regionmap data commanddispatcher
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
157
apps/opencs/model/world/commanddispatcher.cpp
Normal file
157
apps/opencs/model/world/commanddispatcher.cpp
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
|
||||||
|
#include "commanddispatcher.hpp"
|
||||||
|
|
||||||
|
#include "../doc/document.hpp"
|
||||||
|
|
||||||
|
#include "idtable.hpp"
|
||||||
|
#include "record.hpp"
|
||||||
|
#include "commands.hpp"
|
||||||
|
|
||||||
|
std::vector<int> CSMWorld::CommandDispatcher::getDeletableRecords() const
|
||||||
|
{
|
||||||
|
std::vector<int> result;
|
||||||
|
|
||||||
|
IdTable& model = dynamic_cast<IdTable&> (*mDocument.getData().getTableModel (mId));
|
||||||
|
|
||||||
|
for (std::vector<int>::const_iterator iter (mSelection.begin());
|
||||||
|
iter!=mSelection.end(); ++iter)
|
||||||
|
{
|
||||||
|
// check record state
|
||||||
|
RecordBase::State state =
|
||||||
|
static_cast<RecordBase::State> (model.data (model.index (*iter, 1)).toInt());
|
||||||
|
|
||||||
|
if (state==RecordBase::State_Deleted)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// check other columns (only relevant for a subset of the tables)
|
||||||
|
int dialogueTypeIndex = model.searchColumnIndex (Columns::ColumnId_DialogueType);
|
||||||
|
|
||||||
|
if (dialogueTypeIndex!=-1)
|
||||||
|
{
|
||||||
|
int type = model.data (model.index (*iter, dialogueTypeIndex)).toInt();
|
||||||
|
|
||||||
|
if (type!=ESM::Dialogue::Topic && type!=ESM::Dialogue::Journal)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.push_back (*iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> CSMWorld::CommandDispatcher::getRevertableRecords() const
|
||||||
|
{
|
||||||
|
std::vector<int> result;
|
||||||
|
|
||||||
|
IdTable& model = dynamic_cast<IdTable&> (*mDocument.getData().getTableModel (mId));
|
||||||
|
|
||||||
|
/// \todo Reverting temporarily disabled on tables that support reordering, because
|
||||||
|
/// revert logic currently can not handle reordering.
|
||||||
|
if (model.getFeatures() & IdTable::Feature_ReorderWithinTopic)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
for (std::vector<int>::const_iterator iter (mSelection.begin());
|
||||||
|
iter!=mSelection.end(); ++iter)
|
||||||
|
{
|
||||||
|
// check record state
|
||||||
|
RecordBase::State state =
|
||||||
|
static_cast<RecordBase::State> (model.data (model.index (*iter, 1)).toInt());
|
||||||
|
|
||||||
|
if (state==RecordBase::State_BaseOnly)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
result.push_back (*iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMWorld::CommandDispatcher::CommandDispatcher (CSMDoc::Document& document,
|
||||||
|
const CSMWorld::UniversalId& id, QObject *parent)
|
||||||
|
: QObject (parent), mDocument (document), mId (id), mLocked (false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void CSMWorld::CommandDispatcher::setEditLock (bool locked)
|
||||||
|
{
|
||||||
|
mLocked = locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::CommandDispatcher::setSelection (const std::vector<int>& selection)
|
||||||
|
{
|
||||||
|
mSelection = selection;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMWorld::CommandDispatcher::canDelete() const
|
||||||
|
{
|
||||||
|
if (mLocked)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return getDeletableRecords().size()!=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMWorld::CommandDispatcher::canRevert() const
|
||||||
|
{
|
||||||
|
if (mLocked)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return getRevertableRecords().size()!=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::CommandDispatcher::executeDelete()
|
||||||
|
{
|
||||||
|
if (mLocked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::vector<int> rows = getDeletableRecords();
|
||||||
|
|
||||||
|
if (rows.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
IdTable& model = dynamic_cast<IdTable&> (*mDocument.getData().getTableModel (mId));
|
||||||
|
|
||||||
|
int columnIndex = model.findColumnIndex (Columns::ColumnId_Id);
|
||||||
|
|
||||||
|
if (rows.size()>1)
|
||||||
|
mDocument.getUndoStack().beginMacro (tr ("Delete multiple records"));
|
||||||
|
|
||||||
|
for (std::vector<int>::const_iterator iter (rows.begin()); iter!=rows.end(); ++iter)
|
||||||
|
{
|
||||||
|
std::string id = model.data (model.index (*iter, columnIndex)).
|
||||||
|
toString().toUtf8().constData();
|
||||||
|
|
||||||
|
mDocument.getUndoStack().push (new CSMWorld::DeleteCommand (model, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rows.size()>1)
|
||||||
|
mDocument.getUndoStack().endMacro();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::CommandDispatcher::executeRevert()
|
||||||
|
{
|
||||||
|
if (mLocked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::vector<int> rows = getRevertableRecords();
|
||||||
|
|
||||||
|
if (rows.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
IdTable& model = dynamic_cast<IdTable&> (*mDocument.getData().getTableModel (mId));
|
||||||
|
|
||||||
|
int columnIndex = model.findColumnIndex (Columns::ColumnId_Id);
|
||||||
|
|
||||||
|
if (rows.size()>1)
|
||||||
|
mDocument.getUndoStack().beginMacro (tr ("Revert multiple records"));
|
||||||
|
|
||||||
|
for (std::vector<int>::const_iterator iter (rows.begin()); iter!=rows.end(); ++iter)
|
||||||
|
{
|
||||||
|
std::string id = model.data (model.index (*iter, columnIndex)).
|
||||||
|
toString().toUtf8().constData();
|
||||||
|
|
||||||
|
mDocument.getUndoStack().push (new CSMWorld::RevertCommand (model, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rows.size()>1)
|
||||||
|
mDocument.getUndoStack().endMacro();
|
||||||
|
}
|
53
apps/opencs/model/world/commanddispatcher.hpp
Normal file
53
apps/opencs/model/world/commanddispatcher.hpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#ifndef CSM_WOLRD_COMMANDDISPATCHER_H
|
||||||
|
#define CSM_WOLRD_COMMANDDISPATCHER_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "universalid.hpp"
|
||||||
|
|
||||||
|
namespace CSMDoc
|
||||||
|
{
|
||||||
|
class Document;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
class CommandDispatcher : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
bool mLocked;
|
||||||
|
CSMDoc::Document& mDocument;
|
||||||
|
UniversalId mId;
|
||||||
|
std::vector<int> mSelection;
|
||||||
|
|
||||||
|
std::vector<int> getDeletableRecords() const;
|
||||||
|
|
||||||
|
std::vector<int> getRevertableRecords() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
CommandDispatcher (CSMDoc::Document& document, const CSMWorld::UniversalId& id,
|
||||||
|
QObject *parent = 0);
|
||||||
|
///< \param id ID of the table the commands should operate on primarily.
|
||||||
|
|
||||||
|
void setEditLock (bool locked);
|
||||||
|
|
||||||
|
void setSelection (const std::vector<int>& selection);
|
||||||
|
|
||||||
|
bool canDelete() const;
|
||||||
|
|
||||||
|
bool canRevert() const;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
void executeDelete();
|
||||||
|
|
||||||
|
void executeRevert();
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -19,14 +19,28 @@
|
|||||||
#include "../../model/world/columns.hpp"
|
#include "../../model/world/columns.hpp"
|
||||||
#include "../../model/world/tablemimedata.hpp"
|
#include "../../model/world/tablemimedata.hpp"
|
||||||
#include "../../model/world/tablemimedata.hpp"
|
#include "../../model/world/tablemimedata.hpp"
|
||||||
|
#include "../../model/world/commanddispatcher.hpp"
|
||||||
|
|
||||||
#include "recordstatusdelegate.hpp"
|
#include "recordstatusdelegate.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
|
|
||||||
void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
||||||
{
|
{
|
||||||
|
// configure dispatcher
|
||||||
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
||||||
|
|
||||||
|
std::vector<int> rows;
|
||||||
|
|
||||||
|
for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end();
|
||||||
|
++iter)
|
||||||
|
{
|
||||||
|
QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0));
|
||||||
|
rows.push_back (index.row());
|
||||||
|
}
|
||||||
|
|
||||||
|
mDispatcher->setSelection (rows);
|
||||||
|
|
||||||
|
// create context menu
|
||||||
QMenu menu (this);
|
QMenu menu (this);
|
||||||
|
|
||||||
/// \todo add menu items for select all and clear selection
|
/// \todo add menu items for select all and clear selection
|
||||||
@ -44,13 +58,10 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
|||||||
if (mCreateAction)
|
if (mCreateAction)
|
||||||
menu.addAction (mCreateAction);
|
menu.addAction (mCreateAction);
|
||||||
|
|
||||||
/// \todo Reverting temporarily disabled on tables that support reordering, because
|
if (mDispatcher->canRevert())
|
||||||
/// revert logic currently can not handle reordering.
|
menu.addAction (mRevertAction);
|
||||||
if (!(mModel->getFeatures() & CSMWorld::IdTable::Feature_ReorderWithinTopic))
|
|
||||||
if (listRevertableSelectedIds().size()>0)
|
|
||||||
menu.addAction (mRevertAction);
|
|
||||||
|
|
||||||
if (listDeletableSelectedIds().size()>0)
|
if (mDispatcher->canDelete())
|
||||||
menu.addAction (mDeleteAction);
|
menu.addAction (mDeleteAction);
|
||||||
|
|
||||||
if (mModel->getFeatures() & CSMWorld::IdTable::Feature_ReorderWithinTopic)
|
if (mModel->getFeatures() & CSMWorld::IdTable::Feature_ReorderWithinTopic)
|
||||||
@ -108,84 +119,6 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
|||||||
menu.exec (event->globalPos());
|
menu.exec (event->globalPos());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> CSVWorld::Table::listRevertableSelectedIds() const
|
|
||||||
{
|
|
||||||
std::vector<std::string> revertableIds;
|
|
||||||
|
|
||||||
if (mProxyModel->columnCount()>0)
|
|
||||||
{
|
|
||||||
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
|
||||||
|
|
||||||
for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end();
|
|
||||||
++iter)
|
|
||||||
{
|
|
||||||
QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0));
|
|
||||||
|
|
||||||
CSMWorld::RecordBase::State state =
|
|
||||||
static_cast<CSMWorld::RecordBase::State> (
|
|
||||||
mModel->data (mModel->index (index.row(), 1)).toInt());
|
|
||||||
|
|
||||||
if (state!=CSMWorld::RecordBase::State_BaseOnly)
|
|
||||||
{
|
|
||||||
int columnIndex = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id);
|
|
||||||
|
|
||||||
std::string id = mModel->data (mModel->index (index.row(), columnIndex)).
|
|
||||||
toString().toUtf8().constData();
|
|
||||||
|
|
||||||
revertableIds.push_back (id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return revertableIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> CSVWorld::Table::listDeletableSelectedIds() const
|
|
||||||
{
|
|
||||||
std::vector<std::string> deletableIds;
|
|
||||||
|
|
||||||
if (mProxyModel->columnCount()>0)
|
|
||||||
{
|
|
||||||
QModelIndexList selectedRows = selectionModel()->selectedRows();
|
|
||||||
|
|
||||||
for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end();
|
|
||||||
++iter)
|
|
||||||
{
|
|
||||||
QModelIndex index = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0));
|
|
||||||
|
|
||||||
// check record state
|
|
||||||
CSMWorld::RecordBase::State state =
|
|
||||||
static_cast<CSMWorld::RecordBase::State> (
|
|
||||||
mModel->data (mModel->index (index.row(), 1)).toInt());
|
|
||||||
|
|
||||||
if (state==CSMWorld::RecordBase::State_Deleted)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// check other columns (only relevant for a subset of the tables)
|
|
||||||
int dialogueTypeIndex =
|
|
||||||
mModel->searchColumnIndex (CSMWorld::Columns::ColumnId_DialogueType);
|
|
||||||
|
|
||||||
if (dialogueTypeIndex!=-1)
|
|
||||||
{
|
|
||||||
int type = mModel->data (mModel->index (index.row(), dialogueTypeIndex)).toInt();
|
|
||||||
|
|
||||||
if (type!=ESM::Dialogue::Topic && type!=ESM::Dialogue::Journal)
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// add the id to the collection
|
|
||||||
int columnIndex = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id);
|
|
||||||
|
|
||||||
std::string id = mModel->data (mModel->index (index.row(), columnIndex)).
|
|
||||||
toString().toUtf8().constData();
|
|
||||||
|
|
||||||
deletableIds.push_back (id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return deletableIds;
|
|
||||||
}
|
|
||||||
|
|
||||||
CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
|
CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
|
||||||
bool createAndDelete, bool sorting, CSMDoc::Document& document)
|
bool createAndDelete, bool sorting, CSMDoc::Document& document)
|
||||||
: mCreateAction (0), mCloneAction(0), mRecordStatusDisplay (0),
|
: mCreateAction (0), mCloneAction(0), mRecordStatusDisplay (0),
|
||||||
@ -196,6 +129,8 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
|
|||||||
mProxyModel = new CSMWorld::IdTableProxyModel (this);
|
mProxyModel = new CSMWorld::IdTableProxyModel (this);
|
||||||
mProxyModel->setSourceModel (mModel);
|
mProxyModel->setSourceModel (mModel);
|
||||||
|
|
||||||
|
mDispatcher = new CSMWorld::CommandDispatcher (document, id, this);
|
||||||
|
|
||||||
setModel (mProxyModel);
|
setModel (mProxyModel);
|
||||||
horizontalHeader()->setResizeMode (QHeaderView::Interactive);
|
horizontalHeader()->setResizeMode (QHeaderView::Interactive);
|
||||||
verticalHeader()->hide();
|
verticalHeader()->hide();
|
||||||
@ -240,11 +175,11 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
mRevertAction = new QAction (tr ("Revert Record"), this);
|
mRevertAction = new QAction (tr ("Revert Record"), this);
|
||||||
connect (mRevertAction, SIGNAL (triggered()), this, SLOT (revertRecord()));
|
connect (mRevertAction, SIGNAL (triggered()), mDispatcher, SLOT (executeRevert()));
|
||||||
addAction (mRevertAction);
|
addAction (mRevertAction);
|
||||||
|
|
||||||
mDeleteAction = new QAction (tr ("Delete Record"), this);
|
mDeleteAction = new QAction (tr ("Delete Record"), this);
|
||||||
connect (mDeleteAction, SIGNAL (triggered()), this, SLOT (deleteRecord()));
|
connect (mDeleteAction, SIGNAL (triggered()), mDispatcher, SLOT (executeDelete()));
|
||||||
addAction (mDeleteAction);
|
addAction (mDeleteAction);
|
||||||
|
|
||||||
mMoveUpAction = new QAction (tr ("Move Up"), this);
|
mMoveUpAction = new QAction (tr ("Move Up"), this);
|
||||||
@ -283,6 +218,7 @@ void CSVWorld::Table::setEditLock (bool locked)
|
|||||||
(*iter)->setEditLock (locked);
|
(*iter)->setEditLock (locked);
|
||||||
|
|
||||||
DragRecordTable::setEditLock(locked);
|
DragRecordTable::setEditLock(locked);
|
||||||
|
mDispatcher->setEditLock (locked);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::UniversalId CSVWorld::Table::getUniversalId (int row) const
|
CSMWorld::UniversalId CSVWorld::Table::getUniversalId (int row) const
|
||||||
@ -292,46 +228,6 @@ CSMWorld::UniversalId CSVWorld::Table::getUniversalId (int row) const
|
|||||||
mProxyModel->data (mProxyModel->index (row, 0)).toString().toUtf8().constData());
|
mProxyModel->data (mProxyModel->index (row, 0)).toString().toUtf8().constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWorld::Table::revertRecord()
|
|
||||||
{
|
|
||||||
if (!mEditLock)
|
|
||||||
{
|
|
||||||
std::vector<std::string> revertableIds = listRevertableSelectedIds();
|
|
||||||
|
|
||||||
if (!revertableIds.empty())
|
|
||||||
{
|
|
||||||
if (revertableIds.size()>1)
|
|
||||||
mDocument.getUndoStack().beginMacro (tr ("Revert multiple records"));
|
|
||||||
|
|
||||||
for (std::vector<std::string>::const_iterator iter (revertableIds.begin()); iter!=revertableIds.end(); ++iter)
|
|
||||||
mDocument.getUndoStack().push (new CSMWorld::RevertCommand (*mModel, *iter));
|
|
||||||
|
|
||||||
if (revertableIds.size()>1)
|
|
||||||
mDocument.getUndoStack().endMacro();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSVWorld::Table::deleteRecord()
|
|
||||||
{
|
|
||||||
if (!mEditLock)
|
|
||||||
{
|
|
||||||
std::vector<std::string> deletableIds = listDeletableSelectedIds();
|
|
||||||
|
|
||||||
if (!deletableIds.empty())
|
|
||||||
{
|
|
||||||
if (deletableIds.size()>1)
|
|
||||||
mDocument.getUndoStack().beginMacro (tr ("Delete multiple records"));
|
|
||||||
|
|
||||||
for (std::vector<std::string>::const_iterator iter (deletableIds.begin()); iter!=deletableIds.end(); ++iter)
|
|
||||||
mDocument.getUndoStack().push (new CSMWorld::DeleteCommand (*mModel, *iter));
|
|
||||||
|
|
||||||
if (deletableIds.size()>1)
|
|
||||||
mDocument.getUndoStack().endMacro();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSVWorld::Table::editRecord()
|
void CSVWorld::Table::editRecord()
|
||||||
{
|
{
|
||||||
if (!mEditLock)
|
if (!mEditLock)
|
||||||
|
@ -24,6 +24,7 @@ namespace CSMWorld
|
|||||||
class UniversalId;
|
class UniversalId;
|
||||||
class IdTableProxyModel;
|
class IdTableProxyModel;
|
||||||
class IdTable;
|
class IdTable;
|
||||||
|
class CommandDispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace CSVWorld
|
namespace CSVWorld
|
||||||
@ -48,15 +49,12 @@ namespace CSVWorld
|
|||||||
CSMWorld::IdTableProxyModel *mProxyModel;
|
CSMWorld::IdTableProxyModel *mProxyModel;
|
||||||
CSMWorld::IdTable *mModel;
|
CSMWorld::IdTable *mModel;
|
||||||
int mRecordStatusDisplay;
|
int mRecordStatusDisplay;
|
||||||
|
CSMWorld::CommandDispatcher *mDispatcher;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void contextMenuEvent (QContextMenuEvent *event);
|
void contextMenuEvent (QContextMenuEvent *event);
|
||||||
|
|
||||||
std::vector<std::string> listRevertableSelectedIds() const;
|
|
||||||
|
|
||||||
std::vector<std::string> listDeletableSelectedIds() const;
|
|
||||||
|
|
||||||
void mouseMoveEvent(QMouseEvent *event);
|
void mouseMoveEvent(QMouseEvent *event);
|
||||||
|
|
||||||
void dropEvent(QDropEvent *event);
|
void dropEvent(QDropEvent *event);
|
||||||
@ -93,10 +91,6 @@ namespace CSVWorld
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void revertRecord();
|
|
||||||
|
|
||||||
void deleteRecord();
|
|
||||||
|
|
||||||
void editRecord();
|
void editRecord();
|
||||||
|
|
||||||
void cloneRecord();
|
void cloneRecord();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user