diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 95d818a5a..6bcad1d08 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -60,7 +60,7 @@ opencs_hdrs_noqt (view/doc opencs_units (view/world table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool - scenetoolmode infocreator + scenetoolmode infocreator scriptedit ) opencs_units (view/render diff --git a/apps/opencs/model/doc/document.hpp b/apps/opencs/model/doc/document.hpp index 437b0c513..201fb4342 100644 --- a/apps/opencs/model/doc/document.hpp +++ b/apps/opencs/model/doc/document.hpp @@ -71,7 +71,10 @@ namespace CSMDoc public: - Document (const Files::ConfigurationManager& configuration, const std::vector< boost::filesystem::path >& files, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, bool new_); + Document (const Files::ConfigurationManager& configuration, + const std::vector< boost::filesystem::path >& files, + const boost::filesystem::path& savePath, + const boost::filesystem::path& resDir, bool new_); ~Document(); diff --git a/apps/opencs/model/doc/documentmanager.hpp b/apps/opencs/model/doc/documentmanager.hpp index b80a18642..b969862e9 100644 --- a/apps/opencs/model/doc/documentmanager.hpp +++ b/apps/opencs/model/doc/documentmanager.hpp @@ -29,7 +29,9 @@ namespace CSMDoc ~DocumentManager(); - Document *addDocument (const std::vector< boost::filesystem::path >& files, const boost::filesystem::path& savePath, bool new_); + Document *addDocument (const std::vector< boost::filesystem::path >& files, + const boost::filesystem::path& savePath, + bool new_); ///< The ownership of the returned document is not transferred to the caller. /// /// \param new_ Do not load the last content file in \a files and instead create in an diff --git a/apps/opencs/model/world/tablemimedata.cpp b/apps/opencs/model/world/tablemimedata.cpp index b0cf0abcc..ee37dfce6 100644 --- a/apps/opencs/model/world/tablemimedata.cpp +++ b/apps/opencs/model/world/tablemimedata.cpp @@ -4,14 +4,15 @@ #include "universalid.hpp" #include "columnbase.hpp" -CSMWorld::TableMimeData::TableMimeData (UniversalId id) +CSMWorld::TableMimeData::TableMimeData (UniversalId id, const CSMDoc::Document& document) : +mDocument(document) { mUniversalId.push_back (id); mObjectsFormats << QString::fromStdString ("tabledata/" + id.getTypeName()); } -CSMWorld::TableMimeData::TableMimeData (std::vector< CSMWorld::UniversalId >& id) : - mUniversalId (id) +CSMWorld::TableMimeData::TableMimeData (std::vector< CSMWorld::UniversalId >& id, const CSMDoc::Document& document) : + mUniversalId (id), mDocument(document) { for (std::vector::iterator it (mUniversalId.begin()); it != mUniversalId.end(); ++it) { @@ -115,6 +116,11 @@ CSMWorld::UniversalId CSMWorld::TableMimeData::returnMatching (CSMWorld::ColumnB throw ("TableMimeData object does not hold object of the seeked type"); } +bool CSMWorld::TableMimeData::fromDocument (const CSMDoc::Document& document) const +{ + return &document == &mDocument; +} + CSMWorld::UniversalId::Type CSMWorld::TableMimeData::convertEnums (CSMWorld::ColumnBase::Display type) const { switch (type) diff --git a/apps/opencs/model/world/tablemimedata.hpp b/apps/opencs/model/world/tablemimedata.hpp index 2829a0754..010a18acb 100644 --- a/apps/opencs/model/world/tablemimedata.hpp +++ b/apps/opencs/model/world/tablemimedata.hpp @@ -10,6 +10,10 @@ #include "universalid.hpp" #include "columnbase.hpp" +namespace CSMDoc +{ + class Document; +} namespace CSMWorld { @@ -24,22 +28,34 @@ namespace CSMWorld class TableMimeData : public QMimeData { public: - TableMimeData(UniversalId id); - TableMimeData(std::vector& id); + TableMimeData(UniversalId id, const CSMDoc::Document& document); + + TableMimeData(std::vector& id, const CSMDoc::Document& document); + ~TableMimeData(); + virtual QStringList formats() const; + std::string getIcon() const; + std::vector getData() const; + bool holdsType(UniversalId::Type type) const; + bool holdsType(CSMWorld::ColumnBase::Display type) const; + + bool fromDocument(const CSMDoc::Document& document) const; + UniversalId returnMatching(UniversalId::Type type) const; + UniversalId returnMatching(CSMWorld::ColumnBase::Display type) const; private: std::vector mUniversalId; QStringList mObjectsFormats; + const CSMDoc::Document& mDocument; CSMWorld::UniversalId::Type convertEnums(CSMWorld::ColumnBase::Display type) const; }; } -#endif // TABLEMIMEDATA_H +#endif // TABLEMIMEDATA_H \ No newline at end of file diff --git a/apps/opencs/view/world/scriptedit.cpp b/apps/opencs/view/world/scriptedit.cpp new file mode 100644 index 000000000..fccac75b4 --- /dev/null +++ b/apps/opencs/view/world/scriptedit.cpp @@ -0,0 +1,88 @@ +#include "scriptedit.hpp" + +#include + +#include +#include +#include + +#include "../../model/world/universalid.hpp" +#include "../../model/world/tablemimedata.hpp" + +CSVWorld::ScriptEdit::ScriptEdit (QWidget* parent, const CSMDoc::Document& document) : + QTextEdit (parent), + mDocument (document), + mWhiteListQoutes("^[a-z|_]{1}[a-z|0-9|_]{0,}$", Qt::CaseInsensitive) +{ + mAllowedTypes <pos())); + event->acceptProposedAction(); +} + +void CSVWorld::ScriptEdit::dragMoveEvent (QDragMoveEvent* event) +{ + setTextCursor (cursorForPosition (event->pos())); + event->accept(); +} + +void CSVWorld::ScriptEdit::dropEvent (QDropEvent* event) +{ + const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); + + setTextCursor (cursorForPosition (event->pos())); + + if (mime->fromDocument (mDocument)) + { + std::vector records (mime->getData()); + + for (std::vector::iterator it = records.begin(); it != records.end(); ++it) + { + if (mAllowedTypes.contains (it->getType())) + { + if (stringNeedsQuote(it->getId())) + { + insertPlainText(QString::fromStdString ('"' + it->getId() + '"')); + } else { + insertPlainText(QString::fromStdString (it->getId())); + } + } + } + } +} + +bool CSVWorld::ScriptEdit::stringNeedsQuote (const std::string& id) const +{ + const QString string(QString::fromStdString(id)); // is only for c++11, so let's use qregexp for now. + //I'm not quite sure when do we need to put quotes. To be safe we will use quotes for anything other than… + return !(string.contains(mWhiteListQoutes)); +} diff --git a/apps/opencs/view/world/scriptedit.hpp b/apps/opencs/view/world/scriptedit.hpp new file mode 100644 index 000000000..b4627c2fe --- /dev/null +++ b/apps/opencs/view/world/scriptedit.hpp @@ -0,0 +1,39 @@ +#ifndef SCRIPTEDIT_H +#define SCRIPTEDIT_H + +#include +#include + +#include "../../model/world/universalid.hpp" + +class QWidget; +class QRegExp; + +namespace CSMDoc +{ + class Document; +} + +namespace CSVWorld +{ + class ScriptEdit : public QTextEdit + { + Q_OBJECT + public: + ScriptEdit (QWidget* parent, const CSMDoc::Document& document); + + private: + QVector mAllowedTypes; + const CSMDoc::Document& mDocument; + const QRegExp mWhiteListQoutes; + + void dragEnterEvent (QDragEnterEvent* event); + + void dropEvent (QDropEvent* event); + + void dragMoveEvent (QDragMoveEvent* event); + + bool stringNeedsQuote(const std::string& id) const; + }; +} +#endif // SCRIPTEDIT_H \ No newline at end of file diff --git a/apps/opencs/view/world/scriptsubview.cpp b/apps/opencs/view/world/scriptsubview.cpp index 446c34e5f..fa41151ca 100644 --- a/apps/opencs/view/world/scriptsubview.cpp +++ b/apps/opencs/view/world/scriptsubview.cpp @@ -13,6 +13,7 @@ #include "../../model/world/idtable.hpp" #include "scripthighlighter.hpp" +#include "scriptedit.hpp" CSVWorld::ScriptSubView::ChangeLock::ChangeLock (ScriptSubView& view) : mView (view) { @@ -27,7 +28,7 @@ CSVWorld::ScriptSubView::ChangeLock::~ChangeLock() CSVWorld::ScriptSubView::ScriptSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document) : SubView (id), mDocument (document), mColumn (-1), mChangeLocked (0) { - setWidget (mEditor = new QTextEdit (this)); + setWidget (mEditor = new ScriptEdit (this, mDocument)); mEditor->setAcceptRichText (false); mEditor->setLineWrapMode (QTextEdit::NoWrap); diff --git a/apps/opencs/view/world/table.cpp b/apps/opencs/view/world/table.cpp index 3ce90d3a7..f1d89e22c 100644 --- a/apps/opencs/view/world/table.cpp +++ b/apps/opencs/view/world/table.cpp @@ -162,8 +162,8 @@ std::vector CSVWorld::Table::listDeletableSelectedIds() const } CSVWorld::Table::Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, - bool createAndDelete, bool sorting) - : mUndoStack (undoStack), mCreateAction (0), mCloneAction(0), mEditLock (false), mRecordStatusDisplay (0) + bool createAndDelete, bool sorting, const CSMDoc::Document& document) + : mUndoStack (undoStack), mCreateAction (0), mCloneAction(0), mEditLock (false), mRecordStatusDisplay (0), mDocument(document) { mModel = &dynamic_cast (*data.getTableModel (id)); @@ -455,7 +455,7 @@ void CSVWorld::Table::mouseMoveEvent (QMouseEvent* event) if (selectedRows.size() == 1) { - mime = new CSMWorld::TableMimeData (getUniversalId (selectedRows.begin()->row())); + mime = new CSMWorld::TableMimeData (getUniversalId (selectedRows.begin()->row()), mDocument); } else { @@ -466,7 +466,7 @@ void CSVWorld::Table::mouseMoveEvent (QMouseEvent* event) idToDrag.push_back (getUniversalId (it.row())); } - mime = new CSMWorld::TableMimeData (idToDrag); + mime = new CSMWorld::TableMimeData (idToDrag, mDocument); } drag->setMimeData (mime); @@ -485,21 +485,22 @@ void CSVWorld::Table::dropEvent(QDropEvent *event) { QModelIndex index = indexAt (event->pos()); - CSMWorld::ColumnBase::Display display = static_cast - (mModel->headerData(index.column(), Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt()); - - if (dynamic_cast(event->mimeData())->holdsType(display)) + const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); + if (mime->fromDocument (mDocument)) { - const CSMWorld::TableMimeData* mime = dynamic_cast - (event->mimeData()); + CSMWorld::ColumnBase::Display display = static_cast + (mModel->headerData (index.column(), Qt::Horizontal, CSMWorld::ColumnBase::Role_Display).toInt()); - CSMWorld::UniversalId record (mime->returnMatching (display)); + if (mime->holdsType (display)) + { + CSMWorld::UniversalId record (mime->returnMatching (display)); - std::auto_ptr command (new CSMWorld::ModifyCommand - (*mProxyModel, index, QVariant (QString::fromStdString (record.getId())))); + std::auto_ptr command (new CSMWorld::ModifyCommand + (*mProxyModel, index, QVariant (QString::fromStdString (record.getId())))); - mUndoStack.push (command.release()); - } + mUndoStack.push (command.release()); + } + } //TODO handle drops from different document } void CSVWorld::Table::dragMoveEvent(QDragMoveEvent *event) diff --git a/apps/opencs/view/world/table.hpp b/apps/opencs/view/world/table.hpp index 6102a133a..ff08db06f 100644 --- a/apps/opencs/view/world/table.hpp +++ b/apps/opencs/view/world/table.hpp @@ -9,6 +9,10 @@ #include "../../model/filter/node.hpp" +namespace CSMDoc { + class Document; +} + class QUndoStack; class QAction; @@ -43,6 +47,10 @@ namespace CSVWorld bool mEditLock; int mRecordStatusDisplay; + /// \brief This variable is used exclusivly for checking if dropEvents came from the same document. Most likely you + /// should NOT use it for anything else. + const CSMDoc::Document& mDocument; + private: void contextMenuEvent (QContextMenuEvent *event); @@ -62,7 +70,9 @@ namespace CSVWorld public: - Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, bool createAndDelete, bool sorting); + Table (const CSMWorld::UniversalId& id, CSMWorld::Data& data, QUndoStack& undoStack, bool createAndDelete, + bool sorting, const CSMDoc::Document& document); + ///< \param createAndDelete Allow creation and deletion of records. /// \param sorting Allow changing order of rows in the view via column headers. diff --git a/apps/opencs/view/world/tablesubview.cpp b/apps/opencs/view/world/tablesubview.cpp index 981faaf59..d379db51a 100644 --- a/apps/opencs/view/world/tablesubview.cpp +++ b/apps/opencs/view/world/tablesubview.cpp @@ -22,7 +22,7 @@ CSVWorld::TableSubView::TableSubView (const CSMWorld::UniversalId& id, CSMDoc::D new TableBottomBox (creatorFactory, document.getData(), document.getUndoStack(), id, this), 0); layout->insertWidget (0, mTable = - new Table (id, document.getData(), document.getUndoStack(), mBottom->canCreateAndDelete(), sorting), 2); + new Table (id, document.getData(), document.getUndoStack(), mBottom->canCreateAndDelete(), sorting, document), 2); CSVFilter::FilterBox *filterBox = new CSVFilter::FilterBox (document.getData(), this);