1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-10 03:39:55 +00:00
This commit is contained in:
graffy76 2013-05-25 08:06:56 -05:00
commit 089a1d48c1
629 changed files with 37240 additions and 26089 deletions

4
.gitignore vendored
View File

@ -17,3 +17,7 @@ data
CMakeLists.txt.user CMakeLists.txt.user
*.swp *.swp
*.swo *.swo
*.kate-swp
.cproject
.project
.settings/

40
.travis.yml Normal file
View File

@ -0,0 +1,40 @@
language: cpp
compiler:
- gcc
branches:
only:
- master
- next
before_install:
- pwd
- git submodule update --init --recursive
- echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse"
- echo "yes" | sudo apt-add-repository ppa:openmw/deps
- sudo apt-get update -qq
- sudo apt-get install -qq libboost-all-dev libgtest-dev google-mock libzzip-dev
- sudo apt-get install -qq libqt4-dev libxaw7-dev libxrandr-dev libfreeimage-dev libpng-dev
- sudo apt-get install -qq libopenal-dev libmpg123-dev libsndfile1-dev
- sudo apt-get install -qq libcg nvidia-cg-toolkit
- sudo apt-get install -qq libavcodec-dev libavformat-dev libavdevice-dev libavutil-dev libswscale-dev libpostproc-dev
- sudo apt-get install -qq libois-dev libbullet-dev libogre-static-dev libmygui-static-dev
- sudo mkdir /usr/src/gtest/build
- cd /usr/src/gtest/build
- sudo cmake .. -DBUILD_SHARED_LIBS=1
- sudo make -j4
- sudo ln -s /usr/src/gtest/build/libgtest.so /usr/lib/libgtest.so
- sudo ln -s /usr/src/gtest/build/libgtest_main.so /usr/lib/libgtest_main.so
before_script:
- cd -
- mkdir build
- cd build
- cmake .. -DOGRE_STATIC=1 -DMYGUI_STATIC=1 -DBUILD_WITH_CODE_COVERAGE=1 -DBUILD_UNITTESTS=1
script:
- make -j4
after_script:
- ./openmw_test_suite
notifications:
recipients:
- lgromanowski+travis.ci@gmail.com
email:
on_success: change
on_failure: always

View File

@ -15,7 +15,7 @@ include (OpenMWMacros)
# Version # Version
set (OPENMW_VERSION_MAJOR 0) set (OPENMW_VERSION_MAJOR 0)
set (OPENMW_VERSION_MINOR 22) set (OPENMW_VERSION_MINOR 23)
set (OPENMW_VERSION_RELEASE 0) set (OPENMW_VERSION_RELEASE 0)
set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}") set (OPENMW_VERSION "${OPENMW_VERSION_MAJOR}.${OPENMW_VERSION_MINOR}.${OPENMW_VERSION_RELEASE}")
@ -75,6 +75,7 @@ set(LIBDIR ${CMAKE_SOURCE_DIR}/libs)
set(OENGINE_OGRE set(OENGINE_OGRE
${LIBDIR}/openengine/ogre/renderer.cpp ${LIBDIR}/openengine/ogre/renderer.cpp
${LIBDIR}/openengine/ogre/fader.cpp ${LIBDIR}/openengine/ogre/fader.cpp
${LIBDIR}/openengine/ogre/particles.cpp
${LIBDIR}/openengine/ogre/selectionbuffer.cpp ${LIBDIR}/openengine/ogre/selectionbuffer.cpp
) )
set(OENGINE_GUI set(OENGINE_GUI
@ -180,15 +181,8 @@ if (UNIX AND NOT APPLE)
find_package (Threads) find_package (Threads)
endif() endif()
# find boost without components so we can use Boost_VERSION
find_package(Boost REQUIRED)
set(BOOST_COMPONENTS system filesystem program_options thread date_time) set(BOOST_COMPONENTS system filesystem program_options thread date_time wave)
if (Boost_VERSION LESS 104900)
set(SHINY_USE_WAVE_SYSTEM_INSTALL "TRUE")
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} wave)
endif()
IF(BOOST_STATIC) IF(BOOST_STATIC)
set(Boost_USE_STATIC_LIBS ON) set(Boost_USE_STATIC_LIBS ON)
@ -654,12 +648,12 @@ endif (APPLE)
if (NOT WIN32 AND NOT DPKG_PROGRAM AND NOT APPLE) if (NOT WIN32 AND NOT DPKG_PROGRAM AND NOT APPLE)
## Non Debian based Linux building ## Non Debian based Linux building
# paths # paths
set(BINDIR "${CMAKE_INSTALL_PREFIX}/usr/bin" CACHE PATH "Where to install binaries") set(BINDIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Where to install binaries")
set(DATAROOTDIR "${CMAKE_INSTALL_PREFIX}/share" CACHE PATH "Sets the root of data directories to a non-default location") set(DATAROOTDIR "${CMAKE_INSTALL_PREFIX}/share" CACHE PATH "Sets the root of data directories to a non-default location")
set(DATADIR "${DATAROOTDIR}/openmw" CACHE PATH "Sets the openmw data directories to a non-default location") set(DATADIR "${DATAROOTDIR}/games/openmw" CACHE PATH "Sets the openmw data directories to a non-default location")
set(DOCDIR "${DATAROOTDIR}/doc/openmw" CACHE PATH "Sets the doc directory to a non-default location.") set(DOCDIR "${DATAROOTDIR}/doc/openmw" CACHE PATH "Sets the doc directory to a non-default location.")
set(MANDIR "${DATAROOTDIR}/man" CACHE PATH "Where to install manpages") set(MANDIR "${DATAROOTDIR}/man" CACHE PATH "Where to install manpages")
set(SYSCONFDIR "${CMAKE_INSTALL_PREFIX}/etc/openmw" CACHE PATH "Set config dir") set(SYSCONFDIR "/etc/openmw" CACHE PATH "Set config dir")
set(ICONDIR "${DATAROOTDIR}/pixmaps" CACHE PATH "Set icon dir") set(ICONDIR "${DATAROOTDIR}/pixmaps" CACHE PATH "Set icon dir")
# Install binaries # Install binaries
@ -683,6 +677,10 @@ if (NOT WIN32 AND NOT DPKG_PROGRAM AND NOT APPLE)
# Install icon and .desktop # Install icon and .desktop
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "${ICONDIR}") INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "${ICONDIR}")
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications") INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications")
IF(BUILD_OPENCS)
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/opencs/opencs.png" DESTINATION "${ICONDIR}")
INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.desktop" DESTINATION "${DATAROOTDIR}/applications")
ENDIF(BUILD_OPENCS)
# Install global configuration files # Install global configuration files
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" ) INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" )

View File

@ -23,8 +23,7 @@ struct ESMData
std::string author; std::string author;
std::string description; std::string description;
int version; int version;
int type; std::vector<ESM::Header::MasterData> masters;
ESM::ESMReader::MasterList masters;
std::deque<EsmTool::RecordBase *> mRecords; std::deque<EsmTool::RecordBase *> mRecords;
std::map<ESM::Cell *, std::deque<ESM::CellRef> > mCellRefs; std::map<ESM::Cell *, std::deque<ESM::CellRef> > mCellRefs;
@ -52,6 +51,7 @@ struct Arguments
unsigned int raw_given; unsigned int raw_given;
unsigned int quiet_given; unsigned int quiet_given;
unsigned int loadcells_given; unsigned int loadcells_given;
bool plain_given;
std::string mode; std::string mode;
std::string encoding; std::string encoding;
@ -78,6 +78,9 @@ bool parseOptions (int argc, char** argv, Arguments &info)
("type,t", bpo::value< std::vector<std::string> >(), ("type,t", bpo::value< std::vector<std::string> >(),
"Show only records of this type (four character record code). May " "Show only records of this type (four character record code). May "
"be specified multiple times. Only affects dump mode.") "be specified multiple times. Only affects dump mode.")
("plain,p", "Print contents of dialogs, books and scripts. "
"(skipped by default)"
"Only affects dump mode.")
("quiet,q", "Supress all record information. Useful for speed tests.") ("quiet,q", "Supress all record information. Useful for speed tests.")
("loadcells,C", "Browse through contents of all cells.") ("loadcells,C", "Browse through contents of all cells.")
@ -162,6 +165,7 @@ bool parseOptions (int argc, char** argv, Arguments &info)
info.raw_given = variables.count ("raw"); info.raw_given = variables.count ("raw");
info.quiet_given = variables.count ("quiet"); info.quiet_given = variables.count ("quiet");
info.loadcells_given = variables.count ("loadcells"); info.loadcells_given = variables.count ("loadcells");
info.plain_given = (variables.count("plain") > 0);
// Font encoding settings // Font encoding settings
info.encoding = variables["encoding"].as<std::string>(); info.encoding = variables["encoding"].as<std::string>();
@ -228,7 +232,10 @@ void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info)
std::cout << " Refnum: " << ref.mRefnum << std::endl; std::cout << " Refnum: " << ref.mRefnum << std::endl;
std::cout << " ID: '" << ref.mRefID << "'\n"; std::cout << " ID: '" << ref.mRefID << "'\n";
std::cout << " Owner: '" << ref.mOwner << "'\n"; std::cout << " Owner: '" << ref.mOwner << "'\n";
std::cout << " INTV: " << ref.mIntv << " NAM9: " << ref.mIntv << std::endl; std::cout << " Enchantment charge: '" << ref.mEnchantmentCharge << "'\n";
std::cout << " Uses/health: '" << ref.mCharge << "'\n";
std::cout << " Gold value: '" << ref.mGoldValue << "'\n";
std::cout << " Blocked: '" << static_cast<int>(ref.mReferenceBlocked) << "'" << std::endl;
} }
} }
@ -284,16 +291,13 @@ int load(Arguments& info)
info.data.author = esm.getAuthor(); info.data.author = esm.getAuthor();
info.data.description = esm.getDesc(); info.data.description = esm.getDesc();
info.data.masters = esm.getMasters(); info.data.masters = esm.getMasters();
info.data.version = esm.getVer();
info.data.type = esm.getType();
if (!quiet) if (!quiet)
{ {
std::cout << "Author: " << esm.getAuthor() << std::endl std::cout << "Author: " << esm.getAuthor() << std::endl
<< "Description: " << esm.getDesc() << std::endl << "Description: " << esm.getDesc() << std::endl
<< "File format version: " << esm.getFVer() << std::endl << "File format version: " << esm.getFVer() << std::endl;
<< "Special flag: " << esm.getSpecial() << std::endl; std::vector<ESM::Header::MasterData> m = esm.getMasters();
ESM::ESMReader::MasterList m = esm.getMasters();
if (!m.empty()) if (!m.empty())
{ {
std::cout << "Masters:" << std::endl; std::cout << "Masters:" << std::endl;
@ -344,6 +348,7 @@ int load(Arguments& info)
} }
record->setId(id); record->setId(id);
record->setFlags((int) flags); record->setFlags((int) flags);
record->setPrintPlain(info.plain_given);
record->load(esm); record->load(esm);
if (!quiet && interested) record->print(); if (!quiet && interested) record->print();
@ -430,9 +435,9 @@ int clone(Arguments& info)
esm.setAuthor(info.data.author); esm.setAuthor(info.data.author);
esm.setDescription(info.data.description); esm.setDescription(info.data.description);
esm.setVersion(info.data.version); esm.setVersion(info.data.version);
esm.setType(info.data.type); esm.setRecordCount (recordCount);
for (ESM::ESMReader::MasterList::iterator it = info.data.masters.begin(); it != info.data.masters.end(); ++it) for (std::vector<ESM::Header::MasterData>::iterator it = info.data.masters.begin(); it != info.data.masters.end(); ++it)
esm.addMaster(it->name, it->size); esm.addMaster(it->name, it->size);
std::fstream save(info.outname.c_str(), std::fstream::out | std::fstream::binary); std::fstream save(info.outname.c_str(), std::fstream::out | std::fstream::binary);

View File

@ -627,10 +627,10 @@ std::string bodyPartFlags(int flags)
std::string properties = ""; std::string properties = "";
if (flags == 0) properties += "[None] "; if (flags == 0) properties += "[None] ";
if (flags & ESM::BodyPart::BPF_Female) properties += "Female "; if (flags & ESM::BodyPart::BPF_Female) properties += "Female ";
if (flags & ESM::BodyPart::BPF_Playable) properties += "Playable "; if (flags & ESM::BodyPart::BPF_NotPlayable) properties += "NotPlayable ";
int unused = (0xFFFFFFFF ^ int unused = (0xFFFFFFFF ^
(ESM::BodyPart::BPF_Female| (ESM::BodyPart::BPF_Female|
ESM::BodyPart::BPF_Playable)); ESM::BodyPart::BPF_NotPlayable));
if (flags & unused) properties += "Invalid "; if (flags & unused) properties += "Invalid ";
properties += str(boost::format("(0x%08X)") % flags); properties += str(boost::format("(0x%08X)") % flags);
return properties; return properties;

View File

@ -275,7 +275,7 @@ RecordBase::create(ESM::NAME type)
} }
case ESM::REC_LOCK: case ESM::REC_LOCK:
{ {
record = new EsmTool::Record<ESM::Tool>; record = new EsmTool::Record<ESM::Lockpick>;
break; break;
} }
case ESM::REC_LTEX: case ESM::REC_LTEX:
@ -439,7 +439,7 @@ void Record<ESM::Apparatus>::print()
template<> template<>
void Record<ESM::BodyPart>::print() void Record<ESM::BodyPart>::print()
{ {
std::cout << " Name: " << mData.mName << std::endl; std::cout << " Race: " << mData.mRace << std::endl;
std::cout << " Model: " << mData.mModel << std::endl; std::cout << " Model: " << mData.mModel << std::endl;
std::cout << " Type: " << meshTypeLabel(mData.mData.mType) std::cout << " Type: " << meshTypeLabel(mData.mData.mType)
<< " (" << (int)mData.mData.mType << ")" << std::endl; << " (" << (int)mData.mData.mType << ")" << std::endl;
@ -464,12 +464,17 @@ void Record<ESM::Book>::print()
std::cout << " IsScroll: " << mData.mData.mIsScroll << std::endl; std::cout << " IsScroll: " << mData.mData.mIsScroll << std::endl;
std::cout << " SkillID: " << mData.mData.mSkillID << std::endl; std::cout << " SkillID: " << mData.mData.mSkillID << std::endl;
std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl; std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl;
std::cout << " Text: [skipped]" << std::endl; if (mPrintPlain)
// Skip until multi-line fields is controllable by a command line option. {
// Mildly problematic because there are no parameter to print() currently. std::cout << " Text:" << std::endl;
// std::cout << "-------------------------------------------" << std::endl; std::cout << "START--------------------------------------" << std::endl;
// std::cout << mData.mText << std::endl; std::cout << mData.mText << std::endl;
// std::cout << "-------------------------------------------" << std::endl; std::cout << "END----------------------------------------" << std::endl;
}
else
{
std::cout << " Text: [skipped]" << std::endl;
}
} }
template<> template<>
@ -679,14 +684,14 @@ void Record<ESM::Faction>::print()
std::cout << " Hidden: " << mData.mData.mIsHidden << std::endl; std::cout << " Hidden: " << mData.mData.mIsHidden << std::endl;
if (mData.mData.mUnknown != -1) if (mData.mData.mUnknown != -1)
std::cout << " Unknown: " << mData.mData.mUnknown << std::endl; std::cout << " Unknown: " << mData.mData.mUnknown << std::endl;
std::cout << " Attribute1: " << attributeLabel(mData.mData.mAttribute1) std::cout << " Attribute1: " << attributeLabel(mData.mData.mAttribute[0])
<< " (" << mData.mData.mAttribute1 << ")" << std::endl; << " (" << mData.mData.mAttribute[0] << ")" << std::endl;
std::cout << " Attribute2: " << attributeLabel(mData.mData.mAttribute2) std::cout << " Attribute2: " << attributeLabel(mData.mData.mAttribute[1])
<< " (" << mData.mData.mAttribute2 << ")" << std::endl; << " (" << mData.mData.mAttribute[1] << ")" << std::endl;
for (int i = 0; i != 6; i++) for (int i = 0; i != 6; i++)
if (mData.mData.mSkillID[i] != -1) if (mData.mData.mSkills[i] != -1)
std::cout << " Skill: " << skillLabel(mData.mData.mSkillID[i]) std::cout << " Skill: " << skillLabel(mData.mData.mSkills[i])
<< " (" << mData.mData.mSkillID[i] << ")" << std::endl; << " (" << mData.mData.mSkills[i] << ")" << std::endl;
for (int i = 0; i != 10; i++) for (int i = 0; i != 10; i++)
if (mData.mRanks[i] != "") if (mData.mRanks[i] != "")
{ {
@ -753,15 +758,6 @@ void Record<ESM::DialInfo>::print()
if (mData.mSound != "") if (mData.mSound != "")
std::cout << " Sound File: " << mData.mSound << std::endl; std::cout << " Sound File: " << mData.mSound << std::endl;
if (mData.mResultScript != "")
{
std::cout << " Result Script: [skipped]" << std::endl;
// Skip until multi-line fields is controllable by a command line option.
// Mildly problematic because there are no parameter to print() currently.
// std::cout << "-------------------------------------------" << std::endl;
// std::cout << mData.mResultScript << std::endl;
// std::cout << "-------------------------------------------" << std::endl;
}
std::cout << " Quest Status: " << questStatusLabel(mData.mQuestStatus) std::cout << " Quest Status: " << questStatusLabel(mData.mQuestStatus)
<< " (" << mData.mQuestStatus << ")" << std::endl; << " (" << mData.mQuestStatus << ")" << std::endl;
@ -771,6 +767,21 @@ void Record<ESM::DialInfo>::print()
std::vector<ESM::DialInfo::SelectStruct>::iterator sit; std::vector<ESM::DialInfo::SelectStruct>::iterator sit;
for (sit = mData.mSelects.begin(); sit != mData.mSelects.end(); sit++) for (sit = mData.mSelects.begin(); sit != mData.mSelects.end(); sit++)
std::cout << " Select Rule: " << ruleString(*sit) << std::endl; std::cout << " Select Rule: " << ruleString(*sit) << std::endl;
if (mData.mResultScript != "")
{
if (mPrintPlain)
{
std::cout << " Result Script:" << std::endl;
std::cout << "START--------------------------------------" << std::endl;
std::cout << mData.mResultScript << std::endl;
std::cout << "END----------------------------------------" << std::endl;
}
else
{
std::cout << " Result Script: [skipped]" << std::endl;
}
}
} }
template<> template<>
@ -864,14 +875,13 @@ void Record<ESM::Light>::print()
} }
template<> template<>
void Record<ESM::Tool>::print() void Record<ESM::Lockpick>::print()
{ {
std::cout << " Name: " << mData.mName << std::endl; std::cout << " Name: " << mData.mName << std::endl;
std::cout << " Model: " << mData.mModel << std::endl; std::cout << " Model: " << mData.mModel << std::endl;
std::cout << " Icon: " << mData.mIcon << std::endl; std::cout << " Icon: " << mData.mIcon << std::endl;
if (mData.mScript != "") if (mData.mScript != "")
std::cout << " Script: " << mData.mScript << std::endl; std::cout << " Script: " << mData.mScript << std::endl;
std::cout << " Type: " << mData.mType << std::endl;
std::cout << " Weight: " << mData.mData.mWeight << std::endl; std::cout << " Weight: " << mData.mData.mWeight << std::endl;
std::cout << " Value: " << mData.mData.mValue << std::endl; std::cout << " Value: " << mData.mData.mValue << std::endl;
std::cout << " Quality: " << mData.mData.mQuality << std::endl; std::cout << " Quality: " << mData.mData.mQuality << std::endl;
@ -886,8 +896,6 @@ void Record<ESM::Probe>::print()
std::cout << " Icon: " << mData.mIcon << std::endl; std::cout << " Icon: " << mData.mIcon << std::endl;
if (mData.mScript != "") if (mData.mScript != "")
std::cout << " Script: " << mData.mScript << std::endl; std::cout << " Script: " << mData.mScript << std::endl;
// BUG? No Type Label?
std::cout << " Type: " << mData.mType << std::endl;
std::cout << " Weight: " << mData.mData.mWeight << std::endl; std::cout << " Weight: " << mData.mData.mWeight << std::endl;
std::cout << " Value: " << mData.mData.mValue << std::endl; std::cout << " Value: " << mData.mData.mValue << std::endl;
std::cout << " Quality: " << mData.mData.mQuality << std::endl; std::cout << " Quality: " << mData.mData.mQuality << std::endl;
@ -902,7 +910,6 @@ void Record<ESM::Repair>::print()
std::cout << " Icon: " << mData.mIcon << std::endl; std::cout << " Icon: " << mData.mIcon << std::endl;
if (mData.mScript != "") if (mData.mScript != "")
std::cout << " Script: " << mData.mScript << std::endl; std::cout << " Script: " << mData.mScript << std::endl;
std::cout << " Type: " << mData.mType << std::endl;
std::cout << " Weight: " << mData.mData.mWeight << std::endl; std::cout << " Weight: " << mData.mData.mWeight << std::endl;
std::cout << " Value: " << mData.mData.mValue << std::endl; std::cout << " Value: " << mData.mData.mValue << std::endl;
std::cout << " Quality: " << mData.mData.mQuality << std::endl; std::cout << " Quality: " << mData.mData.mQuality << std::endl;
@ -1103,53 +1110,29 @@ void Record<ESM::Pathgrid>::print()
template<> template<>
void Record<ESM::Race>::print() void Record<ESM::Race>::print()
{ {
static const char *sAttributeNames[8] =
{
"Strength", "Intelligence", "Willpower", "Agility",
"Speed", "Endurance", "Personality", "Luck"
};
std::cout << " Name: " << mData.mName << std::endl; std::cout << " Name: " << mData.mName << std::endl;
std::cout << " Description: " << mData.mDescription << std::endl; std::cout << " Description: " << mData.mDescription << std::endl;
std::cout << " Flags: " << raceFlags(mData.mData.mFlags) << std::endl; std::cout << " Flags: " << raceFlags(mData.mData.mFlags) << std::endl;
std::cout << " Male:" << std::endl; for (int i=0; i<2; ++i)
std::cout << " Strength: " {
<< mData.mData.mStrength.mMale << std::endl; bool male = i==0;
std::cout << " Intelligence: "
<< mData.mData.mIntelligence.mMale << std::endl;
std::cout << " Willpower: "
<< mData.mData.mWillpower.mMale << std::endl;
std::cout << " Agility: "
<< mData.mData.mAgility.mMale << std::endl;
std::cout << " Speed: "
<< mData.mData.mSpeed.mMale << std::endl;
std::cout << " Endurance: "
<< mData.mData.mEndurance.mMale << std::endl;
std::cout << " Personality: "
<< mData.mData.mPersonality.mMale << std::endl;
std::cout << " Luck: "
<< mData.mData.mLuck.mMale << std::endl;
std::cout << " Height: "
<< mData.mData.mHeight.mMale << std::endl;
std::cout << " Weight: "
<< mData.mData.mWeight.mMale << std::endl;
std::cout << " Female:" << std::endl; std::cout << (male ? " Male:" : " Female:") << std::endl;
std::cout << " Strength: "
<< mData.mData.mStrength.mFemale << std::endl; for (int i=0; i<8; ++i)
std::cout << " Intelligence: " std::cout << " " << sAttributeNames[i] << ": "
<< mData.mData.mIntelligence.mFemale << std::endl; << mData.mData.mAttributeValues[i].getValue (male) << std::endl;
std::cout << " Willpower: "
<< mData.mData.mWillpower.mFemale << std::endl; std::cout << " Height: " << mData.mData.mHeight.getValue (male) << std::endl;
std::cout << " Agility: " std::cout << " Weight: " << mData.mData.mWeight.getValue (male) << std::endl;
<< mData.mData.mAgility.mFemale << std::endl; }
std::cout << " Speed: "
<< mData.mData.mSpeed.mFemale << std::endl;
std::cout << " Endurance: "
<< mData.mData.mEndurance.mFemale << std::endl;
std::cout << " Personality: "
<< mData.mData.mPersonality.mFemale << std::endl;
std::cout << " Luck: "
<< mData.mData.mLuck.mFemale << std::endl;
std::cout << " Height: "
<< mData.mData.mHeight.mFemale << std::endl;
std::cout << " Weight: "
<< mData.mData.mWeight.mFemale << std::endl;
for (int i = 0; i != 7; i++) for (int i = 0; i != 7; i++)
// Not all races have 7 skills. // Not all races have 7 skills.
@ -1199,21 +1182,28 @@ void Record<ESM::Script>::print()
std::cout << " Script Data Size: " << mData.mData.mScriptDataSize << std::endl; std::cout << " Script Data Size: " << mData.mData.mScriptDataSize << std::endl;
std::cout << " Table Size: " << mData.mData.mStringTableSize << std::endl; std::cout << " Table Size: " << mData.mData.mStringTableSize << std::endl;
std::cout << " Script: [skipped]" << std::endl;
// Skip until multi-line fields is controllable by a command line option.
// Mildly problematic because there are no parameter to print() currently.
// std::cout << "-------------------------------------------" << std::endl;
// std::cout << s->scriptText << std::endl;
// std::cout << "-------------------------------------------" << std::endl;
std::vector<std::string>::iterator vit; std::vector<std::string>::iterator vit;
for (vit = mData.mVarNames.begin(); vit != mData.mVarNames.end(); vit++) for (vit = mData.mVarNames.begin(); vit != mData.mVarNames.end(); vit++)
std::cout << " Variable: " << *vit << std::endl; std::cout << " Variable: " << *vit << std::endl;
std::cout << " ByteCode: "; std::cout << " ByteCode: ";
std::vector<char>::iterator cit; std::vector<unsigned char>::iterator cit;
for (cit = mData.mScriptData.begin(); cit != mData.mScriptData.end(); cit++) for (cit = mData.mScriptData.begin(); cit != mData.mScriptData.end(); cit++)
std::cout << boost::format("%02X") % (int)(*cit); std::cout << boost::format("%02X") % (int)(*cit);
std::cout << std::endl; std::cout << std::endl;
if (mPrintPlain)
{
std::cout << " Script:" << std::endl;
std::cout << "START--------------------------------------" << std::endl;
std::cout << mData.mScriptText << std::endl;
std::cout << "END----------------------------------------" << std::endl;
}
else
{
std::cout << " Script: [skipped]" << std::endl;
}
} }
template<> template<>

View File

@ -21,9 +21,10 @@ namespace EsmTool
std::string mId; std::string mId;
int mFlags; int mFlags;
ESM::NAME mType; ESM::NAME mType;
bool mPrintPlain;
public: public:
RecordBase () {} RecordBase () { mPrintPlain = false; }
virtual ~RecordBase() {} virtual ~RecordBase() {}
const std::string &getId() const { const std::string &getId() const {
@ -46,6 +47,14 @@ namespace EsmTool
return mType; return mType;
} }
bool getPrintPlain() const {
return mPrintPlain;
}
void setPrintPlain(bool plain) {
mPrintPlain = plain;
}
virtual void load(ESM::ESMReader &esm) = 0; virtual void load(ESM::ESMReader &esm) = 0;
virtual void save(ESM::ESMWriter &esm) = 0; virtual void save(ESM::ESMWriter &esm) = 0;
virtual void print() = 0; virtual void print() = 0;
@ -104,7 +113,7 @@ namespace EsmTool
template<> void Record<ESM::CreatureLevList>::print(); template<> void Record<ESM::CreatureLevList>::print();
template<> void Record<ESM::ItemLevList>::print(); template<> void Record<ESM::ItemLevList>::print();
template<> void Record<ESM::Light>::print(); template<> void Record<ESM::Light>::print();
template<> void Record<ESM::Tool>::print(); template<> void Record<ESM::Lockpick>::print();
template<> void Record<ESM::Probe>::print(); template<> void Record<ESM::Probe>::print();
template<> void Record<ESM::Repair>::print(); template<> void Record<ESM::Repair>::print();
template<> void Record<ESM::LandTexture>::print(); template<> void Record<ESM::LandTexture>::print();

View File

@ -102,3 +102,9 @@ if (BUILD_WITH_CODE_COVERAGE)
add_definitions (--coverage) add_definitions (--coverage)
target_link_libraries(omwlauncher gcov) target_link_libraries(omwlauncher gcov)
endif() endif()
# Workaround for binutil => 2.23 problem when linking, should be fixed eventually upstream
if (UNIX AND NOT APPLE)
target_link_libraries(omwlauncher dl Xt)
endif()

View File

@ -2,9 +2,9 @@
#define MAINDIALOG_H #define MAINDIALOG_H
#include <QMainWindow> #include <QMainWindow>
#ifndef Q_MOC_RUN
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#endif
#include "settings/gamesettings.hpp" #include "settings/gamesettings.hpp"
#include "settings/graphicssettings.hpp" #include "settings/graphicssettings.hpp"
#include "settings/launchersettings.hpp" #include "settings/launchersettings.hpp"

View File

@ -96,15 +96,15 @@ bool GameSettings::readFile(QTextStream &stream)
QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$"); QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$");
while (!stream.atEnd()) { while (!stream.atEnd()) {
QString line = stream.readLine().simplified(); QString line = stream.readLine();
if (line.isEmpty() || line.startsWith("#")) if (line.isEmpty() || line.startsWith("#"))
continue; continue;
if (keyRe.indexIn(line) != -1) { if (keyRe.indexIn(line) != -1) {
QString key = keyRe.cap(1).simplified(); QString key = keyRe.cap(1);
QString value = keyRe.cap(2).simplified(); QString value = keyRe.cap(2);
// Don't remove existing data entries // Don't remove existing data entries
if (key != QLatin1String("data")) if (key != QLatin1String("data"))

View File

@ -53,7 +53,7 @@ public:
QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$"); QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$");
while (!stream.atEnd()) { while (!stream.atEnd()) {
QString line = stream.readLine().simplified(); QString line = stream.readLine();
if (line.isEmpty() || line.startsWith("#")) if (line.isEmpty() || line.startsWith("#"))
continue; continue;
@ -66,8 +66,8 @@ public:
if (keyRe.indexIn(line) != -1) { if (keyRe.indexIn(line) != -1) {
QString key = keyRe.cap(1).simplified(); QString key = keyRe.cap(1);
QString value = keyRe.cap(2).simplified(); QString value = keyRe.cap(2);
if (!sectionPrefix.isEmpty()) if (!sectionPrefix.isEmpty())
key.prepend(sectionPrefix); key.prepend(sectionPrefix);

View File

@ -22,3 +22,8 @@ if (BUILD_WITH_CODE_COVERAGE)
add_definitions (--coverage) add_definitions (--coverage)
target_link_libraries(mwiniimport gcov) target_link_libraries(mwiniimport gcov)
endif() endif()
if(DPKG_PROGRAM)
INSTALL(TARGETS mwiniimport RUNTIME DESTINATION games COMPONENT mwiniimport)
endif()

View File

@ -1,4 +1,3 @@
set (OPENCS_SRC main.cpp) set (OPENCS_SRC main.cpp)
opencs_units (. editor) opencs_units (. editor)
@ -24,7 +23,8 @@ opencs_units (model/world
opencs_units_noqt (model/world opencs_units_noqt (model/world
universalid data record idcollection commands columnbase universalid data record idcollection commands columnbase scriptcontext cell refidcollection
refidadapter refiddata refidadapterimp
) )
opencs_hdrs_noqt (model/world opencs_hdrs_noqt (model/world
@ -37,7 +37,8 @@ opencs_units (model/tools
) )
opencs_units_noqt (model/tools opencs_units_noqt (model/tools
stage verifier mandatoryid stage verifier mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
birthsigncheck spellcheck
) )
@ -56,11 +57,11 @@ opencs_hdrs_noqt (view/doc
opencs_units (view/world opencs_units (view/world
table tablesubview table tablesubview scriptsubview
) )
opencs_units_noqt (view/world opencs_units_noqt (view/world
dialoguesubview util subviews enumdelegate vartypedelegate dialoguesubview util subviews enumdelegate vartypedelegate scripthighlighter
) )
@ -72,27 +73,34 @@ opencs_units_noqt (view/tools
subviews subviews
) )
opencs_units (settings opencs_units (view/settings
customblock
proxyblock
settingcontainer
groupbox
settingsitem
abstractblock abstractblock
settingwidget proxyblock
itemblock
groupblock
toggleblock
usersettingsdialog
abstractpage
abstractwidget abstractwidget
blankpage usersettingsdialog
editorpage editorpage
) )
opencs_units_noqt (settings opencs_units_noqt (view/settings
abstractpage
blankpage
groupblock
customblock
groupbox
itemblock
settingwidget
toggleblock
support support
)
opencs_units (model/settings
usersettings usersettings
settingcontainer
)
opencs_units_noqt (model/settings
support
settingsitem
) )
set (OPENCS_US set (OPENCS_US

View File

@ -113,5 +113,7 @@ int CS::Editor::run()
{ {
mStartup.show(); mStartup.show();
QApplication::setQuitOnLastWindowClosed (true);
return QApplication::exec(); return QApplication::exec();
} }

View File

@ -2,9 +2,9 @@
#define CS_EDITOR_H #define CS_EDITOR_H
#include <QObject> #include <QObject>
#ifndef Q_MOC_RUN
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#endif
#include "model/doc/documentmanager.hpp" #include "model/doc/documentmanager.hpp"
#include "view/doc/viewmanager.hpp" #include "view/doc/viewmanager.hpp"
@ -23,7 +23,6 @@ namespace CS
FileDialog mFileDialog; FileDialog mFileDialog;
Files::ConfigurationManager mCfgMgr; Files::ConfigurationManager mCfgMgr;
void setupDataFiles(); void setupDataFiles();
// not implemented // not implemented

View File

@ -151,6 +151,10 @@ void CSMDoc::Document::addOptionalGlobals()
ESM::Global global; ESM::Global global;
global.mId = sGlobals[i]; global.mId = sGlobals[i];
global.mValue.setType (ESM::VT_Long); global.mValue.setType (ESM::VT_Long);
if (i==0)
global.mValue.setInteger (1); // dayspassed starts counting at 1
addOptionalGlobal (global); addOptionalGlobal (global);
} }
} }
@ -190,15 +194,25 @@ void CSMDoc::Document::createBase()
record.mId = sGlobals[i]; record.mId = sGlobals[i];
record.mValue.setType (i==2 ? ESM::VT_Float : ESM::VT_Int); record.mValue.setType (i==2 ? ESM::VT_Float : ESM::VT_Long);
if (i==0) if (i==0 || i==1)
record.mValue.setInteger (1); record.mValue.setInteger (1);
getData().getGlobals().add (record); getData().getGlobals().add (record);
} }
/// \todo add GMSTs /// \todo add GMSTs
for (int i=0; i<27; ++i)
{
ESM::Skill record;
record.mIndex = i;
record.mId = ESM::Skill::indexToId (record.mIndex);
record.blank();
getData().getSkills().add (record);
}
} }
CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files, bool new_) CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files, bool new_)
@ -215,7 +229,7 @@ CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files, b
if (new_ && files.size()==1) if (new_ && files.size()==1)
createBase(); createBase();
else if (files.size()>1) else
{ {
std::vector<boost::filesystem::path>::const_iterator end = files.end(); std::vector<boost::filesystem::path>::const_iterator end = files.end();
@ -238,6 +252,9 @@ CSMDoc::Document::Document (const std::vector<boost::filesystem::path>& files, b
connect (&mSaveTimer, SIGNAL(timeout()), this, SLOT (saving())); connect (&mSaveTimer, SIGNAL(timeout()), this, SLOT (saving()));
} }
CSMDoc::Document::~Document()
{}
QUndoStack& CSMDoc::Document::getUndoStack() QUndoStack& CSMDoc::Document::getUndoStack()
{ {
return mUndoStack; return mUndoStack;
@ -291,11 +308,13 @@ void CSMDoc::Document::abortOperation (int type)
} }
} }
void CSMDoc::Document::modificationStateChanged (bool clean) void CSMDoc::Document::modificationStateChanged (bool clean)
{ {
emit stateChanged (getState(), this); emit stateChanged (getState(), this);
} }
void CSMDoc::Document::operationDone (int type) void CSMDoc::Document::operationDone (int type)
{ {
emit stateChanged (getState(), this); emit stateChanged (getState(), this);
@ -309,9 +328,12 @@ void CSMDoc::Document::saving()
if (mSaveCount>15) if (mSaveCount>15)
{ {
//clear the stack before resetting the save state
//to avoid emitting incorrect states
mUndoStack.setClean();
mSaveCount = 0; mSaveCount = 0;
mSaveTimer.stop(); mSaveTimer.stop();
mUndoStack.setClean();
emit stateChanged (getState(), this); emit stateChanged (getState(), this);
} }
} }

View File

@ -63,6 +63,7 @@ namespace CSMDoc
public: public:
Document (const std::vector<boost::filesystem::path>& files, bool new_); Document (const std::vector<boost::filesystem::path>& files, bool new_);
~Document();
QUndoStack& getUndoStack(); QUndoStack& getUndoStack();

View File

@ -2,17 +2,17 @@
#include <QStringList> #include <QStringList>
CsSettings::SettingContainer::SettingContainer(QObject *parent) : CSMSettings::SettingContainer::SettingContainer(QObject *parent) :
QObject(parent), mValue (0), mValues (0) QObject(parent), mValue (0), mValues (0)
{ {
} }
CsSettings::SettingContainer::SettingContainer(const QString &value, QObject *parent) : CSMSettings::SettingContainer::SettingContainer(const QString &value, QObject *parent) :
QObject(parent), mValue (new QString (value)), mValues (0) QObject(parent), mValue (new QString (value)), mValues (0)
{ {
} }
void CsSettings::SettingContainer::insert (const QString &value) void CSMSettings::SettingContainer::insert (const QString &value)
{ {
if (mValue) if (mValue)
{ {
@ -31,7 +31,7 @@ void CsSettings::SettingContainer::insert (const QString &value)
} }
void CsSettings::SettingContainer::update (const QString &value, int index) void CSMSettings::SettingContainer::update (const QString &value, int index)
{ {
if (isEmpty()) if (isEmpty())
mValue = new QString(value); mValue = new QString(value);
@ -43,7 +43,7 @@ void CsSettings::SettingContainer::update (const QString &value, int index)
mValues->replace(index, value); mValues->replace(index, value);
} }
QString CsSettings::SettingContainer::getValue (int index) const QString CSMSettings::SettingContainer::getValue (int index) const
{ {
QString retVal(""); QString retVal("");
@ -66,7 +66,7 @@ QString CsSettings::SettingContainer::getValue (int index) const
return retVal; return retVal;
} }
int CsSettings::SettingContainer::count () const int CSMSettings::SettingContainer::count () const
{ {
int retVal = 0; int retVal = 0;

View File

@ -5,7 +5,7 @@
class QStringList; class QStringList;
namespace CsSettings namespace CSMSettings
{ {
class SettingContainer : public QObject class SettingContainer : public QObject
{ {

View File

@ -1,6 +1,6 @@
#include "settingsitem.hpp" #include "settingsitem.hpp"
bool CsSettings::SettingsItem::updateItem (const QStringList *values) bool CSMSettings::SettingsItem::updateItem (const QStringList *values)
{ {
QStringList::ConstIterator it = values->begin(); QStringList::ConstIterator it = values->begin();
@ -30,7 +30,7 @@ bool CsSettings::SettingsItem::updateItem (const QStringList *values)
return isValid; return isValid;
} }
bool CsSettings::SettingsItem::updateItem (const QString &value) bool CSMSettings::SettingsItem::updateItem (const QString &value)
{ {
//takes a value or a SettingsContainer and updates itself accordingly //takes a value or a SettingsContainer and updates itself accordingly
//after validating the data against it's own definition //after validating the data against it's own definition
@ -52,7 +52,7 @@ bool CsSettings::SettingsItem::updateItem (const QString &value)
return success; return success;
} }
bool CsSettings::SettingsItem::updateItem(int valueListIndex) bool CSMSettings::SettingsItem::updateItem(int valueListIndex)
{ {
bool success = false; bool success = false;
@ -64,7 +64,7 @@ bool CsSettings::SettingsItem::updateItem(int valueListIndex)
return success; return success;
} }
bool CsSettings::SettingsItem::validate (const QString &value) bool CSMSettings::SettingsItem::validate (const QString &value)
{ {
bool isValid = true; bool isValid = true;
@ -90,13 +90,13 @@ bool CsSettings::SettingsItem::validate (const QString &value)
return isValid; return isValid;
} }
void CsSettings::SettingsItem::setDefaultValue (const QString &value) void CSMSettings::SettingsItem::setDefaultValue (const QString &value)
{ {
mDefaultValue = value; mDefaultValue = value;
update (value); update (value);
} }
QString CsSettings::SettingsItem::getDefaultValue() const QString CSMSettings::SettingsItem::getDefaultValue() const
{ {
return mDefaultValue; return mDefaultValue;
} }

View File

@ -5,7 +5,7 @@
#include "support.hpp" #include "support.hpp"
#include "settingcontainer.hpp" #include "settingcontainer.hpp"
namespace CsSettings namespace CSMSettings
{ {
class SettingsItem : public SettingContainer class SettingsItem : public SettingContainer
{ {

View File

@ -0,0 +1,39 @@
#ifndef MODEL_SUPPORT_HPP
#define MODEL_SUPPORT_HPP
#include <QObject>
#include <QStringList>
class QLayout;
class QWidget;
class QListWidgetItem;
namespace CSMSettings
{
class SettingContainer;
typedef QList<SettingContainer *> SettingList;
typedef QMap<QString, SettingContainer *> SettingMap;
typedef QMap<QString, SettingMap *> SectionMap;
struct QStringPair
{
QStringPair(): left (""), right ("")
{}
QStringPair (const QString &leftValue, const QString &rightValue)
: left (leftValue), right(rightValue)
{}
QStringPair (const QStringPair &pair)
: left (pair.left), right (pair.right)
{}
QString left;
QString right;
bool isEmpty() const
{ return (left.isEmpty() && right.isEmpty()); }
};
}
#endif // MODEL_SUPPORT_HPP

View File

@ -30,16 +30,16 @@ namespace boost
#endif /* (BOOST_VERSION <= 104600) */ #endif /* (BOOST_VERSION <= 104600) */
CsSettings::UserSettings::UserSettings(Files::ConfigurationManager &cfg) CSMSettings::UserSettings::UserSettings()
: mCfgMgr(cfg) {
mUserSettingsInstance = this;
}
CSMSettings::UserSettings::~UserSettings()
{ {
} }
CsSettings::UserSettings::~UserSettings() QFile *CSMSettings::UserSettings::openFile (const QString &filename)
{
}
QFile *CsSettings::UserSettings::openFile (const QString &filename)
{ {
QFile *file = new QFile(filename); QFile *file = new QFile(filename);
@ -63,7 +63,7 @@ QFile *CsSettings::UserSettings::openFile (const QString &filename)
return file; return file;
} }
bool CsSettings::UserSettings::writeFile(QFile *file, QMap<QString, CsSettings::SettingList *> &settings) bool CSMSettings::UserSettings::writeFile(QFile *file, QMap<QString, CSMSettings::SettingList *> &settings)
{ {
if (!file) if (!file)
return false; return false;
@ -88,7 +88,7 @@ bool CsSettings::UserSettings::writeFile(QFile *file, QMap<QString, CsSettings::
return true; return true;
} }
void CsSettings::UserSettings::getSettings(QTextStream &stream, SectionMap &sections) void CSMSettings::UserSettings::getSettings(QTextStream &stream, SectionMap &sections)
{ {
//looks for a square bracket, "'\\[" //looks for a square bracket, "'\\["
//that has one or more "not nothing" in it, "([^]]+)" //that has one or more "not nothing" in it, "([^]]+)"
@ -102,7 +102,7 @@ void CsSettings::UserSettings::getSettings(QTextStream &stream, SectionMap &sect
QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$"); QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$");
CsSettings::SettingMap *settings = 0; CSMSettings::SettingMap *settings = 0;
QString section = "none"; QString section = "none";
while (!stream.atEnd()) while (!stream.atEnd())

View File

@ -15,20 +15,37 @@ namespace Files { typedef std::vector<boost::filesystem::path> PathContainer;
class QFile; class QFile;
namespace CsSettings { namespace CSMSettings {
class UserSettings struct UserSettings: public QObject
{ {
Q_OBJECT
public: public:
UserSettings(Files::ConfigurationManager &cfg);
~UserSettings(); static UserSettings &instance()
{
static UserSettings instance;
return instance;
}
QFile *openFile (const QString &); QFile *openFile (const QString &);
bool writeFile(QFile *file, QMap<QString, SettingList *> &sections); bool writeFile(QFile *file, QMap<QString, SettingList *> &sections);
void getSettings (QTextStream &stream, SectionMap &settings); void getSettings (QTextStream &stream, SectionMap &settings);
private: private:
Files::ConfigurationManager &mCfgMgr;
UserSettings *mUserSettingsInstance;
UserSettings();
~UserSettings();
UserSettings (UserSettings const &); //not implemented
void operator= (UserSettings const &); //not implemented
signals:
void signalUpdateEditorSetting (const QString &settingName, const QString &settingValue);
}; };
} }

View File

@ -0,0 +1,39 @@
#include "birthsigncheck.hpp"
#include <sstream>
#include <map>
#include <components/esm/loadbsgn.hpp>
#include "../world/universalid.hpp"
CSMTools::BirthsignCheckStage::BirthsignCheckStage (const CSMWorld::IdCollection<ESM::BirthSign>& birthsigns)
: mBirthsigns (birthsigns)
{}
int CSMTools::BirthsignCheckStage::setup()
{
return mBirthsigns.getSize();
}
void CSMTools::BirthsignCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::BirthSign& birthsign = mBirthsigns.getRecord (stage).get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Birthsign, birthsign.mId);
// test for empty name, description and texture
if (birthsign.mName.empty())
messages.push_back (id.toString() + "|" + birthsign.mId + " has an empty name");
if (birthsign.mDescription.empty())
messages.push_back (id.toString() + "|" + birthsign.mId + " has an empty description");
if (birthsign.mTexture.empty())
messages.push_back (id.toString() + "|" + birthsign.mId + " is missing a texture");
/// \todo test if the texture exists
/// \todo check data members that can't be edited in the table view
}

View File

@ -0,0 +1,29 @@
#ifndef CSM_TOOLS_BIRTHSIGNCHECK_H
#define CSM_TOOLS_BIRTHSIGNCHECK_H
#include <components/esm/loadbsgn.hpp>
#include "../world/idcollection.hpp"
#include "stage.hpp"
namespace CSMTools
{
/// \brief VerifyStage: make sure that birthsign records are internally consistent
class BirthsignCheckStage : public Stage
{
const CSMWorld::IdCollection<ESM::BirthSign>& mBirthsigns;
public:
BirthsignCheckStage (const CSMWorld::IdCollection<ESM::BirthSign>& birthsigns);
virtual int setup();
///< \return number of steps
virtual void perform (int stage, std::vector<std::string>& messages);
///< Messages resulting from this tage will be appended to \a messages.
};
}
#endif

View File

@ -0,0 +1,72 @@
#include "classcheck.hpp"
#include <sstream>
#include <map>
#include <components/esm/loadclas.hpp>
#include <components/esm/loadskil.hpp>
#include "../world/universalid.hpp"
CSMTools::ClassCheckStage::ClassCheckStage (const CSMWorld::IdCollection<ESM::Class>& classes)
: mClasses (classes)
{}
int CSMTools::ClassCheckStage::setup()
{
return mClasses.getSize();
}
void CSMTools::ClassCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::Class& class_= mClasses.getRecord (stage).get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Class, class_.mId);
// test for empty name and description
if (class_.mName.empty())
messages.push_back (id.toString() + "|" + class_.mId + " has an empty name");
if (class_.mDescription.empty())
messages.push_back (id.toString() + "|" + class_.mId + " has an empty description");
// test for invalid attributes
for (int i=0; i<2; ++i)
if (class_.mData.mAttribute[i]==-1)
{
std::ostringstream stream;
stream << id.toString() << "|Attribute #" << i << " of " << class_.mId << " is not set";
messages.push_back (stream.str());
}
if (class_.mData.mAttribute[0]==class_.mData.mAttribute[1] && class_.mData.mAttribute[0]!=-1)
{
std::ostringstream stream;
stream << id.toString() << "|Class lists same attribute twice";
messages.push_back (stream.str());
}
// test for non-unique skill
std::map<int, int> skills; // ID, number of occurrences
for (int i=0; i<5; ++i)
for (int i2=0; i2<2; ++i2)
++skills[class_.mData.mSkills[i][i2]];
for (std::map<int, int>::const_iterator iter (skills.begin()); iter!=skills.end(); ++iter)
if (iter->second>1)
{
std::ostringstream stream;
stream
<< id.toString() << "|"
<< ESM::Skill::indexToId (iter->first) << " is listed more than once";
messages.push_back (stream.str());
}
}

View File

@ -0,0 +1,29 @@
#ifndef CSM_TOOLS_CLASSCHECK_H
#define CSM_TOOLS_CLASSCHECK_H
#include <components/esm/loadclas.hpp>
#include "../world/idcollection.hpp"
#include "stage.hpp"
namespace CSMTools
{
/// \brief VerifyStage: make sure that class records are internally consistent
class ClassCheckStage : public Stage
{
const CSMWorld::IdCollection<ESM::Class>& mClasses;
public:
ClassCheckStage (const CSMWorld::IdCollection<ESM::Class>& classes);
virtual int setup();
///< \return number of steps
virtual void perform (int stage, std::vector<std::string>& messages);
///< Messages resulting from this tage will be appended to \a messages.
};
}
#endif

View File

@ -0,0 +1,61 @@
#include "factioncheck.hpp"
#include <sstream>
#include <map>
#include <components/esm/loadfact.hpp>
#include <components/esm/loadskil.hpp>
#include "../world/universalid.hpp"
CSMTools::FactionCheckStage::FactionCheckStage (const CSMWorld::IdCollection<ESM::Faction>& factions)
: mFactions (factions)
{}
int CSMTools::FactionCheckStage::setup()
{
return mFactions.getSize();
}
void CSMTools::FactionCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::Faction& faction = mFactions.getRecord (stage).get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Faction, faction.mId);
// test for empty name
if (faction.mName.empty())
messages.push_back (id.toString() + "|" + faction.mId + " has an empty name");
// test for invalid attributes
if (faction.mData.mAttribute[0]==faction.mData.mAttribute[1] && faction.mData.mAttribute[0]!=-1)
{
std::ostringstream stream;
stream << id.toString() << "|Faction lists same attribute twice";
messages.push_back (stream.str());
}
// test for non-unique skill
std::map<int, int> skills; // ID, number of occurrences
for (int i=0; i<6; ++i)
if (faction.mData.mSkills[i]!=-1)
++skills[faction.mData.mSkills[i]];
for (std::map<int, int>::const_iterator iter (skills.begin()); iter!=skills.end(); ++iter)
if (iter->second>1)
{
std::ostringstream stream;
stream
<< id.toString() << "|"
<< ESM::Skill::indexToId (iter->first) << " is listed more than once";
messages.push_back (stream.str());
}
/// \todo check data members that can't be edited in the table view
}

View File

@ -0,0 +1,29 @@
#ifndef CSM_TOOLS_FACTIONCHECK_H
#define CSM_TOOLS_FACTIONCHECK_H
#include <components/esm/loadfact.hpp>
#include "../world/idcollection.hpp"
#include "stage.hpp"
namespace CSMTools
{
/// \brief VerifyStage: make sure that faction records are internally consistent
class FactionCheckStage : public Stage
{
const CSMWorld::IdCollection<ESM::Faction>& mFactions;
public:
FactionCheckStage (const CSMWorld::IdCollection<ESM::Faction>& factions);
virtual int setup();
///< \return number of steps
virtual void perform (int stage, std::vector<std::string>& messages);
///< Messages resulting from this tage will be appended to \a messages.
};
}
#endif

View File

@ -0,0 +1,68 @@
#include "racecheck.hpp"
#include <sstream>
#include <components/esm/loadrace.hpp>
#include "../world/universalid.hpp"
void CSMTools::RaceCheckStage::performPerRecord (int stage, std::vector<std::string>& messages)
{
const ESM::Race& race = mRaces.getRecord (stage).get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Race, race.mId);
// test for empty name and description
if (race.mName.empty())
messages.push_back (id.toString() + "|" + race.mId + " has an empty name");
if (race.mDescription.empty())
messages.push_back (id.toString() + "|" + race.mId + " has an empty description");
// test for positive height
if (race.mData.mHeight.mMale<=0)
messages.push_back (id.toString() + "|male " + race.mId + " has non-positive height");
if (race.mData.mHeight.mFemale<=0)
messages.push_back (id.toString() + "|female " + race.mId + " has non-positive height");
// test for non-negative weight
if (race.mData.mWeight.mMale<0)
messages.push_back (id.toString() + "|male " + race.mId + " has negative weight");
if (race.mData.mWeight.mFemale<0)
messages.push_back (id.toString() + "|female " + race.mId + " has negative weight");
// remember playable flag
if (race.mData.mFlags & 0x1)
mPlayable = true;
/// \todo check data members that can't be edited in the table view
}
void CSMTools::RaceCheckStage::performFinal (std::vector<std::string>& messages)
{
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Races);
if (!mPlayable)
messages.push_back (id.toString() + "|No playable race");
}
CSMTools::RaceCheckStage::RaceCheckStage (const CSMWorld::IdCollection<ESM::Race>& races)
: mRaces (races), mPlayable (false)
{}
int CSMTools::RaceCheckStage::setup()
{
mPlayable = false;
return mRaces.getSize()+1;
}
void CSMTools::RaceCheckStage::perform (int stage, std::vector<std::string>& messages)
{
if (stage==mRaces.getSize())
performFinal (messages);
else
performPerRecord (stage, messages);
}

View File

@ -0,0 +1,34 @@
#ifndef CSM_TOOLS_RACECHECK_H
#define CSM_TOOLS_RACECHECK_H
#include <components/esm/loadrace.hpp>
#include "../world/idcollection.hpp"
#include "stage.hpp"
namespace CSMTools
{
/// \brief VerifyStage: make sure that race records are internally consistent
class RaceCheckStage : public Stage
{
const CSMWorld::IdCollection<ESM::Race>& mRaces;
bool mPlayable;
void performPerRecord (int stage, std::vector<std::string>& messages);
void performFinal (std::vector<std::string>& messages);
public:
RaceCheckStage (const CSMWorld::IdCollection<ESM::Race>& races);
virtual int setup();
///< \return number of steps
virtual void perform (int stage, std::vector<std::string>& messages);
///< Messages resulting from this tage will be appended to \a messages.
};
}
#endif

View File

@ -0,0 +1,33 @@
#include "regioncheck.hpp"
#include <sstream>
#include <map>
#include <components/esm/loadregn.hpp>
#include "../world/universalid.hpp"
CSMTools::RegionCheckStage::RegionCheckStage (const CSMWorld::IdCollection<ESM::Region>& regions)
: mRegions (regions)
{}
int CSMTools::RegionCheckStage::setup()
{
return mRegions.getSize();
}
void CSMTools::RegionCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::Region& region = mRegions.getRecord (stage).get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Region, region.mId);
// test for empty name
if (region.mName.empty())
messages.push_back (id.toString() + "|" + region.mId + " has an empty name");
/// \todo test that the ID in mSleeplist exists
/// \todo check data members that can't be edited in the table view
}

View File

@ -0,0 +1,29 @@
#ifndef CSM_TOOLS_REGIONCHECK_H
#define CSM_TOOLS_REGIONCHECK_H
#include <components/esm/loadregn.hpp>
#include "../world/idcollection.hpp"
#include "stage.hpp"
namespace CSMTools
{
/// \brief VerifyStage: make sure that region records are internally consistent
class RegionCheckStage : public Stage
{
const CSMWorld::IdCollection<ESM::Region>& mRegions;
public:
RegionCheckStage (const CSMWorld::IdCollection<ESM::Region>& regions);
virtual int setup();
///< \return number of steps
virtual void perform (int stage, std::vector<std::string>& messages);
///< Messages resulting from this tage will be appended to \a messages.
};
}
#endif

View File

@ -0,0 +1,37 @@
#include "skillcheck.hpp"
#include <sstream>
#include <components/esm/loadskil.hpp>
#include "../world/universalid.hpp"
CSMTools::SkillCheckStage::SkillCheckStage (const CSMWorld::IdCollection<ESM::Skill>& skills)
: mSkills (skills)
{}
int CSMTools::SkillCheckStage::setup()
{
return mSkills.getSize();
}
void CSMTools::SkillCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::Skill& skill = mSkills.getRecord (stage).get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Skill, skill.mId);
for (int i=0; i<4; ++i)
if (skill.mData.mUseValue[i]<0)
{
std::ostringstream stream;
stream << id.toString() << "|Use value #" << i << " of " << skill.mId << " is negative";
messages.push_back (stream.str());
}
if (skill.mDescription.empty())
messages.push_back (id.toString() + "|" + skill.mId + " has an empty description");
}

View File

@ -0,0 +1,29 @@
#ifndef CSM_TOOLS_SKILLCHECK_H
#define CSM_TOOLS_SKILLCHECK_H
#include <components/esm/loadskil.hpp>
#include "../world/idcollection.hpp"
#include "stage.hpp"
namespace CSMTools
{
/// \brief VerifyStage: make sure that skill records are internally consistent
class SkillCheckStage : public Stage
{
const CSMWorld::IdCollection<ESM::Skill>& mSkills;
public:
SkillCheckStage (const CSMWorld::IdCollection<ESM::Skill>& skills);
virtual int setup();
///< \return number of steps
virtual void perform (int stage, std::vector<std::string>& messages);
///< Messages resulting from this tage will be appended to \a messages.
};
}
#endif

View File

@ -0,0 +1,29 @@
#include "soundcheck.hpp"
#include <sstream>
#include <components/esm/loadskil.hpp>
#include "../world/universalid.hpp"
CSMTools::SoundCheckStage::SoundCheckStage (const CSMWorld::IdCollection<ESM::Sound>& sounds)
: mSounds (sounds)
{}
int CSMTools::SoundCheckStage::setup()
{
return mSounds.getSize();
}
void CSMTools::SoundCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::Sound& sound = mSounds.getRecord (stage).get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Sound, sound.mId);
if (sound.mData.mMinRange>sound.mData.mMaxRange)
messages.push_back (id.toString() + "|Maximum range larger than minimum range");
/// \todo check, if the sound file exists
}

View File

@ -0,0 +1,29 @@
#ifndef CSM_TOOLS_SOUNDCHECK_H
#define CSM_TOOLS_SOUNDCHECK_H
#include <components/esm/loadsoun.hpp>
#include "../world/idcollection.hpp"
#include "stage.hpp"
namespace CSMTools
{
/// \brief VerifyStage: make sure that sound records are internally consistent
class SoundCheckStage : public Stage
{
const CSMWorld::IdCollection<ESM::Sound>& mSounds;
public:
SoundCheckStage (const CSMWorld::IdCollection<ESM::Sound>& sounds);
virtual int setup();
///< \return number of steps
virtual void perform (int stage, std::vector<std::string>& messages);
///< Messages resulting from this tage will be appended to \a messages.
};
}
#endif

View File

@ -0,0 +1,35 @@
#include "spellcheck.hpp"
#include <sstream>
#include <map>
#include <components/esm/loadspel.hpp>
#include "../world/universalid.hpp"
CSMTools::SpellCheckStage::SpellCheckStage (const CSMWorld::IdCollection<ESM::Spell>& spells)
: mSpells (spells)
{}
int CSMTools::SpellCheckStage::setup()
{
return mSpells.getSize();
}
void CSMTools::SpellCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::Spell& spell = mSpells.getRecord (stage).get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Spell, spell.mId);
// test for empty name and description
if (spell.mName.empty())
messages.push_back (id.toString() + "|" + spell.mId + " has an empty name");
// test for invalid cost values
if (spell.mData.mCost<0)
messages.push_back (id.toString() + "|" + spell.mId + " has a negative spell costs");
/// \todo check data members that can't be edited in the table view
}

View File

@ -0,0 +1,29 @@
#ifndef CSM_TOOLS_SPELLCHECK_H
#define CSM_TOOLS_SPELLCHECK_H
#include <components/esm/loadspel.hpp>
#include "../world/idcollection.hpp"
#include "stage.hpp"
namespace CSMTools
{
/// \brief VerifyStage: make sure that spell records are internally consistent
class SpellCheckStage : public Stage
{
const CSMWorld::IdCollection<ESM::Spell>& mSpells;
public:
SpellCheckStage (const CSMWorld::IdCollection<ESM::Spell>& spells);
virtual int setup();
///< \return number of steps
virtual void perform (int stage, std::vector<std::string>& messages);
///< Messages resulting from this tage will be appended to \a messages.
};
}
#endif

View File

@ -12,6 +12,14 @@
#include "reportmodel.hpp" #include "reportmodel.hpp"
#include "mandatoryid.hpp" #include "mandatoryid.hpp"
#include "skillcheck.hpp"
#include "classcheck.hpp"
#include "factioncheck.hpp"
#include "racecheck.hpp"
#include "soundcheck.hpp"
#include "regioncheck.hpp"
#include "birthsigncheck.hpp"
#include "spellcheck.hpp"
CSMTools::Operation *CSMTools::Tools::get (int type) CSMTools::Operation *CSMTools::Tools::get (int type)
{ {
@ -51,6 +59,22 @@ CSMTools::Verifier *CSMTools::Tools::getVerifier()
mVerifier->appendStage (new MandatoryIdStage (mData.getGlobals(), mVerifier->appendStage (new MandatoryIdStage (mData.getGlobals(),
CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), mandatoryIds)); CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), mandatoryIds));
mVerifier->appendStage (new SkillCheckStage (mData.getSkills()));
mVerifier->appendStage (new ClassCheckStage (mData.getClasses()));
mVerifier->appendStage (new FactionCheckStage (mData.getFactions()));
mVerifier->appendStage (new RaceCheckStage (mData.getRaces()));
mVerifier->appendStage (new SoundCheckStage (mData.getSounds()));
mVerifier->appendStage (new RegionCheckStage (mData.getRegions()));
mVerifier->appendStage (new BirthsignCheckStage (mData.getBirthsigns()));
mVerifier->appendStage (new SpellCheckStage (mData.getSpells()));
} }
return mVerifier; return mVerifier;

View File

@ -0,0 +1,20 @@
#include "cell.hpp"
#include <sstream>
void CSMWorld::Cell::load (ESM::ESMReader &esm)
{
mName = mId;
ESM::Cell::load (esm, true); /// \todo set this to false, once the bug in ESM::Cell::load is fixed
if (!(mData.mFlags & Interior))
{
std::ostringstream stream;
stream << "#" << mData.mX << " " << mData.mY;
mId = stream.str();
}
}

View File

@ -0,0 +1,17 @@
#ifndef CSM_WOLRD_CELL_H
#define CSM_WOLRD_CELL_H
#include <components/esm/loadcell.hpp>
namespace CSMWorld
{
/// \brief Wrapper for Cell record
struct Cell : public ESM::Cell
{
std::string mId;
void load (ESM::ESMReader &esm);
};
}
#endif

View File

@ -31,7 +31,17 @@ namespace CSMWorld
Display_Float, Display_Float,
Display_Var, Display_Var,
Display_GmstVarType, Display_GmstVarType,
Display_GlobalVarType Display_GlobalVarType,
Display_Specialisation,
Display_Attribute,
Display_Boolean,
Display_SpellType,
Display_Script,
Display_ApparatusType,
Display_ArmorType,
Display_ClothingType,
Display_CreatureType,
Display_WeaponType
}; };
std::string mTitle; std::string mTitle;

View File

@ -1,6 +1,12 @@
#ifndef CSM_WOLRD_COLUMNS_H #ifndef CSM_WOLRD_COLUMNS_H
#define CSM_WOLRD_COLUMNS_H #define CSM_WOLRD_COLUMNS_H
#include <sstream>
#include <boost/lexical_cast.hpp>
#include <QColor>
#include "columnbase.hpp" #include "columnbase.hpp"
namespace CSMWorld namespace CSMWorld
@ -35,7 +41,7 @@ namespace CSMWorld
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {
return record.get().mId.c_str(); return QString::fromUtf8 (record.get().mId.c_str());
} }
virtual bool isEditable() const virtual bool isEditable() const
@ -127,17 +133,17 @@ namespace CSMWorld
{ {
case ESM::VT_String: case ESM::VT_String:
return record.get().mValue.getString().c_str(); break; return QString::fromUtf8 (record.get().mValue.getString().c_str());
case ESM::VT_Int: case ESM::VT_Int:
case ESM::VT_Short: case ESM::VT_Short:
case ESM::VT_Long: case ESM::VT_Long:
return record.get().mValue.getInteger(); break; return record.get().mValue.getInteger();
case ESM::VT_Float: case ESM::VT_Float:
return record.get().mValue.getFloat(); break; return record.get().mValue.getFloat();
default: return QVariant(); default: return QVariant();
} }
@ -177,6 +183,596 @@ namespace CSMWorld
return true; return true;
} }
}; };
template<typename ESXRecordT>
struct DescriptionColumn : public Column<ESXRecordT>
{
DescriptionColumn() : Column<ESXRecordT> ("Description", ColumnBase::Display_String) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return QString::fromUtf8 (record.get().mDescription.c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mDescription = data.toString().toUtf8().constData();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct SpecialisationColumn : public Column<ESXRecordT>
{
SpecialisationColumn() : Column<ESXRecordT> ("Specialisation", ColumnBase::Display_Specialisation) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mSpecialization;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mSpecialization = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct UseValueColumn : public Column<ESXRecordT>
{
int mIndex;
UseValueColumn (int index)
: Column<ESXRecordT> ("Use value #" + boost::lexical_cast<std::string> (index),
ColumnBase::Display_Float), mIndex (index)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mUseValue[mIndex];
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mUseValue[mIndex] = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct AttributeColumn : public Column<ESXRecordT>
{
AttributeColumn() : Column<ESXRecordT> ("Attribute", ColumnBase::Display_Attribute) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mAttribute;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mAttribute = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct NameColumn : public Column<ESXRecordT>
{
NameColumn() : Column<ESXRecordT> ("Name", ColumnBase::Display_String) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return QString::fromUtf8 (record.get().mName.c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mName = data.toString().toUtf8().constData();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct AttributesColumn : public Column<ESXRecordT>
{
int mIndex;
AttributesColumn (int index)
: Column<ESXRecordT> ("Attribute #" + boost::lexical_cast<std::string> (index),
ColumnBase::Display_Attribute), mIndex (index) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mAttribute[mIndex];
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mAttribute[mIndex] = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct SkillsColumn : public Column<ESXRecordT>
{
int mIndex;
bool mMajor;
SkillsColumn (int index, bool typePrefix = false, bool major = false)
: Column<ESXRecordT> ((typePrefix ? (major ? "Major Skill #" : "Minor Skill #") : "Skill #")+
boost::lexical_cast<std::string> (index), ColumnBase::Display_String),
mIndex (index), mMajor (major)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
int skill = record.get().mData.getSkill (mIndex, mMajor);
return QString::fromUtf8 (ESM::Skill::indexToId (skill).c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
std::istringstream stream (data.toString().toUtf8().constData());
int index = -1;
char c;
stream >> c >> index;
if (index!=-1)
{
ESXRecordT record2 = record.get();
record2.mData.getSkill (mIndex, mMajor) = index;
record.setModified (record2);
}
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct PlayableColumn : public Column<ESXRecordT>
{
PlayableColumn() : Column<ESXRecordT> ("Playable", ColumnBase::Display_Boolean) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mIsPlayable!=0;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mIsPlayable = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct HiddenColumn : public Column<ESXRecordT>
{
HiddenColumn() : Column<ESXRecordT> ("Hidden", ColumnBase::Display_Boolean) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mIsHidden!=0;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mIsHidden = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct FlagColumn : public Column<ESXRecordT>
{
int mMask;
FlagColumn (const std::string& name, int mask)
: Column<ESXRecordT> (name, ColumnBase::Display_Boolean), mMask (mask)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return (record.get().mData.mFlags & mMask)!=0;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
int flags = record2.mData.mFlags & ~mMask;
if (data.toInt())
flags |= mMask;
record2.mData.mFlags = flags;
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct WeightHeightColumn : public Column<ESXRecordT>
{
bool mMale;
bool mWeight;
WeightHeightColumn (bool male, bool weight)
: Column<ESXRecordT> (male ? (weight ? "Male Weight" : "Male Height") :
(weight ? "Female Weight" : "Female Height"), ColumnBase::Display_Float),
mMale (male), mWeight (weight)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
const ESM::Race::MaleFemaleF& value =
mWeight ? record.get().mData.mWeight : record.get().mData.mHeight;
return mMale ? value.mMale : value.mFemale;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
ESM::Race::MaleFemaleF& value =
mWeight ? record2.mData.mWeight : record2.mData.mHeight;
(mMale ? value.mMale : value.mFemale) = data.toFloat();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct SoundParamColumn : public Column<ESXRecordT>
{
enum Type
{
Type_Volume,
Type_MinRange,
Type_MaxRange
};
Type mType;
SoundParamColumn (Type type)
: Column<ESXRecordT> (
type==Type_Volume ? "Volume" : (type==Type_MinRange ? "Min Range" : "Max Range"),
ColumnBase::Display_Integer),
mType (type)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
int value = 0;
switch (mType)
{
case Type_Volume: value = record.get().mData.mVolume; break;
case Type_MinRange: value = record.get().mData.mMinRange; break;
case Type_MaxRange: value = record.get().mData.mMaxRange; break;
}
return value;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
int value = data.toInt();
if (value<0)
value = 0;
else if (value>255)
value = 255;
ESXRecordT record2 = record.get();
switch (mType)
{
case Type_Volume: record2.mData.mVolume = static_cast<unsigned char> (value); break;
case Type_MinRange: record2.mData.mMinRange = static_cast<unsigned char> (value); break;
case Type_MaxRange: record2.mData.mMaxRange = static_cast<unsigned char> (value); break;
}
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct SoundFileColumn : public Column<ESXRecordT>
{
SoundFileColumn() : Column<ESXRecordT> ("Sound File", ColumnBase::Display_String) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return QString::fromUtf8 (record.get().mSound.c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mSound = data.toString().toUtf8().constData();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
/// \todo QColor is a GUI class and should not be in model. Need to think of an alternative
/// solution.
template<typename ESXRecordT>
struct MapColourColumn : public Column<ESXRecordT>
{
/// \todo Replace Display_Integer with something that displays the colour value more directly.
MapColourColumn() : Column<ESXRecordT> ("Map Colour", ColumnBase::Display_Integer) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
int colour = record.get().mMapColor;
return QColor (colour & 0xff, (colour>>8) & 0xff, (colour>>16) & 0xff);
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
QColor colour = data.value<QColor>();
record2.mMapColor = colour.rgb() & 0xffffff;
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct SleepListColumn : public Column<ESXRecordT>
{
SleepListColumn() : Column<ESXRecordT> ("Sleep Encounter", ColumnBase::Display_String) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return QString::fromUtf8 (record.get().mSleepList.c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mSleepList = data.toString().toUtf8().constData();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct TextureColumn : public Column<ESXRecordT>
{
TextureColumn() : Column<ESXRecordT> ("Texture", ColumnBase::Display_String) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return QString::fromUtf8 (record.get().mTexture.c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mTexture = data.toString().toUtf8().constData();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct SpellTypeColumn : public Column<ESXRecordT>
{
SpellTypeColumn() : Column<ESXRecordT> ("Type", ColumnBase::Display_SpellType) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mType;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mType = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct CostColumn : public Column<ESXRecordT>
{
CostColumn() : Column<ESXRecordT> ("Cost", ColumnBase::Display_Integer) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return record.get().mData.mCost;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mData.mCost = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct ScriptColumn : public Column<ESXRecordT>
{
ScriptColumn() : Column<ESXRecordT> ("Script", ColumnBase::Display_Script, 0) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return QString::fromUtf8 (record.get().mScriptText.c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mScriptText = data.toString().toUtf8().constData();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct RegionColumn : public Column<ESXRecordT>
{
RegionColumn() : Column<ESXRecordT> ("Region", ColumnBase::Display_String) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return QString::fromUtf8 (record.get().mRegion.c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mRegion = data.toString().toUtf8().constData();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
} }
#endif #endif

View File

@ -1,7 +1,7 @@
#include "commands.hpp" #include "commands.hpp"
#include <QAbstractTableModel> #include <QAbstractItemModel>
#include "idtableproxymodel.hpp" #include "idtableproxymodel.hpp"
#include "idtable.hpp" #include "idtable.hpp"
@ -71,7 +71,7 @@ void CSMWorld::RevertCommand::redo()
void CSMWorld::RevertCommand::undo() void CSMWorld::RevertCommand::undo()
{ {
mModel.setRecord (*mOld); mModel.setRecord (mId, *mOld);
} }
CSMWorld::DeleteCommand::DeleteCommand (IdTable& model, const std::string& id, QUndoCommand *parent) CSMWorld::DeleteCommand::DeleteCommand (IdTable& model, const std::string& id, QUndoCommand *parent)
@ -104,5 +104,5 @@ void CSMWorld::DeleteCommand::redo()
void CSMWorld::DeleteCommand::undo() void CSMWorld::DeleteCommand::undo()
{ {
mModel.setRecord (*mOld); mModel.setRecord (mId, *mOld);
} }

View File

@ -3,7 +3,7 @@
#include <stdexcept> #include <stdexcept>
#include <QAbstractTableModel> #include <QAbstractItemModel>
#include <components/esm/esmreader.hpp> #include <components/esm/esmreader.hpp>
#include <components/esm/defs.hpp> #include <components/esm/defs.hpp>
@ -12,7 +12,7 @@
#include "idtable.hpp" #include "idtable.hpp"
#include "columns.hpp" #include "columns.hpp"
void CSMWorld::Data::addModel (QAbstractTableModel *model, UniversalId::Type type1, void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type1,
UniversalId::Type type2) UniversalId::Type type2)
{ {
mModels.push_back (model); mModels.push_back (model);
@ -33,16 +33,120 @@ CSMWorld::Data::Data()
mGmsts.addColumn (new StringIdColumn<ESM::GameSetting>); mGmsts.addColumn (new StringIdColumn<ESM::GameSetting>);
mGmsts.addColumn (new RecordStateColumn<ESM::GameSetting>); mGmsts.addColumn (new RecordStateColumn<ESM::GameSetting>);
mGmsts.addColumn (new FixedRecordTypeColumn<ESM::GameSetting> (UniversalId::Type_Gmst)); mGmsts.addColumn (new FixedRecordTypeColumn<ESM::GameSetting> (UniversalId::Type_Gmst));
mGmsts.addColumn (new FixedRecordTypeColumn<ESM::GameSetting> (UniversalId::Type_Gmst));
mGmsts.addColumn (new VarTypeColumn<ESM::GameSetting> (ColumnBase::Display_GmstVarType)); mGmsts.addColumn (new VarTypeColumn<ESM::GameSetting> (ColumnBase::Display_GmstVarType));
mGmsts.addColumn (new VarValueColumn<ESM::GameSetting>); mGmsts.addColumn (new VarValueColumn<ESM::GameSetting>);
mSkills.addColumn (new StringIdColumn<ESM::Skill>);
mSkills.addColumn (new RecordStateColumn<ESM::Skill>);
mSkills.addColumn (new FixedRecordTypeColumn<ESM::Skill> (UniversalId::Type_Skill));
mSkills.addColumn (new AttributeColumn<ESM::Skill>);
mSkills.addColumn (new SpecialisationColumn<ESM::Skill>);
for (int i=0; i<4; ++i)
mSkills.addColumn (new UseValueColumn<ESM::Skill> (i));
mSkills.addColumn (new DescriptionColumn<ESM::Skill>);
mClasses.addColumn (new StringIdColumn<ESM::Class>);
mClasses.addColumn (new RecordStateColumn<ESM::Class>);
mClasses.addColumn (new FixedRecordTypeColumn<ESM::Class> (UniversalId::Type_Class));
mClasses.addColumn (new NameColumn<ESM::Class>);
mClasses.addColumn (new AttributesColumn<ESM::Class> (0));
mClasses.addColumn (new AttributesColumn<ESM::Class> (1));
mClasses.addColumn (new SpecialisationColumn<ESM::Class>);
for (int i=0; i<5; ++i)
mClasses.addColumn (new SkillsColumn<ESM::Class> (i, true, true));
for (int i=0; i<5; ++i)
mClasses.addColumn (new SkillsColumn<ESM::Class> (i, true, false));
mClasses.addColumn (new PlayableColumn<ESM::Class>);
mClasses.addColumn (new DescriptionColumn<ESM::Class>);
mFactions.addColumn (new StringIdColumn<ESM::Faction>);
mFactions.addColumn (new RecordStateColumn<ESM::Faction>);
mFactions.addColumn (new FixedRecordTypeColumn<ESM::Faction> (UniversalId::Type_Faction));
mFactions.addColumn (new NameColumn<ESM::Faction>);
mFactions.addColumn (new AttributesColumn<ESM::Faction> (0));
mFactions.addColumn (new AttributesColumn<ESM::Faction> (1));
mFactions.addColumn (new HiddenColumn<ESM::Faction>);
for (int i=0; i<6; ++i)
mFactions.addColumn (new SkillsColumn<ESM::Faction> (i));
mRaces.addColumn (new StringIdColumn<ESM::Race>);
mRaces.addColumn (new RecordStateColumn<ESM::Race>);
mRaces.addColumn (new FixedRecordTypeColumn<ESM::Race> (UniversalId::Type_Race));
mRaces.addColumn (new NameColumn<ESM::Race>);
mRaces.addColumn (new DescriptionColumn<ESM::Race>);
mRaces.addColumn (new FlagColumn<ESM::Race> ("Playable", 0x1));
mRaces.addColumn (new FlagColumn<ESM::Race> ("Beast Race", 0x2));
mRaces.addColumn (new WeightHeightColumn<ESM::Race> (true, true));
mRaces.addColumn (new WeightHeightColumn<ESM::Race> (true, false));
mRaces.addColumn (new WeightHeightColumn<ESM::Race> (false, true));
mRaces.addColumn (new WeightHeightColumn<ESM::Race> (false, false));
mSounds.addColumn (new StringIdColumn<ESM::Sound>);
mSounds.addColumn (new RecordStateColumn<ESM::Sound>);
mSounds.addColumn (new FixedRecordTypeColumn<ESM::Sound> (UniversalId::Type_Sound));
mSounds.addColumn (new SoundParamColumn<ESM::Sound> (SoundParamColumn<ESM::Sound>::Type_Volume));
mSounds.addColumn (new SoundParamColumn<ESM::Sound> (SoundParamColumn<ESM::Sound>::Type_MinRange));
mSounds.addColumn (new SoundParamColumn<ESM::Sound> (SoundParamColumn<ESM::Sound>::Type_MaxRange));
mSounds.addColumn (new SoundFileColumn<ESM::Sound>);
mScripts.addColumn (new StringIdColumn<ESM::Script>);
mScripts.addColumn (new RecordStateColumn<ESM::Script>);
mScripts.addColumn (new FixedRecordTypeColumn<ESM::Script> (UniversalId::Type_Script));
mScripts.addColumn (new ScriptColumn<ESM::Script>);
mRegions.addColumn (new StringIdColumn<ESM::Region>);
mRegions.addColumn (new RecordStateColumn<ESM::Region>);
mRegions.addColumn (new FixedRecordTypeColumn<ESM::Region> (UniversalId::Type_Region));
mRegions.addColumn (new NameColumn<ESM::Region>);
mRegions.addColumn (new MapColourColumn<ESM::Region>);
mRegions.addColumn (new SleepListColumn<ESM::Region>);
mBirthsigns.addColumn (new StringIdColumn<ESM::BirthSign>);
mBirthsigns.addColumn (new RecordStateColumn<ESM::BirthSign>);
mBirthsigns.addColumn (new FixedRecordTypeColumn<ESM::BirthSign> (UniversalId::Type_Birthsign));
mBirthsigns.addColumn (new NameColumn<ESM::BirthSign>);
mBirthsigns.addColumn (new TextureColumn<ESM::BirthSign>);
mBirthsigns.addColumn (new DescriptionColumn<ESM::BirthSign>);
mSpells.addColumn (new StringIdColumn<ESM::Spell>);
mSpells.addColumn (new RecordStateColumn<ESM::Spell>);
mSpells.addColumn (new FixedRecordTypeColumn<ESM::Spell> (UniversalId::Type_Spell));
mSpells.addColumn (new NameColumn<ESM::Spell>);
mSpells.addColumn (new SpellTypeColumn<ESM::Spell>);
mSpells.addColumn (new CostColumn<ESM::Spell>);
mSpells.addColumn (new FlagColumn<ESM::Spell> ("Autocalc", 0x1));
mSpells.addColumn (new FlagColumn<ESM::Spell> ("Starter Spell", 0x2));
mSpells.addColumn (new FlagColumn<ESM::Spell> ("Always Succeeds", 0x4));
mCells.addColumn (new StringIdColumn<Cell>);
mCells.addColumn (new RecordStateColumn<Cell>);
mCells.addColumn (new FixedRecordTypeColumn<Cell> (UniversalId::Type_Cell));
mCells.addColumn (new NameColumn<Cell>);
mCells.addColumn (new FlagColumn<Cell> ("Sleep forbidden", ESM::Cell::NoSleep));
mCells.addColumn (new FlagColumn<Cell> ("Interior Water", ESM::Cell::HasWater));
mCells.addColumn (new FlagColumn<Cell> ("Interior Sky", ESM::Cell::QuasiEx));
mCells.addColumn (new RegionColumn<Cell>);
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst); addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst);
addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill);
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 (&mCells), UniversalId::Type_Cells, UniversalId::Type_Cell);
addModel (new IdTable (&mReferenceables), UniversalId::Type_Referenceables,
UniversalId::Type_Referenceable);
} }
CSMWorld::Data::~Data() CSMWorld::Data::~Data()
{ {
for (std::vector<QAbstractTableModel *>::iterator iter (mModels.begin()); iter!=mModels.end(); ++iter) for (std::vector<QAbstractItemModel *>::iterator iter (mModels.begin()); iter!=mModels.end(); ++iter)
delete *iter; delete *iter;
} }
@ -66,9 +170,119 @@ CSMWorld::IdCollection<ESM::GameSetting>& CSMWorld::Data::getGmsts()
return mGmsts; return mGmsts;
} }
QAbstractTableModel *CSMWorld::Data::getTableModel (const UniversalId& id) const CSMWorld::IdCollection<ESM::Skill>& CSMWorld::Data::getSkills() const
{ {
std::map<UniversalId::Type, QAbstractTableModel *>::iterator iter = mModelIndex.find (id.getType()); return mSkills;
}
CSMWorld::IdCollection<ESM::Skill>& CSMWorld::Data::getSkills()
{
return mSkills;
}
const CSMWorld::IdCollection<ESM::Class>& CSMWorld::Data::getClasses() const
{
return mClasses;
}
CSMWorld::IdCollection<ESM::Class>& CSMWorld::Data::getClasses()
{
return mClasses;
}
const CSMWorld::IdCollection<ESM::Faction>& CSMWorld::Data::getFactions() const
{
return mFactions;
}
CSMWorld::IdCollection<ESM::Faction>& CSMWorld::Data::getFactions()
{
return mFactions;
}
const CSMWorld::IdCollection<ESM::Race>& CSMWorld::Data::getRaces() const
{
return mRaces;
}
CSMWorld::IdCollection<ESM::Race>& CSMWorld::Data::getRaces()
{
return mRaces;
}
const CSMWorld::IdCollection<ESM::Sound>& CSMWorld::Data::getSounds() const
{
return mSounds;
}
CSMWorld::IdCollection<ESM::Sound>& CSMWorld::Data::getSounds()
{
return mSounds;
}
const CSMWorld::IdCollection<ESM::Script>& CSMWorld::Data::getScripts() const
{
return mScripts;
}
CSMWorld::IdCollection<ESM::Script>& CSMWorld::Data::getScripts()
{
return mScripts;
}
const CSMWorld::IdCollection<ESM::Region>& CSMWorld::Data::getRegions() const
{
return mRegions;
}
CSMWorld::IdCollection<ESM::Region>& CSMWorld::Data::getRegions()
{
return mRegions;
}
const CSMWorld::IdCollection<ESM::BirthSign>& CSMWorld::Data::getBirthsigns() const
{
return mBirthsigns;
}
CSMWorld::IdCollection<ESM::BirthSign>& CSMWorld::Data::getBirthsigns()
{
return mBirthsigns;
}
const CSMWorld::IdCollection<ESM::Spell>& CSMWorld::Data::getSpells() const
{
return mSpells;
}
CSMWorld::IdCollection<ESM::Spell>& CSMWorld::Data::getSpells()
{
return mSpells;
}
const CSMWorld::IdCollection<CSMWorld::Cell>& CSMWorld::Data::getCells() const
{
return mCells;
}
CSMWorld::IdCollection<CSMWorld::Cell>& CSMWorld::Data::getCells()
{
return mCells;
}
const CSMWorld::RefIdCollection& CSMWorld::Data::getReferenceables() const
{
return mReferenceables;
}
CSMWorld::RefIdCollection& CSMWorld::Data::getReferenceables()
{
return mReferenceables;
}
QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id)
{
std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType());
if (iter==mModelIndex.end()) if (iter==mModelIndex.end())
throw std::logic_error ("No table model available for " + id.toString()); throw std::logic_error ("No table model available for " + id.toString());
@ -102,7 +316,40 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base)
{ {
case ESM::REC_GLOB: mGlobals.load (reader, base); break; case ESM::REC_GLOB: mGlobals.load (reader, base); break;
case ESM::REC_GMST: mGmsts.load (reader, base); break; case ESM::REC_GMST: mGmsts.load (reader, base); break;
case ESM::REC_SKIL: mSkills.load (reader, base); break;
case ESM::REC_CLAS: mClasses.load (reader, base); break;
case ESM::REC_FACT: mFactions.load (reader, base); break;
case ESM::REC_RACE: mRaces.load (reader, base); break;
case ESM::REC_SOUN: mSounds.load (reader, base); break;
case ESM::REC_SCPT: mScripts.load (reader, base); break;
case ESM::REC_REGN: mRegions.load (reader, base); break;
case ESM::REC_BSGN: mBirthsigns.load (reader, base); break;
case ESM::REC_SPEL: mSpells.load (reader, base); break;
case ESM::REC_CELL: mCells.load (reader, base); break;
case ESM::REC_ACTI: mReferenceables.load (reader, base, UniversalId::Type_Activator); break;
case ESM::REC_ALCH: mReferenceables.load (reader, base, UniversalId::Type_Potion); break;
case ESM::REC_APPA: mReferenceables.load (reader, base, UniversalId::Type_Apparatus); break;
case ESM::REC_ARMO: mReferenceables.load (reader, base, UniversalId::Type_Armor); break;
case ESM::REC_BOOK: mReferenceables.load (reader, base, UniversalId::Type_Book); break;
case ESM::REC_CLOT: mReferenceables.load (reader, base, UniversalId::Type_Clothing); break;
case ESM::REC_CONT: mReferenceables.load (reader, base, UniversalId::Type_Container); break;
case ESM::REC_CREA: mReferenceables.load (reader, base, UniversalId::Type_Creature); break;
case ESM::REC_DOOR: mReferenceables.load (reader, base, UniversalId::Type_Door); break;
case ESM::REC_INGR: mReferenceables.load (reader, base, UniversalId::Type_Ingredient); break;
case ESM::REC_LEVC:
mReferenceables.load (reader, base, UniversalId::Type_CreatureLevelledList); break;
case ESM::REC_LEVI:
mReferenceables.load (reader, base, UniversalId::Type_ItemLevelledList); break;
case ESM::REC_LIGH: mReferenceables.load (reader, base, UniversalId::Type_Light); break;
case ESM::REC_LOCK: mReferenceables.load (reader, base, UniversalId::Type_Lockpick); break;
case ESM::REC_MISC:
mReferenceables.load (reader, base, UniversalId::Type_Miscellaneous); break;
case ESM::REC_NPC_: mReferenceables.load (reader, base, UniversalId::Type_Npc); break;
case ESM::REC_PROB: mReferenceables.load (reader, base, UniversalId::Type_Probe); break;
case ESM::REC_REPA: mReferenceables.load (reader, base, UniversalId::Type_Repair); break;
case ESM::REC_STAT: mReferenceables.load (reader, base, UniversalId::Type_Static); break;
case ESM::REC_WEAP: mReferenceables.load (reader, base, UniversalId::Type_Weapon); break;
default: default:

View File

@ -8,11 +8,22 @@
#include <components/esm/loadglob.hpp> #include <components/esm/loadglob.hpp>
#include <components/esm/loadgmst.hpp> #include <components/esm/loadgmst.hpp>
#include <components/esm/loadskil.hpp>
#include <components/esm/loadclas.hpp>
#include <components/esm/loadfact.hpp>
#include <components/esm/loadrace.hpp>
#include <components/esm/loadsoun.hpp>
#include <components/esm/loadscpt.hpp>
#include <components/esm/loadregn.hpp>
#include <components/esm/loadbsgn.hpp>
#include <components/esm/loadspel.hpp>
#include "idcollection.hpp" #include "idcollection.hpp"
#include "universalid.hpp" #include "universalid.hpp"
#include "cell.hpp"
#include "refidcollection.hpp"
class QAbstractTableModel; class QAbstractItemModel;
namespace CSMWorld namespace CSMWorld
{ {
@ -20,14 +31,25 @@ namespace CSMWorld
{ {
IdCollection<ESM::Global> mGlobals; IdCollection<ESM::Global> mGlobals;
IdCollection<ESM::GameSetting> mGmsts; IdCollection<ESM::GameSetting> mGmsts;
std::vector<QAbstractTableModel *> mModels; IdCollection<ESM::Skill> mSkills;
std::map<UniversalId::Type, QAbstractTableModel *> mModelIndex; IdCollection<ESM::Class> mClasses;
IdCollection<ESM::Faction> mFactions;
IdCollection<ESM::Race> mRaces;
IdCollection<ESM::Sound> mSounds;
IdCollection<ESM::Script> mScripts;
IdCollection<ESM::Region> mRegions;
IdCollection<ESM::BirthSign> mBirthsigns;
IdCollection<ESM::Spell> mSpells;
IdCollection<Cell> mCells;
RefIdCollection mReferenceables;
std::vector<QAbstractItemModel *> mModels;
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
// not implemented // not implemented
Data (const Data&); Data (const Data&);
Data& operator= (const Data&); Data& operator= (const Data&);
void addModel (QAbstractTableModel *model, UniversalId::Type type1, void addModel (QAbstractItemModel *model, UniversalId::Type type1,
UniversalId::Type type2 = UniversalId::Type_None); UniversalId::Type type2 = UniversalId::Type_None);
public: public:
@ -44,7 +66,51 @@ namespace CSMWorld
IdCollection<ESM::GameSetting>& getGmsts(); IdCollection<ESM::GameSetting>& getGmsts();
QAbstractTableModel *getTableModel (const UniversalId& id); const IdCollection<ESM::Skill>& getSkills() const;
IdCollection<ESM::Skill>& getSkills();
const IdCollection<ESM::Class>& getClasses() const;
IdCollection<ESM::Class>& getClasses();
const IdCollection<ESM::Faction>& getFactions() const;
IdCollection<ESM::Faction>& getFactions();
const IdCollection<ESM::Race>& getRaces() const;
IdCollection<ESM::Race>& getRaces();
const IdCollection<ESM::Sound>& getSounds() const;
IdCollection<ESM::Sound>& getSounds();
const IdCollection<ESM::Script>& getScripts() const;
IdCollection<ESM::Script>& getScripts();
const IdCollection<ESM::Region>& getRegions() const;
IdCollection<ESM::Region>& getRegions();
const IdCollection<ESM::BirthSign>& getBirthsigns() const;
IdCollection<ESM::BirthSign>& getBirthsigns();
const IdCollection<ESM::Spell>& getSpells() const;
IdCollection<ESM::Spell>& getSpells();
const IdCollection<Cell>& getCells() const;
IdCollection<Cell>& getCells();
const RefIdCollection& getReferenceables() const;
RefIdCollection& getReferenceables();
QAbstractItemModel *getTableModel (const UniversalId& id);
///< If no table model is available for \a id, an exception is thrown. ///< If no table model is available for \a id, an exception is thrown.
/// ///
/// \note The returned table may either be the model for the ID itself or the model that /// \note The returned table may either be the model for the ID itself or the model that

View File

@ -16,6 +16,7 @@
#include <components/misc/stringops.hpp> #include <components/misc/stringops.hpp>
#include "columnbase.hpp" #include "columnbase.hpp"
#include "universalid.hpp"
namespace CSMWorld namespace CSMWorld
{ {
@ -45,15 +46,19 @@ namespace CSMWorld
virtual void setData (int index, int column, const QVariant& data) = 0; virtual void setData (int index, int column, const QVariant& data) = 0;
virtual void merge() = 0; // Not in use. Temporarily removed so that the implementation of RefIdCollection can continue without
// these functions for now.
// virtual void merge() = 0;
///< Merge modified into base. ///< Merge modified into base.
virtual void purge() = 0; // virtual void purge() = 0;
///< Remove records that are flagged as erased. ///< Remove records that are flagged as erased.
virtual void removeRows (int index, int count) = 0; virtual void removeRows (int index, int count) = 0;
virtual void appendBlankRecord (const std::string& id) = 0; virtual void appendBlankRecord (const std::string& id,
UniversalId::Type type = UniversalId::Type_None) = 0;
///< \param type Will be ignored, unless the collection supports multiple record types
virtual int searchId (const std::string& id) const = 0; virtual int searchId (const std::string& id) const = 0;
////< Search record with \a id. ////< Search record with \a id.
@ -63,22 +68,47 @@ namespace CSMWorld
///< If the record type does not match, an exception is thrown. ///< If the record type does not match, an exception is thrown.
/// ///
/// \attention \a record must not change the ID. /// \attention \a record must not change the ID.
///< \param type Will be ignored, unless the collection supports multiple record types
virtual void appendRecord (const RecordBase& record) = 0; virtual void appendRecord (const RecordBase& record,
UniversalId::Type type = UniversalId::Type_None) = 0;
///< If the record type does not match, an exception is thrown. ///< If the record type does not match, an exception is thrown.
virtual std::string getId (const RecordBase& record) const = 0;
///< Return ID for \a record.
///
/// \attention Throws an exception, if the type of \a record does not match.
virtual const RecordBase& getRecord (const std::string& id) const = 0; virtual const RecordBase& getRecord (const std::string& id) const = 0;
virtual void load (ESM::ESMReader& reader, bool base) = 0; virtual const RecordBase& getRecord (int index) const = 0;
virtual void load (ESM::ESMReader& reader, bool base,
UniversalId::Type type = UniversalId::Type_None) = 0;
///< \param type Will be ignored, unless the collection supports multiple record types
virtual int getAppendIndex (UniversalId::Type type = UniversalId::Type_None) const = 0;
///< \param type Will be ignored, unless the collection supports multiple record types
}; };
///< \brief Collection of ID-based records ///< \brief Access to ID field in records
template<typename ESXRecordT> template<typename ESXRecordT>
struct IdAccessor
{
std::string& getId (ESXRecordT& record);
const std::string getId (const ESXRecordT& record) const;
};
template<typename ESXRecordT>
std::string& IdAccessor<ESXRecordT>::getId (ESXRecordT& record)
{
return record.mId;
}
template<typename ESXRecordT>
const std::string IdAccessor<ESXRecordT>::getId (const ESXRecordT& record) const
{
return record.mId;
}
///< \brief Collection of ID-based records
template<typename ESXRecordT, typename IdAccessorT = IdAccessor<ESXRecordT> >
class IdCollection : public IdCollectionBase class IdCollection : public IdCollectionBase
{ {
std::vector<Record<ESXRecordT> > mRecords; std::vector<Record<ESXRecordT> > mRecords;
@ -120,7 +150,9 @@ namespace CSMWorld
virtual void removeRows (int index, int count) ; virtual void removeRows (int index, int count) ;
virtual void appendBlankRecord (const std::string& id); virtual void appendBlankRecord (const std::string& id,
UniversalId::Type type = UniversalId::Type_None);
///< \param type Will be ignored, unless the collection supports multiple record types
virtual int searchId (const std::string& id) const; virtual int searchId (const std::string& id) const;
////< Search record with \a id. ////< Search record with \a id.
@ -131,36 +163,40 @@ namespace CSMWorld
/// ///
/// \attention \a record must not change the ID. /// \attention \a record must not change the ID.
virtual void appendRecord (const RecordBase& record); virtual void appendRecord (const RecordBase& record,
UniversalId::Type type = UniversalId::Type_None);
///< If the record type does not match, an exception is thrown. ///< If the record type does not match, an exception is thrown.
///< \param type Will be ignored, unless the collection supports multiple record types
virtual std::string getId (const RecordBase& record) const; virtual const Record<ESXRecordT>& getRecord (const std::string& id) const;
///< Return ID for \a record.
///
/// \attention Throw san exception, if the type of \a record does not match.
virtual const RecordBase& getRecord (const std::string& id) const; virtual const Record<ESXRecordT>& getRecord (int index) const;
virtual void load (ESM::ESMReader& reader, bool base); virtual void load (ESM::ESMReader& reader, bool base,
UniversalId::Type type = UniversalId::Type_None);
///< \param type Will be ignored, unless the collection supports multiple record types
virtual int getAppendIndex (UniversalId::Type type = UniversalId::Type_None) const;
///< \param type Will be ignored, unless the collection supports multiple record types
void addColumn (Column<ESXRecordT> *column); void addColumn (Column<ESXRecordT> *column);
}; };
template<typename ESXRecordT> template<typename ESXRecordT, typename IdAccessorT>
IdCollection<ESXRecordT>::IdCollection() IdCollection<ESXRecordT, IdAccessorT>::IdCollection()
{} {}
template<typename ESXRecordT> template<typename ESXRecordT, typename IdAccessorT>
IdCollection<ESXRecordT>::~IdCollection() IdCollection<ESXRecordT, IdAccessorT>::~IdCollection()
{ {
for (typename std::vector<Column<ESXRecordT> *>::iterator iter (mColumns.begin()); iter!=mColumns.end(); ++iter) for (typename std::vector<Column<ESXRecordT> *>::iterator iter (mColumns.begin()); iter!=mColumns.end(); ++iter)
delete *iter; delete *iter;
} }
template<typename ESXRecordT> template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT>::add (const ESXRecordT& record) void IdCollection<ESXRecordT, IdAccessorT>::add (const ESXRecordT& record)
{ {
std::string id = Misc::StringUtils::lowerCase(record.mId); std::string id = Misc::StringUtils::lowerCase (IdAccessorT().getId (record));
std::map<std::string, int>::iterator iter = mIndex.find (id); std::map<std::string, int>::iterator iter = mIndex.find (id);
@ -179,20 +215,20 @@ namespace CSMWorld
} }
} }
template<typename ESXRecordT> template<typename ESXRecordT, typename IdAccessorT>
int IdCollection<ESXRecordT>::getSize() const int IdCollection<ESXRecordT, IdAccessorT>::getSize() const
{ {
return mRecords.size(); return mRecords.size();
} }
template<typename ESXRecordT> template<typename ESXRecordT, typename IdAccessorT>
std::string IdCollection<ESXRecordT>::getId (int index) const std::string IdCollection<ESXRecordT, IdAccessorT>::getId (int index) const
{ {
return mRecords.at (index).get().mId; return IdAccessorT().getId (mRecords.at (index).get());
} }
template<typename ESXRecordT> template<typename ESXRecordT, typename IdAccessorT>
int IdCollection<ESXRecordT>::getIndex (const std::string& id) const int IdCollection<ESXRecordT, IdAccessorT>::getIndex (const std::string& id) const
{ {
int index = searchId (id); int index = searchId (id);
@ -202,38 +238,38 @@ namespace CSMWorld
return index; return index;
} }
template<typename ESXRecordT> template<typename ESXRecordT, typename IdAccessorT>
int IdCollection<ESXRecordT>::getColumns() const int IdCollection<ESXRecordT, IdAccessorT>::getColumns() const
{ {
return mColumns.size(); return mColumns.size();
} }
template<typename ESXRecordT> template<typename ESXRecordT, typename IdAccessorT>
QVariant IdCollection<ESXRecordT>::getData (int index, int column) const QVariant IdCollection<ESXRecordT, IdAccessorT>::getData (int index, int column) const
{ {
return mColumns.at (column)->get (mRecords.at (index)); return mColumns.at (column)->get (mRecords.at (index));
} }
template<typename ESXRecordT> template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT>::setData (int index, int column, const QVariant& data) void IdCollection<ESXRecordT, IdAccessorT>::setData (int index, int column, const QVariant& data)
{ {
return mColumns.at (column)->set (mRecords.at (index), data); return mColumns.at (column)->set (mRecords.at (index), data);
} }
template<typename ESXRecordT> template<typename ESXRecordT, typename IdAccessorT>
const ColumnBase& IdCollection<ESXRecordT>::getColumn (int column) const const ColumnBase& IdCollection<ESXRecordT, IdAccessorT>::getColumn (int column) const
{ {
return *mColumns.at (column); return *mColumns.at (column);
} }
template<typename ESXRecordT> template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT>::addColumn (Column<ESXRecordT> *column) void IdCollection<ESXRecordT, IdAccessorT>::addColumn (Column<ESXRecordT> *column)
{ {
mColumns.push_back (column); mColumns.push_back (column);
} }
template<typename ESXRecordT> template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT>::merge() void IdCollection<ESXRecordT, IdAccessorT>::merge()
{ {
for (typename std::vector<Record<ESXRecordT> >::iterator iter (mRecords.begin()); iter!=mRecords.end(); ++iter) for (typename std::vector<Record<ESXRecordT> >::iterator iter (mRecords.begin()); iter!=mRecords.end(); ++iter)
iter->merge(); iter->merge();
@ -241,16 +277,22 @@ namespace CSMWorld
purge(); purge();
} }
template<typename ESXRecordT> template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT>::purge() void IdCollection<ESXRecordT, IdAccessorT>::purge()
{ {
mRecords.erase (std::remove_if (mRecords.begin(), mRecords.end(), int i = 0;
std::mem_fun_ref (&Record<ESXRecordT>::isErased) // I want lambda :(
), mRecords.end()); while (i<static_cast<int> (mRecords.size()))
{
if (mRecords[i].isErased())
removeRows (i, 1);
else
++i;
}
} }
template<typename ESXRecordT> template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT>::removeRows (int index, int count) void IdCollection<ESXRecordT, IdAccessorT>::removeRows (int index, int count)
{ {
mRecords.erase (mRecords.begin()+index, mRecords.begin()+index+count); mRecords.erase (mRecords.begin()+index, mRecords.begin()+index+count);
@ -274,17 +316,18 @@ namespace CSMWorld
} }
} }
template<typename ESXRecordT> template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT>::appendBlankRecord (const std::string& id) void IdCollection<ESXRecordT, IdAccessorT>::appendBlankRecord (const std::string& id,
UniversalId::Type type)
{ {
ESXRecordT record; ESXRecordT record;
record.mId = id; IdAccessorT().getId (record) = id;
record.blank(); record.blank();
add (record); add (record);
} }
template<typename ESXRecordT> template<typename ESXRecordT, typename IdAccessorT>
int IdCollection<ESXRecordT>::searchId (const std::string& id) const int IdCollection<ESXRecordT, IdAccessorT>::searchId (const std::string& id) const
{ {
std::string id2 = Misc::StringUtils::lowerCase(id); std::string id2 = Misc::StringUtils::lowerCase(id);
@ -296,35 +339,32 @@ namespace CSMWorld
return iter->second; return iter->second;
} }
template<typename ESXRecordT> template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT>::replace (int index, const RecordBase& record) void IdCollection<ESXRecordT, IdAccessorT>::replace (int index, const RecordBase& record)
{ {
mRecords.at (index) = dynamic_cast<const Record<ESXRecordT>&> (record); mRecords.at (index) = dynamic_cast<const Record<ESXRecordT>&> (record);
} }
template<typename ESXRecordT> template<typename ESXRecordT, typename IdAccessorT>
void IdCollection<ESXRecordT>::appendRecord (const RecordBase& record) void IdCollection<ESXRecordT, IdAccessorT>::appendRecord (const RecordBase& record,
UniversalId::Type type)
{ {
mRecords.push_back (dynamic_cast<const Record<ESXRecordT>&> (record)); mRecords.push_back (dynamic_cast<const Record<ESXRecordT>&> (record));
mIndex.insert (std::make_pair (Misc::StringUtils::lowerCase (getId (record)), mRecords.size()-1)); mIndex.insert (std::make_pair (Misc::StringUtils::lowerCase (IdAccessorT().getId (
dynamic_cast<const Record<ESXRecordT>&> (record).get())),
mRecords.size()-1));
} }
template<typename ESXRecordT> template<typename ESXRecordT, typename IdAccessorT>
std::string IdCollection<ESXRecordT>::getId (const RecordBase& record) const void IdCollection<ESXRecordT, IdAccessorT>::load (ESM::ESMReader& reader, bool base,
{ UniversalId::Type type)
const Record<ESXRecordT>& record2 = dynamic_cast<const Record<ESXRecordT>&> (record);
return (record2.isModified() ? record2.mModified : record2.mBase).mId;
}
template<typename ESXRecordT>
void IdCollection<ESXRecordT>::load (ESM::ESMReader& reader, bool base)
{ {
std::string id = reader.getHNOString ("NAME"); std::string id = reader.getHNOString ("NAME");
int index = searchId (id);
if (reader.isNextSub ("DELE")) if (reader.isNextSub ("DELE"))
{ {
int index = searchId (id);
reader.skipRecord(); reader.skipRecord();
if (index==-1) if (index==-1)
@ -347,9 +387,11 @@ namespace CSMWorld
else else
{ {
ESXRecordT record; ESXRecordT record;
record.mId = id; IdAccessorT().getId (record) = id;
record.load (reader); record.load (reader);
int index = searchId (IdAccessorT().getId (record));
if (index==-1) if (index==-1)
{ {
// new record // new record
@ -372,12 +414,25 @@ namespace CSMWorld
} }
} }
template<typename ESXRecordT> template<typename ESXRecordT, typename IdAccessorT>
const RecordBase& IdCollection<ESXRecordT>::getRecord (const std::string& id) const int IdCollection<ESXRecordT, IdAccessorT>::getAppendIndex (UniversalId::Type type) const
{
return static_cast<int> (mRecords.size());
}
template<typename ESXRecordT, typename IdAccessorT>
const Record<ESXRecordT>& IdCollection<ESXRecordT, IdAccessorT>::getRecord (const std::string& id) const
{ {
int index = getIndex (id); int index = getIndex (id);
return mRecords.at (index); return mRecords.at (index);
} }
template<typename ESXRecordT, typename IdAccessorT>
const Record<ESXRecordT>& IdCollection<ESXRecordT, IdAccessorT>::getRecord (int index) const
{
return mRecords.at (index);
}
} }
#endif #endif

View File

@ -96,9 +96,28 @@ bool CSMWorld::IdTable::removeRows (int row, int count, const QModelIndex& paren
return true; return true;
} }
QModelIndex CSMWorld::IdTable::index (int row, int column, const QModelIndex& parent) const
{
if (parent.isValid())
return QModelIndex();
if (row<0 || row>=mIdCollection->getSize())
return QModelIndex();
if (column<0 || column>=mIdCollection->getColumns())
return QModelIndex();
return createIndex (row, column);
}
QModelIndex CSMWorld::IdTable::parent (const QModelIndex& index) const
{
return QModelIndex();
}
void CSMWorld::IdTable::addRecord (const std::string& id) void CSMWorld::IdTable::addRecord (const std::string& id)
{ {
int index = mIdCollection->getSize(); int index = mIdCollection->getAppendIndex();
beginInsertRows (QModelIndex(), index, index); beginInsertRows (QModelIndex(), index, index);
@ -112,13 +131,13 @@ QModelIndex CSMWorld::IdTable::getModelIndex (const std::string& id, int column)
return index (mIdCollection->getIndex (id), column); return index (mIdCollection->getIndex (id), column);
} }
void CSMWorld::IdTable::setRecord (const RecordBase& record) void CSMWorld::IdTable::setRecord (const std::string& id, const RecordBase& record)
{ {
int index = mIdCollection->searchId (mIdCollection->getId (record)); int index = mIdCollection->searchId (id);
if (index==-1) if (index==-1)
{ {
int index = mIdCollection->getSize(); int index = mIdCollection->getAppendIndex();
beginInsertRows (QModelIndex(), index, index); beginInsertRows (QModelIndex(), index, index);

View File

@ -1,14 +1,14 @@
#ifndef CSM_WOLRD_IDTABLE_H #ifndef CSM_WOLRD_IDTABLE_H
#define CSM_WOLRD_IDTABLE_H #define CSM_WOLRD_IDTABLE_H
#include <QAbstractTableModel> #include <QAbstractItemModel>
namespace CSMWorld namespace CSMWorld
{ {
class IdCollectionBase; class IdCollectionBase;
class RecordBase; class RecordBase;
class IdTable : public QAbstractTableModel class IdTable : public QAbstractItemModel
{ {
Q_OBJECT Q_OBJECT
@ -39,11 +39,16 @@ namespace CSMWorld
virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()); virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex());
virtual QModelIndex index (int row, int column, const QModelIndex& parent = QModelIndex())
const;
virtual QModelIndex parent (const QModelIndex& index) const;
void addRecord (const std::string& id); void addRecord (const std::string& id);
QModelIndex getModelIndex (const std::string& id, int column) const; QModelIndex getModelIndex (const std::string& id, int column) const;
void setRecord (const RecordBase& record); void setRecord (const std::string& id, const RecordBase& record);
///< Add record or overwrite existing recrod. ///< Add record or overwrite existing recrod.
const RecordBase& getRecord (const std::string& id) const; const RecordBase& getRecord (const std::string& id) const;

View File

@ -22,6 +22,9 @@ namespace CSMWorld
virtual RecordBase *clone() const = 0; virtual RecordBase *clone() const = 0;
virtual void assign (const RecordBase& record) = 0;
///< Will throw an exception if the types don't match.
bool isDeleted() const; bool isDeleted() const;
bool isErased() const; bool isErased() const;
@ -37,9 +40,14 @@ namespace CSMWorld
virtual RecordBase *clone() const; virtual RecordBase *clone() const;
virtual void assign (const RecordBase& record);
const ESXRecordT& get() const; const ESXRecordT& get() const;
///< Throws an exception, if the record is deleted. ///< Throws an exception, if the record is deleted.
ESXRecordT& get();
///< Throws an exception, if the record is deleted.
const ESXRecordT& getBase() const; const ESXRecordT& getBase() const;
///< Throws an exception, if the record is deleted. Returns modified, if there is no base. ///< Throws an exception, if the record is deleted. Returns modified, if there is no base.
@ -56,13 +64,28 @@ namespace CSMWorld
return new Record<ESXRecordT> (*this); return new Record<ESXRecordT> (*this);
} }
template <typename ESXRecordT>
void Record<ESXRecordT>::assign (const RecordBase& record)
{
*this = dynamic_cast<const Record<ESXRecordT>& > (record);
}
template <typename ESXRecordT> template <typename ESXRecordT>
const ESXRecordT& Record<ESXRecordT>::get() const const ESXRecordT& Record<ESXRecordT>::get() const
{ {
if (mState==State_Erased) if (mState==State_Erased)
throw std::logic_error ("attempt to access a deleted record"); throw std::logic_error ("attempt to access a deleted record");
return mState==State_BaseOnly ? mBase : mModified; return mState==State_BaseOnly || mState==State_Deleted ? mBase : mModified;
}
template <typename ESXRecordT>
ESXRecordT& Record<ESXRecordT>::get()
{
if (mState==State_Erased)
throw std::logic_error ("attempt to access a deleted record");
return mState==State_BaseOnly || mState==State_Deleted ? mBase : mModified;
} }
template <typename ESXRecordT> template <typename ESXRecordT>
@ -83,7 +106,7 @@ namespace CSMWorld
mModified = modified; mModified = modified;
if (mState!=State_ModifiedOnly) if (mState!=State_ModifiedOnly)
mState = mBase==mModified ? State_BaseOnly : State_Modified; mState = State_Modified;
} }
template <typename ESXRecordT> template <typename ESXRecordT>

View File

@ -0,0 +1,6 @@
#include "refidadapter.hpp"
CSMWorld::RefIdAdapter::RefIdAdapter() {}
CSMWorld::RefIdAdapter::~RefIdAdapter() {}

View File

@ -0,0 +1,37 @@
#ifndef CSM_WOLRD_REFIDADAPTER_H
#define CSM_WOLRD_REFIDADAPTER_H
#include <string>
class QVariant;
namespace CSMWorld
{
class RefIdColumn;
class RefIdData;
class RecordBase;
class RefIdAdapter
{
// not implemented
RefIdAdapter (const RefIdAdapter&);
RefIdAdapter& operator= (const RefIdAdapter&);
public:
RefIdAdapter();
virtual ~RefIdAdapter();
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int idnex)
const = 0;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const = 0;
///< If the data type does not match an exception is thrown.
virtual std::string getId (const RecordBase& record) const = 0;
};
}
#endif

View File

@ -0,0 +1,575 @@
#include "refidadapterimp.hpp"
CSMWorld::PotionRefIdAdapter::PotionRefIdAdapter (const InventoryColumns& columns,
const RefIdColumn *autoCalc)
: InventoryRefIdAdapter<ESM::Potion> (UniversalId::Type_Potion, columns),
mAutoCalc (autoCalc)
{}
QVariant CSMWorld::PotionRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<ESM::Potion>& record = static_cast<const Record<ESM::Potion>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Potion)));
if (column==mAutoCalc)
return record.get().mData.mAutoCalc!=0;
return InventoryRefIdAdapter<ESM::Potion>::getData (column, data, index);
}
void CSMWorld::PotionRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Potion>& record = static_cast<Record<ESM::Potion>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Potion)));
if (column==mAutoCalc)
record.get().mData.mAutoCalc = value.toInt();
else
InventoryRefIdAdapter<ESM::Potion>::setData (column, data, index, value);
}
CSMWorld::ApparatusRefIdAdapter::ApparatusRefIdAdapter (const InventoryColumns& columns,
const RefIdColumn *type, const RefIdColumn *quality)
: InventoryRefIdAdapter<ESM::Apparatus> (UniversalId::Type_Apparatus, columns),
mType (type), mQuality (quality)
{}
QVariant CSMWorld::ApparatusRefIdAdapter::getData (const RefIdColumn *column,
const RefIdData& data, int index) const
{
const Record<ESM::Apparatus>& record = static_cast<const Record<ESM::Apparatus>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Apparatus)));
if (column==mType)
return record.get().mData.mType;
if (column==mQuality)
return record.get().mData.mQuality;
return InventoryRefIdAdapter<ESM::Apparatus>::getData (column, data, index);
}
void CSMWorld::ApparatusRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Apparatus>& record = static_cast<Record<ESM::Apparatus>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Apparatus)));
if (column==mType)
record.get().mData.mType = value.toInt();
else if (column==mQuality)
record.get().mData.mQuality = value.toFloat();
else
InventoryRefIdAdapter<ESM::Apparatus>::setData (column, data, index, value);
}
CSMWorld::ArmorRefIdAdapter::ArmorRefIdAdapter (const EnchantableColumns& columns,
const RefIdColumn *type, const RefIdColumn *health, const RefIdColumn *armor)
: EnchantableRefIdAdapter<ESM::Armor> (UniversalId::Type_Armor, columns),
mType (type), mHealth (health), mArmor (armor)
{}
QVariant CSMWorld::ArmorRefIdAdapter::getData (const RefIdColumn *column,
const RefIdData& data, int index) const
{
const Record<ESM::Armor>& record = static_cast<const Record<ESM::Armor>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Armor)));
if (column==mType)
return record.get().mData.mType;
if (column==mHealth)
return record.get().mData.mHealth;
if (column==mArmor)
return record.get().mData.mArmor;
return EnchantableRefIdAdapter<ESM::Armor>::getData (column, data, index);
}
void CSMWorld::ArmorRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Armor>& record = static_cast<Record<ESM::Armor>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Armor)));
if (column==mType)
record.get().mData.mType = value.toInt();
else if (column==mHealth)
record.get().mData.mHealth = value.toInt();
else if (column==mArmor)
record.get().mData.mArmor = value.toInt();
else
EnchantableRefIdAdapter<ESM::Armor>::setData (column, data, index, value);
}
CSMWorld::BookRefIdAdapter::BookRefIdAdapter (const EnchantableColumns& columns,
const RefIdColumn *scroll, const RefIdColumn *skill)
: EnchantableRefIdAdapter<ESM::Book> (UniversalId::Type_Book, columns),
mScroll (scroll), mSkill (skill)
{}
QVariant CSMWorld::BookRefIdAdapter::getData (const RefIdColumn *column,
const RefIdData& data, int index) const
{
const Record<ESM::Book>& record = static_cast<const Record<ESM::Book>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Book)));
if (column==mScroll)
return record.get().mData.mIsScroll!=0;
if (column==mSkill)
return record.get().mData.mSkillID;
return EnchantableRefIdAdapter<ESM::Book>::getData (column, data, index);
}
void CSMWorld::BookRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Book>& record = static_cast<Record<ESM::Book>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Book)));
if (column==mScroll)
record.get().mData.mIsScroll = value.toInt();
else if (column==mSkill)
record.get().mData.mSkillID = value.toInt();
else
EnchantableRefIdAdapter<ESM::Book>::setData (column, data, index, value);
}
CSMWorld::ClothingRefIdAdapter::ClothingRefIdAdapter (const EnchantableColumns& columns,
const RefIdColumn *type)
: EnchantableRefIdAdapter<ESM::Clothing> (UniversalId::Type_Clothing, columns), mType (type)
{}
QVariant CSMWorld::ClothingRefIdAdapter::getData (const RefIdColumn *column,
const RefIdData& data, int index) const
{
const Record<ESM::Clothing>& record = static_cast<const Record<ESM::Clothing>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Clothing)));
if (column==mType)
return record.get().mData.mType;
return EnchantableRefIdAdapter<ESM::Clothing>::getData (column, data, index);
}
void CSMWorld::ClothingRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Clothing>& record = static_cast<Record<ESM::Clothing>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Clothing)));
if (column==mType)
record.get().mData.mType = value.toInt();
else
EnchantableRefIdAdapter<ESM::Clothing>::setData (column, data, index, value);
}
CSMWorld::ContainerRefIdAdapter::ContainerRefIdAdapter (const NameColumns& columns,
const RefIdColumn *weight, const RefIdColumn *organic, const RefIdColumn *respawn)
: NameRefIdAdapter<ESM::Container> (UniversalId::Type_Container, columns), mWeight (weight),
mOrganic (organic), mRespawn (respawn)
{}
QVariant CSMWorld::ContainerRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<ESM::Container>& record = static_cast<const Record<ESM::Container>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Container)));
if (column==mWeight)
return record.get().mWeight;
if (column==mOrganic)
return (record.get().mFlags & ESM::Container::Organic)!=0;
if (column==mRespawn)
return (record.get().mFlags & ESM::Container::Respawn)!=0;
return NameRefIdAdapter<ESM::Container>::getData (column, data, index);
}
void CSMWorld::ContainerRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Container>& record = static_cast<Record<ESM::Container>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Container)));
if (column==mWeight)
record.get().mWeight = value.toFloat();
else if (column==mOrganic)
{
if (value.toInt())
record.get().mFlags |= ESM::Container::Organic;
else
record.get().mFlags &= ~ESM::Container::Organic;
}
else if (column==mRespawn)
{
if (value.toInt())
record.get().mFlags |= ESM::Container::Respawn;
else
record.get().mFlags &= ~ESM::Container::Respawn;
}
else
NameRefIdAdapter<ESM::Container>::setData (column, data, index, value);
}
CSMWorld::CreatureColumns::CreatureColumns (const ActorColumns& actorColumns)
: ActorColumns (actorColumns)
{}
CSMWorld::CreatureRefIdAdapter::CreatureRefIdAdapter (const CreatureColumns& columns)
: ActorRefIdAdapter<ESM::Creature> (UniversalId::Type_Creature, columns), mColumns (columns)
{}
QVariant CSMWorld::CreatureRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<ESM::Creature>& record = static_cast<const Record<ESM::Creature>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature)));
if (column==mColumns.mType)
return record.get().mData.mType;
if (column==mColumns.mSoul)
return record.get().mData.mSoul;
if (column==mColumns.mScale)
return record.get().mScale;
if (column==mColumns.mOriginal)
return QString::fromUtf8 (record.get().mOriginal.c_str());
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mColumns.mFlags.find (column);
if (iter!=mColumns.mFlags.end())
return (record.get().mFlags & iter->second)!=0;
return ActorRefIdAdapter<ESM::Creature>::getData (column, data, index);
}
void CSMWorld::CreatureRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Creature>& record = static_cast<Record<ESM::Creature>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature)));
if (column==mColumns.mType)
record.get().mData.mType = value.toInt();
else if (column==mColumns.mSoul)
record.get().mData.mSoul = value.toInt();
else if (column==mColumns.mScale)
record.get().mScale = value.toFloat();
else if (column==mColumns.mOriginal)
record.get().mOriginal = value.toString().toUtf8().constData();
else
{
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mColumns.mFlags.find (column);
if (iter!=mColumns.mFlags.end())
{
if (value.toInt()!=0)
record.get().mFlags |= iter->second;
else
record.get().mFlags &= ~iter->second;
}
else
ActorRefIdAdapter<ESM::Creature>::setData (column, data, index, value);
}
}
CSMWorld::DoorRefIdAdapter::DoorRefIdAdapter (const NameColumns& columns,
const RefIdColumn *openSound, const RefIdColumn *closeSound)
: NameRefIdAdapter<ESM::Door> (UniversalId::Type_Door, columns), mOpenSound (openSound),
mCloseSound (closeSound)
{}
QVariant CSMWorld::DoorRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<ESM::Door>& record = static_cast<const Record<ESM::Door>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Door)));
if (column==mOpenSound)
return QString::fromUtf8 (record.get().mOpenSound.c_str());
if (column==mCloseSound)
return QString::fromUtf8 (record.get().mCloseSound.c_str());
return NameRefIdAdapter<ESM::Door>::getData (column, data, index);
}
void CSMWorld::DoorRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Door>& record = static_cast<Record<ESM::Door>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Door)));
if (column==mOpenSound)
record.get().mOpenSound = value.toString().toUtf8().constData();
else if (column==mCloseSound)
record.get().mCloseSound = value.toString().toUtf8().constData();
else
NameRefIdAdapter<ESM::Door>::setData (column, data, index, value);
}
CSMWorld::LightColumns::LightColumns (const InventoryColumns& columns)
: InventoryColumns (columns) {}
CSMWorld::LightRefIdAdapter::LightRefIdAdapter (const LightColumns& columns)
: InventoryRefIdAdapter<ESM::Light> (UniversalId::Type_Light, columns), mColumns (columns)
{}
QVariant CSMWorld::LightRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<ESM::Light>& record = static_cast<const Record<ESM::Light>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Light)));
if (column==mColumns.mTime)
return record.get().mData.mTime;
if (column==mColumns.mRadius)
return record.get().mData.mRadius;
if (column==mColumns.mColor)
return record.get().mData.mColor;
if (column==mColumns.mSound)
return QString::fromUtf8 (record.get().mSound.c_str());
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mColumns.mFlags.find (column);
if (iter!=mColumns.mFlags.end())
return (record.get().mData.mFlags & iter->second)!=0;
return InventoryRefIdAdapter<ESM::Light>::getData (column, data, index);
}
void CSMWorld::LightRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Light>& record = static_cast<Record<ESM::Light>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Light)));
if (column==mColumns.mTime)
record.get().mData.mTime = value.toInt();
else if (column==mColumns.mRadius)
record.get().mData.mRadius = value.toInt();
else if (column==mColumns.mColor)
record.get().mData.mColor = value.toInt();
else if (column==mColumns.mSound)
record.get().mSound = value.toString().toUtf8().constData();
else
{
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mColumns.mFlags.find (column);
if (iter!=mColumns.mFlags.end())
{
if (value.toInt()!=0)
record.get().mData.mFlags |= iter->second;
else
record.get().mData.mFlags &= ~iter->second;
}
else
InventoryRefIdAdapter<ESM::Light>::setData (column, data, index, value);
}
}
CSMWorld::MiscRefIdAdapter::MiscRefIdAdapter (const InventoryColumns& columns, const RefIdColumn *key)
: InventoryRefIdAdapter<ESM::Miscellaneous> (UniversalId::Type_Miscellaneous, columns), mKey (key)
{}
QVariant CSMWorld::MiscRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<ESM::Miscellaneous>& record = static_cast<const Record<ESM::Miscellaneous>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Miscellaneous)));
if (column==mKey)
return record.get().mData.mIsKey!=0;
return InventoryRefIdAdapter<ESM::Miscellaneous>::getData (column, data, index);
}
void CSMWorld::MiscRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Miscellaneous>& record = static_cast<Record<ESM::Miscellaneous>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Miscellaneous)));
if (column==mKey)
record.get().mData.mIsKey = value.toInt();
else
InventoryRefIdAdapter<ESM::Miscellaneous>::setData (column, data, index, value);
}
CSMWorld::NpcColumns::NpcColumns (const ActorColumns& actorColumns) : ActorColumns (actorColumns) {}
CSMWorld::NpcRefIdAdapter::NpcRefIdAdapter (const NpcColumns& columns)
: ActorRefIdAdapter<ESM::NPC> (UniversalId::Type_Npc, columns), mColumns (columns)
{}
QVariant CSMWorld::NpcRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data, int index)
const
{
const Record<ESM::NPC>& record = static_cast<const Record<ESM::NPC>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc)));
if (column==mColumns.mRace)
return QString::fromUtf8 (record.get().mRace.c_str());
if (column==mColumns.mClass)
return QString::fromUtf8 (record.get().mClass.c_str());
if (column==mColumns.mFaction)
return QString::fromUtf8 (record.get().mFaction.c_str());
if (column==mColumns.mHair)
return QString::fromUtf8 (record.get().mHair.c_str());
if (column==mColumns.mHead)
return QString::fromUtf8 (record.get().mHead.c_str());
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mColumns.mFlags.find (column);
if (iter!=mColumns.mFlags.end())
return (record.get().mFlags & iter->second)!=0;
return ActorRefIdAdapter<ESM::NPC>::getData (column, data, index);
}
void CSMWorld::NpcRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::NPC>& record = static_cast<Record<ESM::NPC>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc)));
if (column==mColumns.mRace)
record.get().mRace = value.toString().toUtf8().constData();
else if (column==mColumns.mClass)
record.get().mClass = value.toString().toUtf8().constData();
else if (column==mColumns.mFaction)
record.get().mFaction = value.toString().toUtf8().constData();
else if (column==mColumns.mHair)
record.get().mHair = value.toString().toUtf8().constData();
else if (column==mColumns.mHead)
record.get().mHead = value.toString().toUtf8().constData();
else
{
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mColumns.mFlags.find (column);
if (iter!=mColumns.mFlags.end())
{
if (value.toInt()!=0)
record.get().mFlags |= iter->second;
else
record.get().mFlags &= ~iter->second;
}
else
ActorRefIdAdapter<ESM::NPC>::setData (column, data, index, value);
}
}
CSMWorld::WeaponColumns::WeaponColumns (const EnchantableColumns& columns)
: EnchantableColumns (columns) {}
CSMWorld::WeaponRefIdAdapter::WeaponRefIdAdapter (const WeaponColumns& columns)
: EnchantableRefIdAdapter<ESM::Weapon> (UniversalId::Type_Weapon, columns), mColumns (columns)
{}
QVariant CSMWorld::WeaponRefIdAdapter::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<ESM::Weapon>& record = static_cast<const Record<ESM::Weapon>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Weapon)));
if (column==mColumns.mType)
return record.get().mData.mType;
if (column==mColumns.mHealth)
return record.get().mData.mHealth;
if (column==mColumns.mSpeed)
return record.get().mData.mSpeed;
if (column==mColumns.mReach)
return record.get().mData.mReach;
for (int i=0; i<2; ++i)
{
if (column==mColumns.mChop[i])
return record.get().mData.mChop[i];
if (column==mColumns.mSlash[i])
return record.get().mData.mSlash[i];
if (column==mColumns.mThrust[i])
return record.get().mData.mThrust[i];
}
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mColumns.mFlags.find (column);
if (iter!=mColumns.mFlags.end())
return (record.get().mData.mFlags & iter->second)!=0;
return EnchantableRefIdAdapter<ESM::Weapon>::getData (column, data, index);
}
void CSMWorld::WeaponRefIdAdapter::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<ESM::Weapon>& record = static_cast<Record<ESM::Weapon>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Weapon)));
if (column==mColumns.mType)
record.get().mData.mType = value.toInt();
else if (column==mColumns.mHealth)
record.get().mData.mHealth = value.toInt();
else if (column==mColumns.mSpeed)
record.get().mData.mSpeed = value.toFloat();
else if (column==mColumns.mReach)
record.get().mData.mReach = value.toFloat();
else if (column==mColumns.mChop[0])
record.get().mData.mChop[0] = value.toInt();
else if (column==mColumns.mChop[1])
record.get().mData.mChop[1] = value.toInt();
else if (column==mColumns.mSlash[0])
record.get().mData.mSlash[0] = value.toInt();
else if (column==mColumns.mSlash[1])
record.get().mData.mSlash[1] = value.toInt();
else if (column==mColumns.mThrust[0])
record.get().mData.mThrust[0] = value.toInt();
else if (column==mColumns.mThrust[1])
record.get().mData.mThrust[1] = value.toInt();
else
{
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mColumns.mFlags.find (column);
if (iter!=mColumns.mFlags.end())
{
if (value.toInt()!=0)
record.get().mData.mFlags |= iter->second;
else
record.get().mData.mFlags &= ~iter->second;
}
else
EnchantableRefIdAdapter<ESM::Weapon>::setData (column, data, index, value);
}
}

View File

@ -0,0 +1,766 @@
#ifndef CSM_WOLRD_REFIDADAPTERIMP_H
#define CSM_WOLRD_REFIDADAPTERIMP_H
#include <map>
#include <QVariant>
#include <components/esm/loadalch.hpp>
#include <components/esm/loadappa.hpp>
#include "record.hpp"
#include "refiddata.hpp"
#include "universalid.hpp"
#include "refidadapter.hpp"
namespace CSMWorld
{
struct BaseColumns
{
const RefIdColumn *mId;
const RefIdColumn *mModified;
const RefIdColumn *mType;
};
/// \brief Base adapter for all refereceable record types
template<typename RecordT>
class BaseRefIdAdapter : public RefIdAdapter
{
UniversalId::Type mType;
BaseColumns mBase;
public:
BaseRefIdAdapter (UniversalId::Type type, const BaseColumns& base);
virtual std::string getId (const RecordBase& record) const;
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
UniversalId::Type getType() const;
};
template<typename RecordT>
BaseRefIdAdapter<RecordT>::BaseRefIdAdapter (UniversalId::Type type, const BaseColumns& base)
: mType (type), mBase (base)
{}
template<typename RecordT>
std::string BaseRefIdAdapter<RecordT>::getId (const RecordBase& record) const
{
return dynamic_cast<const Record<RecordT>&> (record).get().mId;
}
template<typename RecordT>
QVariant BaseRefIdAdapter<RecordT>::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<RecordT>& record = static_cast<const Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, mType)));
if (column==mBase.mId)
return QString::fromUtf8 (record.get().mId.c_str());
if (column==mBase.mModified)
{
if (record.mState==Record<RecordT>::State_Erased)
return static_cast<int> (Record<RecordT>::State_Deleted);
return static_cast<int> (record.mState);
}
if (column==mBase.mType)
return static_cast<int> (mType);
return QVariant();
}
template<typename RecordT>
void BaseRefIdAdapter<RecordT>::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, mType)));
if (column==mBase.mModified)
record.mState = static_cast<RecordBase::State> (value.toInt());
}
template<typename RecordT>
UniversalId::Type BaseRefIdAdapter<RecordT>::getType() const
{
return mType;
}
struct ModelColumns : public BaseColumns
{
const RefIdColumn *mModel;
ModelColumns (const BaseColumns& base) : BaseColumns (base) {}
};
/// \brief Adapter for IDs with models (all but levelled lists)
template<typename RecordT>
class ModelRefIdAdapter : public BaseRefIdAdapter<RecordT>
{
ModelColumns mModel;
public:
ModelRefIdAdapter (UniversalId::Type type, const ModelColumns& columns);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
template<typename RecordT>
ModelRefIdAdapter<RecordT>::ModelRefIdAdapter (UniversalId::Type type, const ModelColumns& columns)
: BaseRefIdAdapter<RecordT> (type, columns), mModel (columns)
{}
template<typename RecordT>
QVariant ModelRefIdAdapter<RecordT>::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<RecordT>& record = static_cast<const Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mModel.mModel)
return QString::fromUtf8 (record.get().mModel.c_str());
return BaseRefIdAdapter<RecordT>::getData (column, data, index);
}
template<typename RecordT>
void ModelRefIdAdapter<RecordT>::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mModel.mModel)
record.get().mModel = value.toString().toUtf8().constData();
else
BaseRefIdAdapter<RecordT>::setData (column, data, index, value);
}
struct NameColumns : public ModelColumns
{
const RefIdColumn *mName;
const RefIdColumn *mScript;
NameColumns (const ModelColumns& base) : ModelColumns (base) {}
};
/// \brief Adapter for IDs with names (all but levelled lists and statics)
template<typename RecordT>
class NameRefIdAdapter : public ModelRefIdAdapter<RecordT>
{
NameColumns mName;
public:
NameRefIdAdapter (UniversalId::Type type, const NameColumns& columns);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
template<typename RecordT>
NameRefIdAdapter<RecordT>::NameRefIdAdapter (UniversalId::Type type, const NameColumns& columns)
: ModelRefIdAdapter<RecordT> (type, columns), mName (columns)
{}
template<typename RecordT>
QVariant NameRefIdAdapter<RecordT>::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<RecordT>& record = static_cast<const Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mName.mName)
return QString::fromUtf8 (record.get().mName.c_str());
if (column==mName.mScript)
return QString::fromUtf8 (record.get().mScript.c_str());
return ModelRefIdAdapter<RecordT>::getData (column, data, index);
}
template<typename RecordT>
void NameRefIdAdapter<RecordT>::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mName.mName)
record.get().mName = value.toString().toUtf8().constData();
else if (column==mName.mScript)
record.get().mScript = value.toString().toUtf8().constData();
else
ModelRefIdAdapter<RecordT>::setData (column, data, index, value);
}
struct InventoryColumns : public NameColumns
{
const RefIdColumn *mIcon;
const RefIdColumn *mWeight;
const RefIdColumn *mValue;
InventoryColumns (const NameColumns& base) : NameColumns (base) {}
};
/// \brief Adapter for IDs that can go into an inventory
template<typename RecordT>
class InventoryRefIdAdapter : public NameRefIdAdapter<RecordT>
{
InventoryColumns mInventory;
public:
InventoryRefIdAdapter (UniversalId::Type type, const InventoryColumns& columns);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
template<typename RecordT>
InventoryRefIdAdapter<RecordT>::InventoryRefIdAdapter (UniversalId::Type type,
const InventoryColumns& columns)
: NameRefIdAdapter<RecordT> (type, columns), mInventory (columns)
{}
template<typename RecordT>
QVariant InventoryRefIdAdapter<RecordT>::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<RecordT>& record = static_cast<const Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mInventory.mIcon)
return QString::fromUtf8 (record.get().mIcon.c_str());
if (column==mInventory.mWeight)
return record.get().mData.mWeight;
if (column==mInventory.mValue)
return record.get().mData.mValue;
return NameRefIdAdapter<RecordT>::getData (column, data, index);
}
template<typename RecordT>
void InventoryRefIdAdapter<RecordT>::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mInventory.mIcon)
record.get().mIcon = value.toString().toUtf8().constData();
else if (column==mInventory.mWeight)
record.get().mData.mWeight = value.toFloat();
else if (column==mInventory.mValue)
record.get().mData.mValue = value.toInt();
else
NameRefIdAdapter<RecordT>::setData (column, data, index, value);
}
class PotionRefIdAdapter : public InventoryRefIdAdapter<ESM::Potion>
{
const RefIdColumn *mAutoCalc;
public:
PotionRefIdAdapter (const InventoryColumns& columns, const RefIdColumn *autoCalc);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
struct EnchantableColumns : public InventoryColumns
{
const RefIdColumn *mEnchantment;
const RefIdColumn *mEnchantmentPoints;
EnchantableColumns (const InventoryColumns& base) : InventoryColumns (base) {}
};
/// \brief Adapter for enchantable IDs
template<typename RecordT>
class EnchantableRefIdAdapter : public InventoryRefIdAdapter<RecordT>
{
EnchantableColumns mEnchantable;
public:
EnchantableRefIdAdapter (UniversalId::Type type, const EnchantableColumns& columns);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
template<typename RecordT>
EnchantableRefIdAdapter<RecordT>::EnchantableRefIdAdapter (UniversalId::Type type,
const EnchantableColumns& columns)
: InventoryRefIdAdapter<RecordT> (type, columns), mEnchantable (columns)
{}
template<typename RecordT>
QVariant EnchantableRefIdAdapter<RecordT>::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<RecordT>& record = static_cast<const Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mEnchantable.mEnchantment)
return QString::fromUtf8 (record.get().mEnchant.c_str());
if (column==mEnchantable.mEnchantmentPoints)
return static_cast<int> (record.get().mData.mEnchant);
return InventoryRefIdAdapter<RecordT>::getData (column, data, index);
}
template<typename RecordT>
void EnchantableRefIdAdapter<RecordT>::setData (const RefIdColumn *column, RefIdData& data,
int index, const QVariant& value) const
{
Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mEnchantable.mEnchantment)
record.get().mEnchant = value.toString().toUtf8().constData();
else if (column==mEnchantable.mEnchantmentPoints)
record.get().mData.mEnchant = value.toInt();
else
InventoryRefIdAdapter<RecordT>::setData (column, data, index, value);
}
struct ToolColumns : public InventoryColumns
{
const RefIdColumn *mQuality;
const RefIdColumn *mUses;
ToolColumns (const InventoryColumns& base) : InventoryColumns (base) {}
};
/// \brief Adapter for tools with limited uses IDs (lockpick, repair, probes)
template<typename RecordT>
class ToolRefIdAdapter : public InventoryRefIdAdapter<RecordT>
{
ToolColumns mTools;
public:
ToolRefIdAdapter (UniversalId::Type type, const ToolColumns& columns);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
template<typename RecordT>
ToolRefIdAdapter<RecordT>::ToolRefIdAdapter (UniversalId::Type type, const ToolColumns& columns)
: InventoryRefIdAdapter<RecordT> (type, columns), mTools (columns)
{}
template<typename RecordT>
QVariant ToolRefIdAdapter<RecordT>::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<RecordT>& record = static_cast<const Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mTools.mQuality)
return record.get().mData.mQuality;
if (column==mTools.mUses)
return record.get().mData.mUses;
return InventoryRefIdAdapter<RecordT>::getData (column, data, index);
}
template<typename RecordT>
void ToolRefIdAdapter<RecordT>::setData (const RefIdColumn *column, RefIdData& data,
int index, const QVariant& value) const
{
Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mTools.mQuality)
record.get().mData.mQuality = value.toFloat();
else if (column==mTools.mUses)
record.get().mData.mUses = value.toInt();
else
InventoryRefIdAdapter<RecordT>::setData (column, data, index, value);
}
struct ActorColumns : public NameColumns
{
const RefIdColumn *mHasAi;
const RefIdColumn *mHello;
const RefIdColumn *mFlee;
const RefIdColumn *mFight;
const RefIdColumn *mAlarm;
std::map<const RefIdColumn *, unsigned int> mServices;
ActorColumns (const NameColumns& base) : NameColumns (base) {}
};
/// \brief Adapter for actor IDs (handles common AI functionality)
template<typename RecordT>
class ActorRefIdAdapter : public NameRefIdAdapter<RecordT>
{
ActorColumns mActors;
public:
ActorRefIdAdapter (UniversalId::Type type, const ActorColumns& columns);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
template<typename RecordT>
ActorRefIdAdapter<RecordT>::ActorRefIdAdapter (UniversalId::Type type,
const ActorColumns& columns)
: NameRefIdAdapter<RecordT> (type, columns), mActors (columns)
{}
template<typename RecordT>
QVariant ActorRefIdAdapter<RecordT>::getData (const RefIdColumn *column, const RefIdData& data,
int index) const
{
const Record<RecordT>& record = static_cast<const Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mActors.mHasAi)
return record.get().mHasAI!=0;
if (column==mActors.mHello)
return record.get().mAiData.mHello;
if (column==mActors.mFlee)
return record.get().mAiData.mFlee;
if (column==mActors.mFight)
return record.get().mAiData.mFight;
if (column==mActors.mAlarm)
return record.get().mAiData.mAlarm;
std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mActors.mServices.find (column);
if (iter!=mActors.mServices.end())
return (record.get().mAiData.mServices & iter->second)!=0;
return NameRefIdAdapter<RecordT>::getData (column, data, index);
}
template<typename RecordT>
void ActorRefIdAdapter<RecordT>::setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const
{
Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
if (column==mActors.mHasAi)
record.get().mHasAI = value.toInt();
else if (column==mActors.mHello)
record.get().mAiData.mHello = value.toInt();
else if (column==mActors.mFlee)
record.get().mAiData.mFlee = value.toInt();
else if (column==mActors.mFight)
record.get().mAiData.mFight = value.toInt();
else if (column==mActors.mAlarm)
record.get().mAiData.mAlarm = value.toInt();
else
{
typename std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
mActors.mServices.find (column);
if (iter!=mActors.mServices.end())
{
if (value.toInt()!=0)
record.get().mAiData.mServices |= iter->second;
else
record.get().mAiData.mServices &= ~iter->second;
}
else
NameRefIdAdapter<RecordT>::setData (column, data, index, value);
}
}
class ApparatusRefIdAdapter : public InventoryRefIdAdapter<ESM::Apparatus>
{
const RefIdColumn *mType;
const RefIdColumn *mQuality;
public:
ApparatusRefIdAdapter (const InventoryColumns& columns, const RefIdColumn *type,
const RefIdColumn *quality);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
class ArmorRefIdAdapter : public EnchantableRefIdAdapter<ESM::Armor>
{
const RefIdColumn *mType;
const RefIdColumn *mHealth;
const RefIdColumn *mArmor;
public:
ArmorRefIdAdapter (const EnchantableColumns& columns, const RefIdColumn *type,
const RefIdColumn *health, const RefIdColumn *armor);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
class BookRefIdAdapter : public EnchantableRefIdAdapter<ESM::Book>
{
const RefIdColumn *mScroll;
const RefIdColumn *mSkill;
public:
BookRefIdAdapter (const EnchantableColumns& columns, const RefIdColumn *scroll,
const RefIdColumn *skill);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
class ClothingRefIdAdapter : public EnchantableRefIdAdapter<ESM::Clothing>
{
const RefIdColumn *mType;
public:
ClothingRefIdAdapter (const EnchantableColumns& columns, const RefIdColumn *type);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
class ContainerRefIdAdapter : public NameRefIdAdapter<ESM::Container>
{
const RefIdColumn *mWeight;
const RefIdColumn *mOrganic;
const RefIdColumn *mRespawn;
public:
ContainerRefIdAdapter (const NameColumns& columns, const RefIdColumn *weight,
const RefIdColumn *organic, const RefIdColumn *respawn);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
struct CreatureColumns : public ActorColumns
{
std::map<const RefIdColumn *, unsigned int> mFlags;
const RefIdColumn *mType;
const RefIdColumn *mSoul;
const RefIdColumn *mScale;
const RefIdColumn *mOriginal;
CreatureColumns (const ActorColumns& actorColumns);
};
class CreatureRefIdAdapter : public ActorRefIdAdapter<ESM::Creature>
{
CreatureColumns mColumns;
public:
CreatureRefIdAdapter (const CreatureColumns& columns);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
class DoorRefIdAdapter : public NameRefIdAdapter<ESM::Door>
{
const RefIdColumn *mOpenSound;
const RefIdColumn *mCloseSound;
public:
DoorRefIdAdapter (const NameColumns& columns, const RefIdColumn *openSound,
const RefIdColumn *closeSound);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
struct LightColumns : public InventoryColumns
{
const RefIdColumn *mTime;
const RefIdColumn *mRadius;
const RefIdColumn *mColor;
const RefIdColumn *mSound;
std::map<const RefIdColumn *, unsigned int> mFlags;
LightColumns (const InventoryColumns& columns);
};
class LightRefIdAdapter : public InventoryRefIdAdapter<ESM::Light>
{
LightColumns mColumns;
public:
LightRefIdAdapter (const LightColumns& columns);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
class MiscRefIdAdapter : public InventoryRefIdAdapter<ESM::Miscellaneous>
{
const RefIdColumn *mKey;
public:
MiscRefIdAdapter (const InventoryColumns& columns, const RefIdColumn *key);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
struct NpcColumns : public ActorColumns
{
std::map<const RefIdColumn *, unsigned int> mFlags;
const RefIdColumn *mRace;
const RefIdColumn *mClass;
const RefIdColumn *mFaction;
const RefIdColumn *mHair;
const RefIdColumn *mHead;
NpcColumns (const ActorColumns& actorColumns);
};
class NpcRefIdAdapter : public ActorRefIdAdapter<ESM::NPC>
{
NpcColumns mColumns;
public:
NpcRefIdAdapter (const NpcColumns& columns);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
struct WeaponColumns : public EnchantableColumns
{
const RefIdColumn *mType;
const RefIdColumn *mHealth;
const RefIdColumn *mSpeed;
const RefIdColumn *mReach;
const RefIdColumn *mChop[2];
const RefIdColumn *mSlash[2];
const RefIdColumn *mThrust[2];
std::map<const RefIdColumn *, unsigned int> mFlags;
WeaponColumns (const EnchantableColumns& columns);
};
class WeaponRefIdAdapter : public EnchantableRefIdAdapter<ESM::Weapon>
{
WeaponColumns mColumns;
public:
WeaponRefIdAdapter (const WeaponColumns& columns);
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
const;
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
const QVariant& value) const;
///< If the data type does not match an exception is thrown.
};
}
#endif

View File

@ -0,0 +1,540 @@
#include "refidcollection.hpp"
#include <stdexcept>
#include "refidadapter.hpp"
#include "refidadapterimp.hpp"
CSMWorld::RefIdColumn::RefIdColumn (const std::string& title, Display displayType, int flag,
bool editable, bool userEditable)
: ColumnBase (title, displayType, flag), mEditable (editable), mUserEditable (userEditable)
{}
bool CSMWorld::RefIdColumn::isEditable() const
{
return mEditable;
}
bool CSMWorld::RefIdColumn::isUserEditable() const
{
return mUserEditable;
}
const CSMWorld::RefIdAdapter& CSMWorld::RefIdCollection::findAdaptor (UniversalId::Type type) const
{
std::map<UniversalId::Type, RefIdAdapter *>::const_iterator iter = mAdapters.find (type);
if (iter==mAdapters.end())
throw std::logic_error ("unsupported type in RefIdCollection");
return *iter->second;
}
CSMWorld::RefIdCollection::RefIdCollection()
{
BaseColumns baseColumns;
mColumns.push_back (RefIdColumn ("ID", ColumnBase::Display_String,
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
baseColumns.mId = &mColumns.back();
mColumns.push_back (RefIdColumn ("*", ColumnBase::Display_Integer,
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
baseColumns.mModified = &mColumns.back();
mColumns.push_back (RefIdColumn ("Type", ColumnBase::Display_Integer,
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
baseColumns.mType = &mColumns.back();
ModelColumns modelColumns (baseColumns);
mColumns.push_back (RefIdColumn ("Model", ColumnBase::Display_String));
modelColumns.mModel = &mColumns.back();
NameColumns nameColumns (modelColumns);
mColumns.push_back (RefIdColumn ("Name", ColumnBase::Display_String));
nameColumns.mName = &mColumns.back();
mColumns.push_back (RefIdColumn ("Script", ColumnBase::Display_String));
nameColumns.mScript = &mColumns.back();
InventoryColumns inventoryColumns (nameColumns);
mColumns.push_back (RefIdColumn ("Icon", ColumnBase::Display_String));
inventoryColumns.mIcon = &mColumns.back();
mColumns.push_back (RefIdColumn ("Weight", ColumnBase::Display_Float));
inventoryColumns.mWeight = &mColumns.back();
mColumns.push_back (RefIdColumn ("Value", ColumnBase::Display_Integer));
inventoryColumns.mValue = &mColumns.back();
EnchantableColumns enchantableColumns (inventoryColumns);
mColumns.push_back (RefIdColumn ("Enchantment", ColumnBase::Display_String));
enchantableColumns.mEnchantment = &mColumns.back();
mColumns.push_back (RefIdColumn ("Enchantment Points", ColumnBase::Display_Integer));
enchantableColumns.mEnchantmentPoints = &mColumns.back();
ToolColumns toolsColumns (inventoryColumns);
mColumns.push_back (RefIdColumn ("Quality", ColumnBase::Display_Float));
toolsColumns.mQuality = &mColumns.back();
mColumns.push_back (RefIdColumn ("Uses", ColumnBase::Display_Integer));
toolsColumns.mUses = &mColumns.back();
ActorColumns actorsColumns (nameColumns);
mColumns.push_back (RefIdColumn ("AI", ColumnBase::Display_Boolean));
actorsColumns.mHasAi = &mColumns.back();
mColumns.push_back (RefIdColumn ("AI Hello", ColumnBase::Display_Integer));
actorsColumns.mHello = &mColumns.back();
mColumns.push_back (RefIdColumn ("AI Flee", ColumnBase::Display_Integer));
actorsColumns.mFlee = &mColumns.back();
mColumns.push_back (RefIdColumn ("AI Fight", ColumnBase::Display_Integer));
actorsColumns.mFight = &mColumns.back();
mColumns.push_back (RefIdColumn ("AI Alarm", ColumnBase::Display_Integer));
actorsColumns.mAlarm = &mColumns.back();
static const struct
{
const char *mName;
unsigned int mFlag;
} sServiceTable[] =
{
{ "Buys Weapons", ESM::NPC::Weapon},
{ "Buys Armor", ESM::NPC::Armor},
{ "Buys Clothing", ESM::NPC::Clothing},
{ "Buys Books", ESM::NPC::Books},
{ "Buys Ingredients", ESM::NPC::Ingredients},
{ "Buys Lockpicks", ESM::NPC::Picks},
{ "Buys Probes", ESM::NPC::Probes},
{ "Buys Lights", ESM::NPC::Lights},
{ "Buys Apparati", ESM::NPC::Apparatus},
{ "Buys Repair Items", ESM::NPC::RepairItem},
{ "Buys Misc Items", ESM::NPC::Misc},
{ "Buys Potions", ESM::NPC::Potions},
{ "Buys Magic Items", ESM::NPC::MagicItems},
{ "Sells Spells", ESM::NPC::Spells},
{ "Trainer", ESM::NPC::Training},
{ "Spellmaking", ESM::NPC::Spellmaking},
{ "Enchanting Service", ESM::NPC::Enchanting},
{ "Repair Serivce", ESM::NPC::Repair},
{ 0, 0 }
};
for (int i=0; sServiceTable[i].mName; ++i)
{
mColumns.push_back (RefIdColumn (sServiceTable[i].mName, ColumnBase::Display_Boolean));
actorsColumns.mServices.insert (std::make_pair (&mColumns.back(), sServiceTable[i].mFlag));
}
mColumns.push_back (RefIdColumn ("Auto Calc", ColumnBase::Display_Boolean));
const RefIdColumn *autoCalc = &mColumns.back();
mColumns.push_back (RefIdColumn ("Apparatus Type", ColumnBase::Display_ApparatusType));
const RefIdColumn *apparatusType = &mColumns.back();
mColumns.push_back (RefIdColumn ("Armor Type", ColumnBase::Display_ArmorType));
const RefIdColumn *armorType = &mColumns.back();
mColumns.push_back (RefIdColumn ("Health", ColumnBase::Display_Integer));
const RefIdColumn *health = &mColumns.back();
mColumns.push_back (RefIdColumn ("Armor Value", ColumnBase::Display_Integer));
const RefIdColumn *armor = &mColumns.back();
mColumns.push_back (RefIdColumn ("Scroll", ColumnBase::Display_Boolean));
const RefIdColumn *scroll = &mColumns.back();
mColumns.push_back (RefIdColumn ("Attribute", ColumnBase::Display_Attribute));
const RefIdColumn *attribute = &mColumns.back();
mColumns.push_back (RefIdColumn ("Clothing Type", ColumnBase::Display_ClothingType));
const RefIdColumn *clothingType = &mColumns.back();
mColumns.push_back (RefIdColumn ("Weight Capacity", ColumnBase::Display_Float));
const RefIdColumn *weightCapacity = &mColumns.back();
mColumns.push_back (RefIdColumn ("Organic Container", ColumnBase::Display_Boolean));
const RefIdColumn *organic = &mColumns.back();
mColumns.push_back (RefIdColumn ("Respawn", ColumnBase::Display_Boolean));
const RefIdColumn *respawn = &mColumns.back();
CreatureColumns creatureColumns (actorsColumns);
mColumns.push_back (RefIdColumn ("Creature Type", ColumnBase::Display_CreatureType));
creatureColumns.mType = &mColumns.back();
mColumns.push_back (RefIdColumn ("Soul Points", ColumnBase::Display_Integer));
creatureColumns.mSoul = &mColumns.back();
mColumns.push_back (RefIdColumn ("Scale", ColumnBase::Display_Float));
creatureColumns.mScale = &mColumns.back();
mColumns.push_back (RefIdColumn ("Original Creature", ColumnBase::Display_String));
creatureColumns.mOriginal = &mColumns.back();
static const struct
{
const char *mName;
unsigned int mFlag;
} sCreatureFlagTable[] =
{
{ "Biped", ESM::Creature::Biped },
{ "Has Weapon", ESM::Creature::Weapon },
{ "No Movement", ESM::Creature::None },
{ "Swims", ESM::Creature::Swims },
{ "Flies", ESM::Creature::Flies },
{ "Walks", ESM::Creature::Walks },
{ "Essential", ESM::Creature::Essential },
{ "Skeleton Blood", ESM::Creature::Skeleton },
{ "Metal Blood", ESM::Creature::Metal },
{ 0, 0 }
};
// for re-use in NPC records
const RefIdColumn *essential = 0;
const RefIdColumn *skeletonBlood = 0;
const RefIdColumn *metalBlood = 0;
for (int i=0; sCreatureFlagTable[i].mName; ++i)
{
mColumns.push_back (RefIdColumn (sCreatureFlagTable[i].mName, ColumnBase::Display_Boolean));
creatureColumns.mFlags.insert (std::make_pair (&mColumns.back(), sCreatureFlagTable[i].mFlag));
switch (sCreatureFlagTable[i].mFlag)
{
case ESM::Creature::Essential: essential = &mColumns.back(); break;
case ESM::Creature::Skeleton: skeletonBlood = &mColumns.back(); break;
case ESM::Creature::Metal: metalBlood = &mColumns.back(); break;
}
}
creatureColumns.mFlags.insert (std::make_pair (respawn, ESM::Creature::Respawn));
mColumns.push_back (RefIdColumn ("Open Sound", ColumnBase::Display_String));
const RefIdColumn *openSound = &mColumns.back();
mColumns.push_back (RefIdColumn ("Close Sound", ColumnBase::Display_String));
const RefIdColumn *closeSound = &mColumns.back();
LightColumns lightColumns (inventoryColumns);
mColumns.push_back (RefIdColumn ("Duration", ColumnBase::Display_Integer));
lightColumns.mTime = &mColumns.back();
mColumns.push_back (RefIdColumn ("Radius", ColumnBase::Display_Integer));
lightColumns.mRadius = &mColumns.back();
mColumns.push_back (RefIdColumn ("Colour", ColumnBase::Display_Integer));
lightColumns.mColor = &mColumns.back();
mColumns.push_back (RefIdColumn ("Sound", ColumnBase::Display_String));
lightColumns.mSound = &mColumns.back();
static const struct
{
const char *mName;
unsigned int mFlag;
} sLightFlagTable[] =
{
{ "Dynamic", ESM::Light::Dynamic },
{ "Portable", ESM::Light::Carry },
{ "Negative Light", ESM::Light::Negative },
{ "Flickering", ESM::Light::Flicker },
{ "Slow Flickering", ESM::Light::Flicker },
{ "Pulsing", ESM::Light::Pulse },
{ "Slow Pulsing", ESM::Light::PulseSlow },
{ "Fire", ESM::Light::Fire },
{ "Off by default", ESM::Light::OffDefault },
{ 0, 0 }
};
for (int i=0; sLightFlagTable[i].mName; ++i)
{
mColumns.push_back (RefIdColumn (sLightFlagTable[i].mName, ColumnBase::Display_Boolean));
lightColumns.mFlags.insert (std::make_pair (&mColumns.back(), sLightFlagTable[i].mFlag));
}
mColumns.push_back (RefIdColumn ("Key", ColumnBase::Display_Boolean));
const RefIdColumn *key = &mColumns.back();
NpcColumns npcColumns (actorsColumns);
mColumns.push_back (RefIdColumn ("Race", ColumnBase::Display_String));
npcColumns.mRace = &mColumns.back();
mColumns.push_back (RefIdColumn ("Class", ColumnBase::Display_String));
npcColumns.mClass = &mColumns.back();
mColumns.push_back (RefIdColumn ("Faction", ColumnBase::Display_String));
npcColumns.mFaction = &mColumns.back();
mColumns.push_back (RefIdColumn ("Hair", ColumnBase::Display_String));
npcColumns.mHair = &mColumns.back();
mColumns.push_back (RefIdColumn ("Head", ColumnBase::Display_String));
npcColumns.mHead = &mColumns.back();
mColumns.push_back (RefIdColumn ("Female", ColumnBase::Display_Boolean));
npcColumns.mFlags.insert (std::make_pair (&mColumns.back(), ESM::NPC::Female));
npcColumns.mFlags.insert (std::make_pair (essential, ESM::NPC::Essential));
npcColumns.mFlags.insert (std::make_pair (respawn, ESM::NPC::Respawn));
npcColumns.mFlags.insert (std::make_pair (autoCalc, ESM::NPC::Autocalc));
npcColumns.mFlags.insert (std::make_pair (skeletonBlood, ESM::NPC::Skeleton));
npcColumns.mFlags.insert (std::make_pair (metalBlood, ESM::NPC::Metal));
WeaponColumns weaponColumns (enchantableColumns);
mColumns.push_back (RefIdColumn ("Weapon Type", ColumnBase::Display_WeaponType));
weaponColumns.mType = &mColumns.back();
weaponColumns.mHealth = health;
mColumns.push_back (RefIdColumn ("Weapon Speed", ColumnBase::Display_Float));
weaponColumns.mSpeed = &mColumns.back();
mColumns.push_back (RefIdColumn ("Weapon Reach", ColumnBase::Display_Float));
weaponColumns.mReach = &mColumns.back();
for (int i=0; i<2; ++i)
{
std::string suffix = i==0 ? "Min " : "Max ";
mColumns.push_back (RefIdColumn ("Chop" + suffix, ColumnBase::Display_Integer));
weaponColumns.mChop[i] = &mColumns.back();
mColumns.push_back (RefIdColumn ("Slash" + suffix, ColumnBase::Display_Integer));
weaponColumns.mSlash[i] = &mColumns.back();
mColumns.push_back (RefIdColumn ("Thrust" + suffix, ColumnBase::Display_Integer));
weaponColumns.mThrust[i] = &mColumns.back();
}
static const struct
{
const char *mName;
unsigned int mFlag;
} sWeaponFlagTable[] =
{
{ "Magical", ESM::Weapon::Magical },
{ "Silver", ESM::Weapon::Silver },
{ 0, 0 }
};
for (int i=0; sWeaponFlagTable[i].mName; ++i)
{
mColumns.push_back (RefIdColumn (sWeaponFlagTable[i].mName, ColumnBase::Display_Boolean));
weaponColumns.mFlags.insert (std::make_pair (&mColumns.back(), sWeaponFlagTable[i].mFlag));
}
mAdapters.insert (std::make_pair (UniversalId::Type_Activator,
new NameRefIdAdapter<ESM::Activator> (UniversalId::Type_Activator, nameColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_Potion,
new PotionRefIdAdapter (inventoryColumns, autoCalc)));
mAdapters.insert (std::make_pair (UniversalId::Type_Apparatus,
new ApparatusRefIdAdapter (inventoryColumns, apparatusType, toolsColumns.mQuality)));
mAdapters.insert (std::make_pair (UniversalId::Type_Armor,
new ArmorRefIdAdapter (enchantableColumns, armorType, health, armor)));
mAdapters.insert (std::make_pair (UniversalId::Type_Book,
new BookRefIdAdapter (enchantableColumns, scroll, attribute)));
mAdapters.insert (std::make_pair (UniversalId::Type_Clothing,
new ClothingRefIdAdapter (enchantableColumns, clothingType)));
mAdapters.insert (std::make_pair (UniversalId::Type_Container,
new ContainerRefIdAdapter (nameColumns, weightCapacity, organic, respawn)));
mAdapters.insert (std::make_pair (UniversalId::Type_Creature,
new CreatureRefIdAdapter (creatureColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_Door,
new DoorRefIdAdapter (nameColumns, openSound, closeSound)));
mAdapters.insert (std::make_pair (UniversalId::Type_Ingredient,
new InventoryRefIdAdapter<ESM::Ingredient> (UniversalId::Type_Ingredient, inventoryColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_CreatureLevelledList,
new BaseRefIdAdapter<ESM::CreatureLevList> (
UniversalId::Type_CreatureLevelledList, baseColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_ItemLevelledList,
new BaseRefIdAdapter<ESM::ItemLevList> (UniversalId::Type_ItemLevelledList, baseColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_Light,
new LightRefIdAdapter (lightColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_Lockpick,
new ToolRefIdAdapter<ESM::Lockpick> (UniversalId::Type_Lockpick, toolsColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_Miscellaneous,
new MiscRefIdAdapter (inventoryColumns, key)));
mAdapters.insert (std::make_pair (UniversalId::Type_Npc,
new NpcRefIdAdapter (npcColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_Probe,
new ToolRefIdAdapter<ESM::Probe> (UniversalId::Type_Probe, toolsColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_Repair,
new ToolRefIdAdapter<ESM::Repair> (UniversalId::Type_Repair, toolsColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_Static,
new ModelRefIdAdapter<ESM::Static> (UniversalId::Type_Static, modelColumns)));
mAdapters.insert (std::make_pair (UniversalId::Type_Weapon,
new WeaponRefIdAdapter (weaponColumns)));
}
CSMWorld::RefIdCollection::~RefIdCollection()
{
for (std::map<UniversalId::Type, RefIdAdapter *>::iterator iter (mAdapters.begin());
iter!=mAdapters.end(); ++iter)
delete iter->second;
}
int CSMWorld::RefIdCollection::getSize() const
{
return mData.getSize();
}
std::string CSMWorld::RefIdCollection::getId (int index) const
{
return getData (index, 0).toString().toUtf8().constData();
}
int CSMWorld::RefIdCollection::getIndex (const std::string& id) const
{
int index = searchId (id);
if (index==-1)
throw std::runtime_error ("invalid ID: " + id);
return index;
}
int CSMWorld::RefIdCollection::getColumns() const
{
return mColumns.size();
}
const CSMWorld::ColumnBase& CSMWorld::RefIdCollection::getColumn (int column) const
{
return mColumns.at (column);
}
QVariant CSMWorld::RefIdCollection::getData (int index, int column) const
{
RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (index);
const RefIdAdapter& adaptor = findAdaptor (localIndex.second);
return adaptor.getData (&mColumns.at (column), mData, localIndex.first);
}
void CSMWorld::RefIdCollection::setData (int index, int column, const QVariant& data)
{
RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (index);
const RefIdAdapter& adaptor = findAdaptor (localIndex.second);
adaptor.setData (&mColumns.at (column), mData, localIndex.first, data);
}
void CSMWorld::RefIdCollection::removeRows (int index, int count)
{
mData.erase (index, count);
}
void CSMWorld::RefIdCollection::appendBlankRecord (const std::string& id, UniversalId::Type type)
{
mData.appendRecord (type, id);
}
int CSMWorld::RefIdCollection::searchId (const std::string& id) const
{
RefIdData::LocalIndex localIndex = mData.searchId (id);
if (localIndex.first==-1)
return -1;
return mData.localToGlobalIndex (localIndex);
}
void CSMWorld::RefIdCollection::replace (int index, const RecordBase& record)
{
mData.getRecord (mData.globalToLocalIndex (index)).assign (record);
}
void CSMWorld::RefIdCollection::appendRecord (const RecordBase& record,
UniversalId::Type type)
{
std::string id = findAdaptor (type).getId (record);
int index = mData.getAppendIndex (type);
mData.appendRecord (type, id);
mData.getRecord (mData.globalToLocalIndex (index)).assign (record);
}
const CSMWorld::RecordBase& CSMWorld::RefIdCollection::getRecord (const std::string& id) const
{
return mData.getRecord (mData.searchId (id));
}
const CSMWorld::RecordBase& CSMWorld::RefIdCollection::getRecord (int index) const
{
return mData.getRecord (mData.globalToLocalIndex (index));
}
void CSMWorld::RefIdCollection::load (ESM::ESMReader& reader, bool base, UniversalId::Type type)
{
std::string id = reader.getHNOString ("NAME");
int index = searchId (id);
if (reader.isNextSub ("DELE"))
{
reader.skipRecord();
if (index==-1)
{
// deleting a record that does not exist
// ignore it for now
/// \todo report the problem to the user
}
else if (base)
{
mData.erase (index, 1);
}
else
{
mData.getRecord (mData.globalToLocalIndex (index)).mState = RecordBase::State_Deleted;
}
}
else
{
if (index==-1)
{
// new record
int index = mData.getAppendIndex (type);
mData.appendRecord (type, id);
RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (index);
mData.load (localIndex, reader, base);
mData.getRecord (localIndex).mState =
base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly;
}
else
{
// old record
RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (index);
if (!base)
if (mData.getRecord (localIndex).mState==RecordBase::State_Erased)
throw std::logic_error ("attempt to access a deleted record");
mData.load (localIndex, reader, base);
if (!base)
mData.getRecord (localIndex).mState = RecordBase::State_Modified;
}
}
}
int CSMWorld::RefIdCollection::getAppendIndex (UniversalId::Type type) const
{
return mData.getAppendIndex (type);
}

View File

@ -0,0 +1,95 @@
#ifndef CSM_WOLRD_REFIDCOLLECTION_H
#define CSM_WOLRD_REFIDCOLLECTION_H
#include <vector>
#include <map>
#include <deque>
#include "columnbase.hpp"
#include "idcollection.hpp"
#include "refiddata.hpp"
namespace CSMWorld
{
class RefIdAdapter;
class RefIdColumn : public ColumnBase
{
bool mEditable;
bool mUserEditable;
public:
RefIdColumn (const std::string& title, Display displayType,
int flag = Flag_Table | Flag_Dialogue, bool editable = true,
bool userEditable = true);
virtual bool isEditable() const;
virtual bool isUserEditable() const;
};
class RefIdCollection : public IdCollectionBase
{
private:
RefIdData mData;
std::deque<RefIdColumn> mColumns;
std::map<UniversalId::Type, RefIdAdapter *> mAdapters;
private:
const RefIdAdapter& findAdaptor (UniversalId::Type) const;
///< Throws an exception if no adaptor for \a Type can be found.
public:
RefIdCollection();
virtual ~RefIdCollection();
virtual int getSize() const;
virtual std::string getId (int index) const;
virtual int getIndex (const std::string& id) const;
virtual int getColumns() const;
virtual const ColumnBase& getColumn (int column) const;
virtual QVariant getData (int index, int column) const;
virtual void setData (int index, int column, const QVariant& data);
virtual void removeRows (int index, int count);
virtual void appendBlankRecord (const std::string& id, UniversalId::Type type);
///< \param type Will be ignored, unless the collection supports multiple record types
virtual int searchId (const std::string& id) const;
////< Search record with \a id.
/// \return index of record (if found) or -1 (not found)
virtual void replace (int index, const RecordBase& record);
///< If the record type does not match, an exception is thrown.
///
/// \attention \a record must not change the ID.
virtual void appendRecord (const RecordBase& record, UniversalId::Type type);
///< If the record type does not match, an exception is thrown.
///
///< \param type Will be ignored, unless the collection supports multiple record types
virtual const RecordBase& getRecord (const std::string& id) const;
virtual const RecordBase& getRecord (int index) const;
virtual void load (ESM::ESMReader& reader, bool base, UniversalId::Type type);
virtual int getAppendIndex (UniversalId::Type type) const;
///< \param type Will be ignored, unless the collection supports multiple record types
};
}
#endif

View File

@ -0,0 +1,198 @@
#include "refiddata.hpp"
#include <cassert>
#include <components/misc/stringops.hpp>
CSMWorld::RefIdDataContainerBase::~RefIdDataContainerBase() {}
CSMWorld::RefIdData::RefIdData()
{
mRecordContainers.insert (std::make_pair (UniversalId::Type_Activator, &mActivators));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Potion, &mPotions));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Apparatus, &mApparati));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Armor, &mArmors));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Book, &mBooks));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Clothing, &mClothing));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Container, &mContainers));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Creature, &mCreatures));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Door, &mDoors));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Ingredient, &mIngredients));
mRecordContainers.insert (std::make_pair (UniversalId::Type_CreatureLevelledList,
&mCreatureLevelledLists));
mRecordContainers.insert (std::make_pair (UniversalId::Type_ItemLevelledList, &mItemLevelledLists));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Light, &mLights));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Lockpick, &mLockpicks));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Miscellaneous, &mMiscellaneous));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Npc, &mNpcs));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Probe, &mProbes));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Repair, &mRepairs));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Static, &mStatics));
mRecordContainers.insert (std::make_pair (UniversalId::Type_Weapon, &mWeapons));
}
CSMWorld::RefIdData::LocalIndex CSMWorld::RefIdData::globalToLocalIndex (int index) const
{
for (std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator iter (
mRecordContainers.begin()); iter!=mRecordContainers.end(); ++iter)
{
if (index<iter->second->getSize())
return LocalIndex (index, iter->first);
index -= iter->second->getSize();
}
throw std::runtime_error ("RefIdData index out of range");
}
int CSMWorld::RefIdData::localToGlobalIndex (const LocalIndex& index)
const
{
std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator end =
mRecordContainers.find (index.second);
if (end==mRecordContainers.end())
throw std::logic_error ("invalid local index type");
int globalIndex = index.first;
for (std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator iter (
mRecordContainers.begin()); iter!=end; ++iter)
globalIndex += iter->second->getSize();
return globalIndex;
}
CSMWorld::RefIdData::LocalIndex CSMWorld::RefIdData::searchId (
const std::string& id) const
{
std::string id2 = Misc::StringUtils::lowerCase (id);
std::map<std::string, std::pair<int, UniversalId::Type> >::const_iterator iter = mIndex.find (id2);
if (iter==mIndex.end())
return std::make_pair (-1, CSMWorld::UniversalId::Type_None);
return iter->second;
}
void CSMWorld::RefIdData::erase (int index, int count)
{
LocalIndex localIndex = globalToLocalIndex (index);
std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator iter =
mRecordContainers.find (localIndex.second);
while (count>0 && iter!=mRecordContainers.end())
{
int size = iter->second->getSize();
if (localIndex.first+count>size)
{
erase (localIndex, size-localIndex.first);
count -= size-localIndex.first;
++iter;
if (iter==mRecordContainers.end())
throw std::runtime_error ("invalid count value for erase operation");
localIndex.first = 0;
localIndex.second = iter->first;
}
else
{
erase (localIndex, count);
count = 0;
}
}
}
const CSMWorld::RecordBase& CSMWorld::RefIdData::getRecord (const LocalIndex& index) const
{
std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator iter =
mRecordContainers.find (index.second);
if (iter==mRecordContainers.end())
throw std::logic_error ("invalid local index type");
return iter->second->getRecord (index.first);
}
CSMWorld::RecordBase& CSMWorld::RefIdData::getRecord (const LocalIndex& index)
{
std::map<UniversalId::Type, RefIdDataContainerBase *>::iterator iter =
mRecordContainers.find (index.second);
if (iter==mRecordContainers.end())
throw std::logic_error ("invalid local index type");
return iter->second->getRecord (index.first);
}
void CSMWorld::RefIdData::appendRecord (UniversalId::Type type, const std::string& id)
{
std::map<UniversalId::Type, RefIdDataContainerBase *>::iterator iter =
mRecordContainers.find (type);
if (iter==mRecordContainers.end())
throw std::logic_error ("invalid local index type");
iter->second->appendRecord (id);
mIndex.insert (std::make_pair (Misc::StringUtils::lowerCase (id),
LocalIndex (iter->second->getSize()-1, type)));
}
int CSMWorld::RefIdData::getAppendIndex (UniversalId::Type type) const
{
int index = 0;
for (std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator iter (
mRecordContainers.begin()); iter!=mRecordContainers.end(); ++iter)
{
index += iter->second->getSize();
if (type==iter->first)
break;
}
return index;
}
void CSMWorld::RefIdData::load (const LocalIndex& index, ESM::ESMReader& reader, bool base)
{
std::map<UniversalId::Type, RefIdDataContainerBase *>::iterator iter =
mRecordContainers.find (index.second);
if (iter==mRecordContainers.end())
throw std::logic_error ("invalid local index type");
iter->second->load (index.first, reader, base);
}
void CSMWorld::RefIdData::erase (const LocalIndex& index, int count)
{
std::map<UniversalId::Type, RefIdDataContainerBase *>::iterator iter =
mRecordContainers.find (index.second);
if (iter==mRecordContainers.end())
throw std::logic_error ("invalid local index type");
for (int i=index.first; i<index.first+count; ++i)
{
std::map<std::string, LocalIndex>::iterator result =
mIndex.find (Misc::StringUtils::lowerCase (iter->second->getId (i)));
if (result!=mIndex.end())
mIndex.erase (result);
}
iter->second->erase (index.first, count);
}
int CSMWorld::RefIdData::getSize() const
{
return mIndex.size();
}

View File

@ -0,0 +1,188 @@
#ifndef CSM_WOLRD_REFIDDATA_H
#define CSM_WOLRD_REFIDDATA_H
#include <vector>
#include <map>
#include <components/esm/loadacti.hpp>
#include <components/esm/loadalch.hpp>
#include <components/esm/loadappa.hpp>
#include <components/esm/loadarmo.hpp>
#include <components/esm/loadbook.hpp>
#include <components/esm/loadclot.hpp>
#include <components/esm/loadcont.hpp>
#include <components/esm/loadcrea.hpp>
#include <components/esm/loaddoor.hpp>
#include <components/esm/loadingr.hpp>
#include <components/esm/loadlevlist.hpp>
#include <components/esm/loadligh.hpp>
#include <components/esm/loadlock.hpp>
#include <components/esm/loadprob.hpp>
#include <components/esm/loadrepa.hpp>
#include <components/esm/loadstat.hpp>
#include <components/esm/loadweap.hpp>
#include <components/esm/loadnpc.hpp>
#include <components/esm/loadmisc.hpp>
#include "record.hpp"
#include "universalid.hpp"
namespace ESM
{
class ESMReader;
}
namespace CSMWorld
{
struct RefIdDataContainerBase
{
virtual ~RefIdDataContainerBase();
virtual int getSize() const = 0;
virtual const RecordBase& getRecord (int index) const = 0;
virtual RecordBase& getRecord (int index)= 0;
virtual void appendRecord (const std::string& id) = 0;
virtual void load (int index, ESM::ESMReader& reader, bool base) = 0;
virtual void erase (int index, int count) = 0;
virtual std::string getId (int index) const = 0;
};
template<typename RecordT>
struct RefIdDataContainer : public RefIdDataContainerBase
{
std::vector<Record<RecordT> > mContainer;
virtual int getSize() const;
virtual const RecordBase& getRecord (int index) const;
virtual RecordBase& getRecord (int index);
virtual void appendRecord (const std::string& id);
virtual void load (int index, ESM::ESMReader& reader, bool base);
virtual void erase (int index, int count);
virtual std::string getId (int index) const;
};
template<typename RecordT>
int RefIdDataContainer<RecordT>::getSize() const
{
return static_cast<int> (mContainer.size());
}
template<typename RecordT>
const RecordBase& RefIdDataContainer<RecordT>::getRecord (int index) const
{
return mContainer.at (index);
}
template<typename RecordT>
RecordBase& RefIdDataContainer<RecordT>::getRecord (int index)
{
return mContainer.at (index);
}
template<typename RecordT>
void RefIdDataContainer<RecordT>::appendRecord (const std::string& id)
{
Record<RecordT> record;
record.mModified.mId = id;
record.mModified.blank();
record.mState = RecordBase::State_ModifiedOnly;
mContainer.push_back (record);
}
template<typename RecordT>
void RefIdDataContainer<RecordT>::load (int index, ESM::ESMReader& reader, bool base)
{
(base ? mContainer.at (index).mBase : mContainer.at (index).mModified).load (reader);
}
template<typename RecordT>
void RefIdDataContainer<RecordT>::erase (int index, int count)
{
if (index<0 || index+count>=getSize())
throw std::runtime_error ("invalid RefIdDataContainer index");
mContainer.erase (mContainer.begin()+index, mContainer.begin()+index+count);
}
template<typename RecordT>
std::string RefIdDataContainer<RecordT>::getId (int index) const
{
return mContainer.at (index).get().mId;
}
class RefIdData
{
public:
typedef std::pair<int, UniversalId::Type> LocalIndex;
private:
RefIdDataContainer<ESM::Activator> mActivators;
RefIdDataContainer<ESM::Potion> mPotions;
RefIdDataContainer<ESM::Apparatus> mApparati;
RefIdDataContainer<ESM::Armor> mArmors;
RefIdDataContainer<ESM::Book> mBooks;
RefIdDataContainer<ESM::Clothing> mClothing;
RefIdDataContainer<ESM::Container> mContainers;
RefIdDataContainer<ESM::Creature> mCreatures;
RefIdDataContainer<ESM::Door> mDoors;
RefIdDataContainer<ESM::Ingredient> mIngredients;
RefIdDataContainer<ESM::CreatureLevList> mCreatureLevelledLists;
RefIdDataContainer<ESM::ItemLevList> mItemLevelledLists;
RefIdDataContainer<ESM::Light> mLights;
RefIdDataContainer<ESM::Lockpick> mLockpicks;
RefIdDataContainer<ESM::Miscellaneous> mMiscellaneous;
RefIdDataContainer<ESM::NPC> mNpcs;
RefIdDataContainer<ESM::Probe> mProbes;
RefIdDataContainer<ESM::Repair> mRepairs;
RefIdDataContainer<ESM::Static> mStatics;
RefIdDataContainer<ESM::Weapon> mWeapons;
std::map<std::string, LocalIndex> mIndex;
std::map<UniversalId::Type, RefIdDataContainerBase *> mRecordContainers;
void erase (const LocalIndex& index, int count);
///< Must not spill over into another type.
public:
RefIdData();
LocalIndex globalToLocalIndex (int index) const;
int localToGlobalIndex (const LocalIndex& index) const;
LocalIndex searchId (const std::string& id) const;
void erase (int index, int count);
const RecordBase& getRecord (const LocalIndex& index) const;
RecordBase& getRecord (const LocalIndex& index);
void appendRecord (UniversalId::Type type, const std::string& id);
int getAppendIndex (UniversalId::Type type) const;
void load (const LocalIndex& index, ESM::ESMReader& reader, bool base);
int getSize() const;
};
}
#endif

View File

@ -0,0 +1,22 @@
#include "scriptcontext.hpp"
bool CSMWorld::ScriptContext::canDeclareLocals() const
{
return false;
}
char CSMWorld::ScriptContext::getGlobalType (const std::string& name) const
{
return ' ';
}
char CSMWorld::ScriptContext::getMemberType (const std::string& name, const std::string& id) const
{
return ' ';
}
bool CSMWorld::ScriptContext::isId (const std::string& name) const
{
return false;
}

View File

@ -0,0 +1,26 @@
#ifndef CSM_WORLD_SCRIPTCONTEXT_H
#define CSM_WORLD_SCRIPTCONTEXT_H
#include <components/compiler/context.hpp>
namespace CSMWorld
{
class ScriptContext : public Compiler::Context
{
public:
virtual bool canDeclareLocals() const;
///< Is the compiler allowed to declare local variables?
virtual char getGlobalType (const std::string& name) const;
///< 'l: long, 's': short, 'f': float, ' ': does not exist.
virtual char getMemberType (const std::string& name, const std::string& id) const;
///< 'l: long, 's': short, 'f': float, ' ': does not exist.
virtual bool isId (const std::string& name) const;
///< Does \a name match an ID, that can be referenced?
};
}
#endif

View File

@ -19,6 +19,18 @@ namespace
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "empty" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "empty" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Factions, "Factions" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Races, "Races" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Sounds, "Sounds" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Scripts, "Scripts" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Spells, "Spells" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Cells, "Cells" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Referenceables,
"Referenceables" },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
}; };
@ -27,6 +39,40 @@ namespace
{ {
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Faction, "Faction" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Race, "Race" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Activator, "Activator" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Potion, "Potion" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Apparatus, "Apparatus" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Armor, "Armor" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Book, "Book" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Clothing, "Clothing" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Container, "Container" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Creature, "Creature" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Door, "Door" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Ingredient, "Ingredient" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_CreatureLevelledList,
"Creature Levelled List" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_ItemLevelledList,
"Item Levelled List" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Light, "Light" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Lockpick, "Lockpick" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Miscellaneous,
"Miscellaneous" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Npc, "NPC" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Probe, "Probe" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Repair, "Repair" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Static, "Static" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Weapon, "Weapon" },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
}; };
@ -43,48 +89,45 @@ CSMWorld::UniversalId::UniversalId (const std::string& universalId)
{ {
std::string::size_type index = universalId.find (':'); std::string::size_type index = universalId.find (':');
if (index==std::string::npos) if (index!=std::string::npos)
{ {
std::string type = universalId.substr (0, index); std::string type = universalId.substr (0, index);
if (index==std::string::npos) for (int i=0; sIdArg[i].mName; ++i)
{ if (type==sIdArg[i].mName)
for (int i=0; sNoArg[i].mName; ++i) {
if (type==sNoArg[i].mName) mArgumentType = ArgumentType_Id;
{ mType = sIdArg[i].mType;
mArgumentType = ArgumentType_None; mClass = sIdArg[i].mClass;
mType = sNoArg[i].mType; mId = universalId.substr (index+2);
mClass = sNoArg[i].mClass; return;
}
for (int i=0; sIndexArg[i].mName; ++i)
if (type==sIndexArg[i].mName)
{
mArgumentType = ArgumentType_Index;
mType = sIndexArg[i].mType;
mClass = sIndexArg[i].mClass;
std::istringstream stream (universalId.substr (index+2));
if (stream >> mIndex)
return; return;
}
}
else
{
for (int i=0; sIdArg[i].mName; ++i)
if (type==sIdArg[i].mName)
{
mArgumentType = ArgumentType_Id;
mType = sIdArg[i].mType;
mClass = sIdArg[i].mClass;
mId = universalId.substr (0, index);
return;
}
for (int i=0; sIndexArg[i].mName; ++i) break;
if (type==sIndexArg[i].mName) }
{ }
mArgumentType = ArgumentType_Index; else
mType = sIndexArg[i].mType; {
mClass = sIndexArg[i].mClass; for (int i=0; sNoArg[i].mName; ++i)
if (universalId==sNoArg[i].mName)
std::istringstream stream (universalId.substr (0, index)); {
mArgumentType = ArgumentType_None;
if (stream >> mIndex) mType = sNoArg[i].mType;
return; mClass = sNoArg[i].mClass;
return;
break; }
}
}
} }
throw std::runtime_error ("invalid UniversalId: " + universalId); throw std::runtime_error ("invalid UniversalId: " + universalId);

View File

@ -37,7 +37,49 @@ namespace CSMWorld
Type_Global, Type_Global,
Type_VerificationResults, Type_VerificationResults,
Type_Gmsts, Type_Gmsts,
Type_Gmst Type_Gmst,
Type_Skills,
Type_Skill,
Type_Classes,
Type_Class,
Type_Factions,
Type_Faction,
Type_Races,
Type_Race,
Type_Sounds,
Type_Sound,
Type_Scripts,
Type_Script,
Type_Regions,
Type_Region,
Type_Birthsigns,
Type_Birthsign,
Type_Spells,
Type_Spell,
Type_Cells,
Type_Cell,
Type_Referenceables,
Type_Referenceable,
Type_Activator,
Type_Potion,
Type_Apparatus,
Type_Armor,
Type_Book,
Type_Clothing,
Type_Container,
Type_Creature,
Type_Door,
Type_Ingredient,
Type_CreatureLevelledList,
Type_ItemLevelledList,
Type_Light,
Type_Lockpick,
Type_Miscellaneous,
Type_Npc,
Type_Probe,
Type_Repair,
Type_Static,
Type_Weapon
}; };

View File

@ -1,68 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>UserSettingsDialog</class>
<widget class="QDialog" name="UserSettingsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>638</width>
<height>478</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>10</x>
<y>440</y>
<width>621</width>
<height>32</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</widget>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>UserSettingsDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>UserSettingsDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -56,7 +56,7 @@ void CSVDoc::Operations::quitOperation (int type)
mLayout->removeItem ((*iter)->getLayout()); mLayout->removeItem ((*iter)->getLayout());
delete *iter; (*iter)->deleteLater();
mOperations.erase (iter); mOperations.erase (iter);
if (oldCount > 1) if (oldCount > 1)

View File

@ -7,17 +7,16 @@
#include <QMenuBar> #include <QMenuBar>
#include <QMdiArea> #include <QMdiArea>
#include <QDockWidget> #include <QDockWidget>
#include <QtGui/QApplication>
#include "../../model/doc/document.hpp" #include "../../model/doc/document.hpp"
#include "../world/subviews.hpp" #include "../world/subviews.hpp"
#include "../tools/subviews.hpp" #include "../tools/subviews.hpp"
#include "../../settings/usersettingsdialog.hpp" #include "../settings/usersettingsdialog.hpp"
#include "viewmanager.hpp" #include "viewmanager.hpp"
#include "operations.hpp" #include "operations.hpp"
#include "subview.hpp" #include "subview.hpp"
#include <QDebug>
void CSVDoc::View::closeEvent (QCloseEvent *event) void CSVDoc::View::closeEvent (QCloseEvent *event)
{ {
if (!mViewManager.closeRequest (this)) if (!mViewManager.closeRequest (this))
@ -39,6 +38,20 @@ void CSVDoc::View::setupFileMenu()
mSave = new QAction (tr ("&Save"), this); mSave = new QAction (tr ("&Save"), this);
connect (mSave, SIGNAL (triggered()), this, SLOT (save())); connect (mSave, SIGNAL (triggered()), this, SLOT (save()));
file->addAction (mSave); file->addAction (mSave);
mVerify = new QAction (tr ("&Verify"), this);
connect (mVerify, SIGNAL (triggered()), this, SLOT (verify()));
file->addAction (mVerify);
QAction *close = new QAction (tr ("&Close"), this);
connect (close, SIGNAL (triggered()), this, SLOT (close()));
file->addAction(close);
QAction *exit = new QAction (tr ("&Exit"), this);
connect (exit, SIGNAL (triggered()), this, SLOT (exit()));
connect (this, SIGNAL(exitApplicationRequest(CSVDoc::View *)), &mViewManager, SLOT(exitApplication(CSVDoc::View *)));
file->addAction(exit);
} }
void CSVDoc::View::setupEditMenu() void CSVDoc::View::setupEditMenu()
@ -52,6 +65,10 @@ void CSVDoc::View::setupEditMenu()
mRedo= mDocument->getUndoStack().createRedoAction (this, tr("&Redo")); mRedo= mDocument->getUndoStack().createRedoAction (this, tr("&Redo"));
mRedo->setShortcuts (QKeySequence::Redo); mRedo->setShortcuts (QKeySequence::Redo);
edit->addAction (mRedo); edit->addAction (mRedo);
QAction *userSettings = new QAction (tr ("&Preferences"), this);
connect (userSettings, SIGNAL (triggered()), this, SLOT (showUserSettings()));
edit->addAction (userSettings);
} }
void CSVDoc::View::setupViewMenu() void CSVDoc::View::setupViewMenu()
@ -75,18 +92,49 @@ void CSVDoc::View::setupWorldMenu()
connect (gmsts, SIGNAL (triggered()), this, SLOT (addGmstsSubView())); connect (gmsts, SIGNAL (triggered()), this, SLOT (addGmstsSubView()));
world->addAction (gmsts); world->addAction (gmsts);
mVerify = new QAction (tr ("&Verify"), this); QAction *skills = new QAction (tr ("Skills"), this);
connect (mVerify, SIGNAL (triggered()), this, SLOT (verify())); connect (skills, SIGNAL (triggered()), this, SLOT (addSkillsSubView()));
world->addAction (mVerify); world->addAction (skills);
}
void CSVDoc::View::setupSettingsMenu() QAction *classes = new QAction (tr ("Classes"), this);
{ connect (classes, SIGNAL (triggered()), this, SLOT (addClassesSubView()));
QMenu *settings = menuBar()->addMenu( (tr ("&Settings"))); world->addAction (classes);
QAction *userSettings = new QAction (tr ("User Settings"), this); QAction *factions = new QAction (tr ("Factions"), this);
connect (userSettings, SIGNAL (triggered()), this, SLOT (showUserSettings())); connect (factions, SIGNAL (triggered()), this, SLOT (addFactionsSubView()));
settings->addAction (userSettings); world->addAction (factions);
QAction *races = new QAction (tr ("Races"), this);
connect (races, SIGNAL (triggered()), this, SLOT (addRacesSubView()));
world->addAction (races);
QAction *sounds = new QAction (tr ("Sounds"), this);
connect (sounds, SIGNAL (triggered()), this, SLOT (addSoundsSubView()));
world->addAction (sounds);
QAction *scripts = new QAction (tr ("Scripts"), this);
connect (scripts, SIGNAL (triggered()), this, SLOT (addScriptsSubView()));
world->addAction (scripts);
QAction *regions = new QAction (tr ("Regions"), this);
connect (regions, SIGNAL (triggered()), this, SLOT (addRegionsSubView()));
world->addAction (regions);
QAction *birthsigns = new QAction (tr ("Birthsigns"), this);
connect (birthsigns, SIGNAL (triggered()), this, SLOT (addBirthsignsSubView()));
world->addAction (birthsigns);
QAction *spells = new QAction (tr ("Spells"), this);
connect (spells, SIGNAL (triggered()), this, SLOT (addSpellsSubView()));
world->addAction (spells);
QAction *cells = new QAction (tr ("Cells"), this);
connect (cells, SIGNAL (triggered()), this, SLOT (addCellsSubView()));
world->addAction (cells);
QAction *referenceables = new QAction (tr ("Referenceables"), this);
connect (referenceables, SIGNAL (triggered()), this, SLOT (addReferenceablesSubView()));
world->addAction (referenceables);
} }
@ -96,7 +144,6 @@ void CSVDoc::View::setupUi()
setupEditMenu(); setupEditMenu();
setupViewMenu(); setupViewMenu();
setupWorldMenu(); setupWorldMenu();
setupSettingsMenu();
} }
void CSVDoc::View::updateTitle() void CSVDoc::View::updateTitle()
@ -128,15 +175,15 @@ void CSVDoc::View::updateActions()
mVerify->setEnabled (!(mDocument->getState() & CSMDoc::State_Verifying)); mVerify->setEnabled (!(mDocument->getState() & CSMDoc::State_Verifying));
} }
CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews, QMainWindow *viewParent) CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews)
: mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1), mViewTotal (totalViews), QMainWindow (viewParent) : mViewManager (viewManager), mDocument (document), mViewIndex (totalViews-1),
mViewTotal (totalViews)
{ {
setDockOptions (QMainWindow::AllowNestedDocks);
resize (300, 300); /// \todo get default size from settings and set reasonable minimal size resize (300, 300); /// \todo get default size from settings and set reasonable minimal size
mSubViewWindow = new QMainWindow(); mSubViewWindow.setDockOptions (QMainWindow::AllowNestedDocks);
setCentralWidget (mSubViewWindow);
setCentralWidget (&mSubViewWindow);
mOperations = new Operations; mOperations = new Operations;
addDockWidget (Qt::BottomDockWidgetArea, mOperations); addDockWidget (Qt::BottomDockWidgetArea, mOperations);
@ -211,7 +258,7 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id)
/// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis) /// \todo add an user setting to reuse sub views (on a per document basis or on a per top level view basis)
SubView *view = mSubViewFactory.makeSubView (id, *mDocument); SubView *view = mSubViewFactory.makeSubView (id, *mDocument);
mSubViewWindow->addDockWidget (Qt::TopDockWidgetArea, view); mSubViewWindow.addDockWidget (Qt::TopDockWidgetArea, view);
connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&)), this, connect (view, SIGNAL (focusId (const CSMWorld::UniversalId&)), this,
SLOT (addSubView (const CSMWorld::UniversalId&))); SLOT (addSubView (const CSMWorld::UniversalId&)));
@ -244,22 +291,82 @@ void CSVDoc::View::addGmstsSubView()
addSubView (CSMWorld::UniversalId::Type_Gmsts); addSubView (CSMWorld::UniversalId::Type_Gmsts);
} }
void CSVDoc::View::addSkillsSubView()
{
addSubView (CSMWorld::UniversalId::Type_Skills);
}
void CSVDoc::View::addClassesSubView()
{
addSubView (CSMWorld::UniversalId::Type_Classes);
}
void CSVDoc::View::addFactionsSubView()
{
addSubView (CSMWorld::UniversalId::Type_Factions);
}
void CSVDoc::View::addRacesSubView()
{
addSubView (CSMWorld::UniversalId::Type_Races);
}
void CSVDoc::View::addSoundsSubView()
{
addSubView (CSMWorld::UniversalId::Type_Sounds);
}
void CSVDoc::View::addScriptsSubView()
{
addSubView (CSMWorld::UniversalId::Type_Scripts);
}
void CSVDoc::View::addRegionsSubView()
{
addSubView (CSMWorld::UniversalId::Type_Regions);
}
void CSVDoc::View::addBirthsignsSubView()
{
addSubView (CSMWorld::UniversalId::Type_Birthsigns);
}
void CSVDoc::View::addSpellsSubView()
{
addSubView (CSMWorld::UniversalId::Type_Spells);
}
void CSVDoc::View::addCellsSubView()
{
addSubView (CSMWorld::UniversalId::Type_Cells);
}
void CSVDoc::View::addReferenceablesSubView()
{
addSubView (CSMWorld::UniversalId::Type_Referenceables);
}
void CSVDoc::View::abortOperation (int type) void CSVDoc::View::abortOperation (int type)
{ {
mDocument->abortOperation (type); mDocument->abortOperation (type);
updateActions(); updateActions();
} }
QDockWidget *CSVDoc::View::getOperations() const CSVDoc::Operations *CSVDoc::View::getOperations() const
{ {
return mOperations; return mOperations;
} }
void CSVDoc::View::exit()
{
emit exitApplicationRequest (this);
}
void CSVDoc::View::showUserSettings() void CSVDoc::View::showUserSettings()
{ {
CsSettings::UserSettingsDialog *settingsDialog = new CsSettings::UserSettingsDialog(this); CSVSettings::UserSettingsDialog *settingsDialog = new CSVSettings::UserSettingsDialog(this);
connect (settingsDialog, SIGNAL (signalUpdateEditorSetting (const QString &, const QString &)), connect (&(CSMSettings::UserSettings::instance()), SIGNAL (signalUpdateEditorSetting (const QString &, const QString &)),
this, SLOT (slotUpdateEditorSetting (const QString &, const QString &)) ); this, SLOT (slotUpdateEditorSetting (const QString &, const QString &)) );
settingsDialog->show(); settingsDialog->show();
@ -271,11 +378,7 @@ void CSVDoc::View::slotUpdateEditorSetting(const QString &settingName, const QSt
if (lastValue != settingValue) if (lastValue != settingValue)
{ {
if (settingName == "Undo Stack Size"); //evaluate settingName against tokens to determine which function to call to update Editor application.
if (settingName == "Top-Level Window Count");
if (settingName == "Reuse Subwindows");
lastValue = settingValue; lastValue = settingValue;
} }

View File

@ -41,7 +41,8 @@ namespace CSVDoc
std::vector<QAction *> mEditingActions; std::vector<QAction *> mEditingActions;
Operations *mOperations; Operations *mOperations;
SubViewFactoryManager mSubViewFactory; SubViewFactoryManager mSubViewFactory;
QMainWindow* mSubViewWindow; QMainWindow mSubViewWindow;
// not implemented // not implemented
View (const View&); View (const View&);
@ -59,17 +60,18 @@ namespace CSVDoc
void setupWorldMenu(); void setupWorldMenu();
void setupSettingsMenu();
void setupUi(); void setupUi();
void updateTitle(); void updateTitle();
void updateActions(); void updateActions();
void exitApplication();
public: public:
View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews, QMainWindow *viewParent); View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews);
///< The ownership of \a document is not transferred to *this. ///< The ownership of \a document is not transferred to *this.
virtual ~View(); virtual ~View();
@ -84,7 +86,7 @@ namespace CSVDoc
void updateProgress (int current, int max, int type, int threads); void updateProgress (int current, int max, int type, int threads);
QDockWidget *getOperations() const; Operations *getOperations() const;
signals: signals:
@ -92,10 +94,14 @@ namespace CSVDoc
void loadDocumentRequest(); void loadDocumentRequest();
void exitApplicationRequest (CSVDoc::View *view);
public slots: public slots:
void addSubView (const CSMWorld::UniversalId& id); void addSubView (const CSMWorld::UniversalId& id);
void abortOperation (int type);
void slotUpdateEditorSetting (const QString &settingName, const QString &settingValue); void slotUpdateEditorSetting (const QString &settingName, const QString &settingValue);
private slots: private slots:
@ -104,13 +110,35 @@ namespace CSVDoc
void save(); void save();
void exit();
void verify(); void verify();
void addGlobalsSubView(); void addGlobalsSubView();
void addGmstsSubView(); void addGmstsSubView();
void abortOperation (int type); void addSkillsSubView();
void addClassesSubView();
void addFactionsSubView();
void addRacesSubView();
void addSoundsSubView();
void addScriptsSubView();
void addRegionsSubView();
void addBirthsignsSubView();
void addSpellsSubView();
void addCellsSubView();
void addReferenceablesSubView();
void showUserSettings(); void showUserSettings();
}; };

View File

@ -15,6 +15,11 @@
#include "view.hpp" #include "view.hpp"
#include <QMessageBox>
#include <QPushButton>
#include <QtGui/QApplication>
#include <QDebug>
void CSVDoc::ViewManager::updateIndices() void CSVDoc::ViewManager::updateIndices()
{ {
std::map<CSMDoc::Document *, std::pair<int, int> > documents; std::map<CSMDoc::Document *, std::pair<int, int> > documents;
@ -34,8 +39,53 @@ void CSVDoc::ViewManager::updateIndices()
} }
CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
: mDocumentManager (documentManager) : mDocumentManager (documentManager), mExitOnSaveStateChange(false), mUserWarned(false)
{ {
static const char *sSpecialisations[] =
{
"Combat", "Magic", "Stealth", 0
};
static const char *sAttributes[] =
{
"Strength", "Intelligence", "Willpower", "Agility", "Speed", "Endurance", "Personality",
"Luck", 0
};
static const char *sSpellTypes[] =
{
"Spell", "Ability", "Blight", "Disease", "Curse", "Power", 0
};
static const char *sApparatusTypes[] =
{
"Mortar & Pestle", "Albemic", "Calcinator", "Retort", 0
};
static const char *sArmorTypes[] =
{
"Helmet", "Cuirass", "Left Pauldron", "Right Pauldron", "Greaves", "Boots", "Left Gauntlet",
"Right Gauntlet", "Shield", "Left Bracer", "Right Bracer", 0
};
static const char *sClothingTypes[] =
{
"Pants", "Shoes", "Shirt", "Belt", "Robe", "Right Glove", "Left Glove", "Skirt", "Ring",
"Amulet", 0
};
static const char *sCreatureTypes[] =
{
"Creature", "Deadra", "Undead", "Humanoid", 0
};
static const char *sWeaponTypes[] =
{
"Short Blade 1H", "Long Blade 1H", "Long Blade 2H", "Blunt 1H", "Blunt 2H Close",
"Blunt 2H Wide", "Spear 2H", "Axe 1H", "Axe 2H", "Bow", "Crossbow", "Thrown", "Arrow",
"Bolt", 0
};
mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection; mDelegateFactories = new CSVWorld::CommandDelegateFactoryCollection;
mDelegateFactories->add (CSMWorld::ColumnBase::Display_GmstVarType, mDelegateFactories->add (CSMWorld::ColumnBase::Display_GmstVarType,
@ -44,6 +94,29 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager)
mDelegateFactories->add (CSMWorld::ColumnBase::Display_GlobalVarType, mDelegateFactories->add (CSMWorld::ColumnBase::Display_GlobalVarType,
new CSVWorld::VarTypeDelegateFactory (ESM::VT_Short, ESM::VT_Long, ESM::VT_Float)); new CSVWorld::VarTypeDelegateFactory (ESM::VT_Short, ESM::VT_Long, ESM::VT_Float));
mDelegateFactories->add (CSMWorld::ColumnBase::Display_Specialisation,
new CSVWorld::EnumDelegateFactory (sSpecialisations));
mDelegateFactories->add (CSMWorld::ColumnBase::Display_Attribute,
new CSVWorld::EnumDelegateFactory (sAttributes, true));
mDelegateFactories->add (CSMWorld::ColumnBase::Display_SpellType,
new CSVWorld::EnumDelegateFactory (sSpellTypes));
mDelegateFactories->add (CSMWorld::ColumnBase::Display_ApparatusType,
new CSVWorld::EnumDelegateFactory (sApparatusTypes));
mDelegateFactories->add (CSMWorld::ColumnBase::Display_ArmorType,
new CSVWorld::EnumDelegateFactory (sArmorTypes));
mDelegateFactories->add (CSMWorld::ColumnBase::Display_ClothingType,
new CSVWorld::EnumDelegateFactory (sClothingTypes));
mDelegateFactories->add (CSMWorld::ColumnBase::Display_CreatureType,
new CSVWorld::EnumDelegateFactory (sCreatureTypes));
mDelegateFactories->add (CSMWorld::ColumnBase::Display_WeaponType,
new CSVWorld::EnumDelegateFactory (sWeaponTypes));
} }
CSVDoc::ViewManager::~ViewManager() CSVDoc::ViewManager::~ViewManager()
@ -66,18 +139,11 @@ CSVDoc::View *CSVDoc::ViewManager::addView (CSMDoc::Document *document)
this, SLOT (progress (int, int, int, int, CSMDoc::Document *))); this, SLOT (progress (int, int, int, int, CSMDoc::Document *)));
} }
QMainWindow *mainWindow = new QMainWindow; View *view = new View (*this, document, countViews (document)+1);
View *view = new View (*this, document, countViews (document)+1, mainWindow);
mViews.push_back (view); mViews.push_back (view);
if (mViews.size()==1)
{
QRect scr = QApplication::desktop()->screenGeometry();
QRect rect = view->geometry();
view->move (scr.center().x() - rect.center().x(), scr.center().y() - rect.center().y());
}
view->show(); view->show();
connect (view, SIGNAL (newDocumentRequest ()), this, SIGNAL (newDocumentRequest())); connect (view, SIGNAL (newDocumentRequest ()), this, SIGNAL (newDocumentRequest()));
@ -103,23 +169,143 @@ bool CSVDoc::ViewManager::closeRequest (View *view)
{ {
std::vector<View *>::iterator iter = std::find (mViews.begin(), mViews.end(), view); std::vector<View *>::iterator iter = std::find (mViews.begin(), mViews.end(), view);
bool continueWithClose = true;
if (iter!=mViews.end()) if (iter!=mViews.end())
{ {
bool last = countViews (view->getDocument())<=1; bool last = countViews (view->getDocument())<=1;
/// \todo check if save is in progress -> warn user about possible data loss
/// \todo check if document has not been saved -> return false and start close dialogue
mViews.erase (iter);
view->deleteLater();
if (last) if (last)
mDocumentManager.removeDocument (view->getDocument()); continueWithClose = notifySaveOnClose (view);
else else
{
(*iter)->deleteLater();
mViews.erase (iter);
updateIndices(); updateIndices();
}
} }
return true; return continueWithClose;
}
bool CSVDoc::ViewManager::notifySaveOnClose (CSVDoc::View *view)
{
bool result = true;
CSMDoc::Document *document = view->getDocument();
//notify user of saving in progress
if ( (document->getState() & CSMDoc::State_Saving) )
result = showSaveInProgressMessageBox (view);
//notify user of unsaved changes and process response
else if ( document->getState() & CSMDoc::State_Modified)
result = showModifiedDocumentMessageBox (view);
return result;
}
bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (CSVDoc::View *view)
{
QMessageBox messageBox;
CSMDoc::Document *document = view->getDocument();
messageBox.setText ("The document has been modified.");
messageBox.setInformativeText ("Do you want to save your changes?");
messageBox.setStandardButtons (QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
messageBox.setDefaultButton (QMessageBox::Save);
bool retVal = true;
connect (this, SIGNAL (closeMessageBox()), &messageBox, SLOT (close()));
connect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
mUserWarned = true;
int response = messageBox.exec();
mUserWarned = false;
switch (response)
{
case QMessageBox::Save:
document->save();
mExitOnSaveStateChange = true;
retVal = false;
break;
case QMessageBox::Discard:
disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
break;
case QMessageBox::Cancel:
//disconnect to prevent unintended view closures
disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
retVal = false;
break;
default:
break;
}
return retVal;
}
bool CSVDoc::ViewManager::showSaveInProgressMessageBox (CSVDoc::View *view)
{
QMessageBox messageBox;
CSMDoc::Document *document = view->getDocument();
messageBox.setText ("The document is currently being saved.");
messageBox.setInformativeText("Do you want to close now and abort saving, or wait until saving has completed?");
QPushButton* waitButton = messageBox.addButton (tr("Wait"), QMessageBox::YesRole);
QPushButton* closeButton = messageBox.addButton (tr("Close Now"), QMessageBox::RejectRole);
QPushButton* cancelButton = messageBox.addButton (tr("Cancel"), QMessageBox::NoRole);
messageBox.setDefaultButton (waitButton);
bool retVal = true;
//Connections shut down message box if operation ends before user makes a decision.
connect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
connect (this, SIGNAL (closeMessageBox()), &messageBox, SLOT (close()));
//set / clear the user warned flag to indicate whether or not the message box is currently active.
mUserWarned = true;
messageBox.exec();
mUserWarned = false;
//if closed by the warning handler, defaults to the RejectRole button (closeButton)
if (messageBox.clickedButton() == waitButton)
{
//save the View iterator for shutdown after the save operation ends
mExitOnSaveStateChange = true;
retVal = false;
}
else if (messageBox.clickedButton() == closeButton)
{
//disconnect to avoid segmentation fault
disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
view->abortOperation(CSMDoc::State_Saving);
mExitOnSaveStateChange = true;
}
else if (messageBox.clickedButton() == cancelButton)
{
//abort shutdown, allow save to complete
//disconnection to prevent unintended view closures
mExitOnSaveStateChange = false;
disconnect (document, SIGNAL (stateChanged (int, CSMDoc::Document *)), this, SLOT (onExitWarningHandler(int, CSMDoc::Document *)));
retVal = false;
}
return retVal;
} }
void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *document) void CSVDoc::ViewManager::documentStateChanged (int state, CSMDoc::Document *document)
@ -135,3 +321,25 @@ void CSVDoc::ViewManager::progress (int current, int max, int type, int threads,
if ((*iter)->getDocument()==document) if ((*iter)->getDocument()==document)
(*iter)->updateProgress (current, max, type, threads); (*iter)->updateProgress (current, max, type, threads);
} }
void CSVDoc::ViewManager::onExitWarningHandler (int state, CSMDoc::Document *document)
{
if ( !(state & CSMDoc::State_Saving) )
{
//if the user is being warned (message box is active), shut down the message box,
//as there is no save operation currently running
if ( mUserWarned )
emit closeMessageBox();
//otherwise, the user has closed the message box before the save operation ended.
//exit the application
else if (mExitOnSaveStateChange)
QApplication::instance()->exit();
}
}
void CSVDoc::ViewManager::exitApplication (CSVDoc::View *view)
{
if (notifySaveOnClose (view))
QApplication::instance()->exit();
}

View File

@ -27,12 +27,17 @@ namespace CSVDoc
CSMDoc::DocumentManager& mDocumentManager; CSMDoc::DocumentManager& mDocumentManager;
std::vector<View *> mViews; std::vector<View *> mViews;
CSVWorld::CommandDelegateFactoryCollection *mDelegateFactories; CSVWorld::CommandDelegateFactoryCollection *mDelegateFactories;
bool mExitOnSaveStateChange;
bool mUserWarned;
// not implemented // not implemented
ViewManager (const ViewManager&); ViewManager (const ViewManager&);
ViewManager& operator= (const ViewManager&); ViewManager& operator= (const ViewManager&);
void updateIndices(); void updateIndices();
bool notifySaveOnClose (View *view = 0);
bool showModifiedDocumentMessageBox (View *view);
bool showSaveInProgressMessageBox (View *view);
public: public:
@ -54,13 +59,21 @@ namespace CSVDoc
void loadDocumentRequest(); void loadDocumentRequest();
void closeMessageBox();
public slots:
void exitApplication (CSVDoc::View *view);
private slots: private slots:
void documentStateChanged (int state, CSMDoc::Document *document); void documentStateChanged (int state, CSMDoc::Document *document);
void progress (int current, int max, int type, int threads, CSMDoc::Document *document); void progress (int current, int max, int type, int threads, CSMDoc::Document *document);
void onExitWarningHandler(int state, CSMDoc::Document* document);
}; };
} }
#endif #endif

View File

@ -1,18 +1,19 @@
#include "abstractblock.hpp" #include "abstractblock.hpp"
CsSettings::AbstractBlock::AbstractBlock(QWidget* parent) CSVSettings::AbstractBlock::AbstractBlock(QWidget* parent)
: QObject (parent), mBox ( new GroupBox (parent) ), mWidgetParent (parent) : QObject (parent), mBox ( new GroupBox (parent) ), mWidgetParent (parent)
{} {}
CsSettings::AbstractBlock::AbstractBlock(bool isVisible, QWidget* parent) CSVSettings::AbstractBlock::AbstractBlock(bool isVisible, QWidget* parent)
: QObject (parent), mBox ( new GroupBox (isVisible, parent)), mWidgetParent (parent) : QObject (parent), mBox ( new GroupBox (isVisible, parent)), mWidgetParent (parent)
{} {}
QLayout *CsSettings::AbstractBlock::createLayout (OcsWidgetOrientation direction, bool isZeroMargin, QWidget* parent) QLayout *CSVSettings::AbstractBlock::createLayout (Orientation direction,
bool isZeroMargin, QWidget* parent)
{ {
QLayout *layout = 0; QLayout *layout = 0;
if (direction == OCS_VERTICAL) if (direction == Orient_Vertical)
layout = new QVBoxLayout (parent); layout = new QVBoxLayout (parent);
else else
layout = new QHBoxLayout (parent); layout = new QHBoxLayout (parent);
@ -23,40 +24,40 @@ QLayout *CsSettings::AbstractBlock::createLayout (OcsWidgetOrientation direction
return layout; return layout;
} }
QGroupBox *CsSettings::AbstractBlock::getGroupBox() QGroupBox *CSVSettings::AbstractBlock::getGroupBox()
{ {
return mBox; return mBox;
} }
CsSettings::AbstractWidget *CsSettings::AbstractBlock::buildWidget (const QString& widgetName, WidgetDef &def, CSVSettings::AbstractWidget *CSVSettings::AbstractBlock::buildWidget (const QString& widgetName, WidgetDef &def,
QLayout *layout, bool isConnected) const QLayout *layout, bool isConnected) const
{ {
AbstractWidget *widg = 0; AbstractWidget *widg = 0;
switch (def.type) switch (def.type)
{ {
case OCS_RADIO_WIDGET: case Widget_RadioButton:
widg = createSettingWidget<QRadioButton> (def, layout); widg = createSettingWidget<QRadioButton> (def, layout);
break; break;
case OCS_SPIN_WIDGET: case Widget_SpinBox:
widg = createSettingWidget<QSpinBox> (def, layout); widg = createSettingWidget<QSpinBox> (def, layout);
break; break;
case OCS_CHECK_WIDGET: case Widget_CheckBox:
widg = createSettingWidget<QCheckBox> (def, layout); widg = createSettingWidget<QCheckBox> (def, layout);
break; break;
case OCS_TEXT_WIDGET: case Widget_LineEdit:
widg = createSettingWidget<QLineEdit> (def, layout); widg = createSettingWidget<QLineEdit> (def, layout);
break; break;
case OCS_LIST_WIDGET: case Widget_ListBox:
widg = createSettingWidget<QListWidget> (def, layout); widg = createSettingWidget<QListWidget> (def, layout);
break; break;
case OCS_COMBO_WIDGET: case Widget_ComboBox:
widg = createSettingWidget<QComboBox> (def, layout); widg = createSettingWidget<QComboBox> (def, layout);
break; break;
@ -76,32 +77,32 @@ CsSettings::AbstractWidget *CsSettings::AbstractBlock::buildWidget (const QStrin
return widg; return widg;
} }
void CsSettings::AbstractBlock::setVisible (bool isVisible) void CSVSettings::AbstractBlock::setVisible (bool isVisible)
{ {
mBox->setBorderVisibility (isVisible); mBox->setBorderVisibility (isVisible);
} }
bool CsSettings::AbstractBlock::isVisible () const bool CSVSettings::AbstractBlock::isVisible () const
{ {
return mBox->borderVisibile(); return mBox->borderVisibile();
} }
QWidget *CsSettings::AbstractBlock::getParent() const QWidget *CSVSettings::AbstractBlock::getParent() const
{ {
return mWidgetParent; return mWidgetParent;
} }
void CsSettings::AbstractBlock::slotUpdate (const QString &value) void CSVSettings::AbstractBlock::slotUpdate (const QString &value)
{ {
slotUpdateSetting (objectName(), value); slotUpdateSetting (objectName(), value);
} }
void CsSettings::AbstractBlock::slotSetEnabled(bool value) void CSVSettings::AbstractBlock::slotSetEnabled(bool value)
{ {
mBox->setEnabled(value); mBox->setEnabled(value);
} }
void CsSettings::AbstractBlock::slotUpdateSetting (const QString &settingName, const QString &settingValue) void CSVSettings::AbstractBlock::slotUpdateSetting (const QString &settingName, const QString &settingValue)
{ {
bool doEmit = true; bool doEmit = true;
updateBySignal (settingName, settingValue, doEmit); updateBySignal (settingName, settingValue, doEmit);

View File

@ -5,10 +5,10 @@
#include <QList> #include <QList>
#include "settingwidget.hpp" #include "settingwidget.hpp"
#include "settingsitem.hpp" #include "../../model/settings/settingsitem.hpp"
#include "groupbox.hpp" #include "groupbox.hpp"
namespace CsSettings namespace CSVSettings
{ {
class AbstractBlock : public QObject class AbstractBlock : public QObject
@ -17,7 +17,7 @@ namespace CsSettings
protected: protected:
typedef QMap<QString, SettingsItem*> SettingsItemMap; typedef QMap<QString, CSMSettings::SettingsItem*> SettingsItemMap;
GroupBox *mBox; GroupBox *mBox;
QWidget *mWidgetParent; QWidget *mWidgetParent;
@ -30,14 +30,14 @@ namespace CsSettings
void setVisible (bool isVisible); void setVisible (bool isVisible);
bool isVisible() const; bool isVisible() const;
virtual SettingList *getSettings() = 0; virtual CSMSettings::SettingList *getSettings() = 0;
virtual bool updateSettings (const SettingMap &settings) = 0; virtual bool updateSettings (const CSMSettings::SettingMap &settings) = 0;
virtual bool updateBySignal (const QString &name, const QString &value, bool &doEmit) virtual bool updateBySignal (const QString &name, const QString &value, bool &doEmit)
{ return false; } { return false; }
protected: protected:
QLayout *createLayout (OcsWidgetOrientation direction, bool isZeroMargin, QWidget* parent = 0); QLayout *createLayout (Orientation direction, bool isZeroMargin, QWidget* parent = 0);
AbstractWidget *buildWidget (const QString &widgetName, WidgetDef &wDef, AbstractWidget *buildWidget (const QString &widgetName, WidgetDef &wDef,
QLayout *layout = 0, bool isConnected = true) const; QLayout *layout = 0, bool isConnected = true) const;

View File

@ -10,28 +10,28 @@
#include <QLineEdit> #include <QLineEdit>
#include <QMargins> #include <QMargins>
CsSettings::AbstractPage::AbstractPage(QWidget *parent): CSVSettings::AbstractPage::AbstractPage(QWidget *parent):
QWidget(parent) QWidget(parent)
{ {
} }
CsSettings::AbstractPage::AbstractPage(const QString &pageName, QWidget *parent): CSVSettings::AbstractPage::AbstractPage(const QString &pageName, QWidget *parent):
QWidget(parent) QWidget(parent)
{ {
QWidget::setObjectName (pageName); QWidget::setObjectName (pageName);
} }
CsSettings::AbstractPage::~AbstractPage() CSVSettings::AbstractPage::~AbstractPage()
{ {
} }
CsSettings::SettingList *CsSettings::AbstractPage::getSettings() CSMSettings::SettingList *CSVSettings::AbstractPage::getSettings()
{ {
SettingList *settings = new SettingList(); CSMSettings::SettingList *settings = new CSMSettings::SettingList();
foreach (AbstractBlock *block, mAbstractBlocks) foreach (AbstractBlock *block, mAbstractBlocks)
{ {
SettingList *groupSettings = block->getSettings(); CSMSettings::SettingList *groupSettings = block->getSettings();
settings->append (*groupSettings); settings->append (*groupSettings);
} }

View File

@ -10,15 +10,13 @@
class SettingMap; class SettingMap;
class SettingList; class SettingList;
namespace CsSettings { namespace CSVSettings {
typedef QList<AbstractBlock *> AbstractBlockList; typedef QList<AbstractBlock *> AbstractBlockList;
class AbstractPage: public QWidget class AbstractPage: public QWidget
{ {
Q_OBJECT
protected: protected:
AbstractBlockList mAbstractBlocks; AbstractBlockList mAbstractBlocks;
@ -32,9 +30,9 @@ namespace CsSettings {
virtual void setupUi()=0; virtual void setupUi()=0;
virtual void initializeWidgets (const SettingMap &settings) = 0; virtual void initializeWidgets (const CSMSettings::SettingMap &settings) = 0;
SettingList *getSettings(); CSMSettings::SettingList *getSettings();
void setObjectName(); void setObjectName();

View File

@ -3,7 +3,7 @@
#include <QLayout> #include <QLayout>
#include <QLabel> #include <QLabel>
void CsSettings::AbstractWidget::build(QWidget *widget, WidgetDef &def, bool noLabel) void CSVSettings::AbstractWidget::build(QWidget *widget, WidgetDef &def, bool noLabel)
{ {
if (!mLayout) if (!mLayout)
createLayout(def.orientation, true); createLayout(def.orientation, true);
@ -12,7 +12,7 @@ void CsSettings::AbstractWidget::build(QWidget *widget, WidgetDef &def, bool noL
} }
void CsSettings::AbstractWidget::buildLabelAndWidget (QWidget *widget, WidgetDef &def, bool noLabel) void CSVSettings::AbstractWidget::buildLabelAndWidget (QWidget *widget, WidgetDef &def, bool noLabel)
{ {
if (def.widgetWidth > -1) if (def.widgetWidth > -1)
widget->setFixedWidth (def.widgetWidth); widget->setFixedWidth (def.widgetWidth);
@ -31,10 +31,10 @@ void CsSettings::AbstractWidget::buildLabelAndWidget (QWidget *widget, WidgetDef
mLayout->setAlignment (widget, getAlignment (def.widgetAlignment)); mLayout->setAlignment (widget, getAlignment (def.widgetAlignment));
} }
void CsSettings::AbstractWidget::createLayout void CSVSettings::AbstractWidget::createLayout
(OcsWidgetOrientation direction, bool isZeroMargin) (Orientation direction, bool isZeroMargin)
{ {
if (direction == OCS_VERTICAL) if (direction == Orient_Vertical)
mLayout = new QVBoxLayout (); mLayout = new QVBoxLayout ();
else else
mLayout = new QHBoxLayout (); mLayout = new QHBoxLayout ();
@ -43,36 +43,36 @@ void CsSettings::AbstractWidget::createLayout
mLayout->setContentsMargins(0, 0, 0, 0); mLayout->setContentsMargins(0, 0, 0, 0);
} }
QFlags<Qt::AlignmentFlag> CsSettings::AbstractWidget::getAlignment (CsSettings::OcsAlignment flag) QFlags<Qt::AlignmentFlag> CSVSettings::AbstractWidget::getAlignment (CSVSettings::Alignment flag)
{ {
return QFlags<Qt::AlignmentFlag>(static_cast<int>(flag)); return QFlags<Qt::AlignmentFlag>(static_cast<int>(flag));
} }
QLayout *CsSettings::AbstractWidget::getLayout() QLayout *CSVSettings::AbstractWidget::getLayout()
{ {
return mLayout; return mLayout;
} }
void CsSettings::AbstractWidget::slotUpdateWidget (const QString &value) void CSVSettings::AbstractWidget::slotUpdateWidget (const QString &value)
{ {
updateWidget (value); updateWidget (value);
} }
void CsSettings::AbstractWidget::slotUpdateItem(const QString &value) void CSVSettings::AbstractWidget::slotUpdateItem(const QString &value)
{ {
emit signalUpdateItem (value); emit signalUpdateItem (value);
} }
void CsSettings::AbstractWidget::slotUpdateItem(bool value) void CSVSettings::AbstractWidget::slotUpdateItem(bool value)
{ {
if (value) if (value)
emit signalUpdateItem (widget()->objectName()); emit signalUpdateItem (widget()->objectName());
} }
void CsSettings::AbstractWidget::slotUpdateItem(int value) void CSVSettings::AbstractWidget::slotUpdateItem(int value)
{ {
emit signalUpdateItem (QString::number(value)); emit signalUpdateItem (QString::number(value));
} }
void CsSettings::AbstractWidget::slotUpdateItem (QListWidgetItem* current, QListWidgetItem* previous) void CSVSettings::AbstractWidget::slotUpdateItem (QListWidgetItem* current, QListWidgetItem* previous)
{} {}

View File

@ -6,7 +6,7 @@
class QLayout; class QLayout;
namespace CsSettings namespace CSVSettings
{ {
class AbstractWidget : public QObject class AbstractWidget : public QObject
{ {
@ -35,12 +35,12 @@ namespace CsSettings
virtual void updateWidget (const QString &value) = 0; virtual void updateWidget (const QString &value) = 0;
//converts user-defined enum to Qt equivalents //converts user-defined enum to Qt equivalents
QFlags<Qt::AlignmentFlag> getAlignment (CsSettings::OcsAlignment flag); QFlags<Qt::AlignmentFlag> getAlignment (Alignment flag);
private: private:
//widget initialization utilities //widget initialization utilities
void createLayout (CsSettings::OcsWidgetOrientation direction, bool isZeroMargin); void createLayout (Orientation direction, bool isZeroMargin);
void buildLabelAndWidget (QWidget *widget, WidgetDef &def, bool noLabel); void buildLabelAndWidget (QWidget *widget, WidgetDef &def, bool noLabel);

View File

@ -13,23 +13,23 @@
#include <QPlastiqueStyle> #include <QPlastiqueStyle>
#endif #endif
#include "usersettings.hpp" #include "../../model/settings/usersettings.hpp"
#include "groupblock.hpp" #include "groupblock.hpp"
#include "toggleblock.hpp" #include "toggleblock.hpp"
CsSettings::BlankPage::BlankPage(QWidget *parent): CSVSettings::BlankPage::BlankPage(QWidget *parent):
AbstractPage("Blank", parent) AbstractPage("Blank", parent)
{ {
initPage(); initPage();
} }
CsSettings::BlankPage::BlankPage(const QString &title, QWidget *parent): CSVSettings::BlankPage::BlankPage(const QString &title, QWidget *parent):
AbstractPage(title, parent) AbstractPage(title, parent)
{ {
initPage(); initPage();
} }
void CsSettings::BlankPage::initPage() void CSVSettings::BlankPage::initPage()
{ {
// Hacks to get the stylesheet look properly // Hacks to get the stylesheet look properly
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
@ -40,7 +40,7 @@ void CsSettings::BlankPage::initPage()
setupUi(); setupUi();
} }
void CsSettings::BlankPage::setupUi() void CSVSettings::BlankPage::setupUi()
{ {
QGroupBox *pageBox = new QGroupBox(this); QGroupBox *pageBox = new QGroupBox(this);
QLayout* pageLayout = new QVBoxLayout(); QLayout* pageLayout = new QVBoxLayout();
@ -49,7 +49,7 @@ void CsSettings::BlankPage::setupUi()
pageLayout->addWidget(pageBox); pageLayout->addWidget(pageBox);
} }
void CsSettings::BlankPage::initializeWidgets (const SettingMap &settings) void CSVSettings::BlankPage::initializeWidgets (const CSMSettings::SettingMap &settings)
{ {
//iterate each item in each blocks in this section //iterate each item in each blocks in this section
//validate the corresponding setting against the defined valuelist if any. //validate the corresponding setting against the defined valuelist if any.

View File

@ -5,14 +5,13 @@
class QGroupBox; class QGroupBox;
namespace CsSettings { namespace CSVSettings {
class UserSettings; class UserSettings;
class AbstractBlock; class AbstractBlock;
class BlankPage : public AbstractPage class BlankPage : public AbstractPage
{ {
Q_OBJECT
public: public:
@ -20,7 +19,7 @@ namespace CsSettings {
BlankPage (const QString &title, QWidget *parent); BlankPage (const QString &title, QWidget *parent);
void setupUi(); void setupUi();
void initializeWidgets (const SettingMap &settings); void initializeWidgets (const CSMSettings::SettingMap &settings);
private: private:
void initPage(); void initPage();

View File

@ -3,11 +3,11 @@
#include "itemblock.hpp" #include "itemblock.hpp"
#include "proxyblock.hpp" #include "proxyblock.hpp"
CsSettings::CustomBlock::CustomBlock (QWidget *parent) : AbstractBlock (parent) CSVSettings::CustomBlock::CustomBlock (QWidget *parent) : AbstractBlock (parent)
{ {
} }
int CsSettings::CustomBlock::build(GroupBlockDefList &defList, GroupBlockDefList::iterator *it) int CSVSettings::CustomBlock::build(GroupBlockDefList &defList, GroupBlockDefList::iterator *it)
{ {
int retVal = 0; int retVal = 0;
@ -37,7 +37,7 @@ int CsSettings::CustomBlock::build(GroupBlockDefList &defList, GroupBlockDefList
return retVal; return retVal;
} }
CsSettings::GroupBox *CsSettings::CustomBlock::buildGroupBox (CsSettings::OcsWidgetOrientation orientation) CSVSettings::GroupBox *CSVSettings::CustomBlock::buildGroupBox (Orientation orientation)
{ {
GroupBox *box = new GroupBox (false, mBox); GroupBox *box = new GroupBox (false, mBox);
QLayout *layout = createLayout (orientation, true, box); QLayout *layout = createLayout (orientation, true, box);
@ -45,7 +45,7 @@ CsSettings::GroupBox *CsSettings::CustomBlock::buildGroupBox (CsSettings::OcsWid
return box; return box;
} }
int CsSettings::CustomBlock::buildGroupBlock(GroupBlockDef &def) int CSVSettings::CustomBlock::buildGroupBlock(GroupBlockDef &def)
{ {
GroupBlock *block = new GroupBlock (getParent()); GroupBlock *block = new GroupBlock (getParent());
@ -57,7 +57,7 @@ int CsSettings::CustomBlock::buildGroupBlock(GroupBlockDef &def)
return block->build(def); return block->build(def);
} }
int CsSettings::CustomBlock::buildProxyBlock(GroupBlockDef& def, ProxyBlock *block) int CSVSettings::CustomBlock::buildProxyBlock(GroupBlockDef& def, ProxyBlock *block)
{ {
if (def.properties.size() != 1) if (def.properties.size() != 1)
return -1; return -1;
@ -91,13 +91,13 @@ int CsSettings::CustomBlock::buildProxyBlock(GroupBlockDef& def, ProxyBlock *blo
return 0; return 0;
} }
CsSettings::SettingList *CsSettings::CustomBlock::getSettings() CSMSettings::SettingList *CSVSettings::CustomBlock::getSettings()
{ {
SettingList *settings = new SettingList(); CSMSettings::SettingList *settings = new CSMSettings::SettingList();
foreach (GroupBlock *block, mGroupList) foreach (GroupBlock *block, mGroupList)
{ {
SettingList *groupSettings = block->getSettings(); CSMSettings::SettingList *groupSettings = block->getSettings();
if (groupSettings) if (groupSettings)
settings->append(*groupSettings); settings->append(*groupSettings);
@ -106,7 +106,7 @@ CsSettings::SettingList *CsSettings::CustomBlock::getSettings()
return settings; return settings;
} }
bool CsSettings::CustomBlock::updateSettings (const SettingMap &settings) bool CSVSettings::CustomBlock::updateSettings (const CSMSettings::SettingMap &settings)
{ {
bool success = true; bool success = true;

View File

@ -3,7 +3,7 @@
#include "abstractblock.hpp" #include "abstractblock.hpp"
namespace CsSettings namespace CSVSettings
{ {
class ProxyBlock; class ProxyBlock;
@ -19,13 +19,13 @@ namespace CsSettings
explicit CustomBlock (QWidget *parent = 0); explicit CustomBlock (QWidget *parent = 0);
bool updateSettings (const SettingMap &settings); bool updateSettings (const CSMSettings::SettingMap &settings);
SettingList *getSettings(); CSMSettings::SettingList *getSettings();
int build (GroupBlockDefList &defList, GroupBlockDefList::Iterator *it = 0); int build (GroupBlockDefList &defList, GroupBlockDefList::Iterator *it = 0);
protected: protected:
GroupBox *buildGroupBox (OcsWidgetOrientation orientation); GroupBox *buildGroupBox (Orientation orientation);
private: private:

View File

@ -13,11 +13,11 @@
#include <QPlastiqueStyle> #include <QPlastiqueStyle>
#endif #endif
#include "usersettings.hpp" #include "../../model/settings/usersettings.hpp"
#include "groupblock.hpp" #include "groupblock.hpp"
#include "toggleblock.hpp" #include "toggleblock.hpp"
CsSettings::EditorPage::EditorPage(QWidget *parent): CSVSettings::EditorPage::EditorPage(QWidget *parent):
AbstractPage("Editor", parent) AbstractPage("Editor", parent)
{ {
// Hacks to get the stylesheet look properly // Hacks to get the stylesheet look properly
@ -29,7 +29,7 @@ CsSettings::EditorPage::EditorPage(QWidget *parent):
setupUi(); setupUi();
} }
void CsSettings::EditorPage::setupUi() void CSVSettings::EditorPage::setupUi()
{ {
GroupBlockDef undoStack (QString("Undo Stack Size")); GroupBlockDef undoStack (QString("Undo Stack Size"));
GroupBlockDef topLevelWindowCount (QString("Maximum Top-Level Window Count")); GroupBlockDef topLevelWindowCount (QString("Maximum Top-Level Window Count"));
@ -48,7 +48,7 @@ void CsSettings::EditorPage::setupUi()
undoStackItem->minMax.left = "0"; undoStackItem->minMax.left = "0";
undoStackItem->minMax.right = "64"; undoStackItem->minMax.right = "64";
WidgetDef stackWidget (OCS_SPIN_WIDGET); WidgetDef stackWidget (Widget_SpinBox);
stackWidget.minMax = &(undoStackItem->minMax); stackWidget.minMax = &(undoStackItem->minMax);
stackWidget.widgetWidth = 50; stackWidget.widgetWidth = 50;
@ -63,7 +63,7 @@ void CsSettings::EditorPage::setupUi()
topLevelItem->minMax.left = "1"; topLevelItem->minMax.left = "1";
topLevelItem->minMax.right = "256"; topLevelItem->minMax.right = "256";
WidgetDef topLvlWinWidget (OCS_SPIN_WIDGET); WidgetDef topLvlWinWidget (Widget_SpinBox);
topLvlWinWidget.minMax = &(topLevelItem->minMax); topLvlWinWidget.minMax = &(topLevelItem->minMax);
topLvlWinWidget.widgetWidth = 50; topLvlWinWidget.widgetWidth = 50;
@ -76,9 +76,9 @@ void CsSettings::EditorPage::setupUi()
SettingsItemDef *reuseSubItem = new SettingsItemDef (reuseSubwindow.title, "Reuse Subwindows"); SettingsItemDef *reuseSubItem = new SettingsItemDef (reuseSubwindow.title, "Reuse Subwindows");
*(reuseSubItem->valueList) << "None" << "Top-Level" << "Document-Level"; *(reuseSubItem->valueList) << "None" << "Top-Level" << "Document-Level";
WidgetDef reuseSubWidget (OCS_RADIO_WIDGET); WidgetDef reuseSubWidget (Widget_RadioButton);
reuseSubWidget.valueList = (reuseSubItem->valueList); reuseSubWidget.valueList = (reuseSubItem->valueList);
reuseSubWidget.widgetAlignment = OCS_LEFT; reuseSubWidget.widgetAlignment = Align_Left;
reuseSubwindow.properties << reuseSubItem; reuseSubwindow.properties << reuseSubItem;
reuseSubItem->widget = reuseSubWidget; reuseSubItem->widget = reuseSubWidget;
@ -89,23 +89,23 @@ void CsSettings::EditorPage::setupUi()
//custom width //custom width
SettingsItemDef *widthItem = new SettingsItemDef ("Window Width", "640"); SettingsItemDef *widthItem = new SettingsItemDef ("Window Width", "640");
widthItem->widget = WidgetDef (OCS_TEXT_WIDGET); widthItem->widget = WidgetDef (Widget_LineEdit);
widthItem->widget.widgetWidth = 45; widthItem->widget.widgetWidth = 45;
//custom height //custom height
SettingsItemDef *heightItem = new SettingsItemDef ("Window Height", "480"); SettingsItemDef *heightItem = new SettingsItemDef ("Window Height", "480");
heightItem->widget = WidgetDef (OCS_TEXT_WIDGET); heightItem->widget = WidgetDef (Widget_LineEdit);
heightItem->widget.widgetWidth = 45; heightItem->widget.widgetWidth = 45;
heightItem->widget.caption = "x"; heightItem->widget.caption = "x";
customWindowSize.properties << widthItem << heightItem; customWindowSize.properties << widthItem << heightItem;
customWindowSize.widgetOrientation = OCS_HORIZONTAL; customWindowSize.widgetOrientation = Orient_Horizontal;
customWindowSize.isVisible = false; customWindowSize.isVisible = false;
//pre-defined //pre-defined
SettingsItemDef *widthByHeightItem = new SettingsItemDef ("Window Size", "640x480"); SettingsItemDef *widthByHeightItem = new SettingsItemDef ("Window Size", "640x480");
WidgetDef widthByHeightWidget = WidgetDef (OCS_COMBO_WIDGET); WidgetDef widthByHeightWidget = WidgetDef (Widget_ComboBox);
widthByHeightWidget.widgetWidth = 90; widthByHeightWidget.widgetWidth = 90;
*(widthByHeightItem->valueList) << "640x480" << "800x600" << "1024x768"; *(widthByHeightItem->valueList) << "640x480" << "800x600" << "1024x768";
@ -125,12 +125,12 @@ void CsSettings::EditorPage::setupUi()
// window size toggle // window size toggle
windowSizeToggle.captions << "Pre-Defined" << "Custom"; windowSizeToggle.captions << "Pre-Defined" << "Custom";
windowSizeToggle.widgetOrientation = OCS_VERTICAL; windowSizeToggle.widgetOrientation = Orient_Vertical;
windowSizeToggle.isVisible = false; windowSizeToggle.isVisible = false;
//define a widget for each group in the toggle //define a widget for each group in the toggle
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
windowSizeToggle.widgets << new WidgetDef (OCS_RADIO_WIDGET); windowSizeToggle.widgets << new WidgetDef (Widget_RadioButton);
windowSizeToggle.widgets.at(0)->isDefault = false; windowSizeToggle.widgets.at(0)->isDefault = false;
@ -153,7 +153,7 @@ void CsSettings::EditorPage::setupUi()
} }
} }
void CsSettings::EditorPage::initializeWidgets (const SettingMap &settings) void CSVSettings::EditorPage::initializeWidgets (const CSMSettings::SettingMap &settings)
{ {
//iterate each item in each blocks in this section //iterate each item in each blocks in this section
//validate the corresponding setting against the defined valuelist if any. //validate the corresponding setting against the defined valuelist if any.

View File

@ -5,7 +5,7 @@
class QGroupBox; class QGroupBox;
namespace CsSettings { namespace CSVSettings {
class UserSettings; class UserSettings;
class AbstractBlock; class AbstractBlock;
@ -19,7 +19,7 @@ namespace CsSettings {
EditorPage(QWidget *parent = 0); EditorPage(QWidget *parent = 0);
void setupUi(); void setupUi();
void initializeWidgets (const SettingMap &settings); void initializeWidgets (const CSMSettings::SettingMap &settings);
signals: signals:
void signalUpdateEditorSetting (const QString &settingName, const QString &settingValue); void signalUpdateEditorSetting (const QString &settingName, const QString &settingValue);

View File

@ -1,15 +1,15 @@
#include "groupblock.hpp" #include "groupblock.hpp"
#include "itemblock.hpp" #include "itemblock.hpp"
CsSettings::GroupBlock::GroupBlock (QWidget* parent) CSVSettings::GroupBlock::GroupBlock (QWidget* parent)
: AbstractBlock (parent) : AbstractBlock (parent)
{} {}
CsSettings::GroupBlock::GroupBlock (bool isVisible, QWidget *parent) CSVSettings::GroupBlock::GroupBlock (bool isVisible, QWidget *parent)
: AbstractBlock (isVisible, parent) : AbstractBlock (isVisible, parent)
{} {}
int CsSettings::GroupBlock::build (GroupBlockDef &def) int CSVSettings::GroupBlock::build (GroupBlockDef &def)
{ {
if (def.properties.size() == 0) if (def.properties.size() == 0)
@ -44,14 +44,14 @@ int CsSettings::GroupBlock::build (GroupBlockDef &def)
return retVal; return retVal;
} }
CsSettings::SettingList *CsSettings::GroupBlock::getSettings() CSMSettings::SettingList *CSVSettings::GroupBlock::getSettings()
{ {
SettingList *settings = 0; CSMSettings::SettingList *settings = 0;
foreach (ItemBlock *block, mItemBlockList) foreach (ItemBlock *block, mItemBlockList)
{ {
if (!settings) if (!settings)
settings = new SettingList(); settings = new CSMSettings::SettingList();
settings->append(*(block->getSettings ())); settings->append(*(block->getSettings ()));
} }
@ -59,7 +59,7 @@ CsSettings::SettingList *CsSettings::GroupBlock::getSettings()
return settings; return settings;
} }
CsSettings::ItemBlock *CsSettings::GroupBlock::getItemBlock (const QString &name, ItemBlockList *blockList) CSVSettings::ItemBlock *CSVSettings::GroupBlock::getItemBlock (const QString &name, ItemBlockList *blockList)
{ {
ItemBlock *retBlock = 0; ItemBlock *retBlock = 0;
@ -78,7 +78,7 @@ CsSettings::ItemBlock *CsSettings::GroupBlock::getItemBlock (const QString &name
return retBlock; return retBlock;
} }
CsSettings::ItemBlock *CsSettings::GroupBlock::getItemBlock (int index) CSVSettings::ItemBlock *CSVSettings::GroupBlock::getItemBlock (int index)
{ {
ItemBlock *retBlock = 0; ItemBlock *retBlock = 0;
@ -88,14 +88,14 @@ CsSettings::ItemBlock *CsSettings::GroupBlock::getItemBlock (int index)
return retBlock; return retBlock;
} }
bool CsSettings::GroupBlock::updateSettings (const SettingMap &settings) bool CSVSettings::GroupBlock::updateSettings (const CSMSettings::SettingMap &settings)
{ {
bool success = true; bool success = true;
//update all non-proxy settings //update all non-proxy settings
foreach (ItemBlock *block, mItemBlockList) foreach (ItemBlock *block, mItemBlockList)
{ {
SettingContainer *setting = settings[block->objectName()]; CSMSettings::SettingContainer *setting = settings[block->objectName()];
if (setting) if (setting)
{ {

View File

@ -4,7 +4,7 @@
#include <QList> #include <QList>
#include "abstractblock.hpp" #include "abstractblock.hpp"
namespace CsSettings namespace CSVSettings
{ {
class ItemBlock; class ItemBlock;
@ -18,9 +18,9 @@ namespace CsSettings
int build (GroupBlockDef &def); int build (GroupBlockDef &def);
bool updateSettings (const SettingMap &settings); bool updateSettings (const CSMSettings::SettingMap &settings);
SettingList *getSettings(); CSMSettings::SettingList *getSettings();
ItemBlock *getItemBlock (const QString &name, ItemBlockList *blockList = 0); ItemBlock *getItemBlock (const QString &name, ItemBlockList *blockList = 0);
ItemBlock *getItemBlock (int index); ItemBlock *getItemBlock (int index);

View File

@ -1,21 +1,21 @@
#include "groupbox.hpp" #include "groupbox.hpp"
const QString CsSettings::GroupBox::INVISIBLE_BOX_STYLE = const QString CSVSettings::GroupBox::INVISIBLE_BOX_STYLE =
QString::fromUtf8("QGroupBox { border: 0px; padding 0px; margin: 0px;}"); QString::fromUtf8("QGroupBox { border: 0px; padding 0px; margin: 0px;}");
CsSettings::GroupBox::GroupBox(QWidget *parent) : CSVSettings::GroupBox::GroupBox(QWidget *parent) :
QGroupBox (parent) QGroupBox (parent)
{ {
initBox(); initBox();
} }
CsSettings::GroupBox::GroupBox (bool isVisible, QWidget *parent) : CSVSettings::GroupBox::GroupBox (bool isVisible, QWidget *parent) :
QGroupBox (parent) QGroupBox (parent)
{ {
initBox(isVisible); initBox(isVisible);
} }
void CsSettings::GroupBox::initBox(bool isVisible) void CSVSettings::GroupBox::initBox(bool isVisible)
{ {
setFlat (true); setFlat (true);
VISIBLE_BOX_STYLE = styleSheet(); VISIBLE_BOX_STYLE = styleSheet();
@ -24,12 +24,12 @@ void CsSettings::GroupBox::initBox(bool isVisible)
setStyleSheet (INVISIBLE_BOX_STYLE); setStyleSheet (INVISIBLE_BOX_STYLE);
} }
bool CsSettings::GroupBox::borderVisibile() const bool CSVSettings::GroupBox::borderVisibile() const
{ {
return (styleSheet() != INVISIBLE_BOX_STYLE); return (styleSheet() != INVISIBLE_BOX_STYLE);
} }
void CsSettings::GroupBox::setTitle (const QString &title) void CSVSettings::GroupBox::setTitle (const QString &title)
{ {
if (borderVisibile() ) if (borderVisibile() )
{ {
@ -38,7 +38,7 @@ void CsSettings::GroupBox::setTitle (const QString &title)
} }
} }
void CsSettings::GroupBox::setBorderVisibility (bool value) void CSVSettings::GroupBox::setBorderVisibility (bool value)
{ {
if (value) if (value)
setStyleSheet(VISIBLE_BOX_STYLE); setStyleSheet(VISIBLE_BOX_STYLE);
@ -46,7 +46,7 @@ void CsSettings::GroupBox::setBorderVisibility (bool value)
setStyleSheet(INVISIBLE_BOX_STYLE); setStyleSheet(INVISIBLE_BOX_STYLE);
} }
void CsSettings::GroupBox::setMinimumWidth() void CSVSettings::GroupBox::setMinimumWidth()
{ {
//set minimum width to accommodate title, if needed //set minimum width to accommodate title, if needed
//1.5 multiplier to account for bold title. //1.5 multiplier to account for bold title.

View File

@ -3,12 +3,10 @@
#include <QGroupBox> #include <QGroupBox>
namespace CsSettings namespace CSVSettings
{ {
class GroupBox : public QGroupBox class GroupBox : public QGroupBox
{ {
Q_OBJECT
static const QString INVISIBLE_BOX_STYLE; static const QString INVISIBLE_BOX_STYLE;
QString VISIBLE_BOX_STYLE; //not a const... QString VISIBLE_BOX_STYLE; //not a const...

View File

@ -2,12 +2,12 @@
#include <QFontMetrics> #include <QFontMetrics>
CsSettings::ItemBlock::ItemBlock (QWidget* parent) CSVSettings::ItemBlock::ItemBlock (QWidget* parent)
: mSetting (0), AbstractBlock (false, parent) : mSetting (0), AbstractBlock (false, parent)
{ {
} }
int CsSettings::ItemBlock::build(SettingsItemDef &iDef) int CSVSettings::ItemBlock::build(SettingsItemDef &iDef)
{ {
buildItemBlock (iDef); buildItemBlock (iDef);
buildItemBlockWidgets (iDef); buildItemBlockWidgets (iDef);
@ -15,7 +15,7 @@ int CsSettings::ItemBlock::build(SettingsItemDef &iDef)
return 0; return 0;
} }
void CsSettings::ItemBlock::buildItemBlockWidgets (SettingsItemDef &iDef) void CSVSettings::ItemBlock::buildItemBlockWidgets (SettingsItemDef &iDef)
{ {
WidgetDef wDef = iDef.widget; WidgetDef wDef = iDef.widget;
QLayout *blockLayout = 0; QLayout *blockLayout = 0;
@ -24,8 +24,8 @@ void CsSettings::ItemBlock::buildItemBlockWidgets (SettingsItemDef &iDef)
switch (wDef.type) switch (wDef.type)
{ {
case OCS_CHECK_WIDGET: case Widget_CheckBox:
case OCS_RADIO_WIDGET: case Widget_RadioButton:
foreach (QString item, *(iDef.valueList)) foreach (QString item, *(iDef.valueList))
{ {
@ -37,8 +37,8 @@ void CsSettings::ItemBlock::buildItemBlockWidgets (SettingsItemDef &iDef)
break; break;
case OCS_COMBO_WIDGET: case Widget_ComboBox:
case OCS_LIST_WIDGET: case Widget_ListBox:
//assign the item's value list to the widget's value list. //assign the item's value list to the widget's value list.
//pass through to default to finish widget construction. //pass through to default to finish widget construction.
@ -56,13 +56,13 @@ void CsSettings::ItemBlock::buildItemBlockWidgets (SettingsItemDef &iDef)
} }
} }
void CsSettings::ItemBlock::buildItemBlock (SettingsItemDef &iDef) void CSVSettings::ItemBlock::buildItemBlock (SettingsItemDef &iDef)
{ {
QString defaultValue = iDef.defaultValue; QString defaultValue = iDef.defaultValue;
setObjectName(iDef.name); setObjectName(iDef.name);
mSetting = new SettingsItem (objectName(), mSetting = new CSMSettings::SettingsItem (objectName(),
iDef.hasMultipleValues, iDef.defaultValue, iDef.hasMultipleValues, iDef.defaultValue,
parent()); parent());
@ -74,7 +74,7 @@ void CsSettings::ItemBlock::buildItemBlock (SettingsItemDef &iDef)
} }
bool CsSettings::ItemBlock::update (const QString &value) bool CSVSettings::ItemBlock::update (const QString &value)
{ {
bool success = updateItem (value); bool success = updateItem (value);
@ -85,13 +85,13 @@ bool CsSettings::ItemBlock::update (const QString &value)
} }
bool CsSettings::ItemBlock::updateItem (const QString &value) bool CSVSettings::ItemBlock::updateItem (const QString &value)
{ {
return mSetting->updateItem(value); return mSetting->updateItem(value);
} }
bool CsSettings::ItemBlock::updateBySignal(const QString &name, const QString &value, bool &doEmit) bool CSVSettings::ItemBlock::updateBySignal(const QString &name, const QString &value, bool &doEmit)
{ {
bool success = (mSetting->getValue() != value); bool success = (mSetting->getValue() != value);
@ -101,15 +101,15 @@ bool CsSettings::ItemBlock::updateBySignal(const QString &name, const QString &v
return success; return success;
} }
CsSettings::SettingList *CsSettings::ItemBlock::getSettings () CSMSettings::SettingList *CSVSettings::ItemBlock::getSettings ()
{ {
SettingList *list = new SettingList(); CSMSettings::SettingList *list = new CSMSettings::SettingList();
list->push_back(mSetting); list->push_back(mSetting);
return list; return list;
} }
QString CsSettings::ItemBlock::getValue() const QString CSVSettings::ItemBlock::getValue() const
{ {
return mSetting->getValue(); return mSetting->getValue();
} }

View File

@ -3,21 +3,21 @@
#include "abstractblock.hpp" #include "abstractblock.hpp"
namespace CsSettings namespace CSVSettings
{ {
class ItemBlock : public AbstractBlock class ItemBlock : public AbstractBlock
{ {
SettingsItem *mSetting; CSMSettings::SettingsItem *mSetting;
WidgetList mWidgetList; WidgetList mWidgetList;
public: public:
ItemBlock (QWidget* parent = 0); ItemBlock (QWidget* parent = 0);
bool updateSettings (const SettingMap &settings) { return false; } bool updateSettings (const CSMSettings::SettingMap &settings) { return false; }
SettingList *getSettings (); CSMSettings::SettingList *getSettings ();
QString getValue () const; QString getValue () const;
int getSettingCount(); int getSettingCount();

View File

@ -1,11 +1,11 @@
#include "proxyblock.hpp" #include "proxyblock.hpp"
#include "itemblock.hpp" #include "itemblock.hpp"
CsSettings::ProxyBlock::ProxyBlock (QWidget *parent) CSVSettings::ProxyBlock::ProxyBlock (QWidget *parent)
: GroupBlock (parent) : GroupBlock (parent)
{ {
} }
int CsSettings::ProxyBlock::build (GroupBlockDef &proxyDef) int CSVSettings::ProxyBlock::build (GroupBlockDef &proxyDef)
{ {
//get the list of pre-defined values for the proxy //get the list of pre-defined values for the proxy
mValueList = proxyDef.properties.at(0)->valueList; mValueList = proxyDef.properties.at(0)->valueList;
@ -19,7 +19,7 @@ int CsSettings::ProxyBlock::build (GroupBlockDef &proxyDef)
return success; return success;
} }
void CsSettings::ProxyBlock::addSetting (ItemBlock *settingBlock, QStringList *proxyList) void CSVSettings::ProxyBlock::addSetting (ItemBlock *settingBlock, QStringList *proxyList)
{ {
//connect the item block of the proxied seting to the generic update slot //connect the item block of the proxied seting to the generic update slot
connect (settingBlock, SIGNAL (signalUpdateSetting(const QString &, const QString &)), connect (settingBlock, SIGNAL (signalUpdateSetting(const QString &, const QString &)),
@ -29,23 +29,23 @@ void CsSettings::ProxyBlock::addSetting (ItemBlock *settingBlock, QStringList *p
mProxyList << proxyList; mProxyList << proxyList;
} }
bool CsSettings::ProxyBlock::updateSettings (const SettingMap &settings) bool CSVSettings::ProxyBlock::updateSettings (const CSMSettings::SettingMap &settings)
{ {
return updateByProxiedSettings(&settings); return updateByProxiedSettings(&settings);
} }
bool CsSettings::ProxyBlock::updateBySignal(const QString &name, const QString &value, bool &doEmit) bool CSVSettings::ProxyBlock::updateBySignal(const QString &name, const QString &value, bool &doEmit)
{ {
doEmit = false; doEmit = false;
return updateProxiedSettings(); return updateProxiedSettings();
} }
void CsSettings::ProxyBlock::slotUpdateProxySetting (const QString &name, const QString &value) void CSVSettings::ProxyBlock::slotUpdateProxySetting (const QString &name, const QString &value)
{ {
updateByProxiedSettings(); updateByProxiedSettings();
} }
bool CsSettings::ProxyBlock::updateProxiedSettings() bool CSVSettings::ProxyBlock::updateProxiedSettings()
{ {
foreach (ItemBlock *block, mProxiedItemBlockList) foreach (ItemBlock *block, mProxiedItemBlockList)
{ {
@ -74,7 +74,7 @@ bool CsSettings::ProxyBlock::updateProxiedSettings()
return true; return true;
} }
bool CsSettings::ProxyBlock::updateByProxiedSettings(const SettingMap *settings) bool CSVSettings::ProxyBlock::updateByProxiedSettings(const CSMSettings::SettingMap *settings)
{ {
bool success = false; bool success = false;
int commonIndex = -1; int commonIndex = -1;
@ -143,7 +143,7 @@ bool CsSettings::ProxyBlock::updateByProxiedSettings(const SettingMap *settings)
return success; return success;
} }
CsSettings::ItemBlock *CsSettings::ProxyBlock::getProxiedItemBlock (const QString &name) CSVSettings::ItemBlock *CSVSettings::ProxyBlock::getProxiedItemBlock (const QString &name)
{ {
return getItemBlock (name, &mProxiedItemBlockList); return getItemBlock (name, &mProxiedItemBlockList);
} }

View File

@ -3,7 +3,7 @@
#include "groupblock.hpp" #include "groupblock.hpp"
namespace CsSettings namespace CSVSettings
{ {
class ProxyBlock : public GroupBlock class ProxyBlock : public GroupBlock
{ {
@ -23,14 +23,14 @@ namespace CsSettings
void addSetting (ItemBlock* settingBlock, QStringList *proxyList); void addSetting (ItemBlock* settingBlock, QStringList *proxyList);
int build (GroupBlockDef &def); int build (GroupBlockDef &def);
SettingList *getSettings() { return 0; } CSMSettings::SettingList *getSettings() { return 0; }
bool updateSettings (const SettingMap &settings); bool updateSettings (const CSMSettings::SettingMap &settings);
bool updateBySignal (const QString &name, const QString &value, bool &doEmit); bool updateBySignal (const QString &name, const QString &value, bool &doEmit);
private: private:
ItemBlock *getProxiedItemBlock (const QString &name); ItemBlock *getProxiedItemBlock (const QString &name);
bool updateByProxiedSettings(const SettingMap *settings = 0); bool updateByProxiedSettings(const CSMSettings::SettingMap *settings = 0);
bool updateProxiedSettings(); bool updateProxiedSettings();
private slots: private slots:

View File

@ -14,7 +14,7 @@
#include "abstractwidget.hpp" #include "abstractwidget.hpp"
namespace CsSettings namespace CSVSettings
{ {
//VALID FOR RADIOBUTTON / CHECKBOX (or other toggle widget with it's own label) //VALID FOR RADIOBUTTON / CHECKBOX (or other toggle widget with it's own label)
template <typename T1> template <typename T1>
@ -25,7 +25,7 @@ namespace CsSettings
public: public:
explicit SettingWidget(WidgetDef &def, QLayout *layout, QWidget* parent = 0) explicit SettingWidget (WidgetDef &def, QLayout *layout, QWidget* parent = 0)
: AbstractWidget (layout, parent), mWidget (new T1 (parent)) : AbstractWidget (layout, parent), mWidget (new T1 (parent))
{ {
mWidget->setText(def.caption); mWidget->setText(def.caption);
@ -55,7 +55,7 @@ namespace CsSettings
public: public:
SettingWidget(WidgetDef &def, QLayout *layout, QWidget *parent = 0) SettingWidget (WidgetDef &def, QLayout *layout, QWidget *parent = 0)
: AbstractWidget (layout, parent), mWidget (new QSpinBox (parent)) : AbstractWidget (layout, parent), mWidget (new QSpinBox (parent))
{ {
def.caption += tr(" (%1 to %2)").arg(def.minMax->left).arg(def.minMax->right); def.caption += tr(" (%1 to %2)").arg(def.minMax->left).arg(def.minMax->right);
@ -91,7 +91,7 @@ namespace CsSettings
}; };
template <> template <>
class SettingWidget <QComboBox>: public CsSettings::AbstractWidget class SettingWidget <QComboBox>: public CSVSettings::AbstractWidget
{ {
QComboBox *mWidget; QComboBox *mWidget;
@ -143,7 +143,7 @@ namespace CsSettings
}; };
template <> template <>
class SettingWidget <QLineEdit>: public CsSettings::AbstractWidget class SettingWidget <QLineEdit>: public CSVSettings::AbstractWidget
{ {
QLineEdit *mWidget; QLineEdit *mWidget;
@ -176,7 +176,7 @@ namespace CsSettings
}; };
template <> template <>
class SettingWidget <QListWidget>: public CsSettings::AbstractWidget class SettingWidget <QListWidget>: public CSVSettings::AbstractWidget
{ {
QListWidget *mWidget; QListWidget *mWidget;

View File

@ -0,0 +1 @@
#include "support.hpp"

View File

@ -1,17 +1,13 @@
#ifndef SUPPORT_HPP #ifndef VIEW_SUPPORT_HPP
#define SUPPORT_HPP #define VIEW_SUPPORT_HPP
#include <QObject> #include <QList>
#include <QStringList> #include <QStringList>
class QLayout; #include "../../model/settings/support.hpp"
class QWidget;
class QListWidgetItem;
namespace CsSettings namespace CSVSettings
{ {
class SettingContainer;
struct WidgetDef; struct WidgetDef;
class ItemBlock; class ItemBlock;
class GroupBlock; class GroupBlock;
@ -20,86 +16,63 @@ namespace CsSettings
typedef QList<GroupBlockDef *> GroupBlockDefList; typedef QList<GroupBlockDef *> GroupBlockDefList;
typedef QList<GroupBlock *> GroupBlockList; typedef QList<GroupBlock *> GroupBlockList;
typedef QList<ItemBlock *> ItemBlockList; typedef QList<ItemBlock *> ItemBlockList;
typedef QList<SettingContainer *> SettingList;
typedef QMap<QString, SettingContainer *> SettingMap;
typedef QMap<QString, SettingMap *> SectionMap;
typedef QList<QStringList *> ProxyList; typedef QList<QStringList *> ProxyList;
typedef QList<WidgetDef *> WidgetList; typedef QList<WidgetDef *> WidgetList;
typedef QMap<QString, ItemBlock *> ItemBlockMap; typedef QMap<QString, ItemBlock *> ItemBlockMap;
enum OcsWidgetOrientation enum Orientation
{ {
OCS_HORIZONTAL, Orient_Horizontal,
OCS_VERTICAL Orient_Vertical
}; };
enum OcsWidgetType enum WidgetType
{ {
OCS_CHECK_WIDGET, Widget_CheckBox,
OCS_COMBO_WIDGET, Widget_ComboBox,
OCS_TEXT_WIDGET, Widget_LineEdit,
OCS_LIST_WIDGET, Widget_ListBox,
OCS_RADIO_WIDGET, Widget_RadioButton,
OCS_SPIN_WIDGET, Widget_SpinBox,
OCS_UNDEFINED_WIDGET Widget_Undefined
}; };
enum OcsAlignment enum Alignment
{ {
OCS_LEFT = Qt::AlignLeft, Align_Left = Qt::AlignLeft,
OCS_CENTER = Qt::AlignHCenter, Align_Center = Qt::AlignHCenter,
OCS_RIGHT = Qt::AlignRight Align_Right = Qt::AlignRight
};
struct QStringPair
{
QStringPair(): left (""), right ("")
{}
QStringPair (const QString &leftValue, const QString &rightValue)
: left (leftValue), right(rightValue)
{}
QStringPair (const QStringPair &pair)
: left (pair.left), right (pair.right)
{}
QString left;
QString right;
bool isEmpty()
{ return (left.isEmpty() && right.isEmpty()); }
}; };
//template for defining the widget of a property. //template for defining the widget of a property.
struct WidgetDef struct WidgetDef
{ {
OcsWidgetType type; //type of widget providing input WidgetType type; //type of widget providing input
int labelWidth; //width of caption label int labelWidth; //width of caption label
int widgetWidth; //width of input widget int widgetWidth; //width of input widget
OcsWidgetOrientation orientation; //label / widget orientation (horizontal / vertical) Orientation orientation; //label / widget orientation (horizontal / vertical)
QString inputMask; //input mask (line edit) QString inputMask; //input mask (line edit)
QString caption; //label caption. Leave empty for multiple items. See BlockDef::captionList QString caption; //label caption. Leave empty for multiple items. See BlockDef::captionList
QString value; //widget value. Leave empty for multiple items. See BlockDef::valueList QString value; //widget value. Leave empty for multiple items. See BlockDef::valueList
QStringPair *minMax; //Min/Max QString value pair. If empty, assigned to property item value pair. CSMSettings::QStringPair *minMax; //Min/Max QString value pair. If empty, assigned to property item value pair.
QStringList *valueList; //value list for list widgets. If left empty, is assigned to property item value list during block build(). QStringList *valueList; //value list for list widgets. If left empty, is assigned to property item value list during block build().
bool isDefault; //isDefault - determined at runtime. bool isDefault; //isDefault - determined at runtime.
OcsAlignment valueAlignment; //left / center / right-justify text in widget Alignment valueAlignment; //left / center / right-justify text in widget
OcsAlignment widgetAlignment; //left / center / right-justify widget in group box Alignment widgetAlignment; //left / center / right-justify widget in group box
WidgetDef() : labelWidth (-1), widgetWidth (-1), WidgetDef() : labelWidth (-1), widgetWidth (-1),
orientation (OCS_HORIZONTAL), orientation (Orient_Horizontal),
isDefault (true), valueAlignment (OCS_CENTER), isDefault (true), valueAlignment (Align_Center),
widgetAlignment (OCS_RIGHT), widgetAlignment (Align_Right),
inputMask (""), value (""), inputMask (""), value (""),
caption (""), valueList (0) caption (""), valueList (0)
{} {}
WidgetDef (OcsWidgetType widgType) WidgetDef (WidgetType widgType)
: type (widgType), orientation (OCS_HORIZONTAL), : type (widgType), orientation (Orient_Horizontal),
caption (""), value (""), valueAlignment (OCS_CENTER), caption (""), value (""), valueAlignment (Align_Center),
widgetAlignment (OCS_RIGHT), widgetAlignment (Align_Right),
labelWidth (-1), widgetWidth (-1), labelWidth (-1), widgetWidth (-1),
valueList (0), isDefault (true) valueList (0), isDefault (true)
{} {}
@ -116,15 +89,15 @@ namespace CsSettings
//Used to populate option widget captions or list widget item lists (see WidgetDef::caption / value) //Used to populate option widget captions or list widget item lists (see WidgetDef::caption / value)
QString defaultValue; QString defaultValue;
bool hasMultipleValues; bool hasMultipleValues;
QStringPair minMax; //minimum / maximum value pair CSMSettings::QStringPair minMax; //minimum / maximum value pair
WidgetDef widget; //definition of the input widget for this setting WidgetDef widget; //definition of the input widget for this setting
OcsWidgetOrientation orientation; //general orientation of the widget / label for this property Orientation orientation; //general orientation of the widget / label for this property
ProxyList *proxyList; //list of property and corresponding default values for proxy widget ProxyList *proxyList; //list of property and corresponding default values for proxy widget
SettingsItemDef() : name (""), defaultValue (""), orientation (OCS_VERTICAL), hasMultipleValues (false) SettingsItemDef() : name (""), defaultValue (""), orientation (Orient_Vertical), hasMultipleValues (false)
{} {}
SettingsItemDef (QString propName, QString propDefault, OcsWidgetOrientation propOrient = OCS_VERTICAL) SettingsItemDef (QString propName, QString propDefault, Orientation propOrient = Orient_Vertical)
: name (propName), defaultValue (propDefault), orientation (propOrient), : name (propName), defaultValue (propDefault), orientation (propOrient),
hasMultipleValues(false), valueList (new QStringList), proxyList ( new ProxyList) hasMultipleValues(false), valueList (new QStringList), proxyList ( new ProxyList)
{} {}
@ -139,16 +112,16 @@ namespace CsSettings
QStringList captions; //list of captions for widgets at the block level (not associated with any particular property) QStringList captions; //list of captions for widgets at the block level (not associated with any particular property)
WidgetList widgets; //list of widgets at the block level (not associated with any particular property) WidgetList widgets; //list of widgets at the block level (not associated with any particular property)
QList<SettingsItemDef *> properties; //list of the property(ies) which are subordinate to the property block. QList<SettingsItemDef *> properties; //list of the property(ies) which are subordinate to the property block.
OcsWidgetOrientation widgetOrientation; //general orientation of widgets in group block Orientation widgetOrientation; //general orientation of widgets in group block
bool isVisible; //determines whether or not box border/title are visible bool isVisible; //determines whether or not box border/title are visible
bool isProxy; //indicates whether or not this block defines a proxy block bool isProxy; //indicates whether or not this block defines a proxy block
QString defaultValue; //generic default value attribute QString defaultValue; //generic default value attribute
GroupBlockDef (): title(""), widgetOrientation (OCS_VERTICAL), isVisible (true), isProxy (false), defaultValue ("") GroupBlockDef (): title(""), widgetOrientation (Orient_Vertical), isVisible (true), isProxy (false), defaultValue ("")
{} {}
GroupBlockDef (QString blockTitle) GroupBlockDef (QString blockTitle)
: title (blockTitle), widgetOrientation (OCS_VERTICAL), isProxy (false), isVisible (true), defaultValue ("") : title (blockTitle), widgetOrientation (Orient_Vertical), isProxy (false), isVisible (true), defaultValue ("")
{} {}
}; };
@ -157,14 +130,15 @@ namespace CsSettings
QString title; QString title;
QString defaultValue; //default value for widgets unique to the custom block QString defaultValue; //default value for widgets unique to the custom block
GroupBlockDefList blockDefList; //list of settings groups that comprise the settings within the custom block GroupBlockDefList blockDefList; //list of settings groups that comprise the settings within the custom block
OcsWidgetOrientation blockOrientation; Orientation blockOrientation;
CustomBlockDef (): title (""), defaultValue (""), blockOrientation (OCS_HORIZONTAL) CustomBlockDef (): title (""), defaultValue (""), blockOrientation (Orient_Horizontal)
{} {}
CustomBlockDef (const QString &blockTitle) CustomBlockDef (const QString &blockTitle)
: title (blockTitle), defaultValue (""), blockOrientation (OCS_HORIZONTAL) : title (blockTitle), defaultValue (""), blockOrientation (Orient_Horizontal)
{} {}
}; };
} }
#endif // SUPPORT_HPP
#endif // VIEW_SUPPORT_HPP

View File

@ -3,11 +3,11 @@
#include "groupbox.hpp" #include "groupbox.hpp"
#include "itemblock.hpp" #include "itemblock.hpp"
CsSettings::ToggleBlock::ToggleBlock(QWidget *parent) : CSVSettings::ToggleBlock::ToggleBlock(QWidget *parent) :
CustomBlock(parent) CustomBlock(parent)
{} {}
int CsSettings::ToggleBlock::build(CustomBlockDef &def) int CSVSettings::ToggleBlock::build(CustomBlockDef &def)
{ {
if (def.blockDefList.size()==0) if (def.blockDefList.size()==0)
return -1; return -1;
@ -49,7 +49,7 @@ int CsSettings::ToggleBlock::build(CustomBlockDef &def)
return 0; return 0;
} }
CsSettings::GroupBox *CsSettings::ToggleBlock::buildToggleWidgets (GroupBlockDef &def, QString &defaultToggle) CSVSettings::GroupBox *CSVSettings::ToggleBlock::buildToggleWidgets (GroupBlockDef &def, QString &defaultToggle)
{ {
GroupBox *box = new GroupBox (false, getParent()); GroupBox *box = new GroupBox (false, getParent());
@ -61,7 +61,7 @@ CsSettings::GroupBox *CsSettings::ToggleBlock::buildToggleWidgets (GroupBlockDef
WidgetDef *wDef = def.widgets.at(i); WidgetDef *wDef = def.widgets.at(i);
wDef->caption = caption; wDef->caption = caption;
wDef->widgetAlignment = OCS_LEFT; wDef->widgetAlignment = Align_Left;
AbstractWidget *widg = buildWidget (caption, *wDef, layout, false); AbstractWidget *widg = buildWidget (caption, *wDef, layout, false);

View File

@ -5,7 +5,7 @@
#include "customblock.hpp" #include "customblock.hpp"
namespace CsSettings namespace CSVSettings
{ {
class GroupBlock; class GroupBlock;
class GroupBox; class GroupBox;

View File

@ -12,13 +12,13 @@
#include "blankpage.hpp" #include "blankpage.hpp"
#include "editorpage.hpp" #include "editorpage.hpp"
#include "support.hpp" #include "../../model/settings/support.hpp"
#include "settingwidget.hpp" #include "settingwidget.hpp"
#include <QDebug> #include <QDebug>
CsSettings::UserSettingsDialog::UserSettingsDialog(QMainWindow *parent) : CSVSettings::UserSettingsDialog::UserSettingsDialog(QMainWindow *parent) :
QMainWindow (parent), mUserSettings (mCfgMgr), mStackedWidget (0) QMainWindow (parent), mStackedWidget (0)
{ {
setWindowTitle(QString::fromUtf8 ("User Settings")); setWindowTitle(QString::fromUtf8 ("User Settings"));
buildPages(); buildPages();
@ -31,22 +31,22 @@ CsSettings::UserSettingsDialog::UserSettingsDialog(QMainWindow *parent) :
SLOT (slotChangePage (QListWidgetItem*, QListWidgetItem*))); SLOT (slotChangePage (QListWidgetItem*, QListWidgetItem*)));
} }
CsSettings::UserSettingsDialog::~UserSettingsDialog() CSVSettings::UserSettingsDialog::~UserSettingsDialog()
{ {
} }
void CsSettings::UserSettingsDialog::closeEvent (QCloseEvent *event) void CSVSettings::UserSettingsDialog::closeEvent (QCloseEvent *event)
{ {
writeSettings(); writeSettings();
} }
void CsSettings::UserSettingsDialog::setWidgetStates (SectionMap settingsMap) void CSVSettings::UserSettingsDialog::setWidgetStates (CSMSettings::SectionMap settingsMap)
{ {
//iterate the tabWidget's pages (sections) //iterate the tabWidget's pages (sections)
for (int i = 0; i < mStackedWidget->count(); i++) for (int i = 0; i < mStackedWidget->count(); i++)
{ {
//get the settings defined for the entire section //get the settings defined for the entire section
CsSettings::SettingMap *settings = settingsMap [mStackedWidget->widget(i)->objectName()]; CSMSettings::SettingMap *settings = settingsMap [mStackedWidget->widget(i)->objectName()];
//if found, initialize the page's widgets //if found, initialize the page's widgets
if (settings) if (settings)
@ -57,7 +57,7 @@ void CsSettings::UserSettingsDialog::setWidgetStates (SectionMap settingsMap)
} }
} }
void CsSettings::UserSettingsDialog::buildPages() void CSVSettings::UserSettingsDialog::buildPages()
{ {
//craete central widget with it's layout and immediate children //craete central widget with it's layout and immediate children
QWidget *centralWidget = new QWidget (this); QWidget *centralWidget = new QWidget (this);
@ -81,21 +81,21 @@ void CsSettings::UserSettingsDialog::buildPages()
createPage<BlankPage>("Page3"); createPage<BlankPage>("Page3");
} }
void CsSettings::UserSettingsDialog::createSamplePage() void CSVSettings::UserSettingsDialog::createSamplePage()
{ {
//add pages to stackedwidget and items to listwidget //add pages to stackedwidget and items to listwidget
CsSettings::AbstractPage *page CSVSettings::AbstractPage *page
= new CsSettings::EditorPage(this); = new CSVSettings::EditorPage(this);
mStackedWidget->addWidget (page); mStackedWidget->addWidget (page);
new QListWidgetItem (page->objectName(), mListWidget); new QListWidgetItem (page->objectName(), mListWidget);
connect ( page, SIGNAL ( signalUpdateEditorSetting (const QString &, const QString &)), connect ( page, SIGNAL ( signalUpdateEditorSetting (const QString &, const QString &)),
this, SIGNAL ( signalUpdateEditorSetting (const QString &, const QString &))); &(CSMSettings::UserSettings::instance()), SIGNAL ( signalUpdateEditorSetting (const QString &, const QString &)));
} }
void CsSettings::UserSettingsDialog::positionWindow () void CSVSettings::UserSettingsDialog::positionWindow ()
{ {
QRect scr = QApplication::desktop()->screenGeometry(); QRect scr = QApplication::desktop()->screenGeometry();
@ -103,14 +103,14 @@ void CsSettings::UserSettingsDialog::positionWindow ()
} }
CsSettings::SectionMap CsSettings::UserSettingsDialog::loadSettings () CSMSettings::SectionMap CSVSettings::UserSettingsDialog::loadSettings ()
{ {
QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string()); QString userPath = QString::fromStdString(mCfgMgr.getUserPath().string());
mPaths.append(QString("opencs.cfg")); mPaths.append(QString("opencs.cfg"));
mPaths.append(userPath + QString("opencs.cfg")); mPaths.append(userPath + QString("opencs.cfg"));
SectionMap settingsMap; CSMSettings::SectionMap settingsMap;
foreach (const QString &path, mPaths) foreach (const QString &path, mPaths)
{ {
@ -135,7 +135,7 @@ CsSettings::SectionMap CsSettings::UserSettingsDialog::loadSettings ()
QTextStream stream(&file); QTextStream stream(&file);
stream.setCodec(QTextCodec::codecForName("UTF-8")); stream.setCodec(QTextCodec::codecForName("UTF-8"));
mUserSettings.getSettings(stream, settingsMap); CSMSettings::UserSettings::instance().getSettings(stream, settingsMap);
} }
file.close(); file.close();
@ -144,9 +144,9 @@ CsSettings::SectionMap CsSettings::UserSettingsDialog::loadSettings ()
return settingsMap; return settingsMap;
} }
void CsSettings::UserSettingsDialog::writeSettings() void CSVSettings::UserSettingsDialog::writeSettings()
{ {
QMap<QString, SettingList *> settings; QMap<QString, CSMSettings::SettingList *> settings;
for (int i = 0; i < mStackedWidget->count(); ++i) for (int i = 0; i < mStackedWidget->count(); ++i)
{ {
@ -154,16 +154,16 @@ void CsSettings::UserSettingsDialog::writeSettings()
settings [page->objectName()] = page->getSettings(); settings [page->objectName()] = page->getSettings();
} }
mUserSettings.writeFile(mUserSettings.openFile(mPaths.back()), settings); CSMSettings::UserSettings::instance().writeFile(CSMSettings::UserSettings::instance().openFile(mPaths.back()), settings);
} }
CsSettings::AbstractPage *CsSettings::UserSettingsDialog::getAbstractPage (int index) CSVSettings::AbstractPage *CSVSettings::UserSettingsDialog::getAbstractPage (int index)
{ {
return dynamic_cast<AbstractPage *>(mStackedWidget->widget(index)); return dynamic_cast<AbstractPage *>(mStackedWidget->widget(index));
} }
void CsSettings::UserSettingsDialog::slotChangePage(QListWidgetItem *current, QListWidgetItem *previous) void CSVSettings::UserSettingsDialog::slotChangePage(QListWidgetItem *current, QListWidgetItem *previous)
{ {
if (!current) if (!current)
current = previous; current = previous;

View File

@ -5,18 +5,22 @@
#include <QStackedWidget> #include <QStackedWidget>
#include <QListWidgetItem> #include <QListWidgetItem>
#ifndef Q_MOC_RUN
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#include "usersettings.hpp" #endif
#include "support.hpp"
#include "../../model/settings/usersettings.hpp"
#include "../../model/settings/support.hpp"
class QHBoxLayout; class QHBoxLayout;
class AbstractWidget; class AbstractWidget;
class QStackedWidget; class QStackedWidget;
class QListWidget; class QListWidget;
namespace CsSettings { namespace CSVSettings {
class AbstractPage; class AbstractPage;
class UserSettingsDialog : public QMainWindow class UserSettingsDialog : public QMainWindow
{ {
Q_OBJECT Q_OBJECT
@ -24,7 +28,6 @@ namespace CsSettings {
QStringList mPaths; QStringList mPaths;
QListWidget *mListWidget; QListWidget *mListWidget;
QStackedWidget *mStackedWidget; QStackedWidget *mStackedWidget;
UserSettings mUserSettings;
Files::ConfigurationManager mCfgMgr; Files::ConfigurationManager mCfgMgr;
public: public:
@ -35,10 +38,10 @@ namespace CsSettings {
void closeEvent (QCloseEvent *event); void closeEvent (QCloseEvent *event);
AbstractPage *getAbstractPage (int index); AbstractPage *getAbstractPage (int index);
void setWidgetStates (SectionMap settingsMap); void setWidgetStates (CSMSettings::SectionMap settingsMap);
void buildPages(); void buildPages();
void positionWindow (); void positionWindow ();
SectionMap loadSettings(); CSMSettings::SectionMap loadSettings();
void writeSettings(); void writeSettings();
void createSamplePage(); void createSamplePage();
@ -61,9 +64,6 @@ namespace CsSettings {
resize (mStackedWidget->sizeHint()); resize (mStackedWidget->sizeHint());
} }
signals:
void signalUpdateEditorSetting (const QString &settingName, const QString &settingValue);
public slots: public slots:
void slotChangePage (QListWidgetItem*, QListWidgetItem*); void slotChangePage (QListWidgetItem*, QListWidgetItem*);
}; };

View File

@ -3,7 +3,7 @@
#include <QGridLayout> #include <QGridLayout>
#include <QLabel> #include <QLabel>
#include <QAbstractTableModel> #include <QAbstractItemModel>
#include <QDoubleSpinBox> #include <QDoubleSpinBox>
#include <QSpinBox> #include <QSpinBox>
#include <QLineEdit> #include <QLineEdit>
@ -24,7 +24,7 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM
widget->setLayout (layout); widget->setLayout (layout);
QAbstractTableModel *model = document.getData().getTableModel (id); QAbstractItemModel *model = document.getData().getTableModel (id);
int columns = model->columnCount(); int columns = model->columnCount();

Some files were not shown because too many files have changed in this diff Show More