mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 11:49:56 +00:00
Merge branch 'cc9cii' into jump-to-modified
Conflicts: apps/opencs/view/world/table.cpp apps/opencs/view/world/table.hpp apps/opencs/view/world/tablesubview.cpp
This commit is contained in:
commit
fb3015c9b8
539 changed files with 11468 additions and 2700 deletions
|
@ -38,10 +38,10 @@ before_script:
|
|||
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_script.osx.sh; fi
|
||||
script:
|
||||
- cd ./build
|
||||
- if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j4; fi
|
||||
- if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j2; fi
|
||||
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi
|
||||
after_script:
|
||||
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi
|
||||
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then cd .. && ./CI/check_tabs.sh; fi
|
||||
notifications:
|
||||
recipients:
|
||||
- corrmage+travis-ci@gmail.com
|
||||
|
|
|
@ -19,6 +19,7 @@ Programmers
|
|||
Alexander Nadeau (wareya)
|
||||
Alexander Olofsson (Ace)
|
||||
Artem Kotsynyak (greye)
|
||||
artemutin
|
||||
Arthur Moore (EmperorArthur)
|
||||
athile
|
||||
Bret Curtis (psi29a)
|
||||
|
@ -59,6 +60,7 @@ Programmers
|
|||
Julien Voisin (jvoisin/ap0)
|
||||
Karl-Felix Glatzer (k1ll)
|
||||
Kevin Poitra (PuppyKevin)
|
||||
Koncord
|
||||
Lars Söderberg (Lazaroth)
|
||||
lazydev
|
||||
Leon Saunders (emoose)
|
||||
|
@ -109,6 +111,7 @@ Programmers
|
|||
viadanna
|
||||
Vincent Heuken
|
||||
vocollapse
|
||||
zelurker
|
||||
|
||||
Manual
|
||||
------
|
||||
|
|
9
CI/check_tabs.sh
Executable file
9
CI/check_tabs.sh
Executable file
|
@ -0,0 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
OUTPUT=$(grep -nRP '\t' --include=\*.{cpp,hpp,c,h} apps components)
|
||||
|
||||
if [[ $OUTPUT ]] ; then
|
||||
echo "Error: Tab characters found!"
|
||||
echo $OUTPUT
|
||||
exit 1
|
||||
fi
|
|
@ -98,25 +98,29 @@ endif()
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
# Sound setup
|
||||
set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE AVRESAMPLE)
|
||||
unset(FFMPEG_LIBRARIES CACHE)
|
||||
find_package(FFmpeg)
|
||||
|
||||
find_package(FFmpeg REQUIRED)
|
||||
|
||||
set (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARY})
|
||||
|
||||
if ( NOT AVCODEC_FOUND OR NOT AVFORMAT_FOUND OR NOT AVUTIL_FOUND OR NOT SWSCALE_FOUND )
|
||||
message(FATAL_ERROR "FFmpeg component required, but not found!")
|
||||
endif()
|
||||
set(SOUND_INPUT_INCLUDES ${FFMPEG_INCLUDE_DIRS})
|
||||
set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARIES})
|
||||
if( SWRESAMPLE_FOUND )
|
||||
add_definitions(-DHAVE_LIBSWRESAMPLE)
|
||||
set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${SWRESAMPLE_LIBRARIES})
|
||||
set (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${SWRESAMPLE_LIBRARIES})
|
||||
else()
|
||||
if( AVRESAMPLE_FOUND )
|
||||
set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${AVRESAMPLE_LIBRARIES})
|
||||
set (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${AVRESAMPLE_LIBRARIES})
|
||||
else()
|
||||
message(FATAL_ERROR "Install either libswresample (FFmpeg) or libavresample (Libav).")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES})
|
||||
|
||||
# TinyXML
|
||||
option(USE_SYSTEM_TINYXML "Use system TinyXML library instead of internal." OFF)
|
||||
if(USE_SYSTEM_TINYXML)
|
||||
|
@ -134,9 +138,11 @@ endif()
|
|||
|
||||
# Platform specific
|
||||
if (WIN32)
|
||||
if(NOT MINGW)
|
||||
set(Boost_USE_STATIC_LIBS ON)
|
||||
set(PLATFORM_INCLUDE_DIR "platform")
|
||||
add_definitions(-DBOOST_ALL_NO_LIB)
|
||||
endif(NOT MINGW)
|
||||
|
||||
# Suppress WinMain(), provided by SDL
|
||||
add_definitions(-DSDL_MAIN_HANDLED)
|
||||
|
@ -149,6 +155,19 @@ endif()
|
|||
|
||||
# Dependencies
|
||||
|
||||
set(DESIRED_QT_VERSION 4 CACHE STRING "The QT version OpenMW should use (4 or 5)")
|
||||
message(STATUS "Using Qt${DESIRED_QT_VERSION}")
|
||||
|
||||
if (DESIRED_QT_VERSION MATCHES 4)
|
||||
find_package(Qt4 REQUIRED COMPONENTS QtCore QtGui QtNetwork)
|
||||
else()
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Qt5Core REQUIRED)
|
||||
find_package(Qt5Network REQUIRED)
|
||||
# Instruct CMake to run moc automatically when needed.
|
||||
#set(CMAKE_AUTOMOC ON)
|
||||
endif()
|
||||
|
||||
# Fix for not visible pthreads functions for linker with glibc 2.15
|
||||
if (UNIX AND NOT APPLE)
|
||||
find_package (Threads)
|
||||
|
@ -169,7 +188,7 @@ if (HAVE_UNORDERED_MAP)
|
|||
endif ()
|
||||
|
||||
|
||||
set(BOOST_COMPONENTS system filesystem program_options)
|
||||
set(BOOST_COMPONENTS system filesystem program_options thread wave)
|
||||
if(WIN32)
|
||||
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale)
|
||||
endif(WIN32)
|
||||
|
@ -345,6 +364,8 @@ configure_file(${OpenMW_SOURCE_DIR}/files/gamecontrollerdb.txt
|
|||
if (NOT WIN32 AND NOT APPLE)
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop
|
||||
"${OpenMW_BINARY_DIR}/openmw.desktop")
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.appdata.xml
|
||||
"${OpenMW_BINARY_DIR}/openmw.appdata.xml")
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw-cs.desktop
|
||||
"${OpenMW_BINARY_DIR}/openmw-cs.desktop")
|
||||
endif()
|
||||
|
@ -402,6 +423,9 @@ IF(NOT WIN32 AND NOT APPLE)
|
|||
IF(BUILD_ESMTOOL)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/esmtool" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_ESMTOOL)
|
||||
IF(BUILD_NIFTEST)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/niftest" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_NIFTEST)
|
||||
IF(BUILD_MWINIIMPORTER)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-iniimporter" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_MWINIIMPORTER)
|
||||
|
@ -428,6 +452,7 @@ IF(NOT WIN32 AND NOT APPLE)
|
|||
# Install icon and desktop file
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "${ICONDIR}" COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.appdata.xml" DESTINATION "${DATAROOTDIR}/appdata" COMPONENT "openmw")
|
||||
IF(BUILD_OPENCS)
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw-cs.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "opencs")
|
||||
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/opencs/openmw-cs.png" DESTINATION "${ICONDIR}" COMPONENT "opencs")
|
||||
|
@ -598,6 +623,10 @@ if (BUILD_WIZARD)
|
|||
add_subdirectory(apps/wizard)
|
||||
endif()
|
||||
|
||||
if (BUILD_NIFTEST)
|
||||
add_subdirectory(apps/niftest)
|
||||
endif(BUILD_NIFTEST)
|
||||
|
||||
# UnitTests
|
||||
if (BUILD_UNITTESTS)
|
||||
add_subdirectory( apps/openmw_test_suite )
|
||||
|
|
16
CONTRIBUTING.md
Normal file
16
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,16 @@
|
|||
Description
|
||||
===========
|
||||
|
||||
Your pull request description should include (if applicable):
|
||||
|
||||
* A link back to the bug report or forum discussion that prompted the change
|
||||
* Summary of the changes made
|
||||
* Reasoning / motivation behind the change
|
||||
* What testing you have carried out to verify the change
|
||||
|
||||
Other notes
|
||||
===========
|
||||
|
||||
* Separate your work into multiple pull requests whenever possible. As a rule of thumb, each feature and each bugfix should go into a separate PR, unless they are closely related or dependent upon each other. Small pull requests are easier to review, and are less likely to require further changes before we can merge them. A "mega" pull request with lots of unrelated commits in it is likely to get held up in review for a long time.
|
||||
* Feel free to submit incomplete pull requests. Even if the work can not be merged yet, pull requests are a great place to collect early feedback. Just make sure to mark it as *[Incomplete]* or *[Do not merge yet]* in the title.
|
||||
* If you plan on contributing often, please read the [Developer Reference](https://wiki.openmw.org/index.php?title=Developer_Reference) on our wiki, especially the [Policies and Standards](https://wiki.openmw.org/index.php?title=Policies_and_Standards).
|
|
@ -9,7 +9,8 @@ add_executable(bsatool
|
|||
)
|
||||
|
||||
target_link_libraries(bsatool
|
||||
${Boost_LIBRARIES}
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
${Boost_FILESYSTEM_LIBRARY}
|
||||
components
|
||||
)
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include <exception>
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ add_executable(esmtool
|
|||
)
|
||||
|
||||
target_link_libraries(esmtool
|
||||
${Boost_LIBRARIES}
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
components
|
||||
)
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ std::string clothingTypeLabel(int idx)
|
|||
}
|
||||
|
||||
std::string armorTypeLabel(int idx)
|
||||
{
|
||||
{
|
||||
if (idx >= 0 && idx <= 10)
|
||||
{
|
||||
static const char *armorTypeLabels[] = {
|
||||
|
@ -645,7 +645,7 @@ std::string ruleFunction(int idx)
|
|||
else
|
||||
return "Invalid";
|
||||
}
|
||||
|
||||
|
||||
// The "unused flag bits" should probably be defined alongside the
|
||||
// defined bits in the ESM component. The names of the flag bits are
|
||||
// very inconsistent.
|
||||
|
@ -653,7 +653,7 @@ std::string ruleFunction(int idx)
|
|||
std::string bodyPartFlags(int flags)
|
||||
{
|
||||
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_NotPlayable) properties += "NotPlayable ";
|
||||
int unused = (0xFFFFFFFF ^
|
||||
|
@ -667,7 +667,7 @@ std::string bodyPartFlags(int flags)
|
|||
std::string cellFlags(int flags)
|
||||
{
|
||||
std::string properties = "";
|
||||
if (flags == 0) properties += "[None] ";
|
||||
if (flags == 0) properties += "[None] ";
|
||||
if (flags & ESM::Cell::HasWater) properties += "HasWater ";
|
||||
if (flags & ESM::Cell::Interior) properties += "Interior ";
|
||||
if (flags & ESM::Cell::NoSleep) properties += "NoSleep ";
|
||||
|
@ -830,12 +830,12 @@ std::string npcFlags(int flags)
|
|||
std::string properties = "";
|
||||
if (flags == 0) properties += "[None] ";
|
||||
// Mythicmods and the ESM component differ. Mythicmods says
|
||||
// 0x8=None and 0x10=AutoCalc, while our code defines 0x8 as
|
||||
// AutoCalc. The former seems to be correct. All Bethesda
|
||||
// records have bit 0x8 set. A suspiciously large portion of
|
||||
// females have autocalc turned off.
|
||||
if (flags & ESM::NPC::Autocalc) properties += "Unknown ";
|
||||
if (flags & 0x00000010) properties += "Autocalc ";
|
||||
// 0x8=None and 0x10=AutoCalc, while our code previously defined
|
||||
// 0x8 as AutoCalc. The former seems to be correct. All Bethesda
|
||||
// records have bit 0x8 set. Previously, suspiciously large portion
|
||||
// of females had autocalc turned off.
|
||||
if (flags & 0x00000008) properties += "Unknown ";
|
||||
if (flags & ESM::NPC::Autocalc) properties += "Autocalc ";
|
||||
if (flags & ESM::NPC::Female) properties += "Female ";
|
||||
if (flags & ESM::NPC::Respawn) properties += "Respawn ";
|
||||
if (flags & ESM::NPC::Essential) properties += "Essential ";
|
||||
|
@ -847,8 +847,8 @@ std::string npcFlags(int flags)
|
|||
// however the only unknown bit occurs on ALL records, and
|
||||
// relatively few NPCs have this bit set.
|
||||
int unused = (0xFFFFFFFF ^
|
||||
(ESM::NPC::Autocalc|
|
||||
0x00000010|
|
||||
(0x00000008|
|
||||
ESM::NPC::Autocalc|
|
||||
ESM::NPC::Female|
|
||||
ESM::NPC::Respawn|
|
||||
ESM::NPC::Essential|
|
||||
|
|
|
@ -493,14 +493,14 @@ void Record<ESM::Book>::print()
|
|||
std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl;
|
||||
if (mPrintPlain)
|
||||
{
|
||||
std::cout << " Text:" << std::endl;
|
||||
std::cout << "START--------------------------------------" << std::endl;
|
||||
std::cout << mData.mText << std::endl;
|
||||
std::cout << "END----------------------------------------" << std::endl;
|
||||
std::cout << " Text:" << std::endl;
|
||||
std::cout << "START--------------------------------------" << std::endl;
|
||||
std::cout << mData.mText << std::endl;
|
||||
std::cout << "END----------------------------------------" << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " Text: [skipped]" << std::endl;
|
||||
std::cout << " Text: [skipped]" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -799,14 +799,14 @@ void Record<ESM::DialInfo>::print()
|
|||
{
|
||||
if (mPrintPlain)
|
||||
{
|
||||
std::cout << " Result Script:" << std::endl;
|
||||
std::cout << "START--------------------------------------" << std::endl;
|
||||
std::cout << mData.mResultScript << std::endl;
|
||||
std::cout << "END----------------------------------------" << std::endl;
|
||||
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;
|
||||
std::cout << " Result Script: [skipped]" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -841,19 +841,13 @@ void Record<ESM::Land>::print()
|
|||
std::cout << " Flags: " << landFlags(mData.mFlags) << std::endl;
|
||||
std::cout << " DataTypes: " << mData.mDataTypes << std::endl;
|
||||
|
||||
// Seems like this should done with reference counting in the
|
||||
// loader to me. But I'm not really knowledgable about this
|
||||
// record type yet. --Cory
|
||||
bool wasLoaded = (mData.mDataLoaded != 0);
|
||||
if (mData.mDataTypes) mData.loadData(mData.mDataTypes);
|
||||
if (mData.mDataLoaded)
|
||||
if (const ESM::Land::LandData *data = mData.getLandData (mData.mDataTypes))
|
||||
{
|
||||
std::cout << " Height Offset: " << mData.mLandData->mHeightOffset << std::endl;
|
||||
std::cout << " Height Offset: " << data->mHeightOffset << std::endl;
|
||||
// Lots of missing members.
|
||||
std::cout << " Unknown1: " << mData.mLandData->mUnk1 << std::endl;
|
||||
std::cout << " Unknown2: " << mData.mLandData->mUnk2 << std::endl;
|
||||
std::cout << " Unknown1: " << data->mUnk1 << std::endl;
|
||||
std::cout << " Unknown2: " << data->mUnk2 << std::endl;
|
||||
}
|
||||
if (!wasLoaded) mData.unloadData();
|
||||
}
|
||||
|
||||
template<>
|
||||
|
@ -1207,14 +1201,14 @@ void Record<ESM::Script>::print()
|
|||
|
||||
if (mPrintPlain)
|
||||
{
|
||||
std::cout << " Script:" << std::endl;
|
||||
std::cout << "START--------------------------------------" << std::endl;
|
||||
std::cout << mData.mScriptText << std::endl;
|
||||
std::cout << "END----------------------------------------" << std::endl;
|
||||
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;
|
||||
std::cout << " Script: [skipped]" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace EsmTool
|
|||
}
|
||||
|
||||
void setPrintPlain(bool plain) {
|
||||
mPrintPlain = plain;
|
||||
mPrintPlain = plain;
|
||||
}
|
||||
|
||||
virtual void load(ESM::ESMReader &esm) = 0;
|
||||
|
|
|
@ -33,7 +33,8 @@ add_executable(openmw-essimporter
|
|||
)
|
||||
|
||||
target_link_libraries(openmw-essimporter
|
||||
${Boost_LIBRARIES}
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
${Boost_FILESYSTEM_LIBRARY}
|
||||
components
|
||||
)
|
||||
|
||||
|
|
|
@ -41,9 +41,9 @@ namespace ESSImport
|
|||
{
|
||||
for (int i=0; i<ESM::Skill::Length; ++i)
|
||||
{
|
||||
npcStats.mSkills[i].mRegular.mMod = actorData.mSkills[i][1];
|
||||
npcStats.mSkills[i].mRegular.mCurrent = actorData.mSkills[i][1];
|
||||
npcStats.mSkills[i].mRegular.mBase = actorData.mSkills[i][0];
|
||||
npcStats.mSkills[i].mMod = actorData.mSkills[i][1];
|
||||
npcStats.mSkills[i].mCurrent = actorData.mSkills[i][1];
|
||||
npcStats.mSkills[i].mBase = actorData.mSkills[i][0];
|
||||
}
|
||||
|
||||
npcStats.mTimeToStartDrowning = actorData.mACDT.mBreathMeter;
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace ESSImport
|
|||
for (int i=0; i<8; ++i)
|
||||
out.mObject.mNpcStats.mSkillIncrease[i] = pcdt.mPNAM.mSkillIncreases[i];
|
||||
for (int i=0; i<27; ++i)
|
||||
out.mObject.mNpcStats.mSkills[i].mRegular.mProgress = pcdt.mPNAM.mSkillProgress[i];
|
||||
out.mObject.mNpcStats.mSkills[i].mProgress = pcdt.mPNAM.mSkillProgress[i];
|
||||
out.mObject.mNpcStats.mLevelProgress = pcdt.mPNAM.mLevelProgress;
|
||||
|
||||
if (pcdt.mPNAM.mDrawState & PCDT::DrawState_Weapon)
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
#include "importer.hpp"
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <OgreRoot.h>
|
||||
#include <OgreLogManager.h>
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
#include <components/esm/esmwriter.hpp>
|
||||
|
@ -292,7 +296,7 @@ namespace ESSImport
|
|||
|
||||
ESM::ESMWriter writer;
|
||||
|
||||
writer.setFormat (ESM::Header::CurrentFormat);
|
||||
writer.setFormat (ESM::SavedGame::sCurrentFormat);
|
||||
|
||||
std::ofstream stream(mOutFile.c_str(), std::ios::binary);
|
||||
// all unused
|
||||
|
|
|
@ -57,7 +57,6 @@ set(LAUNCHER_UI
|
|||
|
||||
source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER})
|
||||
|
||||
find_package(Qt4 REQUIRED)
|
||||
set(QT_USE_QTGUI 1)
|
||||
|
||||
# Set some platform specific settings
|
||||
|
@ -66,12 +65,17 @@ if(WIN32)
|
|||
set(QT_USE_QTMAIN TRUE)
|
||||
endif(WIN32)
|
||||
|
||||
QT4_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/launcher/launcher.qrc)
|
||||
QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC})
|
||||
QT4_WRAP_UI(UI_HDRS ${LAUNCHER_UI})
|
||||
if (DESIRED_QT_VERSION MATCHES 4)
|
||||
include(${QT_USE_FILE})
|
||||
QT4_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/launcher/launcher.qrc)
|
||||
QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC})
|
||||
QT4_WRAP_UI(UI_HDRS ${LAUNCHER_UI})
|
||||
else()
|
||||
QT5_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/launcher/launcher.qrc)
|
||||
QT5_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC})
|
||||
QT5_WRAP_UI(UI_HDRS ${LAUNCHER_UI})
|
||||
endif()
|
||||
|
||||
|
||||
include(${QT_USE_FILE})
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
if(NOT WIN32)
|
||||
include_directories(${LIBUNSHIELD_INCLUDE_DIR})
|
||||
|
@ -88,17 +92,27 @@ add_executable(openmw-launcher
|
|||
)
|
||||
|
||||
target_link_libraries(openmw-launcher
|
||||
${Boost_LIBRARIES}
|
||||
${OGRE_LIBRARIES}
|
||||
${OGRE_STATIC_PLUGINS}
|
||||
${SDL2_LIBRARY_ONLY}
|
||||
${QT_LIBRARIES}
|
||||
components
|
||||
)
|
||||
|
||||
if (DESIRED_QT_VERSION MATCHES 4)
|
||||
target_link_libraries(openmw-launcher ${QT_QTGUI_LIBRARY} ${QT_QTCORE_LIBRARY})
|
||||
if(WIN32)
|
||||
target_link_libraries(openmw-launcher ${QT_QTMAIN_LIBRARY})
|
||||
endif(WIN32)
|
||||
else()
|
||||
qt5_use_modules(openmw-launcher Widgets Core)
|
||||
if (WIN32)
|
||||
target_link_libraries(Qt5::WinMain)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (BUILD_WITH_CODE_COVERAGE)
|
||||
add_definitions (--coverage)
|
||||
target_link_libraries(openmw-launcher gcov)
|
||||
endif()
|
||||
|
||||
|
||||
|
|
|
@ -54,9 +54,6 @@ int main(int argc, char *argv[])
|
|||
|
||||
QDir::setCurrent(dir.absolutePath());
|
||||
|
||||
// Support non-latin characters
|
||||
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
|
||||
|
||||
Launcher::MainDialog mainWin;
|
||||
|
||||
Launcher::FirstRunDialogResult result = mainWin.showFirstRunDialog();
|
||||
|
|
|
@ -309,11 +309,11 @@ bool Launcher::MainDialog::setupGameSettings()
|
|||
mGameSettings.readUserFile(stream);
|
||||
}
|
||||
|
||||
// Now the rest
|
||||
// Now the rest - priority: user > local > global
|
||||
QStringList paths;
|
||||
paths.append(userPath + QString("openmw.cfg"));
|
||||
paths.append(QString("openmw.cfg"));
|
||||
paths.append(globalPath + QString("openmw.cfg"));
|
||||
paths.append(QString("openmw.cfg"));
|
||||
paths.append(userPath + QString("openmw.cfg"));
|
||||
|
||||
foreach (const QString &path, paths) {
|
||||
qDebug() << "Loading config file:" << qPrintable(path);
|
||||
|
@ -490,7 +490,7 @@ bool Launcher::MainDialog::writeSettings()
|
|||
// Game settings
|
||||
QFile file(userPath + QString("openmw.cfg"));
|
||||
|
||||
if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) {
|
||||
if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) {
|
||||
// File cannot be opened or created
|
||||
QMessageBox msgBox;
|
||||
msgBox.setWindowTitle(tr("Error writing OpenMW configuration file"));
|
||||
|
@ -503,10 +503,8 @@ bool Launcher::MainDialog::writeSettings()
|
|||
return false;
|
||||
}
|
||||
|
||||
QTextStream stream(&file);
|
||||
stream.setCodec(QTextCodec::codecForName("UTF-8"));
|
||||
|
||||
mGameSettings.writeFile(stream);
|
||||
mGameSettings.writeFileWithComments(file);
|
||||
file.close();
|
||||
|
||||
// Graphics settings
|
||||
|
@ -525,6 +523,7 @@ bool Launcher::MainDialog::writeSettings()
|
|||
return false;
|
||||
}
|
||||
|
||||
QTextStream stream(&file);
|
||||
stream.setDevice(&file);
|
||||
stream.setCodec(QTextCodec::codecForName("UTF-8"));
|
||||
|
||||
|
|
|
@ -14,10 +14,20 @@ add_executable(openmw-iniimporter
|
|||
)
|
||||
|
||||
target_link_libraries(openmw-iniimporter
|
||||
${Boost_LIBRARIES}
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
${Boost_FILESYSTEM_LIBRARY}
|
||||
components
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(openmw-iniimporter
|
||||
${Boost_LOCALE_LIBRARY})
|
||||
endif()
|
||||
|
||||
if (MINGW)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -municode")
|
||||
endif()
|
||||
|
||||
if (BUILD_WITH_CODE_COVERAGE)
|
||||
add_definitions (--coverage)
|
||||
target_link_libraries(openmw-iniimporter gcov)
|
||||
|
|
19
apps/niftest/CMakeLists.txt
Normal file
19
apps/niftest/CMakeLists.txt
Normal file
|
@ -0,0 +1,19 @@
|
|||
set(NIFTEST
|
||||
niftest.cpp
|
||||
)
|
||||
source_group(components\\nif\\tests FILES ${NIFTEST})
|
||||
|
||||
# Main executable
|
||||
add_executable(niftest
|
||||
${NIFTEST}
|
||||
)
|
||||
|
||||
target_link_libraries(niftest
|
||||
${Boost_FILESYSTEM_LIBRARY}
|
||||
components
|
||||
)
|
||||
|
||||
if (BUILD_WITH_CODE_COVERAGE)
|
||||
add_definitions (--coverage)
|
||||
target_link_libraries(niftest gcov)
|
||||
endif()
|
165
apps/niftest/niftest.cpp
Normal file
165
apps/niftest/niftest.cpp
Normal file
|
@ -0,0 +1,165 @@
|
|||
///Program to test .nif files both on the FileSystem and in BSA archives.
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <components/nif/niffile.hpp>
|
||||
#include <components/files/constrainedfilestream.hpp>
|
||||
#include <components/vfs/manager.hpp>
|
||||
#include <components/vfs/bsaarchive.hpp>
|
||||
#include <components/vfs/filesystemarchive.hpp>
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
|
||||
// Create local aliases for brevity
|
||||
namespace bpo = boost::program_options;
|
||||
namespace bfs = boost::filesystem;
|
||||
|
||||
///See if the file has the named extension
|
||||
bool hasExtension(std::string filename, std::string extensionToFind)
|
||||
{
|
||||
std::string extension = filename.substr(filename.find_last_of(".")+1);
|
||||
|
||||
//Convert strings to lower case for comparison
|
||||
std::transform(extension.begin(), extension.end(), extension.begin(), ::tolower);
|
||||
std::transform(extensionToFind.begin(), extensionToFind.end(), extensionToFind.begin(), ::tolower);
|
||||
|
||||
if(extension == extensionToFind)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
///See if the file has the "nif" extension.
|
||||
bool isNIF(std::string filename)
|
||||
{
|
||||
return hasExtension(filename,"nif");
|
||||
}
|
||||
///See if the file has the "bsa" extension.
|
||||
bool isBSA(std::string filename)
|
||||
{
|
||||
return hasExtension(filename,"bsa");
|
||||
}
|
||||
|
||||
/// Check all the nif files in a given VFS::Archive
|
||||
/// \note Takes ownership!
|
||||
/// \note Can not read a bsa file inside of a bsa file.
|
||||
void readVFS(VFS::Archive* anArchive,std::string archivePath = "")
|
||||
{
|
||||
VFS::Manager myManager(true);
|
||||
myManager.addArchive(anArchive);
|
||||
myManager.buildIndex();
|
||||
|
||||
std::map<std::string, VFS::File*> files=myManager.getIndex();
|
||||
for(std::map<std::string, VFS::File*>::const_iterator it=files.begin(); it!=files.end(); ++it)
|
||||
{
|
||||
std::string name = it->first;
|
||||
|
||||
try{
|
||||
if(isNIF(name))
|
||||
{
|
||||
// std::cout << "Decoding: " << name << std::endl;
|
||||
Nif::NIFFile temp_nif(myManager.get(name),archivePath+name);
|
||||
}
|
||||
else if(isBSA(name))
|
||||
{
|
||||
if(!archivePath.empty() && !isBSA(archivePath))
|
||||
{
|
||||
// std::cout << "Reading BSA File: " << name << std::endl;
|
||||
readVFS(new VFS::BsaArchive(archivePath+name),archivePath+name+"/");
|
||||
// std::cout << "Done with BSA File: " << name << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << "ERROR, an exception has occurred: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> parseOptions (int argc, char** argv)
|
||||
{
|
||||
bpo::options_description desc("Ensure that OpenMW can use the provided NIF and BSA files\n\n"
|
||||
"Usages:\n"
|
||||
" niftool <nif files, BSA files, or directories>\n"
|
||||
" Scan the file or directories for nif errors.\n\n"
|
||||
"Allowed options");
|
||||
desc.add_options()
|
||||
("help,h", "print help message.")
|
||||
("input-file", bpo::value< std::vector<std::string> >(), "input file")
|
||||
;
|
||||
|
||||
//Default option if none provided
|
||||
bpo::positional_options_description p;
|
||||
p.add("input-file", -1);
|
||||
|
||||
bpo::variables_map variables;
|
||||
try
|
||||
{
|
||||
bpo::parsed_options valid_opts = bpo::command_line_parser(argc, argv).
|
||||
options(desc).positional(p).run();
|
||||
bpo::store(valid_opts, variables);
|
||||
}
|
||||
catch(std::exception &e)
|
||||
{
|
||||
std::cout << "ERROR parsing arguments: " << e.what() << "\n\n"
|
||||
<< desc << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
bpo::notify(variables);
|
||||
if (variables.count ("help"))
|
||||
{
|
||||
std::cout << desc << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
if (variables.count("input-file"))
|
||||
{
|
||||
return variables["input-file"].as< std::vector<std::string> >();
|
||||
}
|
||||
|
||||
std::cout << "No input files or directories specified!" << std::endl;
|
||||
std::cout << desc << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
std::vector<std::string> files = parseOptions (argc, argv);
|
||||
|
||||
// std::cout << "Reading Files" << std::endl;
|
||||
for(std::vector<std::string>::const_iterator it=files.begin(); it!=files.end(); ++it)
|
||||
{
|
||||
std::string name = *it;
|
||||
|
||||
try{
|
||||
if(isNIF(name))
|
||||
{
|
||||
//std::cout << "Decoding: " << name << std::endl;
|
||||
Nif::NIFFile temp_nif(Files::openConstrainedFileStream(name.c_str()),name);
|
||||
}
|
||||
else if(isBSA(name))
|
||||
{
|
||||
// std::cout << "Reading BSA File: " << name << std::endl;
|
||||
readVFS(new VFS::BsaArchive(name));
|
||||
}
|
||||
else if(bfs::is_directory(bfs::path(name)))
|
||||
{
|
||||
// std::cout << "Reading All Files in: " << name << std::endl;
|
||||
readVFS(new VFS::FileSystemArchive(name),name);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "ERROR: \"" << name << "\" is not a nif file, bsa file, or directory!" << std::endl;
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << "ERROR, an exception has occurred: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -18,14 +18,15 @@ opencs_hdrs_noqt (model/doc
|
|||
|
||||
|
||||
opencs_units (model/world
|
||||
idtable idtableproxymodel regionmap data commanddispatcher idtablebase resourcetable nestedtableproxymodel idtree
|
||||
idtable idtableproxymodel regionmap data commanddispatcher idtablebase resourcetable nestedtableproxymodel idtree infotableproxymodel
|
||||
)
|
||||
|
||||
|
||||
opencs_units_noqt (model/world
|
||||
universalid record commands columnbase scriptcontext cell refidcollection
|
||||
universalid record commands columnbase columnimp scriptcontext cell refidcollection
|
||||
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope
|
||||
pathgrid landtexture land nestedtablewrapper nestedcollection nestedcoladapterimp nestedinfocollection
|
||||
idcompletionmanager npcstats metadata
|
||||
)
|
||||
|
||||
opencs_hdrs_noqt (model/world
|
||||
|
@ -34,13 +35,18 @@ opencs_hdrs_noqt (model/world
|
|||
|
||||
|
||||
opencs_units (model/tools
|
||||
tools reportmodel
|
||||
tools reportmodel mergeoperation
|
||||
)
|
||||
|
||||
opencs_units_noqt (model/tools
|
||||
mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
|
||||
birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck
|
||||
startscriptcheck search searchoperation searchstage pathgridcheck
|
||||
startscriptcheck search searchoperation searchstage pathgridcheck soundgencheck magiceffectcheck
|
||||
mergestages
|
||||
)
|
||||
|
||||
opencs_hdrs_noqt (model/tools
|
||||
mergestate
|
||||
)
|
||||
|
||||
|
||||
|
@ -61,19 +67,20 @@ opencs_hdrs_noqt (view/doc
|
|||
|
||||
opencs_units (view/world
|
||||
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
|
||||
cellcreator referenceablecreator referencecreator scenesubview
|
||||
cellcreator referenceablecreator startscriptcreator referencecreator scenesubview
|
||||
infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable nestedtable
|
||||
dialoguespinbox
|
||||
dialoguespinbox recordbuttonbar tableeditidaction scripterrortable extendedcommandconfigurator
|
||||
)
|
||||
|
||||
opencs_units_noqt (view/world
|
||||
subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
|
||||
scripthighlighter idvalidator dialoguecreator physicssystem
|
||||
scripthighlighter idvalidator dialoguecreator physicssystem idcompletiondelegate
|
||||
colordelegate dragdroputils
|
||||
)
|
||||
|
||||
opencs_units (view/widget
|
||||
scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton
|
||||
scenetooltoggle2
|
||||
scenetooltoggle2 completerpopup coloreditor colorpickerpopup droplineedit
|
||||
)
|
||||
|
||||
opencs_units (view/render
|
||||
|
@ -92,7 +99,7 @@ opencs_hdrs_noqt (view/render
|
|||
|
||||
|
||||
opencs_units (view/tools
|
||||
reportsubview reporttable searchsubview searchbox
|
||||
reportsubview reporttable searchsubview searchbox merge
|
||||
)
|
||||
|
||||
opencs_units_noqt (view/tools
|
||||
|
@ -152,19 +159,16 @@ if(WIN32)
|
|||
set(QT_USE_QTMAIN TRUE)
|
||||
endif(WIN32)
|
||||
|
||||
set(BOOST_COMPONENTS system filesystem program_options thread wave)
|
||||
if(WIN32)
|
||||
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale)
|
||||
endif(WIN32)
|
||||
|
||||
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
||||
|
||||
find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED)
|
||||
include(${QT_USE_FILE})
|
||||
|
||||
qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI})
|
||||
qt4_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT})
|
||||
qt4_add_resources(OPENCS_RES_SRC ${OPENCS_RES})
|
||||
if (DESIRED_QT_VERSION MATCHES 4)
|
||||
include(${QT_USE_FILE})
|
||||
qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI})
|
||||
qt4_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT})
|
||||
qt4_add_resources(OPENCS_RES_SRC ${OPENCS_RES})
|
||||
else()
|
||||
qt5_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI})
|
||||
qt5_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT})
|
||||
qt5_add_resources(OPENCS_RES_SRC ${OPENCS_RES})
|
||||
endif()
|
||||
|
||||
# for compiled .ui files
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
@ -205,12 +209,36 @@ target_link_libraries(openmw-cs
|
|||
${OGRE_Overlay_LIBRARIES}
|
||||
${OGRE_STATIC_PLUGINS}
|
||||
${SHINY_LIBRARIES}
|
||||
${Boost_LIBRARIES}
|
||||
${Boost_SYSTEM_LIBRARY}
|
||||
${Boost_FILESYSTEM_LIBRARY}
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
${Boost_WAVE_LIBRARY}
|
||||
${BULLET_LIBRARIES}
|
||||
${QT_LIBRARIES}
|
||||
components
|
||||
)
|
||||
|
||||
if (DESIRED_QT_VERSION MATCHES 4)
|
||||
target_link_libraries(openmw-cs
|
||||
${QT_QTGUI_LIBRARY}
|
||||
${QT_QTCORE_LIBRARY}
|
||||
${QT_QTNETWORK_LIBRARY})
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(openmw-cs ${QT_QTMAIN_LIBRARY})
|
||||
endif()
|
||||
|
||||
else()
|
||||
qt5_use_modules(openmw-cs Widgets Core Network)
|
||||
if (WIN32)
|
||||
target_link_libraries(Qt5::WinMain)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(openmw-cs ${Boost_LOCALE_LIBRARY})
|
||||
endif()
|
||||
|
||||
|
||||
if(APPLE)
|
||||
INSTALL(TARGETS openmw-cs BUNDLE DESTINATION OpenMW COMPONENT BUNDLE)
|
||||
endif()
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "editor.hpp"
|
||||
|
||||
#include <openengine/bullet/BulletShapeLoader.h>
|
||||
|
@ -7,6 +6,9 @@
|
|||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
#include <QMessageBox>
|
||||
#include <QSplashScreen>
|
||||
#include <QFont>
|
||||
#include <QTimer>
|
||||
|
||||
#include <OgreRoot.h>
|
||||
#include <OgreRenderWindow.h>
|
||||
|
@ -24,7 +26,8 @@
|
|||
CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
|
||||
: mUserSettings (mCfgMgr), mOverlaySystem (0), mDocumentManager (mCfgMgr),
|
||||
mViewManager (mDocumentManager), mPid(""),
|
||||
mLock(), mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL)
|
||||
mLock(), mMerge (mDocumentManager),
|
||||
mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL)
|
||||
{
|
||||
std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig();
|
||||
|
||||
|
@ -46,9 +49,12 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
|
|||
|
||||
mNewGame.setLocalData (mLocal);
|
||||
mFileDialog.setLocalData (mLocal);
|
||||
mMerge.setLocalData (mLocal);
|
||||
|
||||
connect (&mDocumentManager, SIGNAL (documentAdded (CSMDoc::Document *)),
|
||||
this, SLOT (documentAdded (CSMDoc::Document *)));
|
||||
connect (&mDocumentManager, SIGNAL (documentAboutToBeRemoved (CSMDoc::Document *)),
|
||||
this, SLOT (documentAboutToBeRemoved (CSMDoc::Document *)));
|
||||
connect (&mDocumentManager, SIGNAL (lastDocumentDeleted()),
|
||||
this, SLOT (lastDocumentDeleted()));
|
||||
|
||||
|
@ -56,6 +62,7 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
|
|||
connect (&mViewManager, SIGNAL (newAddonRequest ()), this, SLOT (createAddon ()));
|
||||
connect (&mViewManager, SIGNAL (loadDocumentRequest ()), this, SLOT (loadDocument ()));
|
||||
connect (&mViewManager, SIGNAL (editSettingsRequest()), this, SLOT (showSettings ()));
|
||||
connect (&mViewManager, SIGNAL (mergeDocument (CSMDoc::Document *)), this, SLOT (mergeDocument (CSMDoc::Document *)));
|
||||
|
||||
connect (&mStartup, SIGNAL (createGame()), this, SLOT (createGame ()));
|
||||
connect (&mStartup, SIGNAL (createAddon()), this, SLOT (createAddon ()));
|
||||
|
@ -67,9 +74,11 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
|
|||
|
||||
connect (&mFileDialog, SIGNAL(signalCreateNewFile (const boost::filesystem::path&)),
|
||||
this, SLOT(createNewFile (const boost::filesystem::path&)));
|
||||
connect (&mFileDialog, SIGNAL (rejected()), this, SLOT (cancelFileDialog ()));
|
||||
|
||||
connect (&mNewGame, SIGNAL (createRequest (const boost::filesystem::path&)),
|
||||
this, SLOT (createNewGame (const boost::filesystem::path&)));
|
||||
connect (&mNewGame, SIGNAL (cancelCreateGame()), this, SLOT (cancelCreateGame ()));
|
||||
}
|
||||
|
||||
CS::Editor::~Editor ()
|
||||
|
@ -93,7 +102,7 @@ void CS::Editor::setupDataFiles (const Files::PathContainer& dataDirs)
|
|||
}
|
||||
}
|
||||
|
||||
std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfig()
|
||||
std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfig(bool quiet)
|
||||
{
|
||||
boost::program_options::variables_map variables;
|
||||
boost::program_options::options_description desc("Syntax: openmw-cs <options>\nAllowed options");
|
||||
|
@ -113,7 +122,7 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
|
|||
|
||||
boost::program_options::notify(variables);
|
||||
|
||||
mCfgMgr.readConfiguration(variables, desc);
|
||||
mCfgMgr.readConfiguration(variables, desc, quiet);
|
||||
|
||||
mDocumentManager.setEncoding (
|
||||
ToUTF8::calculateEncoding (variables["encoding"].as<std::string>()));
|
||||
|
@ -154,15 +163,23 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
|
|||
}
|
||||
|
||||
dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end());
|
||||
Files::PathContainer canonicalPaths;
|
||||
|
||||
//iterate the data directories and add them to the file dialog for loading
|
||||
for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter)
|
||||
{
|
||||
boost::filesystem::path p = boost::filesystem::canonical(*iter);
|
||||
Files::PathContainer::iterator it = std::find(canonicalPaths.begin(), canonicalPaths.end(), p);
|
||||
if (it == canonicalPaths.end())
|
||||
canonicalPaths.push_back(p);
|
||||
else
|
||||
continue;
|
||||
|
||||
QString path = QString::fromUtf8 (iter->string().c_str());
|
||||
mFileDialog.addFiles(path);
|
||||
}
|
||||
|
||||
return std::make_pair (dataDirs, variables["fallback-archive"].as<std::vector<std::string> >());
|
||||
return std::make_pair (canonicalPaths, variables["fallback-archive"].as<std::vector<std::string> >());
|
||||
}
|
||||
|
||||
void CS::Editor::createGame()
|
||||
|
@ -176,15 +193,53 @@ void CS::Editor::createGame()
|
|||
mNewGame.activateWindow();
|
||||
}
|
||||
|
||||
void CS::Editor::cancelCreateGame()
|
||||
{
|
||||
if (!mDocumentManager.isEmpty())
|
||||
return;
|
||||
|
||||
mNewGame.hide();
|
||||
|
||||
if (mStartup.isHidden())
|
||||
mStartup.show();
|
||||
|
||||
mStartup.raise();
|
||||
mStartup.activateWindow();
|
||||
}
|
||||
|
||||
void CS::Editor::createAddon()
|
||||
{
|
||||
mStartup.hide();
|
||||
|
||||
mFileDialog.clearFiles();
|
||||
std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig(/*quiet*/true);
|
||||
setupDataFiles (config.first);
|
||||
|
||||
mFileDialog.showDialog (CSVDoc::ContentAction_New);
|
||||
}
|
||||
|
||||
void CS::Editor::cancelFileDialog()
|
||||
{
|
||||
if (!mDocumentManager.isEmpty())
|
||||
return;
|
||||
|
||||
mFileDialog.hide();
|
||||
|
||||
if (mStartup.isHidden())
|
||||
mStartup.show();
|
||||
|
||||
mStartup.raise();
|
||||
mStartup.activateWindow();
|
||||
}
|
||||
|
||||
void CS::Editor::loadDocument()
|
||||
{
|
||||
mStartup.hide();
|
||||
|
||||
mFileDialog.clearFiles();
|
||||
std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig(/*quiet*/true);
|
||||
setupDataFiles (config.first);
|
||||
|
||||
mFileDialog.showDialog (CSVDoc::ContentAction_Edit);
|
||||
}
|
||||
|
||||
|
@ -213,6 +268,7 @@ void CS::Editor::createNewFile (const boost::filesystem::path &savePath)
|
|||
mDocumentManager.addDocument (files, savePath, true);
|
||||
|
||||
mFileDialog.hide();
|
||||
showSplashMessage();
|
||||
}
|
||||
|
||||
void CS::Editor::createNewGame (const boost::filesystem::path& file)
|
||||
|
@ -224,6 +280,7 @@ void CS::Editor::createNewGame (const boost::filesystem::path& file)
|
|||
mDocumentManager.addDocument (files, file, true);
|
||||
|
||||
mNewGame.hide();
|
||||
showSplashMessage();
|
||||
}
|
||||
|
||||
void CS::Editor::showStartup()
|
||||
|
@ -277,12 +334,12 @@ bool CS::Editor::makeIPCServer()
|
|||
mServer->close();
|
||||
fullPath.remove(QRegExp("dummy$"));
|
||||
fullPath += mIpcServerName;
|
||||
if(boost::filesystem::exists(fullPath.toStdString().c_str()))
|
||||
if(boost::filesystem::exists(fullPath.toUtf8().constData()))
|
||||
{
|
||||
// TODO: compare pid of the current process with that in the file
|
||||
std::cout << "Detected unclean shutdown." << std::endl;
|
||||
// delete the stale file
|
||||
if(remove(fullPath.toStdString().c_str()))
|
||||
if(remove(fullPath.toUtf8().constData()))
|
||||
std::cerr << "ERROR removing stale connection file" << std::endl;
|
||||
}
|
||||
}
|
||||
|
@ -435,9 +492,65 @@ std::auto_ptr<sh::Factory> CS::Editor::setupGraphics()
|
|||
void CS::Editor::documentAdded (CSMDoc::Document *document)
|
||||
{
|
||||
mViewManager.addView (document);
|
||||
showSplashMessage();
|
||||
}
|
||||
|
||||
void CS::Editor::documentAboutToBeRemoved (CSMDoc::Document *document)
|
||||
{
|
||||
if (mMerge.getDocument()==document)
|
||||
mMerge.cancel();
|
||||
}
|
||||
|
||||
void CS::Editor::lastDocumentDeleted()
|
||||
{
|
||||
QApplication::quit();
|
||||
}
|
||||
|
||||
void CS::Editor::showSplashMessage()
|
||||
{
|
||||
CSMSettings::UserSettings &settings = CSMSettings::UserSettings::instance();
|
||||
if(settings.settingValue ("filter/project-added") == "true" ||
|
||||
settings.settingValue ("filter/project-modified") == "true")
|
||||
{
|
||||
QPixmap img(QPixmap(":./openmw-cs.png"));
|
||||
|
||||
QString msgTop("You have active global filters.");
|
||||
QString msgBottom("Some rows may be hidden!");
|
||||
QFont splashFont(QFont("Arial", 16, QFont::Bold)); // TODO: use system font?
|
||||
//splashFont.setStretch(125);
|
||||
|
||||
QFontMetrics fm(splashFont);
|
||||
int msgWidth = std::max(fm.width(msgTop), fm.width(msgBottom));
|
||||
img.scaledToWidth(msgWidth);
|
||||
|
||||
QSplashScreen *splash = new QSplashScreen(img, Qt::WindowStaysOnTopHint);
|
||||
splash->setFont(splashFont);
|
||||
splash->resize(msgWidth+20, splash->height()+fm.lineSpacing()*2+20); // add some margin
|
||||
|
||||
// try to center the message near the center of the saved window
|
||||
QWidget dummy;
|
||||
bool xWorkaround = settings.settingValue ("window/x-save-state-workaround").toStdString() == "true";
|
||||
if (settings.settingValue ("window/save-state").toStdString() == "true" &&
|
||||
!(xWorkaround && settings.settingValue ("window/maximized").toStdString() == "true"))
|
||||
{
|
||||
dummy.restoreGeometry(settings.value("window/geometry").toByteArray());
|
||||
splash->move(dummy.x()+std::max(0, (dummy.width()-msgWidth)/2),
|
||||
dummy.y()+std::max(0, (dummy.height()-splash->height())/2));
|
||||
}
|
||||
else
|
||||
splash->move(std::max(0, splash->x()-msgWidth/2), splash->y());
|
||||
|
||||
splash->show();
|
||||
splash->showMessage(msgTop+"\n"+msgBottom, Qt::AlignHCenter|Qt::AlignBottom, Qt::red);
|
||||
QTimer::singleShot(4000, splash, SLOT(close())); // 4 seconds should be enough
|
||||
splash->raise(); // for X windows
|
||||
}
|
||||
}
|
||||
|
||||
void CS::Editor::mergeDocument (CSMDoc::Document *document)
|
||||
{
|
||||
mMerge.configure (document);
|
||||
mMerge.show();
|
||||
mMerge.raise();
|
||||
mMerge.activateWindow();
|
||||
}
|
||||
|
|
|
@ -32,11 +32,18 @@
|
|||
#include "view/settings/dialog.hpp"
|
||||
#include "view/render/overlaysystem.hpp"
|
||||
|
||||
#include "view/tools/merge.hpp"
|
||||
|
||||
namespace OgreInit
|
||||
{
|
||||
class OgreInit;
|
||||
}
|
||||
|
||||
namespace CSMDoc
|
||||
{
|
||||
class Document;
|
||||
}
|
||||
|
||||
namespace CS
|
||||
{
|
||||
class Editor : public QObject
|
||||
|
@ -59,10 +66,13 @@ namespace CS
|
|||
boost::interprocess::file_lock mLock;
|
||||
boost::filesystem::ofstream mPidFile;
|
||||
bool mFsStrict;
|
||||
CSVTools::Merge mMerge;
|
||||
|
||||
void showSplashMessage();
|
||||
|
||||
void setupDataFiles (const Files::PathContainer& dataDirs);
|
||||
|
||||
std::pair<Files::PathContainer, std::vector<std::string> > readConfig();
|
||||
std::pair<Files::PathContainer, std::vector<std::string> > readConfig(bool quiet=false);
|
||||
///< \return data paths
|
||||
|
||||
// not implemented
|
||||
|
@ -87,6 +97,8 @@ namespace CS
|
|||
|
||||
void createGame();
|
||||
void createAddon();
|
||||
void cancelCreateGame();
|
||||
void cancelFileDialog();
|
||||
|
||||
void loadDocument();
|
||||
void openFiles (const boost::filesystem::path &path);
|
||||
|
@ -99,8 +111,12 @@ namespace CS
|
|||
|
||||
void documentAdded (CSMDoc::Document *document);
|
||||
|
||||
void documentAboutToBeRemoved (CSMDoc::Document *document);
|
||||
|
||||
void lastDocumentDeleted();
|
||||
|
||||
void mergeDocument (CSMDoc::Document *document);
|
||||
|
||||
private:
|
||||
|
||||
QString mIpcServerName;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "editor.hpp"
|
||||
|
||||
#include <exception>
|
||||
|
@ -13,6 +12,8 @@
|
|||
|
||||
#include <components/ogreinit/ogreinit.hpp>
|
||||
|
||||
#include "model/doc/messages.hpp"
|
||||
|
||||
#include "model/world/universalid.hpp"
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
|
@ -52,6 +53,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
qRegisterMetaType<std::string> ("std::string");
|
||||
qRegisterMetaType<CSMWorld::UniversalId> ("CSMWorld::UniversalId");
|
||||
qRegisterMetaType<CSMDoc::Message> ("CSMDoc::Message");
|
||||
|
||||
OgreInit::OgreInit ogreInit;
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "blacklist.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
|
|
@ -799,9 +799,9 @@ void CSMDoc::Document::addGmsts()
|
|||
"sBookSkillMessage",
|
||||
"sBounty",
|
||||
"sBreath",
|
||||
"sBribe",
|
||||
"sBribe",
|
||||
"sBribe",
|
||||
"sBribe 10 Gold",
|
||||
"sBribe 100 Gold",
|
||||
"sBribe 1000 Gold",
|
||||
"sBribeFail",
|
||||
"sBribeSuccess",
|
||||
"sBuy",
|
||||
|
@ -2251,13 +2251,14 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
|||
ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager,
|
||||
const std::vector<std::string>& blacklistedScripts)
|
||||
: mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding, resourcesManager),
|
||||
mTools (*this),
|
||||
mTools (*this, encoding),
|
||||
mProjectPath ((configuration.getUserDataPath() / "projects") /
|
||||
(savePath.filename().string() + ".project")),
|
||||
mSavingOperation (*this, mProjectPath, encoding),
|
||||
mSaving (&mSavingOperation),
|
||||
mResDir(resDir),
|
||||
mRunner (mProjectPath), mPhysics(boost::shared_ptr<CSVWorld::PhysicsSystem>())
|
||||
mRunner (mProjectPath), mPhysics(boost::shared_ptr<CSVWorld::PhysicsSystem>()),
|
||||
mDirty (false), mIdCompletionManager(mData)
|
||||
{
|
||||
if (mContentFiles.empty())
|
||||
throw std::runtime_error ("Empty content file sequence");
|
||||
|
@ -2271,7 +2272,7 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
|||
|
||||
if (boost::filesystem::exists (customFiltersPath))
|
||||
{
|
||||
destination << std::ifstream(customFiltersPath.c_str(), std::ios::binary).rdbuf();
|
||||
destination << std::ifstream(customFiltersPath.string().c_str(), std::ios::binary).rdbuf();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2281,9 +2282,6 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
|||
|
||||
if (mNew)
|
||||
{
|
||||
mData.setDescription ("");
|
||||
mData.setAuthor ("");
|
||||
|
||||
if (mContentFiles.size()==1)
|
||||
createBase();
|
||||
}
|
||||
|
@ -2298,13 +2296,15 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
|||
|
||||
connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
||||
connect (&mTools, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool)));
|
||||
connect (&mTools, SIGNAL (mergeDone (CSMDoc::Document*)),
|
||||
this, SIGNAL (mergeDone (CSMDoc::Document*)));
|
||||
|
||||
connect (&mSaving, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
||||
connect (&mSaving, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool)));
|
||||
|
||||
connect (
|
||||
&mSaving, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)),
|
||||
this, SLOT (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)));
|
||||
&mSaving, SIGNAL (reportMessage (const CSMDoc::Message&, int)),
|
||||
this, SLOT (reportMessage (const CSMDoc::Message&, int)));
|
||||
|
||||
connect (&mRunner, SIGNAL (runStateChanged()), this, SLOT (runStateChanged()));
|
||||
}
|
||||
|
@ -2322,7 +2322,7 @@ int CSMDoc::Document::getState() const
|
|||
{
|
||||
int state = 0;
|
||||
|
||||
if (!mUndoStack.isClean())
|
||||
if (!mUndoStack.isClean() || mDirty)
|
||||
state |= State_Modified;
|
||||
|
||||
if (mSaving.isRunning())
|
||||
|
@ -2368,9 +2368,9 @@ void CSMDoc::Document::save()
|
|||
emit stateChanged (getState(), this);
|
||||
}
|
||||
|
||||
CSMWorld::UniversalId CSMDoc::Document::verify()
|
||||
CSMWorld::UniversalId CSMDoc::Document::verify (const CSMWorld::UniversalId& reportId)
|
||||
{
|
||||
CSMWorld::UniversalId id = mTools.runVerifier();
|
||||
CSMWorld::UniversalId id = mTools.runVerifier (reportId);
|
||||
emit stateChanged (getState(), this);
|
||||
return id;
|
||||
}
|
||||
|
@ -2387,6 +2387,12 @@ void CSMDoc::Document::runSearch (const CSMWorld::UniversalId& searchId, const C
|
|||
emit stateChanged (getState(), this);
|
||||
}
|
||||
|
||||
void CSMDoc::Document::runMerge (std::auto_ptr<CSMDoc::Document> target)
|
||||
{
|
||||
mTools.runMerge (target);
|
||||
emit stateChanged (getState(), this);
|
||||
}
|
||||
|
||||
void CSMDoc::Document::abortOperation (int type)
|
||||
{
|
||||
if (type==State_Saving)
|
||||
|
@ -2400,15 +2406,17 @@ void CSMDoc::Document::modificationStateChanged (bool clean)
|
|||
emit stateChanged (getState(), this);
|
||||
}
|
||||
|
||||
void CSMDoc::Document::reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint, int type)
|
||||
void CSMDoc::Document::reportMessage (const CSMDoc::Message& message, int type)
|
||||
{
|
||||
/// \todo find a better way to get these messages to the user.
|
||||
std::cout << message << std::endl;
|
||||
std::cout << message.mMessage << std::endl;
|
||||
}
|
||||
|
||||
void CSMDoc::Document::operationDone (int type, bool failed)
|
||||
{
|
||||
if (type==CSMDoc::State_Saving && !failed)
|
||||
mDirty = false;
|
||||
|
||||
emit stateChanged (getState(), this);
|
||||
}
|
||||
|
||||
|
@ -2488,3 +2496,13 @@ boost::shared_ptr<CSVWorld::PhysicsSystem> CSMDoc::Document::getPhysics ()
|
|||
|
||||
return mPhysics;
|
||||
}
|
||||
|
||||
CSMWorld::IdCompletionManager &CSMDoc::Document::getIdCompletionManager()
|
||||
{
|
||||
return mIdCompletionManager;
|
||||
}
|
||||
|
||||
void CSMDoc::Document::flagAsDirty()
|
||||
{
|
||||
mDirty = true;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <components/to_utf8/to_utf8.hpp>
|
||||
|
||||
#include "../world/data.hpp"
|
||||
#include "../world/idcompletionmanager.hpp"
|
||||
|
||||
#include "../tools/tools.hpp"
|
||||
|
||||
|
@ -66,6 +67,9 @@ namespace CSMDoc
|
|||
Blacklist mBlacklist;
|
||||
Runner mRunner;
|
||||
boost::shared_ptr<CSVWorld::PhysicsSystem> mPhysics;
|
||||
bool mDirty;
|
||||
|
||||
CSMWorld::IdCompletionManager mIdCompletionManager;
|
||||
|
||||
// It is important that the undo stack is declared last, because on desctruction it fires a signal, that is connected to a slot, that is
|
||||
// using other member variables. Unfortunately this connection is cut only in the QObject destructor, which is way too late.
|
||||
|
@ -118,12 +122,14 @@ namespace CSMDoc
|
|||
|
||||
void save();
|
||||
|
||||
CSMWorld::UniversalId verify();
|
||||
CSMWorld::UniversalId verify (const CSMWorld::UniversalId& reportId = CSMWorld::UniversalId());
|
||||
|
||||
CSMWorld::UniversalId newSearch();
|
||||
|
||||
void runSearch (const CSMWorld::UniversalId& searchId, const CSMTools::Search& search);
|
||||
|
||||
|
||||
void runMerge (std::auto_ptr<CSMDoc::Document> target);
|
||||
|
||||
void abortOperation (int type);
|
||||
|
||||
const CSMWorld::Data& getData() const;
|
||||
|
@ -144,18 +150,25 @@ namespace CSMDoc
|
|||
|
||||
boost::shared_ptr<CSVWorld::PhysicsSystem> getPhysics();
|
||||
|
||||
CSMWorld::IdCompletionManager &getIdCompletionManager();
|
||||
|
||||
void flagAsDirty();
|
||||
|
||||
signals:
|
||||
|
||||
void stateChanged (int state, CSMDoc::Document *document);
|
||||
|
||||
void progress (int current, int max, int type, int threads, CSMDoc::Document *document);
|
||||
|
||||
/// \attention When this signal is emitted, *this hands over the ownership of the
|
||||
/// document. This signal must be handled to avoid a leak.
|
||||
void mergeDone (CSMDoc::Document *document);
|
||||
|
||||
private slots:
|
||||
|
||||
void modificationStateChanged (bool clean);
|
||||
|
||||
void reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint, int type);
|
||||
void reportMessage (const CSMDoc::Message& message, int type);
|
||||
|
||||
void operationDone (int type, bool failed);
|
||||
|
||||
|
@ -168,4 +181,3 @@ namespace CSMDoc
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "documentmanager.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
@ -49,13 +48,32 @@ CSMDoc::DocumentManager::~DocumentManager()
|
|||
delete *iter;
|
||||
}
|
||||
|
||||
bool CSMDoc::DocumentManager::isEmpty()
|
||||
{
|
||||
return mDocuments.empty();
|
||||
}
|
||||
|
||||
void CSMDoc::DocumentManager::addDocument (const std::vector<boost::filesystem::path>& files, const boost::filesystem::path& savePath,
|
||||
bool new_)
|
||||
{
|
||||
Document *document = new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding, mResourcesManager, mBlacklistedScripts);
|
||||
Document *document = makeDocument (files, savePath, new_);
|
||||
insertDocument (document);
|
||||
}
|
||||
|
||||
CSMDoc::Document *CSMDoc::DocumentManager::makeDocument (
|
||||
const std::vector< boost::filesystem::path >& files,
|
||||
const boost::filesystem::path& savePath, bool new_)
|
||||
{
|
||||
return new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding, mResourcesManager, mBlacklistedScripts);
|
||||
}
|
||||
|
||||
void CSMDoc::DocumentManager::insertDocument (CSMDoc::Document *document)
|
||||
{
|
||||
mDocuments.push_back (document);
|
||||
|
||||
connect (document, SIGNAL (mergeDone (CSMDoc::Document*)),
|
||||
this, SLOT (insertDocument (CSMDoc::Document*)));
|
||||
|
||||
emit loadRequest (document);
|
||||
|
||||
mLoader.hasThingsToDo().wakeAll();
|
||||
|
@ -68,6 +86,8 @@ void CSMDoc::DocumentManager::removeDocument (CSMDoc::Document *document)
|
|||
if (iter==mDocuments.end())
|
||||
throw std::runtime_error ("removing invalid document");
|
||||
|
||||
emit documentAboutToBeRemoved (document);
|
||||
|
||||
mDocuments.erase (iter);
|
||||
document->deleteLater();
|
||||
|
||||
|
|
|
@ -50,6 +50,15 @@ namespace CSMDoc
|
|||
///< \param new_ Do not load the last content file in \a files and instead create in an
|
||||
/// appropriate way.
|
||||
|
||||
/// Create a new document. The ownership of the created document is transferred to
|
||||
/// the calling function. The DocumentManager does not manage it. Loading has not
|
||||
/// taken place at the point when the document is returned.
|
||||
///
|
||||
/// \param new_ Do not load the last content file in \a files and instead create in an
|
||||
/// appropriate way.
|
||||
Document *makeDocument (const std::vector< boost::filesystem::path >& files,
|
||||
const boost::filesystem::path& savePath, bool new_);
|
||||
|
||||
void setResourceDir (const boost::filesystem::path& parResDir);
|
||||
|
||||
void setEncoding (ToUTF8::FromType encoding);
|
||||
|
@ -59,6 +68,8 @@ namespace CSMDoc
|
|||
/// Ask OGRE for a list of available resources.
|
||||
void listResources();
|
||||
|
||||
bool isEmpty();
|
||||
|
||||
private:
|
||||
|
||||
boost::filesystem::path mResDir;
|
||||
|
@ -77,10 +88,16 @@ namespace CSMDoc
|
|||
void removeDocument (CSMDoc::Document *document);
|
||||
///< Emits the lastDocumentDeleted signal, if applicable.
|
||||
|
||||
/// Hand over document to *this. The ownership is transferred. The DocumentManager
|
||||
/// will initiate the load procedure, if necessary
|
||||
void insertDocument (CSMDoc::Document *document);
|
||||
|
||||
signals:
|
||||
|
||||
void documentAdded (CSMDoc::Document *document);
|
||||
|
||||
void documentAboutToBeRemoved (CSMDoc::Document *document);
|
||||
|
||||
void loadRequest (CSMDoc::Document *document);
|
||||
|
||||
void lastDocumentDeleted();
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "loader.hpp"
|
||||
|
||||
#include <QTimer>
|
||||
|
@ -52,7 +51,7 @@ void CSMDoc::Loader::load()
|
|||
{
|
||||
if (iter->second.mRecordsLeft)
|
||||
{
|
||||
CSMDoc::Messages messages;
|
||||
Messages messages (Message::Severity_Error);
|
||||
for (int i=0; i<batchingSize; ++i) // do not flood the system with update signals
|
||||
if (document->getData().continueLoading (messages))
|
||||
{
|
||||
|
@ -68,7 +67,7 @@ void CSMDoc::Loader::load()
|
|||
for (CSMDoc::Messages::Iterator iter (messages.begin());
|
||||
iter!=messages.end(); ++iter)
|
||||
{
|
||||
document->getReport (log)->add (iter->mId, iter->mMessage);
|
||||
document->getReport (log)->add (*iter);
|
||||
emit loadMessage (document, iter->mMessage);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,38 @@
|
|||
|
||||
#include "messages.hpp"
|
||||
|
||||
void CSMDoc::Messages::add (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint)
|
||||
{
|
||||
Message data;
|
||||
data.mId = id;
|
||||
data.mMessage = message;
|
||||
data.mHint = hint;
|
||||
CSMDoc::Message::Message() {}
|
||||
|
||||
mMessages.push_back (data);
|
||||
CSMDoc::Message::Message (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint, Severity severity)
|
||||
: mId (id), mMessage (message), mHint (hint), mSeverity (severity)
|
||||
{}
|
||||
|
||||
std::string CSMDoc::Message::toString (Severity severity)
|
||||
{
|
||||
switch (severity)
|
||||
{
|
||||
case CSMDoc::Message::Severity_Info: return "Information";
|
||||
case CSMDoc::Message::Severity_Warning: return "Warning";
|
||||
case CSMDoc::Message::Severity_Error: return "Error";
|
||||
case CSMDoc::Message::Severity_SeriousError: return "Serious Error";
|
||||
case CSMDoc::Message::Severity_Default: break;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
CSMDoc::Messages::Messages (Message::Severity default_)
|
||||
: mDefault (default_)
|
||||
{}
|
||||
|
||||
void CSMDoc::Messages::add (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint, Message::Severity severity)
|
||||
{
|
||||
if (severity==Message::Severity_Default)
|
||||
severity = mDefault;
|
||||
|
||||
mMessages.push_back (Message (id, message, hint, severity));
|
||||
}
|
||||
|
||||
void CSMDoc::Messages::push_back (const std::pair<CSMWorld::UniversalId, std::string>& data)
|
||||
|
|
|
@ -4,20 +4,43 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <QMetaType>
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
namespace CSMDoc
|
||||
{
|
||||
struct Message
|
||||
{
|
||||
enum Severity
|
||||
{
|
||||
Severity_Info = 0, // no problem
|
||||
Severity_Warning = 1, // a potential problem, but we are probably fine
|
||||
Severity_Error = 2, // an error; we are not fine
|
||||
Severity_SeriousError = 3, // an error so bad we can't even be sure if we are
|
||||
// reporting it correctly
|
||||
Severity_Default = 4
|
||||
};
|
||||
|
||||
CSMWorld::UniversalId mId;
|
||||
std::string mMessage;
|
||||
std::string mHint;
|
||||
Severity mSeverity;
|
||||
|
||||
Message();
|
||||
|
||||
Message (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint, Severity severity);
|
||||
|
||||
static std::string toString (Severity severity);
|
||||
};
|
||||
|
||||
class Messages
|
||||
{
|
||||
public:
|
||||
|
||||
struct Message
|
||||
{
|
||||
CSMWorld::UniversalId mId;
|
||||
std::string mMessage;
|
||||
std::string mHint;
|
||||
};
|
||||
// \deprecated Use CSMDoc::Message directly instead.
|
||||
typedef CSMDoc::Message Message;
|
||||
|
||||
typedef std::vector<Message> Collection;
|
||||
|
||||
|
@ -26,11 +49,15 @@ namespace CSMDoc
|
|||
private:
|
||||
|
||||
Collection mMessages;
|
||||
Message::Severity mDefault;
|
||||
|
||||
public:
|
||||
|
||||
Messages (Message::Severity default_);
|
||||
|
||||
void add (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint = "");
|
||||
const std::string& hint = "",
|
||||
Message::Severity severity = Message::Severity_Default);
|
||||
|
||||
/// \deprecated Use add instead.
|
||||
void push_back (const std::pair<CSMWorld::UniversalId, std::string>& data);
|
||||
|
@ -41,4 +68,6 @@ namespace CSMDoc
|
|||
};
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE (CSMDoc::Message)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "operation.hpp"
|
||||
|
||||
#include <string>
|
||||
|
@ -7,6 +6,7 @@
|
|||
#include <QTimer>
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
#include "../settings/usersettings.hpp"
|
||||
|
||||
#include "state.hpp"
|
||||
#include "stage.hpp"
|
||||
|
@ -23,13 +23,17 @@ void CSMDoc::Operation::prepareStages()
|
|||
{
|
||||
iter->second = iter->first->setup();
|
||||
mTotalSteps += iter->second;
|
||||
|
||||
for (std::map<QString, QStringList>::const_iterator iter2 (mSettings.begin()); iter2!=mSettings.end(); ++iter2)
|
||||
iter->first->updateUserSetting (iter2->first, iter2->second);
|
||||
}
|
||||
}
|
||||
|
||||
CSMDoc::Operation::Operation (int type, bool ordered, bool finalAlways)
|
||||
: mType (type), mStages(std::vector<std::pair<Stage *, int> >()), mCurrentStage(mStages.begin()),
|
||||
mCurrentStep(0), mCurrentStepTotal(0), mTotalSteps(0), mOrdered (ordered),
|
||||
mFinalAlways (finalAlways), mError(false), mConnected (false)
|
||||
mFinalAlways (finalAlways), mError(false), mConnected (false), mPrepared (false),
|
||||
mDefaultSeverity (Message::Severity_Error)
|
||||
{
|
||||
mTimer = new QTimer (this);
|
||||
}
|
||||
|
@ -49,8 +53,8 @@ void CSMDoc::Operation::run()
|
|||
connect (mTimer, SIGNAL (timeout()), this, SLOT (executeStage()));
|
||||
mConnected = true;
|
||||
}
|
||||
|
||||
prepareStages();
|
||||
|
||||
mPrepared = false;
|
||||
|
||||
mTimer->start (0);
|
||||
}
|
||||
|
@ -60,6 +64,19 @@ void CSMDoc::Operation::appendStage (Stage *stage)
|
|||
mStages.push_back (std::make_pair (stage, 0));
|
||||
}
|
||||
|
||||
void CSMDoc::Operation::configureSettings (const std::vector<QString>& settings)
|
||||
{
|
||||
for (std::vector<QString>::const_iterator iter (settings.begin()); iter!=settings.end(); ++iter)
|
||||
{
|
||||
mSettings.insert (std::make_pair (*iter, CSMSettings::UserSettings::instance().definitions (*iter)));
|
||||
}
|
||||
}
|
||||
|
||||
void CSMDoc::Operation::setDefaultSeverity (Message::Severity severity)
|
||||
{
|
||||
mDefaultSeverity = severity;
|
||||
}
|
||||
|
||||
bool CSMDoc::Operation::hasError() const
|
||||
{
|
||||
return mError;
|
||||
|
@ -84,9 +101,23 @@ void CSMDoc::Operation::abort()
|
|||
mCurrentStage = mStages.end();
|
||||
}
|
||||
|
||||
void CSMDoc::Operation::updateUserSetting (const QString& name, const QStringList& value)
|
||||
{
|
||||
std::map<QString, QStringList>::iterator iter = mSettings.find (name);
|
||||
|
||||
if (iter!=mSettings.end())
|
||||
iter->second = value;
|
||||
}
|
||||
|
||||
void CSMDoc::Operation::executeStage()
|
||||
{
|
||||
Messages messages;
|
||||
if (!mPrepared)
|
||||
{
|
||||
prepareStages();
|
||||
mPrepared = true;
|
||||
}
|
||||
|
||||
Messages messages (mDefaultSeverity);
|
||||
|
||||
while (mCurrentStage!=mStages.end())
|
||||
{
|
||||
|
@ -103,7 +134,7 @@ void CSMDoc::Operation::executeStage()
|
|||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
emit reportMessage (CSMWorld::UniversalId(), e.what(), "", mType);
|
||||
emit reportMessage (Message (CSMWorld::UniversalId(), e.what(), "", Message::Severity_SeriousError), mType);
|
||||
abort();
|
||||
}
|
||||
|
||||
|
@ -115,7 +146,7 @@ void CSMDoc::Operation::executeStage()
|
|||
emit progress (mCurrentStepTotal, mTotalSteps ? mTotalSteps : 1, mType);
|
||||
|
||||
for (Messages::Iterator iter (messages.begin()); iter!=messages.end(); ++iter)
|
||||
emit reportMessage (iter->mId, iter->mMessage, iter->mHint, mType);
|
||||
emit reportMessage (*iter, mType);
|
||||
|
||||
if (mCurrentStage==mStages.end())
|
||||
operationDone();
|
||||
|
|
|
@ -2,9 +2,13 @@
|
|||
#define CSM_DOC_OPERATION_H
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
#include <QStringList>
|
||||
|
||||
#include "messages.hpp"
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
|
@ -30,6 +34,9 @@ namespace CSMDoc
|
|||
bool mError;
|
||||
bool mConnected;
|
||||
QTimer *mTimer;
|
||||
std::map<QString, QStringList> mSettings;
|
||||
bool mPrepared;
|
||||
Message::Severity mDefaultSeverity;
|
||||
|
||||
void prepareStages();
|
||||
|
||||
|
@ -46,14 +53,21 @@ namespace CSMDoc
|
|||
///
|
||||
/// \attention Do no call this function while this Operation is running.
|
||||
|
||||
/// Specify settings to be passed on to stages.
|
||||
///
|
||||
/// \attention Do no call this function while this Operation is running.
|
||||
void configureSettings (const std::vector<QString>& settings);
|
||||
|
||||
/// \attention Do no call this function while this Operation is running.
|
||||
void setDefaultSeverity (Message::Severity severity);
|
||||
|
||||
bool hasError() const;
|
||||
|
||||
signals:
|
||||
|
||||
void progress (int current, int max, int type);
|
||||
|
||||
void reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint, int type);
|
||||
void reportMessage (const CSMDoc::Message& message, int type);
|
||||
|
||||
void done (int type, bool failed);
|
||||
|
||||
|
@ -63,11 +77,15 @@ namespace CSMDoc
|
|||
|
||||
void run();
|
||||
|
||||
void updateUserSetting (const QString& name, const QStringList& value);
|
||||
|
||||
private slots:
|
||||
|
||||
void executeStage();
|
||||
|
||||
void operationDone();
|
||||
protected slots:
|
||||
|
||||
virtual void operationDone();
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
#include "operationholder.hpp"
|
||||
|
||||
#include "../settings/usersettings.hpp"
|
||||
|
||||
#include "operation.hpp"
|
||||
|
||||
CSMDoc::OperationHolder::OperationHolder (Operation *operation) : mRunning (false)
|
||||
|
@ -19,8 +20,8 @@ void CSMDoc::OperationHolder::setOperation (Operation *operation)
|
|||
this, SIGNAL (progress (int, int, int)));
|
||||
|
||||
connect (
|
||||
mOperation, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)),
|
||||
this, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)));
|
||||
mOperation, SIGNAL (reportMessage (const CSMDoc::Message&, int)),
|
||||
this, SIGNAL (reportMessage (const CSMDoc::Message&, int)));
|
||||
|
||||
connect (
|
||||
mOperation, SIGNAL (done (int, bool)),
|
||||
|
@ -29,6 +30,9 @@ void CSMDoc::OperationHolder::setOperation (Operation *operation)
|
|||
connect (this, SIGNAL (abortSignal()), mOperation, SLOT (abort()));
|
||||
|
||||
connect (&mThread, SIGNAL (started()), mOperation, SLOT (run()));
|
||||
|
||||
connect (&CSMSettings::UserSettings::instance(), SIGNAL (userSettingUpdated (const QString&, const QStringList&)),
|
||||
mOperation, SLOT (updateUserSetting (const QString&, const QStringList&)));
|
||||
}
|
||||
|
||||
bool CSMDoc::OperationHolder::isRunning() const
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
#include <QObject>
|
||||
#include <QThread>
|
||||
|
||||
#include "messages.hpp"
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
class UniversalId;
|
||||
|
@ -44,8 +46,7 @@ namespace CSMDoc
|
|||
|
||||
void progress (int current, int max, int type);
|
||||
|
||||
void reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint, int type);
|
||||
void reportMessage (const CSMDoc::Message& message, int type);
|
||||
|
||||
void done (int type, bool failed);
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "runner.hpp"
|
||||
|
||||
#include <QApplication>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "saving.hpp"
|
||||
|
||||
#include "../world/data.hpp"
|
||||
|
@ -81,22 +80,25 @@ CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& proje
|
|||
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::StartScript> >
|
||||
(mDocument.getData().getStartScripts(), mState));
|
||||
|
||||
appendStage (new WriteDialogueCollectionStage (mDocument, mState, false));
|
||||
|
||||
appendStage (new WriteDialogueCollectionStage (mDocument, mState, true));
|
||||
|
||||
appendStage (new WriteRefIdCollectionStage (mDocument, mState));
|
||||
|
||||
appendStage (new CollectionReferencesStage (mDocument, mState));
|
||||
|
||||
appendStage (new WriteCellCollectionStage (mDocument, mState));
|
||||
|
||||
// Dialogue can reference objects and cells so must be written after these records for vanilla-compatible files
|
||||
|
||||
appendStage (new WriteDialogueCollectionStage (mDocument, mState, false));
|
||||
|
||||
appendStage (new WriteDialogueCollectionStage (mDocument, mState, true));
|
||||
|
||||
appendStage (new WritePathgridCollectionStage (mDocument, mState));
|
||||
|
||||
appendStage (new WriteLandCollectionStage (mDocument, mState));
|
||||
|
||||
appendStage (new WriteLandTextureCollectionStage (mDocument, mState));
|
||||
|
||||
// references Land Textures
|
||||
appendStage (new WriteLandCollectionStage (mDocument, mState));
|
||||
|
||||
// close file and clean up
|
||||
appendStage (new CloseSaveStage (mState));
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "savingstages.hpp"
|
||||
|
||||
#include <fstream>
|
||||
|
@ -53,18 +52,16 @@ void CSMDoc::WriteHeaderStage::perform (int stage, Messages& messages)
|
|||
|
||||
mState.getWriter().clearMaster();
|
||||
|
||||
mState.getWriter().setFormat (0);
|
||||
|
||||
if (mSimple)
|
||||
{
|
||||
mState.getWriter().setAuthor ("");
|
||||
mState.getWriter().setDescription ("");
|
||||
mState.getWriter().setRecordCount (0);
|
||||
mState.getWriter().setFormat (ESM::Header::CurrentFormat);
|
||||
}
|
||||
else
|
||||
{
|
||||
mState.getWriter().setAuthor (mDocument.getData().getAuthor());
|
||||
mState.getWriter().setDescription (mDocument.getData().getDescription());
|
||||
mDocument.getData().getMetaData().save (mState.getWriter());
|
||||
mState.getWriter().setRecordCount (
|
||||
mDocument.getData().count (CSMWorld::RecordBase::State_Modified) +
|
||||
mDocument.getData().count (CSMWorld::RecordBase::State_ModifiedOnly) +
|
||||
|
@ -137,23 +134,34 @@ void CSMDoc::WriteDialogueCollectionStage::perform (int stage, Messages& message
|
|||
state==CSMWorld::RecordBase::State_ModifiedOnly ||
|
||||
infoModified)
|
||||
{
|
||||
mState.getWriter().startRecord (topic.mModified.sRecordId);
|
||||
mState.getWriter().writeHNCString ("NAME", topic.mModified.mId);
|
||||
topic.mModified.save (mState.getWriter());
|
||||
mState.getWriter().endRecord (topic.mModified.sRecordId);
|
||||
if (infoModified && state != CSMWorld::RecordBase::State_Modified
|
||||
&& state != CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
{
|
||||
mState.getWriter().startRecord (topic.mBase.sRecordId);
|
||||
mState.getWriter().writeHNCString ("NAME", topic.mBase.mId);
|
||||
topic.mBase.save (mState.getWriter());
|
||||
mState.getWriter().endRecord (topic.mBase.sRecordId);
|
||||
}
|
||||
else
|
||||
{
|
||||
mState.getWriter().startRecord (topic.mModified.sRecordId);
|
||||
mState.getWriter().writeHNCString ("NAME", topic.mModified.mId);
|
||||
topic.mModified.save (mState.getWriter());
|
||||
mState.getWriter().endRecord (topic.mModified.sRecordId);
|
||||
}
|
||||
|
||||
// write modified selected info records
|
||||
for (CSMWorld::InfoCollection::RecordConstIterator iter (range.first); iter!=range.second;
|
||||
++iter)
|
||||
{
|
||||
CSMWorld::RecordBase::State state = iter->mState;
|
||||
CSMWorld::RecordBase::State infoState = iter->mState;
|
||||
|
||||
if (state==CSMWorld::RecordBase::State_Deleted)
|
||||
if (infoState==CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
/// \todo wrote record with delete flag
|
||||
}
|
||||
else if (state==CSMWorld::RecordBase::State_Modified ||
|
||||
state==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
else if (infoState==CSMWorld::RecordBase::State_Modified ||
|
||||
infoState==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
{
|
||||
ESM::DialInfo info = iter->get();
|
||||
info.mId = info.mId.substr (info.mId.find_last_of ('#')+1);
|
||||
|
@ -418,15 +426,16 @@ void CSMDoc::WriteLandCollectionStage::perform (int stage, Messages& messages)
|
|||
if (land.mState==CSMWorld::RecordBase::State_Modified ||
|
||||
land.mState==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||
{
|
||||
CSMWorld::Land record = land.get();
|
||||
const CSMWorld::Land& record = land.get();
|
||||
|
||||
mState.getWriter().startRecord (record.mLand->sRecordId);
|
||||
mState.getWriter().startRecord (record.sRecordId);
|
||||
|
||||
record.mLand->save (mState.getWriter());
|
||||
if(record.mLand->mLandData)
|
||||
record.mLand->mLandData->save (mState.getWriter());
|
||||
record.save (mState.getWriter());
|
||||
|
||||
mState.getWriter().endRecord (record.mLand->sRecordId);
|
||||
if (const ESM::Land::LandData *data = record.getLandData (record.mDataTypes))
|
||||
data->save (mState.getWriter());
|
||||
|
||||
mState.getWriter().endRecord (record.sRecordId);
|
||||
}
|
||||
else if (land.mState==CSMWorld::RecordBase::State_Deleted)
|
||||
{
|
||||
|
@ -457,6 +466,8 @@ void CSMDoc::WriteLandTextureCollectionStage::perform (int stage, Messages& mess
|
|||
|
||||
mState.getWriter().startRecord (record.sRecordId);
|
||||
|
||||
mState.getWriter().writeHNString("NAME", record.mId);
|
||||
|
||||
record.save (mState.getWriter());
|
||||
|
||||
mState.getWriter().endRecord (record.sRecordId);
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "savingstate.hpp"
|
||||
|
||||
#include "operation.hpp"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
#include "stage.hpp"
|
||||
|
||||
CSMDoc::Stage::~Stage() {}
|
||||
|
||||
void CSMDoc::Stage::updateUserSetting (const QString& name, const QStringList& value) {}
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#include "messages.hpp"
|
||||
|
||||
class QString;
|
||||
|
||||
namespace CSMDoc
|
||||
{
|
||||
class Stage
|
||||
|
@ -21,6 +23,9 @@ namespace CSMDoc
|
|||
|
||||
virtual void perform (int stage, Messages& messages) = 0;
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
|
||||
/// Default-implementation: ignore
|
||||
virtual void updateUserSetting (const QString& name, const QStringList& value);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace CSMDoc
|
|||
|
||||
State_Saving = 16,
|
||||
State_Verifying = 32,
|
||||
State_Compiling = 64, // not implemented yet
|
||||
State_Merging = 64,
|
||||
State_Searching = 128,
|
||||
State_Loading = 256 // pseudo-state; can not be encountered in a loaded document
|
||||
};
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "andnode.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "booleannode.hpp"
|
||||
|
||||
CSMFilter::BooleanNode::BooleanNode (bool true_) : mTrue (true_) {}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "leafnode.hpp"
|
||||
|
||||
std::vector<int> CSMFilter::LeafNode::getReferencedColumns() const
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "narynode.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "node.hpp"
|
||||
|
||||
CSMFilter::Node::Node() {}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "notnode.hpp"
|
||||
|
||||
CSMFilter::NotNode::NotNode (boost::shared_ptr<Node> child) : UnaryNode (child, "not") {}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "ornode.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "parser.hpp"
|
||||
|
||||
#include <cctype>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "textnode.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "unarynode.hpp"
|
||||
|
||||
CSMFilter::UnaryNode::UnaryNode (boost::shared_ptr<Node> child, const std::string& name)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "valuenode.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
|
|
@ -161,6 +161,16 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
|||
grow->setToolTip ("When \"Grow then Scroll\" option is selected, the window size grows to"
|
||||
" the width of the virtual desktop. \nIf this option is selected the the window growth"
|
||||
"is limited to the current screen.");
|
||||
|
||||
Setting *saveState = createSetting (Type_CheckBox, "save-state", "Save window size and position");
|
||||
saveState->setDefaultValue ("true");
|
||||
saveState->setToolTip ("Remember window size and position between editing sessions.");
|
||||
|
||||
Setting *saveX = createSetting (Type_CheckBox, "x-save-state-workaround", "X windows workaround");
|
||||
saveX->setDefaultValue ("false");
|
||||
saveX->setToolTip ("Some X window managers don't remember the windows state before being"
|
||||
" maximized. In such environments exiting while maximized will correctly start in a maximized"
|
||||
" window, but restoring back to the normal size won't work. Try this workaround.");
|
||||
}
|
||||
|
||||
declareSection ("records", "Records");
|
||||
|
@ -179,7 +189,7 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
|||
ritd->setDeclaredValues (values);
|
||||
}
|
||||
|
||||
declareSection ("table-input", "Table Input");
|
||||
declareSection ("table-input", "ID Tables");
|
||||
{
|
||||
QString inPlaceEdit ("Edit in Place");
|
||||
QString editRecord ("Edit Record");
|
||||
|
@ -232,6 +242,62 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
|||
"Jump to the added or cloned record.");
|
||||
jumpToAdded->setDefaultValue (defaultValue);
|
||||
jumpToAdded->setDeclaredValues (jumpValues);
|
||||
|
||||
Setting *extendedConfig = createSetting (Type_CheckBox, "extended-config",
|
||||
"Manually specify affected record types for an extended delete/revert");
|
||||
extendedConfig->setDefaultValue("false");
|
||||
extendedConfig->setToolTip("Delete and revert commands have an extended form that also affects "
|
||||
"associated records.\n\n"
|
||||
"If this option is enabled, types of affected records are selected "
|
||||
"manually before a command execution.\nOtherwise, all associated "
|
||||
"records are deleted/reverted immediately.");
|
||||
}
|
||||
|
||||
declareSection ("dialogues", "ID Dialogues");
|
||||
{
|
||||
Setting *toolbar = createSetting (Type_CheckBox, "toolbar", "Show toolbar");
|
||||
toolbar->setDefaultValue ("true");
|
||||
}
|
||||
|
||||
declareSection ("report-input", "Reports");
|
||||
{
|
||||
QString none ("None");
|
||||
QString edit ("Edit");
|
||||
QString remove ("Remove");
|
||||
QString editAndRemove ("Edit And Remove");
|
||||
|
||||
QStringList values;
|
||||
values << none << edit << remove << editAndRemove;
|
||||
|
||||
QString toolTip = "<ul>"
|
||||
"<li>None</li>"
|
||||
"<li>Edit: Open a table or dialogue suitable for addressing the listed report</li>"
|
||||
"<li>Remove: Remove the report from the report table</li>"
|
||||
"<li>Edit and Remove: Open a table or dialogue suitable for addressing the listed report, then remove the report from the report table</li>"
|
||||
"</ul>";
|
||||
|
||||
Setting *doubleClick = createSetting (Type_ComboBox, "double", "Double Click");
|
||||
doubleClick->setDeclaredValues (values);
|
||||
doubleClick->setDefaultValue (edit);
|
||||
doubleClick->setToolTip ("Action on double click in report table:<p>" + toolTip);
|
||||
|
||||
Setting *shiftDoubleClick = createSetting (Type_ComboBox, "double-s",
|
||||
"Shift Double Click");
|
||||
shiftDoubleClick->setDeclaredValues (values);
|
||||
shiftDoubleClick->setDefaultValue (remove);
|
||||
shiftDoubleClick->setToolTip ("Action on shift double click in report table:<p>" + toolTip);
|
||||
|
||||
Setting *ctrlDoubleClick = createSetting (Type_ComboBox, "double-c",
|
||||
"Control Double Click");
|
||||
ctrlDoubleClick->setDeclaredValues (values);
|
||||
ctrlDoubleClick->setDefaultValue (editAndRemove);
|
||||
ctrlDoubleClick->setToolTip ("Action on control double click in report table:<p>" + toolTip);
|
||||
|
||||
Setting *shiftCtrlDoubleClick = createSetting (Type_ComboBox, "double-sc",
|
||||
"Shift Control Double Click");
|
||||
shiftCtrlDoubleClick->setDeclaredValues (values);
|
||||
shiftCtrlDoubleClick->setDefaultValue (none);
|
||||
shiftCtrlDoubleClick->setToolTip ("Action on shift control double click in report table:<p>" + toolTip);
|
||||
}
|
||||
|
||||
declareSection ("search", "Search & Replace");
|
||||
|
@ -252,16 +318,97 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
|||
autoDelete->setDefaultValue ("true");
|
||||
}
|
||||
|
||||
declareSection ("script-editor", "Script Editor");
|
||||
declareSection ("script-editor", "Scripts");
|
||||
{
|
||||
Setting *lineNum = createSetting (Type_CheckBox, "show-linenum", "Show Line Numbers");
|
||||
lineNum->setDefaultValue ("true");
|
||||
lineNum->setToolTip ("Show line numbers to the left of the script editor window."
|
||||
"The current row and column numbers of the text cursor are shown at the bottom.");
|
||||
" The current row and column numbers of the text cursor are shown at the bottom.");
|
||||
|
||||
Setting *monoFont = createSetting (Type_CheckBox, "mono-font", "Use monospace font");
|
||||
monoFont->setDefaultValue ("true");
|
||||
monoFont->setToolTip ("Whether to use monospaced fonts on script edit subview.");
|
||||
|
||||
QString tooltip =
|
||||
"\n#RGB (each of R, G, and B is a single hex digit)"
|
||||
"\n#RRGGBB"
|
||||
"\n#RRRGGGBBB"
|
||||
"\n#RRRRGGGGBBBB"
|
||||
"\nA name from the list of colors defined in the list of SVG color keyword names."
|
||||
"\nX11 color names may also work.";
|
||||
|
||||
QString modeNormal ("Normal");
|
||||
|
||||
QStringList modes;
|
||||
modes << "Ignore" << modeNormal << "Strict";
|
||||
|
||||
Setting *warnings = createSetting (Type_ComboBox, "warnings",
|
||||
"Warning Mode");
|
||||
warnings->setDeclaredValues (modes);
|
||||
warnings->setDefaultValue (modeNormal);
|
||||
warnings->setToolTip ("<ul>How to handle warning messages during compilation:<p>"
|
||||
"<li>Ignore: Do not report warning</li>"
|
||||
"<li>Normal: Report warning as a warning</li>"
|
||||
"<li>Strict: Promote warning to an error</li>"
|
||||
"</ul>");
|
||||
|
||||
Setting *toolbar = createSetting (Type_CheckBox, "toolbar", "Show toolbar");
|
||||
toolbar->setDefaultValue ("true");
|
||||
|
||||
Setting *delay = createSetting (Type_SpinBox, "compile-delay",
|
||||
"Delay between updating of source errors");
|
||||
delay->setDefaultValue (100);
|
||||
delay->setRange (0, 10000);
|
||||
delay->setToolTip ("Delay in milliseconds");
|
||||
|
||||
Setting *formatInt = createSetting (Type_LineEdit, "colour-int", "Highlight Colour: Int");
|
||||
formatInt->setDefaultValues (QStringList() << "Dark magenta");
|
||||
formatInt->setToolTip ("(Default: Green) Use one of the following formats:" + tooltip);
|
||||
|
||||
Setting *formatFloat = createSetting (Type_LineEdit, "colour-float", "Highlight Colour: Float");
|
||||
formatFloat->setDefaultValues (QStringList() << "Magenta");
|
||||
formatFloat->setToolTip ("(Default: Magenta) Use one of the following formats:" + tooltip);
|
||||
|
||||
Setting *formatName = createSetting (Type_LineEdit, "colour-name", "Highlight Colour: Name");
|
||||
formatName->setDefaultValues (QStringList() << "Gray");
|
||||
formatName->setToolTip ("(Default: Gray) Use one of the following formats:" + tooltip);
|
||||
|
||||
Setting *formatKeyword = createSetting (Type_LineEdit, "colour-keyword", "Highlight Colour: Keyword");
|
||||
formatKeyword->setDefaultValues (QStringList() << "Red");
|
||||
formatKeyword->setToolTip ("(Default: Red) Use one of the following formats:" + tooltip);
|
||||
|
||||
Setting *formatSpecial = createSetting (Type_LineEdit, "colour-special", "Highlight Colour: Special");
|
||||
formatSpecial->setDefaultValues (QStringList() << "Dark yellow");
|
||||
formatSpecial->setToolTip ("(Default: Dark yellow) Use one of the following formats:" + tooltip);
|
||||
|
||||
Setting *formatComment = createSetting (Type_LineEdit, "colour-comment", "Highlight Colour: Comment");
|
||||
formatComment->setDefaultValues (QStringList() << "Green");
|
||||
formatComment->setToolTip ("(Default: Green) Use one of the following formats:" + tooltip);
|
||||
|
||||
Setting *formatId = createSetting (Type_LineEdit, "colour-id", "Highlight Colour: Id");
|
||||
formatId->setDefaultValues (QStringList() << "Blue");
|
||||
formatId->setToolTip ("(Default: Blue) Use one of the following formats:" + tooltip);
|
||||
}
|
||||
|
||||
declareSection ("filter", "Global Filter");
|
||||
{
|
||||
Setting *projAdded = createSetting (Type_CheckBox, "project-added", "Project::added initial value");
|
||||
projAdded->setDefaultValue ("false");
|
||||
projAdded->setToolTip ("Show records added by the project when opening a table."
|
||||
" Other records are filterd out.");
|
||||
|
||||
Setting *projModified = createSetting (Type_CheckBox, "project-modified", "Project::modified initial value");
|
||||
projModified->setDefaultValue ("false");
|
||||
projModified->setToolTip ("Show records modified by the project when opening a table."
|
||||
" Other records are filterd out.");
|
||||
}
|
||||
|
||||
declareSection ("general-input", "General Input");
|
||||
{
|
||||
Setting *cycle = createSetting (Type_CheckBox, "cycle", "Cyclic next/previous");
|
||||
cycle->setDefaultValue ("false");
|
||||
cycle->setToolTip ("When using next/previous functions at the last/first item of a "
|
||||
"list go to the first/last item");
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -484,6 +631,21 @@ QString CSMSettings::UserSettings::setting(const QString &viewKey, const QString
|
|||
return QString();
|
||||
}
|
||||
|
||||
QVariant CSMSettings::UserSettings::value(const QString &viewKey, const QVariant &value)
|
||||
{
|
||||
if(value != QVariant())
|
||||
{
|
||||
mSettingDefinitions->setValue (viewKey, value);
|
||||
return value;
|
||||
}
|
||||
else if(mSettingDefinitions->contains(viewKey))
|
||||
{
|
||||
return mSettingDefinitions->value (viewKey);
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool CSMSettings::UserSettings::hasSettingDefinitions (const QString &viewKey) const
|
||||
{
|
||||
return (mSettingDefinitions->contains (viewKey));
|
||||
|
|
|
@ -82,6 +82,8 @@ namespace CSMSettings {
|
|||
|
||||
QString setting(const QString &viewKey, const QString &value = QString());
|
||||
|
||||
QVariant value(const QString &viewKey, const QVariant &value = QVariant());
|
||||
|
||||
private:
|
||||
|
||||
void buildSettingModelDefaults();
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "birthsigncheck.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "classcheck.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "factioncheck.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
|
133
apps/opencs/model/tools/magiceffectcheck.cpp
Normal file
133
apps/opencs/model/tools/magiceffectcheck.cpp
Normal file
|
@ -0,0 +1,133 @@
|
|||
#include "magiceffectcheck.hpp"
|
||||
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
|
||||
#include "../world/resources.hpp"
|
||||
#include "../world/data.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
void addMessageIfNotEmpty(CSMDoc::Messages &messages, const CSMWorld::UniversalId &id, const std::string text)
|
||||
{
|
||||
if (!text.empty())
|
||||
{
|
||||
messages.push_back(std::make_pair(id, text));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool CSMTools::MagicEffectCheckStage::isTextureExists(const std::string &texture, bool isIcon) const
|
||||
{
|
||||
const CSMWorld::Resources &textures = isIcon ? mIcons : mTextures;
|
||||
bool exists = false;
|
||||
|
||||
if (textures.searchId(texture) != -1)
|
||||
{
|
||||
exists = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string ddsTexture = texture;
|
||||
if (Misc::ResourceHelpers::changeExtensionToDds(ddsTexture) && textures.searchId(ddsTexture) != -1)
|
||||
{
|
||||
exists = true;
|
||||
}
|
||||
}
|
||||
|
||||
return exists;
|
||||
}
|
||||
|
||||
std::string CSMTools::MagicEffectCheckStage::checkReferenceable(const std::string &id,
|
||||
const CSMWorld::UniversalId &type,
|
||||
const std::string &column) const
|
||||
{
|
||||
std::string error;
|
||||
if (!id.empty())
|
||||
{
|
||||
CSMWorld::RefIdData::LocalIndex index = mReferenceables.getDataSet().searchId(id);
|
||||
if (index.first == -1)
|
||||
{
|
||||
error = "No such " + column + " '" + id + "'";
|
||||
}
|
||||
else if (index.second != type.getType())
|
||||
{
|
||||
error = column + " is not of type " + type.getTypeName();
|
||||
}
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
std::string CSMTools::MagicEffectCheckStage::checkSound(const std::string &id, const std::string &column) const
|
||||
{
|
||||
std::string error;
|
||||
if (!id.empty() && mSounds.searchId(id) == -1)
|
||||
{
|
||||
error = "No such " + column + " '" + id + "'";
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
CSMTools::MagicEffectCheckStage::MagicEffectCheckStage(const CSMWorld::IdCollection<ESM::MagicEffect> &effects,
|
||||
const CSMWorld::IdCollection<ESM::Sound> &sounds,
|
||||
const CSMWorld::RefIdCollection &referenceables,
|
||||
const CSMWorld::Resources &icons,
|
||||
const CSMWorld::Resources &textures)
|
||||
: mMagicEffects(effects),
|
||||
mSounds(sounds),
|
||||
mReferenceables(referenceables),
|
||||
mIcons(icons),
|
||||
mTextures(textures)
|
||||
{}
|
||||
|
||||
int CSMTools::MagicEffectCheckStage::setup()
|
||||
{
|
||||
return mMagicEffects.getSize();
|
||||
}
|
||||
|
||||
void CSMTools::MagicEffectCheckStage::perform(int stage, CSMDoc::Messages &messages)
|
||||
{
|
||||
ESM::MagicEffect effect = mMagicEffects.getRecord(stage).get();
|
||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_MagicEffect, effect.mId);
|
||||
|
||||
if (effect.mData.mBaseCost < 0.0f)
|
||||
{
|
||||
messages.push_back(std::make_pair(id, "Base Cost is negative"));
|
||||
}
|
||||
|
||||
if (effect.mIcon.empty())
|
||||
{
|
||||
messages.push_back(std::make_pair(id, "Icon is not specified"));
|
||||
}
|
||||
else if (!isTextureExists(effect.mIcon, true))
|
||||
{
|
||||
messages.push_back(std::make_pair(id, "No such Icon '" + effect.mIcon + "'"));
|
||||
}
|
||||
|
||||
if (!effect.mParticle.empty() && !isTextureExists(effect.mParticle, false))
|
||||
{
|
||||
messages.push_back(std::make_pair(id, "No such Particle '" + effect.mParticle + "'"));
|
||||
}
|
||||
|
||||
addMessageIfNotEmpty(messages,
|
||||
id,
|
||||
checkReferenceable(effect.mCasting, CSMWorld::UniversalId::Type_Static, "Casting Object"));
|
||||
addMessageIfNotEmpty(messages,
|
||||
id,
|
||||
checkReferenceable(effect.mHit, CSMWorld::UniversalId::Type_Static, "Hit Object"));
|
||||
addMessageIfNotEmpty(messages,
|
||||
id,
|
||||
checkReferenceable(effect.mArea, CSMWorld::UniversalId::Type_Static, "Area Object"));
|
||||
addMessageIfNotEmpty(messages,
|
||||
id,
|
||||
checkReferenceable(effect.mBolt, CSMWorld::UniversalId::Type_Weapon, "Bolt Object"));
|
||||
|
||||
addMessageIfNotEmpty(messages, id, checkSound(effect.mCastSound, "Casting Sound"));
|
||||
addMessageIfNotEmpty(messages, id, checkSound(effect.mHitSound, "Hit Sound"));
|
||||
addMessageIfNotEmpty(messages, id, checkSound(effect.mAreaSound, "Area Sound"));
|
||||
addMessageIfNotEmpty(messages, id, checkSound(effect.mBoltSound, "Bolt Sound"));
|
||||
|
||||
if (effect.mDescription.empty())
|
||||
{
|
||||
messages.push_back(std::make_pair(id, "Description is empty"));
|
||||
}
|
||||
}
|
50
apps/opencs/model/tools/magiceffectcheck.hpp
Normal file
50
apps/opencs/model/tools/magiceffectcheck.hpp
Normal file
|
@ -0,0 +1,50 @@
|
|||
#ifndef CSM_TOOLS_MAGICEFFECTCHECK_HPP
|
||||
#define CSM_TOOLS_MAGICEFFECTCHECK_HPP
|
||||
|
||||
#include <components/esm/loadmgef.hpp>
|
||||
#include <components/esm/loadsoun.hpp>
|
||||
|
||||
#include "../world/idcollection.hpp"
|
||||
#include "../world/refidcollection.hpp"
|
||||
|
||||
#include "../doc/stage.hpp"
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
class Resources;
|
||||
}
|
||||
|
||||
namespace CSMTools
|
||||
{
|
||||
/// \brief VerifyStage: make sure that magic effect records are internally consistent
|
||||
class MagicEffectCheckStage : public CSMDoc::Stage
|
||||
{
|
||||
const CSMWorld::IdCollection<ESM::MagicEffect> &mMagicEffects;
|
||||
const CSMWorld::IdCollection<ESM::Sound> &mSounds;
|
||||
const CSMWorld::RefIdCollection &mReferenceables;
|
||||
const CSMWorld::Resources &mIcons;
|
||||
const CSMWorld::Resources &mTextures;
|
||||
|
||||
private:
|
||||
bool isTextureExists(const std::string &texture, bool isIcon) const;
|
||||
|
||||
std::string checkReferenceable(const std::string &id,
|
||||
const CSMWorld::UniversalId &type,
|
||||
const std::string &column) const;
|
||||
std::string checkSound(const std::string &id, const std::string &column) const;
|
||||
|
||||
public:
|
||||
MagicEffectCheckStage(const CSMWorld::IdCollection<ESM::MagicEffect> &effects,
|
||||
const CSMWorld::IdCollection<ESM::Sound> &sounds,
|
||||
const CSMWorld::RefIdCollection &referenceables,
|
||||
const CSMWorld::Resources &icons,
|
||||
const CSMWorld::Resources &textures);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
virtual void perform (int stage, CSMDoc::Messages &messages);
|
||||
///< Messages resulting from this tage will be appended to \a messages.
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "mandatoryid.hpp"
|
||||
|
||||
#include "../world/collectionbase.hpp"
|
||||
|
|
59
apps/opencs/model/tools/mergeoperation.cpp
Normal file
59
apps/opencs/model/tools/mergeoperation.cpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
|
||||
#include "mergeoperation.hpp"
|
||||
|
||||
#include "../doc/state.hpp"
|
||||
#include "../doc/document.hpp"
|
||||
|
||||
#include "mergestages.hpp"
|
||||
|
||||
CSMTools::MergeOperation::MergeOperation (CSMDoc::Document& document, ToUTF8::FromType encoding)
|
||||
: CSMDoc::Operation (CSMDoc::State_Merging, true), mState (document)
|
||||
{
|
||||
appendStage (new StartMergeStage (mState));
|
||||
|
||||
appendStage (new MergeIdCollectionStage<ESM::Global> (mState, &CSMWorld::Data::getGlobals));
|
||||
appendStage (new MergeIdCollectionStage<ESM::GameSetting> (mState, &CSMWorld::Data::getGmsts));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Skill> (mState, &CSMWorld::Data::getSkills));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Class> (mState, &CSMWorld::Data::getClasses));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Faction> (mState, &CSMWorld::Data::getFactions));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Race> (mState, &CSMWorld::Data::getRaces));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Sound> (mState, &CSMWorld::Data::getSounds));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Script> (mState, &CSMWorld::Data::getScripts));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Region> (mState, &CSMWorld::Data::getRegions));
|
||||
appendStage (new MergeIdCollectionStage<ESM::BirthSign> (mState, &CSMWorld::Data::getBirthsigns));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Spell> (mState, &CSMWorld::Data::getSpells));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Dialogue> (mState, &CSMWorld::Data::getTopics));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Dialogue> (mState, &CSMWorld::Data::getJournals));
|
||||
appendStage (new MergeIdCollectionStage<CSMWorld::Cell> (mState, &CSMWorld::Data::getCells));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Filter> (mState, &CSMWorld::Data::getFilters));
|
||||
appendStage (new MergeIdCollectionStage<ESM::Enchantment> (mState, &CSMWorld::Data::getEnchantments));
|
||||
appendStage (new MergeIdCollectionStage<ESM::BodyPart> (mState, &CSMWorld::Data::getBodyParts));
|
||||
appendStage (new MergeIdCollectionStage<ESM::DebugProfile> (mState, &CSMWorld::Data::getDebugProfiles));
|
||||
appendStage (new MergeIdCollectionStage<ESM::SoundGenerator> (mState, &CSMWorld::Data::getSoundGens));
|
||||
appendStage (new MergeIdCollectionStage<ESM::MagicEffect> (mState, &CSMWorld::Data::getMagicEffects));
|
||||
appendStage (new MergeIdCollectionStage<ESM::StartScript> (mState, &CSMWorld::Data::getStartScripts));
|
||||
appendStage (new MergeIdCollectionStage<CSMWorld::Pathgrid, CSMWorld::SubCellCollection<CSMWorld::Pathgrid> > (mState, &CSMWorld::Data::getPathgrids));
|
||||
appendStage (new MergeIdCollectionStage<CSMWorld::Info, CSMWorld::InfoCollection> (mState, &CSMWorld::Data::getTopicInfos));
|
||||
appendStage (new MergeIdCollectionStage<CSMWorld::Info, CSMWorld::InfoCollection> (mState, &CSMWorld::Data::getJournalInfos));
|
||||
appendStage (new MergeRefIdsStage (mState));
|
||||
appendStage (new MergeReferencesStage (mState));
|
||||
appendStage (new MergeReferencesStage (mState));
|
||||
appendStage (new ListLandTexturesMergeStage (mState));
|
||||
appendStage (new MergeLandTexturesStage (mState));
|
||||
appendStage (new MergeLandStage (mState));
|
||||
|
||||
appendStage (new FinishMergedDocumentStage (mState, encoding));
|
||||
}
|
||||
|
||||
void CSMTools::MergeOperation::setTarget (std::auto_ptr<CSMDoc::Document> document)
|
||||
{
|
||||
mState.mTarget = document;
|
||||
}
|
||||
|
||||
void CSMTools::MergeOperation::operationDone()
|
||||
{
|
||||
CSMDoc::Operation::operationDone();
|
||||
|
||||
if (mState.mCompleted)
|
||||
emit mergeDone (mState.mTarget.release());
|
||||
}
|
45
apps/opencs/model/tools/mergeoperation.hpp
Normal file
45
apps/opencs/model/tools/mergeoperation.hpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
#ifndef CSM_TOOLS_MERGEOPERATION_H
|
||||
#define CSM_TOOLS_MERGEOPERATION_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
|
||||
#include "../doc/operation.hpp"
|
||||
|
||||
#include "mergestate.hpp"
|
||||
|
||||
namespace CSMDoc
|
||||
{
|
||||
class Document;
|
||||
}
|
||||
|
||||
namespace CSMTools
|
||||
{
|
||||
class MergeOperation : public CSMDoc::Operation
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
MergeState mState;
|
||||
|
||||
public:
|
||||
|
||||
MergeOperation (CSMDoc::Document& document, ToUTF8::FromType encoding);
|
||||
|
||||
/// \attention Do not call this function while a merge is running.
|
||||
void setTarget (std::auto_ptr<CSMDoc::Document> document);
|
||||
|
||||
protected slots:
|
||||
|
||||
virtual void operationDone();
|
||||
|
||||
signals:
|
||||
|
||||
/// \attention When this signal is emitted, *this hands over the ownership of the
|
||||
/// document. This signal must be handled to avoid a leak.
|
||||
void mergeDone (CSMDoc::Document *document);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
258
apps/opencs/model/tools/mergestages.cpp
Normal file
258
apps/opencs/model/tools/mergestages.cpp
Normal file
|
@ -0,0 +1,258 @@
|
|||
|
||||
#include "mergestages.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include "mergestate.hpp"
|
||||
|
||||
#include "../doc/document.hpp"
|
||||
#include "../world/data.hpp"
|
||||
|
||||
|
||||
CSMTools::StartMergeStage::StartMergeStage (MergeState& state)
|
||||
: mState (state)
|
||||
{}
|
||||
|
||||
int CSMTools::StartMergeStage::setup()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CSMTools::StartMergeStage::perform (int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
mState.mCompleted = false;
|
||||
mState.mTextureIndices.clear();
|
||||
}
|
||||
|
||||
|
||||
CSMTools::FinishMergedDocumentStage::FinishMergedDocumentStage (MergeState& state, ToUTF8::FromType encoding)
|
||||
: mState (state), mEncoder (encoding)
|
||||
{}
|
||||
|
||||
int CSMTools::FinishMergedDocumentStage::setup()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void CSMTools::FinishMergedDocumentStage::perform (int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
// We know that the content file list contains at least two entries and that the first one
|
||||
// does exist on disc (otherwise it would have been impossible to initiate a merge on that
|
||||
// document).
|
||||
boost::filesystem::path path = mState.mSource.getContentFiles()[0];
|
||||
|
||||
ESM::ESMReader reader;
|
||||
reader.setEncoder (&mEncoder);
|
||||
reader.open (path.string());
|
||||
|
||||
CSMWorld::MetaData source;
|
||||
source.mId = "sys::meta";
|
||||
source.load (reader);
|
||||
|
||||
CSMWorld::MetaData target = mState.mTarget->getData().getMetaData();
|
||||
|
||||
target.mAuthor = source.mAuthor;
|
||||
target.mDescription = source.mDescription;
|
||||
|
||||
mState.mTarget->getData().setMetaData (target);
|
||||
|
||||
mState.mCompleted = true;
|
||||
}
|
||||
|
||||
|
||||
CSMTools::MergeRefIdsStage::MergeRefIdsStage (MergeState& state) : mState (state) {}
|
||||
|
||||
int CSMTools::MergeRefIdsStage::setup()
|
||||
{
|
||||
return mState.mSource.getData().getReferenceables().getSize();
|
||||
}
|
||||
|
||||
void CSMTools::MergeRefIdsStage::perform (int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
mState.mSource.getData().getReferenceables().copyTo (
|
||||
stage, mState.mTarget->getData().getReferenceables());
|
||||
}
|
||||
|
||||
|
||||
CSMTools::MergeReferencesStage::MergeReferencesStage (MergeState& state)
|
||||
: mState (state)
|
||||
{}
|
||||
|
||||
int CSMTools::MergeReferencesStage::setup()
|
||||
{
|
||||
mIndex.clear();
|
||||
return mState.mSource.getData().getReferences().getSize();
|
||||
}
|
||||
|
||||
void CSMTools::MergeReferencesStage::perform (int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
const CSMWorld::Record<CSMWorld::CellRef>& record =
|
||||
mState.mSource.getData().getReferences().getRecord (stage);
|
||||
|
||||
if (!record.isDeleted())
|
||||
{
|
||||
CSMWorld::CellRef ref = record.get();
|
||||
|
||||
ref.mOriginalCell = ref.mCell;
|
||||
|
||||
ref.mRefNum.mIndex = mIndex[Misc::StringUtils::lowerCase (ref.mCell)]++;
|
||||
ref.mRefNum.mContentFile = 0;
|
||||
|
||||
CSMWorld::Record<CSMWorld::CellRef> newRecord (
|
||||
CSMWorld::RecordBase::State_ModifiedOnly, 0, &ref);
|
||||
|
||||
mState.mTarget->getData().getReferences().appendRecord (newRecord);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CSMTools::ListLandTexturesMergeStage::ListLandTexturesMergeStage (MergeState& state)
|
||||
: mState (state)
|
||||
{}
|
||||
|
||||
int CSMTools::ListLandTexturesMergeStage::setup()
|
||||
{
|
||||
return mState.mSource.getData().getLand().getSize();
|
||||
}
|
||||
|
||||
void CSMTools::ListLandTexturesMergeStage::perform (int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
const CSMWorld::Record<CSMWorld::Land>& record =
|
||||
mState.mSource.getData().getLand().getRecord (stage);
|
||||
|
||||
if (!record.isDeleted())
|
||||
{
|
||||
const CSMWorld::Land& land = record.get();
|
||||
|
||||
// make sure record is loaded
|
||||
land.loadData (ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML |
|
||||
ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM);
|
||||
|
||||
if (const ESM::Land::LandData *data = land.getLandData (ESM::Land::DATA_VTEX))
|
||||
{
|
||||
// list texture indices
|
||||
std::pair<uint16_t, int> key;
|
||||
key.second = land.mPlugin;
|
||||
|
||||
for (int i=0; i<ESM::Land::LAND_NUM_TEXTURES; ++i)
|
||||
{
|
||||
key.first = data->mTextures[i];
|
||||
|
||||
mState.mTextureIndices[key] = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CSMTools::MergeLandTexturesStage::MergeLandTexturesStage (MergeState& state)
|
||||
: mState (state), mNext (mState.mTextureIndices.end())
|
||||
{}
|
||||
|
||||
int CSMTools::MergeLandTexturesStage::setup()
|
||||
{
|
||||
// Should use the size of mState.mTextureIndices instead, but that is not available at this
|
||||
// point. Unless there are any errors in the land and land texture records this will not
|
||||
// make a difference.
|
||||
return mState.mSource.getData().getLandTextures().getSize();
|
||||
}
|
||||
|
||||
void CSMTools::MergeLandTexturesStage::perform (int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
if (stage==0)
|
||||
mNext = mState.mTextureIndices.begin();
|
||||
|
||||
bool found = false;
|
||||
|
||||
do
|
||||
{
|
||||
if (mNext==mState.mTextureIndices.end())
|
||||
return;
|
||||
|
||||
mNext->second = stage+1;
|
||||
|
||||
std::ostringstream stream;
|
||||
stream << mNext->first.first-1 << "_" << mNext->first.second;
|
||||
|
||||
int index = mState.mSource.getData().getLandTextures().searchId (stream.str());
|
||||
|
||||
if (index!=-1)
|
||||
{
|
||||
CSMWorld::LandTexture texture =
|
||||
mState.mSource.getData().getLandTextures().getRecord (index).get();
|
||||
|
||||
std::ostringstream stream;
|
||||
stream << mNext->second-1 << "_0";
|
||||
|
||||
texture.mIndex = mNext->second-1;
|
||||
texture.mId = stream.str();
|
||||
|
||||
CSMWorld::Record<CSMWorld::LandTexture> newRecord (
|
||||
CSMWorld::RecordBase::State_ModifiedOnly, 0, &texture);
|
||||
|
||||
mState.mTarget->getData().getLandTextures().appendRecord (newRecord);
|
||||
|
||||
found = true;
|
||||
}
|
||||
|
||||
++mNext;
|
||||
}
|
||||
while (!found);
|
||||
}
|
||||
|
||||
|
||||
CSMTools::MergeLandStage::MergeLandStage (MergeState& state) : mState (state) {}
|
||||
|
||||
int CSMTools::MergeLandStage::setup()
|
||||
{
|
||||
return mState.mSource.getData().getLand().getSize();
|
||||
}
|
||||
|
||||
void CSMTools::MergeLandStage::perform (int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
const CSMWorld::Record<CSMWorld::Land>& record =
|
||||
mState.mSource.getData().getLand().getRecord (stage);
|
||||
|
||||
if (!record.isDeleted())
|
||||
{
|
||||
const CSMWorld::Land& land = record.get();
|
||||
|
||||
land.loadData (ESM::Land::DATA_VCLR | ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML |
|
||||
ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM);
|
||||
|
||||
CSMWorld::Land newLand (land);
|
||||
|
||||
newLand.mEsm = 0; // avoid potential dangling pointer (ESMReader isn't needed anyway,
|
||||
// because record is already fully loaded)
|
||||
newLand.mPlugin = 0;
|
||||
|
||||
if (land.mDataTypes & ESM::Land::DATA_VTEX)
|
||||
{
|
||||
// adjust land texture references
|
||||
if (ESM::Land::LandData *data = newLand.getLandData())
|
||||
{
|
||||
std::pair<uint16_t, int> key;
|
||||
key.second = land.mPlugin;
|
||||
|
||||
for (int i=0; i<ESM::Land::LAND_NUM_TEXTURES; ++i)
|
||||
{
|
||||
key.first = data->mTextures[i];
|
||||
std::map<std::pair<uint16_t, int>, int>::const_iterator iter =
|
||||
mState.mTextureIndices.find (key);
|
||||
|
||||
if (iter!=mState.mTextureIndices.end())
|
||||
data->mTextures[i] = iter->second;
|
||||
else
|
||||
data->mTextures[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CSMWorld::Record<CSMWorld::Land> newRecord (
|
||||
CSMWorld::RecordBase::State_ModifiedOnly, 0, &newLand);
|
||||
|
||||
mState.mTarget->getData().getLand().appendRecord (newRecord);
|
||||
}
|
||||
}
|
166
apps/opencs/model/tools/mergestages.hpp
Normal file
166
apps/opencs/model/tools/mergestages.hpp
Normal file
|
@ -0,0 +1,166 @@
|
|||
#ifndef CSM_TOOLS_MERGESTAGES_H
|
||||
#define CSM_TOOLS_MERGESTAGES_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <map>
|
||||
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
|
||||
#include "../doc/stage.hpp"
|
||||
|
||||
#include "../world/data.hpp"
|
||||
|
||||
#include "mergestate.hpp"
|
||||
|
||||
namespace CSMTools
|
||||
{
|
||||
class StartMergeStage : public CSMDoc::Stage
|
||||
{
|
||||
MergeState& mState;
|
||||
|
||||
public:
|
||||
|
||||
StartMergeStage (MergeState& state);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
|
||||
class FinishMergedDocumentStage : public CSMDoc::Stage
|
||||
{
|
||||
MergeState& mState;
|
||||
ToUTF8::Utf8Encoder mEncoder;
|
||||
|
||||
public:
|
||||
|
||||
FinishMergedDocumentStage (MergeState& state, ToUTF8::FromType encoding);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
|
||||
template<typename RecordType, typename Collection = CSMWorld::IdCollection<RecordType> >
|
||||
class MergeIdCollectionStage : public CSMDoc::Stage
|
||||
{
|
||||
MergeState& mState;
|
||||
Collection& (CSMWorld::Data::*mAccessor)();
|
||||
|
||||
public:
|
||||
|
||||
MergeIdCollectionStage (MergeState& state, Collection& (CSMWorld::Data::*accessor)());
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
|
||||
template<typename RecordType, typename Collection>
|
||||
MergeIdCollectionStage<RecordType, Collection>::MergeIdCollectionStage (MergeState& state, Collection& (CSMWorld::Data::*accessor)())
|
||||
: mState (state), mAccessor (accessor)
|
||||
{}
|
||||
|
||||
template<typename RecordType, typename Collection>
|
||||
int MergeIdCollectionStage<RecordType, Collection>::setup()
|
||||
{
|
||||
return (mState.mSource.getData().*mAccessor)().getSize();
|
||||
}
|
||||
|
||||
template<typename RecordType, typename Collection>
|
||||
void MergeIdCollectionStage<RecordType, Collection>::perform (int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
const Collection& source = (mState.mSource.getData().*mAccessor)();
|
||||
Collection& target = (mState.mTarget->getData().*mAccessor)();
|
||||
|
||||
const CSMWorld::Record<RecordType>& record = source.getRecord (stage);
|
||||
|
||||
if (!record.isDeleted())
|
||||
target.appendRecord (CSMWorld::Record<RecordType> (CSMWorld::RecordBase::State_ModifiedOnly, 0, &record.get()));
|
||||
}
|
||||
|
||||
class MergeRefIdsStage : public CSMDoc::Stage
|
||||
{
|
||||
MergeState& mState;
|
||||
|
||||
public:
|
||||
|
||||
MergeRefIdsStage (MergeState& state);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
|
||||
class MergeReferencesStage : public CSMDoc::Stage
|
||||
{
|
||||
MergeState& mState;
|
||||
std::map<std::string, int> mIndex;
|
||||
|
||||
public:
|
||||
|
||||
MergeReferencesStage (MergeState& state);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
|
||||
class ListLandTexturesMergeStage : public CSMDoc::Stage
|
||||
{
|
||||
MergeState& mState;
|
||||
|
||||
public:
|
||||
|
||||
ListLandTexturesMergeStage (MergeState& state);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
|
||||
class MergeLandTexturesStage : public CSMDoc::Stage
|
||||
{
|
||||
MergeState& mState;
|
||||
std::map<std::pair<uint16_t, int>, int>::iterator mNext;
|
||||
|
||||
public:
|
||||
|
||||
MergeLandTexturesStage (MergeState& state);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
|
||||
class MergeLandStage : public CSMDoc::Stage
|
||||
{
|
||||
MergeState& mState;
|
||||
|
||||
public:
|
||||
|
||||
MergeLandStage (MergeState& state);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
24
apps/opencs/model/tools/mergestate.hpp
Normal file
24
apps/opencs/model/tools/mergestate.hpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef CSM_TOOLS_MERGESTATE_H
|
||||
#define CSM_TOOLS_MERGESTATE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
#include "../doc/document.hpp"
|
||||
|
||||
namespace CSMTools
|
||||
{
|
||||
struct MergeState
|
||||
{
|
||||
std::auto_ptr<CSMDoc::Document> mTarget;
|
||||
CSMDoc::Document& mSource;
|
||||
bool mCompleted;
|
||||
std::map<std::pair<uint16_t, int>, int> mTextureIndices; // (texture, content file) -> new texture
|
||||
|
||||
MergeState (CSMDoc::Document& source) : mSource (source), mCompleted (false) {}
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -8,16 +8,6 @@
|
|||
#include "../world/subcellcollection.hpp"
|
||||
#include "../world/pathgrid.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct Point
|
||||
{
|
||||
unsigned char mConnectionNum;
|
||||
std::vector<int> mOtherIndex;
|
||||
Point() : mConnectionNum(0), mOtherIndex(0) {}
|
||||
};
|
||||
}
|
||||
|
||||
CSMTools::PathgridCheckStage::PathgridCheckStage (const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids)
|
||||
: mPathgrids (pathgrids)
|
||||
{}
|
||||
|
@ -40,11 +30,11 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
|
|||
|
||||
// check the number of pathgrid points
|
||||
if (pathgrid.mData.mS2 > static_cast<int>(pathgrid.mPoints.size()))
|
||||
messages.push_back (std::make_pair (id, pathgrid.mId + " has less points than expected"));
|
||||
messages.add (id, pathgrid.mId + " has less points than expected", "", CSMDoc::Message::Severity_Error);
|
||||
else if (pathgrid.mData.mS2 > static_cast<int>(pathgrid.mPoints.size()))
|
||||
messages.push_back (std::make_pair (id, pathgrid.mId + " has more points than expected"));
|
||||
messages.add (id, pathgrid.mId + " has more points than expected", "", CSMDoc::Message::Severity_Error);
|
||||
|
||||
std::vector<Point> pointList(pathgrid.mPoints.size());
|
||||
std::vector<CSMTools::Point> pointList(pathgrid.mPoints.size());
|
||||
std::vector<int> duplList;
|
||||
|
||||
for (unsigned int i = 0; i < pathgrid.mEdges.size(); ++i)
|
||||
|
@ -61,7 +51,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
|
|||
std::ostringstream ss;
|
||||
ss << "has a duplicate edge between points" << pathgrid.mEdges[i].mV0
|
||||
<< " and " << pathgrid.mEdges[i].mV1;
|
||||
messages.push_back (std::make_pair (id, pathgrid.mId + ss.str()));
|
||||
messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +64,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
|
|||
{
|
||||
std::ostringstream ss;
|
||||
ss << " has an edge connecting a non-existent point " << pathgrid.mEdges[i].mV0;
|
||||
messages.push_back (std::make_pair (id, pathgrid.mId + ss.str()));
|
||||
messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,13 +75,13 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
|
|||
{
|
||||
std::ostringstream ss;
|
||||
ss << " has has less edges than expected for point " << i;
|
||||
messages.push_back (std::make_pair (id, pathgrid.mId + ss.str()));
|
||||
messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error);
|
||||
}
|
||||
else if (pathgrid.mPoints[i].mConnectionNum < pointList[i].mConnectionNum)
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << " has has more edges than expected for point " << i;
|
||||
messages.push_back (std::make_pair (id, pathgrid.mId + ss.str()));
|
||||
messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error);
|
||||
}
|
||||
|
||||
// check that edges are bidirectional
|
||||
|
@ -111,7 +101,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
|
|||
{
|
||||
std::ostringstream ss;
|
||||
ss << " has a missing edge between points " << i << " and " << pointList[i].mOtherIndex[j];
|
||||
messages.push_back (std::make_pair (id, pathgrid.mId + ss.str()));
|
||||
messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -134,7 +124,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
|
|||
<< ") x=" << pathgrid.mPoints[i].mX
|
||||
<< ", y=" << pathgrid.mPoints[i].mY
|
||||
<< ", z=" << pathgrid.mPoints[i].mZ;
|
||||
messages.push_back (std::make_pair (id, pathgrid.mId + ss.str()));
|
||||
messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Warning);
|
||||
|
||||
duplList.push_back(i);
|
||||
break;
|
||||
|
@ -153,7 +143,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
|
|||
<< ") x=" << pathgrid.mPoints[i].mX
|
||||
<< ", y=" << pathgrid.mPoints[i].mY
|
||||
<< ", z=" << pathgrid.mPoints[i].mZ;
|
||||
messages.push_back (std::make_pair (id, pathgrid.mId + ss.str()));
|
||||
messages.add (id, pathgrid.mId + ss.str(), "", CSMDoc::Message::Severity_Warning);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,17 +14,26 @@ namespace CSMWorld
|
|||
|
||||
namespace CSMTools
|
||||
{
|
||||
struct Point
|
||||
{
|
||||
unsigned char mConnectionNum;
|
||||
std::vector<int> mOtherIndex;
|
||||
Point() : mConnectionNum(0), mOtherIndex(0) {}
|
||||
};
|
||||
|
||||
class PathgridCheckStage : public CSMDoc::Stage
|
||||
{
|
||||
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid, CSMWorld::IdAccessor<CSMWorld::Pathgrid> >& mPathgrids;
|
||||
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid,
|
||||
CSMWorld::IdAccessor<CSMWorld::Pathgrid> >& mPathgrids;
|
||||
|
||||
public:
|
||||
public:
|
||||
|
||||
PathgridCheckStage (const CSMWorld::SubCellCollection<CSMWorld::Pathgrid, CSMWorld::IdAccessor<CSMWorld::Pathgrid> >& pathgrids);
|
||||
PathgridCheckStage (const CSMWorld::SubCellCollection<CSMWorld::Pathgrid,
|
||||
CSMWorld::IdAccessor<CSMWorld::Pathgrid> >& pathgrids);
|
||||
|
||||
virtual int setup();
|
||||
virtual int setup();
|
||||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "racecheck.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
|
|
@ -468,6 +468,9 @@ void CSMTools::ReferenceableCheckStage::creatureCheck (
|
|||
if (creature.mData.mGold < 0) //It seems that this is for gold in merchant creatures
|
||||
messages.push_back (std::make_pair (id, creature.mId + " has negative gold "));
|
||||
|
||||
if (creature.mScale == 0)
|
||||
messages.push_back (std::make_pair (id, creature.mId + " has zero scale value"));
|
||||
|
||||
// Check that mentioned scripts exist
|
||||
scriptCheck<ESM::Creature>(creature, messages, id.toString());
|
||||
}
|
||||
|
@ -648,7 +651,7 @@ void CSMTools::ReferenceableCheckStage::npcCheck (
|
|||
|
||||
if (npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) //12 = autocalculated
|
||||
{
|
||||
if ((npc.mFlags & ESM::NPC::Autocalc) == 0) //0x0008 = autocalculated flag
|
||||
if ((npc.mFlags & ESM::NPC::Autocalc) == 0) //0x0010 = autocalculated flag
|
||||
{
|
||||
messages.push_back (std::make_pair (id, npc.mId + " mNpdtType or flags mismatch!")); //should not happend?
|
||||
return;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "regioncheck.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "reportmodel.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
@ -6,24 +5,18 @@
|
|||
|
||||
#include "../world/columns.hpp"
|
||||
|
||||
CSMTools::ReportModel::Line::Line (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint)
|
||||
: mId (id), mMessage (message), mHint (hint)
|
||||
{}
|
||||
|
||||
CSMTools::ReportModel::ReportModel (bool fieldColumn)
|
||||
CSMTools::ReportModel::ReportModel (bool fieldColumn, bool severityColumn)
|
||||
: mColumnField (-1), mColumnSeverity (-1)
|
||||
{
|
||||
if (fieldColumn)
|
||||
{
|
||||
mColumnField = 3;
|
||||
mColumnDescription = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
mColumnDescription = 3;
|
||||
int index = 3;
|
||||
|
||||
mColumnField = -1;
|
||||
}
|
||||
if (severityColumn)
|
||||
mColumnSeverity = index++;
|
||||
|
||||
if (fieldColumn)
|
||||
mColumnField = index++;
|
||||
|
||||
mColumnDescription = index;
|
||||
}
|
||||
|
||||
int CSMTools::ReportModel::rowCount (const QModelIndex & parent) const
|
||||
|
@ -52,7 +45,7 @@ QVariant CSMTools::ReportModel::data (const QModelIndex & index, int role) const
|
|||
case Column_Type:
|
||||
|
||||
return static_cast<int> (mRows.at (index.row()).mId.getType());
|
||||
|
||||
|
||||
case Column_Id:
|
||||
{
|
||||
CSMWorld::UniversalId id = mRows.at (index.row()).mId;
|
||||
|
@ -62,7 +55,7 @@ QVariant CSMTools::ReportModel::data (const QModelIndex & index, int role) const
|
|||
|
||||
return QString ("-");
|
||||
}
|
||||
|
||||
|
||||
case Column_Hint:
|
||||
|
||||
return QString::fromUtf8 (mRows.at (index.row()).mHint.c_str());
|
||||
|
@ -88,7 +81,13 @@ QVariant CSMTools::ReportModel::data (const QModelIndex & index, int role) const
|
|||
|
||||
return QString::fromUtf8 (field.c_str());
|
||||
}
|
||||
|
||||
|
||||
if (index.column()==mColumnSeverity)
|
||||
{
|
||||
return QString::fromUtf8 (
|
||||
CSMDoc::Message::toString (mRows.at (index.row()).mSeverity).c_str());
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
|
@ -112,6 +111,9 @@ QVariant CSMTools::ReportModel::headerData (int section, Qt::Orientation orienta
|
|||
if (section==mColumnField)
|
||||
return "Field";
|
||||
|
||||
if (section==mColumnSeverity)
|
||||
return "Severity";
|
||||
|
||||
return "-";
|
||||
}
|
||||
|
||||
|
@ -132,19 +134,18 @@ bool CSMTools::ReportModel::removeRows (int row, int count, const QModelIndex& p
|
|||
return true;
|
||||
}
|
||||
|
||||
void CSMTools::ReportModel::add (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint)
|
||||
void CSMTools::ReportModel::add (const CSMDoc::Message& message)
|
||||
{
|
||||
beginInsertRows (QModelIndex(), mRows.size(), mRows.size());
|
||||
|
||||
mRows.push_back (Line (id, message, hint));
|
||||
|
||||
mRows.push_back (message);
|
||||
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void CSMTools::ReportModel::flagAsReplaced (int index)
|
||||
{
|
||||
Line& line = mRows.at (index);
|
||||
CSMDoc::Message& line = mRows.at (index);
|
||||
std::string hint = line.mHint;
|
||||
|
||||
if (hint.empty() || hint[0]!='R')
|
||||
|
@ -176,3 +177,16 @@ void CSMTools::ReportModel::clear()
|
|||
endRemoveRows();
|
||||
}
|
||||
}
|
||||
|
||||
int CSMTools::ReportModel::countErrors() const
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
for (std::vector<CSMDoc::Messages::Message>::const_iterator iter (mRows.begin());
|
||||
iter!=mRows.end(); ++iter)
|
||||
if (iter->mSeverity==CSMDoc::Message::Severity_Error ||
|
||||
iter->mSeverity==CSMDoc::Message::Severity_SeriousError)
|
||||
++count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
#include "../doc/messages.hpp"
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
namespace CSMTools
|
||||
|
@ -14,17 +16,7 @@ namespace CSMTools
|
|||
{
|
||||
Q_OBJECT
|
||||
|
||||
struct Line
|
||||
{
|
||||
Line (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint);
|
||||
|
||||
CSMWorld::UniversalId mId;
|
||||
std::string mMessage;
|
||||
std::string mHint;
|
||||
};
|
||||
|
||||
std::vector<Line> mRows;
|
||||
std::vector<CSMDoc::Messages::Message> mRows;
|
||||
|
||||
// Fixed columns
|
||||
enum Columns
|
||||
|
@ -35,10 +27,11 @@ namespace CSMTools
|
|||
// Configurable columns
|
||||
int mColumnDescription;
|
||||
int mColumnField;
|
||||
int mColumnSeverity;
|
||||
|
||||
public:
|
||||
|
||||
ReportModel (bool fieldColumn = false);
|
||||
ReportModel (bool fieldColumn = false, bool severityColumn = true);
|
||||
|
||||
virtual int rowCount (const QModelIndex & parent = QModelIndex()) const;
|
||||
|
||||
|
@ -50,8 +43,7 @@ namespace CSMTools
|
|||
|
||||
virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex());
|
||||
|
||||
void add (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint = "");
|
||||
void add (const CSMDoc::Message& message);
|
||||
|
||||
void flagAsReplaced (int index);
|
||||
|
||||
|
@ -60,6 +52,9 @@ namespace CSMTools
|
|||
std::string getHint (int row) const;
|
||||
|
||||
void clear();
|
||||
|
||||
// Return number of messages with Error or SeriousError severity.
|
||||
int countErrors() const;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "scriptcheck.hpp"
|
||||
|
||||
#include <components/compiler/tokenloc.hpp>
|
||||
|
@ -11,6 +10,17 @@
|
|||
|
||||
#include "../world/data.hpp"
|
||||
|
||||
CSMDoc::Message::Severity CSMTools::ScriptCheckStage::getSeverity (Type type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case WarningMessage: return CSMDoc::Message::Severity_Warning;
|
||||
case ErrorMessage: return CSMDoc::Message::Severity_Error;
|
||||
}
|
||||
|
||||
return CSMDoc::Message::Severity_SeriousError;
|
||||
}
|
||||
|
||||
void CSMTools::ScriptCheckStage::report (const std::string& message, const Compiler::TokenLoc& loc,
|
||||
Type type)
|
||||
{
|
||||
|
@ -18,11 +28,6 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, const Compi
|
|||
|
||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
|
||||
|
||||
if (type==ErrorMessage)
|
||||
stream << "error ";
|
||||
else
|
||||
stream << "warning ";
|
||||
|
||||
stream
|
||||
<< "script " << mFile
|
||||
<< ", line " << loc.mLine << ", column " << loc.mColumn
|
||||
|
@ -32,19 +37,21 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, const Compi
|
|||
|
||||
hintStream << "l:" << loc.mLine << " " << loc.mColumn;
|
||||
|
||||
mMessages->add (id, stream.str(), hintStream.str());
|
||||
mMessages->add (id, stream.str(), hintStream.str(), getSeverity (type));
|
||||
}
|
||||
|
||||
void CSMTools::ScriptCheckStage::report (const std::string& message, Type type)
|
||||
{
|
||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
|
||||
|
||||
mMessages->push_back (std::make_pair (id,
|
||||
(type==ErrorMessage ? "error: " : "warning: ") + message));
|
||||
std::ostringstream stream;
|
||||
stream << "script " << mFile << ": " << message;
|
||||
|
||||
mMessages->add (id, stream.str(), "", getSeverity (type));
|
||||
}
|
||||
|
||||
CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMDoc::Document& document)
|
||||
: mDocument (document), mContext (document.getData()), mMessages (0)
|
||||
: mDocument (document), mContext (document.getData()), mMessages (0), mWarningMode (Mode_Ignore)
|
||||
{
|
||||
/// \todo add an option to configure warning mode
|
||||
setWarningsMode (0);
|
||||
|
@ -58,6 +65,7 @@ int CSMTools::ScriptCheckStage::setup()
|
|||
mContext.clear();
|
||||
mMessages = 0;
|
||||
mId.clear();
|
||||
Compiler::ErrorHandler::reset();
|
||||
|
||||
return mDocument.getData().getScripts().getSize();
|
||||
}
|
||||
|
@ -72,6 +80,13 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
|||
|
||||
mMessages = &messages;
|
||||
|
||||
switch (mWarningMode)
|
||||
{
|
||||
case Mode_Ignore: setWarningsMode (0); break;
|
||||
case Mode_Normal: setWarningsMode (1); break;
|
||||
case Mode_Strict: setWarningsMode (2); break;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
const CSMWorld::Data& data = mDocument.getData();
|
||||
|
@ -93,9 +108,24 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
|||
{
|
||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
|
||||
|
||||
messages.push_back (std::make_pair (id,
|
||||
std::string ("Critical compile error: ") + error.what()));
|
||||
std::ostringstream stream;
|
||||
stream << "script " << mFile << ": " << error.what();
|
||||
|
||||
messages.add (id, stream.str(), "", CSMDoc::Message::Severity_SeriousError);
|
||||
}
|
||||
|
||||
mMessages = 0;
|
||||
}
|
||||
|
||||
void CSMTools::ScriptCheckStage::updateUserSetting (const QString& name, const QStringList& value)
|
||||
{
|
||||
if (name=="script-editor/warnings" && !value.isEmpty())
|
||||
{
|
||||
if (value.at (0)=="Ignore")
|
||||
mWarningMode = Mode_Ignore;
|
||||
else if (value.at (0)=="Normal")
|
||||
mWarningMode = Mode_Normal;
|
||||
else if (value.at (0)=="Strict")
|
||||
mWarningMode = Mode_Strict;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,13 +18,23 @@ namespace CSMTools
|
|||
/// \brief VerifyStage: make sure that scripts compile
|
||||
class ScriptCheckStage : public CSMDoc::Stage, private Compiler::ErrorHandler
|
||||
{
|
||||
enum WarningMode
|
||||
{
|
||||
Mode_Ignore,
|
||||
Mode_Normal,
|
||||
Mode_Strict
|
||||
};
|
||||
|
||||
const CSMDoc::Document& mDocument;
|
||||
Compiler::Extensions mExtensions;
|
||||
CSMWorld::ScriptContext mContext;
|
||||
std::string mId;
|
||||
std::string mFile;
|
||||
CSMDoc::Messages *mMessages;
|
||||
WarningMode mWarningMode;
|
||||
|
||||
CSMDoc::Message::Severity getSeverity (Type type);
|
||||
|
||||
virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type);
|
||||
///< Report error to the user.
|
||||
|
||||
|
@ -40,6 +50,8 @@ namespace CSMTools
|
|||
|
||||
virtual void perform (int stage, CSMDoc::Messages& messages);
|
||||
///< Messages resulting from this tage will be appended to \a messages.
|
||||
|
||||
virtual void updateUserSetting (const QString& name, const QStringList& value);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "search.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
@ -280,7 +279,7 @@ void CSMTools::Search::replace (CSMDoc::Document& document, CSMWorld::IdTableBas
|
|||
bool CSMTools::Search::verify (CSMDoc::Document& document, CSMWorld::IdTableBase *model,
|
||||
const CSMWorld::UniversalId& id, const std::string& messageHint) const
|
||||
{
|
||||
CSMDoc::Messages messages;
|
||||
CSMDoc::Messages messages (CSMDoc::Message::Severity_Info);
|
||||
|
||||
int row = model->getModelIndex (id.getId(),
|
||||
model->findColumnIndex (CSMWorld::Columns::ColumnId_Id)).row();
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "searchoperation.hpp"
|
||||
|
||||
#include "../doc/state.hpp"
|
||||
|
@ -21,6 +20,8 @@ CSMTools::SearchOperation::SearchOperation (CSMDoc::Document& document)
|
|||
iter!=types.end(); ++iter)
|
||||
appendStage (new SearchStage (&dynamic_cast<CSMWorld::IdTableBase&> (
|
||||
*document.getData().getTableModel (*iter))));
|
||||
|
||||
setDefaultSeverity (CSMDoc::Message::Severity_Info);
|
||||
}
|
||||
|
||||
void CSMTools::SearchOperation::configure (const Search& search)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "searchstage.hpp"
|
||||
|
||||
#include "../world/idtablebase.hpp"
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "skillcheck.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "soundcheck.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
|
53
apps/opencs/model/tools/soundgencheck.cpp
Normal file
53
apps/opencs/model/tools/soundgencheck.cpp
Normal file
|
@ -0,0 +1,53 @@
|
|||
#include "soundgencheck.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include "../world/refiddata.hpp"
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
CSMTools::SoundGenCheckStage::SoundGenCheckStage(const CSMWorld::IdCollection<ESM::SoundGenerator> &soundGens,
|
||||
const CSMWorld::IdCollection<ESM::Sound> &sounds,
|
||||
const CSMWorld::RefIdCollection &referenceables)
|
||||
: mSoundGens(soundGens),
|
||||
mSounds(sounds),
|
||||
mReferenceables(referenceables)
|
||||
{}
|
||||
|
||||
int CSMTools::SoundGenCheckStage::setup()
|
||||
{
|
||||
return mSoundGens.getSize();
|
||||
}
|
||||
|
||||
void CSMTools::SoundGenCheckStage::perform(int stage, CSMDoc::Messages &messages)
|
||||
{
|
||||
const CSMWorld::Record<ESM::SoundGenerator> &record = mSoundGens.getRecord(stage);
|
||||
if (record.isDeleted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const ESM::SoundGenerator soundGen = record.get();
|
||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_SoundGen, soundGen.mId);
|
||||
|
||||
if (!soundGen.mCreature.empty())
|
||||
{
|
||||
CSMWorld::RefIdData::LocalIndex creatureIndex = mReferenceables.getDataSet().searchId(soundGen.mCreature);
|
||||
if (creatureIndex.first == -1)
|
||||
{
|
||||
messages.push_back(std::make_pair(id, "No such creature '" + soundGen.mCreature + "'"));
|
||||
}
|
||||
else if (creatureIndex.second != CSMWorld::UniversalId::Type_Creature)
|
||||
{
|
||||
messages.push_back(std::make_pair(id, "'" + soundGen.mCreature + "' is not a creature"));
|
||||
}
|
||||
}
|
||||
|
||||
if (soundGen.mSound.empty())
|
||||
{
|
||||
messages.push_back(std::make_pair(id, "Sound is not specified"));
|
||||
}
|
||||
else if (mSounds.searchId(soundGen.mSound) == -1)
|
||||
{
|
||||
messages.push_back(std::make_pair(id, "No such sound '" + soundGen.mSound + "'"));
|
||||
}
|
||||
}
|
30
apps/opencs/model/tools/soundgencheck.hpp
Normal file
30
apps/opencs/model/tools/soundgencheck.hpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef CSM_TOOLS_SOUNDGENCHECK_HPP
|
||||
#define CSM_TOOLS_SOUNDGENCHECK_HPP
|
||||
|
||||
#include "../world/data.hpp"
|
||||
|
||||
#include "../doc/stage.hpp"
|
||||
|
||||
namespace CSMTools
|
||||
{
|
||||
/// \brief VerifyStage: make sure that sound gen records are internally consistent
|
||||
class SoundGenCheckStage : public CSMDoc::Stage
|
||||
{
|
||||
const CSMWorld::IdCollection<ESM::SoundGenerator> &mSoundGens;
|
||||
const CSMWorld::IdCollection<ESM::Sound> &mSounds;
|
||||
const CSMWorld::RefIdCollection &mReferenceables;
|
||||
|
||||
public:
|
||||
SoundGenCheckStage(const CSMWorld::IdCollection<ESM::SoundGenerator> &soundGens,
|
||||
const CSMWorld::IdCollection<ESM::Sound> &sounds,
|
||||
const CSMWorld::RefIdCollection &referenceables);
|
||||
|
||||
virtual int setup();
|
||||
///< \return number of steps
|
||||
|
||||
virtual void perform(int stage, CSMDoc::Messages &messages);
|
||||
///< Messages resulting from this stage will be appended to \a messages.
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "spellcheck.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "startscriptcheck.hpp"
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "tools.hpp"
|
||||
|
||||
#include <QThreadPool>
|
||||
|
@ -27,6 +26,9 @@
|
|||
#include "startscriptcheck.hpp"
|
||||
#include "searchoperation.hpp"
|
||||
#include "pathgridcheck.hpp"
|
||||
#include "soundgencheck.hpp"
|
||||
#include "magiceffectcheck.hpp"
|
||||
#include "mergeoperation.hpp"
|
||||
|
||||
CSMDoc::OperationHolder *CSMTools::Tools::get (int type)
|
||||
{
|
||||
|
@ -34,6 +36,7 @@ CSMDoc::OperationHolder *CSMTools::Tools::get (int type)
|
|||
{
|
||||
case CSMDoc::State_Verifying: return &mVerifier;
|
||||
case CSMDoc::State_Searching: return &mSearch;
|
||||
case CSMDoc::State_Merging: return &mMerge;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -50,11 +53,15 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier()
|
|||
{
|
||||
mVerifierOperation = new CSMDoc::Operation (CSMDoc::State_Verifying, false);
|
||||
|
||||
std::vector<QString> settings;
|
||||
settings.push_back ("script-editor/warnings");
|
||||
|
||||
mVerifierOperation->configureSettings (settings);
|
||||
|
||||
connect (&mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
|
||||
connect (&mVerifier, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool)));
|
||||
connect (&mVerifier,
|
||||
SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)),
|
||||
this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)));
|
||||
connect (&mVerifier, SIGNAL (reportMessage (const CSMDoc::Message&, int)),
|
||||
this, SLOT (verifierMessage (const CSMDoc::Message&, int)));
|
||||
|
||||
std::vector<std::string> mandatoryIds; // I want C++11, damn it!
|
||||
mandatoryIds.push_back ("Day");
|
||||
|
@ -99,15 +106,25 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier()
|
|||
|
||||
mVerifierOperation->appendStage (new PathgridCheckStage (mData.getPathgrids()));
|
||||
|
||||
mVerifierOperation->appendStage (new SoundGenCheckStage (mData.getSoundGens(),
|
||||
mData.getSounds(),
|
||||
mData.getReferenceables()));
|
||||
|
||||
mVerifierOperation->appendStage (new MagicEffectCheckStage (mData.getMagicEffects(),
|
||||
mData.getSounds(),
|
||||
mData.getReferenceables(),
|
||||
mData.getResources (CSMWorld::UniversalId::Type_Icons),
|
||||
mData.getResources (CSMWorld::UniversalId::Type_Textures)));
|
||||
|
||||
mVerifier.setOperation (mVerifierOperation);
|
||||
}
|
||||
|
||||
return &mVerifier;
|
||||
}
|
||||
|
||||
CSMTools::Tools::Tools (CSMDoc::Document& document)
|
||||
CSMTools::Tools::Tools (CSMDoc::Document& document, ToUTF8::FromType encoding)
|
||||
: mDocument (document), mData (document.getData()), mVerifierOperation (0),
|
||||
mSearchOperation (0), mNextReportNumber (0)
|
||||
mSearchOperation (0), mMergeOperation (0), mNextReportNumber (0), mEncoding (encoding)
|
||||
{
|
||||
// index 0: load error log
|
||||
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel));
|
||||
|
@ -115,9 +132,12 @@ CSMTools::Tools::Tools (CSMDoc::Document& document)
|
|||
|
||||
connect (&mSearch, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
|
||||
connect (&mSearch, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool)));
|
||||
connect (&mSearch,
|
||||
SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)),
|
||||
this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)));
|
||||
connect (&mSearch, SIGNAL (reportMessage (const CSMDoc::Message&, int)),
|
||||
this, SLOT (verifierMessage (const CSMDoc::Message&, int)));
|
||||
|
||||
connect (&mMerge, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
|
||||
connect (&mMerge, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool)));
|
||||
// don't need to connect report message, since there are no messages for merge
|
||||
}
|
||||
|
||||
CSMTools::Tools::~Tools()
|
||||
|
@ -134,23 +154,34 @@ CSMTools::Tools::~Tools()
|
|||
delete mSearchOperation;
|
||||
}
|
||||
|
||||
if (mMergeOperation)
|
||||
{
|
||||
mMerge.abortAndWait();
|
||||
delete mMergeOperation;
|
||||
}
|
||||
|
||||
for (std::map<int, ReportModel *>::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter)
|
||||
delete iter->second;
|
||||
}
|
||||
|
||||
CSMWorld::UniversalId CSMTools::Tools::runVerifier()
|
||||
CSMWorld::UniversalId CSMTools::Tools::runVerifier (const CSMWorld::UniversalId& reportId)
|
||||
{
|
||||
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel));
|
||||
mActiveReports[CSMDoc::State_Verifying] = mNextReportNumber-1;
|
||||
int reportNumber = reportId.getType()==CSMWorld::UniversalId::Type_VerificationResults ?
|
||||
reportId.getIndex() : mNextReportNumber++;
|
||||
|
||||
if (mReports.find (reportNumber)==mReports.end())
|
||||
mReports.insert (std::make_pair (reportNumber, new ReportModel));
|
||||
|
||||
mActiveReports[CSMDoc::State_Verifying] = reportNumber;
|
||||
|
||||
getVerifier()->start();
|
||||
|
||||
return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_VerificationResults, mNextReportNumber-1);
|
||||
return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_VerificationResults, reportNumber);
|
||||
}
|
||||
|
||||
CSMWorld::UniversalId CSMTools::Tools::newSearch()
|
||||
{
|
||||
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel (true)));
|
||||
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel (true, false)));
|
||||
|
||||
return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Search, mNextReportNumber-1);
|
||||
}
|
||||
|
@ -170,6 +201,25 @@ void CSMTools::Tools::runSearch (const CSMWorld::UniversalId& searchId, const Se
|
|||
mSearch.start();
|
||||
}
|
||||
|
||||
void CSMTools::Tools::runMerge (std::auto_ptr<CSMDoc::Document> target)
|
||||
{
|
||||
// not setting an active report, because merge does not produce messages
|
||||
|
||||
if (!mMergeOperation)
|
||||
{
|
||||
mMergeOperation = new MergeOperation (mDocument, mEncoding);
|
||||
mMerge.setOperation (mMergeOperation);
|
||||
connect (mMergeOperation, SIGNAL (mergeDone (CSMDoc::Document*)),
|
||||
this, SIGNAL (mergeDone (CSMDoc::Document*)));
|
||||
}
|
||||
|
||||
target->flagAsDirty();
|
||||
|
||||
mMergeOperation->setTarget (target);
|
||||
|
||||
mMerge.start();
|
||||
}
|
||||
|
||||
void CSMTools::Tools::abortOperation (int type)
|
||||
{
|
||||
if (CSMDoc::OperationHolder *operation = get (type))
|
||||
|
@ -182,6 +232,7 @@ int CSMTools::Tools::getRunningOperations() const
|
|||
{
|
||||
CSMDoc::State_Verifying,
|
||||
CSMDoc::State_Searching,
|
||||
CSMDoc::State_Merging,
|
||||
-1
|
||||
};
|
||||
|
||||
|
@ -205,12 +256,10 @@ CSMTools::ReportModel *CSMTools::Tools::getReport (const CSMWorld::UniversalId&
|
|||
return mReports.at (id.getIndex());
|
||||
}
|
||||
|
||||
void CSMTools::Tools::verifierMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint, int type)
|
||||
void CSMTools::Tools::verifierMessage (const CSMDoc::Message& message, int type)
|
||||
{
|
||||
std::map<int, int>::iterator iter = mActiveReports.find (type);
|
||||
|
||||
if (iter!=mActiveReports.end())
|
||||
mReports[iter->second]->add (id, message, hint);
|
||||
mReports[iter->second]->add (message);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,14 @@
|
|||
#ifndef CSM_TOOLS_TOOLS_H
|
||||
#define CSM_TOOLS_TOOLS_H
|
||||
|
||||
#include <memory>
|
||||
#include <map>
|
||||
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include <map>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
#include "../doc/operationholder.hpp"
|
||||
|
||||
|
@ -24,6 +29,7 @@ namespace CSMTools
|
|||
class ReportModel;
|
||||
class Search;
|
||||
class SearchOperation;
|
||||
class MergeOperation;
|
||||
|
||||
class Tools : public QObject
|
||||
{
|
||||
|
@ -35,9 +41,12 @@ namespace CSMTools
|
|||
CSMDoc::OperationHolder mVerifier;
|
||||
SearchOperation *mSearchOperation;
|
||||
CSMDoc::OperationHolder mSearch;
|
||||
MergeOperation *mMergeOperation;
|
||||
CSMDoc::OperationHolder mMerge;
|
||||
std::map<int, ReportModel *> mReports;
|
||||
int mNextReportNumber;
|
||||
std::map<int, int> mActiveReports; // type, report number
|
||||
ToUTF8::FromType mEncoding;
|
||||
|
||||
// not implemented
|
||||
Tools (const Tools&);
|
||||
|
@ -53,18 +62,23 @@ namespace CSMTools
|
|||
|
||||
public:
|
||||
|
||||
Tools (CSMDoc::Document& document);
|
||||
Tools (CSMDoc::Document& document, ToUTF8::FromType encoding);
|
||||
|
||||
virtual ~Tools();
|
||||
|
||||
CSMWorld::UniversalId runVerifier();
|
||||
///< \return ID of the report for this verification run
|
||||
/// \param reportId If a valid VerificationResults ID, run verifier for the
|
||||
/// specified report instead of creating a new one.
|
||||
///
|
||||
/// \return ID of the report for this verification run
|
||||
CSMWorld::UniversalId runVerifier (const CSMWorld::UniversalId& reportId = CSMWorld::UniversalId());
|
||||
|
||||
/// Return ID of the report for this search.
|
||||
CSMWorld::UniversalId newSearch();
|
||||
|
||||
void runSearch (const CSMWorld::UniversalId& searchId, const Search& search);
|
||||
|
||||
|
||||
void runMerge (std::auto_ptr<CSMDoc::Document> target);
|
||||
|
||||
void abortOperation (int type);
|
||||
///< \attention The operation is not aborted immediately.
|
||||
|
||||
|
@ -75,14 +89,17 @@ namespace CSMTools
|
|||
|
||||
private slots:
|
||||
|
||||
void verifierMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
||||
const std::string& hint, int type);
|
||||
void verifierMessage (const CSMDoc::Message& message, int type);
|
||||
|
||||
signals:
|
||||
|
||||
void progress (int current, int max, int type);
|
||||
|
||||
void done (int type, bool failed);
|
||||
|
||||
/// \attention When this signal is emitted, *this hands over the ownership of the
|
||||
/// document. This signal must be handled to avoid a leak.
|
||||
void mergeDone (CSMDoc::Document *document);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "cell.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "cellcoordinates.hpp"
|
||||
|
||||
#include <ostream>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "cellselection.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "collectionbase.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
|
|
@ -65,6 +65,8 @@ bool CSMWorld::ColumnBase::isId (Display display)
|
|||
Display_JournalInfo,
|
||||
Display_Scene,
|
||||
Display_GlobalVariable,
|
||||
Display_BodyPart,
|
||||
Display_Enchantment,
|
||||
Display_Script,
|
||||
|
||||
Display_Mesh,
|
||||
|
@ -75,16 +77,18 @@ bool CSMWorld::ColumnBase::isId (Display display)
|
|||
Display_Video,
|
||||
|
||||
Display_Id,
|
||||
Display_SkillImpact,
|
||||
Display_SkillId,
|
||||
Display_EffectRange,
|
||||
Display_EffectId,
|
||||
Display_PartRefType,
|
||||
Display_AiPackageType,
|
||||
Display_YesNo,
|
||||
Display_InfoCondFunc,
|
||||
Display_InfoCondVar,
|
||||
Display_InfoCondComp,
|
||||
Display_RaceSkill,
|
||||
|
||||
Display_EffectSkill,
|
||||
Display_EffectAttribute,
|
||||
Display_IngredEffectId,
|
||||
|
||||
Display_None
|
||||
};
|
||||
|
@ -98,7 +102,8 @@ bool CSMWorld::ColumnBase::isId (Display display)
|
|||
|
||||
bool CSMWorld::ColumnBase::isText (Display display)
|
||||
{
|
||||
return display==Display_String || display==Display_LongString;
|
||||
return display==Display_String || display==Display_LongString ||
|
||||
display==Display_String32 || display==Display_LongString256;
|
||||
}
|
||||
|
||||
bool CSMWorld::ColumnBase::isScript (Display display)
|
||||
|
|
|
@ -14,6 +14,13 @@ namespace CSMWorld
|
|||
{
|
||||
struct ColumnBase
|
||||
{
|
||||
enum TableEditModes
|
||||
{
|
||||
TableEdit_None, // no editing
|
||||
TableEdit_Full, // edit cells and add/remove rows
|
||||
TableEdit_FixedRows // edit cells only
|
||||
};
|
||||
|
||||
enum Roles
|
||||
{
|
||||
Role_Flags = Qt::UserRole,
|
||||
|
@ -74,6 +81,8 @@ namespace CSMWorld
|
|||
Display_JournalInfo,
|
||||
Display_Scene,
|
||||
Display_GlobalVariable,
|
||||
Display_BodyPart,
|
||||
Display_Enchantment,
|
||||
//CONCRETE TYPES ENDS HERE
|
||||
|
||||
Display_Integer,
|
||||
|
@ -111,16 +120,20 @@ namespace CSMWorld
|
|||
Display_SoundGeneratorType,
|
||||
Display_School,
|
||||
Display_Id,
|
||||
Display_SkillImpact,
|
||||
Display_SkillId,
|
||||
Display_EffectRange,
|
||||
Display_EffectId,
|
||||
Display_PartRefType,
|
||||
Display_AiPackageType,
|
||||
Display_YesNo,
|
||||
Display_InfoCondFunc,
|
||||
Display_InfoCondVar,
|
||||
Display_InfoCondComp,
|
||||
Display_RaceSkill,
|
||||
Display_String32,
|
||||
Display_LongString256,
|
||||
|
||||
Display_EffectSkill, // must display at least one, unlike Display_Skill
|
||||
Display_EffectAttribute, // must display at least one, unlike Display_Attribute
|
||||
Display_IngredEffectId, // display none allowed, unlike Display_EffectId
|
||||
|
||||
//top level columns that nest other columns
|
||||
Display_NestedHeader
|
||||
|
@ -184,19 +197,32 @@ namespace CSMWorld
|
|||
template<typename ESXRecordT>
|
||||
struct NestedParentColumn : public Column<ESXRecordT>
|
||||
{
|
||||
NestedParentColumn (int id, int flags = ColumnBase::Flag_Dialogue) : Column<ESXRecordT> (id,
|
||||
ColumnBase::Display_NestedHeader, flags)
|
||||
NestedParentColumn (int id, int flags = ColumnBase::Flag_Dialogue, bool fixedRows = false)
|
||||
: Column<ESXRecordT> (id, ColumnBase::Display_NestedHeader, flags), mFixedRows(fixedRows)
|
||||
{}
|
||||
|
||||
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||
{
|
||||
// There is nothing to do here.
|
||||
// This prevents exceptions from parent's implementation
|
||||
}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
return true; // required by IdTree::hasChildren()
|
||||
// by default editable; also see IdTree::hasChildren()
|
||||
if (mFixedRows)
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_FixedRows);
|
||||
else
|
||||
return QVariant::fromValue(ColumnBase::TableEdit_Full);
|
||||
}
|
||||
|
||||
virtual bool isEditable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
bool mFixedRows;
|
||||
};
|
||||
|
||||
struct NestedChildColumn : public NestableColumn
|
||||
|
@ -211,4 +237,6 @@ namespace CSMWorld
|
|||
};
|
||||
}
|
||||
|
||||
Q_DECLARE_METATYPE(CSMWorld::ColumnBase::TableEditModes)
|
||||
|
||||
#endif
|
||||
|
|
28
apps/opencs/model/world/columnimp.cpp
Normal file
28
apps/opencs/model/world/columnimp.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include "columnimp.hpp"
|
||||
|
||||
CSMWorld::BodyPartRaceColumn::BodyPartRaceColumn(const MeshTypeColumn<ESM::BodyPart> *meshType)
|
||||
: mMeshType(meshType)
|
||||
{}
|
||||
|
||||
QVariant CSMWorld::BodyPartRaceColumn::get(const Record<ESM::BodyPart> &record) const
|
||||
{
|
||||
if (mMeshType != NULL && mMeshType->get(record) == ESM::BodyPart::MT_Skin)
|
||||
{
|
||||
return QString::fromUtf8(record.get().mRace.c_str());
|
||||
}
|
||||
return QVariant(QVariant::UserType);
|
||||
}
|
||||
|
||||
void CSMWorld::BodyPartRaceColumn::set(Record<ESM::BodyPart> &record, const QVariant &data)
|
||||
{
|
||||
ESM::BodyPart record2 = record.get();
|
||||
|
||||
record2.mRace = data.toString().toUtf8().constData();
|
||||
|
||||
record.setModified(record2);
|
||||
}
|
||||
|
||||
bool CSMWorld::BodyPartRaceColumn::isEditable() const
|
||||
{
|
||||
return true;
|
||||
}
|
|
@ -9,6 +9,10 @@
|
|||
|
||||
#include <QColor>
|
||||
|
||||
#include <components/esm/loadbody.hpp>
|
||||
#include <components/esm/loadskil.hpp>
|
||||
#include <components/esm/loadrace.hpp>
|
||||
|
||||
#include "columnbase.hpp"
|
||||
#include "columns.hpp"
|
||||
#include "info.hpp"
|
||||
|
@ -694,7 +698,7 @@ namespace CSMWorld
|
|||
|
||||
QColor colour = data.value<QColor>();
|
||||
|
||||
record2.mMapColor = colour.rgb() & 0xffffff;
|
||||
record2.mMapColor = (colour.blue() << 16) | (colour.green() << 8) | colour.red();
|
||||
|
||||
record.setModified (record2);
|
||||
}
|
||||
|
@ -709,7 +713,7 @@ namespace CSMWorld
|
|||
struct SleepListColumn : public Column<ESXRecordT>
|
||||
{
|
||||
SleepListColumn()
|
||||
: Column<ESXRecordT> (Columns::ColumnId_SleepEncounter, ColumnBase::Display_String)
|
||||
: Column<ESXRecordT> (Columns::ColumnId_SleepEncounter, ColumnBase::Display_CreatureLevelledList)
|
||||
{}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
|
@ -735,7 +739,7 @@ namespace CSMWorld
|
|||
template<typename ESXRecordT>
|
||||
struct TextureColumn : public Column<ESXRecordT>
|
||||
{
|
||||
TextureColumn() : Column<ESXRecordT> (Columns::ColumnId_Texture, ColumnBase::Display_String) {}
|
||||
TextureColumn() : Column<ESXRecordT> (Columns::ColumnId_Texture, ColumnBase::Display_Texture) {}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
|
@ -1269,7 +1273,7 @@ namespace CSMWorld
|
|||
template<typename ESXRecordT>
|
||||
struct TrapColumn : public Column<ESXRecordT>
|
||||
{
|
||||
TrapColumn() : Column<ESXRecordT> (Columns::ColumnId_Trap, ColumnBase::Display_String) {}
|
||||
TrapColumn() : Column<ESXRecordT> (Columns::ColumnId_Trap, ColumnBase::Display_Spell) {}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
|
@ -1294,7 +1298,7 @@ namespace CSMWorld
|
|||
template<typename ESXRecordT>
|
||||
struct FilterColumn : public Column<ESXRecordT>
|
||||
{
|
||||
FilterColumn() : Column<ESXRecordT> (Columns::ColumnId_Filter, ColumnBase::Display_String) {}
|
||||
FilterColumn() : Column<ESXRecordT> (Columns::ColumnId_Filter, ColumnBase::Display_Filter) {}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
|
@ -1497,7 +1501,10 @@ namespace CSMWorld
|
|||
template<typename ESXRecordT>
|
||||
struct TopicColumn : public Column<ESXRecordT>
|
||||
{
|
||||
TopicColumn (bool journal) : Column<ESXRecordT> (journal ? Columns::ColumnId_Journal : Columns::ColumnId_Topic, ColumnBase::Display_String) {}
|
||||
TopicColumn (bool journal)
|
||||
: Column<ESXRecordT> (journal ? Columns::ColumnId_Journal : Columns::ColumnId_Topic,
|
||||
journal ? ColumnBase::Display_Journal : ColumnBase::Display_Topic)
|
||||
{}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
|
@ -1527,7 +1534,7 @@ namespace CSMWorld
|
|||
template<typename ESXRecordT>
|
||||
struct ActorColumn : public Column<ESXRecordT>
|
||||
{
|
||||
ActorColumn() : Column<ESXRecordT> (Columns::ColumnId_Actor, ColumnBase::Display_String) {}
|
||||
ActorColumn() : Column<ESXRecordT> (Columns::ColumnId_Actor, ColumnBase::Display_Npc) {}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
|
@ -1830,7 +1837,7 @@ namespace CSMWorld
|
|||
template<typename ESXRecordT>
|
||||
struct ModelColumn : public Column<ESXRecordT>
|
||||
{
|
||||
ModelColumn() : Column<ESXRecordT> (Columns::ColumnId_Model, ColumnBase::Display_String) {}
|
||||
ModelColumn() : Column<ESXRecordT> (Columns::ColumnId_Model, ColumnBase::Display_Mesh) {}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
|
@ -1908,8 +1915,8 @@ namespace CSMWorld
|
|||
template<typename ESXRecordT>
|
||||
struct MeshTypeColumn : public Column<ESXRecordT>
|
||||
{
|
||||
MeshTypeColumn()
|
||||
: Column<ESXRecordT> (Columns::ColumnId_MeshType, ColumnBase::Display_MeshType)
|
||||
MeshTypeColumn(int flags = ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue)
|
||||
: Column<ESXRecordT> (Columns::ColumnId_MeshType, ColumnBase::Display_MeshType, flags)
|
||||
{}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
|
@ -2158,7 +2165,9 @@ namespace CSMWorld
|
|||
struct EffectTextureColumn : public Column<ESXRecordT>
|
||||
{
|
||||
EffectTextureColumn (Columns::ColumnId columnId)
|
||||
: Column<ESXRecordT> (columnId, ColumnBase::Display_Texture)
|
||||
: Column<ESXRecordT> (columnId,
|
||||
columnId == Columns::ColumnId_Particle ? ColumnBase::Display_Texture
|
||||
: ColumnBase::Display_Icon)
|
||||
{
|
||||
assert (this->mColumnId==Columns::ColumnId_Icon ||
|
||||
this->mColumnId==Columns::ColumnId_Particle);
|
||||
|
@ -2303,6 +2312,89 @@ namespace CSMWorld
|
|||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ESXRecordT>
|
||||
struct FormatColumn : public Column<ESXRecordT>
|
||||
{
|
||||
FormatColumn()
|
||||
: Column<ESXRecordT> (Columns::ColumnId_FileFormat, ColumnBase::Display_Integer)
|
||||
{}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
return record.get().mFormat;
|
||||
}
|
||||
|
||||
virtual bool isEditable() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ESXRecordT>
|
||||
struct AuthorColumn : public Column<ESXRecordT>
|
||||
{
|
||||
AuthorColumn()
|
||||
: Column<ESXRecordT> (Columns::ColumnId_Author, ColumnBase::Display_String32)
|
||||
{}
|
||||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
return QString::fromUtf8 (record.get().mAuthor.c_str());
|
||||
}
|
||||
|
||||
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||
{
|
||||
ESXRecordT record2 = record.get();
|
||||
|
||||
record2.mAuthor = data.toString().toUtf8().constData();
|
||||
|
||||
record.setModified (record2);
|
||||
}
|
||||
|
||||
virtual bool isEditable() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename ESXRecordT>
|
||||
struct FileDescriptionColumn : public Column<ESXRecordT>
|
||||
{
|
||||
FileDescriptionColumn()
|
||||
: Column<ESXRecordT> (Columns::ColumnId_FileDescription, ColumnBase::Display_LongString256)
|
||||
{}
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
|
||||
struct BodyPartRaceColumn : public RaceColumn<ESM::BodyPart>
|
||||
{
|
||||
const MeshTypeColumn<ESM::BodyPart> *mMeshType;
|
||||
|
||||
BodyPartRaceColumn(const MeshTypeColumn<ESM::BodyPart> *meshType);
|
||||
|
||||
virtual QVariant get(const Record<ESM::BodyPart> &record) const;
|
||||
virtual void set(Record<ESM::BodyPart> &record, const QVariant &data);
|
||||
virtual bool isEditable() const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "columns.hpp"
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
@ -35,6 +34,8 @@ namespace CSMWorld
|
|||
{ ColumnId_Volume, "Volume" },
|
||||
{ ColumnId_MinRange, "Min Range" },
|
||||
{ ColumnId_MaxRange, "Max Range" },
|
||||
{ ColumnId_MinMagnitude, "Min Magnitude" },
|
||||
{ ColumnId_MaxMagnitude, "Max Magnitude" },
|
||||
{ ColumnId_SoundFile, "Sound File" },
|
||||
{ ColumnId_MapColour, "Map Colour" },
|
||||
{ ColumnId_SleepEncounter, "Sleep Encounter" },
|
||||
|
@ -70,7 +71,6 @@ namespace CSMWorld
|
|||
{ ColumnId_Weight, "Weight" },
|
||||
{ ColumnId_EnchantmentPoints, "Enchantment Points" },
|
||||
{ ColumnId_Quality, "Quality" },
|
||||
{ ColumnId_Ai, "AI" },
|
||||
{ ColumnId_AiHello, "AI Hello" },
|
||||
{ ColumnId_AiFlee, "AI Flee" },
|
||||
{ ColumnId_AiFight, "AI Fight" },
|
||||
|
@ -92,7 +92,7 @@ namespace CSMWorld
|
|||
{ ColumnId_Trainer, "Trainer" },
|
||||
{ ColumnId_Spellmaking, "Spellmaking" },
|
||||
{ ColumnId_EnchantingService, "Enchanting Service" },
|
||||
{ ColumnId_RepairService, "Repair Serivce" },
|
||||
{ ColumnId_RepairService, "Repair Service" },
|
||||
{ ColumnId_ApparatusType, "Apparatus Type" },
|
||||
{ ColumnId_ArmorType, "Armor Type" },
|
||||
{ ColumnId_Health, "Health" },
|
||||
|
@ -107,7 +107,6 @@ namespace CSMWorld
|
|||
{ ColumnId_OriginalCreature, "Original Creature" },
|
||||
{ ColumnId_Biped, "Biped" },
|
||||
{ ColumnId_HasWeapon, "Has Weapon" },
|
||||
{ ColumnId_NoMovement, "No Movement" },
|
||||
{ ColumnId_Swims, "Swims" },
|
||||
{ ColumnId_Flies, "Flies" },
|
||||
{ ColumnId_Walks, "Walks" },
|
||||
|
@ -199,8 +198,6 @@ namespace CSMWorld
|
|||
{ ColumnId_RotY, "Rotation Y"},
|
||||
{ ColumnId_RotZ, "Rotation Z"},
|
||||
|
||||
{ ColumnId_Skill, "Skill" },
|
||||
|
||||
{ ColumnId_OwnerGlobal, "Owner Global" },
|
||||
{ ColumnId_DefaultProfile, "Default Profile" },
|
||||
{ ColumnId_BypassNewGame, "Bypass New Game" },
|
||||
|
@ -252,7 +249,7 @@ namespace CSMWorld
|
|||
{ ColumnId_AiWanderDist, "Wander Dist" },
|
||||
{ ColumnId_AiDuration, "Ai Duration" },
|
||||
{ ColumnId_AiWanderToD, "Wander ToD" },
|
||||
{ ColumnId_AiWanderIdle, "Wander Idle" },
|
||||
//{ ColumnId_AiWanderIdle, "Wander Idle" },
|
||||
{ ColumnId_AiWanderRepeat, "Wander Repeat" },
|
||||
{ ColumnId_AiActivateName, "Activate" },
|
||||
{ ColumnId_AiTargetId, "Target ID" },
|
||||
|
@ -265,13 +262,13 @@ namespace CSMWorld
|
|||
|
||||
{ ColumnId_LevelledList,"Levelled List" },
|
||||
{ ColumnId_LevelledItemId,"Levelled Item" },
|
||||
{ ColumnId_LevelledItemLevel,"Level" },
|
||||
{ ColumnId_LevelledItemLevel,"Item Level" },
|
||||
{ ColumnId_LevelledItemType, "Calculate all levels <= player" },
|
||||
{ ColumnId_LevelledItemTypeEach, "Select a new item each instance" },
|
||||
{ ColumnId_LevelledItemChanceNone, "Chance None" },
|
||||
|
||||
{ ColumnId_PowerList, "Powers" },
|
||||
{ ColumnId_SkillImpact, "Skills" },
|
||||
{ ColumnId_Skill, "Skill" },
|
||||
|
||||
{ ColumnId_InfoList, "Info List" },
|
||||
{ ColumnId_InfoCondition, "Info Conditions" },
|
||||
|
@ -281,26 +278,24 @@ namespace CSMWorld
|
|||
{ ColumnId_InfoCondValue, "Values" },
|
||||
{ ColumnId_OriginalCell, "Original Cell" },
|
||||
|
||||
{ ColumnId_NpcAttributes, "Attributes" },
|
||||
{ ColumnId_NpcSkills, "Skills" },
|
||||
{ ColumnId_NpcAttributes, "NPC Attributes" },
|
||||
{ ColumnId_NpcSkills, "NPC Skill" },
|
||||
{ ColumnId_UChar, "Value [0..255]" },
|
||||
{ ColumnId_NpcMisc, "Misc" },
|
||||
{ ColumnId_NpcLevel, "Level" },
|
||||
{ ColumnId_NpcMisc, "NPC Misc" },
|
||||
{ ColumnId_Level, "Level" },
|
||||
{ ColumnId_NpcFactionID, "Faction ID" },
|
||||
{ ColumnId_NpcHealth, "Health" },
|
||||
{ ColumnId_NpcMana, "Mana" },
|
||||
{ ColumnId_NpcFatigue, "Fatigue" },
|
||||
{ ColumnId_NpcDisposition, "Disposition" },
|
||||
|
||||
{ ColumnId_Mana, "Mana" },
|
||||
{ ColumnId_Fatigue, "Fatigue" },
|
||||
{ ColumnId_NpcDisposition, "NPC Disposition" },
|
||||
{ ColumnId_NpcReputation, "Reputation" },
|
||||
{ ColumnId_NpcRank, "Rank" },
|
||||
{ ColumnId_NpcGold, "Gold" },
|
||||
{ ColumnId_NpcRank, "NPC Rank" },
|
||||
{ ColumnId_Gold, "Gold" },
|
||||
{ ColumnId_NpcPersistence, "Persistent" },
|
||||
|
||||
{ ColumnId_RaceAttributes, "Attributes" },
|
||||
{ ColumnId_RaceMaleValue, "Male" },
|
||||
{ ColumnId_RaceFemaleValue, "Female" },
|
||||
{ ColumnId_RaceAttributes, "Race Attributes" },
|
||||
{ ColumnId_Male, "Male" },
|
||||
{ ColumnId_RaceSkillBonus, "Skill Bonus" },
|
||||
{ ColumnId_RaceSkill, "Skills" },
|
||||
{ ColumnId_RaceBonus, "Bonus" },
|
||||
|
||||
{ ColumnId_Interior, "Interior" },
|
||||
|
@ -311,6 +306,30 @@ namespace CSMWorld
|
|||
{ ColumnId_WaterLevel, "Water Level" },
|
||||
{ ColumnId_MapColor, "Map Color" },
|
||||
|
||||
{ ColumnId_FileFormat, "File Format" },
|
||||
{ ColumnId_FileDescription, "File Description" },
|
||||
{ ColumnId_Author, "Author" },
|
||||
|
||||
{ ColumnId_CreatureAttributes, "Creature Attributes" },
|
||||
{ ColumnId_AttributeValue, "Attrib Value" },
|
||||
{ ColumnId_CreatureAttack, "Creature Attack" },
|
||||
{ ColumnId_MinAttack, "Min Attack" },
|
||||
{ ColumnId_MaxAttack, "Max Attack" },
|
||||
{ ColumnId_CreatureMisc, "Creature Misc" },
|
||||
|
||||
{ ColumnId_Idle1, "Idle 1" },
|
||||
{ ColumnId_Idle2, "Idle 2" },
|
||||
{ ColumnId_Idle3, "Idle 3" },
|
||||
{ ColumnId_Idle4, "Idle 4" },
|
||||
{ ColumnId_Idle5, "Idle 5" },
|
||||
{ ColumnId_Idle6, "Idle 6" },
|
||||
{ ColumnId_Idle7, "Idle 7" },
|
||||
{ ColumnId_Idle8, "Idle 8" },
|
||||
|
||||
{ ColumnId_SpellSrc, "From Race" },
|
||||
{ ColumnId_SpellCost, "Cast Cost" },
|
||||
{ ColumnId_SpellChance, "Cast Chance" },
|
||||
|
||||
{ ColumnId_UseValue1, "Use value 1" },
|
||||
{ ColumnId_UseValue2, "Use value 2" },
|
||||
{ ColumnId_UseValue3, "Use value 3" },
|
||||
|
@ -532,11 +551,6 @@ namespace
|
|||
"AI Wander", "AI Travel", "AI Follow", "AI Escort", "AI Activate", 0
|
||||
};
|
||||
|
||||
static const char *sAiWanderRepeat[] =
|
||||
{
|
||||
"No", "Yes", 0
|
||||
};
|
||||
|
||||
static const char *sInfoCondFunc[] =
|
||||
{
|
||||
" ", "Function", "Global", "Local", "Journal",
|
||||
|
@ -571,17 +585,15 @@ namespace
|
|||
case CSMWorld::Columns::ColumnId_MeshType: return sMeshTypes;
|
||||
case CSMWorld::Columns::ColumnId_SoundGeneratorType: return sSoundGeneratorType;
|
||||
case CSMWorld::Columns::ColumnId_School: return sSchools;
|
||||
case CSMWorld::Columns::ColumnId_SkillImpact: return sSkills;
|
||||
case CSMWorld::Columns::ColumnId_Skill: return sSkills;
|
||||
case CSMWorld::Columns::ColumnId_EffectRange: return sEffectRange;
|
||||
case CSMWorld::Columns::ColumnId_EffectId: return sEffectId;
|
||||
case CSMWorld::Columns::ColumnId_PartRefType: return sPartRefType;
|
||||
case CSMWorld::Columns::ColumnId_AiPackageType: return sAiPackageType;
|
||||
case CSMWorld::Columns::ColumnId_AiWanderRepeat: return sAiWanderRepeat;
|
||||
case CSMWorld::Columns::ColumnId_InfoCondFunc: return sInfoCondFunc;
|
||||
// FIXME: don't have dynamic value enum delegate, use Display_String for now
|
||||
//case CSMWorld::Columns::ColumnId_InfoCond: return sInfoCond;
|
||||
case CSMWorld::Columns::ColumnId_InfoCondComp: return sInfoCondComp;
|
||||
case CSMWorld::Columns::ColumnId_RaceSkill: return sSkills;
|
||||
|
||||
default: return 0;
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace CSMWorld
|
|||
ColumnId_Weight = 50,
|
||||
ColumnId_EnchantmentPoints = 51,
|
||||
ColumnId_Quality = 52,
|
||||
ColumnId_Ai = 53,
|
||||
// unused
|
||||
ColumnId_AiHello = 54,
|
||||
ColumnId_AiFlee = 55,
|
||||
ColumnId_AiFight = 56,
|
||||
|
@ -102,7 +102,7 @@ namespace CSMWorld
|
|||
ColumnId_OriginalCreature = 87,
|
||||
ColumnId_Biped = 88,
|
||||
ColumnId_HasWeapon = 89,
|
||||
ColumnId_NoMovement = 90,
|
||||
// used for SpellSrc
|
||||
ColumnId_Swims = 91,
|
||||
ColumnId_Flies = 92,
|
||||
ColumnId_Walks = 93,
|
||||
|
@ -189,7 +189,7 @@ namespace CSMWorld
|
|||
ColumnId_RotX = 174,
|
||||
ColumnId_RotY = 175,
|
||||
ColumnId_RotZ = 176,
|
||||
ColumnId_Skill = 177,
|
||||
// used for SpellCost
|
||||
ColumnId_OwnerGlobal = 178,
|
||||
ColumnId_DefaultProfile = 179,
|
||||
ColumnId_BypassNewGame = 180,
|
||||
|
@ -241,7 +241,7 @@ namespace CSMWorld
|
|||
ColumnId_AiWanderDist = 221,
|
||||
ColumnId_AiDuration = 222,
|
||||
ColumnId_AiWanderToD = 223,
|
||||
ColumnId_AiWanderIdle = 224,
|
||||
// unused
|
||||
ColumnId_AiWanderRepeat = 225,
|
||||
ColumnId_AiActivateName = 226,
|
||||
// use ColumnId_PosX, etc for AI destinations
|
||||
|
@ -261,7 +261,7 @@ namespace CSMWorld
|
|||
ColumnId_LevelledItemChanceNone = 238,
|
||||
|
||||
ColumnId_PowerList = 239,
|
||||
ColumnId_SkillImpact = 240, // impact from magic effects
|
||||
ColumnId_Skill = 240,
|
||||
|
||||
ColumnId_InfoList = 241,
|
||||
ColumnId_InfoCondition = 242,
|
||||
|
@ -276,22 +276,22 @@ namespace CSMWorld
|
|||
ColumnId_NpcSkills = 249,
|
||||
ColumnId_UChar = 250,
|
||||
ColumnId_NpcMisc = 251,
|
||||
ColumnId_NpcLevel = 252,
|
||||
ColumnId_Level = 252,
|
||||
ColumnId_NpcFactionID = 253,
|
||||
ColumnId_NpcHealth = 254,
|
||||
ColumnId_NpcMana = 255,
|
||||
ColumnId_NpcFatigue = 256,
|
||||
// used for SpellChance
|
||||
ColumnId_Mana = 255,
|
||||
ColumnId_Fatigue = 256,
|
||||
ColumnId_NpcDisposition = 257,
|
||||
ColumnId_NpcReputation = 258,
|
||||
ColumnId_NpcRank = 259,
|
||||
ColumnId_NpcGold = 260,
|
||||
ColumnId_Gold = 260,
|
||||
ColumnId_NpcPersistence = 261,
|
||||
|
||||
ColumnId_RaceAttributes = 262,
|
||||
ColumnId_RaceMaleValue = 263,
|
||||
ColumnId_RaceFemaleValue = 264,
|
||||
ColumnId_Male = 263,
|
||||
// unused
|
||||
ColumnId_RaceSkillBonus = 265,
|
||||
ColumnId_RaceSkill = 266,
|
||||
// unused
|
||||
ColumnId_RaceBonus = 267,
|
||||
|
||||
ColumnId_Interior = 268,
|
||||
|
@ -302,6 +302,33 @@ namespace CSMWorld
|
|||
ColumnId_WaterLevel = 273,
|
||||
ColumnId_MapColor = 274,
|
||||
|
||||
ColumnId_FileFormat = 275,
|
||||
ColumnId_FileDescription = 276,
|
||||
ColumnId_Author = 277,
|
||||
|
||||
ColumnId_MinMagnitude = 278,
|
||||
ColumnId_MaxMagnitude = 279,
|
||||
|
||||
ColumnId_CreatureAttributes = 280,
|
||||
ColumnId_AttributeValue = 281,
|
||||
ColumnId_CreatureAttack = 282,
|
||||
ColumnId_MinAttack = 283,
|
||||
ColumnId_MaxAttack = 284,
|
||||
ColumnId_CreatureMisc = 285,
|
||||
|
||||
ColumnId_Idle1 = 286,
|
||||
ColumnId_Idle2 = 287,
|
||||
ColumnId_Idle3 = 288,
|
||||
ColumnId_Idle4 = 289,
|
||||
ColumnId_Idle5 = 290,
|
||||
ColumnId_Idle6 = 291,
|
||||
ColumnId_Idle7 = 292,
|
||||
ColumnId_Idle8 = 293,
|
||||
|
||||
ColumnId_SpellSrc = 90,
|
||||
ColumnId_SpellCost = 177,
|
||||
ColumnId_SpellChance = 254,
|
||||
|
||||
// Allocated to a separate value range, so we don't get a collision should we ever need
|
||||
// to extend the number of use values.
|
||||
ColumnId_UseValue1 = 0x10000,
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include "commanddispatcher.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
|
|
@ -21,19 +21,31 @@ CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelI
|
|||
// Replace proxy with actual model
|
||||
mIndex = proxy->mapToSource (index);
|
||||
mModel = proxy->sourceModel();
|
||||
}
|
||||
|
||||
if (mIndex.parent().isValid())
|
||||
{
|
||||
setText ("Modify " + dynamic_cast<CSMWorld::IdTree*>(mModel)->nestedHeaderData (
|
||||
mIndex.parent().column(), mIndex.column(), Qt::Horizontal, Qt::DisplayRole).toString());
|
||||
}
|
||||
else
|
||||
{
|
||||
setText ("Modify " + mModel->headerData (mIndex.column(), Qt::Horizontal, Qt::DisplayRole).toString());
|
||||
}
|
||||
|
||||
// Remember record state before the modification
|
||||
if (CSMWorld::IdTable *table = dynamic_cast<IdTable *>(mModel))
|
||||
{
|
||||
mHasRecordState = true;
|
||||
int stateColumnIndex = table->findColumnIndex(Columns::ColumnId_Modification);
|
||||
mRecordStateIndex = table->index(mIndex.row(), stateColumnIndex);
|
||||
|
||||
int rowIndex = mIndex.row();
|
||||
if (mIndex.parent().isValid())
|
||||
{
|
||||
rowIndex = mIndex.parent().row();
|
||||
}
|
||||
|
||||
mRecordStateIndex = table->index(rowIndex, stateColumnIndex);
|
||||
mOldRecordState = static_cast<CSMWorld::RecordBase::State>(table->data(mRecordStateIndex).toInt());
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +70,25 @@ void CSMWorld::CreateCommand::applyModifications()
|
|||
{
|
||||
for (std::map<int, QVariant>::const_iterator iter (mValues.begin()); iter!=mValues.end(); ++iter)
|
||||
mModel.setData (mModel.getModelIndex (mId, iter->first), iter->second);
|
||||
|
||||
if (!mNestedValues.empty())
|
||||
{
|
||||
CSMWorld::IdTree *tree = dynamic_cast<CSMWorld::IdTree *>(&mModel);
|
||||
if (tree == NULL)
|
||||
{
|
||||
throw std::logic_error("CSMWorld::CreateCommand: Attempt to add nested values to the non-nested model");
|
||||
}
|
||||
|
||||
std::map<int, std::pair<int, QVariant> >::const_iterator current = mNestedValues.begin();
|
||||
std::map<int, std::pair<int, QVariant> >::const_iterator end = mNestedValues.end();
|
||||
for (; current != end; ++current)
|
||||
{
|
||||
QModelIndex index = tree->index(0,
|
||||
current->second.first,
|
||||
tree->getNestedModelIndex(mId, current->first));
|
||||
tree->setData(index, current->second.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CSMWorld::CreateCommand::CreateCommand (IdTable& model, const std::string& id, QUndoCommand* parent)
|
||||
|
@ -71,6 +102,11 @@ void CSMWorld::CreateCommand::addValue (int column, const QVariant& value)
|
|||
mValues[column] = value;
|
||||
}
|
||||
|
||||
void CSMWorld::CreateCommand::addNestedValue(int parentColumn, int nestedColumn, const QVariant &value)
|
||||
{
|
||||
mNestedValues[parentColumn] = std::make_pair(nestedColumn, value);
|
||||
}
|
||||
|
||||
void CSMWorld::CreateCommand::setType (UniversalId::Type type)
|
||||
{
|
||||
mType = type;
|
||||
|
@ -258,21 +294,24 @@ CSMWorld::DeleteNestedCommand::DeleteNestedCommand (IdTree& model,
|
|||
std::string title =
|
||||
model.headerData(parentColumn, Qt::Horizontal, Qt::DisplayRole).toString().toUtf8().constData();
|
||||
setText (("Delete row in " + title + " sub-table of " + mId).c_str());
|
||||
|
||||
QModelIndex parentIndex = mModel.getModelIndex(mId, mParentColumn);
|
||||
mModifyParentCommand = new ModifyCommand(mModel, parentIndex, parentIndex.data(Qt::EditRole), this);
|
||||
}
|
||||
|
||||
void CSMWorld::DeleteNestedCommand::redo()
|
||||
{
|
||||
const QModelIndex& parentIndex = mModel.getModelIndex(mId, mParentColumn);
|
||||
|
||||
QModelIndex parentIndex = mModel.getModelIndex(mId, mParentColumn);
|
||||
mModel.removeRows (mNestedRow, 1, parentIndex);
|
||||
mModifyParentCommand->redo();
|
||||
}
|
||||
|
||||
|
||||
void CSMWorld::DeleteNestedCommand::undo()
|
||||
{
|
||||
const QModelIndex& parentIndex = mModel.getModelIndex(mId, mParentColumn);
|
||||
|
||||
QModelIndex parentIndex = mModel.getModelIndex(mId, mParentColumn);
|
||||
mModel.setNestedTable(parentIndex, getOld());
|
||||
mModifyParentCommand->undo();
|
||||
}
|
||||
|
||||
CSMWorld::AddNestedCommand::AddNestedCommand(IdTree& model, const std::string& id, int nestedRow, int parentColumn, QUndoCommand* parent)
|
||||
|
@ -286,20 +325,23 @@ CSMWorld::AddNestedCommand::AddNestedCommand(IdTree& model, const std::string& i
|
|||
std::string title =
|
||||
model.headerData(parentColumn, Qt::Horizontal, Qt::DisplayRole).toString().toUtf8().constData();
|
||||
setText (("Add row in " + title + " sub-table of " + mId).c_str());
|
||||
|
||||
QModelIndex parentIndex = mModel.getModelIndex(mId, mParentColumn);
|
||||
mModifyParentCommand = new ModifyCommand(mModel, parentIndex, parentIndex.data(Qt::EditRole), this);
|
||||
}
|
||||
|
||||
void CSMWorld::AddNestedCommand::redo()
|
||||
{
|
||||
const QModelIndex& parentIndex = mModel.getModelIndex(mId, mParentColumn);
|
||||
|
||||
QModelIndex parentIndex = mModel.getModelIndex(mId, mParentColumn);
|
||||
mModel.addNestedRow (parentIndex, mNewRow);
|
||||
mModifyParentCommand->redo();
|
||||
}
|
||||
|
||||
void CSMWorld::AddNestedCommand::undo()
|
||||
{
|
||||
const QModelIndex& parentIndex = mModel.getModelIndex(mId, mParentColumn);
|
||||
|
||||
QModelIndex parentIndex = mModel.getModelIndex(mId, mParentColumn);
|
||||
mModel.setNestedTable(parentIndex, getOld());
|
||||
mModifyParentCommand->undo();
|
||||
}
|
||||
|
||||
CSMWorld::NestedTableStoring::NestedTableStoring(const IdTree& model, const std::string& id, int parentColumn)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue