diff --git a/apps/opencs/view/world/genericcreator.cpp b/apps/opencs/view/world/genericcreator.cpp index d23fc2803..bbdf2f67b 100644 --- a/apps/opencs/view/world/genericcreator.cpp +++ b/apps/opencs/view/world/genericcreator.cpp @@ -10,6 +10,8 @@ #include #include +#include + #include "../../model/world/commands.hpp" #include "../../model/world/data.hpp" #include "../../model/world/idtable.hpp" @@ -24,9 +26,6 @@ void CSVWorld::GenericCreator::update() mId->setToolTip (QString::fromUtf8 (mErrors.c_str())); mCreate->setEnabled (mErrors.empty() && !mLocked); - - if (mNamespace) - mNamespace->setText (QString::fromUtf8 (getNamespace().c_str())); } void CSVWorld::GenericCreator::setManualEditing (bool enabled) @@ -87,17 +86,40 @@ std::string CSVWorld::GenericCreator::getNamespace() const return ""; } +void CSVWorld::GenericCreator::updateNamespace() +{ + std::string namespace_ = getNamespace(); + + mValidator->setNamespace (namespace_); + + int index = mId->text().indexOf ("::"); + + if (index==-1) + { + // no namespace in old text + mId->setText (QString::fromUtf8 (namespace_.c_str()) + mId->text()); + } + else + { + std::string oldNamespace = + Misc::StringUtils::lowerCase (mId->text().left (index).toUtf8().constData()); + + if (oldNamespace=="project" || oldNamespace=="session") + mId->setText (QString::fromUtf8 (namespace_.c_str()) + mId->text().mid (index+2)); + } +} + CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id, bool relaxedIdRules) : mData (data), mUndoStack (undoStack), mListId (id), mLocked (false), mCloneMode (false), mClonedType (CSMWorld::UniversalId::Type_None), mScopes (CSMWorld::Scope_Content), mScope (0), - mScopeLabel (0), mNamespace (0) + mScopeLabel (0) { mLayout = new QHBoxLayout; mLayout->setContentsMargins (0, 0, 0, 0); mId = new QLineEdit; - mId->setValidator (new IdValidator (relaxedIdRules, this)); + mId->setValidator (mValidator = new IdValidator (relaxedIdRules, this)); mLayout->addWidget (mId, 1); mCreate = new QPushButton ("Create"); @@ -125,6 +147,7 @@ void CSVWorld::GenericCreator::reset() mCloneMode = false; mId->setText (""); update(); + updateNamespace(); } std::string CSVWorld::GenericCreator::getErrors() const @@ -197,21 +220,6 @@ void CSVWorld::GenericCreator::setScope (unsigned int scope) int count = (mScopes & CSMWorld::Scope_Content) + (mScopes & CSMWorld::Scope_Project) + (mScopes & CSMWorld::Scope_Session); - // namespace widget - if (count>1 || (count>0 && !(mScopes & CSMWorld::Scope_Content))) - { - if (!mNamespace) - { - mNamespace = new QLabel ("::", this); - insertAtBeginning (mNamespace, false); - } - } - else - { - delete mNamespace; - mNamespace = 0; - } - // scope selector widget if (count>1) { @@ -242,9 +250,12 @@ void CSVWorld::GenericCreator::setScope (unsigned int scope) delete mScopeLabel; mScopeLabel = 0; } + + updateNamespace(); } void CSVWorld::GenericCreator::scopeChanged (int index) { update(); + updateNamespace(); } \ No newline at end of file diff --git a/apps/opencs/view/world/genericcreator.hpp b/apps/opencs/view/world/genericcreator.hpp index fdd743489..ea099248e 100644 --- a/apps/opencs/view/world/genericcreator.hpp +++ b/apps/opencs/view/world/genericcreator.hpp @@ -19,6 +19,8 @@ namespace CSMWorld namespace CSVWorld { + class IdValidator; + class GenericCreator : public Creator { Q_OBJECT @@ -36,7 +38,7 @@ namespace CSVWorld unsigned int mScopes; QComboBox *mScope; QLabel *mScopeLabel; - QLabel *mNamespace; + IdValidator *mValidator; protected: bool mCloneMode; @@ -62,6 +64,10 @@ namespace CSVWorld std::string getNamespace() const; + private: + + void updateNamespace(); + public: GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack, diff --git a/apps/opencs/view/world/idvalidator.cpp b/apps/opencs/view/world/idvalidator.cpp index 7c210daae..5f4cd2194 100644 --- a/apps/opencs/view/world/idvalidator.cpp +++ b/apps/opencs/view/world/idvalidator.cpp @@ -1,6 +1,8 @@ #include "idvalidator.hpp" +#include + bool CSVWorld::IdValidator::isValid (const QChar& c, bool first) const { if (c.isLetter() || c=='_') @@ -26,11 +28,74 @@ QValidator::State CSVWorld::IdValidator::validate (QString& input, int& pos) con else { bool first = true; + bool scope = false; + bool prevScope = false; - for (QString::const_iterator iter (input.begin()); iter!=input.end(); ++iter, first = false) - if (!isValid (*iter, first)) - return QValidator::Invalid; + QString::const_iterator iter = input.begin(); + + if (!mNamespace.empty()) + { + std::string namespace_ = input.left (mNamespace.size()).toUtf8().constData(); + + if (Misc::StringUtils::lowerCase (namespace_)!=mNamespace) + return QValidator::Invalid; // incorrect namespace + + iter += namespace_.size(); + first = false; + prevScope = true; + } + else + { + int index = input.indexOf (":"); + + if (index!=-1) + { + QString namespace_ = input.left (index); + + if (namespace_=="project" || namespace_=="session") + return QValidator::Invalid; // reserved namespace + } + } + + for (; iter!=input.end(); ++iter, first = false) + { + if (*iter==':') + { + if (first) + return QValidator::Invalid; // scope operator at the beginning + + if (scope) + { + scope = false; + prevScope = true; + } + else + { + if (prevScope) + return QValidator::Invalid; // sequence of two scope operators + + scope = true; + } + } + else if (scope) + return QValidator::Invalid; // incomplete scope operator + else + { + prevScope = false; + + if (!isValid (*iter, first)) + return QValidator::Invalid; + } + } + + if (prevScope) + return QValidator::Intermediate; // ending with scope operator } return QValidator::Acceptable; +} + +void CSVWorld::IdValidator::setNamespace (const std::string& namespace_) +{ + mNamespace = Misc::StringUtils::lowerCase (namespace_); } \ No newline at end of file diff --git a/apps/opencs/view/world/idvalidator.hpp b/apps/opencs/view/world/idvalidator.hpp index 8ca162440..4b3e6cf6a 100644 --- a/apps/opencs/view/world/idvalidator.hpp +++ b/apps/opencs/view/world/idvalidator.hpp @@ -1,6 +1,8 @@ #ifndef CSV_WORLD_IDVALIDATOR_H #define CSV_WORLD_IDVALIDATOR_H +#include + #include namespace CSVWorld @@ -8,6 +10,7 @@ namespace CSVWorld class IdValidator : public QValidator { bool mRelaxed; + std::string mNamespace; private: @@ -20,6 +23,8 @@ namespace CSVWorld virtual State validate (QString& input, int& pos) const; + void setNamespace (const std::string& namespace_); + }; }