mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-07 07:45:35 +00:00
Merge branch 'refs'
This commit is contained in:
commit
c23e9e03fd
14 changed files with 536 additions and 267 deletions
|
@ -18,7 +18,7 @@ opencs_hdrs_noqt (model/doc
|
|||
|
||||
|
||||
opencs_units (model/world
|
||||
idtable idtableproxymodel regionmap data
|
||||
idtable idtableproxymodel regionmap data commanddispatcher
|
||||
)
|
||||
|
||||
|
||||
|
|
267
apps/opencs/model/world/commanddispatcher.cpp
Normal file
267
apps/opencs/model/world/commanddispatcher.cpp
Normal file
|
@ -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();
|
||||
}
|
69
apps/opencs/model/world/commanddispatcher.hpp
Normal file
69
apps/opencs/model/world/commanddispatcher.hpp
Normal file
|
@ -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 "columns.hpp"
|
||||
|
||||
void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type1,
|
||||
UniversalId::Type type2, bool update)
|
||||
void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type, bool update)
|
||||
{
|
||||
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)
|
||||
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 ScopeColumn<CSMFilter::Filter>);
|
||||
|
||||
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
|
||||
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst);
|
||||
addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill, false);
|
||||
addModel (new IdTable (&mClasses), UniversalId::Type_Classes, UniversalId::Type_Class);
|
||||
addModel (new IdTable (&mFactions), UniversalId::Type_Factions, UniversalId::Type_Faction);
|
||||
addModel (new IdTable (&mRaces), UniversalId::Type_Races, UniversalId::Type_Race);
|
||||
addModel (new IdTable (&mSounds), UniversalId::Type_Sounds, UniversalId::Type_Sound);
|
||||
addModel (new IdTable (&mScripts), UniversalId::Type_Scripts, UniversalId::Type_Script);
|
||||
addModel (new IdTable (&mRegions), UniversalId::Type_Regions, UniversalId::Type_Region);
|
||||
addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsigns, UniversalId::Type_Birthsign);
|
||||
addModel (new IdTable (&mSpells), UniversalId::Type_Spells, UniversalId::Type_Spell);
|
||||
addModel (new IdTable (&mTopics), UniversalId::Type_Topics, UniversalId::Type_Topic);
|
||||
addModel (new IdTable (&mJournals), UniversalId::Type_Journals, UniversalId::Type_Journal);
|
||||
addModel (new IdTable (&mTopicInfos, IdTable::Reordering_WithinTopic), UniversalId::Type_TopicInfos, UniversalId::Type_TopicInfo);
|
||||
addModel (new IdTable (&mJournalInfos, IdTable::Reordering_WithinTopic), UniversalId::Type_JournalInfos, UniversalId::Type_JournalInfo);
|
||||
addModel (new IdTable (&mCells, IdTable::Reordering_None, IdTable::Viewing_Id), UniversalId::Type_Cells, UniversalId::Type_Cell);
|
||||
addModel (new IdTable (&mReferenceables, IdTable::Reordering_None, IdTable::Viewing_None, true),
|
||||
UniversalId::Type_Referenceables, UniversalId::Type_Referenceable);
|
||||
addModel (new IdTable (&mRefs, IdTable::Reordering_None, IdTable::Viewing_Cell, true), UniversalId::Type_References, UniversalId::Type_Reference, false);
|
||||
addModel (new IdTable (&mFilters), UniversalId::Type_Filters, UniversalId::Type_Filter, false);
|
||||
addModel (new IdTable (&mGlobals), UniversalId::Type_Global);
|
||||
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmst);
|
||||
addModel (new IdTable (&mSkills), UniversalId::Type_Skill);
|
||||
addModel (new IdTable (&mClasses), UniversalId::Type_Class);
|
||||
addModel (new IdTable (&mFactions), UniversalId::Type_Faction);
|
||||
addModel (new IdTable (&mRaces), UniversalId::Type_Race);
|
||||
addModel (new IdTable (&mSounds), UniversalId::Type_Sound);
|
||||
addModel (new IdTable (&mScripts), UniversalId::Type_Script);
|
||||
addModel (new IdTable (&mRegions), UniversalId::Type_Region);
|
||||
addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsign);
|
||||
addModel (new IdTable (&mSpells), UniversalId::Type_Spell);
|
||||
addModel (new IdTable (&mTopics), UniversalId::Type_Topic);
|
||||
addModel (new IdTable (&mJournals), UniversalId::Type_Journal);
|
||||
addModel (new IdTable (&mTopicInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_TopicInfo);
|
||||
addModel (new IdTable (&mJournalInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_JournalInfo);
|
||||
addModel (new IdTable (&mCells, IdTable::Feature_ViewId), UniversalId::Type_Cell);
|
||||
addModel (new IdTable (&mReferenceables, IdTable::Feature_Preview),
|
||||
UniversalId::Type_Referenceable);
|
||||
addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_Reference);
|
||||
addModel (new IdTable (&mFilters), UniversalId::Type_Filter);
|
||||
}
|
||||
|
||||
CSMWorld::Data::~Data()
|
||||
|
@ -469,8 +470,7 @@ QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId&
|
|||
if (id.getType()==UniversalId::Type_RegionMap)
|
||||
{
|
||||
RegionMap *table = 0;
|
||||
addModel (table = new RegionMap (*this), UniversalId::Type_RegionMap,
|
||||
UniversalId::Type_None, false);
|
||||
addModel (table = new RegionMap (*this), UniversalId::Type_RegionMap, false);
|
||||
return table;
|
||||
}
|
||||
throw std::logic_error ("No table model available for " + id.toString());
|
||||
|
|
|
@ -83,8 +83,8 @@ namespace CSMWorld
|
|||
Data (const Data&);
|
||||
Data& operator= (const Data&);
|
||||
|
||||
void addModel (QAbstractItemModel *model, UniversalId::Type type1,
|
||||
UniversalId::Type type2 = UniversalId::Type_None, bool update = true);
|
||||
void addModel (QAbstractItemModel *model, UniversalId::Type type,
|
||||
bool update = true);
|
||||
|
||||
static void appendIds (std::vector<std::string>& ids, const CollectionBase& collection,
|
||||
bool listDeleted);
|
||||
|
|
|
@ -4,9 +4,8 @@
|
|||
#include "collectionbase.hpp"
|
||||
#include "columnbase.hpp"
|
||||
|
||||
CSMWorld::IdTable::IdTable (CollectionBase *idCollection, Reordering reordering,
|
||||
Viewing viewing, bool preview)
|
||||
: mIdCollection (idCollection), mReordering (reordering), mViewing (viewing), mPreview (preview)
|
||||
CSMWorld::IdTable::IdTable (CollectionBase *idCollection, unsigned int features)
|
||||
: mIdCollection (idCollection), mFeatures (features)
|
||||
{}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
CSMWorld::IdTable::Reordering CSMWorld::IdTable::getReordering() const
|
||||
unsigned int CSMWorld::IdTable::getFeatures() const
|
||||
{
|
||||
return mReordering;
|
||||
}
|
||||
|
||||
CSMWorld::IdTable::Viewing CSMWorld::IdTable::getViewing() const
|
||||
{
|
||||
return mViewing;
|
||||
}
|
||||
|
||||
bool CSMWorld::IdTable::hasPreview() const
|
||||
{
|
||||
return mPreview;
|
||||
return mFeatures;
|
||||
}
|
||||
|
||||
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 hint;
|
||||
|
||||
if (mViewing==Viewing_Cell)
|
||||
if (mFeatures & Feature_ViewCell)
|
||||
{
|
||||
int cellColumn = mIdCollection->searchColumnIndex (Columns::ColumnId_Cell);
|
||||
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());
|
||||
}
|
||||
}
|
||||
else if (mViewing==Viewing_Id)
|
||||
else if (mFeatures & Feature_ViewId)
|
||||
{
|
||||
int column = mIdCollection->searchColumnIndex (Columns::ColumnId_Id);
|
||||
|
||||
|
|
|
@ -19,26 +19,27 @@ namespace CSMWorld
|
|||
|
||||
public:
|
||||
|
||||
enum Reordering
|
||||
enum Features
|
||||
{
|
||||
Reordering_None,
|
||||
Reordering_WithinTopic
|
||||
};
|
||||
Feature_ReorderWithinTopic = 1,
|
||||
|
||||
enum Viewing
|
||||
{
|
||||
Viewing_None,
|
||||
Viewing_Id, // use ID column to generate view request (ID is transformed into
|
||||
// worldspace and original ID is passed as hint with c: prefix)
|
||||
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)
|
||||
/// Use ID column to generate view request (ID is transformed into
|
||||
/// worldspace and original ID is passed as hint with c: prefix).
|
||||
Feature_ViewId = 2,
|
||||
|
||||
/// Use cell column to generate view request (cell ID is transformed
|
||||
/// 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:
|
||||
|
||||
CollectionBase *mIdCollection;
|
||||
Reordering mReordering;
|
||||
Viewing mViewing;
|
||||
unsigned int mFeatures;
|
||||
bool mPreview;
|
||||
|
||||
// not implemented
|
||||
|
@ -47,8 +48,7 @@ namespace CSMWorld
|
|||
|
||||
public:
|
||||
|
||||
IdTable (CollectionBase *idCollection, Reordering reordering = Reordering_None,
|
||||
Viewing viewing = Viewing_None, bool preview = false);
|
||||
IdTable (CollectionBase *idCollection, unsigned int features = 0);
|
||||
///< The ownership of \a idCollection is not transferred.
|
||||
|
||||
virtual ~IdTable();
|
||||
|
@ -97,11 +97,7 @@ namespace CSMWorld
|
|||
///< 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).
|
||||
|
||||
Reordering getReordering() const;
|
||||
|
||||
Viewing getViewing() const;
|
||||
|
||||
bool hasPreview() const;
|
||||
unsigned int getFeatures() const;
|
||||
|
||||
std::pair<UniversalId, std::string> view (int row) const;
|
||||
///< 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_Topic, "Topic", 0 },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Journal, "Journal", 0 },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_TopicInfo, "TopicInfo", 0 },
|
||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo", 0 },
|
||||
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_TopicInfo, "TopicInfo", 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_Missing, "Cell", ":./cell.png" },
|
||||
{ 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_Weapon, "Weapon", ":./weapon.png" },
|
||||
{ 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_Preview, "Preview", 0 },
|
||||
|
@ -320,6 +320,28 @@ std::vector<CSMWorld::UniversalId::Type> CSMWorld::UniversalId::listReferenceabl
|
|||
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)
|
||||
{
|
||||
return left.isEqual (right);
|
||||
|
|
|
@ -32,6 +32,8 @@ namespace CSMWorld
|
|||
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
|
||||
{
|
||||
Type_None = 0,
|
||||
|
@ -86,8 +88,8 @@ namespace CSMWorld
|
|||
Type_References,
|
||||
Type_Reference,
|
||||
Type_RegionMap,
|
||||
Type_Filter,
|
||||
Type_Filters,
|
||||
Type_Filter,
|
||||
Type_Topics,
|
||||
Type_Topic,
|
||||
Type_Journals,
|
||||
|
@ -147,6 +149,11 @@ namespace CSMWorld
|
|||
///< Will return an empty string, if no icon is available.
|
||||
|
||||
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);
|
||||
|
|
|
@ -332,6 +332,7 @@ void CSVWorld::EditWidget::remake(int row)
|
|||
if (mMainWidget)
|
||||
{
|
||||
delete mMainWidget;
|
||||
mMainWidget = 0;
|
||||
}
|
||||
mMainWidget = new QWidget (this);
|
||||
|
||||
|
@ -339,6 +340,7 @@ void CSVWorld::EditWidget::remake(int row)
|
|||
if (mWidgetMapper)
|
||||
{
|
||||
delete mWidgetMapper;
|
||||
mWidgetMapper = 0;
|
||||
}
|
||||
mWidgetMapper = new QDataWidgetMapper (this);
|
||||
mWidgetMapper->setModel(mTable);
|
||||
|
@ -396,7 +398,7 @@ void CSVWorld::EditWidget::remake(int row)
|
|||
|
||||
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->setWidgetResizable(true);
|
||||
}
|
||||
|
@ -407,7 +409,6 @@ void CSVWorld::EditWidget::remake(int row)
|
|||
|
||||
CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document,
|
||||
const CreatorFactoryBase& creatorFactory, bool sorting) :
|
||||
|
||||
SubView (id),
|
||||
mEditWidget(0),
|
||||
mMainLayout(NULL),
|
||||
|
@ -415,8 +416,8 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM
|
|||
mTable(dynamic_cast<CSMWorld::IdTable*>(document.getData().getTableModel(id))),
|
||||
mRow (-1),
|
||||
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&)));
|
||||
mRow = mTable->getModelIndex (id.getId(), 0).row();
|
||||
|
@ -440,7 +441,7 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM
|
|||
QToolButton* revertButton = new QToolButton(mainWidget);
|
||||
revertButton->setIcon(QIcon(":/edit-undo.png"));
|
||||
|
||||
if (mTable->hasPreview())
|
||||
if (mTable->getFeatures() & CSMWorld::IdTable::Feature_Preview)
|
||||
{
|
||||
QToolButton* previewButton = new QToolButton(mainWidget);
|
||||
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()));
|
||||
}
|
||||
|
||||
if (mTable->getViewing()!=CSMWorld::IdTable::Viewing_None)
|
||||
if (mTable->getFeatures() & CSMWorld::IdTable::Feature_View)
|
||||
{
|
||||
QToolButton* viewButton = new QToolButton(mainWidget);
|
||||
viewButton->setIcon(QIcon(":/cell.png"));
|
||||
|
@ -560,14 +561,12 @@ void CSVWorld::DialogueSubView::nextId()
|
|||
void CSVWorld::DialogueSubView::setEditLock (bool locked)
|
||||
{
|
||||
mLocked = locked;
|
||||
|
||||
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(true);
|
||||
} else
|
||||
{
|
||||
mEditWidget->setDisabled(mLocked);
|
||||
}
|
||||
|
||||
mEditWidget->setDisabled (state==CSMWorld::RecordBase::State_Deleted || locked);
|
||||
|
||||
mCommandDispatcher.setEditLock (locked);
|
||||
}
|
||||
|
||||
void CSVWorld::DialogueSubView::dataChanged(const QModelIndex & index)
|
||||
|
@ -575,13 +574,8 @@ void CSVWorld::DialogueSubView::dataChanged(const QModelIndex & index)
|
|||
if (index.row() == mRow)
|
||||
{
|
||||
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(true);
|
||||
} else
|
||||
{
|
||||
mEditWidget->setDisabled(mLocked);
|
||||
}
|
||||
|
||||
mEditWidget->setDisabled (state==CSMWorld::RecordBase::State_Deleted || mLocked);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -671,7 +665,8 @@ void CSVWorld::DialogueSubView::cloneRequest ()
|
|||
|
||||
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()), "");
|
||||
}
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
#include <QScrollArea>
|
||||
|
||||
#include "../doc/subview.hpp"
|
||||
|
||||
#include "../../model/world/columnbase.hpp"
|
||||
#include "../../model/world/commanddispatcher.hpp"
|
||||
|
||||
class QDataWidgetMapper;
|
||||
class QSize;
|
||||
|
@ -169,6 +171,7 @@ namespace CSVWorld
|
|||
bool mLocked;
|
||||
const CSMDoc::Document& mDocument;
|
||||
TableBottomBox* mBottom;
|
||||
CSMWorld::CommandDispatcher mCommandDispatcher;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -80,49 +80,42 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
|||
|
||||
manager.add (CSMWorld::UniversalId::Type_Scene, new CSVDoc::SubViewFactory<SceneSubView>);
|
||||
|
||||
//edit subviews
|
||||
manager.add (CSMWorld::UniversalId::Type_Region,
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
|
||||
// Dialogue subviews
|
||||
static const CSMWorld::UniversalId::Type sTableTypes2[] =
|
||||
{
|
||||
CSMWorld::UniversalId::Type_Region,
|
||||
CSMWorld::UniversalId::Type_Spell,
|
||||
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_Spell,
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
|
||||
CSMWorld::UniversalId::Type_None // end marker
|
||||
};
|
||||
|
||||
for (int i=0; sTableTypes2[i]!=CSMWorld::UniversalId::Type_None; ++i)
|
||||
manager.add (sTableTypes2[i],
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView,
|
||||
CreatorFactory<GenericCreator> > (false));
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_Skill,
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, NullCreatorFactory > (false));
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_Gmst,
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, NullCreatorFactory > (false));
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_Referenceable,
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<ReferenceableCreator> > (false));
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_Birthsign,
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_Global,
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_Gmst,
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_Race,
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_Class,
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> > (false));
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_Reference,
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<ReferenceCreator> > (false));
|
||||
|
||||
manager.add (CSMWorld::UniversalId::Type_Cell,
|
||||
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,
|
||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<InfoCreator> > (false));
|
||||
|
||||
|
|
|
@ -19,14 +19,36 @@
|
|||
#include "../../model/world/columns.hpp"
|
||||
#include "../../model/world/tablemimedata.hpp"
|
||||
#include "../../model/world/tablemimedata.hpp"
|
||||
#include "../../model/world/commanddispatcher.hpp"
|
||||
|
||||
#include "recordstatusdelegate.hpp"
|
||||
#include "util.hpp"
|
||||
|
||||
void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
||||
{
|
||||
// configure dispatcher
|
||||
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);
|
||||
|
||||
/// \todo add menu items for select all and clear selection
|
||||
|
@ -44,22 +66,27 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
|||
if (mCreateAction)
|
||||
menu.addAction (mCreateAction);
|
||||
|
||||
/// \todo Reverting temporarily disabled on tables that support reordering, because
|
||||
/// revert logic currently can not handle reordering.
|
||||
if (mModel->getReordering()==CSMWorld::IdTable::Reordering_None)
|
||||
if (listRevertableSelectedIds().size()>0)
|
||||
menu.addAction (mRevertAction);
|
||||
if (mDispatcher->canRevert())
|
||||
{
|
||||
menu.addAction (mRevertAction);
|
||||
|
||||
if (listDeletableSelectedIds().size()>0)
|
||||
if (!extendedTypes.empty())
|
||||
menu.addAction (mExtendedRevertAction);
|
||||
}
|
||||
|
||||
if (mDispatcher->canDelete())
|
||||
{
|
||||
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
|
||||
if (selectedRows.size()==1)
|
||||
{
|
||||
int row =selectedRows.begin()->row();
|
||||
|
||||
int column = mModel->searchColumnIndex (CSMWorld::Columns::ColumnId_Topic);
|
||||
|
||||
if (column==-1)
|
||||
|
@ -67,14 +94,17 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
|||
|
||||
if (column!=-1)
|
||||
{
|
||||
if (row>0 && mProxyModel->data (mProxyModel->index (row, column))==
|
||||
mProxyModel->data (mProxyModel->index (row-1, column)))
|
||||
int row = mProxyModel->mapToSource (
|
||||
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);
|
||||
}
|
||||
|
||||
if (row<mProxyModel->rowCount()-1 && mProxyModel->data (mProxyModel->index (row, column))==
|
||||
mProxyModel->data (mProxyModel->index (row+1, column)))
|
||||
if (row<mModel->rowCount()-1 && mModel->data (mModel->index (row, column))==
|
||||
mModel->data (mModel->index (row+1, column)))
|
||||
{
|
||||
menu.addAction (mMoveDownAction);
|
||||
}
|
||||
|
@ -85,7 +115,7 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
|||
|
||||
if (selectedRows.size()==1)
|
||||
{
|
||||
if (mModel->getViewing()!=CSMWorld::IdTable::Viewing_None)
|
||||
if (mModel->getFeatures() & CSMWorld::IdTable::Feature_View)
|
||||
{
|
||||
int row = selectedRows.begin()->row();
|
||||
|
||||
|
@ -101,91 +131,13 @@ void CSVWorld::Table::contextMenuEvent (QContextMenuEvent *event)
|
|||
menu.addAction (mViewAction);
|
||||
}
|
||||
|
||||
if (mModel->hasPreview())
|
||||
if (mModel->getFeatures() & CSMWorld::IdTable::Feature_Preview)
|
||||
menu.addAction (mPreviewAction);
|
||||
}
|
||||
|
||||
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,
|
||||
bool createAndDelete, bool sorting, CSMDoc::Document& document)
|
||||
: mCreateAction (0), mCloneAction(0), mRecordStatusDisplay (0),
|
||||
|
@ -196,6 +148,8 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
|
|||
mProxyModel = new CSMWorld::IdTableProxyModel (this);
|
||||
mProxyModel->setSourceModel (mModel);
|
||||
|
||||
mDispatcher = new CSMWorld::CommandDispatcher (document, id, this);
|
||||
|
||||
setModel (mProxyModel);
|
||||
horizontalHeader()->setResizeMode (QHeaderView::Interactive);
|
||||
verticalHeader()->hide();
|
||||
|
@ -240,11 +194,11 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id,
|
|||
}
|
||||
|
||||
mRevertAction = new QAction (tr ("Revert Record"), this);
|
||||
connect (mRevertAction, SIGNAL (triggered()), this, SLOT (revertRecord()));
|
||||
connect (mRevertAction, SIGNAL (triggered()), mDispatcher, SLOT (executeRevert()));
|
||||
addAction (mRevertAction);
|
||||
|
||||
mDeleteAction = new QAction (tr ("Delete Record"), this);
|
||||
connect (mDeleteAction, SIGNAL (triggered()), this, SLOT (deleteRecord()));
|
||||
connect (mDeleteAction, SIGNAL (triggered()), mDispatcher, SLOT (executeDelete()));
|
||||
addAction (mDeleteAction);
|
||||
|
||||
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()));
|
||||
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)),
|
||||
this, SLOT (tableSizeUpdate()));
|
||||
|
||||
|
@ -283,53 +249,19 @@ void CSVWorld::Table::setEditLock (bool locked)
|
|||
(*iter)->setEditLock (locked);
|
||||
|
||||
DragRecordTable::setEditLock(locked);
|
||||
mDispatcher->setEditLock (locked);
|
||||
}
|
||||
|
||||
CSMWorld::UniversalId CSVWorld::Table::getUniversalId (int row) const
|
||||
{
|
||||
row = mProxyModel->mapToSource (mProxyModel->index (row, 0)).row();
|
||||
|
||||
int idColumn = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_Id);
|
||||
int typeColumn = mModel->findColumnIndex (CSMWorld::Columns::ColumnId_RecordType);
|
||||
|
||||
return CSMWorld::UniversalId (
|
||||
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)
|
||||
mDocument.getUndoStack().push (new CSMWorld::DeleteCommand (*mModel, *iter));
|
||||
|
||||
if (deletableIds.size()>1)
|
||||
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()
|
||||
|
|
|
@ -24,6 +24,7 @@ namespace CSMWorld
|
|||
class UniversalId;
|
||||
class IdTableProxyModel;
|
||||
class IdTable;
|
||||
class CommandDispatcher;
|
||||
}
|
||||
|
||||
namespace CSVWorld
|
||||
|
@ -45,18 +46,17 @@ namespace CSVWorld
|
|||
QAction *mMoveDownAction;
|
||||
QAction *mViewAction;
|
||||
QAction *mPreviewAction;
|
||||
QAction *mExtendedDeleteAction;
|
||||
QAction *mExtendedRevertAction;
|
||||
CSMWorld::IdTableProxyModel *mProxyModel;
|
||||
CSMWorld::IdTable *mModel;
|
||||
int mRecordStatusDisplay;
|
||||
CSMWorld::CommandDispatcher *mDispatcher;
|
||||
|
||||
private:
|
||||
|
||||
void contextMenuEvent (QContextMenuEvent *event);
|
||||
|
||||
std::vector<std::string> listRevertableSelectedIds() const;
|
||||
|
||||
std::vector<std::string> listDeletableSelectedIds() const;
|
||||
|
||||
void mouseMoveEvent(QMouseEvent *event);
|
||||
|
||||
void dropEvent(QDropEvent *event);
|
||||
|
@ -93,10 +93,6 @@ namespace CSVWorld
|
|||
|
||||
private slots:
|
||||
|
||||
void revertRecord();
|
||||
|
||||
void deleteRecord();
|
||||
|
||||
void editRecord();
|
||||
|
||||
void cloneRecord();
|
||||
|
|
Loading…
Reference in a new issue