forked from teamnwah/openmw-tes3coop
Merge remote-tracking branch 'upstream/master'
commit
36e380c6be
@ -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
|
@ -0,0 +1,105 @@
|
|||||||
|
#include "itemwidget.hpp"
|
||||||
|
|
||||||
|
#include <MyGUI_FactoryManager.h>
|
||||||
|
#include <MyGUI_ImageBox.h>
|
||||||
|
|
||||||
|
#include "../mwworld/class.hpp"
|
||||||
|
|
||||||
|
namespace MWGui
|
||||||
|
{
|
||||||
|
|
||||||
|
ItemWidget::ItemWidget()
|
||||||
|
: mItem(NULL)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemWidget::registerComponents()
|
||||||
|
{
|
||||||
|
MyGUI::FactoryManager::getInstance().registerFactory<ItemWidget>("Widget");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemWidget::initialiseOverride()
|
||||||
|
{
|
||||||
|
assignWidget(mItem, "Item");
|
||||||
|
if (mItem)
|
||||||
|
mItem->setNeedMouseFocus(false);
|
||||||
|
assignWidget(mFrame, "Frame");
|
||||||
|
if (mFrame)
|
||||||
|
mFrame->setNeedMouseFocus(false);
|
||||||
|
|
||||||
|
Base::initialiseOverride();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemWidget::setIcon(const std::string &icon)
|
||||||
|
{
|
||||||
|
if (mItem)
|
||||||
|
mItem->setImageTexture(icon);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemWidget::setFrame(const std::string &frame, const MyGUI::IntCoord &coord)
|
||||||
|
{
|
||||||
|
if (mFrame)
|
||||||
|
{
|
||||||
|
mFrame->setImageTexture(frame);
|
||||||
|
mFrame->setImageTile(MyGUI::IntSize(coord.width, coord.height)); // Why is this needed? MyGUI bug?
|
||||||
|
mFrame->setImageCoord(coord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ItemWidget::setIcon(const MWWorld::Ptr &ptr)
|
||||||
|
{
|
||||||
|
// image
|
||||||
|
std::string path = std::string("icons\\");
|
||||||
|
path += ptr.getClass().getInventoryIcon(ptr);
|
||||||
|
|
||||||
|
std::string::size_type pos = path.rfind(".");
|
||||||
|
if(pos != std::string::npos)
|
||||||
|
path.erase(pos);
|
||||||
|
path.append(".dds");
|
||||||
|
setIcon(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ItemWidget::setItem(const MWWorld::Ptr &ptr, ItemState state)
|
||||||
|
{
|
||||||
|
if (!mItem)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ptr.isEmpty())
|
||||||
|
{
|
||||||
|
if (mFrame)
|
||||||
|
mFrame->setImageTexture("");
|
||||||
|
mItem->setImageTexture("");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isMagic = !ptr.getClass().getEnchantment(ptr).empty();
|
||||||
|
|
||||||
|
std::string backgroundTex = "textures\\menu_icon";
|
||||||
|
if (isMagic)
|
||||||
|
backgroundTex += "_magic";
|
||||||
|
if (state == None)
|
||||||
|
{
|
||||||
|
if (!isMagic)
|
||||||
|
backgroundTex = "";
|
||||||
|
}
|
||||||
|
else if (state == Equip)
|
||||||
|
{
|
||||||
|
backgroundTex += "_equip";
|
||||||
|
}
|
||||||
|
else if (state == Barter)
|
||||||
|
backgroundTex += "_barter";
|
||||||
|
|
||||||
|
if (backgroundTex != "")
|
||||||
|
backgroundTex += ".dds";
|
||||||
|
|
||||||
|
if (state == Barter && !isMagic)
|
||||||
|
setFrame(backgroundTex, MyGUI::IntCoord(2,2,42,42));
|
||||||
|
else
|
||||||
|
setFrame(backgroundTex, MyGUI::IntCoord(0,0,42,42));
|
||||||
|
|
||||||
|
setIcon(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
#ifndef OPENMW_MWGUI_ITEMWIDGET_H
|
||||||
|
#define OPENMW_MWGUI_ITEMWIDGET_H
|
||||||
|
|
||||||
|
#include <MyGUI_Widget.h>
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
class Ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace MWGui
|
||||||
|
{
|
||||||
|
|
||||||
|
/// @brief A widget that shows an icon for an MWWorld::Ptr
|
||||||
|
class ItemWidget : public MyGUI::Widget
|
||||||
|
{
|
||||||
|
MYGUI_RTTI_DERIVED(ItemWidget)
|
||||||
|
public:
|
||||||
|
ItemWidget();
|
||||||
|
|
||||||
|
/// Register needed components with MyGUI's factory manager
|
||||||
|
static void registerComponents ();
|
||||||
|
|
||||||
|
enum ItemState
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Equip,
|
||||||
|
Barter,
|
||||||
|
Magic
|
||||||
|
};
|
||||||
|
|
||||||
|
/// \a ptr may be empty
|
||||||
|
void setItem (const MWWorld::Ptr& ptr, ItemState state = None);
|
||||||
|
|
||||||
|
// Set icon and frame manually
|
||||||
|
void setIcon (const std::string& icon);
|
||||||
|
void setIcon (const MWWorld::Ptr& ptr);
|
||||||
|
void setFrame (const std::string& frame, const MyGUI::IntCoord& coord);
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual void initialiseOverride();
|
||||||
|
|
||||||
|
MyGUI::ImageBox* mItem;
|
||||||
|
MyGUI::ImageBox* mFrame;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue