Merge branch 'refs'

deque
Marc Zinnschlag 11 years ago
commit c23e9e03fd

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

@ -0,0 +1,267 @@
#include "commanddispatcher.hpp"
#include <algorithm>
#include <components/misc/stringops.hpp>
#include "../doc/document.hpp"
#include "idtable.hpp"
#include "record.hpp"
#include "commands.hpp"
std::vector<std::string> CSMWorld::CommandDispatcher::getDeletableRecords() const
{
std::vector<std::string> result;
IdTable& model = dynamic_cast<IdTable&> (*mDocument.getData().getTableModel (mId));
int stateColumnIndex = model.findColumnIndex (Columns::ColumnId_Modification);
for (std::vector<std::string>::const_iterator iter (mSelection.begin());
iter!=mSelection.end(); ++iter)
{
int row = model.getModelIndex (*iter, 0).row();
// check record state
RecordBase::State state = static_cast<RecordBase::State> (
model.data (model.index (row, stateColumnIndex)).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 (row, dialogueTypeIndex)).toInt();
if (type!=ESM::Dialogue::Topic && type!=ESM::Dialogue::Journal)
continue;
}
result.push_back (*iter);
}
return result;
}
std::vector<std::string> CSMWorld::CommandDispatcher::getRevertableRecords() const
{
std::vector<std::string> 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;
int stateColumnIndex = model.findColumnIndex (Columns::ColumnId_Modification);
for (std::vector<std::string>::const_iterator iter (mSelection.begin());
iter!=mSelection.end(); ++iter)
{
int row = model.getModelIndex (*iter, 0).row();
// check record state
RecordBase::State state = static_cast<RecordBase::State> (
model.data (model.index (row, stateColumnIndex)).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<std::string>& selection)
{
mSelection = selection;
std::for_each (mSelection.begin(), mSelection.end(), Misc::StringUtils::toLower);
std::sort (mSelection.begin(), mSelection.end());
}
void CSMWorld::CommandDispatcher::setExtendedTypes (const std::vector<UniversalId>& types)
{
mExtendedTypes = types;
}
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;
}
std::vector<CSMWorld::UniversalId> CSMWorld::CommandDispatcher::getExtendedTypes() const
{
std::vector<CSMWorld::UniversalId> tables;
if (mId==UniversalId::Type_Cells)
{
tables.push_back (mId);
tables.push_back (UniversalId::Type_References);
/// \todo add other cell-specific types
}
return tables;
}
void CSMWorld::CommandDispatcher::executeDelete()
{
if (mLocked)
return;
std::vector<std::string> 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<std::string>::const_iterator iter (rows.begin()); iter!=rows.end(); ++iter)
{
std::string id = model.data (model.getModelIndex (*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<std::string> 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<std::string>::const_iterator iter (rows.begin()); iter!=rows.end(); ++iter)
{
std::string id = model.data (model.getModelIndex (*iter, columnIndex)).
toString().toUtf8().constData();
mDocument.getUndoStack().push (new CSMWorld::RevertCommand (model, id));
}
if (rows.size()>1)
mDocument.getUndoStack().endMacro();
}
void CSMWorld::CommandDispatcher::executeExtendedDelete()
{
if (mExtendedTypes.size()>1)
mDocument.getUndoStack().beginMacro (tr ("Extended delete of multiple records"));
for (std::vector<UniversalId>::const_iterator iter (mExtendedTypes.begin());
iter!=mExtendedTypes.end(); ++iter)
{
if (*iter==mId)
executeDelete();
else if (*iter==UniversalId::Type_References)
{
IdTable& model = dynamic_cast<IdTable&> (
*mDocument.getData().getTableModel (*iter));
const RefCollection& collection = mDocument.getData().getReferences();
int size = collection.getSize();
for (int i=size-1; i>=0; --i)
{
const Record<CellRef>& record = collection.getRecord (i);
if (record.mState==RecordBase::State_Deleted)
continue;
if (!std::binary_search (mSelection.begin(), mSelection.end(),
Misc::StringUtils::lowerCase (record.get().mCell)))
continue;
mDocument.getUndoStack().push (
new CSMWorld::DeleteCommand (model, record.get().mId));
}
}
}
if (mExtendedTypes.size()>1)
mDocument.getUndoStack().endMacro();
}
void CSMWorld::CommandDispatcher::executeExtendedRevert()
{
if (mExtendedTypes.size()>1)
mDocument.getUndoStack().beginMacro (tr ("Extended revert of multiple records"));
for (std::vector<UniversalId>::const_iterator iter (mExtendedTypes.begin());
iter!=mExtendedTypes.end(); ++iter)
{
if (*iter==mId)
executeRevert();
else if (*iter==UniversalId::Type_References)
{
IdTable& model = dynamic_cast<IdTable&> (
*mDocument.getData().getTableModel (*iter));
const RefCollection& collection = mDocument.getData().getReferences();
int size = collection.getSize();
for (int i=size-1; i>=0; --i)
{
const Record<CellRef>& record = collection.getRecord (i);
if (!std::binary_search (mSelection.begin(), mSelection.end(),
Misc::StringUtils::lowerCase (record.get().mCell)))
continue;
mDocument.getUndoStack().push (
new CSMWorld::RevertCommand (model, record.get().mId));
}
}
}
if (mExtendedTypes.size()>1)
mDocument.getUndoStack().endMacro();
}

@ -0,0 +1,69 @@
#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<std::string> mSelection;
std::vector<UniversalId> mExtendedTypes;
std::vector<std::string> getDeletableRecords() const;
std::vector<std::string> 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<std::string>& selection);
void setExtendedTypes (const std::vector<UniversalId>& types);
///< Set record lists selected by the user for extended operations.
bool canDelete() const;
bool canRevert() const;
/// Return IDs of the record collection that can also be affected when
/// operating on the record collection this dispatcher is used for.
///
/// \note The returned collection contains the ID of the record collection this
/// dispatcher is used for. However if that record collection does not support
/// the extended mode, the returned vector will be empty instead.
std::vector<UniversalId> getExtendedTypes() const;
public slots:
void executeDelete();
void executeRevert();
void executeExtendedDelete();
void executeExtendedRevert();
};
}
#endif

@ -16,11 +16,12 @@
#include "regionmap.hpp" #include "regionmap.hpp"
#include "columns.hpp" #include "columns.hpp"
void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type1, void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type, bool update)
UniversalId::Type type2, bool update)
{ {
mModels.push_back (model); mModels.push_back (model);
mModelIndex.insert (std::make_pair (type1, model)); mModelIndex.insert (std::make_pair (type, model));
UniversalId::Type type2 = UniversalId::getParentType (type);
if (type2!=UniversalId::Type_None) if (type2!=UniversalId::Type_None)
mModelIndex.insert (std::make_pair (type2, model)); mModelIndex.insert (std::make_pair (type2, model));
@ -235,26 +236,26 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding)
mFilters.addColumn (new DescriptionColumn<CSMFilter::Filter>); mFilters.addColumn (new DescriptionColumn<CSMFilter::Filter>);
mFilters.addColumn (new ScopeColumn<CSMFilter::Filter>); mFilters.addColumn (new ScopeColumn<CSMFilter::Filter>);
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); addModel (new IdTable (&mGlobals), UniversalId::Type_Global);
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst); addModel (new IdTable (&mGmsts), UniversalId::Type_Gmst);
addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill, false); addModel (new IdTable (&mSkills), UniversalId::Type_Skill);
addModel (new IdTable (&mClasses), UniversalId::Type_Classes, UniversalId::Type_Class); addModel (new IdTable (&mClasses), UniversalId::Type_Class);
addModel (new IdTable (&mFactions), UniversalId::Type_Factions, UniversalId::Type_Faction); addModel (new IdTable (&mFactions), UniversalId::Type_Faction);
addModel (new IdTable (&mRaces), UniversalId::Type_Races, UniversalId::Type_Race); addModel (new IdTable (&mRaces), UniversalId::Type_Race);
addModel (new IdTable (&mSounds), UniversalId::Type_Sounds, UniversalId::Type_Sound); addModel (new IdTable (&mSounds), UniversalId::Type_Sound);
addModel (new IdTable (&mScripts), UniversalId::Type_Scripts, UniversalId::Type_Script); addModel (new IdTable (&mScripts), UniversalId::Type_Script);
addModel (new IdTable (&mRegions), UniversalId::Type_Regions, UniversalId::Type_Region); addModel (new IdTable (&mRegions), UniversalId::Type_Region);
addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsigns, UniversalId::Type_Birthsign); addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsign);
addModel (new IdTable (&mSpells), UniversalId::Type_Spells, UniversalId::Type_Spell); addModel (new IdTable (&mSpells), UniversalId::Type_Spell);
addModel (new IdTable (&mTopics), UniversalId::Type_Topics, UniversalId::Type_Topic); addModel (new IdTable (&mTopics), UniversalId::Type_Topic);
addModel (new IdTable (&mJournals), UniversalId::Type_Journals, UniversalId::Type_Journal); addModel (new IdTable (&mJournals), UniversalId::Type_Journal);
addModel (new IdTable (&mTopicInfos, IdTable::Reordering_WithinTopic), UniversalId::Type_TopicInfos, UniversalId::Type_TopicInfo); addModel (new IdTable (&mTopicInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_TopicInfo);
addModel (new IdTable (&mJournalInfos, IdTable::Reordering_WithinTopic), UniversalId::Type_JournalInfos, UniversalId::Type_JournalInfo); addModel (new IdTable (&mJournalInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_JournalInfo);
addModel (new IdTable (&mCells, IdTable::Reordering_None, IdTable::Viewing_Id), UniversalId::Type_Cells, UniversalId::Type_Cell); addModel (new IdTable (&mCells, IdTable::Feature_ViewId), UniversalId::Type_Cell);
addModel (new IdTable (&mReferenceables, IdTable::Reordering_None, IdTable::Viewing_None, true), addModel (new IdTable (&mReferenceables, IdTable::Feature_Preview),
UniversalId::Type_Referenceables, UniversalId::Type_Referenceable); UniversalId::Type_Referenceable);
addModel (new IdTable (&mRefs, IdTable::Reordering_None, IdTable::Viewing_Cell, true), UniversalId::Type_References, UniversalId::Type_Reference, false); addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_Reference);
addModel (new IdTable (&mFilters), UniversalId::Type_Filters, UniversalId::Type_Filter, false); addModel (new IdTable (&mFilters), UniversalId::Type_Filter);
} }
CSMWorld::Data::~Data() CSMWorld::Data::~Data()
@ -469,8 +470,7 @@ QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId&
if (id.getType()==UniversalId::Type_RegionMap) if (id.getType()==UniversalId::Type_RegionMap)
{ {
RegionMap *table = 0; RegionMap *table = 0;
addModel (table = new RegionMap (*this), UniversalId::Type_RegionMap, addModel (table = new RegionMap (*this), UniversalId::Type_RegionMap, false);
UniversalId::Type_None, false);
return table; return table;
} }
throw std::logic_error ("No table model available for " + id.toString()); throw std::logic_error ("No table model available for " + id.toString());

@ -83,8 +83,8 @@ namespace CSMWorld
Data (const Data&); Data (const Data&);
Data& operator= (const Data&); Data& operator= (const Data&);
void addModel (QAbstractItemModel *model, UniversalId::Type type1, void addModel (QAbstractItemModel *model, UniversalId::Type type,
UniversalId::Type type2 = UniversalId::Type_None, bool update = true); bool update = true);
static void appendIds (std::vector<std::string>& ids, const CollectionBase& collection, static void appendIds (std::vector<std::string>& ids, const CollectionBase& collection,
bool listDeleted); bool listDeleted);

@ -4,9 +4,8 @@
#include "collectionbase.hpp" #include "collectionbase.hpp"
#include "columnbase.hpp" #include "columnbase.hpp"
CSMWorld::IdTable::IdTable (CollectionBase *idCollection, Reordering reordering, CSMWorld::IdTable::IdTable (CollectionBase *idCollection, unsigned int features)
Viewing viewing, bool preview) : mIdCollection (idCollection), mFeatures (features)
: mIdCollection (idCollection), mReordering (reordering), mViewing (viewing), mPreview (preview)
{} {}
CSMWorld::IdTable::~IdTable() CSMWorld::IdTable::~IdTable()
@ -186,19 +185,9 @@ void CSMWorld::IdTable::reorderRows (int baseIndex, const std::vector<int>& newO
index (baseIndex+newOrder.size()-1, mIdCollection->getColumns()-1)); index (baseIndex+newOrder.size()-1, mIdCollection->getColumns()-1));
} }
CSMWorld::IdTable::Reordering CSMWorld::IdTable::getReordering() const unsigned int CSMWorld::IdTable::getFeatures() const
{ {
return mReordering; return mFeatures;
}
CSMWorld::IdTable::Viewing CSMWorld::IdTable::getViewing() const
{
return mViewing;
}
bool CSMWorld::IdTable::hasPreview() const
{
return mPreview;
} }
std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row) const std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row) const
@ -206,7 +195,7 @@ std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row)
std::string id; std::string id;
std::string hint; std::string hint;
if (mViewing==Viewing_Cell) if (mFeatures & Feature_ViewCell)
{ {
int cellColumn = mIdCollection->searchColumnIndex (Columns::ColumnId_Cell); int cellColumn = mIdCollection->searchColumnIndex (Columns::ColumnId_Cell);
int idColumn = mIdCollection->searchColumnIndex (Columns::ColumnId_Id); int idColumn = mIdCollection->searchColumnIndex (Columns::ColumnId_Id);
@ -217,7 +206,7 @@ std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row)
hint = "r:" + std::string (mIdCollection->getData (row, idColumn).toString().toUtf8().constData()); hint = "r:" + std::string (mIdCollection->getData (row, idColumn).toString().toUtf8().constData());
} }
} }
else if (mViewing==Viewing_Id) else if (mFeatures & Feature_ViewId)
{ {
int column = mIdCollection->searchColumnIndex (Columns::ColumnId_Id); int column = mIdCollection->searchColumnIndex (Columns::ColumnId_Id);

@ -19,26 +19,27 @@ namespace CSMWorld
public: public:
enum Reordering enum Features
{ {
Reordering_None, Feature_ReorderWithinTopic = 1,
Reordering_WithinTopic
};
enum Viewing /// Use ID column to generate view request (ID is transformed into
{ /// worldspace and original ID is passed as hint with c: prefix).
Viewing_None, Feature_ViewId = 2,
Viewing_Id, // use ID column to generate view request (ID is transformed into
// worldspace and original ID is passed as hint with c: prefix) /// Use cell column to generate view request (cell ID is transformed
Viewing_Cell // use cell column to generate view request (cell ID is transformed /// into worldspace and record ID is passed as hint with r: prefix).
// into worldspace and record ID is passed as hint with r: prefix) Feature_ViewCell = 4,
Feature_View = Feature_ViewId | Feature_ViewCell,
Feature_Preview = 8
}; };
private: private:
CollectionBase *mIdCollection; CollectionBase *mIdCollection;
Reordering mReordering; unsigned int mFeatures;
Viewing mViewing;
bool mPreview; bool mPreview;
// not implemented // not implemented
@ -47,8 +48,7 @@ namespace CSMWorld
public: public:
IdTable (CollectionBase *idCollection, Reordering reordering = Reordering_None, IdTable (CollectionBase *idCollection, unsigned int features = 0);
Viewing viewing = Viewing_None, bool preview = false);
///< The ownership of \a idCollection is not transferred. ///< The ownership of \a idCollection is not transferred.
virtual ~IdTable(); virtual ~IdTable();
@ -97,11 +97,7 @@ namespace CSMWorld
///< Reorder the rows [baseIndex, baseIndex+newOrder.size()) according to the indices ///< Reorder the rows [baseIndex, baseIndex+newOrder.size()) according to the indices
/// given in \a newOrder (baseIndex+newOrder[0] specifies the new index of row baseIndex). /// given in \a newOrder (baseIndex+newOrder[0] specifies the new index of row baseIndex).
Reordering getReordering() const; unsigned int getFeatures() const;
Viewing getViewing() const;
bool hasPreview() const;
std::pair<UniversalId, std::string> view (int row) const; std::pair<UniversalId, std::string> view (int row) const;
///< Return the UniversalId and the hint for viewing \a row. If viewing is not ///< Return the UniversalId and the hint for viewing \a row. If viewing is not

@ -61,8 +61,8 @@ namespace
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", ":./spell.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", ":./spell.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Topic, "Topic", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Topic, "Topic", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Journal, "Journal", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Journal, "Journal", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_TopicInfo, "TopicInfo", 0 }, { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_TopicInfo, "TopicInfo", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo", 0 }, { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell_Missing, "Cell", ":./cell.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell_Missing, "Cell", ":./cell.png" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables", 0 },
@ -90,7 +90,7 @@ namespace
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Static, "Static", ":./static.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Static, "Static", ":./static.png" },
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":./weapon.png" }, { CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":./weapon.png" },
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Reference", 0 }, { CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Reference", 0 },
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Filter, "Filter", ":./filter.png" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Filter, "Filter", ":./filter.png" },
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", 0 }, { CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", 0 },
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Preview, "Preview", 0 }, { CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Preview, "Preview", 0 },
@ -320,6 +320,28 @@ std::vector<CSMWorld::UniversalId::Type> CSMWorld::UniversalId::listReferenceabl
return list; return list;
} }
CSMWorld::UniversalId::Type CSMWorld::UniversalId::getParentType (Type type)
{
for (int i=0; sIdArg[i].mType; ++i)
if (type==sIdArg[i].mType)
{
if (sIdArg[i].mClass==Class_RefRecord)
return Type_Referenceables;
if (sIdArg[i].mClass==Class_SubRecord || sIdArg[i].mClass==Class_Record)
{
if (type==Type_Cell_Missing)
return Type_Cells;
return static_cast<Type> (type-1);
}
break;
}
return Type_None;
}
bool CSMWorld::operator== (const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right) bool CSMWorld::operator== (const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right)
{ {
return left.isEqual (right); return left.isEqual (right);

@ -32,6 +32,8 @@ namespace CSMWorld
ArgumentType_Index ArgumentType_Index
}; };
/// \note A record list type must always be immediately followed by the matching
/// record type, if this type is of class SubRecord or Record.
enum Type enum Type
{ {
Type_None = 0, Type_None = 0,
@ -86,8 +88,8 @@ namespace CSMWorld
Type_References, Type_References,
Type_Reference, Type_Reference,
Type_RegionMap, Type_RegionMap,
Type_Filter,
Type_Filters, Type_Filters,
Type_Filter,
Type_Topics, Type_Topics,
Type_Topic, Type_Topic,
Type_Journals, Type_Journals,
@ -147,6 +149,11 @@ namespace CSMWorld
///< Will return an empty string, if no icon is available. ///< Will return an empty string, if no icon is available.
static std::vector<Type> listReferenceableTypes(); static std::vector<Type> listReferenceableTypes();
/// If \a type is a SubRecord, RefRecord or Record type return the type of the table
/// that contains records of type \a type.
/// Otherwise return Type_None.
static Type getParentType (Type type);
}; };
bool operator== (const UniversalId& left, const UniversalId& right); bool operator== (const UniversalId& left, const UniversalId& right);

@ -332,6 +332,7 @@ void CSVWorld::EditWidget::remake(int row)
if (mMainWidget) if (mMainWidget)
{ {
delete mMainWidget; delete mMainWidget;
mMainWidget = 0;
} }
mMainWidget = new QWidget (this); mMainWidget = new QWidget (this);
@ -339,6 +340,7 @@ void CSVWorld::EditWidget::remake(int row)
if (mWidgetMapper) if (mWidgetMapper)
{ {
delete mWidgetMapper; delete mWidgetMapper;
mWidgetMapper = 0;
} }
mWidgetMapper = new QDataWidgetMapper (this); mWidgetMapper = new QDataWidgetMapper (this);
mWidgetMapper->setModel(mTable); mWidgetMapper->setModel(mTable);
@ -396,7 +398,7 @@ void CSVWorld::EditWidget::remake(int row)
mWidgetMapper->setCurrentModelIndex(mTable->index(row, 0)); mWidgetMapper->setCurrentModelIndex(mTable->index(row, 0));
this->setMinimumWidth(325); //TODO find better way to set the width or make it customizable this->setMinimumWidth(325); /// \todo replace hardcoded value with a user setting
this->setWidget(mMainWidget); this->setWidget(mMainWidget);
this->setWidgetResizable(true); this->setWidgetResizable(true);
} }
@ -407,7 +409,6 @@ void CSVWorld::EditWidget::remake(int row)
CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document, CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document,
const CreatorFactoryBase& creatorFactory, bool sorting) : const CreatorFactoryBase& creatorFactory, bool sorting) :
SubView (id), SubView (id),
mEditWidget(0), mEditWidget(0),
mMainLayout(NULL), mMainLayout(NULL),
@ -415,8 +416,8 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM
mTable(dynamic_cast<CSMWorld::IdTable*>(document.getData().getTableModel(id))), mTable(dynamic_cast<CSMWorld::IdTable*>(document.getData().getTableModel(id))),
mRow (-1), mRow (-1),
mLocked(false), mLocked(false),
mDocument(document) mDocument(document),
mCommandDispatcher (document, CSMWorld::UniversalId::getParentType (id.getType()))
{ {
connect(mTable, SIGNAL(dataChanged (const QModelIndex&, const QModelIndex&)), this, SLOT(dataChanged(const QModelIndex&))); connect(mTable, SIGNAL(dataChanged (const QModelIndex&, const QModelIndex&)), this, SLOT(dataChanged(const QModelIndex&)));
mRow = mTable->getModelIndex (id.getId(), 0).row(); mRow = mTable->getModelIndex (id.getId(), 0).row();
@ -440,7 +441,7 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM
QToolButton* revertButton = new QToolButton(mainWidget); QToolButton* revertButton = new QToolButton(mainWidget);
revertButton->setIcon(QIcon(":/edit-undo.png")); revertButton->setIcon(QIcon(":/edit-undo.png"));
if (mTable->hasPreview()) if (mTable->getFeatures() & CSMWorld::IdTable::Feature_Preview)
{ {
QToolButton* previewButton = new QToolButton(mainWidget); QToolButton* previewButton = new QToolButton(mainWidget);
previewButton->setIcon(QIcon(":/edit-preview.png")); previewButton->setIcon(QIcon(":/edit-preview.png"));
@ -448,7 +449,7 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM
connect(previewButton, SIGNAL(clicked()), this, SLOT(showPreview())); connect(previewButton, SIGNAL(clicked()), this, SLOT(showPreview()));
} }
if (mTable->getViewing()!=CSMWorld::IdTable::Viewing_None) if (mTable->getFeatures() & CSMWorld::IdTable::Feature_View)
{ {
QToolButton* viewButton = new QToolButton(mainWidget); QToolButton* viewButton = new QToolButton(mainWidget);
viewButton->setIcon(QIcon(":/cell.png")); viewButton->setIcon(QIcon(":/cell.png"));
@ -560,14 +561,12 @@ void CSVWorld::DialogueSubView::nextId()
void CSVWorld::DialogueSubView::setEditLock (bool locked) void CSVWorld::DialogueSubView::setEditLock (bool locked)
{ {
mLocked = locked; mLocked = locked;
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (mRow, 1)).toInt()); CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (mRow, 1)).toInt());
if (state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased)
{ mEditWidget->setDisabled (state==CSMWorld::RecordBase::State_Deleted || locked);
mEditWidget->setDisabled(true);
} else mCommandDispatcher.setEditLock (locked);
{
mEditWidget->setDisabled(mLocked);
}
} }
void CSVWorld::DialogueSubView::dataChanged(const QModelIndex & index) void CSVWorld::DialogueSubView::dataChanged(const QModelIndex & index)
@ -575,13 +574,8 @@ void CSVWorld::DialogueSubView::dataChanged(const QModelIndex & index)
if (index.row() == mRow) if (index.row() == mRow)
{ {
CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (mRow, 1)).toInt()); CSMWorld::RecordBase::State state = static_cast<CSMWorld::RecordBase::State>(mTable->data (mTable->index (mRow, 1)).toInt());
if (state == CSMWorld::RecordBase::State_Deleted || state == CSMWorld::RecordBase::State_Erased)
{ mEditWidget->setDisabled (state==CSMWorld::RecordBase::State_Deleted || mLocked);
mEditWidget->setDisabled(true);
} else
{
mEditWidget->setDisabled(mLocked);
}
} }
} }
@ -671,7 +665,8 @@ void CSVWorld::DialogueSubView::cloneRequest ()
void CSVWorld::DialogueSubView::showPreview () void CSVWorld::DialogueSubView::showPreview ()
{ {
if (mTable->hasPreview() && mRow < mTable->rowCount()) if ((mTable->getFeatures() & CSMWorld::IdTable::Feature_Preview) &&
mRow < mTable->rowCount())
{ {
emit focusId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Preview, mTable->data(mTable->index (mRow, 0)).toString().toUtf8().constData()), ""); emit focusId(CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Preview, mTable->data(mTable->index (mRow, 0)).toString().toUtf8().constData()), "");
} }

@ -8,7 +8,9 @@
#include <QScrollArea> #include <QScrollArea>
#include "../doc/subview.hpp" #include "../doc/subview.hpp"
#include "../../model/world/columnbase.hpp" #include "../../model/world/columnbase.hpp"
#include "../../model/world/commanddispatcher.hpp"
class QDataWidgetMapper; class QDataWidgetMapper;
class QSize; class QSize;
@ -169,6 +171,7 @@ namespace CSVWorld
bool mLocked; bool mLocked;
const CSMDoc::Document& mDocument; const CSMDoc::Document& mDocument;
TableBottomBox* mBottom; TableBottomBox* mBottom;
CSMWorld::CommandDispatcher mCommandDispatcher;
public: public:

@ -80,30 +80,35 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
manager.add (CSMWorld::UniversalId::Type_Scene, new CSVDoc::SubViewFactory<SceneSubView>); manager.add (CSMWorld::UniversalId::Type_Scene, new CSVDoc::SubViewFactory<SceneSubView>);
//edit subviews // Dialogue subviews
manager.add (CSMWorld::UniversalId::Type_Region, static const CSMWorld::UniversalId::Type sTableTypes2[] =
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false)); {
CSMWorld::UniversalId::Type_Region,
manager.add (CSMWorld::UniversalId::Type_Spell, CSMWorld::UniversalId::Type_Spell,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false)); CSMWorld::UniversalId::Type_Birthsign,
CSMWorld::UniversalId::Type_Global,
CSMWorld::UniversalId::Type_Race,
CSMWorld::UniversalId::Type_Class,
CSMWorld::UniversalId::Type_Filter,
CSMWorld::UniversalId::Type_Sound,
CSMWorld::UniversalId::Type_Faction,
manager.add (CSMWorld::UniversalId::Type_Referenceable, CSMWorld::UniversalId::Type_None // end marker
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<ReferenceableCreator> > (false)); };
manager.add (CSMWorld::UniversalId::Type_Birthsign, for (int i=0; sTableTypes2[i]!=CSMWorld::UniversalId::Type_None; ++i)
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false)); manager.add (sTableTypes2[i],
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView,
CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Global, manager.add (CSMWorld::UniversalId::Type_Skill,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false)); new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, NullCreatorFactory > (false));
manager.add (CSMWorld::UniversalId::Type_Gmst, manager.add (CSMWorld::UniversalId::Type_Gmst,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false)); new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, NullCreatorFactory > (false));
manager.add (CSMWorld::UniversalId::Type_Race,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Class, manager.add (CSMWorld::UniversalId::Type_Referenceable,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false)); new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<ReferenceableCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Reference, manager.add (CSMWorld::UniversalId::Type_Reference,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<ReferenceCreator> > (false)); new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<ReferenceCreator> > (false));
@ -111,18 +116,6 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
manager.add (CSMWorld::UniversalId::Type_Cell, manager.add (CSMWorld::UniversalId::Type_Cell,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<CellCreator> > (false)); new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<CellCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Filter,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Sound,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Faction,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_Skill,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
manager.add (CSMWorld::UniversalId::Type_JournalInfo, manager.add (CSMWorld::UniversalId::Type_JournalInfo,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<InfoCreator> > (false)); new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<InfoCreator> > (false));

@ -19,14 +19,36 @@
#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<std::string> records;
int columnIndex = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id);
for (QModelIndexList::const_iterator iter (selectedRows.begin()); iter!=selectedRows.end();
++iter)
{
int row = mProxyModel->mapToSource (mProxyModel->index (iter->row(), 0)).row();
records.push_back (mModel->data (
mModel->index (row, columnIndex)).toString().toUtf8().constData());
}
mDispatcher->setSelection (records);
std::vector<CSMWorld::UniversalId> extendedTypes = mDispatcher->getExtendedTypes();
mDispatcher->setExtendedTypes (extendedTypes);
// 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,22 +66,27 @@ 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. {
if (mModel->getReordering()==CSMWorld::IdTable::Reordering_None)
if (listRevertableSelectedIds().size()>0)
menu.addAction (mRevertAction); menu.addAction (mRevertAction);
if (listDeletableSelectedIds().size()>0) if (!extendedTypes.empty())
menu.addAction (mExtendedRevertAction);
}
if (mDispatcher->canDelete())
{
menu.addAction (mDeleteAction); menu.addAction (mDeleteAction);
if (mModel->getReordering()==CSMWorld::IdTable::Reordering_WithinTopic) if (!extendedTypes.empty())
menu.addAction (mExtendedDeleteAction);
}
if (mModel->getFeatures() & CSMWorld::IdTable::Feature_ReorderWithinTopic)
{ {
/// \todo allow reordering of multiple rows /// \todo allow reordering of multiple rows
if (selectedRows.size()==1) if (selectedRows.size()==1)
{ {
int row =selectedRows.begin()->row();
int column = mModel->searchColumnIndex (CSMWorld::Columns::ColumnId_Topic); int column = mModel->searchColumnIndex (CSMWorld::Columns::ColumnId_Topic);
if (column==-1) if (column==-1)
@ -67,14 +94,17 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
if (column!=-1) if (column!=-1)
{ {
if (row>0 && mProxyModel->data (mProxyModel->index (row, column))== int row = mProxyModel->mapToSource (
mProxyModel->data (mProxyModel->index (row-1, column))) mProxyModel->index (selectedRows.begin()->row(), 0)).row();
if (row>0 && mModel->data (mModel->index (row, column))==
mModel->data (mModel->index (row-1, column)))
{ {
menu.addAction (mMoveUpAction); menu.addAction (mMoveUpAction);
} }
if (row<mProxyModel->rowCount()-1 && mProxyModel->data (mProxyModel->index (row, column))== if (row<mModel->rowCount()-1 && mModel->data (mModel->index (row, column))==
mProxyModel->data (mProxyModel->index (row+1, column))) mModel->data (mModel->index (row+1, column)))
{ {
menu.addAction (mMoveDownAction); menu.addAction (mMoveDownAction);
} }
@ -85,7 +115,7 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
if (selectedRows.size()==1) if (selectedRows.size()==1)
{ {
if (mModel->getViewing()!=CSMWorld::IdTable::Viewing_None) if (mModel->getFeatures() & CSMWorld::IdTable::Feature_View)
{ {
int row = selectedRows.begin()->row(); int row = selectedRows.begin()->row();
@ -101,91 +131,13 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
menu.addAction (mViewAction); menu.addAction (mViewAction);
} }
if (mModel->hasPreview()) if (mModel->getFeatures() & CSMWorld::IdTable::Feature_Preview)
menu.addAction (mPreviewAction); menu.addAction (mPreviewAction);
} }
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 +148,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 +194,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);
@ -263,6 +217,18 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
connect (mPreviewAction, SIGNAL (triggered()), this, SLOT (previewRecord())); connect (mPreviewAction, SIGNAL (triggered()), this, SLOT (previewRecord()));
addAction (mPreviewAction); addAction (mPreviewAction);
/// \todo add a user option, that redirects the extended action to an input panel (in
/// the bottom bar) that lets the user select which record collections should be
/// modified.
mExtendedDeleteAction = new QAction (tr ("Extended Delete Record"), this);
connect (mExtendedDeleteAction, SIGNAL (triggered()), mDispatcher, SLOT (executeExtendedDelete()));
addAction (mExtendedDeleteAction);
mExtendedRevertAction = new QAction (tr ("Extended Revert Record"), this);
connect (mExtendedRevertAction, SIGNAL (triggered()), mDispatcher, SLOT (executeExtendedRevert()));
addAction (mExtendedRevertAction);
connect (mProxyModel, SIGNAL (rowsInserted (const QModelIndex&, int, int)), connect (mProxyModel, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
this, SLOT (tableSizeUpdate())); this, SLOT (tableSizeUpdate()));
@ -283,53 +249,19 @@ 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
{ {
return CSMWorld::UniversalId ( row = mProxyModel->mapToSource (mProxyModel->index (row, 0)).row();
static_cast<CSMWorld::UniversalId::Type> (mProxyModel->data (mProxyModel->index (row, 2)).toInt()),
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) int idColumn = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id);
mDocument.getUndoStack().push (new CSMWorld::DeleteCommand (*mModel, *iter)); int typeColumn = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_RecordType);
if (deletableIds.size()>1) return CSMWorld::UniversalId (
mDocument.getUndoStack().endMacro(); static_cast<CSMWorld::UniversalId::Type> (mModel->data (mModel->index (row, typeColumn)).toInt()),
} mModel->data (mModel->index (row, idColumn)).toString().toUtf8().constData());
}
} }
void CSVWorld::Table::editRecord() void CSVWorld::Table::editRecord()

@ -24,6 +24,7 @@ namespace CSMWorld
class UniversalId; class UniversalId;
class IdTableProxyModel; class IdTableProxyModel;
class IdTable; class IdTable;
class CommandDispatcher;
} }
namespace CSVWorld namespace CSVWorld
@ -45,18 +46,17 @@ namespace CSVWorld
QAction *mMoveDownAction; QAction *mMoveDownAction;
QAction *mViewAction; QAction *mViewAction;
QAction *mPreviewAction; QAction *mPreviewAction;
QAction *mExtendedDeleteAction;
QAction *mExtendedRevertAction;
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 +93,6 @@ namespace CSVWorld
private slots: private slots:
void revertRecord();
void deleteRecord();
void editRecord(); void editRecord();
void cloneRecord(); void cloneRecord();

Loading…
Cancel
Save