1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-23 10:20:48 +00:00

Merge branch 'master' into pathgrid-edit

Conflicts:
	apps/opencs/view/render/cell.cpp
This commit is contained in:
cc9cii 2015-04-18 15:47:45 +10:00
commit 03578129c7
447 changed files with 5427 additions and 2978 deletions

View File

@ -21,6 +21,14 @@ addons:
build_command_prepend: "cmake ." build_command_prepend: "cmake ."
build_command: "make -j3" build_command: "make -j3"
branch_pattern: coverity_scan branch_pattern: coverity_scan
matrix:
include:
- os: linux
env:
ANALYZE="scan-build-3.6 --use-cc clang-3.6 --use-c++ clang++-3.6 "
compiler: clang
allow_failures:
- env: ANALYZE="scan-build-3.6 --use-cc clang-3.6 --use-c++ clang++-3.6 "
before_install: before_install:
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./CI/before_install.linux.sh; fi - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./CI/before_install.linux.sh; fi
@ -30,7 +38,7 @@ before_script:
- if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_script.osx.sh; fi - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_script.osx.sh; fi
script: script:
- cd ./build - cd ./build
- if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then make -j4; fi - if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j4; fi
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi - if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi
after_script: after_script:
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi

View File

@ -39,6 +39,7 @@ Programmers
Eli2 Eli2
Emanuel Guével (potatoesmaster) Emanuel Guével (potatoesmaster)
eroen eroen
escondida
Evgeniy Mineev (sandstranger) Evgeniy Mineev (sandstranger)
Fil Krynicki (filkry) Fil Krynicki (filkry)
Gašper Sedej Gašper Sedej

View File

@ -1,3 +1,42 @@
0.35.1
------
Bug #781: incorrect trajectory of the sun
Bug #1079: Wrong starting position in "Character Stuff Wonderland"
Bug #1443: Repetitive taking of a stolen object is repetitively considered as a crime
Bug #1533: Divine Intervention goes to the wrong place.
Bug #1714: No visual indicator for time passed during training
Bug #1916: Telekinesis does not allow safe opening of traps
Bug #2227: Editor: addon file name inconsistency
Bug #2271: Player can melee enemies from water with impunity
Bug #2275: Objects with bigger scale move further using Move script
Bug #2285: Aryon's Dominator enchantment does not work properly
Bug #2290: No punishment for stealing gold from owned containers
Bug #2328: Launcher does not respond to Ctrl+C
Bug #2334: Drag-and-drop on a content file in the launcher creates duplicate items
Bug #2338: Arrows reclaimed from corpses do not stack sometimes
Bug #2344: Launcher - Settings importer running correctly?
Bug #2346: Launcher - Importing plugins into content list screws up the load order
Bug #2348: Mod: H.E.L.L.U.V.A. Handy Holdables does not appear in the content list
Bug #2353: Detect Animal detects dead creatures
Bug #2354: Cmake does not respect LIB_SUFFIX
Bug #2356: Active magic set inactive when switching magic items
Bug #2361: ERROR: ESM Error: Previous record contains unread bytes
Bug #2382: Switching spells with "next spell" or "previous spell" while holding shift promps delete spell dialog
Bug #2388: Regression: Can't toggle map on/off
Bug #2392: MOD Shrines - Restore Health and Cancel Options adds 100 health points
Bug #2394: List of Data Files tab in openmw-laucher needs to show all content files.
Bug #2402: Editor: skills saved incorrectly
Bug #2408: Equipping a constant effect Restore Health/Magicka/Fatigue item will permanently boost the stat it's restoring
Bug #2415: It is now possible to fall off the prison ship into the water when starting a new game
Bug #2419: MOD MCA crash to desktop
Bug #2420: Game crashes when character enters a certain area
Bug #2421: infinite loop when using cycle weapon without having a weapon
Feature #2221: Cannot dress dead NPCs
Feature #2349: Check CMake sets correct MSVC compiler settings for release build.
Feature #2397: Set default values for global mandatory records.
Feature #2412: Basic joystick support
0.35.0 0.35.0
------ ------

View File

@ -1,7 +1,12 @@
#!/bin/sh #!/bin/sh
export CXX=g++ if [ "${ANALYZE}" ]; then
export CC=gcc if [ $(lsb_release -sc) = "precise" ]; then
echo "yes" | sudo apt-add-repository ppa:ubuntu-toolchain-r/test
fi
echo "yes" | sudo add-apt-repository "deb http://llvm.org/apt/`lsb_release -sc`/ llvm-toolchain-`lsb_release -sc`-3.6 main"
wget -O - http://llvm.org/apt/llvm-snapshot.gpg.key|sudo apt-key add -
fi
echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse" echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse"
echo "yes" | sudo apt-add-repository ppa:openmw/openmw echo "yes" | sudo apt-add-repository ppa:openmw/openmw
@ -10,6 +15,7 @@ sudo apt-get install -qq libgtest-dev google-mock
sudo apt-get install -qq libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libboost-thread-dev libboost-wave-dev sudo apt-get install -qq libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libboost-thread-dev libboost-wave-dev
sudo apt-get install -qq libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavresample-dev sudo apt-get install -qq libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavresample-dev
sudo apt-get install -qq libbullet-dev libogre-1.9-dev libmygui-dev libsdl2-dev libunshield-dev libtinyxml-dev libopenal-dev libqt4-dev sudo apt-get install -qq libbullet-dev libogre-1.9-dev libmygui-dev libsdl2-dev libunshield-dev libtinyxml-dev libopenal-dev libqt4-dev
if [ "${ANALYZE}" ]; then sudo apt-get install -qq clang-3.6; fi
sudo mkdir /usr/src/gtest/build sudo mkdir /usr/src/gtest/build
cd /usr/src/gtest/build cd /usr/src/gtest/build
sudo cmake .. -DBUILD_SHARED_LIBS=1 sudo cmake .. -DBUILD_SHARED_LIBS=1

View File

@ -2,4 +2,6 @@
mkdir build mkdir build
cd build cd build
cmake .. -DBUILD_WITH_CODE_COVERAGE=1 -DBUILD_UNITTESTS=1 -DCMAKE_INSTALL_PREFIX=/usr -DBINDIR=/usr/games -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DUSE_SYSTEM_TINYXML=TRUE export CODE_COVERAGE=1
if [ "${CC}" = "clang" ]; then export CODE_COVERAGE=0; fi
${ANALYZE}cmake .. -DBUILD_WITH_CODE_COVERAGE=${CODE_COVERAGE} -DBUILD_UNITTESTS=1 -DCMAKE_INSTALL_PREFIX=/usr -DBINDIR=/usr/games -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DUSE_SYSTEM_TINYXML=TRUE

View File

@ -20,7 +20,7 @@ message(STATUS "Configuring OpenMW...")
set(OPENMW_VERSION_MAJOR 0) set(OPENMW_VERSION_MAJOR 0)
set(OPENMW_VERSION_MINOR 35) set(OPENMW_VERSION_MINOR 35)
set(OPENMW_VERSION_RELEASE 0) set(OPENMW_VERSION_RELEASE 1)
set(OPENMW_VERSION_COMMITHASH "") set(OPENMW_VERSION_COMMITHASH "")
set(OPENMW_VERSION_TAGHASH "") set(OPENMW_VERSION_TAGHASH "")
@ -97,43 +97,6 @@ endif()
# We probably support older versions than this. # We probably support older versions than this.
cmake_minimum_required(VERSION 2.6) cmake_minimum_required(VERSION 2.6)
# source directory: libs
set(LIBS_DIR ${CMAKE_SOURCE_DIR}/libs)
set(OENGINE_OGRE
${LIBS_DIR}/openengine/ogre/renderer.cpp
${LIBS_DIR}/openengine/ogre/lights.cpp
${LIBS_DIR}/openengine/ogre/selectionbuffer.cpp
${LIBS_DIR}/openengine/ogre/imagerotate.cpp
)
set(OENGINE_GUI
${LIBS_DIR}/openengine/gui/loglistener.cpp
${LIBS_DIR}/openengine/gui/manager.cpp
${LIBS_DIR}/openengine/gui/layout.cpp
)
set(OENGINE_BULLET
${LIBS_DIR}/openengine/bullet/BtOgre.cpp
${LIBS_DIR}/openengine/bullet/BtOgreExtras.h
${LIBS_DIR}/openengine/bullet/BtOgreGP.h
${LIBS_DIR}/openengine/bullet/BtOgrePG.h
${LIBS_DIR}/openengine/bullet/physic.cpp
${LIBS_DIR}/openengine/bullet/physic.hpp
${LIBS_DIR}/openengine/bullet/BulletShapeLoader.cpp
${LIBS_DIR}/openengine/bullet/BulletShapeLoader.h
${LIBS_DIR}/openengine/bullet/trace.cpp
${LIBS_DIR}/openengine/bullet/trace.h
)
set(OENGINE_ALL ${OENGINE_OGRE} ${OENGINE_GUI} ${OENGINE_BULLET})
source_group(libs\\openengine FILES ${OENGINE_ALL})
set(OPENMW_LIBS ${OENGINE_ALL})
set(OPENMW_LIBS_HEADER)
# Sound setup # Sound setup
set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE AVRESAMPLE) set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE AVRESAMPLE)
unset(FFMPEG_LIBRARIES CACHE) unset(FFMPEG_LIBRARIES CACHE)
@ -266,7 +229,8 @@ endif ()
endif(WIN32) endif(WIN32)
endif(OGRE_STATIC) endif(OGRE_STATIC)
include_directories("." include_directories("." ${LIBS_DIR}
SYSTEM
${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE ${OGRE_INCLUDE_DIRS} ${OGRE_PLUGIN_INCLUDE_DIRS} ${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE ${OGRE_INCLUDE_DIRS} ${OGRE_PLUGIN_INCLUDE_DIRS}
${OGRE_INCLUDE_DIR}/Overlay ${OGRE_Overlay_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Overlay ${OGRE_Overlay_INCLUDE_DIR}
${SDL2_INCLUDE_DIR} ${SDL2_INCLUDE_DIR}
@ -275,7 +239,7 @@ include_directories("."
${MYGUI_INCLUDE_DIRS} ${MYGUI_INCLUDE_DIRS}
${MYGUI_PLATFORM_INCLUDE_DIRS} ${MYGUI_PLATFORM_INCLUDE_DIRS}
${OPENAL_INCLUDE_DIR} ${OPENAL_INCLUDE_DIR}
${LIBS_DIR} ${BULLET_INCLUDE_DIRS}
) )
link_directories(${SDL2_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR} ${MYGUI_LIB_DIR}) link_directories(${SDL2_LIBRARY_DIRS} ${Boost_LIBRARY_DIRS} ${OGRE_LIB_DIR} ${MYGUI_LIB_DIR})
@ -375,6 +339,9 @@ configure_file(${OpenMW_SOURCE_DIR}/files/opencs.ini
configure_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters configure_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters
"${OpenMW_BINARY_DIR}/resources/defaultfilters" COPYONLY) "${OpenMW_BINARY_DIR}/resources/defaultfilters" COPYONLY)
configure_file(${OpenMW_SOURCE_DIR}/files/gamecontrollerdb.txt
"${OpenMW_BINARY_DIR}/gamecontrollerdb.txt")
if (NOT WIN32 AND NOT APPLE) if (NOT WIN32 AND NOT APPLE)
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop
"${OpenMW_BINARY_DIR}/openmw.desktop") "${OpenMW_BINARY_DIR}/openmw.desktop")
@ -382,22 +349,30 @@ if (NOT WIN32 AND NOT APPLE)
"${OpenMW_BINARY_DIR}/openmw-cs.desktop") "${OpenMW_BINARY_DIR}/openmw-cs.desktop")
endif() endif()
# Compiler settings # CXX Compiler settings
if (CMAKE_COMPILER_IS_GNUCC) if (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
SET(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wno-reorder -std=c++98 -pedantic -Wno-long-long ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter -Wno-reorder -std=c++98 -pedantic -Wno-long-long")
if (CMAKE_CXX_COMPILER_ID STREQUAL Clang AND NOT APPLE)
execute_process(COMMAND ${CMAKE_C_COMPILER} --version OUTPUT_VARIABLE CLANG_VERSION)
string(REGEX REPLACE ".*version ([0-9\\.]*).*" "\\1" CLANG_VERSION ${CLANG_VERSION})
if ("${CLANG_VERSION}" VERSION_GREATER 3.6 OR "${CLANG_VERSION}" VERSION_EQUAL 3.6)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-potentially-evaluated-expression")
endif ("${CLANG_VERSION}" VERSION_GREATER 3.6 OR "${CLANG_VERSION}" VERSION_EQUAL 3.6)
endif(CMAKE_CXX_COMPILER_ID STREQUAL Clang AND NOT APPLE)
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
OUTPUT_VARIABLE GCC_VERSION) OUTPUT_VARIABLE GCC_VERSION)
if ("${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6) if (CMAKE_CXX_COMPILER_ID STREQUAL GNU AND "${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6)
SET(CMAKE_CXX_FLAGS "-Wno-unused-but-set-parameter ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-but-set-parameter")
endif("${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6) endif(CMAKE_CXX_COMPILER_ID STREQUAL GNU AND "${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6)
elseif (MSVC) elseif (MSVC)
# Enable link-time code generation globally for all linking # Enable link-time code generation globally for all linking
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL") set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG") set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG") set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG")
set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "${CMAKE_STATIC_LINKER_FLAGS_RELEASE} /LTCG") set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "${CMAKE_STATIC_LINKER_FLAGS_RELEASE} /LTCG")
endif (CMAKE_COMPILER_IS_GNUCC) endif (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
IF(NOT WIN32 AND NOT APPLE) IF(NOT WIN32 AND NOT APPLE)
# Linux building # Linux building
@ -462,6 +437,8 @@ IF(NOT WIN32 AND NOT APPLE)
INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw") INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw") INSTALL(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" COMPONENT "openmw") INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" COMPONENT "openmw")
INSTALL(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
IF(BUILD_OPENCS) IF(BUILD_OPENCS)
INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${SYSCONFDIR}" COMPONENT "opencs") INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${SYSCONFDIR}" COMPONENT "opencs")
ENDIF(BUILD_OPENCS) ENDIF(BUILD_OPENCS)
@ -482,6 +459,7 @@ if(WIN32)
"${OpenMW_SOURCE_DIR}/Docs/license/DejaVu Font License.txt" "${OpenMW_SOURCE_DIR}/Docs/license/DejaVu Font License.txt"
"${OpenMW_BINARY_DIR}/settings-default.cfg" "${OpenMW_BINARY_DIR}/settings-default.cfg"
"${OpenMW_BINARY_DIR}/transparency-overrides.cfg" "${OpenMW_BINARY_DIR}/transparency-overrides.cfg"
"${OpenMW_BINARY_DIR}/gamecontrollerdb.txt"
"${OpenMW_BINARY_DIR}/Release/openmw.exe" "${OpenMW_BINARY_DIR}/Release/openmw.exe"
DESTINATION ".") DESTINATION ".")
@ -566,6 +544,10 @@ if(WIN32)
include(CPack) include(CPack)
endif(WIN32) endif(WIN32)
# Libs
include_directories(libs)
add_subdirectory(libs/openengine)
# Extern # Extern
add_subdirectory (extern/shiny) add_subdirectory (extern/shiny)
add_subdirectory (extern/ogre-ffmpeg-videoplayer) add_subdirectory (extern/ogre-ffmpeg-videoplayer)
@ -699,61 +681,23 @@ if (WIN32)
set(WARNINGS "${WARNINGS} /wd${d}") set(WARNINGS "${WARNINGS} /wd${d}")
endforeach(d) endforeach(d)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNINGS} ${MT_BUILD}")
# boost::wave has a few issues with signed / unsigned conversions, so we suppress those here # boost::wave has a few issues with signed / unsigned conversions, so we suppress those here
set(SHINY_WARNINGS "${WARNINGS} /wd4245") set(SHINY_WARNINGS "${WARNINGS} /wd4245")
set_target_properties(shiny PROPERTIES COMPILE_FLAGS "${SHINY_WARNINGS} ${MT_BUILD}") set_target_properties(shiny PROPERTIES COMPILE_FLAGS "${SHINY_WARNINGS} ${MT_BUILD}")
set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
set_target_properties(sdl4ogre PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
# oics uses tinyxml, which has an initialized but unused variable # oics uses tinyxml, which has an initialized but unused variable
set(OICS_WARNINGS "${WARNINGS} /wd4189") set(OICS_WARNINGS "${WARNINGS} /wd4189")
set_target_properties(oics PROPERTIES COMPILE_FLAGS "${OICS_WARNINGS} ${MT_BUILD}") set_target_properties(oics PROPERTIES COMPILE_FLAGS "${OICS_WARNINGS} ${MT_BUILD}")
set_target_properties(components PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
set_target_properties(ogre-ffmpeg-videoplayer PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
if (BUILD_MYGUI_PLUGIN)
set_target_properties(Plugin_MyGUI_OpenMW_Resources PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_MYGUI_PLUGIN)
if (BUILD_LAUNCHER)
set_target_properties(openmw-launcher PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_LAUNCHER)
set_target_properties(openmw PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
if (BUILD_BSATOOL)
set_target_properties(bsatool PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_BSATOOL)
if (BUILD_ESMTOOL)
set_target_properties(esmtool PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_ESMTOOL)
if (BUILD_WIZARD)
set_target_properties(openmw-wizard PROPERTIES COMPILE_FLAGS ${WARNINGS})
endif (BUILD_WIZARD)
if (BUILD_OPENCS) if (BUILD_OPENCS)
# QT triggers an informational warning that the object layout may differ when compiled with /vd2 # QT triggers an informational warning that the object layout may differ when compiled with /vd2
set(OPENCS_WARNINGS "${WARNINGS} ${MT_BUILD} /wd4435") set(OPENCS_WARNINGS "${WARNINGS} ${MT_BUILD} /wd4435")
set_target_properties(openmw-cs PROPERTIES COMPILE_FLAGS ${OPENCS_WARNINGS}) set_target_properties(openmw-cs PROPERTIES COMPILE_FLAGS ${OPENCS_WARNINGS})
endif (BUILD_OPENCS) endif (BUILD_OPENCS)
if (BUILD_ESSIMPORTER)
set_target_properties(openmw-essimporter PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_ESSIMPORTER)
if (BUILD_MWINIIMPORTER)
set_target_properties(openmw-iniimporter PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_MWINIIMPORTER)
endif(MSVC) endif(MSVC)
# Same for MinGW
if (MINGW)
if (USE_DEBUG_CONSOLE)
set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "-Wl,-subsystem,console")
set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "-Wl,-subsystem,console")
set_target_properties(openmw PROPERTIES COMPILE_DEFINITIONS_DEBUG "_CONSOLE")
else(USE_DEBUG_CONSOLE)
set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "-Wl,-subsystem,windows")
set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "-Wl,-subsystem,windows")
endif(USE_DEBUG_CONSOLE)
set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "-Wl,-subsystem,console")
set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "-Wl,-subsystem,console")
set_target_properties(openmw PROPERTIES COMPILE_DEFINITIONS_RELEASE "_CONSOLE")
endif(MINGW)
# TODO: At some point release builds should not use the console but rather write to a log file # TODO: At some point release builds should not use the console but rather write to a log file
#set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS") #set_target_properties(openmw PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
#set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS") #set_target_properties(openmw PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS")
@ -767,6 +711,7 @@ if (APPLE)
install(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" RENAME "openmw.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
install(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime) install(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)

View File

@ -6,7 +6,7 @@ OpenMW
OpenMW is an attempt at recreating the engine for the popular role-playing game OpenMW is an attempt at recreating the engine for the popular role-playing game
Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work. Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work.
* Version: 0.35.0 * Version: 0.35.1
* License: GPL (see docs/license/GPL3.txt for more information) * License: GPL (see docs/license/GPL3.txt for more information)
* Website: http://www.openmw.org * Website: http://www.openmw.org
* IRC: #openmw on irc.freenode.net * IRC: #openmw on irc.freenode.net
@ -23,7 +23,7 @@ Getting Started
* [Testing the game](https://wiki.openmw.org/index.php?title=Testing) * [Testing the game](https://wiki.openmw.org/index.php?title=Testing)
* [How to contribute](https://wiki.openmw.org/index.php?title=Contribution_Wanted) * [How to contribute](https://wiki.openmw.org/index.php?title=Contribution_Wanted)
* [Report a bug](http://bugs.openmw.org/projects/openmw) - read the [guidelines](https://wiki.openmw.org/index.php?title=Bug_Reporting_Guidelines) before submitting your first bug! * [Report a bug](http://bugs.openmw.org/projects/openmw) - read the [guidelines](https://wiki.openmw.org/index.php?title=Bug_Reporting_Guidelines) before submitting your first bug!
* [Known issues] (http://bugs.openmw.org/projects/openmw/issues?utf8=%E2%9C%93&set_filter=1&f%5B%5D=status_id&op%5Bstatus_id%5D=%3D&v%5Bstatus_id%5D%5B%5D=7&f%5B%5D=tracker_id&op%5Btracker_id%5D=%3D&v%5Btracker_id%5D%5B%5D=1&f%5B%5D=&c%5B%5D=project&c%5B%5D=tracker&c%5B%5D=status&c%5B%5D=priority&c%5B%5D=subject&c%5B%5D=assigned_to&c%5B%5D=updated_on&group_by=tracker) * [Known issues](http://bugs.openmw.org/projects/openmw/issues?utf8=%E2%9C%93&set_filter=1&f%5B%5D=status_id&op%5Bstatus_id%5D=%3D&v%5Bstatus_id%5D%5B%5D=7&f%5B%5D=tracker_id&op%5Btracker_id%5D=%3D&v%5Btracker_id%5D%5B%5D=1&f%5B%5D=&c%5B%5D=project&c%5B%5D=tracker&c%5B%5D=status&c%5B%5D=priority&c%5B%5D=subject&c%5B%5D=assigned_to&c%5B%5D=updated_on&group_by=tracker)
The data path The data path
------------- -------------
@ -68,9 +68,9 @@ Command line options
of the blacklist is enabled) of the blacklist is enabled)
--script-blacklist-use [=arg(=1)] (=1) --script-blacklist-use [=arg(=1)] (=1)
enable script blacklisting enable script blacklisting
--load-savegame arg load a save game file on game startup --load-savegame arg load a save game file on game startup
(specify an absolute filename or a (specify an absolute filename or a
filename relative to the current filename relative to the current
working directory) working directory)
--skip-menu [=arg(=1)] (=0) skip main menu on game startup --skip-menu [=arg(=1)] (=0) skip main menu on game startup
--new-game [=arg(=1)] (=0) run new game sequence (ignored if --new-game [=arg(=1)] (=0) run new game sequence (ignored if

View File

@ -460,7 +460,7 @@ int clone(Arguments& info)
for (Stats::iterator it = stats.begin(); it != stats.end(); ++it) for (Stats::iterator it = stats.begin(); it != stats.end(); ++it)
{ {
name.val = it->first; name.val = it->first;
float amount = it->second; int amount = it->second;
std::cout << std::setw(digitCount) << amount << " " << name.toString() << " "; std::cout << std::setw(digitCount) << amount << " " << name.toString() << " ";
if (++i % 3 == 0) if (++i % 3 == 0)

View File

@ -6,6 +6,9 @@
#include <boost/format.hpp> #include <boost/format.hpp>
namespace
{
void printAIPackage(ESM::AIPackage p) void printAIPackage(ESM::AIPackage p)
{ {
std::cout << " AI Type: " << aiTypeLabel(p.mType) std::cout << " AI Type: " << aiTypeLabel(p.mType)
@ -16,7 +19,7 @@ void printAIPackage(ESM::AIPackage p)
std::cout << " Duration: " << p.mWander.mDuration << std::endl; std::cout << " Duration: " << p.mWander.mDuration << std::endl;
std::cout << " Time of Day: " << (int)p.mWander.mTimeOfDay << std::endl; std::cout << " Time of Day: " << (int)p.mWander.mTimeOfDay << std::endl;
if (p.mWander.mShouldRepeat != 1) if (p.mWander.mShouldRepeat != 1)
std::cout << " Should repeat: " << (bool)p.mWander.mShouldRepeat << std::endl; std::cout << " Should repeat: " << (bool)(p.mWander.mShouldRepeat != 0) << std::endl;
std::cout << " Idle: "; std::cout << " Idle: ";
for (int i = 0; i != 8; i++) for (int i = 0; i != 8; i++)
@ -149,6 +152,26 @@ void printEffectList(ESM::EffectList effects)
} }
} }
void printTransport(const std::vector<ESM::Transport::Dest>& transport)
{
std::vector<ESM::Transport::Dest>::const_iterator dit;
for (dit = transport.begin(); dit != transport.end(); ++dit)
{
std::cout << " Destination Position: "
<< boost::format("%12.3f") % dit->mPos.pos[0] << ","
<< boost::format("%12.3f") % dit->mPos.pos[1] << ","
<< boost::format("%12.3f") % dit->mPos.pos[2] << ")" << std::endl;
std::cout << " Destination Rotation: "
<< boost::format("%9.6f") % dit->mPos.rot[0] << ","
<< boost::format("%9.6f") % dit->mPos.rot[1] << ","
<< boost::format("%9.6f") % dit->mPos.rot[2] << ")" << std::endl;
if (dit->mCellName != "")
std::cout << " Destination Cell: " << dit->mCellName << std::endl;
}
}
}
namespace EsmTool { namespace EsmTool {
RecordBase * RecordBase *
@ -631,6 +654,8 @@ void Record<ESM::Creature>::print()
for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit) for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit)
std::cout << " Spell: " << *sit << std::endl; std::cout << " Spell: " << *sit << std::endl;
printTransport(mData.getTransport());
std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl; std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl;
std::cout << " AI Hello:" << (int)mData.mAiData.mHello << std::endl; std::cout << " AI Hello:" << (int)mData.mAiData.mHello << std::endl;
std::cout << " AI Fight:" << (int)mData.mAiData.mFight << std::endl; std::cout << " AI Fight:" << (int)mData.mAiData.mFight << std::endl;
@ -1042,20 +1067,7 @@ void Record<ESM::NPC>::print()
for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit) for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit)
std::cout << " Spell: " << *sit << std::endl; std::cout << " Spell: " << *sit << std::endl;
std::vector<ESM::NPC::Dest>::iterator dit; printTransport(mData.getTransport());
for (dit = mData.mTransport.begin(); dit != mData.mTransport.end(); ++dit)
{
std::cout << " Destination Position: "
<< boost::format("%12.3f") % dit->mPos.pos[0] << ","
<< boost::format("%12.3f") % dit->mPos.pos[1] << ","
<< boost::format("%12.3f") % dit->mPos.pos[2] << ")" << std::endl;
std::cout << " Destination Rotation: "
<< boost::format("%9.6f") % dit->mPos.rot[0] << ","
<< boost::format("%9.6f") % dit->mPos.rot[1] << ","
<< boost::format("%9.6f") % dit->mPos.rot[2] << ")" << std::endl;
if (dit->mCellName != "")
std::cout << " Destination Cell: " << dit->mCellName << std::endl;
}
std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl; std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl;
std::cout << " AI Hello:" << (int)mData.mAiData.mHello << std::endl; std::cout << " AI Hello:" << (int)mData.mAiData.mHello << std::endl;
@ -1253,7 +1265,7 @@ void Record<ESM::Spell>::print()
template<> template<>
void Record<ESM::StartScript>::print() void Record<ESM::StartScript>::print()
{ {
std::cout << "Start Script: " << mData.mScript << std::endl; std::cout << "Start Script: " << mData.mId << std::endl;
std::cout << "Start Data: " << mData.mData << std::endl; std::cout << "Start Data: " << mData.mData << std::endl;
} }

View File

@ -23,18 +23,18 @@ namespace ESSImport
} }
for (int i=0; i<8; ++i) for (int i=0; i<8; ++i)
{ {
cStats.mAttributes[i].mBase = acdt.mAttributes[i][1]; cStats.mAttributes[i].mBase = static_cast<int>(acdt.mAttributes[i][1]);
cStats.mAttributes[i].mMod = acdt.mAttributes[i][0]; cStats.mAttributes[i].mMod = static_cast<int>(acdt.mAttributes[i][0]);
cStats.mAttributes[i].mCurrent = acdt.mAttributes[i][0]; cStats.mAttributes[i].mCurrent = static_cast<int>(acdt.mAttributes[i][0]);
} }
cStats.mGoldPool = acdt.mGoldPool; cStats.mGoldPool = acdt.mGoldPool;
cStats.mTalkedTo = acdt.mFlags & TalkedToPlayer; cStats.mTalkedTo = (acdt.mFlags & TalkedToPlayer) != 0;
cStats.mAttacked = acdt.mFlags & Attacked; cStats.mAttacked = (acdt.mFlags & Attacked) != 0;
} }
void convertACSC (const ACSC& acsc, ESM::CreatureStats& cStats) void convertACSC (const ACSC& acsc, ESM::CreatureStats& cStats)
{ {
cStats.mDead = acsc.mFlags & Dead; cStats.mDead = (acsc.mFlags & Dead) != 0;
} }
void convertNpcData (const ActorData& actorData, ESM::NpcStats& npcStats) void convertNpcData (const ActorData& actorData, ESM::NpcStats& npcStats)

View File

@ -553,7 +553,7 @@ public:
ESM::WeatherState weather; ESM::WeatherState weather;
weather.mCurrentWeather = toString(mGame.mGMDT.mCurrentWeather); weather.mCurrentWeather = toString(mGame.mGMDT.mCurrentWeather);
weather.mNextWeather = toString(mGame.mGMDT.mNextWeather); weather.mNextWeather = toString(mGame.mGMDT.mNextWeather);
weather.mRemainingTransitionTime = mGame.mGMDT.mWeatherTransition/100.f*(0.015*24*3600); weather.mRemainingTransitionTime = mGame.mGMDT.mWeatherTransition/100.f*(0.015f*24*3600);
weather.mHour = mContext->mHour; weather.mHour = mContext->mHour;
weather.mWindSpeed = 0.f; weather.mWindSpeed = 0.f;
weather.mTimePassed = 0.0; weather.mTimePassed = 0.0;

View File

@ -43,7 +43,7 @@ namespace ESSImport
{ {
unsigned int deleted; unsigned int deleted;
esm.getHT(deleted); esm.getHT(deleted);
mDeleted = (deleted >> 24) & 0x2; // the other 3 bytes seem to be uninitialized garbage mDeleted = ((deleted >> 24) & 0x2) != 0; // the other 3 bytes seem to be uninitialized garbage
} }
if (esm.isNextSub("MVRF")) if (esm.isNextSub("MVRF"))

View File

@ -903,4 +903,4 @@ std::time_t MwIniImporter::lastWriteTime(const boost::filesystem::path& filename
std::cout << "content file: " << filename << " not found" << std::endl; std::cout << "content file: " << filename << " not found" << std::endl;
} }
return writeTime; return writeTime;
} }

View File

@ -110,7 +110,7 @@ int wmain(int argc, wchar_t *wargv[]) {
std::cerr << "cfg file does not exist" << std::endl; std::cerr << "cfg file does not exist" << std::endl;
MwIniImporter importer; MwIniImporter importer;
importer.setVerbose(vm.count("verbose")); importer.setVerbose(vm.count("verbose") != 0);
// Font encoding settings // Font encoding settings
std::string encoding(vm["encoding"].as<std::string>()); std::string encoding(vm["encoding"].as<std::string>());

View File

@ -5,7 +5,7 @@ set (OPENCS_SRC main.cpp
opencs_units (. editor) opencs_units (. editor)
opencs_units (model/doc opencs_units (model/doc
document operation saving documentmanager loader runner document operation saving documentmanager loader runner operationholder
) )
opencs_units_noqt (model/doc opencs_units_noqt (model/doc
@ -40,6 +40,7 @@ opencs_units (model/tools
opencs_units_noqt (model/tools opencs_units_noqt (model/tools
mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck
startscriptcheck search searchoperation searchstage
) )
@ -91,7 +92,7 @@ opencs_hdrs_noqt (view/render
opencs_units (view/tools opencs_units (view/tools
reportsubview reporttable reportsubview reporttable searchsubview searchbox
) )
opencs_units_noqt (view/tools opencs_units_noqt (view/tools
@ -165,7 +166,8 @@ qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI})
qt4_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT}) qt4_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT})
qt4_add_resources(OPENCS_RES_SRC ${OPENCS_RES}) qt4_add_resources(OPENCS_RES_SRC ${OPENCS_RES})
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${BULLET_INCLUDE_DIRS}) # for compiled .ui files
include_directories(${CMAKE_CURRENT_BINARY_DIR})
if(APPLE) if(APPLE)
set (OPENCS_MAC_ICON ${CMAKE_SOURCE_DIR}/files/mac/openmw-cs.icns) set (OPENCS_MAC_ICON ${CMAKE_SOURCE_DIR}/files/mac/openmw-cs.icns)
@ -175,7 +177,6 @@ endif(APPLE)
add_executable(openmw-cs add_executable(openmw-cs
MACOSX_BUNDLE MACOSX_BUNDLE
${OENGINE_BULLET}
${OPENCS_SRC} ${OPENCS_SRC}
${OPENCS_UI_HDR} ${OPENCS_UI_HDR}
${OPENCS_MOC_SRC} ${OPENCS_MOC_SRC}
@ -199,6 +200,7 @@ if(APPLE)
endif(APPLE) endif(APPLE)
target_link_libraries(openmw-cs target_link_libraries(openmw-cs
${OENGINE_LIBRARY}
${OGRE_LIBRARIES} ${OGRE_LIBRARIES}
${OGRE_Overlay_LIBRARIES} ${OGRE_Overlay_LIBRARIES}
${OGRE_STATIC_PLUGINS} ${OGRE_STATIC_PLUGINS}

View File

@ -28,4 +28,4 @@ void CSMDoc::Blacklist::add (CSMWorld::UniversalId::Type type,
std::transform (ids.begin(), ids.end(), list.begin()+size, Misc::StringUtils::lowerCase); std::transform (ids.begin(), ids.end(), list.begin()+size, Misc::StringUtils::lowerCase);
std::sort (list.begin(), list.end()); std::sort (list.begin(), list.end());
} }

View File

@ -2254,7 +2254,8 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
mTools (*this), mResDir(resDir), mTools (*this), mResDir(resDir),
mProjectPath ((configuration.getUserDataPath() / "projects") / mProjectPath ((configuration.getUserDataPath() / "projects") /
(savePath.filename().string() + ".project")), (savePath.filename().string() + ".project")),
mSaving (*this, mProjectPath, encoding), mSavingOperation (*this, mProjectPath, encoding),
mSaving (&mSavingOperation),
mRunner (mProjectPath), mPhysics(boost::shared_ptr<CSVWorld::PhysicsSystem>()) mRunner (mProjectPath), mPhysics(boost::shared_ptr<CSVWorld::PhysicsSystem>())
{ {
if (mContentFiles.empty()) if (mContentFiles.empty())
@ -2373,6 +2374,17 @@ CSMWorld::UniversalId CSMDoc::Document::verify()
return id; return id;
} }
CSMWorld::UniversalId CSMDoc::Document::newSearch()
{
return mTools.newSearch();
}
void CSMDoc::Document::runSearch (const CSMWorld::UniversalId& searchId, const CSMTools::Search& search)
{
return mTools.runSearch (searchId, search);
}
void CSMDoc::Document::abortOperation (int type) void CSMDoc::Document::abortOperation (int type)
{ {
if (type==State_Saving) if (type==State_Saving)

View File

@ -20,6 +20,7 @@
#include "saving.hpp" #include "saving.hpp"
#include "blacklist.hpp" #include "blacklist.hpp"
#include "runner.hpp" #include "runner.hpp"
#include "operationholder.hpp"
class QAbstractItemModel; class QAbstractItemModel;
@ -32,7 +33,7 @@ namespace ESM
namespace Files namespace Files
{ {
class ConfigurationManager; struct ConfigurationManager;
} }
namespace CSMWorld namespace CSMWorld
@ -59,7 +60,8 @@ namespace CSMDoc
CSMWorld::Data mData; CSMWorld::Data mData;
CSMTools::Tools mTools; CSMTools::Tools mTools;
boost::filesystem::path mProjectPath; boost::filesystem::path mProjectPath;
Saving mSaving; Saving mSavingOperation;
OperationHolder mSaving;
boost::filesystem::path mResDir; boost::filesystem::path mResDir;
Blacklist mBlacklist; Blacklist mBlacklist;
Runner mRunner; Runner mRunner;
@ -118,6 +120,10 @@ namespace CSMDoc
CSMWorld::UniversalId verify(); CSMWorld::UniversalId verify();
CSMWorld::UniversalId newSearch();
void runSearch (const CSMWorld::UniversalId& searchId, const CSMTools::Search& search);
void abortOperation (int type); void abortOperation (int type);
const CSMWorld::Data& getData() const; const CSMWorld::Data& getData() const;

View File

@ -107,4 +107,4 @@ void CSMDoc::DocumentManager::documentNotLoaded (Document *document, const std::
if (error.empty()) // do not remove the document yet, if we have an error if (error.empty()) // do not remove the document yet, if we have an error
removeDocument (document); removeDocument (document);
} }

View File

@ -17,7 +17,7 @@
namespace Files namespace Files
{ {
class ConfigurationManager; struct ConfigurationManager;
} }
namespace CSMDoc namespace CSMDoc
@ -50,7 +50,7 @@ namespace CSMDoc
///< \param new_ Do not load the last content file in \a files and instead create in an ///< \param new_ Do not load the last content file in \a files and instead create in an
/// appropriate way. /// appropriate way.
void setResourceDir (const boost::filesystem::path& parResDir); void setResourceDir (const boost::filesystem::path& parResDir);
void setEncoding (ToUTF8::FromType encoding); void setEncoding (ToUTF8::FromType encoding);
@ -61,7 +61,7 @@ namespace CSMDoc
private: private:
boost::filesystem::path mResDir; boost::filesystem::path mResDir;
private slots: private slots:
@ -99,4 +99,4 @@ namespace CSMDoc
}; };
} }
#endif #endif

View File

@ -25,4 +25,4 @@ CSMDoc::Messages::Iterator CSMDoc::Messages::begin() const
CSMDoc::Messages::Iterator CSMDoc::Messages::end() const CSMDoc::Messages::Iterator CSMDoc::Messages::end() const
{ {
return mMessages.end(); return mMessages.end();
} }

View File

@ -29,9 +29,9 @@ void CSMDoc::Operation::prepareStages()
CSMDoc::Operation::Operation (int type, bool ordered, bool finalAlways) CSMDoc::Operation::Operation (int type, bool ordered, bool finalAlways)
: mType (type), mStages(std::vector<std::pair<Stage *, int> >()), mCurrentStage(mStages.begin()), : mType (type), mStages(std::vector<std::pair<Stage *, int> >()), mCurrentStage(mStages.begin()),
mCurrentStep(0), mCurrentStepTotal(0), mTotalSteps(0), mOrdered (ordered), mCurrentStep(0), mCurrentStepTotal(0), mTotalSteps(0), mOrdered (ordered),
mFinalAlways (finalAlways), mError(false) mFinalAlways (finalAlways), mError(false), mConnected (false)
{ {
connect (this, SIGNAL (finished()), this, SLOT (operationDone())); mTimer = new QTimer (this);
} }
CSMDoc::Operation::~Operation() CSMDoc::Operation::~Operation()
@ -42,15 +42,17 @@ CSMDoc::Operation::~Operation()
void CSMDoc::Operation::run() void CSMDoc::Operation::run()
{ {
mTimer->stop();
if (!mConnected)
{
connect (mTimer, SIGNAL (timeout()), this, SLOT (executeStage()));
mConnected = true;
}
prepareStages(); prepareStages();
QTimer timer; mTimer->start (0);
timer.connect (&timer, SIGNAL (timeout()), this, SLOT (executeStage()));
timer.start (0);
exec();
} }
void CSMDoc::Operation::appendStage (Stage *stage) void CSMDoc::Operation::appendStage (Stage *stage)
@ -65,7 +67,7 @@ bool CSMDoc::Operation::hasError() const
void CSMDoc::Operation::abort() void CSMDoc::Operation::abort()
{ {
if (!isRunning()) if (!mTimer->isActive())
return; return;
mError = true; mError = true;
@ -116,10 +118,11 @@ void CSMDoc::Operation::executeStage()
emit reportMessage (iter->mId, iter->mMessage, iter->mHint, mType); emit reportMessage (iter->mId, iter->mMessage, iter->mHint, mType);
if (mCurrentStage==mStages.end()) if (mCurrentStage==mStages.end())
exit(); operationDone();
} }
void CSMDoc::Operation::operationDone() void CSMDoc::Operation::operationDone()
{ {
mTimer->stop();
emit done (mType, mError); emit done (mType, mError);
} }

View File

@ -3,7 +3,8 @@
#include <vector> #include <vector>
#include <QThread> #include <QObject>
#include <QTimer>
namespace CSMWorld namespace CSMWorld
{ {
@ -14,7 +15,7 @@ namespace CSMDoc
{ {
class Stage; class Stage;
class Operation : public QThread class Operation : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -27,6 +28,8 @@ namespace CSMDoc
int mOrdered; int mOrdered;
bool mFinalAlways; bool mFinalAlways;
bool mError; bool mError;
bool mConnected;
QTimer *mTimer;
void prepareStages(); void prepareStages();
@ -38,8 +41,6 @@ namespace CSMDoc
virtual ~Operation(); virtual ~Operation();
virtual void run();
void appendStage (Stage *stage); void appendStage (Stage *stage);
///< The ownership of \a stage is transferred to *this. ///< The ownership of \a stage is transferred to *this.
/// ///
@ -60,6 +61,8 @@ namespace CSMDoc
void abort(); void abort();
void run();
private slots: private slots:
void executeStage(); void executeStage();
@ -68,4 +71,4 @@ namespace CSMDoc
}; };
} }
#endif #endif

View File

@ -0,0 +1,65 @@
#include "operationholder.hpp"
#include "operation.hpp"
CSMDoc::OperationHolder::OperationHolder (Operation *operation) : mRunning (false)
{
if (operation)
setOperation (operation);
}
void CSMDoc::OperationHolder::setOperation (Operation *operation)
{
mOperation = operation;
mOperation->moveToThread (&mThread);
connect (
mOperation, SIGNAL (progress (int, int, int)),
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)));
connect (
mOperation, SIGNAL (done (int, bool)),
this, SLOT (doneSlot (int, bool)));
connect (this, SIGNAL (abortSignal()), mOperation, SLOT (abort()));
connect (&mThread, SIGNAL (started()), mOperation, SLOT (run()));
}
bool CSMDoc::OperationHolder::isRunning() const
{
return mRunning;
}
void CSMDoc::OperationHolder::start()
{
mRunning = true;
mThread.start();
}
void CSMDoc::OperationHolder::abort()
{
mRunning = false;
emit abortSignal();
}
void CSMDoc::OperationHolder::abortAndWait()
{
if (mRunning)
{
mThread.quit();
mThread.wait();
}
}
void CSMDoc::OperationHolder::doneSlot (int type, bool failed)
{
mRunning = false;
mThread.quit();
emit done (type, failed);
}

View File

@ -0,0 +1,56 @@
#ifndef CSM_DOC_OPERATIONHOLDER_H
#define CSM_DOC_OPERATIONHOLDER_H
#include <QObject>
#include <QThread>
namespace CSMWorld
{
class UniversalId;
}
namespace CSMDoc
{
class Operation;
class OperationHolder : public QObject
{
Q_OBJECT
QThread mThread;
Operation *mOperation;
bool mRunning;
public:
OperationHolder (Operation *operation = 0);
void setOperation (Operation *operation);
bool isRunning() const;
void start();
void abort();
// Abort and wait until thread has finished.
void abortAndWait();
private slots:
void doneSlot (int type, bool failed);
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 done (int type, bool failed);
void abortSignal();
};
}
#endif

View File

@ -6,7 +6,7 @@
#include <QTemporaryFile> #include <QTemporaryFile>
#include <QTextStream> #include <QTextStream>
#include "operation.hpp" #include "operationholder.hpp"
CSMDoc::Runner::Runner (const boost::filesystem::path& projectPath) CSMDoc::Runner::Runner (const boost::filesystem::path& projectPath)
: mRunning (false), mStartup (0), mProjectPath (projectPath) : mRunning (false), mStartup (0), mProjectPath (projectPath)
@ -145,7 +145,7 @@ void CSMDoc::Runner::readyReadStandardOutput()
} }
CSMDoc::SaveWatcher::SaveWatcher (Runner *runner, Operation *operation) CSMDoc::SaveWatcher::SaveWatcher (Runner *runner, OperationHolder *operation)
: QObject (runner), mRunner (runner) : QObject (runner), mRunner (runner)
{ {
connect (operation, SIGNAL (done (int, bool)), this, SLOT (saveDone (int, bool))); connect (operation, SIGNAL (done (int, bool)), this, SLOT (saveDone (int, bool)));

View File

@ -16,6 +16,8 @@ class QTemporaryFile;
namespace CSMDoc namespace CSMDoc
{ {
class OperationHolder;
class Runner : public QObject class Runner : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -74,7 +76,7 @@ namespace CSMDoc
public: public:
/// *this attaches itself to runner /// *this attaches itself to runner
SaveWatcher (Runner *runner, Operation *operation); SaveWatcher (Runner *runner, OperationHolder *operation);
private slots: private slots:

View File

@ -78,6 +78,9 @@ CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& proje
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::MagicEffect> > appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::MagicEffect> >
(mDocument.getData().getMagicEffects(), mState)); (mDocument.getData().getMagicEffects(), mState));
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::StartScript> >
(mDocument.getData().getStartScripts(), mState));
appendStage (new WriteDialogueCollectionStage (mDocument, mState, false)); appendStage (new WriteDialogueCollectionStage (mDocument, mState, false));
appendStage (new WriteDialogueCollectionStage (mDocument, mState, true)); appendStage (new WriteDialogueCollectionStage (mDocument, mState, true));
@ -90,8 +93,12 @@ CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& proje
appendStage (new WritePathgridCollectionStage (mDocument, mState)); appendStage (new WritePathgridCollectionStage (mDocument, mState));
appendStage (new WriteLandCollectionStage (mDocument, mState));
appendStage (new WriteLandTextureCollectionStage (mDocument, mState));
// close file and clean up // close file and clean up
appendStage (new CloseSaveStage (mState)); appendStage (new CloseSaveStage (mState));
appendStage (new FinalSavingStage (mDocument, mState)); appendStage (new FinalSavingStage (mDocument, mState));
} }

View File

@ -90,7 +90,7 @@ void CSMDoc::WriteHeaderStage::perform (int stage, Messages& messages)
CSMDoc::WriteDialogueCollectionStage::WriteDialogueCollectionStage (Document& document, CSMDoc::WriteDialogueCollectionStage::WriteDialogueCollectionStage (Document& document,
SavingState& state, bool journal) SavingState& state, bool journal)
: mDocument (document), mState (state), : mState (state),
mTopics (journal ? document.getData().getJournals() : document.getData().getTopics()), mTopics (journal ? document.getData().getJournals() : document.getData().getTopics()),
mInfos (journal ? document.getData().getJournalInfos() : document.getData().getTopicInfos()) mInfos (journal ? document.getData().getJournalInfos() : document.getData().getTopicInfos())
{} {}
@ -353,6 +353,74 @@ void CSMDoc::WritePathgridCollectionStage::perform (int stage, Messages& message
} }
CSMDoc::WriteLandCollectionStage::WriteLandCollectionStage (Document& document,
SavingState& state)
: mDocument (document), mState (state)
{}
int CSMDoc::WriteLandCollectionStage::setup()
{
return mDocument.getData().getLand().getSize();
}
void CSMDoc::WriteLandCollectionStage::perform (int stage, Messages& messages)
{
const CSMWorld::Record<CSMWorld::Land>& land =
mDocument.getData().getLand().getRecord (stage);
if (land.mState==CSMWorld::RecordBase::State_Modified ||
land.mState==CSMWorld::RecordBase::State_ModifiedOnly)
{
CSMWorld::Land record = land.get();
mState.getWriter().startRecord (record.mLand->sRecordId);
record.mLand->save (mState.getWriter());
if(record.mLand->mLandData)
record.mLand->mLandData->save (mState.getWriter());
mState.getWriter().endRecord (record.mLand->sRecordId);
}
else if (land.mState==CSMWorld::RecordBase::State_Deleted)
{
/// \todo write record with delete flag
}
}
CSMDoc::WriteLandTextureCollectionStage::WriteLandTextureCollectionStage (Document& document,
SavingState& state)
: mDocument (document), mState (state)
{}
int CSMDoc::WriteLandTextureCollectionStage::setup()
{
return mDocument.getData().getLandTextures().getSize();
}
void CSMDoc::WriteLandTextureCollectionStage::perform (int stage, Messages& messages)
{
const CSMWorld::Record<CSMWorld::LandTexture>& landTexture =
mDocument.getData().getLandTextures().getRecord (stage);
if (landTexture.mState==CSMWorld::RecordBase::State_Modified ||
landTexture.mState==CSMWorld::RecordBase::State_ModifiedOnly)
{
CSMWorld::LandTexture record = landTexture.get();
mState.getWriter().startRecord (record.sRecordId);
record.save (mState.getWriter());
mState.getWriter().endRecord (record.sRecordId);
}
else if (landTexture.mState==CSMWorld::RecordBase::State_Deleted)
{
/// \todo write record with delete flag
}
}
CSMDoc::CloseSaveStage::CloseSaveStage (SavingState& state) CSMDoc::CloseSaveStage::CloseSaveStage (SavingState& state)
: mState (state) : mState (state)
{} {}

View File

@ -7,6 +7,8 @@
#include "../world/idcollection.hpp" #include "../world/idcollection.hpp"
#include "../world/scope.hpp" #include "../world/scope.hpp"
#include <components/esm/defs.hpp>
#include "savingstate.hpp" #include "savingstate.hpp"
namespace ESM namespace ESM
@ -103,8 +105,15 @@ namespace CSMDoc
if (state==CSMWorld::RecordBase::State_Modified || if (state==CSMWorld::RecordBase::State_Modified ||
state==CSMWorld::RecordBase::State_ModifiedOnly) state==CSMWorld::RecordBase::State_ModifiedOnly)
{ {
mState.getWriter().startRecord (mCollection.getRecord (stage).mModified.sRecordId); // FIXME: A quick Workaround to support records which should not write
mState.getWriter().writeHNCString ("NAME", mCollection.getId (stage)); // NAME, including SKIL, MGEF and SCPT. If there are many more
// idcollection records that doesn't use NAME then a more generic
// solution may be required.
uint32_t name = mCollection.getRecord (stage).mModified.sRecordId;
mState.getWriter().startRecord (name);
if(name != ESM::REC_SKIL && name != ESM::REC_MGEF && name != ESM::REC_SCPT)
mState.getWriter().writeHNCString ("NAME", mCollection.getId (stage));
mCollection.getRecord (stage).mModified.save (mState.getWriter()); mCollection.getRecord (stage).mModified.save (mState.getWriter());
mState.getWriter().endRecord (mCollection.getRecord (stage).mModified.sRecordId); mState.getWriter().endRecord (mCollection.getRecord (stage).mModified.sRecordId);
} }
@ -117,7 +126,6 @@ namespace CSMDoc
class WriteDialogueCollectionStage : public Stage class WriteDialogueCollectionStage : public Stage
{ {
Document& mDocument;
SavingState& mState; SavingState& mState;
const CSMWorld::IdCollection<ESM::Dialogue>& mTopics; const CSMWorld::IdCollection<ESM::Dialogue>& mTopics;
CSMWorld::InfoCollection& mInfos; CSMWorld::InfoCollection& mInfos;
@ -200,6 +208,40 @@ namespace CSMDoc
///< Messages resulting from this stage will be appended to \a messages. ///< Messages resulting from this stage will be appended to \a messages.
}; };
class WriteLandCollectionStage : public Stage
{
Document& mDocument;
SavingState& mState;
public:
WriteLandCollectionStage (Document& document, SavingState& state);
virtual int setup();
///< \return number of steps
virtual void perform (int stage, Messages& messages);
///< Messages resulting from this stage will be appended to \a messages.
};
class WriteLandTextureCollectionStage : public Stage
{
Document& mDocument;
SavingState& mState;
public:
WriteLandTextureCollectionStage (Document& document, SavingState& state);
virtual int setup();
///< \return number of steps
virtual void perform (int stage, Messages& messages);
///< Messages resulting from this stage will be appended to \a messages.
};
class CloseSaveStage : public Stage class CloseSaveStage : public Stage
{ {
SavingState& mState; SavingState& mState;

View File

@ -1,4 +1,4 @@
#include "stage.hpp" #include "stage.hpp"
CSMDoc::Stage::~Stage() {} CSMDoc::Stage::~Stage() {}

View File

@ -13,7 +13,7 @@ namespace CSMDoc
State_Saving = 16, State_Saving = 16,
State_Verifying = 32, State_Verifying = 32,
State_Compiling = 64, // not implemented yet State_Compiling = 64, // not implemented yet
State_Searching = 128, // not implemented yet State_Searching = 128,
State_Loading = 256 // pseudo-state; can not be encountered in a loaded document State_Loading = 256 // pseudo-state; can not be encountered in a loaded document
}; };
} }

View File

@ -12,4 +12,4 @@ bool CSMFilter::BooleanNode::test (const CSMWorld::IdTableBase& table, int row,
std::string CSMFilter::BooleanNode::toString (bool numericColumns) const std::string CSMFilter::BooleanNode::toString (bool numericColumns) const
{ {
return mTrue ? "true" : "false"; return mTrue ? "true" : "false";
} }

View File

@ -26,4 +26,4 @@ namespace CSMFilter
}; };
} }
#endif #endif

View File

@ -3,4 +3,4 @@
CSMFilter::Node::Node() {} CSMFilter::Node::Node() {}
CSMFilter::Node::~Node() {} CSMFilter::Node::~Node() {}

View File

@ -7,4 +7,4 @@ bool CSMFilter::NotNode::test (const CSMWorld::IdTableBase& table, int row,
const std::map<int, int>& columns) const const std::map<int, int>& columns) const
{ {
return !getChild().test (table, row, columns); return !getChild().test (table, row, columns);
} }

View File

@ -82,4 +82,4 @@ std::string CSMFilter::TextNode::toString (bool numericColumns) const
stream << ", \"" << mText << "\")"; stream << ", \"" << mText << "\")";
return stream.str(); return stream.str();
} }

View File

@ -23,4 +23,4 @@ std::vector<int> CSMFilter::UnaryNode::getReferencedColumns() const
std::string CSMFilter::UnaryNode::toString (bool numericColumns) const std::string CSMFilter::UnaryNode::toString (bool numericColumns) const
{ {
return mName + " " + mChild->toString (numericColumns); return mName + " " + mChild->toString (numericColumns);
} }

View File

@ -94,4 +94,4 @@ std::string CSMFilter::ValueNode::toString (bool numericColumns) const
stream << ")"; stream << ")";
return stream.str(); return stream.str();
} }

View File

@ -208,6 +208,21 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
shiftCtrlDoubleClick->setToolTip ("Action on shift control double click in table:<p>" + toolTip); shiftCtrlDoubleClick->setToolTip ("Action on shift control double click in table:<p>" + toolTip);
} }
declareSection ("search", "Search & Replace");
{
Setting *before = createSetting (Type_SpinBox, "char-before",
"Characters before search string");
before->setDefaultValue (10);
before->setRange (0, 1000);
before->setToolTip ("Maximum number of character to display in search result before the searched text");
Setting *after = createSetting (Type_SpinBox, "char-after",
"Characters after search string");
after->setDefaultValue (10);
after->setRange (0, 1000);
after->setToolTip ("Maximum number of character to display in search result after the searched text");
}
{ {
/****************************************************************** /******************************************************************
* There are three types of values: * There are three types of values:

View File

@ -41,4 +41,4 @@ void CSMTools::BirthsignCheckStage::perform (int stage, CSMDoc::Messages& messag
/// \todo test if the texture exists /// \todo test if the texture exists
/// \todo check data members that can't be edited in the table view /// \todo check data members that can't be edited in the table view
} }

View File

@ -32,4 +32,4 @@ namespace CSMTools
}; };
} }
#endif #endif

View File

@ -65,4 +65,4 @@ void CSMTools::ClassCheckStage::perform (int stage, CSMDoc::Messages& messages)
messages.push_back (std::make_pair (id, messages.push_back (std::make_pair (id,
ESM::Skill::indexToId (iter->first) + " is listed more than once")); ESM::Skill::indexToId (iter->first) + " is listed more than once"));
} }
} }

View File

@ -20,4 +20,4 @@ void CSMTools::MandatoryIdStage::perform (int stage, CSMDoc::Messages& messages)
if (mIdCollection.searchId (mIds.at (stage))==-1 || if (mIdCollection.searchId (mIds.at (stage))==-1 ||
mIdCollection.getRecord (mIds.at (stage)).isDeleted()) mIdCollection.getRecord (mIds.at (stage)).isDeleted())
messages.add (mCollectionId, "Missing mandatory record: " + mIds.at (stage)); messages.add (mCollectionId, "Missing mandatory record: " + mIds.at (stage));
} }

View File

@ -70,4 +70,4 @@ void CSMTools::RaceCheckStage::perform (int stage, CSMDoc::Messages& messages)
performFinal (messages); performFinal (messages);
else else
performPerRecord (stage, messages); performPerRecord (stage, messages);
} }

View File

@ -48,10 +48,6 @@ void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages &message
} }
} }
// Check if referenced object is in valid cell
if (mCells.searchId(cellRef.mCell) == -1)
messages.push_back(std::make_pair(id, " is referencing object from non existing cell " + cellRef.mCell));
// If object have owner, check if that owner reference is valid // If object have owner, check if that owner reference is valid
if (!cellRef.mOwner.empty() && mReferencables.searchId(cellRef.mOwner) == -1) if (!cellRef.mOwner.empty() && mReferencables.searchId(cellRef.mOwner) == -1)
messages.push_back(std::make_pair(id, " has non existing owner " + cellRef.mOwner)); messages.push_back(std::make_pair(id, " has non existing owner " + cellRef.mOwner));
@ -70,9 +66,9 @@ void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages &message
// Check item's faction rank // Check item's faction rank
if (hasFaction && cellRef.mFactionRank < -1) if (hasFaction && cellRef.mFactionRank < -1)
messages.push_back(std::make_pair(id, " has faction set but has invalid faction rank " + cellRef.mFactionRank)); messages.push_back(std::make_pair(id, " has faction set but has invalid faction rank " + boost::lexical_cast<std::string>(cellRef.mFactionRank)));
else if (!hasFaction && cellRef.mFactionRank != -2) else if (!hasFaction && cellRef.mFactionRank != -2)
messages.push_back(std::make_pair(id, " has invalid faction rank " + cellRef.mFactionRank)); messages.push_back(std::make_pair(id, " has invalid faction rank " + boost::lexical_cast<std::string>(cellRef.mFactionRank)));
// If door have destination cell, check if that reference is valid // If door have destination cell, check if that reference is valid
if (!cellRef.mDestCell.empty()) if (!cellRef.mDestCell.empty())

View File

@ -26,4 +26,4 @@ namespace CSMTools
}; };
} }
#endif // CSM_TOOLS_REFERENCECHECK_H #endif // CSM_TOOLS_REFERENCECHECK_H

View File

@ -35,4 +35,4 @@ void CSMTools::RegionCheckStage::perform (int stage, CSMDoc::Messages& messages)
/// \todo test that the ID in mSleeplist exists /// \todo test that the ID in mSleeplist exists
/// \todo check data members that can't be edited in the table view /// \todo check data members that can't be edited in the table view
} }

View File

@ -2,6 +2,29 @@
#include "reportmodel.hpp" #include "reportmodel.hpp"
#include <stdexcept> #include <stdexcept>
#include <sstream>
#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)
{
if (fieldColumn)
{
mColumnField = 3;
mColumnDescription = 4;
}
else
{
mColumnDescription = 3;
mColumnField = -1;
}
}
int CSMTools::ReportModel::rowCount (const QModelIndex & parent) const int CSMTools::ReportModel::rowCount (const QModelIndex & parent) const
{ {
@ -16,7 +39,7 @@ int CSMTools::ReportModel::columnCount (const QModelIndex & parent) const
if (parent.isValid()) if (parent.isValid())
return 0; return 0;
return 3; return mColumnDescription+1;
} }
QVariant CSMTools::ReportModel::data (const QModelIndex & index, int role) const QVariant CSMTools::ReportModel::data (const QModelIndex & index, int role) const
@ -24,13 +47,49 @@ QVariant CSMTools::ReportModel::data (const QModelIndex & index, int role) const
if (role!=Qt::DisplayRole) if (role!=Qt::DisplayRole)
return QVariant(); return QVariant();
if (index.column()==0) switch (index.column())
return static_cast<int> (mRows.at (index.row()).first.getType()); {
case Column_Type:
if (index.column()==1) return static_cast<int> (mRows.at (index.row()).mId.getType());
return QString::fromUtf8 (mRows.at (index.row()).second.first.c_str());
case Column_Id:
{
CSMWorld::UniversalId id = mRows.at (index.row()).mId;
return QString::fromUtf8 (mRows.at (index.row()).second.second.c_str()); if (id.getArgumentType()==CSMWorld::UniversalId::ArgumentType_Id)
return QString::fromUtf8 (id.getId().c_str());
return QString ("-");
}
case Column_Hint:
return QString::fromUtf8 (mRows.at (index.row()).mHint.c_str());
}
if (index.column()==mColumnDescription)
return QString::fromUtf8 (mRows.at (index.row()).mMessage.c_str());
if (index.column()==mColumnField)
{
std::string field;
std::istringstream stream (mRows.at (index.row()).mHint);
char type, ignore;
int fieldIndex;
if ((stream >> type >> ignore >> fieldIndex) && (type=='r' || type=='R'))
{
field = CSMWorld::Columns::getName (
static_cast<CSMWorld::Columns::ColumnId> (fieldIndex));
}
return QString::fromUtf8 (field.c_str());
}
return QVariant();
} }
QVariant CSMTools::ReportModel::headerData (int section, Qt::Orientation orientation, int role) const QVariant CSMTools::ReportModel::headerData (int section, Qt::Orientation orientation, int role) const
@ -41,13 +100,19 @@ QVariant CSMTools::ReportModel::headerData (int section, Qt::Orientation orienta
if (orientation==Qt::Vertical) if (orientation==Qt::Vertical)
return QVariant(); return QVariant();
if (section==0) switch (section)
return "Type"; {
case Column_Type: return "Type";
case Column_Id: return "ID";
}
if (section==1) if (section==mColumnDescription)
return "Description"; return "Description";
return "Hint"; if (section==mColumnField)
return "Field";
return "-";
} }
bool CSMTools::ReportModel::removeRows (int row, int count, const QModelIndex& parent) bool CSMTools::ReportModel::removeRows (int row, int count, const QModelIndex& parent)
@ -64,18 +129,43 @@ void CSMTools::ReportModel::add (const CSMWorld::UniversalId& id, const std::str
const std::string& hint) const std::string& hint)
{ {
beginInsertRows (QModelIndex(), mRows.size(), mRows.size()); beginInsertRows (QModelIndex(), mRows.size(), mRows.size());
mRows.push_back (std::make_pair (id, std::make_pair (message, hint))); mRows.push_back (Line (id, message, hint));
endInsertRows(); endInsertRows();
} }
void CSMTools::ReportModel::flagAsReplaced (int index)
{
Line& line = mRows.at (index);
std::string hint = line.mHint;
if (hint.empty() || hint[0]!='R')
throw std::logic_error ("trying to flag message as replaced that is not replaceable");
hint[0] = 'r';
line.mHint = hint;
emit dataChanged (this->index (index, 0), this->index (index, columnCount()));
}
const CSMWorld::UniversalId& CSMTools::ReportModel::getUniversalId (int row) const const CSMWorld::UniversalId& CSMTools::ReportModel::getUniversalId (int row) const
{ {
return mRows.at (row).first; return mRows.at (row).mId;
} }
std::string CSMTools::ReportModel::getHint (int row) const std::string CSMTools::ReportModel::getHint (int row) const
{ {
return mRows.at (row).second.second; return mRows.at (row).mHint;
} }
void CSMTools::ReportModel::clear()
{
if (!mRows.empty())
{
beginRemoveRows (QModelIndex(), 0, mRows.size()-1);
mRows.clear();
endRemoveRows();
}
}

View File

@ -14,10 +14,32 @@ namespace CSMTools
{ {
Q_OBJECT Q_OBJECT
std::vector<std::pair<CSMWorld::UniversalId, std::pair<std::string, std::string> > > mRows; 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;
// Fixed columns
enum Columns
{
Column_Type = 0, Column_Id = 1, Column_Hint = 2
};
// Configurable columns
int mColumnDescription;
int mColumnField;
public: public:
ReportModel (bool fieldColumn = false);
virtual int rowCount (const QModelIndex & parent = QModelIndex()) const; virtual int rowCount (const QModelIndex & parent = QModelIndex()) const;
virtual int columnCount (const QModelIndex & parent = QModelIndex()) const; virtual int columnCount (const QModelIndex & parent = QModelIndex()) const;
@ -27,13 +49,17 @@ namespace CSMTools
virtual QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; virtual QVariant headerData (int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex()); virtual bool removeRows (int row, int count, const QModelIndex& parent = QModelIndex());
void add (const CSMWorld::UniversalId& id, const std::string& message, void add (const CSMWorld::UniversalId& id, const std::string& message,
const std::string& hint = ""); const std::string& hint = "");
void flagAsReplaced (int index);
const CSMWorld::UniversalId& getUniversalId (int row) const; const CSMWorld::UniversalId& getUniversalId (int row) const;
std::string getHint (int row) const; std::string getHint (int row) const;
void clear();
}; };
} }

View File

@ -98,4 +98,4 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages)
} }
mMessages = 0; mMessages = 0;
} }

View File

@ -0,0 +1,279 @@
#include "search.hpp"
#include <stdexcept>
#include <sstream>
#include "../doc/messages.hpp"
#include "../doc/document.hpp"
#include "../world/idtablebase.hpp"
#include "../world/columnbase.hpp"
#include "../world/universalid.hpp"
#include "../world/commands.hpp"
void CSMTools::Search::searchTextCell (const CSMWorld::IdTableBase *model,
const QModelIndex& index, const CSMWorld::UniversalId& id, bool writable,
CSMDoc::Messages& messages) const
{
// using QString here for easier handling of case folding.
QString search = QString::fromUtf8 (mText.c_str());
QString text = model->data (index).toString();
int pos = 0;
while ((pos = text.indexOf (search, pos, Qt::CaseInsensitive))!=-1)
{
std::ostringstream hint;
hint
<< (writable ? 'R' : 'r')
<<": "
<< model->getColumnId (index.column())
<< " " << pos
<< " " << search.length();
messages.add (id, formatDescription (text, pos, search.length()).toUtf8().data(), hint.str());
pos += search.length();
}
}
void CSMTools::Search::searchRegExCell (const CSMWorld::IdTableBase *model,
const QModelIndex& index, const CSMWorld::UniversalId& id, bool writable,
CSMDoc::Messages& messages) const
{
QString text = model->data (index).toString();
int pos = 0;
while ((pos = mRegExp.indexIn (text, pos))!=-1)
{
int length = mRegExp.matchedLength();
std::ostringstream hint;
hint
<< (writable ? 'R' : 'r')
<<": "
<< model->getColumnId (index.column())
<< " " << pos
<< " " << length;
messages.add (id, formatDescription (text, pos, length).toUtf8().data(), hint.str());
pos += length;
}
}
void CSMTools::Search::searchRecordStateCell (const CSMWorld::IdTableBase *model,
const QModelIndex& index, const CSMWorld::UniversalId& id, bool writable, CSMDoc::Messages& messages) const
{
if (writable)
throw std::logic_error ("Record state can not be modified by search and replace");
int data = model->data (index).toInt();
if (data==mValue)
{
std::vector<std::string> states =
CSMWorld::Columns::getEnums (CSMWorld::Columns::ColumnId_Modification);
std::ostringstream message;
message << states.at (data);
std::ostringstream hint;
hint << "r: " << model->getColumnId (index.column());
messages.add (id, message.str(), hint.str());
}
}
QString CSMTools::Search::formatDescription (const QString& description, int pos, int length) const
{
QString text (description);
// split
QString highlight = flatten (text.mid (pos, length));
QString before = flatten (mPaddingBefore>=pos ?
text.mid (0, pos) : text.mid (pos-mPaddingBefore, mPaddingBefore));
QString after = flatten (text.mid (pos+length, mPaddingAfter));
// compensate for Windows nonsense
text.remove ('\r');
// join
text = before + "<b>" + highlight + "</b>" + after;
// improve layout for single line display
text.replace ("\n", "&lt;CR>");
text.replace ('\t', ' ');
return text;
}
QString CSMTools::Search::flatten (const QString& text) const
{
QString flat (text);
flat.replace ("&", "&amp;");
flat.replace ("<", "&lt;");
return flat;
}
CSMTools::Search::Search() : mType (Type_None), mPaddingBefore (10), mPaddingAfter (10) {}
CSMTools::Search::Search (Type type, const std::string& value)
: mType (type), mText (value), mPaddingBefore (10), mPaddingAfter (10)
{
if (type!=Type_Text && type!=Type_Id)
throw std::logic_error ("Invalid search parameter (string)");
}
CSMTools::Search::Search (Type type, const QRegExp& value)
: mType (type), mRegExp (value), mPaddingBefore (10), mPaddingAfter (10)
{
if (type!=Type_TextRegEx && type!=Type_IdRegEx)
throw std::logic_error ("Invalid search parameter (RegExp)");
}
CSMTools::Search::Search (Type type, int value)
: mType (type), mValue (value), mPaddingBefore (10), mPaddingAfter (10)
{
if (type!=Type_RecordState)
throw std::logic_error ("invalid search parameter (int)");
}
void CSMTools::Search::configure (const CSMWorld::IdTableBase *model)
{
mColumns.clear();
int columns = model->columnCount();
for (int i=0; i<columns; ++i)
{
CSMWorld::ColumnBase::Display display = static_cast<CSMWorld::ColumnBase::Display> (
model->headerData (
i, Qt::Horizontal, static_cast<int> (CSMWorld::ColumnBase::Role_Display)).toInt());
bool consider = false;
switch (mType)
{
case Type_Text:
case Type_TextRegEx:
if (CSMWorld::ColumnBase::isText (display) ||
CSMWorld::ColumnBase::isScript (display))
{
consider = true;
}
break;
case Type_Id:
case Type_IdRegEx:
if (CSMWorld::ColumnBase::isId (display) ||
CSMWorld::ColumnBase::isScript (display))
{
consider = true;
}
break;
case Type_RecordState:
if (display==CSMWorld::ColumnBase::Display_RecordState)
consider = true;
break;
case Type_None:
break;
}
if (consider)
mColumns.insert (i);
}
mIdColumn = model->findColumnIndex (CSMWorld::Columns::ColumnId_Id);
mTypeColumn = model->findColumnIndex (CSMWorld::Columns::ColumnId_RecordType);
}
void CSMTools::Search::searchRow (const CSMWorld::IdTableBase *model, int row,
CSMDoc::Messages& messages) const
{
for (std::set<int>::const_iterator iter (mColumns.begin()); iter!=mColumns.end(); ++iter)
{
QModelIndex index = model->index (row, *iter);
CSMWorld::UniversalId::Type type = static_cast<CSMWorld::UniversalId::Type> (
model->data (model->index (row, mTypeColumn)).toInt());
CSMWorld::UniversalId id (
type, model->data (model->index (row, mIdColumn)).toString().toUtf8().data());
bool writable = model->flags (index) & Qt::ItemIsEditable;
switch (mType)
{
case Type_Text:
case Type_Id:
searchTextCell (model, index, id, writable, messages);
break;
case Type_TextRegEx:
case Type_IdRegEx:
searchRegExCell (model, index, id, writable, messages);
break;
case Type_RecordState:
searchRecordStateCell (model, index, id, writable, messages);
break;
case Type_None:
break;
}
}
}
void CSMTools::Search::setPadding (int before, int after)
{
mPaddingBefore = before;
mPaddingAfter = after;
}
void CSMTools::Search::replace (CSMDoc::Document& document, CSMWorld::IdTableBase *model,
const CSMWorld::UniversalId& id, const std::string& messageHint,
const std::string& replaceText) const
{
std::istringstream stream (messageHint.c_str());
char hint, ignore;
int columnId, pos, length;
if (stream >> hint >> ignore >> columnId >> pos >> length)
{
int column =
model->findColumnIndex (static_cast<CSMWorld::Columns::ColumnId> (columnId));
QModelIndex index = model->getModelIndex (id.getId(), column);
std::string text = model->data (index).toString().toUtf8().constData();
std::string before = text.substr (0, pos);
std::string after = text.substr (pos+length);
std::string newText = before + replaceText + after;
document.getUndoStack().push (
new CSMWorld::ModifyCommand (*model, index, QString::fromUtf8 (newText.c_str())));
}
}

View File

@ -0,0 +1,96 @@
#ifndef CSM_TOOLS_SEARCH_H
#define CSM_TOOLS_SEARCH_H
#include <string>
#include <set>
#include <QRegExp>
#include <QMetaType>
class QModelIndex;
namespace CSMDoc
{
class Messages;
class Document;
}
namespace CSMWorld
{
class IdTableBase;
class UniversalId;
}
namespace CSMTools
{
class Search
{
public:
enum Type
{
Type_Text = 0,
Type_TextRegEx = 1,
Type_Id = 2,
Type_IdRegEx = 3,
Type_RecordState = 4,
Type_None
};
private:
Type mType;
std::string mText;
QRegExp mRegExp;
int mValue;
std::set<int> mColumns;
int mIdColumn;
int mTypeColumn;
int mPaddingBefore;
int mPaddingAfter;
void searchTextCell (const CSMWorld::IdTableBase *model, const QModelIndex& index,
const CSMWorld::UniversalId& id, bool writable, CSMDoc::Messages& messages) const;
void searchRegExCell (const CSMWorld::IdTableBase *model, const QModelIndex& index,
const CSMWorld::UniversalId& id, bool writable, CSMDoc::Messages& messages) const;
void searchRecordStateCell (const CSMWorld::IdTableBase *model,
const QModelIndex& index, const CSMWorld::UniversalId& id, bool writable,
CSMDoc::Messages& messages) const;
QString formatDescription (const QString& description, int pos, int length) const;
QString flatten (const QString& text) const;
public:
Search();
Search (Type type, const std::string& value);
Search (Type type, const QRegExp& value);
Search (Type type, int value);
// Configure search for the specified model.
void configure (const CSMWorld::IdTableBase *model);
// Search row in \a model and store results in \a messages.
//
// \attention *this needs to be configured for \a model.
void searchRow (const CSMWorld::IdTableBase *model, int row,
CSMDoc::Messages& messages) const;
void setPadding (int before, int after);
// Configuring *this for the model is not necessary when calling this function.
void replace (CSMDoc::Document& document, CSMWorld::IdTableBase *model,
const CSMWorld::UniversalId& id, const std::string& messageHint,
const std::string& replaceText) const;
};
}
Q_DECLARE_METATYPE (CSMTools::Search)
#endif

View File

@ -0,0 +1,40 @@
#include "searchoperation.hpp"
#include "../doc/state.hpp"
#include "../doc/document.hpp"
#include "../world/data.hpp"
#include "../world/idtablebase.hpp"
#include "searchstage.hpp"
CSMTools::SearchOperation::SearchOperation (CSMDoc::Document& document)
: CSMDoc::Operation (CSMDoc::State_Searching, false)
{
std::vector<CSMWorld::UniversalId::Type> types = CSMWorld::UniversalId::listTypes (
CSMWorld::UniversalId::Class_RecordList |
CSMWorld::UniversalId::Class_ResourceList
);
for (std::vector<CSMWorld::UniversalId::Type>::const_iterator iter (types.begin());
iter!=types.end(); ++iter)
appendStage (new SearchStage (&dynamic_cast<CSMWorld::IdTableBase&> (
*document.getData().getTableModel (*iter))));
}
void CSMTools::SearchOperation::configure (const Search& search)
{
mSearch = search;
}
void CSMTools::SearchOperation::appendStage (SearchStage *stage)
{
CSMDoc::Operation::appendStage (stage);
stage->setOperation (this);
}
const CSMTools::Search& CSMTools::SearchOperation::getSearch() const
{
return mSearch;
}

View File

@ -0,0 +1,38 @@
#ifndef CSM_TOOLS_SEARCHOPERATION_H
#define CSM_TOOLS_SEARCHOPERATION_H
#include "../doc/operation.hpp"
#include "search.hpp"
namespace CSMDoc
{
class Document;
}
namespace CSMTools
{
class SearchStage;
class SearchOperation : public CSMDoc::Operation
{
Search mSearch;
public:
SearchOperation (CSMDoc::Document& document);
/// \attention Do not call this function while a search is running.
void configure (const Search& search);
void appendStage (SearchStage *stage);
///< The ownership of \a stage is transferred to *this.
///
/// \attention Do no call this function while this Operation is running.
const Search& getSearch() const;
};
}
#endif

View File

@ -0,0 +1,30 @@
#include "searchstage.hpp"
#include "../world/idtablebase.hpp"
#include "searchoperation.hpp"
CSMTools::SearchStage::SearchStage (const CSMWorld::IdTableBase *model)
: mModel (model), mOperation (0)
{}
int CSMTools::SearchStage::setup()
{
if (mOperation)
mSearch = mOperation->getSearch();
mSearch.configure (mModel);
return mModel->rowCount();
}
void CSMTools::SearchStage::perform (int stage, CSMDoc::Messages& messages)
{
mSearch.searchRow (mModel, stage, messages);
}
void CSMTools::SearchStage::setOperation (const SearchOperation *operation)
{
mOperation = operation;
}

View File

@ -0,0 +1,37 @@
#ifndef CSM_TOOLS_SEARCHSTAGE_H
#define CSM_TOOLS_SEARCHSTAGE_H
#include "../doc/stage.hpp"
#include "search.hpp"
namespace CSMWorld
{
class IdTableBase;
}
namespace CSMTools
{
class SearchOperation;
class SearchStage : public CSMDoc::Stage
{
const CSMWorld::IdTableBase *mModel;
Search mSearch;
const SearchOperation *mOperation;
public:
SearchStage (const CSMWorld::IdTableBase *model);
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.
void setOperation (const SearchOperation *operation);
};
}
#endif

View File

@ -39,4 +39,4 @@ void CSMTools::SkillCheckStage::perform (int stage, CSMDoc::Messages& messages)
if (skill.mDescription.empty()) if (skill.mDescription.empty())
messages.push_back (std::make_pair (id, skill.mId + " has an empty description")); messages.push_back (std::make_pair (id, skill.mId + " has an empty description"));
} }

View File

@ -31,4 +31,4 @@ void CSMTools::SoundCheckStage::perform (int stage, CSMDoc::Messages& messages)
messages.push_back (std::make_pair (id, "Maximum range larger than minimum range")); messages.push_back (std::make_pair (id, "Maximum range larger than minimum range"));
/// \todo check, if the sound file exists /// \todo check, if the sound file exists
} }

View File

@ -37,4 +37,4 @@ void CSMTools::SpellCheckStage::perform (int stage, CSMDoc::Messages& messages)
messages.push_back (std::make_pair (id, spell.mId + " has a negative spell costs")); messages.push_back (std::make_pair (id, spell.mId + " has a negative spell costs"));
/// \todo check data members that can't be edited in the table view /// \todo check data members that can't be edited in the table view
} }

View File

@ -0,0 +1,31 @@
#include "startscriptcheck.hpp"
#include <components/misc/stringops.hpp>
CSMTools::StartScriptCheckStage::StartScriptCheckStage (
const CSMWorld::IdCollection<ESM::StartScript>& startScripts,
const CSMWorld::IdCollection<ESM::Script>& scripts)
: mStartScripts (startScripts), mScripts (scripts)
{}
void CSMTools::StartScriptCheckStage::perform(int stage, CSMDoc::Messages& messages)
{
const CSMWorld::Record<ESM::StartScript>& record = mStartScripts.getRecord (stage);
if (record.isDeleted())
return;
std::string scriptId = record.get().mId;
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_StartScript, scriptId);
if (mScripts.searchId (Misc::StringUtils::lowerCase (scriptId))==-1)
messages.push_back (
std::make_pair (id, "Start script " + scriptId + " does not exist"));
}
int CSMTools::StartScriptCheckStage::setup()
{
return mStartScripts.getSize();
}

View File

@ -0,0 +1,28 @@
#ifndef CSM_TOOLS_STARTSCRIPTCHECK_H
#define CSM_TOOLS_STARTSCRIPTCHECK_H
#include <components/esm/loadsscr.hpp>
#include <components/esm/loadscpt.hpp>
#include "../doc/stage.hpp"
#include "../world/idcollection.hpp"
namespace CSMTools
{
class StartScriptCheckStage : public CSMDoc::Stage
{
const CSMWorld::IdCollection<ESM::StartScript>& mStartScripts;
const CSMWorld::IdCollection<ESM::Script>& mScripts;
public:
StartScriptCheckStage (const CSMWorld::IdCollection<ESM::StartScript>& startScripts,
const CSMWorld::IdCollection<ESM::Script>& scripts);
virtual void perform(int stage, CSMDoc::Messages& messages);
virtual int setup();
};
}
#endif

View File

@ -24,31 +24,34 @@
#include "scriptcheck.hpp" #include "scriptcheck.hpp"
#include "bodypartcheck.hpp" #include "bodypartcheck.hpp"
#include "referencecheck.hpp" #include "referencecheck.hpp"
#include "startscriptcheck.hpp"
#include "searchoperation.hpp"
CSMDoc::Operation *CSMTools::Tools::get (int type) CSMDoc::OperationHolder *CSMTools::Tools::get (int type)
{ {
switch (type) switch (type)
{ {
case CSMDoc::State_Verifying: return mVerifier; case CSMDoc::State_Verifying: return &mVerifier;
case CSMDoc::State_Searching: return &mSearch;
} }
return 0; return 0;
} }
const CSMDoc::Operation *CSMTools::Tools::get (int type) const const CSMDoc::OperationHolder *CSMTools::Tools::get (int type) const
{ {
return const_cast<Tools *> (this)->get (type); return const_cast<Tools *> (this)->get (type);
} }
CSMDoc::Operation *CSMTools::Tools::getVerifier() CSMDoc::OperationHolder *CSMTools::Tools::getVerifier()
{ {
if (!mVerifier) if (!mVerifierOperation)
{ {
mVerifier = new CSMDoc::Operation (CSMDoc::State_Verifying, false); mVerifierOperation = new CSMDoc::Operation (CSMDoc::State_Verifying, false);
connect (mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int))); 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 (done (int, bool)), this, SIGNAL (done (int, bool)));
connect (mVerifier, connect (&mVerifier,
SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)), 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))); this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, const std::string&, int)));
@ -59,54 +62,75 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier()
mandatoryIds.push_back ("Month"); mandatoryIds.push_back ("Month");
mandatoryIds.push_back ("PCRace"); mandatoryIds.push_back ("PCRace");
mVerifier->appendStage (new MandatoryIdStage (mData.getGlobals(), mVerifierOperation->appendStage (new MandatoryIdStage (mData.getGlobals(),
CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), mandatoryIds)); CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), mandatoryIds));
mVerifier->appendStage (new SkillCheckStage (mData.getSkills())); mVerifierOperation->appendStage (new SkillCheckStage (mData.getSkills()));
mVerifier->appendStage (new ClassCheckStage (mData.getClasses())); mVerifierOperation->appendStage (new ClassCheckStage (mData.getClasses()));
mVerifier->appendStage (new FactionCheckStage (mData.getFactions())); mVerifierOperation->appendStage (new FactionCheckStage (mData.getFactions()));
mVerifier->appendStage (new RaceCheckStage (mData.getRaces())); mVerifierOperation->appendStage (new RaceCheckStage (mData.getRaces()));
mVerifier->appendStage (new SoundCheckStage (mData.getSounds())); mVerifierOperation->appendStage (new SoundCheckStage (mData.getSounds()));
mVerifier->appendStage (new RegionCheckStage (mData.getRegions())); mVerifierOperation->appendStage (new RegionCheckStage (mData.getRegions()));
mVerifier->appendStage (new BirthsignCheckStage (mData.getBirthsigns())); mVerifierOperation->appendStage (new BirthsignCheckStage (mData.getBirthsigns()));
mVerifier->appendStage (new SpellCheckStage (mData.getSpells())); mVerifierOperation->appendStage (new SpellCheckStage (mData.getSpells()));
mVerifier->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions())); mVerifierOperation->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions()));
mVerifier->appendStage (new ReferenceCheckStage(mData.getReferences(), mData.getReferenceables(), mData.getCells(), mData.getFactions())); mVerifierOperation->appendStage (new ReferenceCheckStage(mData.getReferences(), mData.getReferenceables(), mData.getCells(), mData.getFactions()));
mVerifier->appendStage (new ScriptCheckStage (mDocument)); mVerifierOperation->appendStage (new ScriptCheckStage (mDocument));
mVerifier->appendStage( mVerifierOperation->appendStage (new StartScriptCheckStage (mData.getStartScripts(), mData.getScripts()));
mVerifierOperation->appendStage(
new BodyPartCheckStage( new BodyPartCheckStage(
mData.getBodyParts(), mData.getBodyParts(),
mData.getResources( mData.getResources(
CSMWorld::UniversalId( CSMWorld::UniversalId::Type_Meshes )), CSMWorld::UniversalId( CSMWorld::UniversalId::Type_Meshes )),
mData.getRaces() )); mData.getRaces() ));
mVerifier.setOperation (mVerifierOperation);
} }
return mVerifier; return &mVerifier;
} }
CSMTools::Tools::Tools (CSMDoc::Document& document) CSMTools::Tools::Tools (CSMDoc::Document& document)
: mDocument (document), mData (document.getData()), mVerifier (0), mNextReportNumber (0) : mDocument (document), mData (document.getData()), mVerifierOperation (0), mNextReportNumber (0),
mSearchOperation (0)
{ {
// index 0: load error log // index 0: load error log
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel)); mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel));
mActiveReports.insert (std::make_pair (CSMDoc::State_Loading, 0)); mActiveReports.insert (std::make_pair (CSMDoc::State_Loading, 0));
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)));
} }
CSMTools::Tools::~Tools() CSMTools::Tools::~Tools()
{ {
delete mVerifier; if (mVerifierOperation)
{
mVerifier.abortAndWait();
delete mVerifierOperation;
}
if (mSearchOperation)
{
mSearch.abortAndWait();
delete mSearchOperation;
}
for (std::map<int, ReportModel *>::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter) for (std::map<int, ReportModel *>::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter)
delete iter->second; delete iter->second;
} }
@ -121,9 +145,31 @@ CSMWorld::UniversalId CSMTools::Tools::runVerifier()
return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_VerificationResults, mNextReportNumber-1); return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_VerificationResults, mNextReportNumber-1);
} }
CSMWorld::UniversalId CSMTools::Tools::newSearch()
{
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel (true)));
return CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Search, mNextReportNumber-1);
}
void CSMTools::Tools::runSearch (const CSMWorld::UniversalId& searchId, const Search& search)
{
mActiveReports[CSMDoc::State_Searching] = searchId.getIndex();
if (!mSearchOperation)
{
mSearchOperation = new SearchOperation (mDocument);
mSearch.setOperation (mSearchOperation);
}
mSearchOperation->configure (search);
mSearch.start();
}
void CSMTools::Tools::abortOperation (int type) void CSMTools::Tools::abortOperation (int type)
{ {
if (CSMDoc::Operation *operation = get (type)) if (CSMDoc::OperationHolder *operation = get (type))
operation->abort(); operation->abort();
} }
@ -132,13 +178,14 @@ int CSMTools::Tools::getRunningOperations() const
static const int sOperations[] = static const int sOperations[] =
{ {
CSMDoc::State_Verifying, CSMDoc::State_Verifying,
CSMDoc::State_Searching,
-1 -1
}; };
int result = 0; int result = 0;
for (int i=0; sOperations[i]!=-1; ++i) for (int i=0; sOperations[i]!=-1; ++i)
if (const CSMDoc::Operation *operation = get (sOperations[i])) if (const CSMDoc::OperationHolder *operation = get (sOperations[i]))
if (operation->isRunning()) if (operation->isRunning())
result |= sOperations[i]; result |= sOperations[i];
@ -148,9 +195,10 @@ int CSMTools::Tools::getRunningOperations() const
CSMTools::ReportModel *CSMTools::Tools::getReport (const CSMWorld::UniversalId& id) CSMTools::ReportModel *CSMTools::Tools::getReport (const CSMWorld::UniversalId& id)
{ {
if (id.getType()!=CSMWorld::UniversalId::Type_VerificationResults && if (id.getType()!=CSMWorld::UniversalId::Type_VerificationResults &&
id.getType()!=CSMWorld::UniversalId::Type_LoadErrorLog) id.getType()!=CSMWorld::UniversalId::Type_LoadErrorLog &&
id.getType()!=CSMWorld::UniversalId::Type_Search)
throw std::logic_error ("invalid request for report model: " + id.toString()); throw std::logic_error ("invalid request for report model: " + id.toString());
return mReports.at (id.getIndex()); return mReports.at (id.getIndex());
} }

View File

@ -5,6 +5,8 @@
#include <map> #include <map>
#include "../doc/operationholder.hpp"
namespace CSMWorld namespace CSMWorld
{ {
class Data; class Data;
@ -20,6 +22,8 @@ namespace CSMDoc
namespace CSMTools namespace CSMTools
{ {
class ReportModel; class ReportModel;
class Search;
class SearchOperation;
class Tools : public QObject class Tools : public QObject
{ {
@ -27,7 +31,10 @@ namespace CSMTools
CSMDoc::Document& mDocument; CSMDoc::Document& mDocument;
CSMWorld::Data& mData; CSMWorld::Data& mData;
CSMDoc::Operation *mVerifier; CSMDoc::Operation *mVerifierOperation;
CSMDoc::OperationHolder mVerifier;
SearchOperation *mSearchOperation;
CSMDoc::OperationHolder mSearch;
std::map<int, ReportModel *> mReports; std::map<int, ReportModel *> mReports;
int mNextReportNumber; int mNextReportNumber;
std::map<int, int> mActiveReports; // type, report number std::map<int, int> mActiveReports; // type, report number
@ -36,12 +43,12 @@ namespace CSMTools
Tools (const Tools&); Tools (const Tools&);
Tools& operator= (const Tools&); Tools& operator= (const Tools&);
CSMDoc::Operation *getVerifier(); CSMDoc::OperationHolder *getVerifier();
CSMDoc::Operation *get (int type); CSMDoc::OperationHolder *get (int type);
///< Returns a 0-pointer, if operation hasn't been used yet. ///< Returns a 0-pointer, if operation hasn't been used yet.
const CSMDoc::Operation *get (int type) const; const CSMDoc::OperationHolder *get (int type) const;
///< Returns a 0-pointer, if operation hasn't been used yet. ///< Returns a 0-pointer, if operation hasn't been used yet.
public: public:
@ -53,6 +60,11 @@ namespace CSMTools
CSMWorld::UniversalId runVerifier(); CSMWorld::UniversalId runVerifier();
///< \return ID of the report for this verification run ///< \return ID of the report for this verification run
/// Return ID of the report for this search.
CSMWorld::UniversalId newSearch();
void runSearch (const CSMWorld::UniversalId& searchId, const Search& search);
void abortOperation (int type); void abortOperation (int type);
///< \attention The operation is not aborted immediately. ///< \attention The operation is not aborted immediately.

View File

@ -21,4 +21,4 @@ namespace CSMWorld
}; };
} }
#endif #endif

View File

@ -28,4 +28,4 @@ int CSMWorld::CollectionBase::findColumnIndex (Columns::ColumnId id) const
throw std::logic_error ("invalid column index"); throw std::logic_error ("invalid column index");
return index; return index;
} }

View File

@ -106,4 +106,4 @@ namespace CSMWorld
}; };
} }
#endif #endif

View File

@ -19,7 +19,80 @@ std::string CSMWorld::ColumnBase::getTitle() const
return Columns::getName (static_cast<Columns::ColumnId> (mColumnId)); return Columns::getName (static_cast<Columns::ColumnId> (mColumnId));
} }
int CSMWorld::ColumnBase::getId() const int CSMWorld::ColumnBase::getId() const
{ {
return mColumnId; return mColumnId;
} }
bool CSMWorld::ColumnBase::isId (Display display)
{
static const Display ids[] =
{
Display_Skill,
Display_Class,
Display_Faction,
Display_Race,
Display_Sound,
Display_Region,
Display_Birthsign,
Display_Spell,
Display_Cell,
Display_Referenceable,
Display_Activator,
Display_Potion,
Display_Apparatus,
Display_Armor,
Display_Book,
Display_Clothing,
Display_Container,
Display_Creature,
Display_Door,
Display_Ingredient,
Display_CreatureLevelledList,
Display_ItemLevelledList,
Display_Light,
Display_Lockpick,
Display_Miscellaneous,
Display_Npc,
Display_Probe,
Display_Repair,
Display_Static,
Display_Weapon,
Display_Reference,
Display_Filter,
Display_Topic,
Display_Journal,
Display_TopicInfo,
Display_JournalInfo,
Display_Scene,
Display_GlobalVariable,
Display_Script,
Display_Mesh,
Display_Icon,
Display_Music,
Display_SoundRes,
Display_Texture,
Display_Video,
Display_Id,
Display_None
};
for (int i=0; ids[i]!=Display_None; ++i)
if (ids[i]==display)
return true;
return false;
}
bool CSMWorld::ColumnBase::isText (Display display)
{
return display==Display_String || display==Display_LongString;
}
bool CSMWorld::ColumnBase::isScript (Display display)
{
return display==Display_ScriptFile || display==Display_ScriptLines;
}

View File

@ -101,9 +101,11 @@ namespace CSMWorld
Display_Texture, Display_Texture,
Display_Video, Display_Video,
Display_Colour, Display_Colour,
Display_ScriptFile,
Display_ScriptLines, // console context Display_ScriptLines, // console context
Display_SoundGeneratorType, Display_SoundGeneratorType,
Display_School Display_School,
Display_Id
}; };
int mColumnId; int mColumnId;
@ -122,6 +124,12 @@ namespace CSMWorld
virtual std::string getTitle() const; virtual std::string getTitle() const;
virtual int getId() const; virtual int getId() const;
static bool isId (Display display);
static bool isText (Display display);
static bool isScript (Display display);
}; };
template<typename ESXRecordT> template<typename ESXRecordT>

View File

@ -43,7 +43,7 @@ namespace CSMWorld
struct StringIdColumn : public Column<ESXRecordT> struct StringIdColumn : public Column<ESXRecordT>
{ {
StringIdColumn (bool hidden = false) StringIdColumn (bool hidden = false)
: Column<ESXRecordT> (Columns::ColumnId_Id, ColumnBase::Display_String, : Column<ESXRecordT> (Columns::ColumnId_Id, ColumnBase::Display_Id,
hidden ? 0 : ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue) hidden ? 0 : ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue)
{} {}
@ -818,7 +818,7 @@ namespace CSMWorld
ScriptColumn (Type type) ScriptColumn (Type type)
: Column<ESXRecordT> (Columns::ColumnId_ScriptText, : Column<ESXRecordT> (Columns::ColumnId_ScriptText,
type==Type_File ? ColumnBase::Display_Script : ColumnBase::Display_ScriptLines, type==Type_File ? ColumnBase::Display_ScriptFile : ColumnBase::Display_ScriptLines,
type==Type_File ? 0 : ColumnBase::Flag_Dialogue) type==Type_File ? 0 : ColumnBase::Flag_Dialogue)
{} {}

View File

@ -264,4 +264,4 @@ void CSMWorld::CommandDispatcher::executeExtendedRevert()
if (mExtendedTypes.size()>1) if (mExtendedTypes.size()>1)
mDocument.getUndoStack().endMacro(); mDocument.getUndoStack().endMacro();
} }

View File

@ -170,4 +170,4 @@ void CSMWorld::CloneCommand::redo()
void CSMWorld::CloneCommand::undo() void CSMWorld::CloneCommand::undo()
{ {
mModel.removeRow (mModel.getModelIndex (mId, 0).row()); mModel.removeRow (mModel.getModelIndex (mId, 0).row());
} }

View File

@ -20,7 +20,7 @@ namespace CSMWorld
{ {
class IdTable; class IdTable;
class IdTable; class IdTable;
class RecordBase; struct RecordBase;
class ModifyCommand : public QUndoCommand class ModifyCommand : public QUndoCommand
{ {
@ -141,4 +141,4 @@ namespace CSMWorld
}; };
} }
#endif #endif

View File

@ -254,6 +254,10 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
mPathgrids.addColumn (new RecordStateColumn<Pathgrid>); mPathgrids.addColumn (new RecordStateColumn<Pathgrid>);
mPathgrids.addColumn (new FixedRecordTypeColumn<Pathgrid> (UniversalId::Type_Pathgrid)); mPathgrids.addColumn (new FixedRecordTypeColumn<Pathgrid> (UniversalId::Type_Pathgrid));
mStartScripts.addColumn (new StringIdColumn<ESM::StartScript>);
mStartScripts.addColumn (new RecordStateColumn<ESM::StartScript>);
mStartScripts.addColumn (new FixedRecordTypeColumn<ESM::StartScript> (UniversalId::Type_StartScript));
mRefs.addColumn (new StringIdColumn<CellRef> (true)); mRefs.addColumn (new StringIdColumn<CellRef> (true));
mRefs.addColumn (new RecordStateColumn<CellRef>); mRefs.addColumn (new RecordStateColumn<CellRef>);
mRefs.addColumn (new FixedRecordTypeColumn<CellRef> (UniversalId::Type_Reference)); mRefs.addColumn (new FixedRecordTypeColumn<CellRef> (UniversalId::Type_Reference));
@ -327,6 +331,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
addModel (new IdTable (&mSoundGens), UniversalId::Type_SoundGen); addModel (new IdTable (&mSoundGens), UniversalId::Type_SoundGen);
addModel (new IdTable (&mMagicEffects), UniversalId::Type_MagicEffect); addModel (new IdTable (&mMagicEffects), UniversalId::Type_MagicEffect);
addModel (new IdTable (&mPathgrids), UniversalId::Type_Pathgrid); addModel (new IdTable (&mPathgrids), UniversalId::Type_Pathgrid);
addModel (new IdTable (&mStartScripts), UniversalId::Type_StartScript);
addModel (new IdTable (&mReferenceables, IdTable::Feature_Preview), addModel (new IdTable (&mReferenceables, IdTable::Feature_Preview),
UniversalId::Type_Referenceable); UniversalId::Type_Referenceable);
addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_Reference); addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_Reference);
@ -615,6 +620,16 @@ CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& CSMWorld::Data::getPathgrids()
return mPathgrids; return mPathgrids;
} }
const CSMWorld::IdCollection<ESM::StartScript>& CSMWorld::Data::getStartScripts() const
{
return mStartScripts;
}
CSMWorld::IdCollection<ESM::StartScript>& CSMWorld::Data::getStartScripts()
{
return mStartScripts;
}
const CSMWorld::Resources& CSMWorld::Data::getResources (const UniversalId& id) const const CSMWorld::Resources& CSMWorld::Data::getResources (const UniversalId& id) const
{ {
return mResourcesManager.get (id.getType()); return mResourcesManager.get (id.getType());
@ -719,6 +734,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages)
case ESM::REC_SNDG: mSoundGens.load (*mReader, mBase); break; case ESM::REC_SNDG: mSoundGens.load (*mReader, mBase); break;
case ESM::REC_MGEF: mMagicEffects.load (*mReader, mBase); break; case ESM::REC_MGEF: mMagicEffects.load (*mReader, mBase); break;
case ESM::REC_PGRD: mPathgrids.load (*mReader, mBase); break; case ESM::REC_PGRD: mPathgrids.load (*mReader, mBase); break;
case ESM::REC_SSCR: mStartScripts.load (*mReader, mBase); break;
case ESM::REC_LTEX: mLandTextures.load (*mReader, mBase); break; case ESM::REC_LTEX: mLandTextures.load (*mReader, mBase); break;
@ -729,7 +745,7 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Messages& messages)
if (index!=-1 && !mBase) if (index!=-1 && !mBase)
mLand.getRecord (index).mModified.mLand->loadData ( mLand.getRecord (index).mModified.mLand->loadData (
ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR | ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR |
ESM::Land::DATA_VTEX); ESM::Land::DATA_VTEX | ESM::Land::DATA_WNAM);
break; break;
} }

View File

@ -25,6 +25,7 @@
#include <components/esm/loadbody.hpp> #include <components/esm/loadbody.hpp>
#include <components/esm/loadsndg.hpp> #include <components/esm/loadsndg.hpp>
#include <components/esm/loadmgef.hpp> #include <components/esm/loadmgef.hpp>
#include <components/esm/loadsscr.hpp>
#include <components/esm/debugprofile.hpp> #include <components/esm/debugprofile.hpp>
#include <components/esm/filter.hpp> #include <components/esm/filter.hpp>
@ -80,6 +81,7 @@ namespace CSMWorld
SubCellCollection<Pathgrid> mPathgrids; SubCellCollection<Pathgrid> mPathgrids;
IdCollection<ESM::DebugProfile> mDebugProfiles; IdCollection<ESM::DebugProfile> mDebugProfiles;
IdCollection<ESM::SoundGenerator> mSoundGens; IdCollection<ESM::SoundGenerator> mSoundGens;
IdCollection<ESM::StartScript> mStartScripts;
InfoCollection mTopicInfos; InfoCollection mTopicInfos;
InfoCollection mJournalInfos; InfoCollection mJournalInfos;
IdCollection<Cell> mCells; IdCollection<Cell> mCells;
@ -225,6 +227,10 @@ namespace CSMWorld
SubCellCollection<Pathgrid>& getPathgrids(); SubCellCollection<Pathgrid>& getPathgrids();
const IdCollection<ESM::StartScript>& getStartScripts() const;
IdCollection<ESM::StartScript>& getStartScripts();
/// Throws an exception, if \a id does not match a resources list. /// Throws an exception, if \a id does not match a resources list.
const Resources& getResources (const UniversalId& id) const; const Resources& getResources (const UniversalId& id) const;

View File

@ -10,7 +10,7 @@
namespace CSMWorld namespace CSMWorld
{ {
class CollectionBase; class CollectionBase;
class RecordBase; struct RecordBase;
class IdTable : public IdTableBase class IdTable : public IdTableBase
{ {
@ -82,7 +82,7 @@ namespace CSMWorld
/// Is \a id flagged as deleted? /// Is \a id flagged as deleted?
virtual bool isDeleted (const std::string& id) const; virtual bool isDeleted (const std::string& id) const;
int getColumnId(int column) const; virtual int getColumnId(int column) const;
}; };
} }

View File

@ -6,4 +6,4 @@ CSMWorld::IdTableBase::IdTableBase (unsigned int features) : mFeatures (features
unsigned int CSMWorld::IdTableBase::getFeatures() const unsigned int CSMWorld::IdTableBase::getFeatures() const
{ {
return mFeatures; return mFeatures;
} }

View File

@ -60,6 +60,8 @@ namespace CSMWorld
/// Is \a id flagged as deleted? /// Is \a id flagged as deleted?
virtual bool isDeleted (const std::string& id) const = 0; virtual bool isDeleted (const std::string& id) const = 0;
virtual int getColumnId (int column) const = 0;
unsigned int getFeatures() const; unsigned int getFeatures() const;
}; };
} }

View File

@ -26,7 +26,7 @@ void CSMWorld::InfoCollection::load (const Info& record, bool base)
if (!record2.get().mPrev.empty()) if (!record2.get().mPrev.empty())
{ {
index = getIndex (record2.get().mPrev, topic); index = getInfoIndex (record2.get().mPrev, topic);
if (index!=-1) if (index!=-1)
++index; ++index;
@ -34,7 +34,7 @@ void CSMWorld::InfoCollection::load (const Info& record, bool base)
if (index==-1 && !record2.get().mNext.empty()) if (index==-1 && !record2.get().mNext.empty())
{ {
index = getIndex (record2.get().mNext, topic); index = getInfoIndex (record2.get().mNext, topic);
} }
if (index==-1) if (index==-1)
@ -60,7 +60,7 @@ void CSMWorld::InfoCollection::load (const Info& record, bool base)
} }
} }
int CSMWorld::InfoCollection::getIndex (const std::string& id, const std::string& topic) const int CSMWorld::InfoCollection::getInfoIndex (const std::string& id, const std::string& topic) const
{ {
std::string fullId = Misc::StringUtils::lowerCase (topic) + "#" + id; std::string fullId = Misc::StringUtils::lowerCase (topic) + "#" + id;

View File

@ -6,7 +6,7 @@
namespace ESM namespace ESM
{ {
class Dialogue; struct Dialogue;
} }
namespace CSMWorld namespace CSMWorld
@ -22,7 +22,7 @@ namespace CSMWorld
void load (const Info& record, bool base); void load (const Info& record, bool base);
int getIndex (const std::string& id, const std::string& topic) const; int getInfoIndex (const std::string& id, const std::string& topic) const;
///< Return index for record \a id or -1 (if not present; deleted records are considered) ///< Return index for record \a id or -1 (if not present; deleted records are considered)
/// ///
/// \param id info ID without topic prefix /// \param id info ID without topic prefix
@ -47,4 +47,4 @@ namespace CSMWorld
}; };
} }
#endif #endif

View File

@ -26,4 +26,4 @@ namespace CSMWorld
}; };
} }
#endif #endif

View File

@ -18,4 +18,4 @@ bool CSMWorld::RecordBase::isErased() const
bool CSMWorld::RecordBase::isModified() const bool CSMWorld::RecordBase::isModified() const
{ {
return mState==State_Modified || mState==State_ModifiedOnly; return mState==State_Modified || mState==State_ModifiedOnly;
} }

View File

@ -22,6 +22,8 @@ namespace CSMWorld
virtual RecordBase *clone() const = 0; virtual RecordBase *clone() const = 0;
virtual RecordBase *modifiedCopy() const = 0;
virtual void assign (const RecordBase& record) = 0; virtual void assign (const RecordBase& record) = 0;
///< Will throw an exception if the types don't match. ///< Will throw an exception if the types don't match.
@ -38,8 +40,15 @@ namespace CSMWorld
ESXRecordT mBase; ESXRecordT mBase;
ESXRecordT mModified; ESXRecordT mModified;
Record();
Record(State state,
const ESXRecordT *base = 0, const ESXRecordT *modified = 0);
virtual RecordBase *clone() const; virtual RecordBase *clone() const;
virtual RecordBase *modifiedCopy() const;
virtual void assign (const RecordBase& record); virtual void assign (const RecordBase& record);
const ESXRecordT& get() const; const ESXRecordT& get() const;
@ -58,6 +67,29 @@ namespace CSMWorld
///< Merge modified into base. ///< Merge modified into base.
}; };
template <typename ESXRecordT>
Record<ESXRecordT>::Record()
: mBase(), mModified()
{ }
template <typename ESXRecordT>
Record<ESXRecordT>::Record(State state, const ESXRecordT *base, const ESXRecordT *modified)
{
if(base)
mBase = *base;
if(modified)
mModified = *modified;
this->mState = state;
}
template <typename ESXRecordT>
RecordBase *Record<ESXRecordT>::modifiedCopy() const
{
return new Record<ESXRecordT> (State_ModifiedOnly, 0, &(this->get()));
}
template <typename ESXRecordT> template <typename ESXRecordT>
RecordBase *Record<ESXRecordT>::clone() const RecordBase *Record<ESXRecordT>::clone() const
{ {

View File

@ -5,4 +5,4 @@ CSMWorld::CellRef::CellRef()
{ {
mRefNum.mIndex = 0; mRefNum.mIndex = 0;
mRefNum.mContentFile = 0; mRefNum.mContentFile = 0;
} }

View File

@ -5,8 +5,6 @@
namespace CSMWorld namespace CSMWorld
{ {
class Cell;
/// \brief Wrapper for CellRef sub record /// \brief Wrapper for CellRef sub record
struct CellRef : public ESM::CellRef struct CellRef : public ESM::CellRef
{ {

View File

@ -12,7 +12,7 @@
namespace CSMWorld namespace CSMWorld
{ {
struct Cell; struct Cell;
struct UniversalId; class UniversalId;
/// \brief References in cells /// \brief References in cells
class RefCollection : public Collection<CellRef> class RefCollection : public Collection<CellRef>

View File

@ -3,4 +3,4 @@
CSMWorld::RefIdAdapter::RefIdAdapter() {} CSMWorld::RefIdAdapter::RefIdAdapter() {}
CSMWorld::RefIdAdapter::~RefIdAdapter() {} CSMWorld::RefIdAdapter::~RefIdAdapter() {}

View File

@ -9,7 +9,7 @@ namespace CSMWorld
{ {
class RefIdColumn; class RefIdColumn;
class RefIdData; class RefIdData;
class RecordBase; struct RecordBase;
class RefIdAdapter class RefIdAdapter
{ {
@ -35,4 +35,4 @@ namespace CSMWorld
}; };
} }
#endif #endif

View File

@ -156,10 +156,16 @@ namespace CSMWorld
Record<RecordT>& record = static_cast<Record<RecordT>&> ( Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType()))); data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
RecordT record2 = record.get();
if (column==mModel.mModel) if (column==mModel.mModel)
record.get().mModel = value.toString().toUtf8().constData(); record2.mModel = value.toString().toUtf8().constData();
else else
{
BaseRefIdAdapter<RecordT>::setData (column, data, index, value); BaseRefIdAdapter<RecordT>::setData (column, data, index, value);
return;
}
record.setModified(record2);
} }
struct NameColumns : public ModelColumns struct NameColumns : public ModelColumns
@ -216,12 +222,18 @@ namespace CSMWorld
Record<RecordT>& record = static_cast<Record<RecordT>&> ( Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType()))); data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
RecordT record2 = record.get();
if (column==mName.mName) if (column==mName.mName)
record.get().mName = value.toString().toUtf8().constData(); record2.mName = value.toString().toUtf8().constData();
else if (column==mName.mScript) else if (column==mName.mScript)
record.get().mScript = value.toString().toUtf8().constData(); record2.mScript = value.toString().toUtf8().constData();
else else
{
ModelRefIdAdapter<RecordT>::setData (column, data, index, value); ModelRefIdAdapter<RecordT>::setData (column, data, index, value);
return;
}
record.setModified(record2);
} }
struct InventoryColumns : public NameColumns struct InventoryColumns : public NameColumns
@ -283,14 +295,20 @@ namespace CSMWorld
Record<RecordT>& record = static_cast<Record<RecordT>&> ( Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType()))); data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
RecordT record2 = record.get();
if (column==mInventory.mIcon) if (column==mInventory.mIcon)
record.get().mIcon = value.toString().toUtf8().constData(); record2.mIcon = value.toString().toUtf8().constData();
else if (column==mInventory.mWeight) else if (column==mInventory.mWeight)
record.get().mData.mWeight = value.toFloat(); record2.mData.mWeight = value.toFloat();
else if (column==mInventory.mValue) else if (column==mInventory.mValue)
record.get().mData.mValue = value.toInt(); record2.mData.mValue = value.toInt();
else else
{
NameRefIdAdapter<RecordT>::setData (column, data, index, value); NameRefIdAdapter<RecordT>::setData (column, data, index, value);
return;
}
record.setModified(record2);
} }
class PotionRefIdAdapter : public InventoryRefIdAdapter<ESM::Potion> class PotionRefIdAdapter : public InventoryRefIdAdapter<ESM::Potion>
@ -364,12 +382,18 @@ namespace CSMWorld
Record<RecordT>& record = static_cast<Record<RecordT>&> ( Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType()))); data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
RecordT record2 = record.get();
if (column==mEnchantable.mEnchantment) if (column==mEnchantable.mEnchantment)
record.get().mEnchant = value.toString().toUtf8().constData(); record2.mEnchant = value.toString().toUtf8().constData();
else if (column==mEnchantable.mEnchantmentPoints) else if (column==mEnchantable.mEnchantmentPoints)
record.get().mData.mEnchant = value.toInt(); record2.mData.mEnchant = value.toInt();
else else
{
InventoryRefIdAdapter<RecordT>::setData (column, data, index, value); InventoryRefIdAdapter<RecordT>::setData (column, data, index, value);
return;
}
record.setModified(record2);
} }
struct ToolColumns : public InventoryColumns struct ToolColumns : public InventoryColumns
@ -426,12 +450,18 @@ namespace CSMWorld
Record<RecordT>& record = static_cast<Record<RecordT>&> ( Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType()))); data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
RecordT record2 = record.get();
if (column==mTools.mQuality) if (column==mTools.mQuality)
record.get().mData.mQuality = value.toFloat(); record2.mData.mQuality = value.toFloat();
else if (column==mTools.mUses) else if (column==mTools.mUses)
record.get().mData.mUses = value.toInt(); record2.mData.mUses = value.toInt();
else else
{
InventoryRefIdAdapter<RecordT>::setData (column, data, index, value); InventoryRefIdAdapter<RecordT>::setData (column, data, index, value);
return;
}
record.setModified(record2);
} }
struct ActorColumns : public NameColumns struct ActorColumns : public NameColumns
@ -508,16 +538,17 @@ namespace CSMWorld
Record<RecordT>& record = static_cast<Record<RecordT>&> ( Record<RecordT>& record = static_cast<Record<RecordT>&> (
data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType()))); data.getRecord (RefIdData::LocalIndex (index, BaseRefIdAdapter<RecordT>::getType())));
RecordT record2 = record.get();
if (column==mActors.mHasAi) if (column==mActors.mHasAi)
record.get().mHasAI = value.toInt(); record2.mHasAI = value.toInt();
else if (column==mActors.mHello) else if (column==mActors.mHello)
record.get().mAiData.mHello = value.toInt(); record2.mAiData.mHello = value.toInt();
else if (column==mActors.mFlee) else if (column==mActors.mFlee)
record.get().mAiData.mFlee = value.toInt(); record2.mAiData.mFlee = value.toInt();
else if (column==mActors.mFight) else if (column==mActors.mFight)
record.get().mAiData.mFight = value.toInt(); record2.mAiData.mFight = value.toInt();
else if (column==mActors.mAlarm) else if (column==mActors.mAlarm)
record.get().mAiData.mAlarm = value.toInt(); record2.mAiData.mAlarm = value.toInt();
else else
{ {
typename std::map<const RefIdColumn *, unsigned int>::const_iterator iter = typename std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
@ -525,13 +556,18 @@ namespace CSMWorld
if (iter!=mActors.mServices.end()) if (iter!=mActors.mServices.end())
{ {
if (value.toInt()!=0) if (value.toInt()!=0)
record.get().mAiData.mServices |= iter->second; record2.mAiData.mServices |= iter->second;
else else
record.get().mAiData.mServices &= ~iter->second; record2.mAiData.mServices &= ~iter->second;
} }
else else
{
NameRefIdAdapter<RecordT>::setData (column, data, index, value); NameRefIdAdapter<RecordT>::setData (column, data, index, value);
return;
}
} }
record.setModified(record2);
} }
class ApparatusRefIdAdapter : public InventoryRefIdAdapter<ESM::Apparatus> class ApparatusRefIdAdapter : public InventoryRefIdAdapter<ESM::Apparatus>

View File

@ -40,7 +40,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
{ {
BaseColumns baseColumns; BaseColumns baseColumns;
mColumns.push_back (RefIdColumn (Columns::ColumnId_Id, ColumnBase::Display_String, mColumns.push_back (RefIdColumn (Columns::ColumnId_Id, ColumnBase::Display_Id,
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false)); ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
baseColumns.mId = &mColumns.back(); baseColumns.mId = &mColumns.back();
mColumns.push_back (RefIdColumn (Columns::ColumnId_Modification, ColumnBase::Display_RecordState, mColumns.push_back (RefIdColumn (Columns::ColumnId_Modification, ColumnBase::Display_RecordState,
@ -470,8 +470,7 @@ void CSMWorld::RefIdCollection::cloneRecord(const std::string& origin,
const std::string& destination, const std::string& destination,
const CSMWorld::UniversalId::Type type) const CSMWorld::UniversalId::Type type)
{ {
std::auto_ptr<RecordBase> newRecord(mData.getRecord(mData.searchId(origin)).clone()); std::auto_ptr<RecordBase> newRecord(mData.getRecord(mData.searchId(origin)).modifiedCopy());
newRecord->mState = RecordBase::State_ModifiedOnly;
mAdapters.find(type)->second->setId(*newRecord, destination); mAdapters.find(type)->second->setId(*newRecord, destination);
mData.insertRecord(*newRecord, type, destination); mData.insertRecord(*newRecord, type, destination);
} }

View File

@ -503,4 +503,4 @@ void CSMWorld::RegionMap::cellsChanged (const QModelIndex& topLeft, const QModel
// columns we are interested in. If not we can exit the function here and avoid all updating. // columns we are interested in. If not we can exit the function here and avoid all updating.
addCells (topLeft.row(), bottomRight.row()); addCells (topLeft.row(), bottomRight.row());
} }

View File

@ -105,4 +105,4 @@ int CSMWorld::Resources::searchId (const std::string& id) const
CSMWorld::UniversalId::Type CSMWorld::Resources::getType() const CSMWorld::UniversalId::Type CSMWorld::Resources::getType() const
{ {
return mType; return mType;
} }

View File

@ -30,4 +30,4 @@ const CSMWorld::Resources& CSMWorld::ResourcesManager::get (UniversalId::Type ty
throw std::logic_error ("Unknown resource type"); throw std::logic_error ("Unknown resource type");
return iter->second; return iter->second;
} }

View File

@ -25,4 +25,4 @@ namespace CSMWorld
}; };
} }
#endif #endif

View File

@ -60,7 +60,7 @@ QVariant CSMWorld::ResourceTable::headerData (int section, Qt::Orientation orien
return Columns::getName (Columns::ColumnId_Id).c_str(); return Columns::getName (Columns::ColumnId_Id).c_str();
if (role==ColumnBase::Role_Display) if (role==ColumnBase::Role_Display)
return ColumnBase::Display_String; return ColumnBase::Display_Id;
break; break;
@ -143,4 +143,15 @@ std::pair<CSMWorld::UniversalId, std::string> CSMWorld::ResourceTable::view (int
bool CSMWorld::ResourceTable::isDeleted (const std::string& id) const bool CSMWorld::ResourceTable::isDeleted (const std::string& id) const
{ {
return false; return false;
} }
int CSMWorld::ResourceTable::getColumnId (int column) const
{
switch (column)
{
case 0: return Columns::ColumnId_Id;
case 1: return Columns::ColumnId_RecordType;
}
return -1;
}

View File

@ -51,6 +51,8 @@ namespace CSMWorld
/// Is \a id flagged as deleted? /// Is \a id flagged as deleted?
virtual bool isDeleted (const std::string& id) const; virtual bool isDeleted (const std::string& id) const;
virtual int getColumnId (int column) const;
}; };
} }

View File

@ -22,4 +22,4 @@ CSMWorld::Scope CSMWorld::getScopeFromId (const std::string& id)
return Scope_Session; return Scope_Session;
return Scope_Content; return Scope_Content;
} }

View File

@ -120,4 +120,4 @@ void CSMWorld::ScriptContext::clear()
mIds.clear(); mIds.clear();
mIdsUpdated = false; mIdsUpdated = false;
mLocals.clear(); mLocals.clear();
} }

View File

@ -55,6 +55,7 @@ namespace
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_SoundGens, "Sound Generators", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_SoundGens, "Sound Generators", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MagicEffects, "Magic Effects", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_MagicEffects, "Magic Effects", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Pathgrids, "Pathgrids", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Pathgrids, "Pathgrids", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_StartScripts, "Start Scripts", 0 },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
}; };
@ -118,6 +119,7 @@ namespace
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_SoundGen, "Sound Generator", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_SoundGen, "Sound Generator", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MagicEffect, "Magic Effect", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_MagicEffect, "Magic Effect", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Pathgrid, "Pathgrid", 0 }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Pathgrid, "Pathgrid", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_StartScript, "Start Script", 0 },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
}; };
@ -126,6 +128,7 @@ namespace
{ {
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, "Verification Results", 0 }, { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_VerificationResults, "Verification Results", 0 },
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_LoadErrorLog, "Load Error Log", 0 }, { CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_LoadErrorLog, "Load Error Log", 0 },
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_Search, "Global Search", 0 },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
}; };
} }
@ -345,6 +348,25 @@ std::vector<CSMWorld::UniversalId::Type> CSMWorld::UniversalId::listReferenceabl
return list; return list;
} }
std::vector<CSMWorld::UniversalId::Type> CSMWorld::UniversalId::listTypes (int classes)
{
std::vector<CSMWorld::UniversalId::Type> list;
for (int i=0; sNoArg[i].mName; ++i)
if (sNoArg[i].mClass & classes)
list.push_back (sNoArg[i].mType);
for (int i=0; sIdArg[i].mName; ++i)
if (sIdArg[i].mClass & classes)
list.push_back (sIdArg[i].mType);
for (int i=0; sIndexArg[i].mName; ++i)
if (sIndexArg[i].mClass & classes)
list.push_back (sIndexArg[i].mType);
return list;
}
CSMWorld::UniversalId::Type CSMWorld::UniversalId::getParentType (Type type) CSMWorld::UniversalId::Type CSMWorld::UniversalId::getParentType (Type type)
{ {
for (int i=0; sIdArg[i].mType; ++i) for (int i=0; sIdArg[i].mType; ++i)

View File

@ -16,16 +16,16 @@ namespace CSMWorld
enum Class enum Class
{ {
Class_None = 0, Class_None = 0,
Class_Record, Class_Record = 1,
Class_RefRecord, // referenceable record Class_RefRecord = 2, // referenceable record
Class_SubRecord, Class_SubRecord = 4,
Class_RecordList, Class_RecordList = 8,
Class_Collection, // multiple types of records combined Class_Collection = 16, // multiple types of records combined
Class_Transient, // not part of the world data or the project data Class_Transient = 32, // not part of the world data or the project data
Class_NonRecord, // record like data that is not part of the world Class_NonRecord = 64, // record like data that is not part of the world
Class_Resource, ///< \attention Resource IDs are unique only within the Class_Resource = 128, ///< \attention Resource IDs are unique only within the
/// respective collection /// respective collection
Class_ResourceList Class_ResourceList = 256
}; };
enum ArgumentType enum ArgumentType
@ -128,6 +128,9 @@ namespace CSMWorld
Type_MagicEffect, Type_MagicEffect,
Type_Pathgrids, Type_Pathgrids,
Type_Pathgrid, Type_Pathgrid,
Type_StartScripts,
Type_StartScript,
Type_Search,
Type_RunLog Type_RunLog
}; };
@ -178,6 +181,8 @@ namespace CSMWorld
static std::vector<Type> listReferenceableTypes(); static std::vector<Type> listReferenceableTypes();
static std::vector<Type> listTypes (int classes);
/// If \a type is a SubRecord, RefRecord or Record type return the type of the table /// If \a type is a SubRecord, RefRecord or Record type return the type of the table
/// that contains records of type \a type. /// that contains records of type \a type.
/// Otherwise return Type_None. /// Otherwise return Type_None.

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