mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-27 03:35:27 +00:00
Merge branch 'dialog-fix' into NonTableFields
This commit is contained in:
commit
187fccc8cc
131
CMakeLists.txt
131
CMakeLists.txt
@ -12,7 +12,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/)
|
|||||||
message(STATUS "Configuring OpenMW...")
|
message(STATUS "Configuring OpenMW...")
|
||||||
|
|
||||||
set(OPENMW_VERSION_MAJOR 0)
|
set(OPENMW_VERSION_MAJOR 0)
|
||||||
set(OPENMW_VERSION_MINOR 29)
|
set(OPENMW_VERSION_MINOR 30)
|
||||||
set(OPENMW_VERSION_RELEASE 0)
|
set(OPENMW_VERSION_RELEASE 0)
|
||||||
|
|
||||||
set(OPENMW_VERSION_COMMITHASH "")
|
set(OPENMW_VERSION_COMMITHASH "")
|
||||||
@ -36,18 +36,8 @@ if(EXISTS ${PROJECT_SOURCE_DIR}/.git)
|
|||||||
string(REGEX REPLACE "^openmw-[0-9]+\\.([0-9]+).*" "\\1" GIT_VERSION_MINOR "${VERSION}")
|
string(REGEX REPLACE "^openmw-[0-9]+\\.([0-9]+).*" "\\1" GIT_VERSION_MINOR "${VERSION}")
|
||||||
string(REGEX REPLACE "^openmw-[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" GIT_VERSION_RELEASE "${VERSION}")
|
string(REGEX REPLACE "^openmw-[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" GIT_VERSION_RELEASE "${VERSION}")
|
||||||
|
|
||||||
set(GIT_VERSION "${GIT_VERSION_MAJOR}.${GIT_VERSION_MINOR}.${GIT_VERSION_RELEASE}")
|
set(OPENMW_VERSION_COMMITHASH "${COMMITHASH}")
|
||||||
|
set(OPENMW_VERSION_TAGHASH "${TAGHASH}")
|
||||||
if(NOT ${OPENMW_VERSION} STREQUAL ${GIT_VERSION})
|
|
||||||
message(FATAL_ERROR "Silly Zini forgot to update the version again...")
|
|
||||||
else(NOT ${OPENMW_VERSION} STREQUAL ${GIT_VERSION})
|
|
||||||
set(OPENMW_VERSION_MAJOR ${GIT_VERSION_MAJOR})
|
|
||||||
set(OPENMW_VERSION_MINOR ${GIT_VERSION_MINOR})
|
|
||||||
set(OPENMW_VERSION_RELEASE ${GIT_VERSION_RELEASE})
|
|
||||||
|
|
||||||
set(OPENMW_VERSION_COMMITHASH "${COMMITHASH}")
|
|
||||||
set(OPENMW_VERSION_TAGHASH "${TAGHASH}")
|
|
||||||
endif(NOT ${OPENMW_VERSION} STREQUAL ${GIT_VERSION})
|
|
||||||
|
|
||||||
message(STATUS "OpenMW version ${OPENMW_VERSION}")
|
message(STATUS "OpenMW version ${OPENMW_VERSION}")
|
||||||
else(MATCH)
|
else(MATCH)
|
||||||
@ -86,8 +76,6 @@ option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest ang GMock fram
|
|||||||
|
|
||||||
# Sound source selection
|
# Sound source selection
|
||||||
option(USE_FFMPEG "use ffmpeg for sound" ON)
|
option(USE_FFMPEG "use ffmpeg for sound" ON)
|
||||||
option(USE_AUDIERE "use audiere for sound" ON)
|
|
||||||
option(USE_MPG123 "use mpg123 + libsndfile for sound" ON)
|
|
||||||
|
|
||||||
# OS X deployment
|
# OS X deployment
|
||||||
option(OPENMW_OSX_DEPLOYMENT OFF)
|
option(OPENMW_OSX_DEPLOYMENT OFF)
|
||||||
@ -102,13 +90,13 @@ endif(UNIX AND NOT APPLE)
|
|||||||
# Location of morrowind data files
|
# Location of morrowind data files
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
set(MORROWIND_DATA_FILES "./data" CACHE PATH "location of Morrowind data files")
|
set(MORROWIND_DATA_FILES "./data" CACHE PATH "location of Morrowind data files")
|
||||||
set(MORROWIND_RESOURCE_FILES "./resources" CACHE PATH "location of OpenMW resources files")
|
set(OPENMW_RESOURCE_FILES "./resources" CACHE PATH "location of OpenMW resources files")
|
||||||
elseif(UNIX)
|
elseif(UNIX)
|
||||||
set(MORROWIND_DATA_FILES "/usr/share/games/openmw/data/" CACHE PATH "location of Morrowind data files")
|
set(MORROWIND_DATA_FILES "${CMAKE_INSTALL_PREFIX}/share/games/openmw/data/" CACHE PATH "location of Morrowind data files")
|
||||||
set(MORROWIND_RESOURCE_FILES "/usr/share/games/openmw/resources/" CACHE PATH "location of OpenMW resources files")
|
set(OPENMW_RESOURCE_FILES "${CMAKE_INSTALL_PREFIX}/share/games/openmw/resources/" CACHE PATH "location of OpenMW resources files")
|
||||||
else()
|
else()
|
||||||
set(MORROWIND_DATA_FILES "data" CACHE PATH "location of Morrowind data files")
|
set(MORROWIND_DATA_FILES "data" CACHE PATH "location of Morrowind data files")
|
||||||
set(MORROWIND_RESOURCE_FILES "resources" CACHE PATH "location of OpenMW resources files")
|
set(OPENMW_RESOURCE_FILES "resources" CACHE PATH "location of OpenMW resources files")
|
||||||
endif(APPLE)
|
endif(APPLE)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
@ -131,6 +119,7 @@ set(OENGINE_OGRE
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(OENGINE_GUI
|
set(OENGINE_GUI
|
||||||
|
${LIBDIR}/openengine/gui/loglistener.cpp
|
||||||
${LIBDIR}/openengine/gui/manager.cpp
|
${LIBDIR}/openengine/gui/manager.cpp
|
||||||
${LIBDIR}/openengine/gui/layout.hpp
|
${LIBDIR}/openengine/gui/layout.hpp
|
||||||
)
|
)
|
||||||
@ -171,27 +160,6 @@ if (USE_FFMPEG)
|
|||||||
endif (FFMPEG_FOUND)
|
endif (FFMPEG_FOUND)
|
||||||
endif (USE_FFMPEG)
|
endif (USE_FFMPEG)
|
||||||
|
|
||||||
if (USE_AUDIERE AND NOT GOT_SOUND_INPUT)
|
|
||||||
find_package(Audiere)
|
|
||||||
if (AUDIERE_FOUND)
|
|
||||||
set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${AUDIERE_INCLUDE_DIR})
|
|
||||||
set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${AUDIERE_LIBRARY})
|
|
||||||
set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_AUDIERE)
|
|
||||||
set(GOT_SOUND_INPUT 1)
|
|
||||||
endif (AUDIERE_FOUND)
|
|
||||||
endif (USE_AUDIERE AND NOT GOT_SOUND_INPUT)
|
|
||||||
|
|
||||||
if (USE_MPG123 AND NOT GOT_SOUND_INPUT)
|
|
||||||
find_package(MPG123 REQUIRED)
|
|
||||||
find_package(SNDFILE REQUIRED)
|
|
||||||
if (MPG123_FOUND AND SNDFILE_FOUND)
|
|
||||||
set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${MPG123_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR})
|
|
||||||
set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${MPG123_LIBRARY} ${SNDFILE_LIBRARY})
|
|
||||||
set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_MPG123)
|
|
||||||
set(GOT_SOUND_INPUT 1)
|
|
||||||
endif (MPG123_FOUND AND SNDFILE_FOUND)
|
|
||||||
endif (USE_MPG123 AND NOT GOT_SOUND_INPUT)
|
|
||||||
|
|
||||||
if (NOT GOT_SOUND_INPUT)
|
if (NOT GOT_SOUND_INPUT)
|
||||||
message(WARNING "--------------------")
|
message(WARNING "--------------------")
|
||||||
message(WARNING "Failed to find any sound input packages")
|
message(WARNING "Failed to find any sound input packages")
|
||||||
@ -257,6 +225,9 @@ endif ()
|
|||||||
|
|
||||||
|
|
||||||
set(BOOST_COMPONENTS system filesystem program_options)
|
set(BOOST_COMPONENTS system filesystem program_options)
|
||||||
|
if(WIN32)
|
||||||
|
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale)
|
||||||
|
endif(WIN32)
|
||||||
|
|
||||||
IF(BOOST_STATIC)
|
IF(BOOST_STATIC)
|
||||||
set(Boost_USE_STATIC_LIBS ON)
|
set(Boost_USE_STATIC_LIBS ON)
|
||||||
@ -268,16 +239,40 @@ find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
|||||||
find_package(SDL2 REQUIRED)
|
find_package(SDL2 REQUIRED)
|
||||||
find_package(OpenAL REQUIRED)
|
find_package(OpenAL REQUIRED)
|
||||||
find_package(Bullet REQUIRED)
|
find_package(Bullet REQUIRED)
|
||||||
IF(OGRE_STATIC)
|
|
||||||
find_package(Cg)
|
set(OGRE_PLUGIN_INCLUDE_DIRS "")
|
||||||
IF(WIN32)
|
set(OGRE_STATIC_PLUGINS "")
|
||||||
set(OGRE_PLUGIN_INCLUDE_DIRS ${OGRE_Plugin_CgProgramManager_INCLUDE_DIRS} ${OGRE_Plugin_OctreeSceneManager_INCLUDE_DIRS} ${OGRE_Plugin_ParticleFX_INCLUDE_DIRS} ${OGRE_RenderSystem_Direct3D9_INCLUDE_DIRS} ${OGRE_RenderSystem_GL_INCLUDE_DIRS})
|
|
||||||
ELSE(WIN32)
|
macro(add_static_ogre_plugin PLUGIN)
|
||||||
set(OGRE_PLUGIN_INCLUDE_DIRS ${OGRE_Plugin_CgProgramManager_INCLUDE_DIRS} ${OGRE_Plugin_OctreeSceneManager_INCLUDE_DIRS} ${OGRE_Plugin_ParticleFX_INCLUDE_DIRS} ${OGRE_RenderSystem_GL_INCLUDE_DIRS})
|
if(OGRE_${PLUGIN}_FOUND)
|
||||||
ENDIF(WIN32)
|
# strip RenderSystem_ or Plugin_ prefix from plugin name
|
||||||
ENDIF(OGRE_STATIC)
|
string(REPLACE "RenderSystem_" "" PLUGIN_TEMP ${PLUGIN})
|
||||||
|
string(REPLACE "Plugin_" "" PLUGIN_NAME ${PLUGIN_TEMP})
|
||||||
|
add_definitions(-DENABLE_PLUGIN_${PLUGIN_NAME})
|
||||||
|
|
||||||
|
list(APPEND OGRE_PLUGIN_INCLUDE_DIRS ${OGRE_${PLUGIN}_INCLUDE_DIRS})
|
||||||
|
list(APPEND OGRE_STATIC_PLUGINS ${OGRE_${PLUGIN}_LIBRARIES})
|
||||||
|
endif(OGRE_${PLUGIN}_FOUND)
|
||||||
|
endmacro(add_static_ogre_plugin)
|
||||||
|
|
||||||
|
if(OGRE_STATIC)
|
||||||
|
# set up OGRE_PLUGIN_INCLUDE_DIRS and OGRE_STATIC_PLUGINS
|
||||||
|
add_static_ogre_plugin(Plugin_OctreeSceneManager)
|
||||||
|
add_static_ogre_plugin(Plugin_ParticleFX)
|
||||||
|
find_package(Cg)
|
||||||
|
if(Cg_FOUND)
|
||||||
|
add_static_ogre_plugin(Plugin_CgProgramManager)
|
||||||
|
list(APPEND OGRE_STATIC_PLUGINS ${Cg_LIBRARIES})
|
||||||
|
endif(Cg_FOUND)
|
||||||
|
|
||||||
|
add_static_ogre_plugin(RenderSystem_GL)
|
||||||
|
if(WIN32)
|
||||||
|
add_static_ogre_plugin(RenderSystem_Direct3D9)
|
||||||
|
endif(WIN32)
|
||||||
|
endif(OGRE_STATIC)
|
||||||
|
|
||||||
include_directories("."
|
include_directories("."
|
||||||
${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE ${OGRE_PLUGIN_INCLUDE_DIRS}
|
${OGRE_INCLUDE_DIR} ${OGRE_INCLUDE_DIR}/Ogre ${OGRE_INCLUDE_DIR}/OGRE ${OGRE_INCLUDE_DIRS} ${OGRE_PLUGIN_INCLUDE_DIRS}
|
||||||
${SDL2_INCLUDE_DIR}
|
${SDL2_INCLUDE_DIR}
|
||||||
${Boost_INCLUDE_DIR}
|
${Boost_INCLUDE_DIR}
|
||||||
${PLATFORM_INCLUDE_DIR}
|
${PLATFORM_INCLUDE_DIR}
|
||||||
@ -289,6 +284,10 @@ include_directories("."
|
|||||||
|
|
||||||
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})
|
||||||
|
|
||||||
|
if(MYGUI_STATIC)
|
||||||
|
add_definitions(-DMYGUI_STATIC)
|
||||||
|
endif (MYGUI_STATIC)
|
||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
# List used Ogre plugins
|
# List used Ogre plugins
|
||||||
SET(USED_OGRE_PLUGINS ${OGRE_RenderSystem_GL_LIBRARY_REL}
|
SET(USED_OGRE_PLUGINS ${OGRE_RenderSystem_GL_LIBRARY_REL}
|
||||||
@ -368,8 +367,8 @@ configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg.local
|
|||||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg
|
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.cfg
|
||||||
"${OpenMW_BINARY_DIR}/openmw.cfg.install")
|
"${OpenMW_BINARY_DIR}/openmw.cfg.install")
|
||||||
|
|
||||||
configure_file(${OpenMW_SOURCE_DIR}/files/opencs.cfg
|
configure_file(${OpenMW_SOURCE_DIR}/files/opencs.ini
|
||||||
"${OpenMW_BINARY_DIR}/opencs.cfg")
|
"${OpenMW_BINARY_DIR}/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)
|
||||||
@ -434,7 +433,6 @@ IF(NOT WIN32 AND NOT APPLE)
|
|||||||
|
|
||||||
# Install licenses
|
# Install licenses
|
||||||
INSTALL(FILES "DejaVu Font License.txt" DESTINATION "${LICDIR}" )
|
INSTALL(FILES "DejaVu Font License.txt" DESTINATION "${LICDIR}" )
|
||||||
INSTALL(FILES "OFL.txt" DESTINATION "${LICDIR}" )
|
|
||||||
INSTALL(FILES "extern/shiny/License.txt" DESTINATION "${LICDIR}" RENAME "Shiny License.txt" )
|
INSTALL(FILES "extern/shiny/License.txt" DESTINATION "${LICDIR}" RENAME "Shiny License.txt" )
|
||||||
ENDIF (DPKG_PROGRAM)
|
ENDIF (DPKG_PROGRAM)
|
||||||
|
|
||||||
@ -451,7 +449,7 @@ IF(NOT WIN32 AND NOT APPLE)
|
|||||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${SYSCONFDIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
INSTALL(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${SYSCONFDIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||||
IF(BUILD_OPENCS)
|
IF(BUILD_OPENCS)
|
||||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.cfg" DESTINATION "${SYSCONFDIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "opencs")
|
INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${SYSCONFDIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "opencs")
|
||||||
ENDIF(BUILD_OPENCS)
|
ENDIF(BUILD_OPENCS)
|
||||||
|
|
||||||
# Install resources
|
# Install resources
|
||||||
@ -480,7 +478,7 @@ if(WIN32)
|
|||||||
ENDIF(BUILD_MWINIIMPORTER)
|
ENDIF(BUILD_MWINIIMPORTER)
|
||||||
IF(BUILD_OPENCS)
|
IF(BUILD_OPENCS)
|
||||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/opencs.exe" DESTINATION ".")
|
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/opencs.exe" DESTINATION ".")
|
||||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.cfg" DESTINATION ".")
|
INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION ".")
|
||||||
ENDIF(BUILD_OPENCS)
|
ENDIF(BUILD_OPENCS)
|
||||||
|
|
||||||
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".")
|
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".")
|
||||||
@ -618,6 +616,7 @@ if (WIN32)
|
|||||||
4706 # Assignment in conditional expression
|
4706 # Assignment in conditional expression
|
||||||
4738 # Storing 32-bit float result in memory, possible loss of performance
|
4738 # Storing 32-bit float result in memory, possible loss of performance
|
||||||
4986 # Undocumented warning that occurs in the crtdbg.h file
|
4986 # Undocumented warning that occurs in the crtdbg.h file
|
||||||
|
4987 # nonstandard extension used (triggered by setjmp.h)
|
||||||
4996 # Function was declared deprecated
|
4996 # Function was declared deprecated
|
||||||
|
|
||||||
# cause by ogre extensivly
|
# cause by ogre extensivly
|
||||||
@ -634,7 +633,9 @@ if (WIN32)
|
|||||||
4305 # Truncating value (double to float, for example)
|
4305 # Truncating value (double to float, for example)
|
||||||
4309 # Variable overflow, trying to store 128 in a signed char for example
|
4309 # Variable overflow, trying to store 128 in a signed char for example
|
||||||
4355 # Using 'this' in member initialization list
|
4355 # Using 'this' in member initialization list
|
||||||
|
4505 # Unreferenced local function has been removed
|
||||||
4701 # Potentially uninitialized local variable used
|
4701 # Potentially uninitialized local variable used
|
||||||
|
4702 # Unreachable code
|
||||||
4800 # Boolean optimization warning, e.g. myBool = (myInt != 0) instead of myBool = myInt
|
4800 # Boolean optimization warning, e.g. myBool = (myInt != 0) instead of myBool = myInt
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -642,19 +643,31 @@ if (WIN32)
|
|||||||
set(WARNINGS "${WARNINGS} /wd${d}")
|
set(WARNINGS "${WARNINGS} /wd${d}")
|
||||||
endforeach(d)
|
endforeach(d)
|
||||||
|
|
||||||
set_target_properties(shiny PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
# boost::wave has a few issues with signed / unsigned conversions, so we suppress those here
|
||||||
set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
set(SHINY_WARNINGS "${WARNINGS} /wd4245")
|
||||||
|
set_target_properties(shiny PROPERTIES COMPILE_FLAGS ${SHINY_WARNINGS})
|
||||||
|
# there's an unreferenced local variable in the ogre platform, suppress it
|
||||||
|
set(SHINY_OGRE_WARNINGS "${WARNINGS} /wd4101")
|
||||||
|
set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS ${SHINY_OGRE_WARNINGS})
|
||||||
|
set_target_properties(sdl4ogre PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||||
|
set_target_properties(oics PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||||
set_target_properties(components PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
set_target_properties(components PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||||
if (BUILD_LAUNCHER)
|
if (BUILD_LAUNCHER)
|
||||||
set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||||
endif (BUILD_LAUNCHER)
|
endif (BUILD_LAUNCHER)
|
||||||
set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||||
if (BUILD_BSATOOL)
|
if (BUILD_BSATOOL)
|
||||||
set_target_properties(bsatool PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
set_target_properties(bsatool PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||||
endif (BUILD_BSATOOL)
|
endif (BUILD_BSATOOL)
|
||||||
if (BUILD_ESMTOOL)
|
if (BUILD_ESMTOOL)
|
||||||
set_target_properties(esmtool PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
set_target_properties(esmtool PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||||
endif (BUILD_ESMTOOL)
|
endif (BUILD_ESMTOOL)
|
||||||
|
if (BUILD_OPENCS)
|
||||||
|
set_target_properties(opencs PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||||
|
endif (BUILD_OPENCS)
|
||||||
|
if (BUILD_MWINIIMPORTER)
|
||||||
|
set_target_properties(mwiniimport PROPERTIES COMPILE_FLAGS ${WARNINGS})
|
||||||
|
endif (BUILD_MWINIIMPORTER)
|
||||||
endif(MSVC)
|
endif(MSVC)
|
||||||
|
|
||||||
# Same for MinGW
|
# Same for MinGW
|
||||||
@ -687,7 +700,7 @@ if (APPLE)
|
|||||||
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}/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.cfg" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
install(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${INSTALL_SUBDIR}" COMPONENT Runtime)
|
||||||
|
|
||||||
set(CPACK_GENERATOR "DragNDrop")
|
set(CPACK_GENERATOR "DragNDrop")
|
||||||
set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION})
|
set(CPACK_PACKAGE_VERSION ${OPENMW_VERSION})
|
||||||
|
@ -333,7 +333,7 @@ int load(Arguments& info)
|
|||||||
|
|
||||||
// Is the user interested in this record type?
|
// Is the user interested in this record type?
|
||||||
bool interested = true;
|
bool interested = true;
|
||||||
if (info.types.size() > 0)
|
if (!info.types.empty())
|
||||||
{
|
{
|
||||||
std::vector<std::string>::iterator match;
|
std::vector<std::string>::iterator match;
|
||||||
match = std::find(info.types.begin(), info.types.end(),
|
match = std::find(info.types.begin(), info.types.end(),
|
||||||
|
@ -387,7 +387,7 @@ std::string magicEffectLabel(int idx)
|
|||||||
"sEffectSummonCreature04",
|
"sEffectSummonCreature04",
|
||||||
"sEffectSummonCreature05"
|
"sEffectSummonCreature05"
|
||||||
};
|
};
|
||||||
if (idx >= 0 && idx <= 143)
|
if (idx >= 0 && idx <= 142)
|
||||||
return magicEffectLabels[idx];
|
return magicEffectLabels[idx];
|
||||||
else
|
else
|
||||||
return "Invalid";
|
return "Invalid";
|
||||||
@ -471,7 +471,7 @@ std::string skillLabel(int idx)
|
|||||||
"Speechcraft",
|
"Speechcraft",
|
||||||
"Hand-to-hand"
|
"Hand-to-hand"
|
||||||
};
|
};
|
||||||
if (idx >= 0 && idx <= 27)
|
if (idx >= 0 && idx <= 26)
|
||||||
return skillLabels[idx];
|
return skillLabels[idx];
|
||||||
else
|
else
|
||||||
return "Invalid";
|
return "Invalid";
|
||||||
@ -498,7 +498,7 @@ std::string rangeTypeLabel(int idx)
|
|||||||
"Touch",
|
"Touch",
|
||||||
"Target"
|
"Target"
|
||||||
};
|
};
|
||||||
if (idx >= 0 && idx <= 3)
|
if (idx >= 0 && idx <= 2)
|
||||||
return rangeTypeLabels[idx];
|
return rangeTypeLabels[idx];
|
||||||
else
|
else
|
||||||
return "Invalid";
|
return "Invalid";
|
||||||
|
@ -124,7 +124,7 @@ void printEffectList(ESM::EffectList effects)
|
|||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
std::vector<ESM::ENAMstruct>::iterator eit;
|
std::vector<ESM::ENAMstruct>::iterator eit;
|
||||||
for (eit = effects.mList.begin(); eit != effects.mList.end(); eit++)
|
for (eit = effects.mList.begin(); eit != effects.mList.end(); ++eit)
|
||||||
{
|
{
|
||||||
std::cout << " Effect[" << i << "]: " << magicEffectLabel(eit->mEffectID)
|
std::cout << " Effect[" << i << "]: " << magicEffectLabel(eit->mEffectID)
|
||||||
<< " (" << eit->mEffectID << ")" << std::endl;
|
<< " (" << eit->mEffectID << ")" << std::endl;
|
||||||
@ -651,7 +651,7 @@ void Record<ESM::Dialogue>::print()
|
|||||||
// Sadly, there are no DialInfos, because the loader dumps as it
|
// Sadly, there are no DialInfos, because the loader dumps as it
|
||||||
// loads, rather than loading and then dumping. :-( Anyone mind if
|
// loads, rather than loading and then dumping. :-( Anyone mind if
|
||||||
// I change this?
|
// I change this?
|
||||||
std::vector<ESM::DialInfo>::iterator iit;
|
ESM::Dialogue::InfoContainer::iterator iit;
|
||||||
for (iit = mData.mInfo.begin(); iit != mData.mInfo.end(); iit++)
|
for (iit = mData.mInfo.begin(); iit != mData.mInfo.end(); iit++)
|
||||||
std::cout << "INFO!" << iit->mId << std::endl;
|
std::cout << "INFO!" << iit->mId << std::endl;
|
||||||
}
|
}
|
||||||
@ -707,9 +707,9 @@ void Record<ESM::Faction>::print()
|
|||||||
std::cout << " Faction Reaction: "
|
std::cout << " Faction Reaction: "
|
||||||
<< mData.mData.mRankData[i].mFactReaction << std::endl;
|
<< mData.mData.mRankData[i].mFactReaction << std::endl;
|
||||||
}
|
}
|
||||||
std::vector<ESM::Faction::Reaction>::iterator rit;
|
std::map<std::string, int>::iterator rit;
|
||||||
for (rit = mData.mReactions.begin(); rit != mData.mReactions.end(); rit++)
|
for (rit = mData.mReactions.begin(); rit != mData.mReactions.end(); rit++)
|
||||||
std::cout << " Reaction: " << rit->mReaction << " = " << rit->mFaction << std::endl;
|
std::cout << " Reaction: " << rit->second << " = " << rit->first << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
@ -94,15 +94,6 @@ if(NOT WIN32)
|
|||||||
endif(NOT WIN32)
|
endif(NOT WIN32)
|
||||||
|
|
||||||
# Main executable
|
# Main executable
|
||||||
IF(OGRE_STATIC)
|
|
||||||
IF(WIN32)
|
|
||||||
ADD_DEFINITIONS(-DENABLE_PLUGIN_Direct3D9 -DENABLE_PLUGIN_GL)
|
|
||||||
set(OGRE_STATIC_PLUGINS ${OGRE_RenderSystem_Direct3D9_LIBRARIES} ${OGRE_RenderSystem_GL_LIBRARIES})
|
|
||||||
ELSE(WIN32)
|
|
||||||
ADD_DEFINITIONS(-DENABLE_PLUGIN_GL)
|
|
||||||
set(OGRE_STATIC_PLUGINS ${OGRE_RenderSystem_GL_LIBRARIES})
|
|
||||||
ENDIF(WIN32)
|
|
||||||
ENDIF(OGRE_STATIC)
|
|
||||||
add_executable(omwlauncher
|
add_executable(omwlauncher
|
||||||
${GUI_TYPE}
|
${GUI_TYPE}
|
||||||
${LAUNCHER}
|
${LAUNCHER}
|
||||||
@ -116,7 +107,7 @@ target_link_libraries(omwlauncher
|
|||||||
${Boost_LIBRARIES}
|
${Boost_LIBRARIES}
|
||||||
${OGRE_LIBRARIES}
|
${OGRE_LIBRARIES}
|
||||||
${OGRE_STATIC_PLUGINS}
|
${OGRE_STATIC_PLUGINS}
|
||||||
${SDL2_LIBRARY}
|
${SDL2_LIBRARY_ONLY}
|
||||||
${QT_LIBRARIES}
|
${QT_LIBRARIES}
|
||||||
components
|
components
|
||||||
)
|
)
|
||||||
|
@ -214,13 +214,13 @@ QStringList Launcher::GraphicsPage::getAvailableOptions(const QString &key, Ogre
|
|||||||
uint row = 0;
|
uint row = 0;
|
||||||
Ogre::ConfigOptionMap options = renderer->getConfigOptions();
|
Ogre::ConfigOptionMap options = renderer->getConfigOptions();
|
||||||
|
|
||||||
for (Ogre::ConfigOptionMap::iterator i = options.begin (); i != options.end (); i++, row++)
|
for (Ogre::ConfigOptionMap::iterator i = options.begin (); i != options.end (); ++i, ++row)
|
||||||
{
|
{
|
||||||
Ogre::StringVector::iterator opt_it;
|
Ogre::StringVector::iterator opt_it;
|
||||||
uint idx = 0;
|
uint idx = 0;
|
||||||
|
|
||||||
for (opt_it = i->second.possibleValues.begin();
|
for (opt_it = i->second.possibleValues.begin();
|
||||||
opt_it != i->second.possibleValues.end(); opt_it++, idx++)
|
opt_it != i->second.possibleValues.end(); ++opt_it, ++idx)
|
||||||
{
|
{
|
||||||
if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0) {
|
if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0) {
|
||||||
result << ((key == "FSAA") ? QString("MSAA ") : QString("")) + QString::fromStdString((*opt_it).c_str()).simplified();
|
result << ((key == "FSAA") ? QString("MSAA ") : QString("")) + QString::fromStdString((*opt_it).c_str()).simplified();
|
||||||
|
@ -41,11 +41,11 @@ Launcher::MainDialog::MainDialog(QWidget *parent)
|
|||||||
// Check if the font is installed
|
// Check if the font is installed
|
||||||
if (!fonts.contains("EB Garamond")) {
|
if (!fonts.contains("EB Garamond")) {
|
||||||
|
|
||||||
QString font = QString::fromStdString(mCfgMgr.getGlobalDataPath().string()) + QString("resources/mygui/EBGaramond-Regular.ttf");
|
QString font = QString::fromUtf8(mCfgMgr.getGlobalDataPath().string().c_str()) + QString("resources/mygui/EBGaramond-Regular.ttf");
|
||||||
file.setFileName(font);
|
file.setFileName(font);
|
||||||
|
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
font = QString::fromStdString(mCfgMgr.getLocalPath().string()) + QString("resources/mygui/EBGaramond-Regular.ttf");
|
font = QString::fromUtf8(mCfgMgr.getLocalPath().string().c_str()) + QString("resources/mygui/EBGaramond-Regular.ttf");
|
||||||
}
|
}
|
||||||
|
|
||||||
fontDatabase.addApplicationFont(font);
|
fontDatabase.addApplicationFont(font);
|
||||||
@ -243,7 +243,7 @@ bool Launcher::MainDialog::showFirstRunDialog()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create the file if it doesn't already exist, else the importer will fail
|
// Create the file if it doesn't already exist, else the importer will fail
|
||||||
QString path = QString::fromStdString(mCfgMgr.getUserConfigPath().string()) + QString("openmw.cfg");
|
QString path = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str()) + QString("openmw.cfg");
|
||||||
QFile file(path);
|
QFile file(path);
|
||||||
|
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
@ -358,7 +358,7 @@ bool Launcher::MainDialog::setupLauncherSettings()
|
|||||||
{
|
{
|
||||||
mLauncherSettings.setMultiValueEnabled(true);
|
mLauncherSettings.setMultiValueEnabled(true);
|
||||||
|
|
||||||
QString userPath = QString::fromStdString(mCfgMgr.getUserConfigPath().string());
|
QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str());
|
||||||
|
|
||||||
QStringList paths;
|
QStringList paths;
|
||||||
paths.append(QString("launcher.cfg"));
|
paths.append(QString("launcher.cfg"));
|
||||||
@ -464,8 +464,8 @@ bool Launcher::expansions(Launcher::UnshieldThread& cd)
|
|||||||
|
|
||||||
bool Launcher::MainDialog::setupGameSettings()
|
bool Launcher::MainDialog::setupGameSettings()
|
||||||
{
|
{
|
||||||
QString userPath = QString::fromStdString(mCfgMgr.getUserConfigPath().string());
|
QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str());
|
||||||
QString globalPath = QString::fromStdString(mCfgMgr.getGlobalPath().string());
|
QString globalPath = QString::fromUtf8(mCfgMgr.getGlobalPath().string().c_str());
|
||||||
|
|
||||||
// Load the user config file first, separately
|
// Load the user config file first, separately
|
||||||
// So we can write it properly, uncontaminated
|
// So we can write it properly, uncontaminated
|
||||||
@ -594,7 +594,7 @@ bool Launcher::MainDialog::setupGameSettings()
|
|||||||
|
|
||||||
while(expansions(cd));
|
while(expansions(cd));
|
||||||
|
|
||||||
selectedFile = QString::fromStdString(cd.GetMWEsmPath());
|
selectedFile = QString::fromUtf8(cd.GetMWEsmPath().c_str());
|
||||||
}
|
}
|
||||||
#endif // WIN32
|
#endif // WIN32
|
||||||
|
|
||||||
@ -615,8 +615,8 @@ bool Launcher::MainDialog::setupGraphicsSettings()
|
|||||||
{
|
{
|
||||||
mGraphicsSettings.setMultiValueEnabled(false);
|
mGraphicsSettings.setMultiValueEnabled(false);
|
||||||
|
|
||||||
QString userPath = QString::fromStdString(mCfgMgr.getUserConfigPath().string());
|
QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str());
|
||||||
QString globalPath = QString::fromStdString(mCfgMgr.getGlobalPath().string());
|
QString globalPath = QString::fromUtf8(mCfgMgr.getGlobalPath().string().c_str());
|
||||||
|
|
||||||
QFile localDefault(QString("settings-default.cfg"));
|
QFile localDefault(QString("settings-default.cfg"));
|
||||||
QFile globalDefault(globalPath + QString("settings-default.cfg"));
|
QFile globalDefault(globalPath + QString("settings-default.cfg"));
|
||||||
@ -702,7 +702,7 @@ bool Launcher::MainDialog::writeSettings()
|
|||||||
mGraphicsPage->saveSettings();
|
mGraphicsPage->saveSettings();
|
||||||
mDataFilesPage->saveSettings();
|
mDataFilesPage->saveSettings();
|
||||||
|
|
||||||
QString userPath = QString::fromStdString(mCfgMgr.getUserConfigPath().string());
|
QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str());
|
||||||
QDir dir(userPath);
|
QDir dir(userPath);
|
||||||
|
|
||||||
if (!dir.exists()) {
|
if (!dir.exists()) {
|
||||||
@ -806,7 +806,7 @@ void Launcher::MainDialog::play()
|
|||||||
msgBox.setWindowTitle(tr("No game file selected"));
|
msgBox.setWindowTitle(tr("No game file selected"));
|
||||||
msgBox.setIcon(QMessageBox::Warning);
|
msgBox.setIcon(QMessageBox::Warning);
|
||||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||||
msgBox.setText(tr("<br><b>You do not have no game file selected.</b><br><br> \
|
msgBox.setText(tr("<br><b>You do not have a game file selected.</b><br><br> \
|
||||||
OpenMW will not start without a game file selected.<br>"));
|
OpenMW will not start without a game file selected.<br>"));
|
||||||
msgBox.exec();
|
msgBox.exec();
|
||||||
return;
|
return;
|
||||||
|
@ -45,7 +45,8 @@ void Launcher::GameSettings::validatePaths()
|
|||||||
Files::PathContainer dataDirs;
|
Files::PathContainer dataDirs;
|
||||||
|
|
||||||
foreach (const QString &path, paths) {
|
foreach (const QString &path, paths) {
|
||||||
dataDirs.push_back(Files::PathContainer::value_type(path.toStdString()));
|
QByteArray bytes = path.toUtf8();
|
||||||
|
dataDirs.push_back(Files::PathContainer::value_type(std::string(bytes.constData(), bytes.length())));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the data dirs to convert the tokenized paths
|
// Parse the data dirs to convert the tokenized paths
|
||||||
@ -53,7 +54,7 @@ void Launcher::GameSettings::validatePaths()
|
|||||||
mDataDirs.clear();
|
mDataDirs.clear();
|
||||||
|
|
||||||
for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) {
|
for (Files::PathContainer::iterator it = dataDirs.begin(); it != dataDirs.end(); ++it) {
|
||||||
QString path = QString::fromStdString(it->string());
|
QString path = QString::fromUtf8(it->string().c_str());
|
||||||
path.remove(QChar('\"'));
|
path.remove(QChar('\"'));
|
||||||
|
|
||||||
QDir dir(path);
|
QDir dir(path);
|
||||||
@ -68,12 +69,13 @@ void Launcher::GameSettings::validatePaths()
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
dataDirs.clear();
|
dataDirs.clear();
|
||||||
dataDirs.push_back(Files::PathContainer::value_type(local.toStdString()));
|
QByteArray bytes = local.toUtf8();
|
||||||
|
dataDirs.push_back(Files::PathContainer::value_type(std::string(bytes.constData(), bytes.length())));
|
||||||
|
|
||||||
mCfgMgr.processPaths(dataDirs);
|
mCfgMgr.processPaths(dataDirs);
|
||||||
|
|
||||||
if (!dataDirs.empty()) {
|
if (!dataDirs.empty()) {
|
||||||
QString path = QString::fromStdString(dataDirs.front().string());
|
QString path = QString::fromUtf8(dataDirs.front().string().c_str());
|
||||||
path.remove(QChar('\"'));
|
path.remove(QChar('\"'));
|
||||||
|
|
||||||
QDir dir(path);
|
QDir dir(path);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "unshieldthread.hpp"
|
#include "unshieldthread.hpp"
|
||||||
|
|
||||||
#include <fstream>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
namespace bfs = boost::filesystem;
|
namespace bfs = boost::filesystem;
|
||||||
@ -49,7 +49,7 @@ namespace
|
|||||||
|
|
||||||
std::string read_to_string(const bfs::path& path)
|
std::string read_to_string(const bfs::path& path)
|
||||||
{
|
{
|
||||||
std::ifstream strstream(path.c_str(), std::ios::in | std::ios::binary);
|
bfs::ifstream strstream(path, std::ios::in | std::ios::binary);
|
||||||
std::string str;
|
std::string str;
|
||||||
|
|
||||||
strstream.seekg(0, std::ios::end);
|
strstream.seekg(0, std::ios::end);
|
||||||
@ -201,7 +201,7 @@ namespace
|
|||||||
add_setting("Archives", "Archive 1", "Bloodmoon.bsa", ini);
|
add_setting("Archives", "Archive 1", "Bloodmoon.bsa", ini);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ofstream inistream(ini_path.c_str());
|
bfs::ofstream inistream((ini_path));
|
||||||
inistream << ini;
|
inistream << ini;
|
||||||
inistream.close();
|
inistream.close();
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "importer.hpp"
|
#include "importer.hpp"
|
||||||
#include <boost/iostreams/device/file.hpp>
|
|
||||||
#include <boost/iostreams/stream.hpp>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
@ -9,6 +8,10 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <components/misc/stringops.hpp>
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
|
||||||
|
namespace bfs = boost::filesystem;
|
||||||
|
|
||||||
MwIniImporter::MwIniImporter()
|
MwIniImporter::MwIniImporter()
|
||||||
: mVerbose(false)
|
: mVerbose(false)
|
||||||
@ -661,7 +664,7 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(const std::string& filenam
|
|||||||
|
|
||||||
std::string section("");
|
std::string section("");
|
||||||
MwIniImporter::multistrmap map;
|
MwIniImporter::multistrmap map;
|
||||||
boost::iostreams::stream<boost::iostreams::file_source>file(filename.c_str());
|
bfs::ifstream file((bfs::path(filename)));
|
||||||
ToUTF8::Utf8Encoder encoder(mEncoding);
|
ToUTF8::Utf8Encoder encoder(mEncoding);
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
@ -674,6 +677,10 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(const std::string& filenam
|
|||||||
line = line.substr(0, line.length()-1);
|
line = line.substr(0, line.length()-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(line.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(line[0] == '[') {
|
if(line[0] == '[') {
|
||||||
int pos = line.find(']');
|
int pos = line.find(']');
|
||||||
if(pos < 2) {
|
if(pos < 2) {
|
||||||
@ -690,10 +697,6 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(const std::string& filenam
|
|||||||
line = line.substr(0,comment_pos);
|
line = line.substr(0,comment_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(line.empty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pos = line.find("=");
|
int pos = line.find("=");
|
||||||
if(pos < 1) {
|
if(pos < 1) {
|
||||||
continue;
|
continue;
|
||||||
@ -720,7 +723,7 @@ MwIniImporter::multistrmap MwIniImporter::loadCfgFile(const std::string& filenam
|
|||||||
std::cout << "load cfg file: " << filename << std::endl;
|
std::cout << "load cfg file: " << filename << std::endl;
|
||||||
|
|
||||||
MwIniImporter::multistrmap map;
|
MwIniImporter::multistrmap map;
|
||||||
boost::iostreams::stream<boost::iostreams::file_source>file(filename.c_str());
|
bfs::ifstream file((bfs::path(filename)));
|
||||||
|
|
||||||
std::string line;
|
std::string line;
|
||||||
while (std::getline(file, line)) {
|
while (std::getline(file, line)) {
|
||||||
@ -858,7 +861,7 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini) co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MwIniImporter::writeToFile(boost::iostreams::stream<boost::iostreams::file_sink> &out, const multistrmap &cfg) {
|
void MwIniImporter::writeToFile(std::ostream &out, const multistrmap &cfg) {
|
||||||
|
|
||||||
for(multistrmap::const_iterator it=cfg.begin(); it != cfg.end(); ++it) {
|
for(multistrmap::const_iterator it=cfg.begin(); it != cfg.end(); ++it) {
|
||||||
for(std::vector<std::string>::const_iterator entry=it->second.begin(); entry != it->second.end(); ++entry) {
|
for(std::vector<std::string>::const_iterator entry=it->second.begin(); entry != it->second.end(); ++entry) {
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
#ifndef MWINIIMPORTER_IMPORTER
|
#ifndef MWINIIMPORTER_IMPORTER
|
||||||
#define MWINIIMPORTER_IMPORTER 1
|
#define MWINIIMPORTER_IMPORTER 1
|
||||||
|
|
||||||
#include <boost/iostreams/device/file.hpp>
|
|
||||||
#include <boost/iostreams/stream.hpp>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
#include <iosfwd>
|
||||||
|
|
||||||
#include <components/to_utf8/to_utf8.hpp>
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
|
|
||||||
@ -24,7 +23,7 @@ class MwIniImporter {
|
|||||||
void mergeFallback(multistrmap &cfg, const multistrmap &ini) const;
|
void mergeFallback(multistrmap &cfg, const multistrmap &ini) const;
|
||||||
void importGameFiles(multistrmap &cfg, const multistrmap &ini) const;
|
void importGameFiles(multistrmap &cfg, const multistrmap &ini) const;
|
||||||
void importArchives(multistrmap &cfg, const multistrmap &ini) const;
|
void importArchives(multistrmap &cfg, const multistrmap &ini) const;
|
||||||
static void writeToFile(boost::iostreams::stream<boost::iostreams::file_sink> &out, const multistrmap &cfg);
|
static void writeToFile(std::ostream &out, const multistrmap &cfg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void insertMultistrmap(multistrmap &cfg, const std::string& key, const std::string& value);
|
static void insertMultistrmap(multistrmap &cfg, const std::string& key, const std::string& value);
|
||||||
|
@ -1,14 +1,59 @@
|
|||||||
#include "importer.hpp"
|
#include "importer.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
|
||||||
namespace bpo = boost::program_options;
|
namespace bpo = boost::program_options;
|
||||||
|
namespace bfs = boost::filesystem;
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
|
#else
|
||||||
|
|
||||||
|
// Include on Windows only
|
||||||
|
#include <boost/locale.hpp>
|
||||||
|
|
||||||
|
class utf8argv
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
utf8argv(int argc, wchar_t *wargv[])
|
||||||
|
{
|
||||||
|
args.reserve(argc);
|
||||||
|
argv = new const char *[argc];
|
||||||
|
|
||||||
|
for (int i = 0; i < argc; ++i) {
|
||||||
|
args.push_back(boost::locale::conv::utf_to_utf<char>(wargv[i]));
|
||||||
|
argv[i] = args.back().c_str();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~utf8argv() { delete[] argv; }
|
||||||
|
char **get() const { return const_cast<char **>(argv); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
const char **argv;
|
||||||
|
std::vector<std::string> args;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The only way to pass Unicode on Winodws with CLI is to use wide
|
||||||
|
characters interface which presents UTF-16 encoding. The rest of
|
||||||
|
OpenMW application stack assumes UTF-8 encoding, therefore this
|
||||||
|
conversion.
|
||||||
|
|
||||||
|
For boost::filesystem::path::imbue see components/files/windowspath.cpp
|
||||||
|
*/
|
||||||
|
int wmain(int argc, wchar_t *wargv[]) {
|
||||||
|
utf8argv converter(argc, wargv);
|
||||||
|
char **argv = converter.get();
|
||||||
|
boost::filesystem::path::imbue(boost::locale::generator().generate(""));
|
||||||
|
#endif
|
||||||
bpo::options_description desc("Syntax: mwiniimporter <options> inifile configfile\nAllowed options");
|
bpo::options_description desc("Syntax: mwiniimporter <options> inifile configfile\nAllowed options");
|
||||||
bpo::positional_options_description p_desc;
|
bpo::positional_options_description p_desc;
|
||||||
desc.add_options()
|
desc.add_options()
|
||||||
@ -94,7 +139,7 @@ int main(int argc, char *argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "write to: " << outputFile << std::endl;
|
std::cout << "write to: " << outputFile << std::endl;
|
||||||
boost::iostreams::stream<boost::iostreams::file_sink> file(outputFile);
|
bfs::ofstream file((bfs::path(outputFile)));
|
||||||
importer.writeToFile(file, cfg);
|
importer.writeToFile(file, cfg);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -5,11 +5,11 @@ opencs_units (. editor)
|
|||||||
set (CMAKE_BUILD_TYPE DEBUG)
|
set (CMAKE_BUILD_TYPE DEBUG)
|
||||||
|
|
||||||
opencs_units (model/doc
|
opencs_units (model/doc
|
||||||
document operation saving
|
document operation saving documentmanager loader
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units_noqt (model/doc
|
opencs_units_noqt (model/doc
|
||||||
documentmanager stage savingstate savingstages
|
stage savingstate savingstages
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_hdrs_noqt (model/doc
|
opencs_hdrs_noqt (model/doc
|
||||||
@ -18,7 +18,7 @@ opencs_hdrs_noqt (model/doc
|
|||||||
|
|
||||||
|
|
||||||
opencs_units (model/world
|
opencs_units (model/world
|
||||||
idtable idtableproxymodel regionmap data
|
idtable idtableproxymodel regionmap data commanddispatcher
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ opencs_units_noqt (model/tools
|
|||||||
|
|
||||||
opencs_units (view/doc
|
opencs_units (view/doc
|
||||||
viewmanager view operations operation subview startup filedialog newgame
|
viewmanager view operations operation subview startup filedialog newgame
|
||||||
filewidget adjusterwidget
|
filewidget adjusterwidget loader
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ opencs_hdrs_noqt (view/doc
|
|||||||
opencs_units (view/world
|
opencs_units (view/world
|
||||||
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
|
table tablesubview scriptsubview util regionmapsubview tablebottombox creator genericcreator
|
||||||
cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool
|
cellcreator referenceablecreator referencecreator scenesubview scenetoolbar scenetool
|
||||||
scenetoolmode infocreator scriptedit dialoguesubview previewsubview regionmap
|
scenetoolmode infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units (view/render
|
opencs_units (view/render
|
||||||
@ -88,34 +88,30 @@ opencs_units_noqt (view/tools
|
|||||||
)
|
)
|
||||||
|
|
||||||
opencs_units (view/settings
|
opencs_units (view/settings
|
||||||
abstractblock
|
settingwindow
|
||||||
proxyblock
|
dialog
|
||||||
abstractwidget
|
page
|
||||||
usersettingsdialog
|
view
|
||||||
datadisplayformatpage
|
booleanview
|
||||||
windowpage
|
textview
|
||||||
|
listview
|
||||||
|
rangeview
|
||||||
|
resizeablestackedwidget
|
||||||
|
spinbox
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units_noqt (view/settings
|
opencs_units_noqt (view/settings
|
||||||
abstractpage
|
frame
|
||||||
blankpage
|
|
||||||
groupblock
|
|
||||||
customblock
|
|
||||||
groupbox
|
|
||||||
itemblock
|
|
||||||
settingwidget
|
|
||||||
toggleblock
|
|
||||||
support
|
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units (model/settings
|
opencs_units (model/settings
|
||||||
usersettings
|
usersettings
|
||||||
settingcontainer
|
setting
|
||||||
|
connector
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units_noqt (model/settings
|
opencs_hdrs_noqt (model/settings
|
||||||
support
|
support
|
||||||
settingsitem
|
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units_noqt (model/filter
|
opencs_units_noqt (model/filter
|
||||||
@ -149,6 +145,10 @@ if(WIN32)
|
|||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
set(BOOST_COMPONENTS system filesystem program_options thread wave)
|
set(BOOST_COMPONENTS system filesystem program_options thread wave)
|
||||||
|
if(WIN32)
|
||||||
|
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale)
|
||||||
|
endif(WIN32)
|
||||||
|
|
||||||
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
||||||
|
|
||||||
find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED)
|
find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED)
|
||||||
@ -192,6 +192,7 @@ endif(APPLE)
|
|||||||
|
|
||||||
target_link_libraries(opencs
|
target_link_libraries(opencs
|
||||||
${OGRE_LIBRARIES}
|
${OGRE_LIBRARIES}
|
||||||
|
${OGRE_STATIC_PLUGINS}
|
||||||
${SHINY_LIBRARIES}
|
${SHINY_LIBRARIES}
|
||||||
${Boost_LIBRARIES}
|
${Boost_LIBRARIES}
|
||||||
${QT_LIBRARIES}
|
${QT_LIBRARIES}
|
||||||
|
@ -20,14 +20,15 @@
|
|||||||
#include "model/world/data.hpp"
|
#include "model/world/data.hpp"
|
||||||
|
|
||||||
CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
|
CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
|
||||||
: mDocumentManager (mCfgMgr), mViewManager (mDocumentManager),
|
: mUserSettings (mCfgMgr), mDocumentManager (mCfgMgr), mViewManager (mDocumentManager),
|
||||||
mIpcServerName ("org.openmw.OpenCS")
|
mIpcServerName ("org.openmw.OpenCS")
|
||||||
{
|
{
|
||||||
std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig();
|
std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig();
|
||||||
|
|
||||||
setupDataFiles (config.first);
|
setupDataFiles (config.first);
|
||||||
|
|
||||||
CSMSettings::UserSettings::instance().loadSettings ("opencs.cfg");
|
CSMSettings::UserSettings::instance().loadSettings ("opencs.ini");
|
||||||
|
mSettings.setModel (CSMSettings::UserSettings::instance());
|
||||||
|
|
||||||
ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string());
|
ogreInit.init ((mCfgMgr.getUserConfigPath() / "opencsOgre.log").string());
|
||||||
|
|
||||||
@ -37,6 +38,11 @@ CS::Editor::Editor (OgreInit::OgreInit& ogreInit)
|
|||||||
mNewGame.setLocalData (mLocal);
|
mNewGame.setLocalData (mLocal);
|
||||||
mFileDialog.setLocalData (mLocal);
|
mFileDialog.setLocalData (mLocal);
|
||||||
|
|
||||||
|
connect (&mDocumentManager, SIGNAL (documentAdded (CSMDoc::Document *)),
|
||||||
|
this, SLOT (documentAdded (CSMDoc::Document *)));
|
||||||
|
connect (&mDocumentManager, SIGNAL (lastDocumentDeleted()),
|
||||||
|
this, SLOT (lastDocumentDeleted()));
|
||||||
|
|
||||||
connect (&mViewManager, SIGNAL (newGameRequest ()), this, SLOT (createGame ()));
|
connect (&mViewManager, SIGNAL (newGameRequest ()), this, SLOT (createGame ()));
|
||||||
connect (&mViewManager, SIGNAL (newAddonRequest ()), this, SLOT (createAddon ()));
|
connect (&mViewManager, SIGNAL (newAddonRequest ()), this, SLOT (createAddon ()));
|
||||||
connect (&mViewManager, SIGNAL (loadDocumentRequest ()), this, SLOT (loadDocument ()));
|
connect (&mViewManager, SIGNAL (loadDocumentRequest ()), this, SLOT (loadDocument ()));
|
||||||
@ -84,6 +90,9 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
|
|||||||
|
|
||||||
mCfgMgr.readConfiguration(variables, desc);
|
mCfgMgr.readConfiguration(variables, desc);
|
||||||
|
|
||||||
|
mDocumentManager.setEncoding (
|
||||||
|
ToUTF8::calculateEncoding (variables["encoding"].as<std::string>()));
|
||||||
|
|
||||||
mDocumentManager.setResourceDir (mResources = variables["resources"].as<std::string>());
|
mDocumentManager.setResourceDir (mResources = variables["resources"].as<std::string>());
|
||||||
|
|
||||||
mFsStrict = variables["fs-strict"].as<bool>();
|
mFsStrict = variables["fs-strict"].as<bool>();
|
||||||
@ -117,6 +126,13 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
|
|||||||
|
|
||||||
dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end());
|
dataDirs.insert (dataDirs.end(), dataLocal.begin(), dataLocal.end());
|
||||||
|
|
||||||
|
//iterate the data directories and add them to the file dialog for loading
|
||||||
|
for (Files::PathContainer::const_iterator iter = dataDirs.begin(); iter != dataDirs.end(); ++iter)
|
||||||
|
{
|
||||||
|
QString path = QString::fromUtf8 (iter->string().c_str());
|
||||||
|
mFileDialog.addFiles(path);
|
||||||
|
}
|
||||||
|
|
||||||
return std::make_pair (dataDirs, variables["fallback-archive"].as<std::vector<std::string> >());
|
return std::make_pair (dataDirs, variables["fallback-archive"].as<std::vector<std::string> >());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,9 +166,8 @@ void CS::Editor::openFiles (const boost::filesystem::path &savePath)
|
|||||||
foreach (const QString &path, mFileDialog.selectedFilePaths())
|
foreach (const QString &path, mFileDialog.selectedFilePaths())
|
||||||
files.push_back(path.toUtf8().constData());
|
files.push_back(path.toUtf8().constData());
|
||||||
|
|
||||||
CSMDoc::Document *document = mDocumentManager.addDocument (files, savePath, false);
|
mDocumentManager.addDocument (files, savePath, false);
|
||||||
|
|
||||||
mViewManager.addView (document);
|
|
||||||
mFileDialog.hide();
|
mFileDialog.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,9 +181,8 @@ void CS::Editor::createNewFile (const boost::filesystem::path &savePath)
|
|||||||
|
|
||||||
files.push_back(mFileDialog.filename().toUtf8().constData());
|
files.push_back(mFileDialog.filename().toUtf8().constData());
|
||||||
|
|
||||||
CSMDoc::Document *document = mDocumentManager.addDocument (files, savePath, true);
|
mDocumentManager.addDocument (files, savePath, true);
|
||||||
|
|
||||||
mViewManager.addView (document);
|
|
||||||
mFileDialog.hide();
|
mFileDialog.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,9 +192,7 @@ void CS::Editor::createNewGame (const boost::filesystem::path& file)
|
|||||||
|
|
||||||
files.push_back (file);
|
files.push_back (file);
|
||||||
|
|
||||||
CSMDoc::Document *document = mDocumentManager.addDocument (files, file, true);
|
mDocumentManager.addDocument (files, file, true);
|
||||||
|
|
||||||
mViewManager.addView (document);
|
|
||||||
|
|
||||||
mNewGame.hide();
|
mNewGame.hide();
|
||||||
}
|
}
|
||||||
@ -287,3 +299,13 @@ std::auto_ptr<sh::Factory> CS::Editor::setupGraphics()
|
|||||||
|
|
||||||
return factory;
|
return factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CS::Editor::documentAdded (CSMDoc::Document *document)
|
||||||
|
{
|
||||||
|
mViewManager.addView (document);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CS::Editor::lastDocumentDeleted()
|
||||||
|
{
|
||||||
|
exit (0);
|
||||||
|
}
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
#include "view/doc/filedialog.hpp"
|
#include "view/doc/filedialog.hpp"
|
||||||
#include "view/doc/newgame.hpp"
|
#include "view/doc/newgame.hpp"
|
||||||
|
|
||||||
#include "view/settings/usersettingsdialog.hpp"
|
#include "view/settings/dialog.hpp"
|
||||||
|
|
||||||
namespace OgreInit
|
namespace OgreInit
|
||||||
{
|
{
|
||||||
@ -43,7 +43,7 @@ namespace CS
|
|||||||
CSVDoc::ViewManager mViewManager;
|
CSVDoc::ViewManager mViewManager;
|
||||||
CSVDoc::StartupDialogue mStartup;
|
CSVDoc::StartupDialogue mStartup;
|
||||||
CSVDoc::NewGameDialogue mNewGame;
|
CSVDoc::NewGameDialogue mNewGame;
|
||||||
CSVSettings::UserSettingsDialog mSettings;
|
CSVSettings::Dialog mSettings;
|
||||||
CSVDoc::FileDialog mFileDialog;
|
CSVDoc::FileDialog mFileDialog;
|
||||||
boost::filesystem::path mLocal;
|
boost::filesystem::path mLocal;
|
||||||
boost::filesystem::path mResources;
|
boost::filesystem::path mResources;
|
||||||
@ -85,6 +85,10 @@ namespace CS
|
|||||||
|
|
||||||
void showSettings();
|
void showSettings();
|
||||||
|
|
||||||
|
void documentAdded (CSMDoc::Document *document);
|
||||||
|
|
||||||
|
void lastDocumentDeleted();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
QString mIpcServerName;
|
QString mIpcServerName;
|
||||||
|
@ -3,18 +3,24 @@
|
|||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
|
#include <QMetaType>
|
||||||
|
|
||||||
#include <extern/shiny/Main/Factory.hpp>
|
#include <extern/shiny/Main/Factory.hpp>
|
||||||
|
|
||||||
#include <components/ogreinit/ogreinit.hpp>
|
#include <components/ogreinit/ogreinit.hpp>
|
||||||
|
|
||||||
|
#include "model/world/universalid.hpp"
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Q_DECLARE_METATYPE (std::string)
|
||||||
|
|
||||||
class Application : public QApplication
|
class Application : public QApplication
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
@ -42,6 +48,9 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
Q_INIT_RESOURCE (resources);
|
Q_INIT_RESOURCE (resources);
|
||||||
|
|
||||||
|
qRegisterMetaType<std::string> ("std::string");
|
||||||
|
qRegisterMetaType<CSMWorld::UniversalId> ("CSMWorld::UniversalId");
|
||||||
|
|
||||||
OgreInit::OgreInit ogreInit;
|
OgreInit::OgreInit ogreInit;
|
||||||
|
|
||||||
std::auto_ptr<sh::Factory> shinyFactory;
|
std::auto_ptr<sh::Factory> shinyFactory;
|
||||||
|
@ -8,23 +8,6 @@
|
|||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void CSMDoc::Document::load (const std::vector<boost::filesystem::path>::const_iterator& begin,
|
|
||||||
const std::vector<boost::filesystem::path>::const_iterator& end, bool lastAsModified)
|
|
||||||
{
|
|
||||||
assert (begin!=end);
|
|
||||||
|
|
||||||
std::vector<boost::filesystem::path>::const_iterator end2 (end);
|
|
||||||
|
|
||||||
if (lastAsModified)
|
|
||||||
--end2;
|
|
||||||
|
|
||||||
for (std::vector<boost::filesystem::path>::const_iterator iter (begin); iter!=end2; ++iter)
|
|
||||||
getData().loadFile (*iter, true, false);
|
|
||||||
|
|
||||||
if (lastAsModified)
|
|
||||||
getData().loadFile (*end2, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSMDoc::Document::addGmsts()
|
void CSMDoc::Document::addGmsts()
|
||||||
{
|
{
|
||||||
static const char *gmstFloats[] =
|
static const char *gmstFloats[] =
|
||||||
@ -2219,64 +2202,42 @@ void CSMDoc::Document::createBase()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, const std::vector< boost::filesystem::path >& files, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, bool new_)
|
CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
||||||
: mSavePath (savePath), mContentFiles (files), mTools (mData), mResDir(resDir),
|
const std::vector< boost::filesystem::path >& files, bool new_,
|
||||||
mProjectPath ((configuration.getUserDataPath() / "projects") /
|
const boost::filesystem::path& savePath, const boost::filesystem::path& resDir,
|
||||||
(savePath.filename().string() + ".project")),
|
ToUTF8::FromType encoding)
|
||||||
mSaving (*this, mProjectPath)
|
: mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding), mTools (mData),
|
||||||
|
mResDir(resDir),
|
||||||
|
mProjectPath ((configuration.getUserDataPath() / "projects") /
|
||||||
|
(savePath.filename().string() + ".project")),
|
||||||
|
mSaving (*this, mProjectPath, encoding)
|
||||||
{
|
{
|
||||||
if (files.empty())
|
if (mContentFiles.empty())
|
||||||
throw std::runtime_error ("Empty content file sequence");
|
throw std::runtime_error ("Empty content file sequence");
|
||||||
|
|
||||||
if (new_ && files.size()==1)
|
if (!boost::filesystem::exists (mProjectPath))
|
||||||
createBase();
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::vector<boost::filesystem::path>::const_iterator end = files.end();
|
|
||||||
|
|
||||||
if (new_)
|
|
||||||
--end;
|
|
||||||
|
|
||||||
load (files.begin(), end, !new_);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (new_)
|
|
||||||
{
|
|
||||||
mData.setDescription ("");
|
|
||||||
mData.setAuthor ("");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool filtersFound = false;
|
|
||||||
|
|
||||||
if (boost::filesystem::exists (mProjectPath))
|
|
||||||
{
|
|
||||||
filtersFound = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
boost::filesystem::path locCustomFiltersPath (configuration.getUserDataPath());
|
boost::filesystem::path locCustomFiltersPath (configuration.getUserDataPath());
|
||||||
locCustomFiltersPath /= "defaultfilters";
|
locCustomFiltersPath /= "defaultfilters";
|
||||||
|
|
||||||
if (boost::filesystem::exists(locCustomFiltersPath))
|
if (boost::filesystem::exists (locCustomFiltersPath))
|
||||||
{
|
{
|
||||||
boost::filesystem::copy_file (locCustomFiltersPath, mProjectPath);
|
boost::filesystem::copy_file (locCustomFiltersPath, mProjectPath);
|
||||||
filtersFound = true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
boost::filesystem::path filters(mResDir);
|
boost::filesystem::copy_file (mResDir / "defaultfilters", mProjectPath);
|
||||||
filters /= "defaultfilters";
|
|
||||||
|
|
||||||
if (boost::filesystem::exists(filters))
|
|
||||||
{
|
|
||||||
boost::filesystem::copy_file(filters, mProjectPath);
|
|
||||||
filtersFound = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filtersFound)
|
if (mNew)
|
||||||
getData().loadFile (mProjectPath, false, true);
|
{
|
||||||
|
mData.setDescription ("");
|
||||||
|
mData.setAuthor ("");
|
||||||
|
|
||||||
|
if (mContentFiles.size()==1)
|
||||||
|
createBase();
|
||||||
|
}
|
||||||
|
|
||||||
addOptionalGmsts();
|
addOptionalGmsts();
|
||||||
addOptionalGlobals();
|
addOptionalGlobals();
|
||||||
@ -2288,8 +2249,10 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, co
|
|||||||
|
|
||||||
connect (&mSaving, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
connect (&mSaving, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
||||||
connect (&mSaving, SIGNAL (done (int)), this, SLOT (operationDone (int)));
|
connect (&mSaving, SIGNAL (done (int)), this, SLOT (operationDone (int)));
|
||||||
connect (&mSaving, SIGNAL (reportMessage (const QString&, int)),
|
|
||||||
this, SLOT (reportMessage (const QString&, int)));
|
connect (
|
||||||
|
&mSaving, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, int)),
|
||||||
|
this, SLOT (reportMessage (const CSMWorld::UniversalId&, const std::string&, int)));
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMDoc::Document::~Document()
|
CSMDoc::Document::~Document()
|
||||||
@ -2322,11 +2285,21 @@ const boost::filesystem::path& CSMDoc::Document::getSavePath() const
|
|||||||
return mSavePath;
|
return mSavePath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const boost::filesystem::path& CSMDoc::Document::getProjectPath() const
|
||||||
|
{
|
||||||
|
return mProjectPath;
|
||||||
|
}
|
||||||
|
|
||||||
const std::vector<boost::filesystem::path>& CSMDoc::Document::getContentFiles() const
|
const std::vector<boost::filesystem::path>& CSMDoc::Document::getContentFiles() const
|
||||||
{
|
{
|
||||||
return mContentFiles;
|
return mContentFiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CSMDoc::Document::isNew() const
|
||||||
|
{
|
||||||
|
return mNew;
|
||||||
|
}
|
||||||
|
|
||||||
void CSMDoc::Document::save()
|
void CSMDoc::Document::save()
|
||||||
{
|
{
|
||||||
if (mSaving.isRunning())
|
if (mSaving.isRunning())
|
||||||
@ -2358,10 +2331,11 @@ void CSMDoc::Document::modificationStateChanged (bool clean)
|
|||||||
emit stateChanged (getState(), this);
|
emit stateChanged (getState(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::Document::reportMessage (const QString& message, int type)
|
void CSMDoc::Document::reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
||||||
|
int type)
|
||||||
{
|
{
|
||||||
/// \todo find a better way to get these messages to the user.
|
/// \todo find a better way to get these messages to the user.
|
||||||
std::cout << message.toUtf8().constData() << std::endl;
|
std::cout << message << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::Document::operationDone (int type)
|
void CSMDoc::Document::operationDone (int type)
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
|
|
||||||
#include "../world/data.hpp"
|
#include "../world/data.hpp"
|
||||||
|
|
||||||
#include "../tools/tools.hpp"
|
#include "../tools/tools.hpp"
|
||||||
@ -39,6 +41,7 @@ namespace CSMDoc
|
|||||||
|
|
||||||
boost::filesystem::path mSavePath;
|
boost::filesystem::path mSavePath;
|
||||||
std::vector<boost::filesystem::path> mContentFiles;
|
std::vector<boost::filesystem::path> mContentFiles;
|
||||||
|
bool mNew;
|
||||||
CSMWorld::Data mData;
|
CSMWorld::Data mData;
|
||||||
CSMTools::Tools mTools;
|
CSMTools::Tools mTools;
|
||||||
boost::filesystem::path mProjectPath;
|
boost::filesystem::path mProjectPath;
|
||||||
@ -53,10 +56,6 @@ namespace CSMDoc
|
|||||||
Document (const Document&);
|
Document (const Document&);
|
||||||
Document& operator= (const Document&);
|
Document& operator= (const Document&);
|
||||||
|
|
||||||
void load (const std::vector<boost::filesystem::path>::const_iterator& begin,
|
|
||||||
const std::vector<boost::filesystem::path>::const_iterator& end, bool lastAsModified);
|
|
||||||
///< \param lastAsModified Store the last file in Modified instead of merging it into Base.
|
|
||||||
|
|
||||||
void createBase();
|
void createBase();
|
||||||
|
|
||||||
void addGmsts();
|
void addGmsts();
|
||||||
@ -72,9 +71,9 @@ namespace CSMDoc
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
Document (const Files::ConfigurationManager& configuration,
|
Document (const Files::ConfigurationManager& configuration,
|
||||||
const std::vector< boost::filesystem::path >& files,
|
const std::vector< boost::filesystem::path >& files, bool new_,
|
||||||
const boost::filesystem::path& savePath,
|
const boost::filesystem::path& savePath, const boost::filesystem::path& resDir,
|
||||||
const boost::filesystem::path& resDir, bool new_);
|
ToUTF8::FromType encoding);
|
||||||
|
|
||||||
~Document();
|
~Document();
|
||||||
|
|
||||||
@ -84,10 +83,15 @@ namespace CSMDoc
|
|||||||
|
|
||||||
const boost::filesystem::path& getSavePath() const;
|
const boost::filesystem::path& getSavePath() const;
|
||||||
|
|
||||||
|
const boost::filesystem::path& getProjectPath() const;
|
||||||
|
|
||||||
const std::vector<boost::filesystem::path>& getContentFiles() const;
|
const std::vector<boost::filesystem::path>& getContentFiles() const;
|
||||||
///< \attention The last element in this collection is the file that is being edited,
|
///< \attention The last element in this collection is the file that is being edited,
|
||||||
/// but with its original path instead of the save path.
|
/// but with its original path instead of the save path.
|
||||||
|
|
||||||
|
bool isNew() const;
|
||||||
|
///< Is this a newly created content file?
|
||||||
|
|
||||||
void save();
|
void save();
|
||||||
|
|
||||||
CSMWorld::UniversalId verify();
|
CSMWorld::UniversalId verify();
|
||||||
@ -111,7 +115,8 @@ namespace CSMDoc
|
|||||||
|
|
||||||
void modificationStateChanged (bool clean);
|
void modificationStateChanged (bool clean);
|
||||||
|
|
||||||
void reportMessage (const QString& message, int type);
|
void reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
||||||
|
int type);
|
||||||
|
|
||||||
void operationDone (int type);
|
void operationDone (int type);
|
||||||
|
|
||||||
|
@ -13,44 +13,88 @@
|
|||||||
#include "document.hpp"
|
#include "document.hpp"
|
||||||
|
|
||||||
CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& configuration)
|
CSMDoc::DocumentManager::DocumentManager (const Files::ConfigurationManager& configuration)
|
||||||
: mConfiguration (configuration)
|
: mConfiguration (configuration), mEncoding (ToUTF8::WINDOWS_1252)
|
||||||
{
|
{
|
||||||
boost::filesystem::path projectPath = configuration.getUserDataPath() / "projects";
|
boost::filesystem::path projectPath = configuration.getUserDataPath() / "projects";
|
||||||
|
|
||||||
if (!boost::filesystem::is_directory (projectPath))
|
if (!boost::filesystem::is_directory (projectPath))
|
||||||
boost::filesystem::create_directories (projectPath);
|
boost::filesystem::create_directories (projectPath);
|
||||||
|
|
||||||
|
mLoader.moveToThread (&mLoaderThread);
|
||||||
|
mLoaderThread.start();
|
||||||
|
|
||||||
|
connect (&mLoader, SIGNAL (documentLoaded (Document *)),
|
||||||
|
this, SLOT (documentLoaded (Document *)));
|
||||||
|
connect (&mLoader, SIGNAL (documentNotLoaded (Document *, const std::string&)),
|
||||||
|
this, SLOT (documentNotLoaded (Document *, const std::string&)));
|
||||||
|
connect (this, SIGNAL (loadRequest (CSMDoc::Document *)),
|
||||||
|
&mLoader, SLOT (loadDocument (CSMDoc::Document *)));
|
||||||
|
connect (&mLoader, SIGNAL (nextStage (CSMDoc::Document *, const std::string&, int)),
|
||||||
|
this, SIGNAL (nextStage (CSMDoc::Document *, const std::string&, int)));
|
||||||
|
connect (&mLoader, SIGNAL (nextRecord (CSMDoc::Document *)),
|
||||||
|
this, SIGNAL (nextRecord (CSMDoc::Document *)));
|
||||||
|
connect (this, SIGNAL (cancelLoading (CSMDoc::Document *)),
|
||||||
|
&mLoader, SLOT (abortLoading (CSMDoc::Document *)));
|
||||||
|
connect (&mLoader, SIGNAL (loadMessage (CSMDoc::Document *, const std::string&)),
|
||||||
|
this, SIGNAL (loadMessage (CSMDoc::Document *, const std::string&)));
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMDoc::DocumentManager::~DocumentManager()
|
CSMDoc::DocumentManager::~DocumentManager()
|
||||||
{
|
{
|
||||||
|
mLoaderThread.quit();
|
||||||
|
mLoader.hasThingsToDo().wakeAll();
|
||||||
|
mLoaderThread.wait();
|
||||||
|
|
||||||
for (std::vector<Document *>::iterator iter (mDocuments.begin()); iter!=mDocuments.end(); ++iter)
|
for (std::vector<Document *>::iterator iter (mDocuments.begin()); iter!=mDocuments.end(); ++iter)
|
||||||
delete *iter;
|
delete *iter;
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMDoc::Document *CSMDoc::DocumentManager::addDocument (const std::vector<boost::filesystem::path>& files, const boost::filesystem::path& savePath,
|
void CSMDoc::DocumentManager::addDocument (const std::vector<boost::filesystem::path>& files, const boost::filesystem::path& savePath,
|
||||||
bool new_)
|
bool new_)
|
||||||
{
|
{
|
||||||
Document *document = new Document (mConfiguration, files, savePath, mResDir, new_);
|
Document *document = new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding);
|
||||||
|
|
||||||
mDocuments.push_back (document);
|
mDocuments.push_back (document);
|
||||||
|
|
||||||
return document;
|
emit loadRequest (document);
|
||||||
|
|
||||||
|
mLoader.hasThingsToDo().wakeAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSMDoc::DocumentManager::removeDocument (Document *document)
|
void CSMDoc::DocumentManager::removeDocument (CSMDoc::Document *document)
|
||||||
{
|
{
|
||||||
std::vector<Document *>::iterator iter = std::find (mDocuments.begin(), mDocuments.end(), document);
|
std::vector<Document *>::iterator iter = std::find (mDocuments.begin(), mDocuments.end(), document);
|
||||||
|
|
||||||
if (iter==mDocuments.end())
|
if (iter==mDocuments.end())
|
||||||
throw std::runtime_error ("removing invalid document");
|
throw std::runtime_error ("removing invalid document");
|
||||||
|
|
||||||
mDocuments.erase (iter);
|
mDocuments.erase (iter);
|
||||||
delete document;
|
delete document;
|
||||||
|
|
||||||
return mDocuments.empty();
|
if (mDocuments.empty())
|
||||||
|
emit lastDocumentDeleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::DocumentManager::setResourceDir (const boost::filesystem::path& parResDir)
|
void CSMDoc::DocumentManager::setResourceDir (const boost::filesystem::path& parResDir)
|
||||||
{
|
{
|
||||||
mResDir = boost::filesystem::system_complete(parResDir);
|
mResDir = boost::filesystem::system_complete(parResDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSMDoc::DocumentManager::setEncoding (ToUTF8::FromType encoding)
|
||||||
|
{
|
||||||
|
mEncoding = encoding;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::DocumentManager::documentLoaded (Document *document)
|
||||||
|
{
|
||||||
|
emit documentAdded (document);
|
||||||
|
emit loadingStopped (document, true, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::DocumentManager::documentNotLoaded (Document *document, const std::string& error)
|
||||||
|
{
|
||||||
|
emit loadingStopped (document, false, error);
|
||||||
|
|
||||||
|
if (error.empty()) // do not remove the document yet, if we have an error
|
||||||
|
removeDocument (document);
|
||||||
|
}
|
@ -6,6 +6,13 @@
|
|||||||
|
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QThread>
|
||||||
|
|
||||||
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
|
|
||||||
|
#include "loader.hpp"
|
||||||
|
|
||||||
namespace Files
|
namespace Files
|
||||||
{
|
{
|
||||||
class ConfigurationManager;
|
class ConfigurationManager;
|
||||||
@ -15,10 +22,15 @@ namespace CSMDoc
|
|||||||
{
|
{
|
||||||
class Document;
|
class Document;
|
||||||
|
|
||||||
class DocumentManager
|
class DocumentManager : public QObject
|
||||||
{
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
std::vector<Document *> mDocuments;
|
std::vector<Document *> mDocuments;
|
||||||
const Files::ConfigurationManager& mConfiguration;
|
const Files::ConfigurationManager& mConfiguration;
|
||||||
|
QThread mLoaderThread;
|
||||||
|
Loader mLoader;
|
||||||
|
ToUTF8::FromType mEncoding;
|
||||||
|
|
||||||
DocumentManager (const DocumentManager&);
|
DocumentManager (const DocumentManager&);
|
||||||
DocumentManager& operator= (const DocumentManager&);
|
DocumentManager& operator= (const DocumentManager&);
|
||||||
@ -29,20 +41,51 @@ namespace CSMDoc
|
|||||||
|
|
||||||
~DocumentManager();
|
~DocumentManager();
|
||||||
|
|
||||||
Document *addDocument (const std::vector< boost::filesystem::path >& files,
|
void addDocument (const std::vector< boost::filesystem::path >& files,
|
||||||
const boost::filesystem::path& savePath,
|
const boost::filesystem::path& savePath, bool new_);
|
||||||
bool new_);
|
///< \param new_ Do not load the last content file in \a files and instead create in an
|
||||||
///< The ownership of the returned document is not transferred to the caller.
|
|
||||||
///
|
|
||||||
/// \param new_ Do not load the last content file in \a files and instead create in an
|
|
||||||
/// appropriate way.
|
/// appropriate way.
|
||||||
|
|
||||||
bool removeDocument (Document *document);
|
|
||||||
///< \return last document removed?
|
|
||||||
void setResourceDir (const boost::filesystem::path& parResDir);
|
void setResourceDir (const boost::filesystem::path& parResDir);
|
||||||
|
|
||||||
private:
|
void setEncoding (ToUTF8::FromType encoding);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
boost::filesystem::path mResDir;
|
boost::filesystem::path mResDir;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void documentLoaded (Document *document);
|
||||||
|
///< The ownership of \a document is not transferred.
|
||||||
|
|
||||||
|
void documentNotLoaded (Document *document, const std::string& error);
|
||||||
|
///< Document load has been interrupted either because of a call to abortLoading
|
||||||
|
/// or a problem during loading). In the former case error will be an empty string.
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
void removeDocument (CSMDoc::Document *document);
|
||||||
|
///< Emits the lastDocumentDeleted signal, if applicable.
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void documentAdded (CSMDoc::Document *document);
|
||||||
|
|
||||||
|
void loadRequest (CSMDoc::Document *document);
|
||||||
|
|
||||||
|
void lastDocumentDeleted();
|
||||||
|
|
||||||
|
void loadingStopped (CSMDoc::Document *document, bool completed,
|
||||||
|
const std::string& error);
|
||||||
|
|
||||||
|
void nextStage (CSMDoc::Document *document, const std::string& name, int steps);
|
||||||
|
|
||||||
|
void nextRecord (CSMDoc::Document *document);
|
||||||
|
|
||||||
|
void cancelLoading (CSMDoc::Document *document);
|
||||||
|
|
||||||
|
void loadMessage (CSMDoc::Document *document, const std::string& message);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
130
apps/opencs/model/doc/loader.cpp
Normal file
130
apps/opencs/model/doc/loader.cpp
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
|
||||||
|
#include "loader.hpp"
|
||||||
|
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include "../tools/reportmodel.hpp"
|
||||||
|
|
||||||
|
#include "document.hpp"
|
||||||
|
#include "state.hpp"
|
||||||
|
|
||||||
|
CSMDoc::Loader::Stage::Stage() : mFile (0), mRecordsLeft (false) {}
|
||||||
|
|
||||||
|
|
||||||
|
CSMDoc::Loader::Loader()
|
||||||
|
{
|
||||||
|
QTimer *timer = new QTimer (this);
|
||||||
|
|
||||||
|
connect (timer, SIGNAL (timeout()), this, SLOT (load()));
|
||||||
|
timer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
QWaitCondition& CSMDoc::Loader::hasThingsToDo()
|
||||||
|
{
|
||||||
|
return mThingsToDo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::Loader::load()
|
||||||
|
{
|
||||||
|
if (mDocuments.empty())
|
||||||
|
{
|
||||||
|
mMutex.lock();
|
||||||
|
mThingsToDo.wait (&mMutex);
|
||||||
|
mMutex.unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<Document *, Stage> >::iterator iter = mDocuments.begin();
|
||||||
|
|
||||||
|
Document *document = iter->first;
|
||||||
|
|
||||||
|
int size = static_cast<int> (document->getContentFiles().size());
|
||||||
|
|
||||||
|
if (document->isNew())
|
||||||
|
--size;
|
||||||
|
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
|
const int batchingSize = 100;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (iter->second.mRecordsLeft)
|
||||||
|
{
|
||||||
|
CSMDoc::Stage::Messages messages;
|
||||||
|
for (int i=0; i<batchingSize; ++i) // do not flood the system with update signals
|
||||||
|
if (document->getData().continueLoading (messages))
|
||||||
|
{
|
||||||
|
iter->second.mRecordsLeft = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMWorld::UniversalId log (CSMWorld::UniversalId::Type_LoadErrorLog, 0);
|
||||||
|
|
||||||
|
for (CSMDoc::Stage::Messages::const_iterator iter (messages.begin());
|
||||||
|
iter!=messages.end(); ++iter)
|
||||||
|
{
|
||||||
|
document->getReport (log)->add (iter->first, iter->second);
|
||||||
|
emit loadMessage (document, iter->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit nextRecord (document);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iter->second.mFile<size)
|
||||||
|
{
|
||||||
|
boost::filesystem::path path = document->getContentFiles()[iter->second.mFile];
|
||||||
|
|
||||||
|
int steps = document->getData().startLoading (path, iter->second.mFile<size-1, false);
|
||||||
|
iter->second.mRecordsLeft = true;
|
||||||
|
|
||||||
|
emit nextStage (document, path.filename().string(), steps/batchingSize);
|
||||||
|
}
|
||||||
|
else if (iter->second.mFile==size)
|
||||||
|
{
|
||||||
|
int steps = document->getData().startLoading (document->getProjectPath(), false, true);
|
||||||
|
iter->second.mRecordsLeft = true;
|
||||||
|
|
||||||
|
emit nextStage (document, "Project File", steps/batchingSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
done = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
++(iter->second.mFile);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
mDocuments.erase (iter);
|
||||||
|
emit documentNotLoaded (document, e.what());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (done)
|
||||||
|
{
|
||||||
|
mDocuments.erase (iter);
|
||||||
|
emit documentLoaded (document);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::Loader::loadDocument (CSMDoc::Document *document)
|
||||||
|
{
|
||||||
|
mDocuments.push_back (std::make_pair (document, Stage()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::Loader::abortLoading (CSMDoc::Document *document)
|
||||||
|
{
|
||||||
|
for (std::vector<std::pair<Document *, Stage> >::iterator iter = mDocuments.begin();
|
||||||
|
iter!=mDocuments.end(); ++iter)
|
||||||
|
{
|
||||||
|
if (iter->first==document)
|
||||||
|
{
|
||||||
|
mDocuments.erase (iter);
|
||||||
|
emit documentNotLoaded (document, "");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
71
apps/opencs/model/doc/loader.hpp
Normal file
71
apps/opencs/model/doc/loader.hpp
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#ifndef CSM_DOC_LOADER_H
|
||||||
|
#define CSM_DOC_LOADER_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QWaitCondition>
|
||||||
|
|
||||||
|
namespace CSMDoc
|
||||||
|
{
|
||||||
|
class Document;
|
||||||
|
|
||||||
|
class Loader : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
struct Stage
|
||||||
|
{
|
||||||
|
int mFile;
|
||||||
|
bool mRecordsLeft;
|
||||||
|
|
||||||
|
Stage();
|
||||||
|
};
|
||||||
|
|
||||||
|
QMutex mMutex;
|
||||||
|
QWaitCondition mThingsToDo;
|
||||||
|
std::vector<std::pair<Document *, Stage> > mDocuments;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Loader();
|
||||||
|
|
||||||
|
QWaitCondition& hasThingsToDo();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void load();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
void loadDocument (CSMDoc::Document *document);
|
||||||
|
///< The ownership of \a document is not transferred.
|
||||||
|
|
||||||
|
void abortLoading (CSMDoc::Document *document);
|
||||||
|
///< Abort loading \a docuemnt (ignored if \a document has already finished being
|
||||||
|
/// loaded). Will result in a documentNotLoaded signal, once the Loader has finished
|
||||||
|
/// cleaning up.
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void documentLoaded (Document *document);
|
||||||
|
///< The ownership of \a document is not transferred.
|
||||||
|
|
||||||
|
void documentNotLoaded (Document *document, const std::string& error);
|
||||||
|
///< Document load has been interrupted either because of a call to abortLoading
|
||||||
|
/// or a problem during loading). In the former case error will be an empty string.
|
||||||
|
|
||||||
|
void nextStage (CSMDoc::Document *document, const std::string& name, int steps);
|
||||||
|
|
||||||
|
void nextRecord (CSMDoc::Document *document);
|
||||||
|
///< \note This signal is only given once per group of records. The group size is
|
||||||
|
/// approximately the total number of records divided by the steps value of the
|
||||||
|
/// previous nextStage signal.
|
||||||
|
|
||||||
|
void loadMessage (CSMDoc::Document *document, const std::string& message);
|
||||||
|
///< Non-critical load error or warning
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -6,6 +6,8 @@
|
|||||||
|
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include "../world/universalid.hpp"
|
||||||
|
|
||||||
#include "state.hpp"
|
#include "state.hpp"
|
||||||
#include "stage.hpp"
|
#include "stage.hpp"
|
||||||
|
|
||||||
@ -80,7 +82,7 @@ void CSMDoc::Operation::abort()
|
|||||||
|
|
||||||
void CSMDoc::Operation::executeStage()
|
void CSMDoc::Operation::executeStage()
|
||||||
{
|
{
|
||||||
std::vector<std::string> messages;
|
Stage::Messages messages;
|
||||||
|
|
||||||
while (mCurrentStage!=mStages.end())
|
while (mCurrentStage!=mStages.end())
|
||||||
{
|
{
|
||||||
@ -97,7 +99,7 @@ void CSMDoc::Operation::executeStage()
|
|||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
emit reportMessage (e.what(), mType);
|
emit reportMessage (CSMWorld::UniversalId(), e.what(), mType);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,8 +110,8 @@ void CSMDoc::Operation::executeStage()
|
|||||||
|
|
||||||
emit progress (mCurrentStepTotal, mTotalSteps ? mTotalSteps : 1, mType);
|
emit progress (mCurrentStepTotal, mTotalSteps ? mTotalSteps : 1, mType);
|
||||||
|
|
||||||
for (std::vector<std::string>::const_iterator iter (messages.begin()); iter!=messages.end(); ++iter)
|
for (Stage::Messages::const_iterator iter (messages.begin()); iter!=messages.end(); ++iter)
|
||||||
emit reportMessage (iter->c_str(), mType);
|
emit reportMessage (iter->first, iter->second, mType);
|
||||||
|
|
||||||
if (mCurrentStage==mStages.end())
|
if (mCurrentStage==mStages.end())
|
||||||
exit();
|
exit();
|
||||||
|
@ -5,6 +5,11 @@
|
|||||||
|
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
class UniversalId;
|
||||||
|
}
|
||||||
|
|
||||||
namespace CSMDoc
|
namespace CSMDoc
|
||||||
{
|
{
|
||||||
class Stage;
|
class Stage;
|
||||||
@ -46,7 +51,8 @@ namespace CSMDoc
|
|||||||
|
|
||||||
void progress (int current, int max, int type);
|
void progress (int current, int max, int type);
|
||||||
|
|
||||||
void reportMessage (const QString& message, int type);
|
void reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
||||||
|
int type);
|
||||||
|
|
||||||
void done (int type);
|
void done (int type);
|
||||||
|
|
||||||
|
@ -8,8 +8,9 @@
|
|||||||
#include "savingstages.hpp"
|
#include "savingstages.hpp"
|
||||||
#include "document.hpp"
|
#include "document.hpp"
|
||||||
|
|
||||||
CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& projectPath)
|
CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& projectPath,
|
||||||
: Operation (State_Saving, true, true), mDocument (document), mState (*this, projectPath)
|
ToUTF8::FromType encoding)
|
||||||
|
: Operation (State_Saving, true, true), mDocument (document), mState (*this, projectPath, encoding)
|
||||||
{
|
{
|
||||||
// save project file
|
// save project file
|
||||||
appendStage (new OpenSaveStage (mDocument, mState, true));
|
appendStage (new OpenSaveStage (mDocument, mState, true));
|
||||||
@ -64,7 +65,11 @@ CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& proje
|
|||||||
|
|
||||||
appendStage (new WriteRefIdCollectionStage (mDocument, mState));
|
appendStage (new WriteRefIdCollectionStage (mDocument, mState));
|
||||||
|
|
||||||
|
appendStage (new CollectionReferencesStage (mDocument, mState));
|
||||||
|
|
||||||
|
appendStage (new WriteCellCollectionStage (mDocument, mState));
|
||||||
|
|
||||||
|
// close file and clean up
|
||||||
appendStage (new CloseSaveStage (mState));
|
appendStage (new CloseSaveStage (mState));
|
||||||
|
|
||||||
appendStage (new FinalSavingStage (mDocument, mState));
|
appendStage (new FinalSavingStage (mDocument, mState));
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
|
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
|
|
||||||
#include "operation.hpp"
|
#include "operation.hpp"
|
||||||
#include "savingstate.hpp"
|
#include "savingstate.hpp"
|
||||||
|
|
||||||
@ -19,7 +21,8 @@ namespace CSMDoc
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Saving (Document& document, const boost::filesystem::path& projectPath);
|
Saving (Document& document, const boost::filesystem::path& projectPath,
|
||||||
|
ToUTF8::FromType encoding);
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
#include <components/esm/loaddial.hpp>
|
#include <components/esm/loaddial.hpp>
|
||||||
|
|
||||||
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
#include "../world/infocollection.hpp"
|
#include "../world/infocollection.hpp"
|
||||||
|
|
||||||
#include "document.hpp"
|
#include "document.hpp"
|
||||||
@ -23,11 +25,13 @@ int CSMDoc::OpenSaveStage::setup()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::OpenSaveStage::perform (int stage, std::vector<std::string>& messages)
|
void CSMDoc::OpenSaveStage::perform (int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
mState.start (mDocument, mProjectFile);
|
mState.start (mDocument, mProjectFile);
|
||||||
|
|
||||||
mState.getStream().open ((mProjectFile ? mState.getPath() : mState.getTmpPath()).string().c_str());
|
mState.getStream().open (
|
||||||
|
mProjectFile ? mState.getPath() : mState.getTmpPath(),
|
||||||
|
std::ios::binary);
|
||||||
|
|
||||||
if (!mState.getStream().is_open())
|
if (!mState.getStream().is_open())
|
||||||
throw std::runtime_error ("failed to open stream for saving");
|
throw std::runtime_error ("failed to open stream for saving");
|
||||||
@ -43,7 +47,7 @@ int CSMDoc::WriteHeaderStage::setup()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::WriteHeaderStage::perform (int stage, std::vector<std::string>& messages)
|
void CSMDoc::WriteHeaderStage::perform (int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
mState.getWriter().setVersion();
|
mState.getWriter().setVersion();
|
||||||
|
|
||||||
@ -96,7 +100,7 @@ int CSMDoc::WriteDialogueCollectionStage::setup()
|
|||||||
return mTopics.getSize();
|
return mTopics.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::WriteDialogueCollectionStage::perform (int stage, std::vector<std::string>& messages)
|
void CSMDoc::WriteDialogueCollectionStage::perform (int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<ESM::Dialogue>& topic = mTopics.getRecord (stage);
|
const CSMWorld::Record<ESM::Dialogue>& topic = mTopics.getRecord (stage);
|
||||||
|
|
||||||
@ -191,7 +195,7 @@ int CSMDoc::WriteRefIdCollectionStage::setup()
|
|||||||
return mDocument.getData().getReferenceables().getSize();
|
return mDocument.getData().getReferenceables().getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::WriteRefIdCollectionStage::perform (int stage, std::vector<std::string>& messages)
|
void CSMDoc::WriteRefIdCollectionStage::perform (int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
mDocument.getData().getReferenceables().save (stage, mState.getWriter());
|
mDocument.getData().getReferenceables().save (stage, mState.getWriter());
|
||||||
}
|
}
|
||||||
@ -204,7 +208,7 @@ CSMDoc::WriteFilterStage::WriteFilterStage (Document& document, SavingState& sta
|
|||||||
mDocument (document), mScope (scope)
|
mDocument (document), mScope (scope)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void CSMDoc::WriteFilterStage::perform (int stage, std::vector<std::string>& messages)
|
void CSMDoc::WriteFilterStage::perform (int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<CSMFilter::Filter>& record =
|
const CSMWorld::Record<CSMFilter::Filter>& record =
|
||||||
mDocument.getData().getFilters().getRecord (stage);
|
mDocument.getData().getFilters().getRecord (stage);
|
||||||
@ -214,6 +218,143 @@ void CSMDoc::WriteFilterStage::perform (int stage, std::vector<std::string>& mes
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSMDoc::CollectionReferencesStage::CollectionReferencesStage (Document& document,
|
||||||
|
SavingState& state)
|
||||||
|
: mDocument (document), mState (state)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMDoc::CollectionReferencesStage::setup()
|
||||||
|
{
|
||||||
|
mState.getSubRecords().clear();
|
||||||
|
|
||||||
|
int size = mDocument.getData().getReferences().getSize();
|
||||||
|
|
||||||
|
int steps = size/100;
|
||||||
|
if (size%100) ++steps;
|
||||||
|
|
||||||
|
return steps;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::CollectionReferencesStage::perform (int stage, Messages& messages)
|
||||||
|
{
|
||||||
|
int size = mDocument.getData().getReferences().getSize();
|
||||||
|
|
||||||
|
for (int i=stage*100; i<stage*100+100 && i<size; ++i)
|
||||||
|
{
|
||||||
|
const CSMWorld::Record<CSMWorld::CellRef>& record =
|
||||||
|
mDocument.getData().getReferences().getRecord (i);
|
||||||
|
|
||||||
|
if (record.mState==CSMWorld::RecordBase::State_Deleted ||
|
||||||
|
record.mState==CSMWorld::RecordBase::State_Modified ||
|
||||||
|
record.mState==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||||
|
{
|
||||||
|
mState.getSubRecords()[Misc::StringUtils::lowerCase (record.get().mCell)]
|
||||||
|
.push_back (i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSMDoc::WriteCellCollectionStage::WriteCellCollectionStage (Document& document,
|
||||||
|
SavingState& state)
|
||||||
|
: mDocument (document), mState (state)
|
||||||
|
{}
|
||||||
|
|
||||||
|
int CSMDoc::WriteCellCollectionStage::setup()
|
||||||
|
{
|
||||||
|
return mDocument.getData().getCells().getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages)
|
||||||
|
{
|
||||||
|
const CSMWorld::Record<CSMWorld::Cell>& cell =
|
||||||
|
mDocument.getData().getCells().getRecord (stage);
|
||||||
|
|
||||||
|
std::map<std::string, std::vector<int> >::const_iterator references =
|
||||||
|
mState.getSubRecords().find (Misc::StringUtils::lowerCase (cell.get().mId));
|
||||||
|
|
||||||
|
if (cell.mState==CSMWorld::RecordBase::State_Modified ||
|
||||||
|
cell.mState==CSMWorld::RecordBase::State_ModifiedOnly ||
|
||||||
|
references!=mState.getSubRecords().end())
|
||||||
|
{
|
||||||
|
bool interior = cell.get().mId.substr (0, 1)!="#";
|
||||||
|
|
||||||
|
// write cell data
|
||||||
|
mState.getWriter().startRecord (cell.mModified.sRecordId);
|
||||||
|
|
||||||
|
mState.getWriter().writeHNOCString ("NAME", cell.get().mName);
|
||||||
|
|
||||||
|
ESM::Cell cell2 = cell.get();
|
||||||
|
|
||||||
|
if (interior)
|
||||||
|
cell2.mData.mFlags |= ESM::Cell::Interior;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cell2.mData.mFlags &= ~ESM::Cell::Interior;
|
||||||
|
|
||||||
|
std::istringstream stream (cell.get().mId.c_str());
|
||||||
|
char ignore;
|
||||||
|
stream >> ignore >> cell2.mData.mX >> cell2.mData.mY;
|
||||||
|
}
|
||||||
|
cell2.save (mState.getWriter());
|
||||||
|
|
||||||
|
// write references
|
||||||
|
if (references!=mState.getSubRecords().end())
|
||||||
|
{
|
||||||
|
// first pass: find highest RefNum
|
||||||
|
int lastRefNum = -1;
|
||||||
|
|
||||||
|
for (std::vector<int>::const_iterator iter (references->second.begin());
|
||||||
|
iter!=references->second.end(); ++iter)
|
||||||
|
{
|
||||||
|
const CSMWorld::Record<CSMWorld::CellRef>& ref =
|
||||||
|
mDocument.getData().getReferences().getRecord (*iter);
|
||||||
|
|
||||||
|
if (ref.get().mRefNum.mContentFile==0 && ref.get().mRefNum.mIndex>lastRefNum)
|
||||||
|
lastRefNum = ref.get().mRefNum.mIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
// second pass: write
|
||||||
|
for (std::vector<int>::const_iterator iter (references->second.begin());
|
||||||
|
iter!=references->second.end(); ++iter)
|
||||||
|
{
|
||||||
|
const CSMWorld::Record<CSMWorld::CellRef>& ref =
|
||||||
|
mDocument.getData().getReferences().getRecord (*iter);
|
||||||
|
|
||||||
|
if (ref.mState==CSMWorld::RecordBase::State_Modified ||
|
||||||
|
ref.mState==CSMWorld::RecordBase::State_ModifiedOnly)
|
||||||
|
{
|
||||||
|
if (ref.get().mRefNum.mContentFile==-2)
|
||||||
|
{
|
||||||
|
if (lastRefNum>=0xffffff)
|
||||||
|
throw std::runtime_error (
|
||||||
|
"RefNums exhausted in cell: " + cell.get().mId);
|
||||||
|
|
||||||
|
ESM::CellRef ref2 = ref.get();
|
||||||
|
ref2.mRefNum.mContentFile = 0;
|
||||||
|
ref2.mRefNum.mIndex = ++lastRefNum;
|
||||||
|
|
||||||
|
ref2.save (mState.getWriter());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ref.get().save (mState.getWriter());
|
||||||
|
}
|
||||||
|
else if (ref.mState==CSMWorld::RecordBase::State_Deleted)
|
||||||
|
{
|
||||||
|
/// \todo write record with delete flag
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mState.getWriter().endRecord (cell.mModified.sRecordId);
|
||||||
|
}
|
||||||
|
else if (cell.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)
|
||||||
{}
|
{}
|
||||||
@ -223,7 +364,7 @@ int CSMDoc::CloseSaveStage::setup()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::CloseSaveStage::perform (int stage, std::vector<std::string>& messages)
|
void CSMDoc::CloseSaveStage::perform (int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
mState.getStream().close();
|
mState.getStream().close();
|
||||||
|
|
||||||
@ -241,7 +382,7 @@ int CSMDoc::FinalSavingStage::setup()
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMDoc::FinalSavingStage::perform (int stage, std::vector<std::string>& messages)
|
void CSMDoc::FinalSavingStage::perform (int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
if (mState.hasError())
|
if (mState.hasError())
|
||||||
{
|
{
|
||||||
@ -260,4 +401,4 @@ void CSMDoc::FinalSavingStage::perform (int stage, std::vector<std::string>& mes
|
|||||||
|
|
||||||
mDocument.getUndoStack().setClean();
|
mDocument.getUndoStack().setClean();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ namespace CSMDoc
|
|||||||
virtual int setup();
|
virtual int setup();
|
||||||
///< \return number of steps
|
///< \return number of steps
|
||||||
|
|
||||||
virtual void perform (int stage, std::vector<std::string>& messages);
|
virtual void perform (int stage, Messages& messages);
|
||||||
///< Messages resulting from this stage will be appended to \a messages.
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -57,7 +57,7 @@ namespace CSMDoc
|
|||||||
virtual int setup();
|
virtual int setup();
|
||||||
///< \return number of steps
|
///< \return number of steps
|
||||||
|
|
||||||
virtual void perform (int stage, std::vector<std::string>& messages);
|
virtual void perform (int stage, Messages& messages);
|
||||||
///< Messages resulting from this stage will be appended to \a messages.
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ namespace CSMDoc
|
|||||||
virtual int setup();
|
virtual int setup();
|
||||||
///< \return number of steps
|
///< \return number of steps
|
||||||
|
|
||||||
virtual void perform (int stage, std::vector<std::string>& messages);
|
virtual void perform (int stage, Messages& messages);
|
||||||
///< Messages resulting from this stage will be appended to \a messages.
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ namespace CSMDoc
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class CollectionT>
|
template<class CollectionT>
|
||||||
void WriteCollectionStage<CollectionT>::perform (int stage, std::vector<std::string>& messages)
|
void WriteCollectionStage<CollectionT>::perform (int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
CSMWorld::RecordBase::State state = mCollection.getRecord (stage).mState;
|
CSMWorld::RecordBase::State state = mCollection.getRecord (stage).mState;
|
||||||
|
|
||||||
@ -130,7 +130,7 @@ namespace CSMDoc
|
|||||||
virtual int setup();
|
virtual int setup();
|
||||||
///< \return number of steps
|
///< \return number of steps
|
||||||
|
|
||||||
virtual void perform (int stage, std::vector<std::string>& messages);
|
virtual void perform (int stage, Messages& messages);
|
||||||
///< Messages resulting from this stage will be appended to \a messages.
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -147,7 +147,7 @@ namespace CSMDoc
|
|||||||
virtual int setup();
|
virtual int setup();
|
||||||
///< \return number of steps
|
///< \return number of steps
|
||||||
|
|
||||||
virtual void perform (int stage, std::vector<std::string>& messages);
|
virtual void perform (int stage, Messages& messages);
|
||||||
///< Messages resulting from this stage will be appended to \a messages.
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -161,10 +161,42 @@ namespace CSMDoc
|
|||||||
|
|
||||||
WriteFilterStage (Document& document, SavingState& state, CSMFilter::Filter::Scope scope);
|
WriteFilterStage (Document& document, SavingState& state, CSMFilter::Filter::Scope scope);
|
||||||
|
|
||||||
virtual void perform (int stage, std::vector<std::string>& messages);
|
virtual void perform (int stage, Messages& messages);
|
||||||
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
class CollectionReferencesStage : public Stage
|
||||||
|
{
|
||||||
|
Document& mDocument;
|
||||||
|
SavingState& mState;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
CollectionReferencesStage (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.
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class WriteCellCollectionStage : public Stage
|
||||||
|
{
|
||||||
|
Document& mDocument;
|
||||||
|
SavingState& mState;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
WriteCellCollectionStage (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
|
||||||
{
|
{
|
||||||
@ -177,7 +209,7 @@ namespace CSMDoc
|
|||||||
virtual int setup();
|
virtual int setup();
|
||||||
///< \return number of steps
|
///< \return number of steps
|
||||||
|
|
||||||
virtual void perform (int stage, std::vector<std::string>& messages);
|
virtual void perform (int stage, Messages& messages);
|
||||||
///< Messages resulting from this stage will be appended to \a messages.
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -193,7 +225,7 @@ namespace CSMDoc
|
|||||||
virtual int setup();
|
virtual int setup();
|
||||||
///< \return number of steps
|
///< \return number of steps
|
||||||
|
|
||||||
virtual void perform (int stage, std::vector<std::string>& messages);
|
virtual void perform (int stage, Messages& messages);
|
||||||
///< Messages resulting from this stage will be appended to \a messages.
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,9 @@
|
|||||||
#include "operation.hpp"
|
#include "operation.hpp"
|
||||||
#include "document.hpp"
|
#include "document.hpp"
|
||||||
|
|
||||||
CSMDoc::SavingState::SavingState (Operation& operation, const boost::filesystem::path& projectPath)
|
CSMDoc::SavingState::SavingState (Operation& operation, const boost::filesystem::path& projectPath,
|
||||||
: mOperation (operation),
|
ToUTF8::FromType encoding)
|
||||||
/// \todo set encoding properly, once config implementation has been fixed.
|
: mOperation (operation), mEncoder (encoding), mProjectPath (projectPath), mProjectFile (false)
|
||||||
mEncoder (ToUTF8::calculateEncoding ("win1252")),
|
|
||||||
mProjectPath (projectPath), mProjectFile (false)
|
|
||||||
{
|
{
|
||||||
mWriter.setEncoder (&mEncoder);
|
mWriter.setEncoder (&mEncoder);
|
||||||
}
|
}
|
||||||
@ -27,6 +25,8 @@ void CSMDoc::SavingState::start (Document& document, bool project)
|
|||||||
|
|
||||||
mStream.clear();
|
mStream.clear();
|
||||||
|
|
||||||
|
mSubRecords.clear();
|
||||||
|
|
||||||
if (project)
|
if (project)
|
||||||
mPath = mProjectPath;
|
mPath = mProjectPath;
|
||||||
else
|
else
|
||||||
@ -49,7 +49,7 @@ const boost::filesystem::path& CSMDoc::SavingState::getTmpPath() const
|
|||||||
return mTmpPath;
|
return mTmpPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ofstream& CSMDoc::SavingState::getStream()
|
boost::filesystem::ofstream& CSMDoc::SavingState::getStream()
|
||||||
{
|
{
|
||||||
return mStream;
|
return mStream;
|
||||||
}
|
}
|
||||||
@ -62,4 +62,9 @@ ESM::ESMWriter& CSMDoc::SavingState::getWriter()
|
|||||||
bool CSMDoc::SavingState::isProjectFile() const
|
bool CSMDoc::SavingState::isProjectFile() const
|
||||||
{
|
{
|
||||||
return mProjectFile;
|
return mProjectFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::map<std::string, std::vector<int> >& CSMDoc::SavingState::getSubRecords()
|
||||||
|
{
|
||||||
|
return mSubRecords;
|
||||||
|
}
|
||||||
|
@ -2,11 +2,15 @@
|
|||||||
#define CSM_DOC_SAVINGSTATE_H
|
#define CSM_DOC_SAVINGSTATE_H
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
|
#include <boost/filesystem/fstream.hpp>
|
||||||
|
|
||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
|
|
||||||
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
|
|
||||||
namespace CSMDoc
|
namespace CSMDoc
|
||||||
{
|
{
|
||||||
class Operation;
|
class Operation;
|
||||||
@ -18,14 +22,16 @@ namespace CSMDoc
|
|||||||
boost::filesystem::path mPath;
|
boost::filesystem::path mPath;
|
||||||
boost::filesystem::path mTmpPath;
|
boost::filesystem::path mTmpPath;
|
||||||
ToUTF8::Utf8Encoder mEncoder;
|
ToUTF8::Utf8Encoder mEncoder;
|
||||||
std::ofstream mStream;
|
boost::filesystem::ofstream mStream;
|
||||||
ESM::ESMWriter mWriter;
|
ESM::ESMWriter mWriter;
|
||||||
boost::filesystem::path mProjectPath;
|
boost::filesystem::path mProjectPath;
|
||||||
bool mProjectFile;
|
bool mProjectFile;
|
||||||
|
std::map<std::string, std::vector<int> > mSubRecords; // record ID, list of subrecords
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SavingState (Operation& operation, const boost::filesystem::path& projectPath);
|
SavingState (Operation& operation, const boost::filesystem::path& projectPath,
|
||||||
|
ToUTF8::FromType encoding);
|
||||||
|
|
||||||
bool hasError() const;
|
bool hasError() const;
|
||||||
|
|
||||||
@ -36,15 +42,17 @@ namespace CSMDoc
|
|||||||
|
|
||||||
const boost::filesystem::path& getTmpPath() const;
|
const boost::filesystem::path& getTmpPath() const;
|
||||||
|
|
||||||
std::ofstream& getStream();
|
boost::filesystem::ofstream& getStream();
|
||||||
|
|
||||||
ESM::ESMWriter& getWriter();
|
ESM::ESMWriter& getWriter();
|
||||||
|
|
||||||
bool isProjectFile() const;
|
bool isProjectFile() const;
|
||||||
///< Currently saving project file? (instead of content file)
|
///< Currently saving project file? (instead of content file)
|
||||||
|
|
||||||
|
std::map<std::string, std::vector<int> >& getSubRecords();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -4,18 +4,22 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "../world/universalid.hpp"
|
||||||
|
|
||||||
namespace CSMDoc
|
namespace CSMDoc
|
||||||
{
|
{
|
||||||
class Stage
|
class Stage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
typedef std::vector<std::pair<CSMWorld::UniversalId, std::string> > Messages;
|
||||||
|
|
||||||
virtual ~Stage();
|
virtual ~Stage();
|
||||||
|
|
||||||
virtual int setup() = 0;
|
virtual int setup() = 0;
|
||||||
///< \return number of steps
|
///< \return number of steps
|
||||||
|
|
||||||
virtual void perform (int stage, std::vector<std::string>& messages) = 0;
|
virtual void perform (int stage, Messages& messages) = 0;
|
||||||
///< Messages resulting from this stage will be appended to \a messages.
|
///< Messages resulting from this stage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -3,17 +3,18 @@
|
|||||||
|
|
||||||
namespace CSMDoc
|
namespace CSMDoc
|
||||||
{
|
{
|
||||||
enum State
|
enum State
|
||||||
{
|
{
|
||||||
State_Modified = 1,
|
State_Modified = 1,
|
||||||
State_Locked = 2,
|
State_Locked = 2,
|
||||||
State_Operation = 4,
|
State_Operation = 4,
|
||||||
|
|
||||||
State_Saving = 8,
|
State_Saving = 8,
|
||||||
State_Verifying = 16,
|
State_Verifying = 16,
|
||||||
State_Compiling = 32, // not implemented yet
|
State_Compiling = 32, // not implemented yet
|
||||||
State_Searching = 64 // not implemented yet
|
State_Searching = 64, // not implemented yet
|
||||||
};
|
State_Loading = 128 // pseudo-state; can not be encountered in a loaded document
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
128
apps/opencs/model/settings/connector.cpp
Normal file
128
apps/opencs/model/settings/connector.cpp
Normal file
@ -0,0 +1,128 @@
|
|||||||
|
#include "connector.hpp"
|
||||||
|
#include "../../view/settings/view.hpp"
|
||||||
|
#include "../../view/settings/page.hpp"
|
||||||
|
|
||||||
|
CSMSettings::Connector::Connector(CSVSettings::View *master,
|
||||||
|
QObject *parent)
|
||||||
|
: mMasterView (master), QObject(parent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void CSMSettings::Connector::addSlaveView (CSVSettings::View *view,
|
||||||
|
QList <QStringList> &masterProxyValues)
|
||||||
|
{
|
||||||
|
mSlaveViews.append (view);
|
||||||
|
|
||||||
|
mProxyListMap[view->viewKey()].append (masterProxyValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
QList <QStringList> CSMSettings::Connector::getSlaveViewValues() const
|
||||||
|
{
|
||||||
|
QList <QStringList> list;
|
||||||
|
|
||||||
|
foreach (const CSVSettings::View *view, mSlaveViews)
|
||||||
|
list.append (view->selectedValues());
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMSettings::Connector::proxyListsMatch (
|
||||||
|
const QList <QStringList> &list1,
|
||||||
|
const QList <QStringList> &list2) const
|
||||||
|
{
|
||||||
|
bool success = true;
|
||||||
|
|
||||||
|
for (int i = 0; i < list1.size(); i++)
|
||||||
|
{
|
||||||
|
success = stringListsMatch (list1.at(i), list2.at(i));
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Connector::slotUpdateMaster() const
|
||||||
|
{
|
||||||
|
//list of the current values for each slave.
|
||||||
|
QList <QStringList> slaveValueList = getSlaveViewValues();
|
||||||
|
|
||||||
|
int masterColumn = -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A row in the master view is one of the values in the
|
||||||
|
* master view's data model. This corresponds directly to the number of
|
||||||
|
* values in a proxy list contained in the ProxyListMap member.
|
||||||
|
* Thus, we iterate each "column" in the master proxy list
|
||||||
|
* (one for each vlaue in the master. Each column represents
|
||||||
|
* one master value's corresponding list of slave values. We examine
|
||||||
|
* each master value's list, comparing it to the current slave value list,
|
||||||
|
* stopping when we find a match using proxyListsMatch().
|
||||||
|
*
|
||||||
|
* If no match is found, clear the master view's value
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (int i = 0; i < mMasterView->rowCount(); i++)
|
||||||
|
{
|
||||||
|
QList <QStringList> proxyValueList;
|
||||||
|
|
||||||
|
foreach (const QString &settingKey, mProxyListMap.keys())
|
||||||
|
{
|
||||||
|
// append the proxy value list stored in the i'th column
|
||||||
|
// for each setting key. A setting key is the id of the setting
|
||||||
|
// in page.name format.
|
||||||
|
proxyValueList.append (mProxyListMap.value(settingKey).at(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (proxyListsMatch (slaveValueList, proxyValueList))
|
||||||
|
{
|
||||||
|
masterColumn = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString masterValue = mMasterView->value (masterColumn);
|
||||||
|
|
||||||
|
mMasterView->setSelectedValue (masterValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Connector::slotUpdateSlaves() const
|
||||||
|
{
|
||||||
|
int row = mMasterView->currentIndex();
|
||||||
|
|
||||||
|
if (row == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//iterate the proxy lists for the chosen master index
|
||||||
|
//and pass the list to each slave for updating
|
||||||
|
for (int i = 0; i < mSlaveViews.size(); i++)
|
||||||
|
{
|
||||||
|
QList <QStringList> proxyList =
|
||||||
|
mProxyListMap.value(mSlaveViews.at(i)->viewKey());
|
||||||
|
|
||||||
|
mSlaveViews.at(i)->setSelectedValues (proxyList.at(row));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMSettings::Connector::stringListsMatch (
|
||||||
|
const QStringList &list1,
|
||||||
|
const QStringList &list2) const
|
||||||
|
{
|
||||||
|
//returns a "sloppy" match, verifying that each list contains all the same
|
||||||
|
//items, though not necessarily in the same order.
|
||||||
|
|
||||||
|
if (list1.size() != list2.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QStringList tempList(list2);
|
||||||
|
|
||||||
|
//iterate each value in the list, removing one occurrence of the value in
|
||||||
|
//the other list. If no corresponding value is found, test fails
|
||||||
|
foreach (const QString &value, list1)
|
||||||
|
{
|
||||||
|
if (!tempList.contains(value))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
tempList.removeOne(value);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
67
apps/opencs/model/settings/connector.hpp
Normal file
67
apps/opencs/model/settings/connector.hpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#ifndef CSMSETTINGS_CONNECTOR_HPP
|
||||||
|
#define CSMSETTINGS_CONNECTOR_HPP
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QList>
|
||||||
|
#include <QMap>
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
#include "support.hpp"
|
||||||
|
|
||||||
|
namespace CSVSettings {
|
||||||
|
class View;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CSMSettings {
|
||||||
|
|
||||||
|
class Connector : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
CSVSettings::View *mMasterView;
|
||||||
|
|
||||||
|
///map using the view pointer as a key to it's index value
|
||||||
|
QList <CSVSettings::View *> mSlaveViews;
|
||||||
|
|
||||||
|
///list of proxy values for each master value.
|
||||||
|
///value list order is indexed to the master value index.
|
||||||
|
QMap < QString, QList <QStringList> > mProxyListMap;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit Connector(CSVSettings::View *master,
|
||||||
|
QObject *parent = 0);
|
||||||
|
|
||||||
|
///Set the view which acts as a proxy for other setting views
|
||||||
|
void setMasterView (CSVSettings::View *view);
|
||||||
|
|
||||||
|
///Add a view to be updated / update to the master
|
||||||
|
void addSlaveView (CSVSettings::View *view,
|
||||||
|
QList <QStringList> &masterProxyValues);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
///loosely matches lists of proxy values across registered slaves
|
||||||
|
///against a proxy value list for a given master value
|
||||||
|
bool proxyListsMatch (const QList <QStringList> &list1,
|
||||||
|
const QList <QStringList> &list2) const;
|
||||||
|
|
||||||
|
///loosely matches two string lists
|
||||||
|
bool stringListsMatch (const QStringList &list1,
|
||||||
|
const QStringList &list2) const;
|
||||||
|
|
||||||
|
///retrieves current values of registered slave views
|
||||||
|
QList <QStringList> getSlaveViewValues() const;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
///updates slave views with proxy values associated with current
|
||||||
|
///master value
|
||||||
|
void slotUpdateSlaves() const;
|
||||||
|
|
||||||
|
///updates master value associated with the currently selected
|
||||||
|
///slave values, if applicable.
|
||||||
|
void slotUpdateMaster() const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CSMSETTINGS_CONNECTOR_HPP
|
391
apps/opencs/model/settings/setting.cpp
Normal file
391
apps/opencs/model/settings/setting.cpp
Normal file
@ -0,0 +1,391 @@
|
|||||||
|
#include "setting.hpp"
|
||||||
|
#include "support.hpp"
|
||||||
|
|
||||||
|
CSMSettings::Setting::Setting(SettingType typ, const QString &settingName,
|
||||||
|
const QString &pageName)
|
||||||
|
: mIsEditorSetting (false)
|
||||||
|
{
|
||||||
|
buildDefaultSetting();
|
||||||
|
|
||||||
|
int settingType = static_cast <int> (typ);
|
||||||
|
|
||||||
|
//even-numbered setting types are multi-valued
|
||||||
|
if ((settingType % 2) == 0)
|
||||||
|
setProperty (Property_IsMultiValue, QVariant(true).toString());
|
||||||
|
|
||||||
|
//view type is related to setting type by an order of magnitude
|
||||||
|
setProperty (Property_SettingType, QVariant (settingType).toString());
|
||||||
|
setProperty (Property_Page, pageName);
|
||||||
|
setProperty (Property_Name, settingName);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::buildDefaultSetting()
|
||||||
|
{
|
||||||
|
int arrLen = sizeof(sPropertyDefaults) / sizeof (*sPropertyDefaults);
|
||||||
|
|
||||||
|
for (int i = 0; i < arrLen; i++)
|
||||||
|
{
|
||||||
|
QStringList propertyList;
|
||||||
|
|
||||||
|
if (i <Property_DefaultValues)
|
||||||
|
propertyList.append (sPropertyDefaults[i]);
|
||||||
|
|
||||||
|
mProperties.append (propertyList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::addProxy (const Setting *setting,
|
||||||
|
const QStringList &vals)
|
||||||
|
{
|
||||||
|
if (serializable())
|
||||||
|
setSerializable (false);
|
||||||
|
|
||||||
|
QList <QStringList> list;
|
||||||
|
|
||||||
|
foreach (const QString &val, vals)
|
||||||
|
list << (QStringList() << val);
|
||||||
|
|
||||||
|
mProxies [setting->page() + '/' + setting->name()] = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::addProxy (const Setting *setting,
|
||||||
|
const QList <QStringList> &list)
|
||||||
|
{
|
||||||
|
if (serializable())
|
||||||
|
setProperty (Property_Serializable, false);
|
||||||
|
|
||||||
|
mProxies [setting->page() + '/' + setting->name()] = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setColumnSpan (int value)
|
||||||
|
{
|
||||||
|
setProperty (Property_ColumnSpan, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSMSettings::Setting::columnSpan() const
|
||||||
|
{
|
||||||
|
return property (Property_ColumnSpan).at(0).toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setDeclaredValues (QStringList list)
|
||||||
|
{
|
||||||
|
setProperty (Property_DeclaredValues, list);
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList CSMSettings::Setting::declaredValues() const
|
||||||
|
{
|
||||||
|
return property (Property_DeclaredValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList CSMSettings::Setting::property (SettingProperty prop) const
|
||||||
|
{
|
||||||
|
if (prop >= mProperties.size())
|
||||||
|
return QStringList();
|
||||||
|
|
||||||
|
return mProperties.at(prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setDefaultValue (int value)
|
||||||
|
{
|
||||||
|
setDefaultValues (QStringList() << QVariant (value).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setDefaultValue (double value)
|
||||||
|
{
|
||||||
|
setDefaultValues (QStringList() << QVariant (value).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setDefaultValue (const QString &value)
|
||||||
|
{
|
||||||
|
setDefaultValues (QStringList() << value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setDefaultValues (const QStringList &values)
|
||||||
|
{
|
||||||
|
setProperty (Property_DefaultValues, values);
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList CSMSettings::Setting::defaultValues() const
|
||||||
|
{
|
||||||
|
return property (Property_DefaultValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setDelimiter (const QString &value)
|
||||||
|
{
|
||||||
|
setProperty (Property_Delimiter, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CSMSettings::Setting::delimiter() const
|
||||||
|
{
|
||||||
|
return property (Property_Delimiter).at(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setEditorSetting(bool state)
|
||||||
|
{
|
||||||
|
mIsEditorSetting = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMSettings::Setting::isEditorSetting() const
|
||||||
|
{
|
||||||
|
return mIsEditorSetting;
|
||||||
|
}
|
||||||
|
void CSMSettings::Setting::setIsMultiLine (bool state)
|
||||||
|
{
|
||||||
|
setProperty (Property_IsMultiLine, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMSettings::Setting::isMultiLine() const
|
||||||
|
{
|
||||||
|
return (property (Property_IsMultiLine).at(0) == "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setIsMultiValue (bool state)
|
||||||
|
{
|
||||||
|
setProperty (Property_IsMultiValue, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMSettings::Setting::isMultiValue() const
|
||||||
|
{
|
||||||
|
return (property (Property_IsMultiValue).at(0) == "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
const CSMSettings::ProxyValueMap &CSMSettings::Setting::proxyLists() const
|
||||||
|
{
|
||||||
|
return mProxies;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setSerializable (bool state)
|
||||||
|
{
|
||||||
|
setProperty (Property_Serializable, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMSettings::Setting::serializable() const
|
||||||
|
{
|
||||||
|
return (property (Property_Serializable).at(0) == "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setSpecialValueText(const QString &text)
|
||||||
|
{
|
||||||
|
setProperty (Property_SpecialValueText, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CSMSettings::Setting::specialValueText() const
|
||||||
|
{
|
||||||
|
return property (Property_SpecialValueText).at(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setName (const QString &value)
|
||||||
|
{
|
||||||
|
setProperty (Property_Name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CSMSettings::Setting::name() const
|
||||||
|
{
|
||||||
|
return property (Property_Name).at(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setPage (const QString &value)
|
||||||
|
{
|
||||||
|
setProperty (Property_Page, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CSMSettings::Setting::page() const
|
||||||
|
{
|
||||||
|
return property (Property_Page).at(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setPrefix (const QString &value)
|
||||||
|
{
|
||||||
|
setProperty (Property_Prefix, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CSMSettings::Setting::prefix() const
|
||||||
|
{
|
||||||
|
return property (Property_Prefix).at(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setRowSpan (const int value)
|
||||||
|
{
|
||||||
|
setProperty (Property_RowSpan, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSMSettings::Setting::rowSpan () const
|
||||||
|
{
|
||||||
|
return property (Property_RowSpan).at(0).toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setSingleStep (int value)
|
||||||
|
{
|
||||||
|
setProperty (Property_SingleStep, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setSingleStep (double value)
|
||||||
|
{
|
||||||
|
setProperty (Property_SingleStep, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CSMSettings::Setting::singleStep() const
|
||||||
|
{
|
||||||
|
return property (Property_SingleStep).at(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setSuffix (const QString &value)
|
||||||
|
{
|
||||||
|
setProperty (Property_Suffix, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CSMSettings::Setting::suffix() const
|
||||||
|
{
|
||||||
|
return property (Property_Suffix).at(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setTickInterval (int value)
|
||||||
|
{
|
||||||
|
setProperty (Property_TickInterval, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSMSettings::Setting::tickInterval () const
|
||||||
|
{
|
||||||
|
return property (Property_TickInterval).at(0).toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setTicksAbove (bool state)
|
||||||
|
{
|
||||||
|
setProperty (Property_TicksAbove, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMSettings::Setting::ticksAbove() const
|
||||||
|
{
|
||||||
|
return (property (Property_TicksAbove).at(0) == "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setTicksBelow (bool state)
|
||||||
|
{
|
||||||
|
setProperty (Property_TicksBelow, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMSettings::Setting::ticksBelow() const
|
||||||
|
{
|
||||||
|
return (property (Property_TicksBelow).at(0) == "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setType (int settingType)
|
||||||
|
{
|
||||||
|
setProperty (Property_SettingType, settingType);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMSettings::SettingType CSMSettings::Setting::type() const
|
||||||
|
{
|
||||||
|
return static_cast <CSMSettings::SettingType> ( property (
|
||||||
|
Property_SettingType).at(0).toInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setMaximum (int value)
|
||||||
|
{
|
||||||
|
setProperty (Property_Maximum, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setMaximum (double value)
|
||||||
|
{
|
||||||
|
setProperty (Property_Maximum, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CSMSettings::Setting::maximum() const
|
||||||
|
{
|
||||||
|
return property (Property_Maximum).at(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setMinimum (int value)
|
||||||
|
{
|
||||||
|
setProperty (Property_Minimum, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setMinimum (double value)
|
||||||
|
{
|
||||||
|
setProperty (Property_Minimum, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString CSMSettings::Setting::minimum() const
|
||||||
|
{
|
||||||
|
return property (Property_Minimum).at(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVSettings::ViewType CSMSettings::Setting::viewType() const
|
||||||
|
{
|
||||||
|
return static_cast <CSVSettings::ViewType> ( property (
|
||||||
|
Property_SettingType).at(0).toInt() / 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setViewColumn (int value)
|
||||||
|
{
|
||||||
|
setProperty (Property_ViewColumn, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSMSettings::Setting::viewColumn() const
|
||||||
|
{
|
||||||
|
return property (Property_ViewColumn).at(0).toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setViewLocation (int row, int column)
|
||||||
|
{
|
||||||
|
setViewRow (row);
|
||||||
|
setViewColumn (column);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setViewRow (int value)
|
||||||
|
{
|
||||||
|
setProperty (Property_ViewRow, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSMSettings::Setting::viewRow() const
|
||||||
|
{
|
||||||
|
return property (Property_ViewRow).at(0).toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setWidgetWidth (int value)
|
||||||
|
{
|
||||||
|
setProperty (Property_WidgetWidth, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
int CSMSettings::Setting::widgetWidth() const
|
||||||
|
{
|
||||||
|
return property (Property_WidgetWidth).at(0).toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setWrapping (bool state)
|
||||||
|
{
|
||||||
|
setProperty (Property_Wrapping, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMSettings::Setting::wrapping() const
|
||||||
|
{
|
||||||
|
return (property (Property_Wrapping).at(0) == "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setProperty (SettingProperty prop, bool value)
|
||||||
|
{
|
||||||
|
setProperty (prop, QStringList() << QVariant (value).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setProperty (SettingProperty prop, int value)
|
||||||
|
{
|
||||||
|
setProperty (prop, QStringList() << QVariant (value).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setProperty (SettingProperty prop, double value)
|
||||||
|
{
|
||||||
|
setProperty (prop, QStringList() << QVariant (value).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setProperty (SettingProperty prop,
|
||||||
|
const QString &value)
|
||||||
|
{
|
||||||
|
setProperty (prop, QStringList() << value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMSettings::Setting::setProperty (SettingProperty prop,
|
||||||
|
const QStringList &value)
|
||||||
|
{
|
||||||
|
if (prop < mProperties.size())
|
||||||
|
mProperties.replace (prop, value);
|
||||||
|
}
|
150
apps/opencs/model/settings/setting.hpp
Normal file
150
apps/opencs/model/settings/setting.hpp
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
#ifndef CSMSETTINGS_SETTING_HPP
|
||||||
|
#define CSMSETTINGS_SETTING_HPP
|
||||||
|
|
||||||
|
#include <QStringList>
|
||||||
|
#include <QMap>
|
||||||
|
#include "support.hpp"
|
||||||
|
|
||||||
|
namespace CSMSettings
|
||||||
|
{
|
||||||
|
//QString is the setting id in the form of "page/name"
|
||||||
|
//QList is a list of stringlists of proxy values.
|
||||||
|
//Order is important! Proxy stringlists are matched against
|
||||||
|
//master values by their position in the QList.
|
||||||
|
typedef QMap <QString, QList <QStringList> > ProxyValueMap;
|
||||||
|
|
||||||
|
///Setting class is the interface for the User Settings. It contains
|
||||||
|
///a great deal of boiler plate to provide the core API functions, as
|
||||||
|
///well as the property() functions which use enumeration to be iterable.
|
||||||
|
///This makes the Setting class capable of being manipulated by script.
|
||||||
|
///See CSMSettings::support.hpp for enumerations / string values.
|
||||||
|
class Setting
|
||||||
|
{
|
||||||
|
QList <QStringList> mProperties;
|
||||||
|
QStringList mDefaults;
|
||||||
|
|
||||||
|
bool mIsEditorSetting;
|
||||||
|
|
||||||
|
ProxyValueMap mProxies;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit Setting(SettingType typ, const QString &settingName,
|
||||||
|
const QString &pageName);
|
||||||
|
|
||||||
|
void addProxy (const Setting *setting, const QStringList &vals);
|
||||||
|
void addProxy (const Setting *setting, const QList <QStringList> &list);
|
||||||
|
|
||||||
|
const QList <QStringList> &properties() const { return mProperties; }
|
||||||
|
const ProxyValueMap &proxies() const { return mProxies; }
|
||||||
|
|
||||||
|
void setColumnSpan (int value);
|
||||||
|
int columnSpan() const;
|
||||||
|
|
||||||
|
void setDeclaredValues (QStringList list);
|
||||||
|
QStringList declaredValues() const;
|
||||||
|
|
||||||
|
void setDefaultValue (int value);
|
||||||
|
void setDefaultValue (double value);
|
||||||
|
void setDefaultValue (const QString &value);
|
||||||
|
|
||||||
|
void setDefaultValues (const QStringList &values);
|
||||||
|
QStringList defaultValues() const;
|
||||||
|
|
||||||
|
void setDelimiter (const QString &value);
|
||||||
|
QString delimiter() const;
|
||||||
|
|
||||||
|
void setEditorSetting (bool state);
|
||||||
|
bool isEditorSetting() const;
|
||||||
|
|
||||||
|
void setIsMultiLine (bool state);
|
||||||
|
bool isMultiLine() const;
|
||||||
|
|
||||||
|
void setIsMultiValue (bool state);
|
||||||
|
bool isMultiValue() const;
|
||||||
|
|
||||||
|
void setMask (const QString &value);
|
||||||
|
QString mask() const;
|
||||||
|
|
||||||
|
void setMaximum (int value);
|
||||||
|
void setMaximum (double value);
|
||||||
|
QString maximum() const;
|
||||||
|
|
||||||
|
void setMinimum (int value);
|
||||||
|
void setMinimum (double value);
|
||||||
|
QString minimum() const;
|
||||||
|
|
||||||
|
void setName (const QString &value);
|
||||||
|
QString name() const;
|
||||||
|
|
||||||
|
void setPage (const QString &value);
|
||||||
|
QString page() const;
|
||||||
|
|
||||||
|
void setPrefix (const QString &value);
|
||||||
|
QString prefix() const;
|
||||||
|
|
||||||
|
void setRowSpan (const int value);
|
||||||
|
int rowSpan() const;
|
||||||
|
|
||||||
|
const ProxyValueMap &proxyLists() const;
|
||||||
|
|
||||||
|
void setSerializable (bool state);
|
||||||
|
bool serializable() const;
|
||||||
|
|
||||||
|
void setSpecialValueText (const QString &text);
|
||||||
|
QString specialValueText() const;
|
||||||
|
|
||||||
|
void setSingleStep (int value);
|
||||||
|
void setSingleStep (double value);
|
||||||
|
QString singleStep() const;
|
||||||
|
|
||||||
|
void setSuffix (const QString &value);
|
||||||
|
QString suffix() const;
|
||||||
|
|
||||||
|
void setTickInterval (int value);
|
||||||
|
int tickInterval() const;
|
||||||
|
|
||||||
|
void setTicksAbove (bool state);
|
||||||
|
bool ticksAbove() const;
|
||||||
|
|
||||||
|
void setTicksBelow (bool state);
|
||||||
|
bool ticksBelow() const;
|
||||||
|
|
||||||
|
void setViewColumn (int value);
|
||||||
|
int viewColumn() const;
|
||||||
|
|
||||||
|
void setViewLocation (int row = -1, int column = -1);
|
||||||
|
|
||||||
|
void setViewRow (int value);
|
||||||
|
int viewRow() const;
|
||||||
|
|
||||||
|
void setType (int settingType);
|
||||||
|
CSMSettings::SettingType type() const;
|
||||||
|
|
||||||
|
CSVSettings::ViewType viewType() const;
|
||||||
|
|
||||||
|
void setWrapping (bool state);
|
||||||
|
bool wrapping() const;
|
||||||
|
|
||||||
|
void setWidgetWidth (int value);
|
||||||
|
int widgetWidth() const;
|
||||||
|
|
||||||
|
///returns the specified property value
|
||||||
|
QStringList property (SettingProperty prop) const;
|
||||||
|
|
||||||
|
///boilerplate code to convert setting values of common types
|
||||||
|
void setProperty (SettingProperty prop, bool value);
|
||||||
|
void setProperty (SettingProperty prop, int value);
|
||||||
|
void setProperty (SettingProperty prop, double value);
|
||||||
|
void setProperty (SettingProperty prop, const QString &value);
|
||||||
|
void setProperty (SettingProperty prop, const QStringList &value);
|
||||||
|
|
||||||
|
void addProxy (Setting* setting,
|
||||||
|
QMap <QString, QStringList> &proxyMap);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void buildDefaultSetting();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CSMSETTINGS_SETTING_HPP
|
@ -1,82 +0,0 @@
|
|||||||
#include "settingcontainer.hpp"
|
|
||||||
|
|
||||||
#include <QStringList>
|
|
||||||
|
|
||||||
CSMSettings::SettingContainer::SettingContainer(QObject *parent) :
|
|
||||||
QObject(parent), mValue (0), mValues (0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
CSMSettings::SettingContainer::SettingContainer(const QString &value, QObject *parent) :
|
|
||||||
QObject(parent), mValue (new QString (value)), mValues (0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSMSettings::SettingContainer::insert (const QString &value)
|
|
||||||
{
|
|
||||||
if (mValue)
|
|
||||||
{
|
|
||||||
mValues = new QStringList;
|
|
||||||
mValues->push_back (*mValue);
|
|
||||||
mValues->push_back (value);
|
|
||||||
|
|
||||||
delete mValue;
|
|
||||||
mValue = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
delete mValue;
|
|
||||||
mValue = new QString (value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSMSettings::SettingContainer::update (const QString &value, int index)
|
|
||||||
{
|
|
||||||
if (isEmpty())
|
|
||||||
mValue = new QString(value);
|
|
||||||
|
|
||||||
else if (mValue)
|
|
||||||
*mValue = value;
|
|
||||||
|
|
||||||
else if (mValues)
|
|
||||||
mValues->replace(index, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString CSMSettings::SettingContainer::getValue (int index) const
|
|
||||||
{
|
|
||||||
QString retVal("");
|
|
||||||
|
|
||||||
//if mValue is valid, it's a single-value property.
|
|
||||||
//ignore the index and return the value
|
|
||||||
if (mValue)
|
|
||||||
retVal = *mValue;
|
|
||||||
|
|
||||||
//otherwise, if it's a multivalued property
|
|
||||||
//return the appropriate value at the index
|
|
||||||
else if (mValues)
|
|
||||||
{
|
|
||||||
if (index == -1)
|
|
||||||
retVal = mValues->at(0);
|
|
||||||
|
|
||||||
else if (index < mValues->size())
|
|
||||||
retVal = mValues->at(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
return retVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
int CSMSettings::SettingContainer::count () const
|
|
||||||
{
|
|
||||||
int retVal = 0;
|
|
||||||
|
|
||||||
if (!isEmpty())
|
|
||||||
{
|
|
||||||
if (mValues)
|
|
||||||
retVal = mValues->size();
|
|
||||||
else
|
|
||||||
retVal = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return retVal;
|
|
||||||
}
|
|
@ -1,47 +0,0 @@
|
|||||||
#ifndef SETTINGCONTAINER_HPP
|
|
||||||
#define SETTINGCONTAINER_HPP
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
|
|
||||||
class QStringList;
|
|
||||||
|
|
||||||
namespace CSMSettings
|
|
||||||
{
|
|
||||||
class SettingContainer : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
QString *mValue;
|
|
||||||
QStringList *mValues;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
explicit SettingContainer (QObject *parent = 0);
|
|
||||||
explicit SettingContainer (const QString &value, QObject *parent = 0);
|
|
||||||
|
|
||||||
/// add a value to the container
|
|
||||||
/// multiple values supported
|
|
||||||
void insert (const QString &value);
|
|
||||||
|
|
||||||
/// update an existing value
|
|
||||||
/// index specifies multiple values
|
|
||||||
void update (const QString &value, int index = 0);
|
|
||||||
|
|
||||||
/// return value at specified index
|
|
||||||
QString getValue (int index = -1) const;
|
|
||||||
|
|
||||||
/// retrieve list of all values
|
|
||||||
inline QStringList *getValues() const { return mValues; }
|
|
||||||
|
|
||||||
/// return size of list
|
|
||||||
int count() const;
|
|
||||||
|
|
||||||
/// test for empty container
|
|
||||||
/// useful for default-constructed containers returned by QMap when invalid key is passed
|
|
||||||
inline bool isEmpty() const { return (!mValue && !mValues); }
|
|
||||||
|
|
||||||
inline bool isMultiValue() const { return (mValues); }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // SETTINGCONTAINER_HPP
|
|
@ -1,104 +0,0 @@
|
|||||||
#include "settingsitem.hpp"
|
|
||||||
|
|
||||||
#include <QStringList>
|
|
||||||
|
|
||||||
bool CSMSettings::SettingsItem::updateItem (const QStringList *values)
|
|
||||||
{
|
|
||||||
QStringList::ConstIterator it = values->begin();
|
|
||||||
|
|
||||||
//if the item is not multivalued,
|
|
||||||
//save the last value passed in the container
|
|
||||||
if (!mIsMultiValue)
|
|
||||||
{
|
|
||||||
it = values->end();
|
|
||||||
it--;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isValid = true;
|
|
||||||
QString value ("");
|
|
||||||
|
|
||||||
for (; it != values->end(); ++it)
|
|
||||||
{
|
|
||||||
value = *it;
|
|
||||||
isValid = validate(value);
|
|
||||||
|
|
||||||
//skip only the invalid values
|
|
||||||
if (!isValid)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
insert(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return isValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSMSettings::SettingsItem::updateItem (const QString &value)
|
|
||||||
{
|
|
||||||
//takes a value or a SettingsContainer and updates itself accordingly
|
|
||||||
//after validating the data against it's own definition
|
|
||||||
|
|
||||||
QString newValue = value;
|
|
||||||
|
|
||||||
if (!validate (newValue))
|
|
||||||
newValue = mDefaultValue;
|
|
||||||
|
|
||||||
bool success = (getValue() != newValue);
|
|
||||||
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
if (mIsMultiValue)
|
|
||||||
insert (newValue);
|
|
||||||
else
|
|
||||||
update (newValue);
|
|
||||||
}
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSMSettings::SettingsItem::updateItem(int valueListIndex)
|
|
||||||
{
|
|
||||||
bool success = false;
|
|
||||||
|
|
||||||
if (mValueList)
|
|
||||||
{
|
|
||||||
if (mValueList->size() > valueListIndex)
|
|
||||||
success = updateItem (mValueList->at(valueListIndex));
|
|
||||||
}
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSMSettings::SettingsItem::validate (const QString &value)
|
|
||||||
{
|
|
||||||
//if there is no value list or value pair, there is no validation to do
|
|
||||||
bool isValid = !(!mValueList->isEmpty() || mValuePair);
|
|
||||||
|
|
||||||
if (!isValid && !mValueList->isEmpty())
|
|
||||||
{
|
|
||||||
for (QStringList::Iterator it = mValueList->begin(); it != mValueList->end(); ++it)
|
|
||||||
// foreach (QString listItem, *mValueList)
|
|
||||||
{
|
|
||||||
isValid = (value == *it);
|
|
||||||
|
|
||||||
if (isValid)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (!isValid && mValuePair)
|
|
||||||
{
|
|
||||||
int numVal = value.toInt();
|
|
||||||
|
|
||||||
isValid = (numVal > mValuePair->left.toInt() && numVal < mValuePair->right.toInt());
|
|
||||||
}
|
|
||||||
|
|
||||||
return isValid;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSMSettings::SettingsItem::setDefaultValue (const QString &value)
|
|
||||||
{
|
|
||||||
mDefaultValue = value;
|
|
||||||
update (value);
|
|
||||||
}
|
|
||||||
|
|
||||||
QString CSMSettings::SettingsItem::getDefaultValue() const
|
|
||||||
{
|
|
||||||
return mDefaultValue;
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
#ifndef SETTINGSITEM_HPP
|
|
||||||
#define SETTINGSITEM_HPP
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include "support.hpp"
|
|
||||||
#include "settingcontainer.hpp"
|
|
||||||
|
|
||||||
namespace CSMSettings
|
|
||||||
{
|
|
||||||
/// Represents a setting including metadata
|
|
||||||
/// (valid values, ranges, defaults, and multivalue status
|
|
||||||
class SettingsItem : public SettingContainer
|
|
||||||
{
|
|
||||||
QStringPair *mValuePair;
|
|
||||||
QStringList *mValueList;
|
|
||||||
bool mIsMultiValue;
|
|
||||||
QString mDefaultValue;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit SettingsItem(QString name, bool isMultiValue,
|
|
||||||
const QString& defaultValue, QObject *parent = 0)
|
|
||||||
: SettingContainer(defaultValue, parent),
|
|
||||||
mIsMultiValue (isMultiValue), mValueList (0),
|
|
||||||
mValuePair (0), mDefaultValue (defaultValue)
|
|
||||||
{
|
|
||||||
QObject::setObjectName(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// updateItem overloads for updating setting value
|
|
||||||
/// provided a list of values (multi-valued),
|
|
||||||
/// a specific value
|
|
||||||
/// or an index value corresponding to the mValueList
|
|
||||||
bool updateItem (const QStringList *values);
|
|
||||||
bool updateItem (const QString &value);
|
|
||||||
bool updateItem (int valueListIndex);
|
|
||||||
|
|
||||||
/// retrieve list of valid values for setting
|
|
||||||
inline QStringList *getValueList() { return mValueList; }
|
|
||||||
|
|
||||||
/// write list of valid values for setting
|
|
||||||
inline void setValueList (QStringList *valueList) { mValueList = valueList; }
|
|
||||||
|
|
||||||
/// valuePair used for spin boxes (max / min)
|
|
||||||
inline QStringPair *getValuePair() { return mValuePair; }
|
|
||||||
|
|
||||||
/// set value range (spinbox / integer use)
|
|
||||||
inline void setValuePair (QStringPair valuePair)
|
|
||||||
{
|
|
||||||
delete mValuePair;
|
|
||||||
mValuePair = new QStringPair(valuePair);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool isMultivalue () { return mIsMultiValue; }
|
|
||||||
|
|
||||||
void setDefaultValue (const QString &value);
|
|
||||||
QString getDefaultValue () const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
/// Verifies that the supplied value is one of the following:
|
|
||||||
/// 1. Within the limits of the value pair (min / max)
|
|
||||||
/// 2. One of the values indicated in the value list
|
|
||||||
bool validate (const QString &value);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif // SETTINGSITEM_HPP
|
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
#include "support.hpp"
|
|
@ -1,39 +1,145 @@
|
|||||||
#ifndef MODEL_SUPPORT_HPP
|
#ifndef SETTING_SUPPORT_HPP
|
||||||
#define MODEL_SUPPORT_HPP
|
#define SETTING_SUPPORT_HPP
|
||||||
|
|
||||||
#include <QObject>
|
#include <Qt>
|
||||||
|
#include <QPair>
|
||||||
|
#include <QList>
|
||||||
|
#include <QVariant>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
class QLayout;
|
//Enums
|
||||||
class QWidget;
|
namespace CSMSettings
|
||||||
class QListWidgetItem;
|
{
|
||||||
|
///Enumerated properties for scripting
|
||||||
|
enum SettingProperty
|
||||||
|
{
|
||||||
|
Property_Name = 0,
|
||||||
|
Property_Page = 1,
|
||||||
|
Property_SettingType = 2,
|
||||||
|
Property_IsMultiValue = 3,
|
||||||
|
Property_IsMultiLine = 4,
|
||||||
|
Property_WidgetWidth = 5,
|
||||||
|
Property_ViewRow = 6,
|
||||||
|
Property_ViewColumn = 7,
|
||||||
|
Property_Delimiter = 8,
|
||||||
|
Property_Serializable = 9,
|
||||||
|
Property_ColumnSpan = 10,
|
||||||
|
Property_RowSpan = 11,
|
||||||
|
Property_Minimum = 12,
|
||||||
|
Property_Maximum = 13,
|
||||||
|
Property_SpecialValueText = 14,
|
||||||
|
Property_Prefix = 15,
|
||||||
|
Property_Suffix = 16,
|
||||||
|
Property_SingleStep = 17,
|
||||||
|
Property_Wrapping = 18,
|
||||||
|
Property_TickInterval = 19,
|
||||||
|
Property_TicksAbove = 20,
|
||||||
|
Property_TicksBelow = 21,
|
||||||
|
|
||||||
|
//Stringlists should always be the last items
|
||||||
|
Property_DefaultValues = 22,
|
||||||
|
Property_DeclaredValues = 23,
|
||||||
|
Property_DefinedValues = 24,
|
||||||
|
Property_Proxies = 25
|
||||||
|
};
|
||||||
|
|
||||||
|
///Basic setting widget types.
|
||||||
|
enum SettingType
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* 0 - 9 - Boolean widgets
|
||||||
|
* 10-19 - List widgets
|
||||||
|
* 21-29 - Range widgets
|
||||||
|
* 31-39 - Text widgets
|
||||||
|
*
|
||||||
|
* Each range corresponds to a View_Type enum by a factor of 10.
|
||||||
|
*
|
||||||
|
* Even-numbered values are single-value widgets
|
||||||
|
* Odd-numbered values are multi-valued widgets
|
||||||
|
*/
|
||||||
|
|
||||||
|
Type_CheckBox = 0,
|
||||||
|
Type_RadioButton = 1,
|
||||||
|
Type_ListView = 10,
|
||||||
|
Type_ComboBox = 11,
|
||||||
|
Type_SpinBox = 21,
|
||||||
|
Type_DoubleSpinBox = 23,
|
||||||
|
Type_Slider = 25,
|
||||||
|
Type_Dial = 27,
|
||||||
|
Type_TextArea = 30,
|
||||||
|
Type_LineEdit = 31,
|
||||||
|
Type_Undefined = 40
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CSVSettings
|
||||||
|
{
|
||||||
|
///Categorical view types which encompass the setting widget types
|
||||||
|
enum ViewType
|
||||||
|
{
|
||||||
|
ViewType_Boolean = 0,
|
||||||
|
ViewType_List = 1,
|
||||||
|
ViewType_Range = 2,
|
||||||
|
ViewType_Text = 3,
|
||||||
|
ViewType_Undefined = 4
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
namespace CSMSettings
|
namespace CSMSettings
|
||||||
{
|
{
|
||||||
class SettingContainer;
|
///used to construct default settings in the Setting class
|
||||||
|
struct PropertyDefaultValues
|
||||||
typedef QList<SettingContainer *> SettingList;
|
|
||||||
typedef QMap<QString, SettingContainer *> SettingMap;
|
|
||||||
typedef QMap<QString, SettingMap *> SectionMap;
|
|
||||||
|
|
||||||
struct QStringPair
|
|
||||||
{
|
{
|
||||||
QStringPair(): left (""), right ("")
|
int id;
|
||||||
{}
|
QString name;
|
||||||
|
QVariant value;
|
||||||
|
};
|
||||||
|
|
||||||
QStringPair (const QString &leftValue, const QString &rightValue)
|
///strings which correspond to setting values. These strings represent
|
||||||
: left (leftValue), right(rightValue)
|
///the script language keywords which would be used to declare setting
|
||||||
{}
|
///views for 3rd party addons
|
||||||
|
const QString sPropertyNames[] =
|
||||||
|
{
|
||||||
|
"name", "page", "setting_type", "is_multi_value",
|
||||||
|
"is_multi_line", "widget_width", "view_row", "view_column", "delimiter",
|
||||||
|
"is_serializable","column_span", "row_span", "minimum", "maximum",
|
||||||
|
"special_value_text", "prefix", "suffix", "single_step", "wrapping",
|
||||||
|
"tick_interval", "ticks_above", "ticks_below",
|
||||||
|
"defaults", "declarations", "definitions", "proxies"
|
||||||
|
};
|
||||||
|
|
||||||
QStringPair (const QStringPair &pair)
|
///Default values for a setting. Used in setting creation.
|
||||||
: left (pair.left), right (pair.right)
|
const QString sPropertyDefaults[] =
|
||||||
{}
|
{
|
||||||
|
"", //name
|
||||||
QString left;
|
"", //page
|
||||||
QString right;
|
"40", //setting type
|
||||||
|
"false", //multivalue
|
||||||
bool isEmpty() const
|
"false", //multiline
|
||||||
{ return (left.isEmpty() && right.isEmpty()); }
|
"7", //widget width
|
||||||
|
"-1", //view row
|
||||||
|
"-1", //view column
|
||||||
|
",", //delimiter
|
||||||
|
"true", //serialized
|
||||||
|
"1", //column span
|
||||||
|
"1", //row span
|
||||||
|
"0", //value range
|
||||||
|
"0", //value minimum
|
||||||
|
"0", //value maximum
|
||||||
|
"", //special text
|
||||||
|
"", //prefix
|
||||||
|
"", //suffix
|
||||||
|
"false", //wrapping
|
||||||
|
"1", //tick interval
|
||||||
|
"false", //ticks above
|
||||||
|
"true", //ticks below
|
||||||
|
"", //default values
|
||||||
|
"", //declared values
|
||||||
|
"", //defined values
|
||||||
|
"" //proxy values
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif // MODEL_SUPPORT_HPP
|
|
||||||
|
#endif // VIEW_SUPPORT_HPP
|
||||||
|
@ -1,19 +1,15 @@
|
|||||||
#include "usersettings.hpp"
|
#include "usersettings.hpp"
|
||||||
|
|
||||||
#include <QTextStream>
|
#include <QSettings>
|
||||||
#include <QDir>
|
|
||||||
#include <QString>
|
|
||||||
#include <QRegExp>
|
|
||||||
#include <QMap>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QTextCodec>
|
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
|
||||||
#include <components/files/configurationmanager.hpp>
|
#include <components/files/configurationmanager.hpp>
|
||||||
#include "settingcontainer.hpp"
|
|
||||||
#include <boost/version.hpp>
|
#include <boost/version.hpp>
|
||||||
|
|
||||||
|
#include "setting.hpp"
|
||||||
|
#include "support.hpp"
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Workaround for problems with whitespaces in paths in older versions of Boost library
|
* Workaround for problems with whitespaces in paths in older versions of Boost library
|
||||||
*/
|
*/
|
||||||
@ -32,43 +28,250 @@ namespace boost
|
|||||||
|
|
||||||
CSMSettings::UserSettings *CSMSettings::UserSettings::mUserSettingsInstance = 0;
|
CSMSettings::UserSettings *CSMSettings::UserSettings::mUserSettingsInstance = 0;
|
||||||
|
|
||||||
CSMSettings::UserSettings::UserSettings()
|
CSMSettings::UserSettings::UserSettings (const Files::ConfigurationManager& configurationManager)
|
||||||
|
: mCfgMgr (configurationManager)
|
||||||
{
|
{
|
||||||
assert(!mUserSettingsInstance);
|
assert(!mUserSettingsInstance);
|
||||||
mUserSettingsInstance = this;
|
mUserSettingsInstance = this;
|
||||||
|
|
||||||
mReadWriteMessage = QObject::tr("<br><b>Could not open or create file for writing</b><br><br> \
|
mSettingDefinitions = 0;
|
||||||
Please make sure you have the right permissions and try again.<br>");
|
|
||||||
|
|
||||||
mReadOnlyMessage = QObject::tr("<br><b>Could not open file for reading</b><br><br> \
|
buildSettingModelDefaults();
|
||||||
Please make sure you have the right permissions and try again.<br>");
|
|
||||||
|
|
||||||
buildEditorSettingDefaults();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMSettings::UserSettings::buildEditorSettingDefaults()
|
void CSMSettings::UserSettings::buildSettingModelDefaults()
|
||||||
{
|
{
|
||||||
SettingContainer *windowHeight = new SettingContainer("768", this);
|
QString section = "Window Size";
|
||||||
SettingContainer *windowWidth = new SettingContainer("1024", this);
|
{
|
||||||
SettingContainer *rsDelegate = new SettingContainer("Icon and Text", this);
|
Setting *width = createSetting (Type_LineEdit, section, "Width");
|
||||||
SettingContainer *refIdTypeDelegate = new SettingContainer("Icon and Text", this);
|
Setting *height = createSetting (Type_LineEdit, section, "Height");
|
||||||
|
|
||||||
windowHeight->setObjectName ("Height");
|
width->setWidgetWidth (5);
|
||||||
windowWidth->setObjectName ("Width");
|
height->setWidgetWidth (8);
|
||||||
rsDelegate->setObjectName ("Record Status Display");
|
|
||||||
refIdTypeDelegate->setObjectName ("Referenceable ID Type Display");
|
|
||||||
|
|
||||||
SettingMap *displayFormatMap = new SettingMap;
|
width->setDefaultValues (QStringList() << "1024");
|
||||||
SettingMap *windowSizeMap = new SettingMap;
|
height->setDefaultValues (QStringList() << "768");
|
||||||
|
|
||||||
displayFormatMap->insert (rsDelegate->objectName(), rsDelegate );
|
width->setEditorSetting (true);
|
||||||
displayFormatMap->insert (refIdTypeDelegate->objectName(), refIdTypeDelegate);
|
height->setEditorSetting (true);
|
||||||
|
|
||||||
windowSizeMap->insert (windowWidth->objectName(), windowWidth );
|
height->setViewLocation (2,2);
|
||||||
windowSizeMap->insert (windowHeight->objectName(), windowHeight );
|
width->setViewLocation (2,1);
|
||||||
|
|
||||||
mEditorSettingDefaults.insert ("Display Format", displayFormatMap);
|
/*
|
||||||
mEditorSettingDefaults.insert ("Window Size", windowSizeMap);
|
*Create the proxy setting for predefined values
|
||||||
|
*/
|
||||||
|
Setting *preDefined = createSetting (Type_ComboBox, section,
|
||||||
|
"Pre-Defined");
|
||||||
|
|
||||||
|
preDefined->setDeclaredValues (QStringList() << "640 x 480"
|
||||||
|
<< "800 x 600" << "1024 x 768" << "1440 x 900");
|
||||||
|
|
||||||
|
preDefined->setViewLocation (1, 1);
|
||||||
|
preDefined->setWidgetWidth (10);
|
||||||
|
preDefined->setColumnSpan (2);
|
||||||
|
|
||||||
|
preDefined->addProxy (width,
|
||||||
|
QStringList() << "640" << "800" << "1024" << "1440"
|
||||||
|
);
|
||||||
|
|
||||||
|
preDefined->addProxy (height,
|
||||||
|
QStringList() << "480" << "600" << "768" << "900"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
section = "Display Format";
|
||||||
|
{
|
||||||
|
QString defaultValue = "Icon and Text";
|
||||||
|
|
||||||
|
QStringList values = QStringList()
|
||||||
|
<< defaultValue << "Icon Only" << "Text Only";
|
||||||
|
|
||||||
|
Setting *rsd = createSetting (Type_RadioButton,
|
||||||
|
section, "Record Status Display");
|
||||||
|
|
||||||
|
Setting *ritd = createSetting (Type_RadioButton,
|
||||||
|
section, "Referenceable ID Type Display");
|
||||||
|
|
||||||
|
rsd->setDeclaredValues (values);
|
||||||
|
ritd->setDeclaredValues (values);
|
||||||
|
|
||||||
|
rsd->setEditorSetting (true);
|
||||||
|
ritd->setEditorSetting (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
section = "Proxy Selection Test";
|
||||||
|
{
|
||||||
|
/******************************************************************
|
||||||
|
* There are three types of values:
|
||||||
|
*
|
||||||
|
* Declared values
|
||||||
|
*
|
||||||
|
* Pre-determined values, typically for
|
||||||
|
* combobox drop downs and boolean (radiobutton / checkbox) labels.
|
||||||
|
* These values represent the total possible list of values that
|
||||||
|
* may define a setting. No other values are allowed.
|
||||||
|
*
|
||||||
|
* Defined values
|
||||||
|
*
|
||||||
|
* Values which represent the actual, current value of
|
||||||
|
* a setting. For settings with declared values, this must be one
|
||||||
|
* or several declared values, as appropriate.
|
||||||
|
*
|
||||||
|
* Proxy values
|
||||||
|
* Values the proxy master updates the proxy slave when
|
||||||
|
* it's own definition is set / changed. These are definitions for
|
||||||
|
* proxy slave settings, but must match any declared values the
|
||||||
|
* proxy slave has, if any.
|
||||||
|
*******************************************************************/
|
||||||
|
/*
|
||||||
|
//create setting objects, specifying the basic widget type,
|
||||||
|
//the page name, and the view name
|
||||||
|
|
||||||
|
Setting *masterBoolean = createSetting (Type_RadioButton, section,
|
||||||
|
"Master Proxy");
|
||||||
|
|
||||||
|
Setting *slaveBoolean = createSetting (Type_CheckBox, section,
|
||||||
|
"Proxy Checkboxes");
|
||||||
|
|
||||||
|
Setting *slaveSingleText = createSetting (Type_LineEdit, section,
|
||||||
|
"Proxy TextBox 1");
|
||||||
|
|
||||||
|
Setting *slaveMultiText = createSetting (Type_LineEdit, section,
|
||||||
|
"ProxyTextBox 2");
|
||||||
|
|
||||||
|
Setting *slaveAlphaSpinbox = createSetting (Type_SpinBox, section,
|
||||||
|
"Alpha Spinbox");
|
||||||
|
|
||||||
|
Setting *slaveIntegerSpinbox = createSetting (Type_SpinBox, section,
|
||||||
|
"Int Spinbox");
|
||||||
|
|
||||||
|
Setting *slaveDoubleSpinbox = createSetting (Type_DoubleSpinBox,
|
||||||
|
section, "Double Spinbox");
|
||||||
|
|
||||||
|
Setting *slaveSlider = createSetting (Type_Slider, section, "Slider");
|
||||||
|
|
||||||
|
Setting *slaveDial = createSetting (Type_Dial, section, "Dial");
|
||||||
|
|
||||||
|
//set declared values for selected views
|
||||||
|
masterBoolean->setDeclaredValues (QStringList()
|
||||||
|
<< "Profile One" << "Profile Two"
|
||||||
|
<< "Profile Three" << "Profile Four");
|
||||||
|
|
||||||
|
slaveBoolean->setDeclaredValues (QStringList()
|
||||||
|
<< "One" << "Two" << "Three" << "Four" << "Five");
|
||||||
|
|
||||||
|
slaveAlphaSpinbox->setDeclaredValues (QStringList()
|
||||||
|
<< "One" << "Two" << "Three" << "Four");
|
||||||
|
|
||||||
|
|
||||||
|
masterBoolean->addProxy (slaveBoolean, QList <QStringList>()
|
||||||
|
<< (QStringList() << "One" << "Three")
|
||||||
|
<< (QStringList() << "One" << "Three")
|
||||||
|
<< (QStringList() << "One" << "Three" << "Five")
|
||||||
|
<< (QStringList() << "Two" << "Four")
|
||||||
|
);
|
||||||
|
|
||||||
|
masterBoolean->addProxy (slaveSingleText, QList <QStringList>()
|
||||||
|
<< (QStringList() << "Text A")
|
||||||
|
<< (QStringList() << "Text B")
|
||||||
|
<< (QStringList() << "Text A")
|
||||||
|
<< (QStringList() << "Text C")
|
||||||
|
);
|
||||||
|
|
||||||
|
masterBoolean->addProxy (slaveMultiText, QList <QStringList>()
|
||||||
|
<< (QStringList() << "One" << "Three")
|
||||||
|
<< (QStringList() << "One" << "Three")
|
||||||
|
<< (QStringList() << "One" << "Three" << "Five")
|
||||||
|
<< (QStringList() << "Two" << "Four")
|
||||||
|
);
|
||||||
|
|
||||||
|
masterBoolean->addProxy (slaveAlphaSpinbox, QList <QStringList>()
|
||||||
|
<< (QStringList() << "Four")
|
||||||
|
<< (QStringList() << "Three")
|
||||||
|
<< (QStringList() << "Two")
|
||||||
|
<< (QStringList() << "One"));
|
||||||
|
|
||||||
|
masterBoolean->addProxy (slaveIntegerSpinbox, QList <QStringList> ()
|
||||||
|
<< (QStringList() << "0")
|
||||||
|
<< (QStringList() << "7")
|
||||||
|
<< (QStringList() << "14")
|
||||||
|
<< (QStringList() << "21"));
|
||||||
|
|
||||||
|
masterBoolean->addProxy (slaveDoubleSpinbox, QList <QStringList> ()
|
||||||
|
<< (QStringList() << "0.17")
|
||||||
|
<< (QStringList() << "0.34")
|
||||||
|
<< (QStringList() << "0.51")
|
||||||
|
<< (QStringList() << "0.68"));
|
||||||
|
|
||||||
|
masterBoolean->addProxy (slaveSlider, QList <QStringList> ()
|
||||||
|
<< (QStringList() << "25")
|
||||||
|
<< (QStringList() << "50")
|
||||||
|
<< (QStringList() << "75")
|
||||||
|
<< (QStringList() << "100")
|
||||||
|
);
|
||||||
|
|
||||||
|
masterBoolean->addProxy (slaveDial, QList <QStringList> ()
|
||||||
|
<< (QStringList() << "25")
|
||||||
|
<< (QStringList() << "50")
|
||||||
|
<< (QStringList() << "75")
|
||||||
|
<< (QStringList() << "100")
|
||||||
|
);
|
||||||
|
|
||||||
|
//settings with proxies are not serialized by default
|
||||||
|
//other settings non-serialized for demo purposes
|
||||||
|
slaveBoolean->setSerializable (false);
|
||||||
|
slaveSingleText->setSerializable (false);
|
||||||
|
slaveMultiText->setSerializable (false);
|
||||||
|
slaveAlphaSpinbox->setSerializable (false);
|
||||||
|
slaveIntegerSpinbox->setSerializable (false);
|
||||||
|
slaveDoubleSpinbox->setSerializable (false);
|
||||||
|
slaveSlider->setSerializable (false);
|
||||||
|
slaveDial->setSerializable (false);
|
||||||
|
|
||||||
|
slaveBoolean->setDefaultValues (QStringList()
|
||||||
|
<< "One" << "Three" << "Five");
|
||||||
|
|
||||||
|
slaveSingleText->setDefaultValue ("Text A");
|
||||||
|
|
||||||
|
slaveMultiText->setDefaultValues (QStringList()
|
||||||
|
<< "One" << "Three" << "Five");
|
||||||
|
|
||||||
|
slaveSingleText->setWidgetWidth (24);
|
||||||
|
slaveMultiText->setWidgetWidth (24);
|
||||||
|
|
||||||
|
slaveAlphaSpinbox->setDefaultValue ("Two");
|
||||||
|
slaveAlphaSpinbox->setWidgetWidth (20);
|
||||||
|
//slaveAlphaSpinbox->setPrefix ("No. ");
|
||||||
|
//slaveAlphaSpinbox->setSuffix ("!");
|
||||||
|
slaveAlphaSpinbox->setWrapping (true);
|
||||||
|
|
||||||
|
slaveIntegerSpinbox->setDefaultValue (14);
|
||||||
|
slaveIntegerSpinbox->setMinimum (0);
|
||||||
|
slaveIntegerSpinbox->setMaximum (58);
|
||||||
|
slaveIntegerSpinbox->setPrefix ("$");
|
||||||
|
slaveIntegerSpinbox->setSuffix (".00");
|
||||||
|
slaveIntegerSpinbox->setWidgetWidth (10);
|
||||||
|
slaveIntegerSpinbox->setSpecialValueText ("Nothing!");
|
||||||
|
|
||||||
|
slaveDoubleSpinbox->setDefaultValue (0.51);
|
||||||
|
slaveDoubleSpinbox->setSingleStep(0.17);
|
||||||
|
slaveDoubleSpinbox->setMaximum(4.0);
|
||||||
|
|
||||||
|
slaveSlider->setMinimum (0);
|
||||||
|
slaveSlider->setMaximum (100);
|
||||||
|
slaveSlider->setDefaultValue (75);
|
||||||
|
slaveSlider->setWidgetWidth (100);
|
||||||
|
slaveSlider->setTicksAbove (true);
|
||||||
|
slaveSlider->setTickInterval (25);
|
||||||
|
|
||||||
|
slaveDial->setMinimum (0);
|
||||||
|
slaveDial->setMaximum (100);
|
||||||
|
slaveDial->setSingleStep (5);
|
||||||
|
slaveDial->setDefaultValue (75);
|
||||||
|
slaveDial->setTickInterval (25);
|
||||||
|
*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMSettings::UserSettings::~UserSettings()
|
CSMSettings::UserSettings::~UserSettings()
|
||||||
@ -76,230 +279,62 @@ CSMSettings::UserSettings::~UserSettings()
|
|||||||
mUserSettingsInstance = 0;
|
mUserSettingsInstance = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
QTextStream *CSMSettings::UserSettings::openFileStream (const QString &filePath, bool isReadOnly) const
|
|
||||||
{
|
|
||||||
QIODevice::OpenMode openFlags = QIODevice::Text;
|
|
||||||
|
|
||||||
if (isReadOnly)
|
|
||||||
openFlags = QIODevice::ReadOnly | openFlags;
|
|
||||||
else
|
|
||||||
openFlags = QIODevice::ReadWrite | QIODevice::Truncate | openFlags;
|
|
||||||
|
|
||||||
QFile *file = new QFile(filePath);
|
|
||||||
QTextStream *stream = 0;
|
|
||||||
|
|
||||||
if (file->open(openFlags))
|
|
||||||
{
|
|
||||||
stream = new QTextStream(file);
|
|
||||||
stream->setCodec(QTextCodec::codecForName("UTF-8"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return stream;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSMSettings::UserSettings::writeSettings(QMap<QString, CSMSettings::SettingList *> &settings)
|
|
||||||
{
|
|
||||||
QTextStream *stream = openFileStream(mUserFilePath);
|
|
||||||
|
|
||||||
bool success = (stream);
|
|
||||||
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
QList<QString> keyList = settings.keys();
|
|
||||||
|
|
||||||
foreach (QString key, keyList)
|
|
||||||
{
|
|
||||||
SettingList *sectionSettings = settings[key];
|
|
||||||
|
|
||||||
*stream << "[" << key << "]" << '\n';
|
|
||||||
|
|
||||||
foreach (SettingContainer *item, *sectionSettings)
|
|
||||||
*stream << item->objectName() << " = " << item->getValue() << '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
stream->device()->close();
|
|
||||||
delete stream;
|
|
||||||
stream = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
displayFileErrorMessage(mReadWriteMessage, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (success);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const CSMSettings::SectionMap &CSMSettings::UserSettings::getSectionMap() const
|
|
||||||
{
|
|
||||||
return mSectionSettings;
|
|
||||||
}
|
|
||||||
|
|
||||||
const CSMSettings::SettingMap *CSMSettings::UserSettings::getSettings(const QString §ionName) const
|
|
||||||
{
|
|
||||||
return getValidSettings(sectionName);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSMSettings::UserSettings::loadFromFile(const QString &filePath)
|
|
||||||
{
|
|
||||||
if (filePath.isEmpty())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
SectionMap loadedSettings;
|
|
||||||
|
|
||||||
QTextStream *stream = openFileStream (filePath, true);
|
|
||||||
|
|
||||||
bool success = (stream);
|
|
||||||
|
|
||||||
if (success)
|
|
||||||
{
|
|
||||||
//looks for a square bracket, "'\\["
|
|
||||||
//that has one or more "not nothing" in it, "([^]]+)"
|
|
||||||
//and is closed with a square bracket, "\\]"
|
|
||||||
|
|
||||||
QRegExp sectionRe("^\\[([^]]+)\\]");
|
|
||||||
|
|
||||||
//Find any character(s) that is/are not equal sign(s), "[^=]+"
|
|
||||||
//followed by an optional whitespace, an equal sign, and another optional whitespace, "\\s*=\\s*"
|
|
||||||
//and one or more periods, "(.+)"
|
|
||||||
|
|
||||||
QRegExp keyRe("^([^=]+)\\s*=\\s*(.+)$");
|
|
||||||
|
|
||||||
CSMSettings::SettingMap *settings = 0;
|
|
||||||
QString section = "none";
|
|
||||||
|
|
||||||
while (!stream->atEnd())
|
|
||||||
{
|
|
||||||
QString line = stream->readLine().simplified();
|
|
||||||
|
|
||||||
if (line.isEmpty() || line.startsWith("#"))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
//if a section is found, push it onto a new QStringList
|
|
||||||
//and push the QStringList onto
|
|
||||||
if (sectionRe.exactMatch(line))
|
|
||||||
{
|
|
||||||
//add the previous section's settings to the member map
|
|
||||||
if (settings)
|
|
||||||
loadedSettings.insert(section, settings);
|
|
||||||
|
|
||||||
//save new section and create a new list
|
|
||||||
section = sectionRe.cap(1);
|
|
||||||
settings = new SettingMap;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keyRe.indexIn(line) != -1)
|
|
||||||
{
|
|
||||||
SettingContainer *sc = new SettingContainer (keyRe.cap(2).simplified());
|
|
||||||
sc->setObjectName(keyRe.cap(1).simplified());
|
|
||||||
(*settings)[keyRe.cap(1).simplified()] = sc;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
loadedSettings.insert(section, settings);
|
|
||||||
|
|
||||||
stream->device()->close();
|
|
||||||
delete stream;
|
|
||||||
stream = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
mergeMap (loadedSettings);
|
|
||||||
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSMSettings::UserSettings::mergeMap (const CSMSettings::SectionMap §ionSettings)
|
|
||||||
{
|
|
||||||
foreach (QString key, sectionSettings.uniqueKeys())
|
|
||||||
{
|
|
||||||
// insert entire section if it does not already exist in the loaded files
|
|
||||||
if (mSectionSettings.find(key) == mSectionSettings.end())
|
|
||||||
mSectionSettings.insert(key, sectionSettings.value(key));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SettingMap *passedSettings = sectionSettings.value(key);
|
|
||||||
SettingMap *settings = mSectionSettings.value(key);
|
|
||||||
|
|
||||||
foreach (QString key2, passedSettings->uniqueKeys())
|
|
||||||
{
|
|
||||||
//insert section settings individially if they do not already exist
|
|
||||||
if (settings->find(key2) == settings->end())
|
|
||||||
settings->insert(key2, passedSettings->value(key2));
|
|
||||||
else
|
|
||||||
{
|
|
||||||
settings->value(key2)->update(passedSettings->value(key2)->getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CSMSettings::UserSettings::loadSettings (const QString &fileName)
|
void CSMSettings::UserSettings::loadSettings (const QString &fileName)
|
||||||
{
|
{
|
||||||
mSectionSettings.clear();
|
QString userFilePath = QString::fromUtf8
|
||||||
|
(mCfgMgr.getUserConfigPath().string().c_str());
|
||||||
|
|
||||||
//global
|
QString globalFilePath = QString::fromUtf8
|
||||||
QString globalFilePath = QString::fromStdString(mCfgMgr.getGlobalPath().string()) + fileName;
|
(mCfgMgr.getGlobalPath().string().c_str());
|
||||||
bool globalOk = loadFromFile(globalFilePath);
|
|
||||||
|
|
||||||
|
QString otherFilePath = globalFilePath;
|
||||||
|
|
||||||
//local
|
//test for local only if global fails (uninstalled copy)
|
||||||
QString localFilePath = QString::fromStdString(mCfgMgr.getLocalPath().string()) + fileName;
|
if (!QFile (globalFilePath + fileName).exists())
|
||||||
bool localOk = loadFromFile(localFilePath);
|
|
||||||
|
|
||||||
//user
|
|
||||||
mUserFilePath = QString::fromStdString(mCfgMgr.getUserConfigPath().string()) + fileName;
|
|
||||||
loadFromFile(mUserFilePath);
|
|
||||||
|
|
||||||
if (!(localOk || globalOk))
|
|
||||||
{
|
{
|
||||||
QString message = QObject::tr("<br><b>Could not open user settings files for reading</b><br><br> \
|
//if global is invalid, use the local path
|
||||||
Global and local settings files could not be read.\
|
otherFilePath = QString::fromUtf8
|
||||||
You may have incorrect file permissions or the OpenCS installation may be corrupted.<br>");
|
(mCfgMgr.getLocalPath().string().c_str());
|
||||||
|
|
||||||
message += QObject::tr("<br>Global filepath: ") + globalFilePath;
|
|
||||||
message += QObject::tr("<br>Local filepath: ") + localFilePath;
|
|
||||||
|
|
||||||
displayFileErrorMessage ( message, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSettings::setPath
|
||||||
|
(QSettings::IniFormat, QSettings::UserScope, userFilePath);
|
||||||
|
|
||||||
|
QSettings::setPath
|
||||||
|
(QSettings::IniFormat, QSettings::SystemScope, otherFilePath);
|
||||||
|
|
||||||
|
mSettingDefinitions = new QSettings
|
||||||
|
(QSettings::IniFormat, QSettings::UserScope, "opencs", QString(), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMSettings::UserSettings::updateSettings (const QString §ionName, const QString &settingName)
|
bool CSMSettings::UserSettings::hasSettingDefinitions
|
||||||
|
(const QString &viewKey) const
|
||||||
{
|
{
|
||||||
|
return (mSettingDefinitions->contains (viewKey));
|
||||||
SettingMap *settings = getValidSettings(sectionName);
|
|
||||||
|
|
||||||
if (!settings)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (settingName.isEmpty())
|
|
||||||
{
|
|
||||||
foreach (const SettingContainer *setting, *settings)
|
|
||||||
emit signalUpdateEditorSetting (setting->objectName(), setting->getValue());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (settings->find(settingName) != settings->end())
|
|
||||||
{
|
|
||||||
const SettingContainer *setting = settings->value(settingName);
|
|
||||||
emit signalUpdateEditorSetting (setting->objectName(), setting->getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString CSMSettings::UserSettings::getSetting (const QString §ion, const QString &setting) const
|
void CSMSettings::UserSettings::setDefinitions
|
||||||
|
(const QString &key, const QStringList &list)
|
||||||
{
|
{
|
||||||
SettingMap *settings = getValidSettings(section);
|
mSettingDefinitions->setValue (key, list);
|
||||||
|
}
|
||||||
|
|
||||||
QString retVal = "";
|
void CSMSettings::UserSettings::saveDefinitions() const
|
||||||
|
{
|
||||||
|
mSettingDefinitions->sync();
|
||||||
|
}
|
||||||
|
|
||||||
if (settings->find(setting) != settings->end())
|
QString CSMSettings::UserSettings::settingValue (const QString &settingKey)
|
||||||
retVal = settings->value(setting)->getValue();
|
{
|
||||||
|
if (!mSettingDefinitions->contains (settingKey))
|
||||||
|
return QString();
|
||||||
|
|
||||||
return retVal;
|
QStringList defs = mSettingDefinitions->value (settingKey).toStringList();
|
||||||
|
|
||||||
|
if (defs.isEmpty())
|
||||||
|
return QString();
|
||||||
|
|
||||||
|
return defs.at(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMSettings::UserSettings& CSMSettings::UserSettings::instance()
|
CSMSettings::UserSettings& CSMSettings::UserSettings::instance()
|
||||||
@ -308,48 +343,85 @@ CSMSettings::UserSettings& CSMSettings::UserSettings::instance()
|
|||||||
return *mUserSettingsInstance;
|
return *mUserSettingsInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMSettings::UserSettings::displayFileErrorMessage(const QString &message, bool isReadOnly)
|
void CSMSettings::UserSettings::updateUserSetting(const QString &settingKey,
|
||||||
|
const QStringList &list)
|
||||||
{
|
{
|
||||||
// File cannot be opened or created
|
mSettingDefinitions->setValue (settingKey ,list);
|
||||||
QMessageBox msgBox;
|
|
||||||
msgBox.setWindowTitle(QObject::tr("OpenCS configuration file I/O error"));
|
|
||||||
msgBox.setIcon(QMessageBox::Critical);
|
|
||||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
|
||||||
|
|
||||||
if (!isReadOnly)
|
emit userSettingUpdated (settingKey, list);
|
||||||
msgBox.setText (mReadWriteMessage + message);
|
|
||||||
else
|
|
||||||
msgBox.setText (message);
|
|
||||||
|
|
||||||
msgBox.exec();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMSettings::SettingMap *
|
CSMSettings::Setting *CSMSettings::UserSettings::findSetting
|
||||||
CSMSettings::UserSettings::getValidSettings (const QString §ionName) const
|
(const QString &pageName, const QString &settingName)
|
||||||
{
|
{
|
||||||
SettingMap *settings = 0;
|
foreach (Setting *setting, mSettings)
|
||||||
|
|
||||||
//copy the default values for the entire section if it's not found
|
|
||||||
if (mSectionSettings.find(sectionName) == mSectionSettings.end())
|
|
||||||
{
|
{
|
||||||
if (mEditorSettingDefaults.find(sectionName) != mEditorSettingDefaults.end())
|
if (setting->name() == settingName)
|
||||||
settings = mEditorSettingDefaults.value (sectionName);
|
|
||||||
}
|
|
||||||
//otherwise, iterate the section's settings, looking for missing values and replacing them with defaults.
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SettingMap *loadedSettings = mSectionSettings[sectionName];
|
|
||||||
SettingMap *defaultSettings = mEditorSettingDefaults[sectionName];
|
|
||||||
|
|
||||||
foreach (QString key, defaultSettings->uniqueKeys())
|
|
||||||
{
|
{
|
||||||
//write the default value to the loaded settings
|
if (setting->page() == pageName)
|
||||||
if (loadedSettings->find((key))==loadedSettings->end())
|
return setting;
|
||||||
loadedSettings->insert(key, defaultSettings->value(key));
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
settings = mSectionSettings.value (sectionName);
|
void CSMSettings::UserSettings::removeSetting
|
||||||
|
(const QString &pageName, const QString &settingName)
|
||||||
|
{
|
||||||
|
if (mSettings.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
QList <Setting *>::iterator removeIterator = mSettings.begin();
|
||||||
|
|
||||||
|
while (removeIterator != mSettings.end())
|
||||||
|
{
|
||||||
|
if ((*removeIterator)->name() == settingName)
|
||||||
|
{
|
||||||
|
if ((*removeIterator)->page() == pageName)
|
||||||
|
{
|
||||||
|
mSettings.erase (removeIterator);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
removeIterator++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSMSettings::SettingPageMap CSMSettings::UserSettings::settingPageMap() const
|
||||||
|
{
|
||||||
|
SettingPageMap pageMap;
|
||||||
|
|
||||||
|
foreach (Setting *setting, mSettings)
|
||||||
|
pageMap[setting->page()].append (setting);
|
||||||
|
|
||||||
|
return pageMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMSettings::Setting *CSMSettings::UserSettings::createSetting
|
||||||
|
(CSMSettings::SettingType typ, const QString &page, const QString &name)
|
||||||
|
{
|
||||||
|
//get list of all settings for the current setting name
|
||||||
|
if (findSetting (page, name))
|
||||||
|
{
|
||||||
|
qWarning() << "Duplicate declaration encountered: "
|
||||||
|
<< (name + '/' + page);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return settings;
|
Setting *setting = new Setting (typ, name, page);
|
||||||
|
|
||||||
|
|
||||||
|
//add declaration to the model
|
||||||
|
mSettings.append (setting);
|
||||||
|
|
||||||
|
return setting;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList CSMSettings::UserSettings::definitions (const QString &viewKey) const
|
||||||
|
{
|
||||||
|
if (mSettingDefinitions->contains (viewKey))
|
||||||
|
return mSettingDefinitions->value (viewKey).toStringList();
|
||||||
|
|
||||||
|
return QStringList();
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
#ifndef USERSETTINGS_HPP
|
#ifndef USERSETTINGS_HPP
|
||||||
#define USERSETTINGS_HPP
|
#define USERSETTINGS_HPP
|
||||||
|
|
||||||
#include <QTextStream>
|
#include <QList>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
|
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
#include "support.hpp"
|
#include "support.hpp"
|
||||||
|
|
||||||
#ifndef Q_MOC_RUN
|
#ifndef Q_MOC_RUN
|
||||||
@ -18,77 +17,79 @@ namespace Files { typedef std::vector<boost::filesystem::path> PathContainer;
|
|||||||
struct ConfigurationManager;}
|
struct ConfigurationManager;}
|
||||||
|
|
||||||
class QFile;
|
class QFile;
|
||||||
|
class QSettings;
|
||||||
|
|
||||||
namespace CSMSettings {
|
namespace CSMSettings {
|
||||||
|
|
||||||
struct UserSettings: public QObject
|
class Setting;
|
||||||
|
typedef QMap <QString, QList <Setting *> > SettingPageMap;
|
||||||
|
|
||||||
|
class UserSettings: public QObject
|
||||||
{
|
{
|
||||||
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
SectionMap mSectionSettings;
|
|
||||||
SectionMap mEditorSettingDefaults;
|
|
||||||
|
|
||||||
static UserSettings *mUserSettingsInstance;
|
static UserSettings *mUserSettingsInstance;
|
||||||
QString mUserFilePath;
|
const Files::ConfigurationManager& mCfgMgr;
|
||||||
Files::ConfigurationManager mCfgMgr;
|
|
||||||
QString mReadOnlyMessage;
|
QSettings *mSettingDefinitions;
|
||||||
QString mReadWriteMessage;
|
QList <Setting *> mSettings;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// Singleton implementation
|
/// Singleton implementation
|
||||||
static UserSettings& instance();
|
static UserSettings& instance();
|
||||||
|
|
||||||
UserSettings();
|
UserSettings (const Files::ConfigurationManager& configurationManager);
|
||||||
~UserSettings();
|
~UserSettings();
|
||||||
|
|
||||||
UserSettings (UserSettings const &); //not implemented
|
UserSettings (UserSettings const &); //not implemented
|
||||||
void operator= (UserSettings const &); //not implemented
|
UserSettings& operator= (UserSettings const &); //not implemented
|
||||||
|
|
||||||
/// Writes settings to the last loaded settings file
|
|
||||||
bool writeSettings(QMap<QString, SettingList *> §ions);
|
|
||||||
|
|
||||||
/// Called from editor to trigger signal to update the specified setting.
|
|
||||||
/// If no setting name is specified, all settings found in the specified section are updated.
|
|
||||||
void updateSettings (const QString §ionName, const QString &settingName = "");
|
|
||||||
|
|
||||||
/// Retrieves the settings file at all three levels (global, local and user).
|
/// Retrieves the settings file at all three levels (global, local and user).
|
||||||
|
|
||||||
/// \todo Multi-valued settings are not fully implemented. Setting values
|
|
||||||
/// \todo loaded in later files will always overwrite previously loaded values.
|
|
||||||
void loadSettings (const QString &fileName);
|
void loadSettings (const QString &fileName);
|
||||||
|
|
||||||
/// Returns the entire map of settings across all sections
|
/// Updates QSettings and syncs with the ini file
|
||||||
const SectionMap &getSectionMap () const;
|
void setDefinitions (const QString &key, const QStringList &defs);
|
||||||
|
|
||||||
const SettingMap *getSettings (const QString §ionName) const;
|
QString settingValue (const QString &settingKey);
|
||||||
|
|
||||||
/// Retrieves the value as a QString of the specified setting in the specified section
|
///retrieve a setting object from a given page and setting name
|
||||||
QString getSetting(const QString §ion, const QString &setting) const;
|
Setting *findSetting
|
||||||
|
(const QString &pageName, const QString &settingName = QString());
|
||||||
|
|
||||||
|
///remove a setting from the list
|
||||||
|
void removeSetting
|
||||||
|
(const QString &pageName, const QString &settingName);
|
||||||
|
|
||||||
|
///Retreive a map of the settings, keyed by page name
|
||||||
|
SettingPageMap settingPageMap() const;
|
||||||
|
|
||||||
|
///Returns a string list of defined vlaues for the specified setting
|
||||||
|
///in "page/name" format.
|
||||||
|
QStringList definitions (const QString &viewKey) const;
|
||||||
|
|
||||||
|
///Test to indicate whether or not a setting has any definitions
|
||||||
|
bool hasSettingDefinitions (const QString &viewKey) const;
|
||||||
|
|
||||||
|
///Save any unsaved changes in the QSettings object
|
||||||
|
void saveDefinitions() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
void buildSettingModelDefaults();
|
||||||
|
|
||||||
/// Opens a QTextStream from the provided path as read-only or read-write.
|
///add a new setting to the model and return it
|
||||||
QTextStream *openFileStream (const QString &filePath, bool isReadOnly = false) const;
|
Setting *createSetting (CSMSettings::SettingType typ,
|
||||||
|
const QString &page, const QString &name);
|
||||||
/// Parses a setting file specified in filePath from the provided text stream.
|
|
||||||
bool loadFromFile (const QString &filePath = "");
|
|
||||||
|
|
||||||
/// merge the passed map into mSectionSettings
|
|
||||||
void mergeMap (const SectionMap &);
|
|
||||||
|
|
||||||
void displayFileErrorMessage(const QString &message, bool isReadOnly);
|
|
||||||
|
|
||||||
void buildEditorSettingDefaults();
|
|
||||||
|
|
||||||
SettingMap *getValidSettings (const QString §ionName) const;
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void signalUpdateEditorSetting (const QString &settingName, const QString &settingValue);
|
void userSettingUpdated (const QString &, const QStringList &);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
void updateUserSetting (const QString &, const QStringList &);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif // USERSETTINGS_HPP
|
#endif // USERSETTINGS_HPP
|
||||||
|
@ -17,7 +17,7 @@ int CSMTools::BirthsignCheckStage::setup()
|
|||||||
return mBirthsigns.getSize();
|
return mBirthsigns.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::BirthsignCheckStage::perform (int stage, std::vector<std::string>& messages)
|
void CSMTools::BirthsignCheckStage::perform (int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<ESM::BirthSign>& record = mBirthsigns.getRecord (stage);
|
const CSMWorld::Record<ESM::BirthSign>& record = mBirthsigns.getRecord (stage);
|
||||||
|
|
||||||
@ -30,13 +30,13 @@ void CSMTools::BirthsignCheckStage::perform (int stage, std::vector<std::string>
|
|||||||
|
|
||||||
// test for empty name, description and texture
|
// test for empty name, description and texture
|
||||||
if (birthsign.mName.empty())
|
if (birthsign.mName.empty())
|
||||||
messages.push_back (id.toString() + "|" + birthsign.mId + " has an empty name");
|
messages.push_back (std::make_pair (id, birthsign.mId + " has an empty name"));
|
||||||
|
|
||||||
if (birthsign.mDescription.empty())
|
if (birthsign.mDescription.empty())
|
||||||
messages.push_back (id.toString() + "|" + birthsign.mId + " has an empty description");
|
messages.push_back (std::make_pair (id, birthsign.mId + " has an empty description"));
|
||||||
|
|
||||||
if (birthsign.mTexture.empty())
|
if (birthsign.mTexture.empty())
|
||||||
messages.push_back (id.toString() + "|" + birthsign.mId + " is missing a texture");
|
messages.push_back (std::make_pair (id, birthsign.mId + " is missing a texture"));
|
||||||
|
|
||||||
/// \todo test if the texture exists
|
/// \todo test if the texture exists
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ namespace CSMTools
|
|||||||
virtual int setup();
|
virtual int setup();
|
||||||
///< \return number of steps
|
///< \return number of steps
|
||||||
|
|
||||||
virtual void perform (int stage, std::vector<std::string>& messages);
|
virtual void perform (int stage, Messages& messages);
|
||||||
///< Messages resulting from this tage will be appended to \a messages.
|
///< Messages resulting from this tage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ int CSMTools::ClassCheckStage::setup()
|
|||||||
return mClasses.getSize();
|
return mClasses.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ClassCheckStage::perform (int stage, std::vector<std::string>& messages)
|
void CSMTools::ClassCheckStage::perform (int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<ESM::Class>& record = mClasses.getRecord (stage);
|
const CSMWorld::Record<ESM::Class>& record = mClasses.getRecord (stage);
|
||||||
|
|
||||||
@ -31,10 +31,10 @@ void CSMTools::ClassCheckStage::perform (int stage, std::vector<std::string>& me
|
|||||||
|
|
||||||
// test for empty name and description
|
// test for empty name and description
|
||||||
if (class_.mName.empty())
|
if (class_.mName.empty())
|
||||||
messages.push_back (id.toString() + "|" + class_.mId + " has an empty name");
|
messages.push_back (std::make_pair (id, class_.mId + " has an empty name"));
|
||||||
|
|
||||||
if (class_.mDescription.empty())
|
if (class_.mDescription.empty())
|
||||||
messages.push_back (id.toString() + "|" + class_.mId + " has an empty description");
|
messages.push_back (std::make_pair (id, class_.mId + " has an empty description"));
|
||||||
|
|
||||||
// test for invalid attributes
|
// test for invalid attributes
|
||||||
for (int i=0; i<2; ++i)
|
for (int i=0; i<2; ++i)
|
||||||
@ -42,18 +42,14 @@ void CSMTools::ClassCheckStage::perform (int stage, std::vector<std::string>& me
|
|||||||
{
|
{
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
|
|
||||||
stream << id.toString() << "|Attribute #" << i << " of " << class_.mId << " is not set";
|
stream << "Attribute #" << i << " of " << class_.mId << " is not set";
|
||||||
|
|
||||||
messages.push_back (stream.str());
|
messages.push_back (std::make_pair (id, stream.str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (class_.mData.mAttribute[0]==class_.mData.mAttribute[1] && class_.mData.mAttribute[0]!=-1)
|
if (class_.mData.mAttribute[0]==class_.mData.mAttribute[1] && class_.mData.mAttribute[0]!=-1)
|
||||||
{
|
{
|
||||||
std::ostringstream stream;
|
messages.push_back (std::make_pair (id, "Class lists same attribute twice"));
|
||||||
|
|
||||||
stream << id.toString() << "|Class lists same attribute twice";
|
|
||||||
|
|
||||||
messages.push_back (stream.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// test for non-unique skill
|
// test for non-unique skill
|
||||||
@ -66,12 +62,7 @@ void CSMTools::ClassCheckStage::perform (int stage, std::vector<std::string>& me
|
|||||||
for (std::map<int, int>::const_iterator iter (skills.begin()); iter!=skills.end(); ++iter)
|
for (std::map<int, int>::const_iterator iter (skills.begin()); iter!=skills.end(); ++iter)
|
||||||
if (iter->second>1)
|
if (iter->second>1)
|
||||||
{
|
{
|
||||||
std::ostringstream stream;
|
messages.push_back (std::make_pair (id,
|
||||||
|
ESM::Skill::indexToId (iter->first) + " is listed more than once"));
|
||||||
stream
|
|
||||||
<< id.toString() << "|"
|
|
||||||
<< ESM::Skill::indexToId (iter->first) << " is listed more than once";
|
|
||||||
|
|
||||||
messages.push_back (stream.str());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -21,7 +21,7 @@ namespace CSMTools
|
|||||||
virtual int setup();
|
virtual int setup();
|
||||||
///< \return number of steps
|
///< \return number of steps
|
||||||
|
|
||||||
virtual void perform (int stage, std::vector<std::string>& messages);
|
virtual void perform (int stage, Messages& messages);
|
||||||
///< Messages resulting from this tage will be appended to \a messages.
|
///< Messages resulting from this tage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ int CSMTools::FactionCheckStage::setup()
|
|||||||
return mFactions.getSize();
|
return mFactions.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::FactionCheckStage::perform (int stage, std::vector<std::string>& messages)
|
void CSMTools::FactionCheckStage::perform (int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<ESM::Faction>& record = mFactions.getRecord (stage);
|
const CSMWorld::Record<ESM::Faction>& record = mFactions.getRecord (stage);
|
||||||
|
|
||||||
@ -31,16 +31,12 @@ void CSMTools::FactionCheckStage::perform (int stage, std::vector<std::string>&
|
|||||||
|
|
||||||
// test for empty name
|
// test for empty name
|
||||||
if (faction.mName.empty())
|
if (faction.mName.empty())
|
||||||
messages.push_back (id.toString() + "|" + faction.mId + " has an empty name");
|
messages.push_back (std::make_pair (id, faction.mId + " has an empty name"));
|
||||||
|
|
||||||
// test for invalid attributes
|
// test for invalid attributes
|
||||||
if (faction.mData.mAttribute[0]==faction.mData.mAttribute[1] && faction.mData.mAttribute[0]!=-1)
|
if (faction.mData.mAttribute[0]==faction.mData.mAttribute[1] && faction.mData.mAttribute[0]!=-1)
|
||||||
{
|
{
|
||||||
std::ostringstream stream;
|
messages.push_back (std::make_pair (id , "Faction lists same attribute twice"));
|
||||||
|
|
||||||
stream << id.toString() << "|Faction lists same attribute twice";
|
|
||||||
|
|
||||||
messages.push_back (stream.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// test for non-unique skill
|
// test for non-unique skill
|
||||||
@ -53,13 +49,8 @@ void CSMTools::FactionCheckStage::perform (int stage, std::vector<std::string>&
|
|||||||
for (std::map<int, int>::const_iterator iter (skills.begin()); iter!=skills.end(); ++iter)
|
for (std::map<int, int>::const_iterator iter (skills.begin()); iter!=skills.end(); ++iter)
|
||||||
if (iter->second>1)
|
if (iter->second>1)
|
||||||
{
|
{
|
||||||
std::ostringstream stream;
|
messages.push_back (std::make_pair (id,
|
||||||
|
ESM::Skill::indexToId (iter->first) + " is listed more than once"));
|
||||||
stream
|
|
||||||
<< id.toString() << "|"
|
|
||||||
<< ESM::Skill::indexToId (iter->first) << " is listed more than once";
|
|
||||||
|
|
||||||
messages.push_back (stream.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \todo check data members that can't be edited in the table view
|
/// \todo check data members that can't be edited in the table view
|
||||||
|
@ -21,7 +21,7 @@ namespace CSMTools
|
|||||||
virtual int setup();
|
virtual int setup();
|
||||||
///< \return number of steps
|
///< \return number of steps
|
||||||
|
|
||||||
virtual void perform (int stage, std::vector<std::string>& messages);
|
virtual void perform (int stage, Messages& messages);
|
||||||
///< Messages resulting from this tage will be appended to \a messages.
|
///< Messages resulting from this tage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -15,9 +15,10 @@ int CSMTools::MandatoryIdStage::setup()
|
|||||||
return mIds.size();
|
return mIds.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::MandatoryIdStage::perform (int stage, std::vector<std::string>& messages)
|
void CSMTools::MandatoryIdStage::perform (int stage, 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.push_back (mCollectionId.toString() + "|Missing mandatory record: " + mIds.at (stage));
|
messages.push_back (std::make_pair (mCollectionId,
|
||||||
|
"Missing mandatory record: " + mIds.at (stage)));
|
||||||
}
|
}
|
@ -30,7 +30,7 @@ namespace CSMTools
|
|||||||
virtual int setup();
|
virtual int setup();
|
||||||
///< \return number of steps
|
///< \return number of steps
|
||||||
|
|
||||||
virtual void perform (int stage, std::vector<std::string>& messages);
|
virtual void perform (int stage, Messages& messages);
|
||||||
///< Messages resulting from this tage will be appended to \a messages.
|
///< Messages resulting from this tage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
#include "../world/universalid.hpp"
|
#include "../world/universalid.hpp"
|
||||||
|
|
||||||
void CSMTools::RaceCheckStage::performPerRecord (int stage, std::vector<std::string>& messages)
|
void CSMTools::RaceCheckStage::performPerRecord (int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<ESM::Race>& record = mRaces.getRecord (stage);
|
const CSMWorld::Record<ESM::Race>& record = mRaces.getRecord (stage);
|
||||||
|
|
||||||
@ -20,24 +20,24 @@ void CSMTools::RaceCheckStage::performPerRecord (int stage, std::vector<std::str
|
|||||||
|
|
||||||
// test for empty name and description
|
// test for empty name and description
|
||||||
if (race.mName.empty())
|
if (race.mName.empty())
|
||||||
messages.push_back (id.toString() + "|" + race.mId + " has an empty name");
|
messages.push_back (std::make_pair (id, race.mId + " has an empty name"));
|
||||||
|
|
||||||
if (race.mDescription.empty())
|
if (race.mDescription.empty())
|
||||||
messages.push_back (id.toString() + "|" + race.mId + " has an empty description");
|
messages.push_back (std::make_pair (id, race.mId + " has an empty description"));
|
||||||
|
|
||||||
// test for positive height
|
// test for positive height
|
||||||
if (race.mData.mHeight.mMale<=0)
|
if (race.mData.mHeight.mMale<=0)
|
||||||
messages.push_back (id.toString() + "|male " + race.mId + " has non-positive height");
|
messages.push_back (std::make_pair (id, "male " + race.mId + " has non-positive height"));
|
||||||
|
|
||||||
if (race.mData.mHeight.mFemale<=0)
|
if (race.mData.mHeight.mFemale<=0)
|
||||||
messages.push_back (id.toString() + "|female " + race.mId + " has non-positive height");
|
messages.push_back (std::make_pair (id, "female " + race.mId + " has non-positive height"));
|
||||||
|
|
||||||
// test for non-negative weight
|
// test for non-negative weight
|
||||||
if (race.mData.mWeight.mMale<0)
|
if (race.mData.mWeight.mMale<0)
|
||||||
messages.push_back (id.toString() + "|male " + race.mId + " has negative weight");
|
messages.push_back (std::make_pair (id, "male " + race.mId + " has negative weight"));
|
||||||
|
|
||||||
if (race.mData.mWeight.mFemale<0)
|
if (race.mData.mWeight.mFemale<0)
|
||||||
messages.push_back (id.toString() + "|female " + race.mId + " has negative weight");
|
messages.push_back (std::make_pair (id, "female " + race.mId + " has negative weight"));
|
||||||
|
|
||||||
// remember playable flag
|
// remember playable flag
|
||||||
if (race.mData.mFlags & 0x1)
|
if (race.mData.mFlags & 0x1)
|
||||||
@ -46,12 +46,12 @@ void CSMTools::RaceCheckStage::performPerRecord (int stage, std::vector<std::str
|
|||||||
/// \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
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::RaceCheckStage::performFinal (std::vector<std::string>& messages)
|
void CSMTools::RaceCheckStage::performFinal (Messages& messages)
|
||||||
{
|
{
|
||||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Races);
|
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Races);
|
||||||
|
|
||||||
if (!mPlayable)
|
if (!mPlayable)
|
||||||
messages.push_back (id.toString() + "|No playable race");
|
messages.push_back (std::make_pair (id, "No playable race"));
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMTools::RaceCheckStage::RaceCheckStage (const CSMWorld::IdCollection<ESM::Race>& races)
|
CSMTools::RaceCheckStage::RaceCheckStage (const CSMWorld::IdCollection<ESM::Race>& races)
|
||||||
@ -64,7 +64,7 @@ int CSMTools::RaceCheckStage::setup()
|
|||||||
return mRaces.getSize()+1;
|
return mRaces.getSize()+1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::RaceCheckStage::perform (int stage, std::vector<std::string>& messages)
|
void CSMTools::RaceCheckStage::perform (int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
if (stage==mRaces.getSize())
|
if (stage==mRaces.getSize())
|
||||||
performFinal (messages);
|
performFinal (messages);
|
||||||
|
@ -15,9 +15,9 @@ namespace CSMTools
|
|||||||
const CSMWorld::IdCollection<ESM::Race>& mRaces;
|
const CSMWorld::IdCollection<ESM::Race>& mRaces;
|
||||||
bool mPlayable;
|
bool mPlayable;
|
||||||
|
|
||||||
void performPerRecord (int stage, std::vector<std::string>& messages);
|
void performPerRecord (int stage, Messages& messages);
|
||||||
|
|
||||||
void performFinal (std::vector<std::string>& messages);
|
void performFinal (Messages& messages);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ namespace CSMTools
|
|||||||
virtual int setup();
|
virtual int setup();
|
||||||
///< \return number of steps
|
///< \return number of steps
|
||||||
|
|
||||||
virtual void perform (int stage, std::vector<std::string>& messages);
|
virtual void perform (int stage, Messages& messages);
|
||||||
///< Messages resulting from this tage will be appended to \a messages.
|
///< Messages resulting from this tage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
#include "referenceablecheck.hpp"
|
#include "referenceablecheck.hpp"
|
||||||
|
|
||||||
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
#include "../world/record.hpp"
|
#include "../world/record.hpp"
|
||||||
#include "../world/universalid.hpp"
|
#include "../world/universalid.hpp"
|
||||||
#include <components/misc/stringops.hpp>
|
|
||||||
|
|
||||||
CSMTools::ReferenceableCheckStage::ReferenceableCheckStage(
|
CSMTools::ReferenceableCheckStage::ReferenceableCheckStage(
|
||||||
const CSMWorld::RefIdData& referenceable, const CSMWorld::IdCollection<ESM::Race >& races,
|
const CSMWorld::RefIdData& referenceable, const CSMWorld::IdCollection<ESM::Race >& races,
|
||||||
@ -16,7 +18,7 @@ CSMTools::ReferenceableCheckStage::ReferenceableCheckStage(
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ReferenceableCheckStage::perform(int stage, std::vector< std::string >& messages)
|
void CSMTools::ReferenceableCheckStage::perform (int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
//Checks for books, than, when stage is above mBooksSize goes to other checks, with (stage - PrevSum) as stage.
|
//Checks for books, than, when stage is above mBooksSize goes to other checks, with (stage - PrevSum) as stage.
|
||||||
const int bookSize(mReferencables.getBooks().getSize());
|
const int bookSize(mReferencables.getBooks().getSize());
|
||||||
@ -206,11 +208,11 @@ void CSMTools::ReferenceableCheckStage::perform(int stage, std::vector< std::str
|
|||||||
staticCheck(stage, mReferencables.getStatics(), messages);
|
staticCheck(stage, mReferencables.getStatics(), messages);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
stage -= staticSize;
|
stage -= staticSize;
|
||||||
|
|
||||||
const int creatureSize(mReferencables.getCreatures().getSize());
|
const int creatureSize(mReferencables.getCreatures().getSize());
|
||||||
|
|
||||||
if (stage < creatureSize)
|
if (stage < creatureSize)
|
||||||
{
|
{
|
||||||
creatureCheck(stage, mReferencables.getCreatures(), messages);
|
creatureCheck(stage, mReferencables.getCreatures(), messages);
|
||||||
@ -230,7 +232,7 @@ int CSMTools::ReferenceableCheckStage::setup()
|
|||||||
void CSMTools::ReferenceableCheckStage::bookCheck(
|
void CSMTools::ReferenceableCheckStage::bookCheck(
|
||||||
int stage,
|
int stage,
|
||||||
const CSMWorld::RefIdDataContainer< ESM::Book >& records,
|
const CSMWorld::RefIdDataContainer< ESM::Book >& records,
|
||||||
std::vector< std::string >& messages)
|
Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
@ -248,7 +250,7 @@ void CSMTools::ReferenceableCheckStage::bookCheck(
|
|||||||
void CSMTools::ReferenceableCheckStage::activatorCheck(
|
void CSMTools::ReferenceableCheckStage::activatorCheck(
|
||||||
int stage,
|
int stage,
|
||||||
const CSMWorld::RefIdDataContainer< ESM::Activator >& records,
|
const CSMWorld::RefIdDataContainer< ESM::Activator >& records,
|
||||||
std::vector< std::string >& messages)
|
Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
@ -262,15 +264,13 @@ void CSMTools::ReferenceableCheckStage::activatorCheck(
|
|||||||
|
|
||||||
//Checking for model, IIRC all activators should have a model
|
//Checking for model, IIRC all activators should have a model
|
||||||
if (activator.mModel.empty())
|
if (activator.mModel.empty())
|
||||||
{
|
messages.push_back (std::make_pair (id, activator.mId + " has no model"));
|
||||||
messages.push_back(id.toString() + "|" + activator.mId + " has no model");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ReferenceableCheckStage::potionCheck(
|
void CSMTools::ReferenceableCheckStage::potionCheck(
|
||||||
int stage,
|
int stage,
|
||||||
const CSMWorld::RefIdDataContainer< ESM::Potion >& records,
|
const CSMWorld::RefIdDataContainer< ESM::Potion >& records,
|
||||||
std::vector< std::string >& messages)
|
Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
@ -290,7 +290,7 @@ void CSMTools::ReferenceableCheckStage::potionCheck(
|
|||||||
void CSMTools::ReferenceableCheckStage::apparatusCheck(
|
void CSMTools::ReferenceableCheckStage::apparatusCheck(
|
||||||
int stage,
|
int stage,
|
||||||
const CSMWorld::RefIdDataContainer< ESM::Apparatus >& records,
|
const CSMWorld::RefIdDataContainer< ESM::Apparatus >& records,
|
||||||
std::vector< std::string >& messages)
|
Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
@ -310,7 +310,7 @@ void CSMTools::ReferenceableCheckStage::apparatusCheck(
|
|||||||
void CSMTools::ReferenceableCheckStage::armorCheck(
|
void CSMTools::ReferenceableCheckStage::armorCheck(
|
||||||
int stage,
|
int stage,
|
||||||
const CSMWorld::RefIdDataContainer< ESM::Armor >& records,
|
const CSMWorld::RefIdDataContainer< ESM::Armor >& records,
|
||||||
std::vector< std::string >& messages)
|
Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
@ -326,21 +326,17 @@ void CSMTools::ReferenceableCheckStage::armorCheck(
|
|||||||
|
|
||||||
//checking for armor class, armor should have poistive armor class, but 0 is considered legal
|
//checking for armor class, armor should have poistive armor class, but 0 is considered legal
|
||||||
if (armor.mData.mArmor < 0)
|
if (armor.mData.mArmor < 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, armor.mId + " has negative armor class"));
|
||||||
messages.push_back(id.toString() + "|" + armor.mId + " has negative armor class");
|
|
||||||
}
|
|
||||||
|
|
||||||
//checking for health. Only positive numbers are allowed, or 0 is illegal
|
//checking for health. Only positive numbers are allowed, or 0 is illegal
|
||||||
if (armor.mData.mHealth <= 0)
|
if (armor.mData.mHealth <= 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, armor.mId + " has non positive health"));
|
||||||
messages.push_back(id.toString() + "|" + armor.mId + " has non positive health");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ReferenceableCheckStage::clothingCheck(
|
void CSMTools::ReferenceableCheckStage::clothingCheck(
|
||||||
int stage,
|
int stage,
|
||||||
const CSMWorld::RefIdDataContainer< ESM::Clothing >& records,
|
const CSMWorld::RefIdDataContainer< ESM::Clothing >& records,
|
||||||
std::vector< std::string >& messages)
|
Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
@ -357,7 +353,7 @@ void CSMTools::ReferenceableCheckStage::clothingCheck(
|
|||||||
void CSMTools::ReferenceableCheckStage::containerCheck(
|
void CSMTools::ReferenceableCheckStage::containerCheck(
|
||||||
int stage,
|
int stage,
|
||||||
const CSMWorld::RefIdDataContainer< ESM::Container >& records,
|
const CSMWorld::RefIdDataContainer< ESM::Container >& records,
|
||||||
std::vector< std::string >& messages)
|
Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
@ -371,153 +367,109 @@ void CSMTools::ReferenceableCheckStage::containerCheck(
|
|||||||
|
|
||||||
//Checking for model, IIRC all containers should have a model
|
//Checking for model, IIRC all containers should have a model
|
||||||
if (container.mModel.empty())
|
if (container.mModel.empty())
|
||||||
{
|
messages.push_back (std::make_pair (id, container.mId + " has no model"));
|
||||||
messages.push_back(id.toString() + "|" + container.mId + " has no model");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Checking for capacity (weight)
|
//Checking for capacity (weight)
|
||||||
if (container.mWeight < 0) //0 is allowed
|
if (container.mWeight < 0) //0 is allowed
|
||||||
{
|
messages.push_back (std::make_pair (id,
|
||||||
messages.push_back(id.toString() + "|" + container.mId + " has negative weight (capacity)");
|
container.mId + " has negative weight (capacity)"));
|
||||||
}
|
|
||||||
|
|
||||||
//checking for name
|
//checking for name
|
||||||
if (container.mName.empty())
|
if (container.mName.empty())
|
||||||
{
|
messages.push_back (std::make_pair (id, container.mId + " has an empty name"));
|
||||||
messages.push_back(id.toString() + "|" + container.mId + " has an empty name");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ReferenceableCheckStage::creatureCheck(
|
void CSMTools::ReferenceableCheckStage::creatureCheck (
|
||||||
int stage,
|
int stage, const CSMWorld::RefIdDataContainer< ESM::Creature >& records,
|
||||||
const CSMWorld::RefIdDataContainer< ESM::Creature >& records,
|
Messages& messages)
|
||||||
std::vector< std::string >& messages)
|
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
if (baseRecord.isDeleted())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
const ESM::Creature& creature = (dynamic_cast<const CSMWorld::Record<ESM::Creature>&>(baseRecord)).get();
|
const ESM::Creature& creature = (dynamic_cast<const CSMWorld::Record<ESM::Creature>&>(baseRecord)).get();
|
||||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Creature, creature.mId);
|
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Creature, creature.mId);
|
||||||
|
|
||||||
if (creature.mModel.empty())
|
if (creature.mModel.empty())
|
||||||
{
|
messages.push_back (std::make_pair (id, creature.mId + " has no model"));
|
||||||
messages.push_back(id.toString() + "|" + creature.mId + " has no model");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (creature.mName.empty())
|
if (creature.mName.empty())
|
||||||
{
|
messages.push_back (std::make_pair (id, creature.mId + " has an empty name"));
|
||||||
messages.push_back(id.toString() + "|" + creature.mId + " has an empty name");
|
|
||||||
}
|
|
||||||
|
|
||||||
//stats checks
|
//stats checks
|
||||||
if (creature.mData.mLevel < 1)
|
if (creature.mData.mLevel < 1)
|
||||||
{
|
messages.push_back (std::make_pair (id, creature.mId + " has non-postive level"));
|
||||||
messages.push_back(id.toString() + "|" + creature.mId + " has non-postive level");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (creature.mData.mStrength < 0)
|
if (creature.mData.mStrength < 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, creature.mId + " has negative strength"));
|
||||||
messages.push_back(id.toString() + "|" + creature.mId + " has negative strength");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (creature.mData.mIntelligence < 0)
|
if (creature.mData.mIntelligence < 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, creature.mId + " has negative intelligence"));
|
||||||
messages.push_back(id.toString() + "|" + creature.mId + " has negative intelligence");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (creature.mData.mWillpower < 0)
|
if (creature.mData.mWillpower < 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, creature.mId + " has negative willpower"));
|
||||||
messages.push_back(id.toString() + "|" + creature.mId + " has negative willpower");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (creature.mData.mAgility < 0)
|
if (creature.mData.mAgility < 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, creature.mId + " has negative agility"));
|
||||||
messages.push_back(id.toString() + "|" + creature.mId + " has negative agility");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (creature.mData.mSpeed < 0)
|
if (creature.mData.mSpeed < 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, creature.mId + " has negative speed"));
|
||||||
messages.push_back(id.toString() + "|" + creature.mId + " has negative speed");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (creature.mData.mEndurance < 0)
|
if (creature.mData.mEndurance < 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, creature.mId + " has negative endurance"));
|
||||||
messages.push_back(id.toString() + "|" + creature.mId + " has negative endurance");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (creature.mData.mPersonality < 0)
|
if (creature.mData.mPersonality < 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, creature.mId + " has negative personality"));
|
||||||
messages.push_back(id.toString() + "|" + creature.mId + " has negative personality");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (creature.mData.mLuck < 0)
|
if (creature.mData.mLuck < 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, creature.mId + " has negative luck"));
|
||||||
messages.push_back(id.toString() + "|" + creature.mId + " has negative luck");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (creature.mData.mHealth < 0)
|
if (creature.mData.mHealth < 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, creature.mId + " has negative health"));
|
||||||
messages.push_back(id.toString() + "|" + creature.mId + " has negative health");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (creature.mData.mSoul < 0)
|
if (creature.mData.mSoul < 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, creature.mId + " has negative soul value"));
|
||||||
messages.push_back(id.toString() + "|" + creature.mId + " has negative soul value");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 6; ++i)
|
for (int i = 0; i < 6; ++i)
|
||||||
{
|
{
|
||||||
if (creature.mData.mAttack[i] < 0)
|
if (creature.mData.mAttack[i] < 0)
|
||||||
{
|
{
|
||||||
messages.push_back(id.toString() + "|" + creature.mId + " has negative attack strength");
|
messages.push_back (std::make_pair (id,
|
||||||
|
creature.mId + " has negative attack strength"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO, find meaning of other values
|
//TODO, find meaning of other values
|
||||||
if (creature.mData.mGold < 0) //It seems that this is for gold in merchant creatures
|
if (creature.mData.mGold < 0) //It seems that this is for gold in merchant creatures
|
||||||
{
|
messages.push_back (std::make_pair (id, creature.mId + " has negative gold "));
|
||||||
messages.push_back(id.toString() + "|" + creature.mId + " has negative gold ");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ReferenceableCheckStage::doorCheck(
|
void CSMTools::ReferenceableCheckStage::doorCheck(
|
||||||
int stage,
|
int stage, const CSMWorld::RefIdDataContainer< ESM::Door >& records,
|
||||||
const CSMWorld::RefIdDataContainer< ESM::Door >& records,
|
Messages& messages)
|
||||||
std::vector< std::string >& messages)
|
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
if (baseRecord.isDeleted())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
const ESM::Door& Door = (dynamic_cast<const CSMWorld::Record<ESM::Door>&>(baseRecord)).get();
|
const ESM::Door& Door = (dynamic_cast<const CSMWorld::Record<ESM::Door>&>(baseRecord)).get();
|
||||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Door, Door.mId);
|
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Door, Door.mId);
|
||||||
|
|
||||||
//usual, name or model
|
//usual, name or model
|
||||||
if (Door.mName.empty())
|
if (Door.mName.empty())
|
||||||
{
|
messages.push_back (std::make_pair (id, Door.mId + " has an empty name"));
|
||||||
messages.push_back(id.toString() + "|" + Door.mId + " has an empty name");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Door.mModel.empty())
|
if (Door.mModel.empty())
|
||||||
{
|
messages.push_back (std::make_pair (id, Door.mId + " has no model"));
|
||||||
messages.push_back(id.toString() + "|" + Door.mId + " has no model");
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO, check what static unsigned int sRecordId; is for
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ReferenceableCheckStage::ingredientCheck(
|
void CSMTools::ReferenceableCheckStage::ingredientCheck(
|
||||||
int stage,
|
int stage,
|
||||||
const CSMWorld::RefIdDataContainer< ESM::Ingredient >& records,
|
const CSMWorld::RefIdDataContainer< ESM::Ingredient >& records,
|
||||||
std::vector< std::string >& messages)
|
Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
@ -535,7 +487,7 @@ void CSMTools::ReferenceableCheckStage::ingredientCheck(
|
|||||||
void CSMTools::ReferenceableCheckStage::creaturesLevListCheck(
|
void CSMTools::ReferenceableCheckStage::creaturesLevListCheck(
|
||||||
int stage,
|
int stage,
|
||||||
const CSMWorld::RefIdDataContainer< ESM::CreatureLevList >& records,
|
const CSMWorld::RefIdDataContainer< ESM::CreatureLevList >& records,
|
||||||
std::vector< std::string >& messages)
|
Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
@ -553,7 +505,7 @@ void CSMTools::ReferenceableCheckStage::creaturesLevListCheck(
|
|||||||
void CSMTools::ReferenceableCheckStage::itemLevelledListCheck(
|
void CSMTools::ReferenceableCheckStage::itemLevelledListCheck(
|
||||||
int stage,
|
int stage,
|
||||||
const CSMWorld::RefIdDataContainer< ESM::ItemLevList >& records,
|
const CSMWorld::RefIdDataContainer< ESM::ItemLevList >& records,
|
||||||
std::vector< std::string >& messages)
|
Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
@ -569,40 +521,33 @@ void CSMTools::ReferenceableCheckStage::itemLevelledListCheck(
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ReferenceableCheckStage::lightCheck(
|
void CSMTools::ReferenceableCheckStage::lightCheck(
|
||||||
int stage,
|
int stage, const CSMWorld::RefIdDataContainer< ESM::Light >& records,
|
||||||
const CSMWorld::RefIdDataContainer< ESM::Light >& records,
|
Messages& messages)
|
||||||
std::vector< std::string >& messages)
|
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
if (baseRecord.isDeleted())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
const ESM::Light& light = (dynamic_cast<const CSMWorld::Record<ESM::Light>& >(baseRecord)).get();
|
const ESM::Light& light = (dynamic_cast<const CSMWorld::Record<ESM::Light>& >(baseRecord)).get();
|
||||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Light, light.mId);
|
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Light, light.mId);
|
||||||
|
|
||||||
if (light.mData.mRadius < 0)
|
if (light.mData.mRadius < 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, light.mId + " has negative light radius"));
|
||||||
messages.push_back(id.toString() + "|" + light.mId + " has negative light radius");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (light.mData.mFlags & ESM::Light::Carry)
|
if (light.mData.mFlags & ESM::Light::Carry)
|
||||||
{
|
{
|
||||||
inventoryItemCheck<ESM::Light>(light, messages, id.toString());
|
inventoryItemCheck<ESM::Light>(light, messages, id.toString());
|
||||||
|
|
||||||
if (light.mData.mTime == 0)
|
if (light.mData.mTime == 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, light.mId + " has zero duration"));
|
||||||
messages.push_back(id.toString() + "|" + light.mId + " has zero duration");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ReferenceableCheckStage::lockpickCheck(
|
void CSMTools::ReferenceableCheckStage::lockpickCheck(
|
||||||
int stage,
|
int stage,
|
||||||
const CSMWorld::RefIdDataContainer< ESM::Lockpick >& records,
|
const CSMWorld::RefIdDataContainer< ESM::Lockpick >& records,
|
||||||
std::vector< std::string >& messages)
|
Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
@ -622,7 +567,7 @@ void CSMTools::ReferenceableCheckStage::lockpickCheck(
|
|||||||
void CSMTools::ReferenceableCheckStage::miscCheck(
|
void CSMTools::ReferenceableCheckStage::miscCheck(
|
||||||
int stage,
|
int stage,
|
||||||
const CSMWorld::RefIdDataContainer< ESM::Miscellaneous >& records,
|
const CSMWorld::RefIdDataContainer< ESM::Miscellaneous >& records,
|
||||||
std::vector< std::string >& messages)
|
Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
@ -637,20 +582,17 @@ void CSMTools::ReferenceableCheckStage::miscCheck(
|
|||||||
inventoryItemCheck<ESM::Miscellaneous>(miscellaneous, messages, id.toString());
|
inventoryItemCheck<ESM::Miscellaneous>(miscellaneous, messages, id.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ReferenceableCheckStage::npcCheck(
|
void CSMTools::ReferenceableCheckStage::npcCheck (
|
||||||
int stage,
|
int stage, const CSMWorld::RefIdDataContainer< ESM::NPC >& records,
|
||||||
const CSMWorld::RefIdDataContainer< ESM::NPC >& records,
|
Messages& messages)
|
||||||
std::vector< std::string >& messages)
|
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
if (baseRecord.isDeleted())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
const ESM::NPC& npc = (dynamic_cast<const CSMWorld::Record<ESM::NPC>& >(baseRecord)).get();
|
const ESM::NPC& npc = (dynamic_cast<const CSMWorld::Record<ESM::NPC>& >(baseRecord)).get();
|
||||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Npc, npc.mId);
|
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Npc, npc.mId);
|
||||||
|
|
||||||
short level(npc.mNpdt52.mLevel);
|
short level(npc.mNpdt52.mLevel);
|
||||||
char disposition(npc.mNpdt52.mDisposition);
|
char disposition(npc.mNpdt52.mDisposition);
|
||||||
@ -661,15 +603,13 @@ void CSMTools::ReferenceableCheckStage::npcCheck(
|
|||||||
|
|
||||||
//Detect if player is present
|
//Detect if player is present
|
||||||
if (Misc::StringUtils::ciEqual(npc.mId, "player")) //Happy now, scrawl?
|
if (Misc::StringUtils::ciEqual(npc.mId, "player")) //Happy now, scrawl?
|
||||||
{
|
|
||||||
mPlayerPresent = true;
|
mPlayerPresent = true;
|
||||||
}
|
|
||||||
|
|
||||||
if (npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) //12 = autocalculated
|
if (npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) //12 = autocalculated
|
||||||
{
|
{
|
||||||
if ((npc.mFlags & ESM::NPC::Autocalc) == 0) //0x0008 = autocalculated flag
|
if ((npc.mFlags & ESM::NPC::Autocalc) == 0) //0x0008 = autocalculated flag
|
||||||
{
|
{
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " mNpdtType or flags mismatch!"); //should not happend?
|
messages.push_back (std::make_pair (id, npc.mId + " mNpdtType or flags mismatch!")); //should not happend?
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -681,146 +621,95 @@ void CSMTools::ReferenceableCheckStage::npcCheck(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (npc.mNpdt52.mMana < 0)
|
|
||||||
{
|
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " mana has negative value");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (npc.mNpdt52.mFatigue < 0)
|
|
||||||
{
|
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " fatigue has negative value");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (npc.mNpdt52.mAgility == 0)
|
if (npc.mNpdt52.mAgility == 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, npc.mId + " agility has zero value"));
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " agility has zero value");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (npc.mNpdt52.mEndurance == 0)
|
if (npc.mNpdt52.mEndurance == 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, npc.mId + " endurance has zero value"));
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " endurance has zero value");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (npc.mNpdt52.mIntelligence == 0)
|
if (npc.mNpdt52.mIntelligence == 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, npc.mId + " intelligence has zero value"));
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " intelligence has zero value");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (npc.mNpdt52.mLuck == 0)
|
if (npc.mNpdt52.mLuck == 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, npc.mId + " luck has zero value"));
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " luck has zero value");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (npc.mNpdt52.mPersonality == 0)
|
if (npc.mNpdt52.mPersonality == 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, npc.mId + " personality has zero value"));
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " personality has zero value");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (npc.mNpdt52.mStrength == 0)
|
if (npc.mNpdt52.mStrength == 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, npc.mId + " strength has zero value"));
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " strength has zero value");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (npc.mNpdt52.mSpeed == 0)
|
if (npc.mNpdt52.mSpeed == 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, npc.mId + " speed has zero value"));
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " speed has zero value");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (npc.mNpdt52.mWillpower == 0)
|
if (npc.mNpdt52.mWillpower == 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, npc.mId + " willpower has zero value"));
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " willpower has zero value");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (level < 1)
|
if (level < 1)
|
||||||
{
|
messages.push_back (std::make_pair (id, npc.mId + " level is non positive"));
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " level is non positive");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gold < 0)
|
if (gold < 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, npc.mId + " gold has negative value"));
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " gold has negative value");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (npc.mName.empty())
|
if (npc.mName.empty())
|
||||||
{
|
messages.push_back (std::make_pair (id, npc.mId + " has any empty name"));
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " has any empty name");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (npc.mClass.empty())
|
if (npc.mClass.empty())
|
||||||
{
|
{
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " has any empty class");
|
messages.push_back (std::make_pair (id, npc.mId + " has any empty class"));
|
||||||
}
|
}
|
||||||
else //checking if there is such class
|
else if (mClasses.searchId (npc.mClass) == -1)
|
||||||
{
|
{
|
||||||
if (mClasses.searchId(npc.mClass) == -1)
|
messages.push_back (std::make_pair (id, npc.mId + " has invalid class"));
|
||||||
{
|
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " has invalid class");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (npc.mRace.empty())
|
if (npc.mRace.empty())
|
||||||
{
|
{
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " has any empty race");
|
messages.push_back (std::make_pair (id, npc.mId + " has any empty race"));
|
||||||
}
|
}
|
||||||
else //checking if there is a such race
|
else if (mRaces.searchId (npc.mRace) == -1)
|
||||||
{
|
{
|
||||||
if (mRaces.searchId(npc.mRace) == -1)
|
messages.push_back (std::make_pair (id, npc.mId + " has invalid race"));
|
||||||
{
|
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " has invalid race");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (disposition < 0)
|
if (disposition < 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, npc.mId + " has negative disposition"));
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " has negative disposition");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (reputation < 0) //It seems that no character in Morrowind.esm have negative reputation. I'm assuming that negative reputation is invalid
|
if (reputation < 0) //It seems that no character in Morrowind.esm have negative reputation. I'm assuming that negative reputation is invalid
|
||||||
{
|
{
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " has negative reputation");
|
messages.push_back (std::make_pair (id, npc.mId + " has negative reputation"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (npc.mFaction.empty() == false)
|
if (!npc.mFaction.empty())
|
||||||
{
|
{
|
||||||
if (rank < 0)
|
if (rank < 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, npc.mId + " has negative rank"));
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " has negative rank");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mFactions.searchId(npc.mFaction) == -1)
|
if (mFactions.searchId(npc.mFaction) == -1)
|
||||||
{
|
messages.push_back (std::make_pair (id, npc.mId + " has invalid faction"));
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " has invalid faction");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (npc.mHead.empty())
|
if (npc.mHead.empty())
|
||||||
{
|
messages.push_back (std::make_pair (id, npc.mId + " has no head"));
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " has no head");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (npc.mHair.empty())
|
if (npc.mHair.empty())
|
||||||
{
|
messages.push_back (std::make_pair (id, npc.mId + " has no hair"));
|
||||||
messages.push_back(id.toString() + "|" + npc.mId + " has no hair");
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: reputation, Disposition, rank, everything else
|
//TODO: reputation, Disposition, rank, everything else
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ReferenceableCheckStage::weaponCheck(
|
void CSMTools::ReferenceableCheckStage::weaponCheck(
|
||||||
int stage,
|
int stage, const CSMWorld::RefIdDataContainer< ESM::Weapon >& records,
|
||||||
const CSMWorld::RefIdDataContainer< ESM::Weapon >& records,
|
Messages& messages)
|
||||||
std::vector< std::string >& messages)
|
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord (stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
if (baseRecord.isDeleted())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
const ESM::Weapon& weapon = (dynamic_cast<const CSMWorld::Record<ESM::Weapon>& >(baseRecord)).get();
|
const ESM::Weapon& weapon = (dynamic_cast<const CSMWorld::Record<ESM::Weapon>& >(baseRecord)).get();
|
||||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Weapon, weapon.mId);
|
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Weapon, weapon.mId);
|
||||||
|
|
||||||
//TODO, It seems that this stuff for spellcasting is obligatory and In fact We should check if records are present
|
//TODO, It seems that this stuff for spellcasting is obligatory and In fact We should check if records are present
|
||||||
if
|
if
|
||||||
@ -860,20 +749,17 @@ void CSMTools::ReferenceableCheckStage::weaponCheck(
|
|||||||
weapon.mData.mType == ESM::Weapon::Bolt))
|
weapon.mData.mType == ESM::Weapon::Bolt))
|
||||||
{
|
{
|
||||||
if (weapon.mData.mSlash[0] > weapon.mData.mSlash[1])
|
if (weapon.mData.mSlash[0] > weapon.mData.mSlash[1])
|
||||||
{
|
messages.push_back (std::make_pair (id,
|
||||||
messages.push_back(id.toString() + "|" + weapon.mId + " has minimum slash damage higher than maximum");
|
weapon.mId + " has minimum slash damage higher than maximum"));
|
||||||
}
|
|
||||||
|
|
||||||
if (weapon.mData.mThrust[0] > weapon.mData.mThrust[1])
|
if (weapon.mData.mThrust[0] > weapon.mData.mThrust[1])
|
||||||
{
|
messages.push_back (std::make_pair (id,
|
||||||
messages.push_back(id.toString() + "|" + weapon.mId + " has minimum thrust damage higher than maximum");
|
weapon.mId + " has minimum thrust damage higher than maximum"));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (weapon.mData.mChop[0] > weapon.mData.mChop[1])
|
if (weapon.mData.mChop[0] > weapon.mData.mChop[1])
|
||||||
{
|
messages.push_back (std::make_pair (id,
|
||||||
messages.push_back(id.toString() + "|" + weapon.mId + " has minimum chop damage higher than maximum");
|
weapon.mId + " has minimum chop damage higher than maximum"));
|
||||||
}
|
|
||||||
|
|
||||||
if (!(weapon.mData.mType == ESM::Weapon::Arrow ||
|
if (!(weapon.mData.mType == ESM::Weapon::Arrow ||
|
||||||
weapon.mData.mType == ESM::Weapon::Bolt ||
|
weapon.mData.mType == ESM::Weapon::Bolt ||
|
||||||
@ -881,14 +767,10 @@ void CSMTools::ReferenceableCheckStage::weaponCheck(
|
|||||||
{
|
{
|
||||||
//checking of health
|
//checking of health
|
||||||
if (weapon.mData.mHealth <= 0)
|
if (weapon.mData.mHealth <= 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, weapon.mId + " has non-positivie health"));
|
||||||
messages.push_back(id.toString() + "|" + weapon.mId + " has non-positivie health");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (weapon.mData.mReach < 0)
|
if (weapon.mData.mReach < 0)
|
||||||
{
|
messages.push_back (std::make_pair (id, weapon.mId + " has negative reach"));
|
||||||
messages.push_back(id.toString() + "|" + weapon.mId + " has negative reach");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -896,7 +778,7 @@ void CSMTools::ReferenceableCheckStage::weaponCheck(
|
|||||||
void CSMTools::ReferenceableCheckStage::probeCheck(
|
void CSMTools::ReferenceableCheckStage::probeCheck(
|
||||||
int stage,
|
int stage,
|
||||||
const CSMWorld::RefIdDataContainer< ESM::Probe >& records,
|
const CSMWorld::RefIdDataContainer< ESM::Probe >& records,
|
||||||
std::vector< std::string >& messages)
|
Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||||
|
|
||||||
@ -912,184 +794,128 @@ void CSMTools::ReferenceableCheckStage::probeCheck(
|
|||||||
toolCheck<ESM::Probe>(probe, messages, id.toString(), true);
|
toolCheck<ESM::Probe>(probe, messages, id.toString(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ReferenceableCheckStage::repairCheck(
|
void CSMTools::ReferenceableCheckStage::repairCheck (
|
||||||
int stage,
|
int stage, const CSMWorld::RefIdDataContainer< ESM::Repair >& records,
|
||||||
const CSMWorld::RefIdDataContainer< ESM::Repair >& records,
|
Messages& messages)
|
||||||
std::vector< std::string >& messages)
|
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord (stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
if (baseRecord.isDeleted())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
const ESM::Repair& repair = (dynamic_cast<const CSMWorld::Record<ESM::Repair>& >(baseRecord)).get();
|
const ESM::Repair& repair = (dynamic_cast<const CSMWorld::Record<ESM::Repair>& >(baseRecord)).get();
|
||||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Repair, repair.mId);
|
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Repair, repair.mId);
|
||||||
|
|
||||||
inventoryItemCheck<ESM::Repair>(repair, messages, id.toString());
|
inventoryItemCheck<ESM::Repair> (repair, messages, id.toString());
|
||||||
toolCheck<ESM::Repair>(repair, messages, id.toString(), true);
|
toolCheck<ESM::Repair> (repair, messages, id.toString(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ReferenceableCheckStage::staticCheck(
|
void CSMTools::ReferenceableCheckStage::staticCheck (
|
||||||
int stage,
|
int stage, const CSMWorld::RefIdDataContainer< ESM::Static >& records,
|
||||||
const CSMWorld::RefIdDataContainer< ESM::Static >& records,
|
Messages& messages)
|
||||||
std::vector< std::string >& messages)
|
|
||||||
{
|
{
|
||||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
const CSMWorld::RecordBase& baseRecord = records.getRecord (stage);
|
||||||
|
|
||||||
if (baseRecord.isDeleted())
|
if (baseRecord.isDeleted())
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
const ESM::Static& staticElement = (dynamic_cast<const CSMWorld::Record<ESM::Static>& >(baseRecord)).get();
|
const ESM::Static& staticElement = (dynamic_cast<const CSMWorld::Record<ESM::Static>& >(baseRecord)).get();
|
||||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Static, staticElement.mId);
|
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Static, staticElement.mId);
|
||||||
|
|
||||||
if (staticElement.mModel.empty())
|
if (staticElement.mModel.empty())
|
||||||
{
|
messages.push_back (std::make_pair (id, staticElement.mId + " has no model"));
|
||||||
messages.push_back(id.toString() + "|" + staticElement.mId + " has no model");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//final check
|
//final check
|
||||||
|
|
||||||
void CSMTools::ReferenceableCheckStage::finalCheck(std::vector< std::string >& messages)
|
void CSMTools::ReferenceableCheckStage::finalCheck (Messages& messages)
|
||||||
{
|
{
|
||||||
if (!mPlayerPresent)
|
if (!mPlayerPresent)
|
||||||
{
|
messages.push_back (std::make_pair (CSMWorld::UniversalId::Type_Referenceables,
|
||||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Npc);
|
"There is no player record"));
|
||||||
messages.push_back(id.toString() + "| There is no player record");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//Templates begins here
|
//Templates begins here
|
||||||
|
|
||||||
template<typename ITEM> void CSMTools::ReferenceableCheckStage::inventoryItemCheck(
|
template<typename Item> void CSMTools::ReferenceableCheckStage::inventoryItemCheck (
|
||||||
const ITEM& someItem,
|
const Item& someItem, Messages& messages, const std::string& someID, bool enchantable)
|
||||||
std::vector< std::string >& messages,
|
|
||||||
const std::string& someID, bool enchantable)
|
|
||||||
{
|
{
|
||||||
if (someItem.mName.empty())
|
if (someItem.mName.empty())
|
||||||
{
|
messages.push_back (std::make_pair (someID, someItem.mId + " has an empty name"));
|
||||||
messages.push_back(someID + "|" + someItem.mId + " has an empty name");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Checking for weight
|
//Checking for weight
|
||||||
if (someItem.mData.mWeight < 0)
|
if (someItem.mData.mWeight < 0)
|
||||||
{
|
messages.push_back (std::make_pair (someID, someItem.mId + " has negative weight"));
|
||||||
messages.push_back(someID + "|" + someItem.mId + " has negative weight");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Checking for value
|
//Checking for value
|
||||||
if (someItem.mData.mValue < 0)
|
if (someItem.mData.mValue < 0)
|
||||||
{
|
messages.push_back (std::make_pair (someID, someItem.mId + " has negative value"));
|
||||||
messages.push_back(someID + "|" + someItem.mId + " has negative value");
|
|
||||||
}
|
|
||||||
|
|
||||||
//checking for model
|
|
||||||
if (someItem.mModel.empty())
|
|
||||||
{
|
|
||||||
messages.push_back(someID + "|" + someItem.mId + " has no model");
|
|
||||||
}
|
|
||||||
|
|
||||||
//checking for icon
|
|
||||||
if (someItem.mIcon.empty())
|
|
||||||
{
|
|
||||||
messages.push_back(someID + "|" + someItem.mId + " has no icon");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enchantable)
|
|
||||||
{
|
|
||||||
if (someItem.mData.mEnchant < 0)
|
|
||||||
{
|
|
||||||
messages.push_back(someID + "|" + someItem.mId + " has negative enchantment");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename ITEM> void CSMTools::ReferenceableCheckStage::inventoryItemCheck(
|
|
||||||
const ITEM& someItem,
|
|
||||||
std::vector< std::string >& messages,
|
|
||||||
const std::string& someID)
|
|
||||||
{
|
|
||||||
if (someItem.mName.empty())
|
|
||||||
{
|
|
||||||
messages.push_back(someID + "|" + someItem.mId + " has an empty name");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Checking for weight
|
|
||||||
if (someItem.mData.mWeight < 0)
|
|
||||||
{
|
|
||||||
messages.push_back(someID + "|" + someItem.mId + " has negative weight");
|
|
||||||
}
|
|
||||||
|
|
||||||
//Checking for value
|
|
||||||
if (someItem.mData.mValue < 0)
|
|
||||||
{
|
|
||||||
messages.push_back(someID + "|" + someItem.mId + " has negative value");
|
|
||||||
}
|
|
||||||
|
|
||||||
//checking for model
|
//checking for model
|
||||||
if (someItem.mModel.empty())
|
if (someItem.mModel.empty())
|
||||||
{
|
messages.push_back (std::make_pair (someID, someItem.mId + " has no model"));
|
||||||
messages.push_back(someID + "|" + someItem.mId + " has no model");
|
|
||||||
}
|
|
||||||
|
|
||||||
//checking for icon
|
//checking for icon
|
||||||
if (someItem.mIcon.empty())
|
if (someItem.mIcon.empty())
|
||||||
{
|
messages.push_back (std::make_pair (someID, someItem.mId + " has no icon"));
|
||||||
messages.push_back(someID + "|" + someItem.mId + " has no icon");
|
|
||||||
}
|
if (enchantable && someItem.mData.mEnchant < 0)
|
||||||
|
messages.push_back (std::make_pair (someID, someItem.mId + " has negative enchantment"));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename TOOL> void CSMTools::ReferenceableCheckStage::toolCheck(
|
template<typename Item> void CSMTools::ReferenceableCheckStage::inventoryItemCheck (
|
||||||
const TOOL& someTool,
|
const Item& someItem, Messages& messages, const std::string& someID)
|
||||||
std::vector< std::string >& messages,
|
{
|
||||||
const std::string& someID, bool canBeBroken)
|
if (someItem.mName.empty())
|
||||||
|
messages.push_back (std::make_pair (someID, someItem.mId + " has an empty name"));
|
||||||
|
|
||||||
|
//Checking for weight
|
||||||
|
if (someItem.mData.mWeight < 0)
|
||||||
|
messages.push_back (std::make_pair (someID, someItem.mId + " has negative weight"));
|
||||||
|
|
||||||
|
//Checking for value
|
||||||
|
if (someItem.mData.mValue < 0)
|
||||||
|
messages.push_back (std::make_pair (someID, someItem.mId + " has negative value"));
|
||||||
|
|
||||||
|
//checking for model
|
||||||
|
if (someItem.mModel.empty())
|
||||||
|
messages.push_back (std::make_pair (someID, someItem.mId + " has no model"));
|
||||||
|
|
||||||
|
//checking for icon
|
||||||
|
if (someItem.mIcon.empty())
|
||||||
|
messages.push_back (std::make_pair (someID, someItem.mId + " has no icon"));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Tool> void CSMTools::ReferenceableCheckStage::toolCheck (
|
||||||
|
const Tool& someTool, Messages& messages, const std::string& someID, bool canBeBroken)
|
||||||
{
|
{
|
||||||
if (someTool.mData.mQuality <= 0)
|
if (someTool.mData.mQuality <= 0)
|
||||||
{
|
messages.push_back (std::make_pair (someID, someTool.mId + " has non-positive quality"));
|
||||||
messages.push_back(someID + "|" + someTool.mId + " has non-positive quality");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (canBeBroken)
|
if (canBeBroken && someTool.mData.mUses<=0)
|
||||||
{
|
messages.push_back (std::make_pair (someID,
|
||||||
if (someTool.mData.mUses <= 0)
|
someTool.mId + " has non-positive uses count"));
|
||||||
{
|
|
||||||
messages.push_back(someID + "|" + someTool.mId + " has non-positive uses count");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename TOOL> void CSMTools::ReferenceableCheckStage::toolCheck(
|
template<typename Tool> void CSMTools::ReferenceableCheckStage::toolCheck (
|
||||||
const TOOL& someTool,
|
const Tool& someTool, Messages& messages, const std::string& someID)
|
||||||
std::vector< std::string >& messages,
|
|
||||||
const std::string& someID)
|
|
||||||
{
|
{
|
||||||
if (someTool.mData.mQuality <= 0)
|
if (someTool.mData.mQuality <= 0)
|
||||||
{
|
messages.push_back (std::make_pair (someID, someTool.mId + " has non-positive quality"));
|
||||||
messages.push_back(someID + "|" + someTool.mId + " has non-positive quality");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename LIST> void CSMTools::ReferenceableCheckStage::listCheck(
|
template<typename List> void CSMTools::ReferenceableCheckStage::listCheck (
|
||||||
const LIST& someList,
|
const List& someList, Messages& messages, const std::string& someID)
|
||||||
std::vector< std::string >& messages,
|
|
||||||
const std::string& someID)
|
|
||||||
{
|
{
|
||||||
for (unsigned i = 0; i < someList.mList.size(); ++i)
|
for (unsigned i = 0; i < someList.mList.size(); ++i)
|
||||||
{
|
{
|
||||||
if (mReferencables.searchId(someList.mList[i].mId).first == -1)
|
if (mReferencables.searchId(someList.mList[i].mId).first == -1)
|
||||||
{
|
messages.push_back (std::make_pair (someID,
|
||||||
messages.push_back(someID + "|" + someList.mId + " contains item without referencable");
|
someList.mId + " contains item without referencable"));
|
||||||
}
|
|
||||||
|
|
||||||
if (someList.mList[i].mLevel < 1)
|
if (someList.mList[i].mLevel < 1)
|
||||||
{
|
messages.push_back (std::make_pair (someID,
|
||||||
messages.push_back(someID + "|" + someList.mId + " contains item with non-positive level");
|
someList.mId + " contains item with non-positive level"));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// kate: indent-mode cstyle; indent-width 4; replace-tabs on;
|
|
||||||
|
@ -11,63 +11,64 @@ namespace CSMTools
|
|||||||
class ReferenceableCheckStage : public CSMDoc::Stage
|
class ReferenceableCheckStage : public CSMDoc::Stage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ReferenceableCheckStage(const CSMWorld::RefIdData& referenceable,
|
|
||||||
const CSMWorld::IdCollection<ESM::Race>& races,
|
|
||||||
const CSMWorld::IdCollection<ESM::Class>& classes,
|
|
||||||
const CSMWorld::IdCollection<ESM::Faction>& factions);
|
|
||||||
|
|
||||||
virtual void perform(int stage, std::vector< std::string >& messages);
|
ReferenceableCheckStage (const CSMWorld::RefIdData& referenceable,
|
||||||
|
const CSMWorld::IdCollection<ESM::Race>& races,
|
||||||
|
const CSMWorld::IdCollection<ESM::Class>& classes,
|
||||||
|
const CSMWorld::IdCollection<ESM::Faction>& factions);
|
||||||
|
|
||||||
|
virtual void perform(int stage, Messages& messages);
|
||||||
virtual int setup();
|
virtual int setup();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//CONCRETE CHECKS
|
//CONCRETE CHECKS
|
||||||
void bookCheck(int stage, const CSMWorld::RefIdDataContainer< ESM::Book >& records, std::vector< std::string >& messages);
|
void bookCheck(int stage, const CSMWorld::RefIdDataContainer< ESM::Book >& records, Messages& messages);
|
||||||
void activatorCheck(int stage, const CSMWorld::RefIdDataContainer< ESM::Activator >& records, std::vector< std::string >& messages);
|
void activatorCheck(int stage, const CSMWorld::RefIdDataContainer< ESM::Activator >& records, Messages& messages);
|
||||||
void potionCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Potion>& records, std::vector<std::string>& messages);
|
void potionCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Potion>& records, Messages& messages);
|
||||||
void apparatusCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Apparatus>& records, std::vector<std::string>& messages);
|
void apparatusCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Apparatus>& records, Messages& messages);
|
||||||
void armorCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Armor>& records, std::vector<std::string>& messages);
|
void armorCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Armor>& records, Messages& messages);
|
||||||
void clothingCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Clothing>& records, std::vector<std::string>& messages);
|
void clothingCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Clothing>& records, Messages& messages);
|
||||||
void containerCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Container>& records, std::vector<std::string>& messages);
|
void containerCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Container>& records, Messages& messages);
|
||||||
void creatureCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Creature>& records, std::vector<std::string>& messages);
|
void creatureCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Creature>& records, Messages& messages);
|
||||||
void doorCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Door>& records, std::vector<std::string>& messages);
|
void doorCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Door>& records, Messages& messages);
|
||||||
void ingredientCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Ingredient>& records, std::vector<std::string>& messages);
|
void ingredientCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Ingredient>& records, Messages& messages);
|
||||||
void creaturesLevListCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::CreatureLevList>& records, std::vector<std::string>& messages);
|
void creaturesLevListCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::CreatureLevList>& records, Messages& messages);
|
||||||
void itemLevelledListCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::ItemLevList>& records, std::vector<std::string>& messages);
|
void itemLevelledListCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::ItemLevList>& records, Messages& messages);
|
||||||
void lightCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Light>& records, std::vector<std::string>& messages);
|
void lightCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Light>& records, Messages& messages);
|
||||||
void lockpickCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Lockpick>& records, std::vector<std::string>& messages);
|
void lockpickCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Lockpick>& records, Messages& messages);
|
||||||
void miscCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Miscellaneous>& records, std::vector<std::string>& messages);
|
void miscCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Miscellaneous>& records, Messages& messages);
|
||||||
void npcCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::NPC>& records, std::vector<std::string>& messages);
|
void npcCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::NPC>& records, Messages& messages);
|
||||||
void weaponCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Weapon>& records, std::vector<std::string>& messages);
|
void weaponCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Weapon>& records, Messages& messages);
|
||||||
void probeCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Probe>& records, std::vector<std::string>& messages);
|
void probeCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Probe>& records, Messages& messages);
|
||||||
void repairCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Repair>& records, std::vector<std::string>& messages);
|
void repairCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Repair>& records, Messages& messages);
|
||||||
void staticCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Static>& records, std::vector<std::string>& messages);
|
void staticCheck(int stage, const CSMWorld::RefIdDataContainer<ESM::Static>& records, Messages& messages);
|
||||||
|
|
||||||
//FINAL CHECK
|
//FINAL CHECK
|
||||||
void finalCheck(std::vector<std::string>& messages);
|
void finalCheck (Messages& messages);
|
||||||
|
|
||||||
//TEMPLATE CHECKS
|
//TEMPLATE CHECKS
|
||||||
template<typename ITEM> void inventoryItemCheck(const ITEM& someItem,
|
template<typename ITEM> void inventoryItemCheck(const ITEM& someItem,
|
||||||
std::vector<std::string>& messages,
|
Messages& messages,
|
||||||
const std::string& someID,
|
const std::string& someID,
|
||||||
bool enchantable); //for all enchantable items.
|
bool enchantable); //for all enchantable items.
|
||||||
|
|
||||||
template<typename ITEM> void inventoryItemCheck(const ITEM& someItem,
|
template<typename ITEM> void inventoryItemCheck(const ITEM& someItem,
|
||||||
std::vector<std::string>& messages,
|
Messages& messages,
|
||||||
const std::string& someID); //for non-enchantable items.
|
const std::string& someID); //for non-enchantable items.
|
||||||
|
|
||||||
template<typename TOOL> void toolCheck(const TOOL& someTool,
|
template<typename TOOL> void toolCheck(const TOOL& someTool,
|
||||||
std::vector<std::string>& messages,
|
Messages& messages,
|
||||||
const std::string& someID,
|
const std::string& someID,
|
||||||
bool canbebroken); //for tools with uses.
|
bool canbebroken); //for tools with uses.
|
||||||
|
|
||||||
template<typename TOOL> void toolCheck(const TOOL& someTool,
|
template<typename TOOL> void toolCheck(const TOOL& someTool,
|
||||||
std::vector<std::string>& messages,
|
Messages& messages,
|
||||||
const std::string& someID); //for tools without uses.
|
const std::string& someID); //for tools without uses.
|
||||||
|
|
||||||
template<typename LIST> void listCheck(const LIST& someList,
|
template<typename LIST> void listCheck(const LIST& someList,
|
||||||
std::vector< std::string >& messages,
|
Messages& messages,
|
||||||
const std::string& someID);
|
const std::string& someID);
|
||||||
|
|
||||||
const CSMWorld::RefIdData& mReferencables;
|
const CSMWorld::RefIdData& mReferencables;
|
||||||
const CSMWorld::IdCollection<ESM::Race>& mRaces;
|
const CSMWorld::IdCollection<ESM::Race>& mRaces;
|
||||||
const CSMWorld::IdCollection<ESM::Class>& mClasses;
|
const CSMWorld::IdCollection<ESM::Class>& mClasses;
|
||||||
|
@ -17,7 +17,7 @@ int CSMTools::RegionCheckStage::setup()
|
|||||||
return mRegions.getSize();
|
return mRegions.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::RegionCheckStage::perform (int stage, std::vector<std::string>& messages)
|
void CSMTools::RegionCheckStage::perform (int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<ESM::Region>& record = mRegions.getRecord (stage);
|
const CSMWorld::Record<ESM::Region>& record = mRegions.getRecord (stage);
|
||||||
|
|
||||||
@ -30,7 +30,7 @@ void CSMTools::RegionCheckStage::perform (int stage, std::vector<std::string>& m
|
|||||||
|
|
||||||
// test for empty name
|
// test for empty name
|
||||||
if (region.mName.empty())
|
if (region.mName.empty())
|
||||||
messages.push_back (id.toString() + "|" + region.mId + " has an empty name");
|
messages.push_back (std::make_pair (id, region.mId + " has an empty name"));
|
||||||
|
|
||||||
/// \todo test that the ID in mSleeplist exists
|
/// \todo test that the ID in mSleeplist exists
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ namespace CSMTools
|
|||||||
virtual int setup();
|
virtual int setup();
|
||||||
///< \return number of steps
|
///< \return number of steps
|
||||||
|
|
||||||
virtual void perform (int stage, std::vector<std::string>& messages);
|
virtual void perform (int stage, Messages& messages);
|
||||||
///< Messages resulting from this tage will be appended to \a messages.
|
///< Messages resulting from this tage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -51,16 +51,11 @@ bool CSMTools::ReportModel::removeRows (int row, int count, const QModelIndex& p
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ReportModel::add (const std::string& row)
|
void CSMTools::ReportModel::add (const CSMWorld::UniversalId& id, const std::string& message)
|
||||||
{
|
{
|
||||||
std::string::size_type index = row.find ('|');
|
|
||||||
|
|
||||||
if (index==std::string::npos)
|
|
||||||
throw std::logic_error ("invalid report message");
|
|
||||||
|
|
||||||
beginInsertRows (QModelIndex(), mRows.size(), mRows.size());
|
beginInsertRows (QModelIndex(), mRows.size(), mRows.size());
|
||||||
|
|
||||||
mRows.push_back (std::make_pair (row.substr (0, index), row.substr (index+1)));
|
mRows.push_back (std::make_pair (id, message));
|
||||||
|
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ namespace CSMTools
|
|||||||
|
|
||||||
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 std::string& row);
|
void add (const CSMWorld::UniversalId& id, const std::string& message);
|
||||||
|
|
||||||
const CSMWorld::UniversalId& getUniversalId (int row) const;
|
const CSMWorld::UniversalId& getUniversalId (int row) const;
|
||||||
};
|
};
|
||||||
|
@ -16,8 +16,6 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, const Compi
|
|||||||
|
|
||||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
|
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
|
||||||
|
|
||||||
stream << id.toString() << "|";
|
|
||||||
|
|
||||||
if (type==ErrorMessage)
|
if (type==ErrorMessage)
|
||||||
stream << "error ";
|
stream << "error ";
|
||||||
else
|
else
|
||||||
@ -28,25 +26,15 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, const Compi
|
|||||||
<< ", line " << loc.mLine << ", column " << loc.mColumn
|
<< ", line " << loc.mLine << ", column " << loc.mColumn
|
||||||
<< " (" << loc.mLiteral << "): " << message;
|
<< " (" << loc.mLiteral << "): " << message;
|
||||||
|
|
||||||
mMessages->push_back (stream.str());
|
mMessages->push_back (std::make_pair (id, stream.str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ScriptCheckStage::report (const std::string& message, Type type)
|
void CSMTools::ScriptCheckStage::report (const std::string& message, Type type)
|
||||||
{
|
{
|
||||||
std::ostringstream stream;
|
|
||||||
|
|
||||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
|
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
|
||||||
|
|
||||||
stream << id.toString() << "|";
|
mMessages->push_back (std::make_pair (id,
|
||||||
|
(type==ErrorMessage ? "error: " : "warning: ") + message));
|
||||||
if (type==ErrorMessage)
|
|
||||||
stream << "error: ";
|
|
||||||
else
|
|
||||||
stream << "warning: ";
|
|
||||||
|
|
||||||
stream << message;
|
|
||||||
|
|
||||||
mMessages->push_back (stream.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMWorld::Data& data)
|
CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMWorld::Data& data)
|
||||||
@ -68,7 +56,7 @@ int CSMTools::ScriptCheckStage::setup()
|
|||||||
return mData.getScripts().getSize();
|
return mData.getScripts().getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::ScriptCheckStage::perform (int stage, std::vector<std::string>& messages)
|
void CSMTools::ScriptCheckStage::perform (int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
mMessages = &messages;
|
mMessages = &messages;
|
||||||
mId = mData.getScripts().getId (stage);
|
mId = mData.getScripts().getId (stage);
|
||||||
@ -90,13 +78,10 @@ void CSMTools::ScriptCheckStage::perform (int stage, std::vector<std::string>& m
|
|||||||
}
|
}
|
||||||
catch (const std::exception& error)
|
catch (const std::exception& error)
|
||||||
{
|
{
|
||||||
std::ostringstream stream;
|
|
||||||
|
|
||||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
|
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Script, mId);
|
||||||
|
|
||||||
stream << id.toString() << "|Critical compile error: " << error.what();
|
messages.push_back (std::make_pair (id,
|
||||||
|
std::string ("Critical compile error: ") + error.what()));
|
||||||
messages.push_back (stream.str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mMessages = 0;
|
mMessages = 0;
|
||||||
|
@ -18,7 +18,7 @@ namespace CSMTools
|
|||||||
CSMWorld::ScriptContext mContext;
|
CSMWorld::ScriptContext mContext;
|
||||||
std::string mId;
|
std::string mId;
|
||||||
std::string mFile;
|
std::string mFile;
|
||||||
std::vector<std::string> *mMessages;
|
Messages *mMessages;
|
||||||
|
|
||||||
virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type);
|
virtual void report (const std::string& message, const Compiler::TokenLoc& loc, Type type);
|
||||||
///< Report error to the user.
|
///< Report error to the user.
|
||||||
@ -33,7 +33,7 @@ namespace CSMTools
|
|||||||
virtual int setup();
|
virtual int setup();
|
||||||
///< \return number of steps
|
///< \return number of steps
|
||||||
|
|
||||||
virtual void perform (int stage, std::vector<std::string>& messages);
|
virtual void perform (int stage, Messages& messages);
|
||||||
///< Messages resulting from this tage will be appended to \a messages.
|
///< Messages resulting from this tage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ int CSMTools::SkillCheckStage::setup()
|
|||||||
return mSkills.getSize();
|
return mSkills.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::SkillCheckStage::perform (int stage, std::vector<std::string>& messages)
|
void CSMTools::SkillCheckStage::perform (int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<ESM::Skill>& record = mSkills.getRecord (stage);
|
const CSMWorld::Record<ESM::Skill>& record = mSkills.getRecord (stage);
|
||||||
|
|
||||||
@ -32,11 +32,11 @@ void CSMTools::SkillCheckStage::perform (int stage, std::vector<std::string>& me
|
|||||||
{
|
{
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
|
|
||||||
stream << id.toString() << "|Use value #" << i << " of " << skill.mId << " is negative";
|
stream << "Use value #" << i << " of " << skill.mId << " is negative";
|
||||||
|
|
||||||
messages.push_back (stream.str());
|
messages.push_back (std::make_pair (id, stream.str()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (skill.mDescription.empty())
|
if (skill.mDescription.empty())
|
||||||
messages.push_back (id.toString() + "|" + skill.mId + " has an empty description");
|
messages.push_back (std::make_pair (id, skill.mId + " has an empty description"));
|
||||||
}
|
}
|
@ -21,7 +21,7 @@ namespace CSMTools
|
|||||||
virtual int setup();
|
virtual int setup();
|
||||||
///< \return number of steps
|
///< \return number of steps
|
||||||
|
|
||||||
virtual void perform (int stage, std::vector<std::string>& messages);
|
virtual void perform (int stage, Messages& messages);
|
||||||
///< Messages resulting from this tage will be appended to \a messages.
|
///< Messages resulting from this tage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ int CSMTools::SoundCheckStage::setup()
|
|||||||
return mSounds.getSize();
|
return mSounds.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::SoundCheckStage::perform (int stage, std::vector<std::string>& messages)
|
void CSMTools::SoundCheckStage::perform (int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<ESM::Sound>& record = mSounds.getRecord (stage);
|
const CSMWorld::Record<ESM::Sound>& record = mSounds.getRecord (stage);
|
||||||
|
|
||||||
@ -28,7 +28,7 @@ void CSMTools::SoundCheckStage::perform (int stage, std::vector<std::string>& me
|
|||||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Sound, sound.mId);
|
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Sound, sound.mId);
|
||||||
|
|
||||||
if (sound.mData.mMinRange>sound.mData.mMaxRange)
|
if (sound.mData.mMinRange>sound.mData.mMaxRange)
|
||||||
messages.push_back (id.toString() + "|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
|
||||||
}
|
}
|
@ -21,7 +21,7 @@ namespace CSMTools
|
|||||||
virtual int setup();
|
virtual int setup();
|
||||||
///< \return number of steps
|
///< \return number of steps
|
||||||
|
|
||||||
virtual void perform (int stage, std::vector<std::string>& messages);
|
virtual void perform (int stage, Messages& messages);
|
||||||
///< Messages resulting from this tage will be appended to \a messages.
|
///< Messages resulting from this tage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ int CSMTools::SpellCheckStage::setup()
|
|||||||
return mSpells.getSize();
|
return mSpells.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::SpellCheckStage::perform (int stage, std::vector<std::string>& messages)
|
void CSMTools::SpellCheckStage::perform (int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<ESM::Spell>& record = mSpells.getRecord (stage);
|
const CSMWorld::Record<ESM::Spell>& record = mSpells.getRecord (stage);
|
||||||
|
|
||||||
@ -30,11 +30,11 @@ void CSMTools::SpellCheckStage::perform (int stage, std::vector<std::string>& me
|
|||||||
|
|
||||||
// test for empty name and description
|
// test for empty name and description
|
||||||
if (spell.mName.empty())
|
if (spell.mName.empty())
|
||||||
messages.push_back (id.toString() + "|" + spell.mId + " has an empty name");
|
messages.push_back (std::make_pair (id, spell.mId + " has an empty name"));
|
||||||
|
|
||||||
// test for invalid cost values
|
// test for invalid cost values
|
||||||
if (spell.mData.mCost<0)
|
if (spell.mData.mCost<0)
|
||||||
messages.push_back (id.toString() + "|" + 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
|
||||||
}
|
}
|
@ -21,7 +21,7 @@ namespace CSMTools
|
|||||||
virtual int setup();
|
virtual int setup();
|
||||||
///< \return number of steps
|
///< \return number of steps
|
||||||
|
|
||||||
virtual void perform (int stage, std::vector<std::string>& messages);
|
virtual void perform (int stage, Messages& messages);
|
||||||
///< Messages resulting from this tage will be appended to \a messages.
|
///< Messages resulting from this tage will be appended to \a messages.
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -45,8 +45,9 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier()
|
|||||||
|
|
||||||
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)), this, SIGNAL (done (int)));
|
connect (mVerifier, SIGNAL (done (int)), this, SIGNAL (done (int)));
|
||||||
connect (mVerifier, SIGNAL (reportMessage (const QString&, int)),
|
connect (mVerifier,
|
||||||
this, SLOT (verifierMessage (const QString&, int)));
|
SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, int)),
|
||||||
|
this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, int)));
|
||||||
|
|
||||||
std::vector<std::string> mandatoryIds; // I want C++11, damn it!
|
std::vector<std::string> mandatoryIds; // I want C++11, damn it!
|
||||||
mandatoryIds.push_back ("Day");
|
mandatoryIds.push_back ("Day");
|
||||||
@ -87,13 +88,17 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier()
|
|||||||
|
|
||||||
CSMTools::Tools::Tools (CSMWorld::Data& data) : mData (data), mVerifier (0), mNextReportNumber (0)
|
CSMTools::Tools::Tools (CSMWorld::Data& data) : mData (data), mVerifier (0), mNextReportNumber (0)
|
||||||
{
|
{
|
||||||
for (std::map<int, ReportModel *>::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter)
|
// index 0: load error log
|
||||||
delete iter->second;
|
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel));
|
||||||
|
mActiveReports.insert (std::make_pair (CSMDoc::State_Loading, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMTools::Tools::~Tools()
|
CSMTools::Tools::~Tools()
|
||||||
{
|
{
|
||||||
delete mVerifier;
|
delete mVerifier;
|
||||||
|
|
||||||
|
for (std::map<int, ReportModel *>::iterator iter (mReports.begin()); iter!=mReports.end(); ++iter)
|
||||||
|
delete iter->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::UniversalId CSMTools::Tools::runVerifier()
|
CSMWorld::UniversalId CSMTools::Tools::runVerifier()
|
||||||
@ -132,17 +137,19 @@ 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)
|
||||||
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMTools::Tools::verifierMessage (const QString& message, int type)
|
void CSMTools::Tools::verifierMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
||||||
|
int type)
|
||||||
{
|
{
|
||||||
std::map<int, int>::iterator iter = mActiveReports.find (type);
|
std::map<int, int>::iterator iter = mActiveReports.find (type);
|
||||||
|
|
||||||
if (iter!=mActiveReports.end())
|
if (iter!=mActiveReports.end())
|
||||||
mReports[iter->second]->add (message.toUtf8().constData());
|
mReports[iter->second]->add (id, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,8 @@ namespace CSMTools
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void verifierMessage (const QString& message, int type);
|
void verifierMessage (const CSMWorld::UniversalId& id, const std::string& message,
|
||||||
|
int type);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
|
@ -18,8 +18,3 @@ void CSMWorld::Cell::load (ESM::ESMReader &esm)
|
|||||||
mId = stream.str();
|
mId = stream.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMWorld::Cell::addRef (const std::string& id)
|
|
||||||
{
|
|
||||||
mRefs.push_back (std::make_pair (id, false));
|
|
||||||
}
|
|
@ -15,12 +15,9 @@ namespace CSMWorld
|
|||||||
struct Cell : public ESM::Cell
|
struct Cell : public ESM::Cell
|
||||||
{
|
{
|
||||||
std::string mId;
|
std::string mId;
|
||||||
std::vector<std::pair<std::string, bool> > mRefs; // ID, modified
|
|
||||||
std::vector<std::string> mDeletedRefs;
|
|
||||||
|
|
||||||
void load (ESM::ESMReader &esm);
|
void load (ESM::ESMReader &esm);
|
||||||
|
|
||||||
void addRef (const std::string& id);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,6 +86,8 @@ namespace CSMWorld
|
|||||||
|
|
||||||
virtual QVariant getData (int index, int column) const;
|
virtual QVariant getData (int index, int column) const;
|
||||||
|
|
||||||
|
virtual QVariant getNestedData(int row, int column, int subRow, int subColumn) const;
|
||||||
|
|
||||||
virtual void setData (int index, int column, const QVariant& data);
|
virtual void setData (int index, int column, const QVariant& data);
|
||||||
|
|
||||||
virtual const ColumnBase& getColumn (int column) const;
|
virtual const ColumnBase& getColumn (int column) const;
|
||||||
@ -295,6 +297,12 @@ namespace CSMWorld
|
|||||||
return mColumns.at (column)->get (mRecords.at (index));
|
return mColumns.at (column)->get (mRecords.at (index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
QVariant Collection<ESXRecordT, IdAccessorT>::getNestedData(int row, int column, int subRow, int subColumn) const
|
||||||
|
{
|
||||||
|
return 10; //TODO
|
||||||
|
}
|
||||||
|
|
||||||
template<typename ESXRecordT, typename IdAccessorT>
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
void Collection<ESXRecordT, IdAccessorT>::setData (int index, int column, const QVariant& data)
|
void Collection<ESXRecordT, IdAccessorT>::setData (int index, int column, const QVariant& data)
|
||||||
{
|
{
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "collectionbase.hpp"
|
#include "collectionbase.hpp"
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
#include "columnbase.hpp"
|
#include "columnbase.hpp"
|
||||||
|
|
||||||
|
@ -48,6 +48,8 @@ namespace CSMWorld
|
|||||||
|
|
||||||
virtual QVariant getData (int index, int column) const = 0;
|
virtual QVariant getData (int index, int column) const = 0;
|
||||||
|
|
||||||
|
virtual QVariant getNestedData(int row, int column, int subRow, int subColumn) const = 0;
|
||||||
|
|
||||||
virtual void setData (int index, int column, const QVariant& data) = 0;
|
virtual void setData (int index, int column, const QVariant& data) = 0;
|
||||||
|
|
||||||
virtual void setNestedData(int row, int column, const QVariant& data, int subRow, int subColumn);
|
virtual void setNestedData(int row, int column, const QVariant& data, int subRow, int subColumn);
|
||||||
|
@ -89,7 +89,9 @@ namespace CSMWorld
|
|||||||
Display_RefRecordType,
|
Display_RefRecordType,
|
||||||
Display_DialogueType,
|
Display_DialogueType,
|
||||||
Display_QuestStatusType,
|
Display_QuestStatusType,
|
||||||
Display_Gender
|
Display_Gender,
|
||||||
|
|
||||||
|
Display_Nested
|
||||||
};
|
};
|
||||||
|
|
||||||
int mColumnId;
|
int mColumnId;
|
||||||
@ -125,6 +127,12 @@ namespace CSMWorld
|
|||||||
throw std::logic_error ("Column " + getTitle() + " is not editable");
|
throw std::logic_error ("Column " + getTitle() + " is not editable");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
struct NestedColumn
|
||||||
|
{
|
||||||
|
virtual QVariant getNested(const Record<ESXRecordT>& record, int subColumn, int subSow) const = 0;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -167,6 +167,7 @@ namespace CSMWorld
|
|||||||
ColumnId_PcRank = 154,
|
ColumnId_PcRank = 154,
|
||||||
ColumnId_Scope = 155,
|
ColumnId_Scope = 155,
|
||||||
ColumnId_ReferenceableId = 156,
|
ColumnId_ReferenceableId = 156,
|
||||||
|
ColumnId_ContainerContent = 157,
|
||||||
|
|
||||||
// Allocated to a separate value range, so we don't get a collision should we ever need
|
// Allocated to a separate value range, so we don't get a collision should we ever need
|
||||||
// to extend the number of use values.
|
// to extend the number of use values.
|
||||||
|
165
apps/opencs/model/world/commanddispatcher.cpp
Normal file
165
apps/opencs/model/world/commanddispatcher.cpp
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
|
||||||
|
#include "commanddispatcher.hpp"
|
||||||
|
|
||||||
|
#include "../doc/document.hpp"
|
||||||
|
|
||||||
|
#include "idtable.hpp"
|
||||||
|
#include "record.hpp"
|
||||||
|
#include "commands.hpp"
|
||||||
|
|
||||||
|
std::vector<std::string> CSMWorld::CommandDispatcher::getDeletableRecords() const
|
||||||
|
{
|
||||||
|
std::vector<std::string> result;
|
||||||
|
|
||||||
|
IdTable& model = dynamic_cast<IdTable&> (*mDocument.getData().getTableModel (mId));
|
||||||
|
|
||||||
|
int stateColumnIndex = model.findColumnIndex (Columns::ColumnId_Modification);
|
||||||
|
|
||||||
|
for (std::vector<std::string>::const_iterator iter (mSelection.begin());
|
||||||
|
iter!=mSelection.end(); ++iter)
|
||||||
|
{
|
||||||
|
int row = model.getModelIndex (*iter, 0).row();
|
||||||
|
|
||||||
|
// check record state
|
||||||
|
RecordBase::State state = static_cast<RecordBase::State> (
|
||||||
|
model.data (model.index (row, stateColumnIndex)).toInt());
|
||||||
|
|
||||||
|
if (state==RecordBase::State_Deleted)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// check other columns (only relevant for a subset of the tables)
|
||||||
|
int dialogueTypeIndex = model.searchColumnIndex (Columns::ColumnId_DialogueType);
|
||||||
|
|
||||||
|
if (dialogueTypeIndex!=-1)
|
||||||
|
{
|
||||||
|
int type = model.data (model.index (row, dialogueTypeIndex)).toInt();
|
||||||
|
|
||||||
|
if (type!=ESM::Dialogue::Topic && type!=ESM::Dialogue::Journal)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.push_back (*iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> CSMWorld::CommandDispatcher::getRevertableRecords() const
|
||||||
|
{
|
||||||
|
std::vector<std::string> result;
|
||||||
|
|
||||||
|
IdTable& model = dynamic_cast<IdTable&> (*mDocument.getData().getTableModel (mId));
|
||||||
|
|
||||||
|
/// \todo Reverting temporarily disabled on tables that support reordering, because
|
||||||
|
/// revert logic currently can not handle reordering.
|
||||||
|
if (model.getFeatures() & IdTable::Feature_ReorderWithinTopic)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
int stateColumnIndex = model.findColumnIndex (Columns::ColumnId_Modification);
|
||||||
|
|
||||||
|
for (std::vector<std::string>::const_iterator iter (mSelection.begin());
|
||||||
|
iter!=mSelection.end(); ++iter)
|
||||||
|
{
|
||||||
|
int row = model.getModelIndex (*iter, 0).row();
|
||||||
|
|
||||||
|
// check record state
|
||||||
|
RecordBase::State state = static_cast<RecordBase::State> (
|
||||||
|
model.data (model.index (row, stateColumnIndex)).toInt());
|
||||||
|
|
||||||
|
if (state==RecordBase::State_BaseOnly)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
result.push_back (*iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMWorld::CommandDispatcher::CommandDispatcher (CSMDoc::Document& document,
|
||||||
|
const CSMWorld::UniversalId& id, QObject *parent)
|
||||||
|
: QObject (parent), mDocument (document), mId (id), mLocked (false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void CSMWorld::CommandDispatcher::setEditLock (bool locked)
|
||||||
|
{
|
||||||
|
mLocked = locked;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::CommandDispatcher::setSelection (const std::vector<std::string>& selection)
|
||||||
|
{
|
||||||
|
mSelection = selection;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMWorld::CommandDispatcher::canDelete() const
|
||||||
|
{
|
||||||
|
if (mLocked)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return getDeletableRecords().size()!=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CSMWorld::CommandDispatcher::canRevert() const
|
||||||
|
{
|
||||||
|
if (mLocked)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return getRevertableRecords().size()!=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::CommandDispatcher::executeDelete()
|
||||||
|
{
|
||||||
|
if (mLocked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::vector<std::string> rows = getDeletableRecords();
|
||||||
|
|
||||||
|
if (rows.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
IdTable& model = dynamic_cast<IdTable&> (*mDocument.getData().getTableModel (mId));
|
||||||
|
|
||||||
|
int columnIndex = model.findColumnIndex (Columns::ColumnId_Id);
|
||||||
|
|
||||||
|
if (rows.size()>1)
|
||||||
|
mDocument.getUndoStack().beginMacro (tr ("Delete multiple records"));
|
||||||
|
|
||||||
|
for (std::vector<std::string>::const_iterator iter (rows.begin()); iter!=rows.end(); ++iter)
|
||||||
|
{
|
||||||
|
std::string id = model.data (model.getModelIndex (*iter, columnIndex)).
|
||||||
|
toString().toUtf8().constData();
|
||||||
|
|
||||||
|
mDocument.getUndoStack().push (new CSMWorld::DeleteCommand (model, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rows.size()>1)
|
||||||
|
mDocument.getUndoStack().endMacro();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::CommandDispatcher::executeRevert()
|
||||||
|
{
|
||||||
|
if (mLocked)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::vector<std::string> rows = getRevertableRecords();
|
||||||
|
|
||||||
|
if (rows.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
IdTable& model = dynamic_cast<IdTable&> (*mDocument.getData().getTableModel (mId));
|
||||||
|
|
||||||
|
int columnIndex = model.findColumnIndex (Columns::ColumnId_Id);
|
||||||
|
|
||||||
|
if (rows.size()>1)
|
||||||
|
mDocument.getUndoStack().beginMacro (tr ("Revert multiple records"));
|
||||||
|
|
||||||
|
for (std::vector<std::string>::const_iterator iter (rows.begin()); iter!=rows.end(); ++iter)
|
||||||
|
{
|
||||||
|
std::string id = model.data (model.getModelIndex (*iter, columnIndex)).
|
||||||
|
toString().toUtf8().constData();
|
||||||
|
|
||||||
|
mDocument.getUndoStack().push (new CSMWorld::RevertCommand (model, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rows.size()>1)
|
||||||
|
mDocument.getUndoStack().endMacro();
|
||||||
|
}
|
53
apps/opencs/model/world/commanddispatcher.hpp
Normal file
53
apps/opencs/model/world/commanddispatcher.hpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#ifndef CSM_WOLRD_COMMANDDISPATCHER_H
|
||||||
|
#define CSM_WOLRD_COMMANDDISPATCHER_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
#include "universalid.hpp"
|
||||||
|
|
||||||
|
namespace CSMDoc
|
||||||
|
{
|
||||||
|
class Document;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
class CommandDispatcher : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
bool mLocked;
|
||||||
|
CSMDoc::Document& mDocument;
|
||||||
|
UniversalId mId;
|
||||||
|
std::vector<std::string> mSelection;
|
||||||
|
|
||||||
|
std::vector<std::string> getDeletableRecords() const;
|
||||||
|
|
||||||
|
std::vector<std::string> getRevertableRecords() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
CommandDispatcher (CSMDoc::Document& document, const CSMWorld::UniversalId& id,
|
||||||
|
QObject *parent = 0);
|
||||||
|
///< \param id ID of the table the commands should operate on primarily.
|
||||||
|
|
||||||
|
void setEditLock (bool locked);
|
||||||
|
|
||||||
|
void setSelection (const std::vector<std::string>& selection);
|
||||||
|
|
||||||
|
bool canDelete() const;
|
||||||
|
|
||||||
|
bool canRevert() const;
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
void executeDelete();
|
||||||
|
|
||||||
|
void executeRevert();
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -16,11 +16,12 @@
|
|||||||
#include "regionmap.hpp"
|
#include "regionmap.hpp"
|
||||||
#include "columns.hpp"
|
#include "columns.hpp"
|
||||||
|
|
||||||
void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type1,
|
void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type, bool update)
|
||||||
UniversalId::Type type2, bool update)
|
|
||||||
{
|
{
|
||||||
mModels.push_back (model);
|
mModels.push_back (model);
|
||||||
mModelIndex.insert (std::make_pair (type1, model));
|
mModelIndex.insert (std::make_pair (type, model));
|
||||||
|
|
||||||
|
UniversalId::Type type2 = UniversalId::getParentType (type);
|
||||||
|
|
||||||
if (type2!=UniversalId::Type_None)
|
if (type2!=UniversalId::Type_None)
|
||||||
mModelIndex.insert (std::make_pair (type2, model));
|
mModelIndex.insert (std::make_pair (type2, model));
|
||||||
@ -55,7 +56,8 @@ int CSMWorld::Data::count (RecordBase::State state, const CollectionBase& collec
|
|||||||
return number;
|
return number;
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::Data::Data() : mRefs (mCells)
|
CSMWorld::Data::Data (ToUTF8::FromType encoding)
|
||||||
|
: mEncoder (encoding), mRefs (mCells), mReader (0), mDialogue (0)
|
||||||
{
|
{
|
||||||
mGlobals.addColumn (new StringIdColumn<ESM::Global>);
|
mGlobals.addColumn (new StringIdColumn<ESM::Global>);
|
||||||
mGlobals.addColumn (new RecordStateColumn<ESM::Global>);
|
mGlobals.addColumn (new RecordStateColumn<ESM::Global>);
|
||||||
@ -234,32 +236,34 @@ CSMWorld::Data::Data() : mRefs (mCells)
|
|||||||
mFilters.addColumn (new DescriptionColumn<CSMFilter::Filter>);
|
mFilters.addColumn (new DescriptionColumn<CSMFilter::Filter>);
|
||||||
mFilters.addColumn (new ScopeColumn<CSMFilter::Filter>);
|
mFilters.addColumn (new ScopeColumn<CSMFilter::Filter>);
|
||||||
|
|
||||||
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
|
addModel (new IdTable (&mGlobals), UniversalId::Type_Global);
|
||||||
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst);
|
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmst);
|
||||||
addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill, false);
|
addModel (new IdTable (&mSkills), UniversalId::Type_Skill);
|
||||||
addModel (new IdTable (&mClasses), UniversalId::Type_Classes, UniversalId::Type_Class);
|
addModel (new IdTable (&mClasses), UniversalId::Type_Class);
|
||||||
addModel (new IdTable (&mFactions), UniversalId::Type_Factions, UniversalId::Type_Faction);
|
addModel (new IdTable (&mFactions), UniversalId::Type_Faction);
|
||||||
addModel (new IdTable (&mRaces), UniversalId::Type_Races, UniversalId::Type_Race);
|
addModel (new IdTable (&mRaces), UniversalId::Type_Race);
|
||||||
addModel (new IdTable (&mSounds), UniversalId::Type_Sounds, UniversalId::Type_Sound);
|
addModel (new IdTable (&mSounds), UniversalId::Type_Sound);
|
||||||
addModel (new IdTable (&mScripts), UniversalId::Type_Scripts, UniversalId::Type_Script);
|
addModel (new IdTable (&mScripts), UniversalId::Type_Script);
|
||||||
addModel (new IdTable (&mRegions), UniversalId::Type_Regions, UniversalId::Type_Region);
|
addModel (new IdTable (&mRegions), UniversalId::Type_Region);
|
||||||
addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsigns, UniversalId::Type_Birthsign);
|
addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsign);
|
||||||
addModel (new IdTable (&mSpells), UniversalId::Type_Spells, UniversalId::Type_Spell);
|
addModel (new IdTable (&mSpells), UniversalId::Type_Spell);
|
||||||
addModel (new IdTable (&mTopics), UniversalId::Type_Topics, UniversalId::Type_Topic);
|
addModel (new IdTable (&mTopics), UniversalId::Type_Topic);
|
||||||
addModel (new IdTable (&mJournals), UniversalId::Type_Journals, UniversalId::Type_Journal);
|
addModel (new IdTable (&mJournals), UniversalId::Type_Journal);
|
||||||
addModel (new IdTable (&mTopicInfos, IdTable::Reordering_WithinTopic), UniversalId::Type_TopicInfos, UniversalId::Type_TopicInfo);
|
addModel (new IdTable (&mTopicInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_TopicInfo);
|
||||||
addModel (new IdTable (&mJournalInfos, IdTable::Reordering_WithinTopic), UniversalId::Type_JournalInfos, UniversalId::Type_JournalInfo);
|
addModel (new IdTable (&mJournalInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_JournalInfo);
|
||||||
addModel (new IdTable (&mCells, IdTable::Reordering_None, IdTable::Viewing_Id), UniversalId::Type_Cells, UniversalId::Type_Cell);
|
addModel (new IdTable (&mCells, IdTable::Feature_ViewId), UniversalId::Type_Cell);
|
||||||
addModel (new IdTable (&mReferenceables, IdTable::Reordering_None, IdTable::Viewing_None, true),
|
addModel (new IdTable (&mReferenceables, IdTable::Feature_Preview),
|
||||||
UniversalId::Type_Referenceables, UniversalId::Type_Referenceable);
|
UniversalId::Type_Referenceable);
|
||||||
addModel (new IdTable (&mRefs, IdTable::Reordering_None, IdTable::Viewing_Cell, true), UniversalId::Type_References, UniversalId::Type_Reference, false);
|
addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_Reference);
|
||||||
addModel (new IdTable (&mFilters), UniversalId::Type_Filters, UniversalId::Type_Filter, false);
|
addModel (new IdTable (&mFilters), UniversalId::Type_Filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::Data::~Data()
|
CSMWorld::Data::~Data()
|
||||||
{
|
{
|
||||||
for (std::vector<QAbstractItemModel *>::iterator iter (mModels.begin()); iter!=mModels.end(); ++iter)
|
for (std::vector<QAbstractItemModel *>::iterator iter (mModels.begin()); iter!=mModels.end(); ++iter)
|
||||||
delete *iter;
|
delete *iter;
|
||||||
|
|
||||||
|
delete mReader;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CSMWorld::IdCollection<ESM::Global>& CSMWorld::Data::getGlobals() const
|
const CSMWorld::IdCollection<ESM::Global>& CSMWorld::Data::getGlobals() const
|
||||||
@ -453,7 +457,7 @@ CSMWorld::IdCollection<CSMFilter::Filter>& CSMWorld::Data::getFilters()
|
|||||||
return mFilters;
|
return mFilters;
|
||||||
}
|
}
|
||||||
|
|
||||||
QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id)
|
QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId& id)
|
||||||
{
|
{
|
||||||
std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType());
|
std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType());
|
||||||
|
|
||||||
@ -466,8 +470,7 @@ QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id)
|
|||||||
if (id.getType()==UniversalId::Type_RegionMap)
|
if (id.getType()==UniversalId::Type_RegionMap)
|
||||||
{
|
{
|
||||||
RegionMap *table = 0;
|
RegionMap *table = 0;
|
||||||
addModel (table = new RegionMap (*this), UniversalId::Type_RegionMap,
|
addModel (table = new RegionMap (*this), UniversalId::Type_RegionMap, false);
|
||||||
UniversalId::Type_None, false);
|
|
||||||
return table;
|
return table;
|
||||||
}
|
}
|
||||||
throw std::logic_error ("No table model available for " + id.toString());
|
throw std::logic_error ("No table model available for " + id.toString());
|
||||||
@ -481,148 +484,171 @@ void CSMWorld::Data::merge()
|
|||||||
mGlobals.merge();
|
mGlobals.merge();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base, bool project)
|
int CSMWorld::Data::startLoading (const boost::filesystem::path& path, bool base, bool project)
|
||||||
{
|
{
|
||||||
ESM::ESMReader reader;
|
delete mReader;
|
||||||
|
mReader = 0;
|
||||||
|
mDialogue = 0;
|
||||||
|
mRefLoadCache.clear();
|
||||||
|
|
||||||
/// \todo set encoding properly, once config implementation has been fixed.
|
mReader = new ESM::ESMReader;
|
||||||
ToUTF8::Utf8Encoder encoder (ToUTF8::calculateEncoding ("win1252"));
|
mReader->setEncoder (&mEncoder);
|
||||||
reader.setEncoder (&encoder);
|
mReader->open (path.string());
|
||||||
|
|
||||||
reader.open (path.string());
|
mBase = base;
|
||||||
|
mProject = project;
|
||||||
|
|
||||||
const ESM::Dialogue *dialogue = 0;
|
mAuthor = mReader->getAuthor();
|
||||||
|
mDescription = mReader->getDesc();
|
||||||
|
|
||||||
mAuthor = reader.getAuthor();
|
return mReader->getRecordCount();
|
||||||
mDescription = reader.getDesc();
|
}
|
||||||
|
|
||||||
// Note: We do not need to send update signals here, because at this point the model is not connected
|
bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages)
|
||||||
// to any view.
|
{
|
||||||
while (reader.hasMoreRecs())
|
if (!mReader)
|
||||||
|
throw std::logic_error ("can't continue loading, because no load has been started");
|
||||||
|
|
||||||
|
if (!mReader->hasMoreRecs())
|
||||||
{
|
{
|
||||||
ESM::NAME n = reader.getRecName();
|
delete mReader;
|
||||||
reader.getRecHeader();
|
mReader = 0;
|
||||||
|
mDialogue = 0;
|
||||||
switch (n.val)
|
mRefLoadCache.clear();
|
||||||
{
|
return true;
|
||||||
case ESM::REC_GLOB: mGlobals.load (reader, base); break;
|
|
||||||
case ESM::REC_GMST: mGmsts.load (reader, base); break;
|
|
||||||
case ESM::REC_SKIL: mSkills.load (reader, base); break;
|
|
||||||
case ESM::REC_CLAS: mClasses.load (reader, base); break;
|
|
||||||
case ESM::REC_FACT: mFactions.load (reader, base); break;
|
|
||||||
case ESM::REC_RACE: mRaces.load (reader, base); break;
|
|
||||||
case ESM::REC_SOUN: mSounds.load (reader, base); break;
|
|
||||||
case ESM::REC_SCPT: mScripts.load (reader, base); break;
|
|
||||||
case ESM::REC_REGN: mRegions.load (reader, base); break;
|
|
||||||
case ESM::REC_BSGN: mBirthsigns.load (reader, base); break;
|
|
||||||
case ESM::REC_SPEL: mSpells.load (reader, base); break;
|
|
||||||
|
|
||||||
case ESM::REC_CELL:
|
|
||||||
mCells.load (reader, base);
|
|
||||||
mRefs.load (reader, mCells.getSize()-1, base);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ESM::REC_ACTI: mReferenceables.load (reader, base, UniversalId::Type_Activator); break;
|
|
||||||
case ESM::REC_ALCH: mReferenceables.load (reader, base, UniversalId::Type_Potion); break;
|
|
||||||
case ESM::REC_APPA: mReferenceables.load (reader, base, UniversalId::Type_Apparatus); break;
|
|
||||||
case ESM::REC_ARMO: mReferenceables.load (reader, base, UniversalId::Type_Armor); break;
|
|
||||||
case ESM::REC_BOOK: mReferenceables.load (reader, base, UniversalId::Type_Book); break;
|
|
||||||
case ESM::REC_CLOT: mReferenceables.load (reader, base, UniversalId::Type_Clothing); break;
|
|
||||||
case ESM::REC_CONT: mReferenceables.load (reader, base, UniversalId::Type_Container); break;
|
|
||||||
case ESM::REC_CREA: mReferenceables.load (reader, base, UniversalId::Type_Creature); break;
|
|
||||||
case ESM::REC_DOOR: mReferenceables.load (reader, base, UniversalId::Type_Door); break;
|
|
||||||
case ESM::REC_INGR: mReferenceables.load (reader, base, UniversalId::Type_Ingredient); break;
|
|
||||||
case ESM::REC_LEVC:
|
|
||||||
mReferenceables.load (reader, base, UniversalId::Type_CreatureLevelledList); break;
|
|
||||||
case ESM::REC_LEVI:
|
|
||||||
mReferenceables.load (reader, base, UniversalId::Type_ItemLevelledList); break;
|
|
||||||
case ESM::REC_LIGH: mReferenceables.load (reader, base, UniversalId::Type_Light); break;
|
|
||||||
case ESM::REC_LOCK: mReferenceables.load (reader, base, UniversalId::Type_Lockpick); break;
|
|
||||||
case ESM::REC_MISC:
|
|
||||||
mReferenceables.load (reader, base, UniversalId::Type_Miscellaneous); break;
|
|
||||||
case ESM::REC_NPC_: mReferenceables.load (reader, base, UniversalId::Type_Npc); break;
|
|
||||||
case ESM::REC_PROB: mReferenceables.load (reader, base, UniversalId::Type_Probe); break;
|
|
||||||
case ESM::REC_REPA: mReferenceables.load (reader, base, UniversalId::Type_Repair); break;
|
|
||||||
case ESM::REC_STAT: mReferenceables.load (reader, base, UniversalId::Type_Static); break;
|
|
||||||
case ESM::REC_WEAP: mReferenceables.load (reader, base, UniversalId::Type_Weapon); break;
|
|
||||||
|
|
||||||
case ESM::REC_DIAL:
|
|
||||||
{
|
|
||||||
std::string id = reader.getHNOString ("NAME");
|
|
||||||
|
|
||||||
ESM::Dialogue record;
|
|
||||||
record.mId = id;
|
|
||||||
record.load (reader);
|
|
||||||
|
|
||||||
if (record.mType==ESM::Dialogue::Journal)
|
|
||||||
{
|
|
||||||
mJournals.load (record, base);
|
|
||||||
dialogue = &mJournals.getRecord (id).get();
|
|
||||||
}
|
|
||||||
else if (record.mType==ESM::Dialogue::Deleted)
|
|
||||||
{
|
|
||||||
dialogue = 0; // record vector can be shuffled around which would make pointer
|
|
||||||
// to record invalid
|
|
||||||
|
|
||||||
if (mJournals.tryDelete (id))
|
|
||||||
{
|
|
||||||
/// \todo handle info records
|
|
||||||
}
|
|
||||||
else if (mTopics.tryDelete (id))
|
|
||||||
{
|
|
||||||
/// \todo handle info records
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/// \todo report deletion of non-existing record
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mTopics.load (record, base);
|
|
||||||
dialogue = &mTopics.getRecord (id).get();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ESM::REC_INFO:
|
|
||||||
{
|
|
||||||
if (!dialogue)
|
|
||||||
{
|
|
||||||
/// \todo INFO record without matching DIAL record -> report to user
|
|
||||||
reader.skipRecord();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (dialogue->mType==ESM::Dialogue::Journal)
|
|
||||||
mJournalInfos.load (reader, base, *dialogue);
|
|
||||||
else
|
|
||||||
mTopicInfos.load (reader, base, *dialogue);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case ESM::REC_FILT:
|
|
||||||
|
|
||||||
if (project)
|
|
||||||
{
|
|
||||||
mFilters.load (reader, base);
|
|
||||||
mFilters.setData (mFilters.getSize()-1,
|
|
||||||
mFilters.findColumnIndex (CSMWorld::Columns::ColumnId_Scope),
|
|
||||||
static_cast<int> (CSMFilter::Filter::Scope_Project));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// fall through (filter record in a content file is an error with format 0)
|
|
||||||
|
|
||||||
default:
|
|
||||||
|
|
||||||
/// \todo throw an exception instead, once all records are implemented
|
|
||||||
/// or maybe report error and continue?
|
|
||||||
reader.skipRecord();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ESM::NAME n = mReader->getRecName();
|
||||||
|
mReader->getRecHeader();
|
||||||
|
|
||||||
|
switch (n.val)
|
||||||
|
{
|
||||||
|
case ESM::REC_GLOB: mGlobals.load (*mReader, mBase); break;
|
||||||
|
case ESM::REC_GMST: mGmsts.load (*mReader, mBase); break;
|
||||||
|
case ESM::REC_SKIL: mSkills.load (*mReader, mBase); break;
|
||||||
|
case ESM::REC_CLAS: mClasses.load (*mReader, mBase); break;
|
||||||
|
case ESM::REC_FACT: mFactions.load (*mReader, mBase); break;
|
||||||
|
case ESM::REC_RACE: mRaces.load (*mReader, mBase); break;
|
||||||
|
case ESM::REC_SOUN: mSounds.load (*mReader, mBase); break;
|
||||||
|
case ESM::REC_SCPT: mScripts.load (*mReader, mBase); break;
|
||||||
|
case ESM::REC_REGN: mRegions.load (*mReader, mBase); break;
|
||||||
|
case ESM::REC_BSGN: mBirthsigns.load (*mReader, mBase); break;
|
||||||
|
case ESM::REC_SPEL: mSpells.load (*mReader, mBase); break;
|
||||||
|
|
||||||
|
case ESM::REC_CELL:
|
||||||
|
{
|
||||||
|
mCells.load (*mReader, mBase);
|
||||||
|
std::string cellId = Misc::StringUtils::lowerCase (mCells.getId (mCells.getSize()-1));
|
||||||
|
mRefs.load (*mReader, mCells.getSize()-1, mBase, mRefLoadCache[cellId], messages);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ESM::REC_ACTI: mReferenceables.load (*mReader, mBase, UniversalId::Type_Activator); break;
|
||||||
|
case ESM::REC_ALCH: mReferenceables.load (*mReader, mBase, UniversalId::Type_Potion); break;
|
||||||
|
case ESM::REC_APPA: mReferenceables.load (*mReader, mBase, UniversalId::Type_Apparatus); break;
|
||||||
|
case ESM::REC_ARMO: mReferenceables.load (*mReader, mBase, UniversalId::Type_Armor); break;
|
||||||
|
case ESM::REC_BOOK: mReferenceables.load (*mReader, mBase, UniversalId::Type_Book); break;
|
||||||
|
case ESM::REC_CLOT: mReferenceables.load (*mReader, mBase, UniversalId::Type_Clothing); break;
|
||||||
|
case ESM::REC_CONT: mReferenceables.load (*mReader, mBase, UniversalId::Type_Container); break;
|
||||||
|
case ESM::REC_CREA: mReferenceables.load (*mReader, mBase, UniversalId::Type_Creature); break;
|
||||||
|
case ESM::REC_DOOR: mReferenceables.load (*mReader, mBase, UniversalId::Type_Door); break;
|
||||||
|
case ESM::REC_INGR: mReferenceables.load (*mReader, mBase, UniversalId::Type_Ingredient); break;
|
||||||
|
case ESM::REC_LEVC:
|
||||||
|
mReferenceables.load (*mReader, mBase, UniversalId::Type_CreatureLevelledList); break;
|
||||||
|
case ESM::REC_LEVI:
|
||||||
|
mReferenceables.load (*mReader, mBase, UniversalId::Type_ItemLevelledList); break;
|
||||||
|
case ESM::REC_LIGH: mReferenceables.load (*mReader, mBase, UniversalId::Type_Light); break;
|
||||||
|
case ESM::REC_LOCK: mReferenceables.load (*mReader, mBase, UniversalId::Type_Lockpick); break;
|
||||||
|
case ESM::REC_MISC:
|
||||||
|
mReferenceables.load (*mReader, mBase, UniversalId::Type_Miscellaneous); break;
|
||||||
|
case ESM::REC_NPC_: mReferenceables.load (*mReader, mBase, UniversalId::Type_Npc); break;
|
||||||
|
case ESM::REC_PROB: mReferenceables.load (*mReader, mBase, UniversalId::Type_Probe); break;
|
||||||
|
case ESM::REC_REPA: mReferenceables.load (*mReader, mBase, UniversalId::Type_Repair); break;
|
||||||
|
case ESM::REC_STAT: mReferenceables.load (*mReader, mBase, UniversalId::Type_Static); break;
|
||||||
|
case ESM::REC_WEAP: mReferenceables.load (*mReader, mBase, UniversalId::Type_Weapon); break;
|
||||||
|
|
||||||
|
case ESM::REC_DIAL:
|
||||||
|
{
|
||||||
|
std::string id = mReader->getHNOString ("NAME");
|
||||||
|
|
||||||
|
ESM::Dialogue record;
|
||||||
|
record.mId = id;
|
||||||
|
record.load (*mReader);
|
||||||
|
|
||||||
|
if (record.mType==ESM::Dialogue::Journal)
|
||||||
|
{
|
||||||
|
mJournals.load (record, mBase);
|
||||||
|
mDialogue = &mJournals.getRecord (id).get();
|
||||||
|
}
|
||||||
|
else if (record.mType==ESM::Dialogue::Deleted)
|
||||||
|
{
|
||||||
|
mDialogue = 0; // record vector can be shuffled around which would make pointer
|
||||||
|
// to record invalid
|
||||||
|
|
||||||
|
if (mJournals.tryDelete (id))
|
||||||
|
{
|
||||||
|
/// \todo handle info records
|
||||||
|
}
|
||||||
|
else if (mTopics.tryDelete (id))
|
||||||
|
{
|
||||||
|
/// \todo handle info records
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
messages.push_back (std::make_pair (UniversalId::Type_None,
|
||||||
|
"Trying to delete dialogue record " + id + " which does not exist"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mTopics.load (record, mBase);
|
||||||
|
mDialogue = &mTopics.getRecord (id).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ESM::REC_INFO:
|
||||||
|
{
|
||||||
|
if (!mDialogue)
|
||||||
|
{
|
||||||
|
messages.push_back (std::make_pair (UniversalId::Type_None,
|
||||||
|
"Found info record not following a dialogue record"));
|
||||||
|
|
||||||
|
mReader->skipRecord();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mDialogue->mType==ESM::Dialogue::Journal)
|
||||||
|
mJournalInfos.load (*mReader, mBase, *mDialogue);
|
||||||
|
else
|
||||||
|
mTopicInfos.load (*mReader, mBase, *mDialogue);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ESM::REC_FILT:
|
||||||
|
|
||||||
|
if (mProject)
|
||||||
|
{
|
||||||
|
mFilters.load (*mReader, mBase);
|
||||||
|
mFilters.setData (mFilters.getSize()-1,
|
||||||
|
mFilters.findColumnIndex (CSMWorld::Columns::ColumnId_Scope),
|
||||||
|
static_cast<int> (CSMFilter::Filter::Scope_Project));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fall through (filter record in a content file is an error with format 0)
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
messages.push_back (std::make_pair (UniversalId::Type_None,
|
||||||
|
"Unsupported record type: " + n.toString()));
|
||||||
|
|
||||||
|
mReader->skipRecord();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSMWorld::Data::hasId (const std::string& id) const
|
bool CSMWorld::Data::hasId (const std::string& id) const
|
||||||
|
@ -22,8 +22,12 @@
|
|||||||
#include <components/esm/loadspel.hpp>
|
#include <components/esm/loadspel.hpp>
|
||||||
#include <components/esm/loaddial.hpp>
|
#include <components/esm/loaddial.hpp>
|
||||||
|
|
||||||
|
#include <components/to_utf8/to_utf8.hpp>
|
||||||
|
|
||||||
#include "../filter/filter.hpp"
|
#include "../filter/filter.hpp"
|
||||||
|
|
||||||
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
#include "idcollection.hpp"
|
#include "idcollection.hpp"
|
||||||
#include "universalid.hpp"
|
#include "universalid.hpp"
|
||||||
#include "cell.hpp"
|
#include "cell.hpp"
|
||||||
@ -33,12 +37,19 @@
|
|||||||
|
|
||||||
class QAbstractItemModel;
|
class QAbstractItemModel;
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
class ESMReader;
|
||||||
|
struct Dialogue;
|
||||||
|
}
|
||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
class Data : public QObject
|
class Data : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
ToUTF8::Utf8Encoder mEncoder;
|
||||||
IdCollection<ESM::Global> mGlobals;
|
IdCollection<ESM::Global> mGlobals;
|
||||||
IdCollection<ESM::GameSetting> mGmsts;
|
IdCollection<ESM::GameSetting> mGmsts;
|
||||||
IdCollection<ESM::Skill> mSkills;
|
IdCollection<ESM::Skill> mSkills;
|
||||||
@ -62,13 +73,18 @@ namespace CSMWorld
|
|||||||
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
|
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
|
||||||
std::string mAuthor;
|
std::string mAuthor;
|
||||||
std::string mDescription;
|
std::string mDescription;
|
||||||
|
ESM::ESMReader *mReader;
|
||||||
|
const ESM::Dialogue *mDialogue; // last loaded dialogue
|
||||||
|
bool mBase;
|
||||||
|
bool mProject;
|
||||||
|
std::map<std::string, std::map<ESM::RefNum, std::string> > mRefLoadCache;
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
Data (const Data&);
|
Data (const Data&);
|
||||||
Data& operator= (const Data&);
|
Data& operator= (const Data&);
|
||||||
|
|
||||||
void addModel (QAbstractItemModel *model, UniversalId::Type type1,
|
void addModel (QAbstractItemModel *model, UniversalId::Type type,
|
||||||
UniversalId::Type type2 = UniversalId::Type_None, bool update = true);
|
bool update = true);
|
||||||
|
|
||||||
static void appendIds (std::vector<std::string>& ids, const CollectionBase& collection,
|
static void appendIds (std::vector<std::string>& ids, const CollectionBase& collection,
|
||||||
bool listDeleted);
|
bool listDeleted);
|
||||||
@ -78,7 +94,7 @@ namespace CSMWorld
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Data();
|
Data (ToUTF8::FromType encoding);
|
||||||
|
|
||||||
virtual ~Data();
|
virtual ~Data();
|
||||||
|
|
||||||
@ -167,10 +183,15 @@ namespace CSMWorld
|
|||||||
void merge();
|
void merge();
|
||||||
///< Merge modified into base.
|
///< Merge modified into base.
|
||||||
|
|
||||||
void loadFile (const boost::filesystem::path& path, bool base, bool project);
|
int startLoading (const boost::filesystem::path& path, bool base, bool project);
|
||||||
///< Merging content of a file into base or modified.
|
///< Begin merging content of a file into base or modified.
|
||||||
///
|
///
|
||||||
/// \param project load project file instead of content file
|
/// \param project load project file instead of content file
|
||||||
|
///
|
||||||
|
///< \return estimated number of records
|
||||||
|
|
||||||
|
bool continueLoading (CSMDoc::Stage::Messages& messages);
|
||||||
|
///< \return Finished?
|
||||||
|
|
||||||
bool hasId (const std::string& id) const;
|
bool hasId (const std::string& id) const;
|
||||||
|
|
||||||
|
@ -6,9 +6,8 @@
|
|||||||
#include "collectionbase.hpp"
|
#include "collectionbase.hpp"
|
||||||
#include "columnbase.hpp"
|
#include "columnbase.hpp"
|
||||||
|
|
||||||
CSMWorld::IdTable::IdTable (CollectionBase *idCollection, Reordering reordering,
|
CSMWorld::IdTable::IdTable (CollectionBase *idCollection, unsigned int features)
|
||||||
Viewing viewing, bool preview)
|
: mIdCollection (idCollection), mFeatures (features)
|
||||||
: mIdCollection (idCollection), mReordering (reordering), mViewing (viewing), mPreview (preview)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
CSMWorld::IdTable::~IdTable()
|
CSMWorld::IdTable::~IdTable()
|
||||||
@ -18,10 +17,10 @@ int CSMWorld::IdTable::rowCount (const QModelIndex & parent) const
|
|||||||
{
|
{
|
||||||
if (hasChildren(parent))
|
if (hasChildren(parent))
|
||||||
{
|
{
|
||||||
int nestedRows = mIdCollection->getNestedRowsCount(parent.row(), parent.column());
|
int nestedRows = mIdCollection->getNestedRowsCount(parent.row(), parent.column());
|
||||||
return nestedRows;
|
return nestedRows;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mIdCollection->getSize();
|
return mIdCollection->getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,7 +28,7 @@ int CSMWorld::IdTable::columnCount (const QModelIndex & parent) const
|
|||||||
{
|
{
|
||||||
if (parent.isValid())
|
if (parent.isValid())
|
||||||
{
|
{
|
||||||
return mIdCollection->getNestedColumnsCount(parent.row(), parent.column());
|
return mIdCollection->getNestedColumnsCount(parent.row(), parent.column());
|
||||||
}
|
}
|
||||||
|
|
||||||
return mIdCollection->getColumns();
|
return mIdCollection->getColumns();
|
||||||
@ -46,7 +45,7 @@ QVariant CSMWorld::IdTable::data (const QModelIndex & index, int role) const
|
|||||||
if (index.internalId() != 0)
|
if (index.internalId() != 0)
|
||||||
{
|
{
|
||||||
std::pair<int, int> parentAdress(unfoldIndexAdress(index.internalId()));
|
std::pair<int, int> parentAdress(unfoldIndexAdress(index.internalId()));
|
||||||
return mIdCollection->getNestedData(parentAdress.first, parentAdress.second, index.row(), index.column());
|
return mIdCollection->getNestedData(index.row(), index.column(), parentAdress.first, parentAdress.second);
|
||||||
} else {
|
} else {
|
||||||
return mIdCollection->getData (index.row(), index.column());
|
return mIdCollection->getData (index.row(), index.column());
|
||||||
}
|
}
|
||||||
@ -117,8 +116,11 @@ bool CSMWorld::IdTable::removeRows (int row, int count, const QModelIndex& paren
|
|||||||
|
|
||||||
QModelIndex CSMWorld::IdTable::index (int row, int column, const QModelIndex& parent) const
|
QModelIndex CSMWorld::IdTable::index (int row, int column, const QModelIndex& parent) const
|
||||||
{
|
{
|
||||||
|
unsigned int encodedId = 0;
|
||||||
if (parent.isValid())
|
if (parent.isValid())
|
||||||
return QModelIndex();
|
{
|
||||||
|
encodedId = this->foldIndexAdress(parent);
|
||||||
|
}
|
||||||
|
|
||||||
if (row<0 || row>=mIdCollection->getSize())
|
if (row<0 || row>=mIdCollection->getSize())
|
||||||
return QModelIndex();
|
return QModelIndex();
|
||||||
@ -126,7 +128,7 @@ QModelIndex CSMWorld::IdTable::index (int row, int column, const QModelIndex& pa
|
|||||||
if (column<0 || column>=mIdCollection->getColumns())
|
if (column<0 || column>=mIdCollection->getColumns())
|
||||||
return QModelIndex();
|
return QModelIndex();
|
||||||
|
|
||||||
return createIndex (row, column);
|
return createIndex(row, column, encodedId);
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex CSMWorld::IdTable::parent (const QModelIndex& index) const
|
QModelIndex CSMWorld::IdTable::parent (const QModelIndex& index) const
|
||||||
@ -136,14 +138,14 @@ QModelIndex CSMWorld::IdTable::parent (const QModelIndex& index) const
|
|||||||
return QModelIndex();
|
return QModelIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::pair<int, int>& adress(unfoldIndexAdress(index.internalId()));
|
unsigned int id = index.internalId();
|
||||||
|
const std::pair<int, int>& adress(unfoldIndexAdress(id));
|
||||||
|
|
||||||
if (adress.first >= this->rowCount() || adress.second >= this->columnCount())
|
if (adress.first >= this->rowCount() || adress.second >= this->columnCount())
|
||||||
{
|
{
|
||||||
qDebug()<<"Parent index is not present in the model";
|
|
||||||
throw "Parent index is not present in the model";
|
throw "Parent index is not present in the model";
|
||||||
}
|
}
|
||||||
return createIndex(adress.first, adress.second, 0);
|
return createIndex(adress.first, adress.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMWorld::IdTable::addRecord (const std::string& id, UniversalId::Type type)
|
void CSMWorld::IdTable::addRecord (const std::string& id, UniversalId::Type type)
|
||||||
@ -162,15 +164,16 @@ void CSMWorld::IdTable::cloneRecord(const std::string& origin,
|
|||||||
CSMWorld::UniversalId::Type type)
|
CSMWorld::UniversalId::Type type)
|
||||||
{
|
{
|
||||||
int index = mIdCollection->getAppendIndex (destination);
|
int index = mIdCollection->getAppendIndex (destination);
|
||||||
|
|
||||||
beginInsertRows (QModelIndex(), index, index);
|
beginInsertRows (QModelIndex(), index, index);
|
||||||
mIdCollection->cloneRecord(origin, destination, type);
|
mIdCollection->cloneRecord(origin, destination, type);
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///This method can return only indexes to the top level table cells
|
||||||
QModelIndex CSMWorld::IdTable::getModelIndex (const std::string& id, int column) const
|
QModelIndex CSMWorld::IdTable::getModelIndex (const std::string& id, int column) const
|
||||||
{
|
{
|
||||||
return index (mIdCollection->getIndex (id), column);
|
return index(mIdCollection->getIndex (id), column);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMWorld::IdTable::setRecord (const std::string& id, const RecordBase& record)
|
void CSMWorld::IdTable::setRecord (const std::string& id, const RecordBase& record)
|
||||||
@ -218,19 +221,9 @@ void CSMWorld::IdTable::reorderRows (int baseIndex, const std::vector<int>& newO
|
|||||||
index (baseIndex+newOrder.size()-1, mIdCollection->getColumns()-1));
|
index (baseIndex+newOrder.size()-1, mIdCollection->getColumns()-1));
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::IdTable::Reordering CSMWorld::IdTable::getReordering() const
|
unsigned int CSMWorld::IdTable::getFeatures() const
|
||||||
{
|
{
|
||||||
return mReordering;
|
return mFeatures;
|
||||||
}
|
|
||||||
|
|
||||||
CSMWorld::IdTable::Viewing CSMWorld::IdTable::getViewing() const
|
|
||||||
{
|
|
||||||
return mViewing;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSMWorld::IdTable::hasPreview() const
|
|
||||||
{
|
|
||||||
return mPreview;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row) const
|
std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row) const
|
||||||
@ -238,7 +231,7 @@ std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row)
|
|||||||
std::string id;
|
std::string id;
|
||||||
std::string hint;
|
std::string hint;
|
||||||
|
|
||||||
if (mViewing==Viewing_Cell)
|
if (mFeatures & Feature_ViewCell)
|
||||||
{
|
{
|
||||||
int cellColumn = mIdCollection->searchColumnIndex (Columns::ColumnId_Cell);
|
int cellColumn = mIdCollection->searchColumnIndex (Columns::ColumnId_Cell);
|
||||||
int idColumn = mIdCollection->searchColumnIndex (Columns::ColumnId_Id);
|
int idColumn = mIdCollection->searchColumnIndex (Columns::ColumnId_Id);
|
||||||
@ -249,7 +242,7 @@ std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row)
|
|||||||
hint = "r:" + std::string (mIdCollection->getData (row, idColumn).toString().toUtf8().constData());
|
hint = "r:" + std::string (mIdCollection->getData (row, idColumn).toString().toUtf8().constData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (mViewing==Viewing_Id)
|
else if (mFeatures & Feature_ViewId)
|
||||||
{
|
{
|
||||||
int column = mIdCollection->searchColumnIndex (Columns::ColumnId_Id);
|
int column = mIdCollection->searchColumnIndex (Columns::ColumnId_Id);
|
||||||
|
|
||||||
@ -269,31 +262,23 @@ std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view (int row)
|
|||||||
return std::make_pair (UniversalId (UniversalId::Type_Scene, id), hint);
|
return std::make_pair (UniversalId (UniversalId::Type_Scene, id), hint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///For top level data/columns
|
||||||
int CSMWorld::IdTable::getColumnId(int column) const
|
int CSMWorld::IdTable::getColumnId(int column) const
|
||||||
{
|
{
|
||||||
return mIdCollection->getColumn(column).getId();
|
return mIdCollection->getColumn(column).getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CSMWorld::IdTable::hasChildren(const QModelIndex& index) const
|
|
||||||
{
|
|
||||||
return (index.isValid() &&
|
|
||||||
mIdCollection->getColumn (index.column()).mDisplayType == ColumnBase::Display_Nested &&
|
|
||||||
index.data().isValid());
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int CSMWorld::IdTable::foldIndexAdress (const QModelIndex& index) const
|
unsigned int CSMWorld::IdTable::foldIndexAdress (const QModelIndex& index) const
|
||||||
{
|
{
|
||||||
unsigned int out = index.row() * this->columnCount();
|
unsigned int out = index.row() * this->columnCount();
|
||||||
out += index.column();
|
out += index.column();
|
||||||
++out;
|
return ++out;
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair< int, int > CSMWorld::IdTable::unfoldIndexAdress (unsigned int id) const
|
std::pair< int, int > CSMWorld::IdTable::unfoldIndexAdress (unsigned int id) const
|
||||||
{
|
{
|
||||||
if (id == 0)
|
if (id == 0)
|
||||||
{
|
{
|
||||||
qDebug()<<"Attempt to unfold index id of the top level data cell";
|
|
||||||
throw "Attempt to unfold index id of the top level data cell";
|
throw "Attempt to unfold index id of the top level data cell";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,19 +8,15 @@
|
|||||||
#include "universalid.hpp"
|
#include "universalid.hpp"
|
||||||
#include "columns.hpp"
|
#include "columns.hpp"
|
||||||
|
|
||||||
<<<<<<< Updated upstream
|
|
||||||
=======
|
|
||||||
/*! \brief
|
/*! \brief
|
||||||
* Clas for holding the model. Uses typical qt table abstraction/interface for granting access to the individiual fields of the records,
|
* Clas for holding the model. Uses typical qt table abstraction/interface for granting access to the individiual fields of the records,
|
||||||
* Some records are holding nested data (for instance inventory list of the npc). In casses like this, table model offers interface
|
* Some records are holding nested data (for instance inventory list of the npc). In casses like this, table model offers interface
|
||||||
* to access nested data in the qt way – that is specify parent. The parent is encoded in the internalid of the index model
|
* to access nested data in the qt way – that is specify parent. Since some of those nested data require multiple columns to
|
||||||
* See methods fold and unfold adress to see why. This approach has some serious limitations: it allows only
|
* represent informations, single int (default way to index model in the qmodelindex) is not sufficiant. Therefore tablemodelindex class
|
||||||
* a single level of the nesting. At the point of creating this code this seemed to be a good enough solution.
|
* can hold two ints for the sake of indexing two dimensions of the table. This model does not support multiple levels of the nested
|
||||||
* If for some reason it turned out that in fact multiple levels of nesting are needed, change in the addressing of the
|
* data. Vast majority of methods makes sense only for the top level data.
|
||||||
* index is most likely the very first to be considered.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
>>>>>>> Stashed changes
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
class CollectionBase;
|
class CollectionBase;
|
||||||
@ -32,43 +28,38 @@ namespace CSMWorld
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum Reordering
|
enum Features
|
||||||
{
|
{
|
||||||
Reordering_None,
|
Feature_ReorderWithinTopic = 1,
|
||||||
Reordering_WithinTopic
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Viewing
|
/// Use ID column to generate view request (ID is transformed into
|
||||||
{
|
/// worldspace and original ID is passed as hint with c: prefix).
|
||||||
Viewing_None,
|
Feature_ViewId = 2,
|
||||||
Viewing_Id, // use ID column to generate view request (ID is transformed into
|
|
||||||
// worldspace and original ID is passed as hint with c: prefix)
|
/// Use cell column to generate view request (cell ID is transformed
|
||||||
Viewing_Cell // use cell column to generate view request (cell ID is transformed
|
/// into worldspace and record ID is passed as hint with r: prefix).
|
||||||
// into worldspace and record ID is passed as hint with r: prefix)
|
Feature_ViewCell = 4,
|
||||||
|
|
||||||
|
Feature_View = Feature_ViewId | Feature_ViewCell,
|
||||||
|
|
||||||
|
Feature_Preview = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
CollectionBase *mIdCollection;
|
CollectionBase *mIdCollection;
|
||||||
Reordering mReordering;
|
unsigned int mFeatures;
|
||||||
Viewing mViewing;
|
|
||||||
bool mPreview;
|
bool mPreview;
|
||||||
|
|
||||||
// not implemented
|
// not implemented
|
||||||
IdTable (const IdTable&);
|
IdTable (const IdTable&);
|
||||||
IdTable& operator= (const IdTable&);
|
IdTable& operator= (const IdTable&);
|
||||||
<<<<<<< Updated upstream
|
|
||||||
=======
|
|
||||||
|
|
||||||
unsigned int foldIndexAdress(const QModelIndex& index) const;
|
unsigned int foldIndexAdress(const QModelIndex& index) const;
|
||||||
|
|
||||||
std::pair<int, int> unfoldIndexAdress(unsigned int id) const;
|
std::pair<int, int> unfoldIndexAdress(unsigned int id) const;
|
||||||
>>>>>>> Stashed changes
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
IdTable (CollectionBase *idCollection, Reordering reordering = Reordering_None,
|
IdTable (CollectionBase *idCollection, unsigned int features = 0);
|
||||||
Viewing viewing = Viewing_None, bool preview = false);
|
|
||||||
///< The ownership of \a idCollection is not transferred.
|
///< The ownership of \a idCollection is not transferred.
|
||||||
|
|
||||||
virtual ~IdTable();
|
virtual ~IdTable();
|
||||||
@ -91,8 +82,8 @@ namespace CSMWorld
|
|||||||
const;
|
const;
|
||||||
|
|
||||||
virtual QModelIndex parent (const QModelIndex& index) const;
|
virtual QModelIndex parent (const QModelIndex& index) const;
|
||||||
|
|
||||||
virtual bool hasChildren (const QModelIndex& index) const;
|
virtual bool hasChildren (const QModelIndex& index) const;
|
||||||
|
|
||||||
void addRecord (const std::string& id, UniversalId::Type type = UniversalId::Type_None);
|
void addRecord (const std::string& id, UniversalId::Type type = UniversalId::Type_None);
|
||||||
///< \param type Will be ignored, unless the collection supports multiple record types
|
///< \param type Will be ignored, unless the collection supports multiple record types
|
||||||
@ -119,11 +110,7 @@ namespace CSMWorld
|
|||||||
///< Reorder the rows [baseIndex, baseIndex+newOrder.size()) according to the indices
|
///< Reorder the rows [baseIndex, baseIndex+newOrder.size()) according to the indices
|
||||||
/// given in \a newOrder (baseIndex+newOrder[0] specifies the new index of row baseIndex).
|
/// given in \a newOrder (baseIndex+newOrder[0] specifies the new index of row baseIndex).
|
||||||
|
|
||||||
Reordering getReordering() const;
|
unsigned int getFeatures() const;
|
||||||
|
|
||||||
Viewing getViewing() const;
|
|
||||||
|
|
||||||
bool hasPreview() const;
|
|
||||||
|
|
||||||
std::pair<UniversalId, std::string> view (int row) const;
|
std::pair<UniversalId, std::string> view (int row) const;
|
||||||
///< Return the UniversalId and the hint for viewing \a row. If viewing is not
|
///< Return the UniversalId and the hint for viewing \a row. If viewing is not
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
|
|
||||||
#include "ref.hpp"
|
#include "ref.hpp"
|
||||||
|
|
||||||
#include "cell.hpp"
|
CSMWorld::CellRef::CellRef()
|
||||||
|
|
||||||
void CSMWorld::CellRef::load (ESM::ESMReader &esm, Cell& cell, const std::string& id)
|
|
||||||
{
|
{
|
||||||
mId = id;
|
mRefNum.mIndex = 0;
|
||||||
mCell = cell.mId;
|
|
||||||
|
|
||||||
cell.addRef (mId);
|
// special marker: This reference does not have a RefNum assign to it yet.
|
||||||
|
mRefNum.mContentFile = -2;
|
||||||
}
|
}
|
@ -3,11 +3,6 @@
|
|||||||
|
|
||||||
#include <components/esm/cellref.hpp>
|
#include <components/esm/cellref.hpp>
|
||||||
|
|
||||||
namespace ESM
|
|
||||||
{
|
|
||||||
class ESMReader;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
class Cell;
|
class Cell;
|
||||||
@ -18,8 +13,7 @@ namespace CSMWorld
|
|||||||
std::string mId;
|
std::string mId;
|
||||||
std::string mCell;
|
std::string mCell;
|
||||||
|
|
||||||
void load (ESM::ESMReader &esm, Cell& cell, const std::string& id);
|
CellRef();
|
||||||
///< Load cell ref and register it with \a cell.
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,12 +3,15 @@
|
|||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
#include "ref.hpp"
|
#include "ref.hpp"
|
||||||
#include "cell.hpp"
|
#include "cell.hpp"
|
||||||
#include "universalid.hpp"
|
#include "universalid.hpp"
|
||||||
#include "record.hpp"
|
#include "record.hpp"
|
||||||
|
|
||||||
void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool base)
|
void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool base,
|
||||||
|
std::map<ESM::RefNum, std::string>& cache, CSMDoc::Stage::Messages& messages)
|
||||||
{
|
{
|
||||||
Record<Cell> cell = mCells.getRecord (cellIndex);
|
Record<Cell> cell = mCells.getRecord (cellIndex);
|
||||||
|
|
||||||
@ -17,19 +20,73 @@ void CSMWorld::RefCollection::load (ESM::ESMReader& reader, int cellIndex, bool
|
|||||||
CellRef ref;
|
CellRef ref;
|
||||||
|
|
||||||
bool deleted = false;
|
bool deleted = false;
|
||||||
while (cell2.getNextRef (reader, ref, deleted))
|
|
||||||
|
while (ESM::Cell::getNextRef (reader, ref, deleted))
|
||||||
{
|
{
|
||||||
/// \todo handle deleted and moved references
|
ref.mCell = cell2.mId;
|
||||||
ref.load (reader, cell2, getNewId());
|
|
||||||
|
|
||||||
Record<CellRef> record2;
|
/// \todo handle moved references
|
||||||
record2.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly;
|
|
||||||
(base ? record2.mBase : record2.mModified) = ref;
|
|
||||||
|
|
||||||
appendRecord (record2);
|
std::map<ESM::RefNum, std::string>::iterator iter = cache.find (ref.mRefNum);
|
||||||
|
|
||||||
|
if (deleted)
|
||||||
|
{
|
||||||
|
if (iter==cache.end())
|
||||||
|
{
|
||||||
|
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Cell,
|
||||||
|
mCells.getId (cellIndex));
|
||||||
|
|
||||||
|
messages.push_back (std::make_pair (id,
|
||||||
|
"Attempt to delete a non-existing reference"));
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = getIndex (iter->second);
|
||||||
|
|
||||||
|
Record<CellRef> record = getRecord (index);
|
||||||
|
|
||||||
|
if (record.mState==RecordBase::State_BaseOnly)
|
||||||
|
{
|
||||||
|
removeRows (index, 1);
|
||||||
|
cache.erase (iter);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
record.mState = RecordBase::State_Deleted;
|
||||||
|
setRecord (index, record);
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iter==cache.end())
|
||||||
|
{
|
||||||
|
// new reference
|
||||||
|
ref.mId = getNewId();
|
||||||
|
|
||||||
|
Record<CellRef> record;
|
||||||
|
record.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly;
|
||||||
|
(base ? record.mBase : record.mModified) = ref;
|
||||||
|
|
||||||
|
appendRecord (record);
|
||||||
|
|
||||||
|
cache.insert (std::make_pair (ref.mRefNum, ref.mId));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// old reference -> merge
|
||||||
|
ref.mId = iter->second;
|
||||||
|
|
||||||
|
int index = getIndex (ref.mId);
|
||||||
|
|
||||||
|
Record<CellRef> record = getRecord (index);
|
||||||
|
record.mState = base ? RecordBase::State_BaseOnly : RecordBase::State_Modified;
|
||||||
|
(base ? record.mBase : record.mModified) = ref;
|
||||||
|
|
||||||
|
setRecord (index, record);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mCells.setRecord (cellIndex, cell);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CSMWorld::RefCollection::getNewId()
|
std::string CSMWorld::RefCollection::getNewId()
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
#ifndef CSM_WOLRD_REFCOLLECTION_H
|
#ifndef CSM_WOLRD_REFCOLLECTION_H
|
||||||
#define CSM_WOLRD_REFCOLLECTION_H
|
#define CSM_WOLRD_REFCOLLECTION_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "../doc/stage.hpp"
|
||||||
|
|
||||||
#include "collection.hpp"
|
#include "collection.hpp"
|
||||||
#include "ref.hpp"
|
#include "ref.hpp"
|
||||||
#include "record.hpp"
|
#include "record.hpp"
|
||||||
@ -22,7 +26,9 @@ namespace CSMWorld
|
|||||||
: mCells (cells), mNextId (0)
|
: mCells (cells), mNextId (0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void load (ESM::ESMReader& reader, int cellIndex, bool base);
|
void load (ESM::ESMReader& reader, int cellIndex, bool base,
|
||||||
|
std::map<ESM::RefNum, std::string>& cache,
|
||||||
|
CSMDoc::Stage::Messages& messages);
|
||||||
///< Load a sequence of references.
|
///< Load a sequence of references.
|
||||||
|
|
||||||
std::string getNewId();
|
std::string getNewId();
|
||||||
|
@ -1,14 +1,13 @@
|
|||||||
|
|
||||||
#include "refidadapter.hpp"
|
#include "refidadapter.hpp"
|
||||||
|
|
||||||
|
#include "cassert"
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
CSMWorld::RefIdAdapter::RefIdAdapter() {}
|
CSMWorld::RefIdAdapter::RefIdAdapter() {}
|
||||||
|
|
||||||
<<<<<<< Updated upstream
|
|
||||||
CSMWorld::RefIdAdapter::~RefIdAdapter() {}
|
|
||||||
=======
|
|
||||||
CSMWorld::RefIdAdapter::~RefIdAdapter() {}
|
CSMWorld::RefIdAdapter::~RefIdAdapter() {}
|
||||||
|
|
||||||
CSMWorld::NestedRefIdAdapter::NestedRefIdAdapter() {}
|
CSMWorld::NestedRefIdAdapter::NestedRefIdAdapter() {}
|
||||||
|
|
||||||
CSMWorld::NestedRefIdAdapter::~NestedRefIdAdapter() {}
|
CSMWorld::NestedRefIdAdapter::~NestedRefIdAdapter() {}
|
||||||
>>>>>>> Stashed changes
|
|
@ -30,6 +30,13 @@ namespace CSMWorld
|
|||||||
const QVariant& value) const = 0;
|
const QVariant& value) const = 0;
|
||||||
///< If the data type does not match an exception is thrown.
|
///< If the data type does not match an exception is thrown.
|
||||||
|
|
||||||
|
virtual QVariant getNestedData (const RefIdColumn *column, const RefIdData& data,
|
||||||
|
int idnex, int subRowIndex, int subColIndex) const;
|
||||||
|
|
||||||
|
virtual void setNestedData (const RefIdColumn *column, RefIdData& data,
|
||||||
|
const QVariant& value, int index,
|
||||||
|
int subRowIndex, int subColIndex) const;
|
||||||
|
|
||||||
virtual std::string getId (const RecordBase& record) const = 0;
|
virtual std::string getId (const RecordBase& record) const = 0;
|
||||||
|
|
||||||
virtual void setId(RecordBase& record, const std::string& id) = 0;
|
virtual void setId(RecordBase& record, const std::string& id) = 0;
|
||||||
@ -43,15 +50,14 @@ namespace CSMWorld
|
|||||||
virtual ~NestedRefIdAdapter();
|
virtual ~NestedRefIdAdapter();
|
||||||
|
|
||||||
virtual void setNestedData (const RefIdColumn *column, RefIdData& data, int row,
|
virtual void setNestedData (const RefIdColumn *column, RefIdData& data, int row,
|
||||||
const QVariant& value, int subRowIndex, int subColIndex) const = 0;
|
const QVariant& value, int subRowIndex, int subColIndex) const = 0;
|
||||||
|
|
||||||
virtual QVariant getNestedData (const RefIdColumn *column, const RefIdData& data,
|
virtual QVariant getNestedData (const RefIdColumn *column, const RefIdData& data,
|
||||||
int index, int subRowIndex, int subColIndex) const = 0;
|
int index, int subRowIndex, int subColIndex) const = 0;
|
||||||
|
|
||||||
|
|
||||||
virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const = 0;
|
|
||||||
|
|
||||||
virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const = 0;
|
virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const = 0;
|
||||||
|
|
||||||
|
virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,9 +175,9 @@ void CSMWorld::ClothingRefIdAdapter::setData (const RefIdColumn *column, RefIdDa
|
|||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::ContainerRefIdAdapter::ContainerRefIdAdapter (const NameColumns& columns,
|
CSMWorld::ContainerRefIdAdapter::ContainerRefIdAdapter (const NameColumns& columns,
|
||||||
const RefIdColumn *weight, const RefIdColumn *organic, const RefIdColumn *respawn)
|
const RefIdColumn *weight, const RefIdColumn *organic, const RefIdColumn *respawn, const RefIdColumn *content)
|
||||||
: NameRefIdAdapter<ESM::Container> (UniversalId::Type_Container, columns), mWeight (weight),
|
: NameRefIdAdapter<ESM::Container> (UniversalId::Type_Container, columns), mWeight (weight),
|
||||||
mOrganic (organic), mRespawn (respawn)
|
mOrganic (organic), mRespawn (respawn), mContent(content)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
int CSMWorld::ContainerRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const
|
int CSMWorld::ContainerRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const
|
||||||
@ -220,7 +220,7 @@ QVariant CSMWorld::ContainerRefIdAdapter::getData (const RefIdColumn *column, co
|
|||||||
|
|
||||||
if (column==mRespawn)
|
if (column==mRespawn)
|
||||||
return (record.get().mFlags & ESM::Container::Respawn)!=0;
|
return (record.get().mFlags & ESM::Container::Respawn)!=0;
|
||||||
|
|
||||||
if (column==mContent)
|
if (column==mContent)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -253,16 +253,14 @@ void CSMWorld::ContainerRefIdAdapter::setData (const RefIdColumn *column, RefIdD
|
|||||||
NameRefIdAdapter<ESM::Container>::setData (column, data, index, value);
|
NameRefIdAdapter<ESM::Container>::setData (column, data, index, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
<<<<<<< Updated upstream
|
|
||||||
=======
|
|
||||||
void CSMWorld::ContainerRefIdAdapter::setNestedData(const RefIdColumn *column, RefIdData& data,
|
void CSMWorld::ContainerRefIdAdapter::setNestedData(const RefIdColumn *column, RefIdData& data,
|
||||||
int row,
|
int index,
|
||||||
const QVariant& value,
|
const QVariant& value,
|
||||||
int subRowIndex,
|
int subRowIndex,
|
||||||
int subColIndex) const
|
int subColIndex) const
|
||||||
{
|
{
|
||||||
Record<ESM::Container>& record = static_cast<Record<ESM::Container>&> (
|
Record<ESM::Container>& record = static_cast<Record<ESM::Container>&> (
|
||||||
data.getRecord (RefIdData::LocalIndex (row, UniversalId::Type_Container)));
|
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Container)));
|
||||||
|
|
||||||
if (column==mContent)
|
if (column==mContent)
|
||||||
{
|
{
|
||||||
@ -286,12 +284,11 @@ void CSMWorld::ContainerRefIdAdapter::setNestedData(const RefIdColumn *column, R
|
|||||||
}
|
}
|
||||||
|
|
||||||
QVariant CSMWorld::ContainerRefIdAdapter::getNestedData (const CSMWorld::RefIdColumn* column,
|
QVariant CSMWorld::ContainerRefIdAdapter::getNestedData (const CSMWorld::RefIdColumn* column,
|
||||||
const CSMWorld::RefIdData& data,
|
const CSMWorld::RefIdData& data,
|
||||||
int index,
|
int index,
|
||||||
int subRowIndex,
|
int subRowIndex,
|
||||||
int subColIndex) const
|
int subColIndex) const
|
||||||
{
|
{
|
||||||
qDebug()<<"Accessing content column";
|
|
||||||
const Record<ESM::Container>& record = static_cast<const Record<ESM::Container>&> (
|
const Record<ESM::Container>& record = static_cast<const Record<ESM::Container>&> (
|
||||||
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Container)));
|
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Container)));
|
||||||
|
|
||||||
@ -317,7 +314,6 @@ QVariant CSMWorld::ContainerRefIdAdapter::getNestedData (const CSMWorld::RefIdCo
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
>>>>>>> Stashed changes
|
|
||||||
CSMWorld::CreatureColumns::CreatureColumns (const ActorColumns& actorColumns)
|
CSMWorld::CreatureColumns::CreatureColumns (const ActorColumns& actorColumns)
|
||||||
: ActorColumns (actorColumns)
|
: ActorColumns (actorColumns)
|
||||||
{}
|
{}
|
||||||
|
@ -35,7 +35,7 @@ namespace CSMWorld
|
|||||||
BaseRefIdAdapter (UniversalId::Type type, const BaseColumns& base);
|
BaseRefIdAdapter (UniversalId::Type type, const BaseColumns& base);
|
||||||
|
|
||||||
virtual std::string getId (const RecordBase& record) const;
|
virtual std::string getId (const RecordBase& record) const;
|
||||||
|
|
||||||
virtual void setId (RecordBase& record, const std::string& id);
|
virtual void setId (RecordBase& record, const std::string& id);
|
||||||
|
|
||||||
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
|
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index)
|
||||||
@ -58,7 +58,7 @@ namespace CSMWorld
|
|||||||
{
|
{
|
||||||
(dynamic_cast<Record<RecordT>&> (record).get().mId) = id;
|
(dynamic_cast<Record<RecordT>&> (record).get().mId) = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename RecordT>
|
template<typename RecordT>
|
||||||
std::string BaseRefIdAdapter<RecordT>::getId (const RecordBase& record) const
|
std::string BaseRefIdAdapter<RecordT>::getId (const RecordBase& record) const
|
||||||
{
|
{
|
||||||
@ -611,33 +611,27 @@ namespace CSMWorld
|
|||||||
const RefIdColumn *mWeight;
|
const RefIdColumn *mWeight;
|
||||||
const RefIdColumn *mOrganic;
|
const RefIdColumn *mOrganic;
|
||||||
const RefIdColumn *mRespawn;
|
const RefIdColumn *mRespawn;
|
||||||
|
const RefIdColumn *mContent;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ContainerRefIdAdapter (const NameColumns& columns, const RefIdColumn *weight,
|
ContainerRefIdAdapter (const NameColumns& columns, const RefIdColumn *weight,
|
||||||
<<<<<<< Updated upstream
|
const RefIdColumn *organic, const RefIdColumn *respawn, const RefIdColumn *content);
|
||||||
const RefIdColumn *organic, const RefIdColumn *respawn);
|
|
||||||
=======
|
|
||||||
const RefIdColumn *organic, const RefIdColumn *respawn, const RefIdColumn *content);
|
|
||||||
|
|
||||||
virtual QVariant getNestedData (const RefIdColumn *column, const RefIdData& data,
|
virtual QVariant getNestedData (const RefIdColumn *column, const RefIdData& data, int index,
|
||||||
int index, int subRowIndex, int subColIndex) const;
|
int subRowIndex, int subColIndex) const;
|
||||||
>>>>>>> Stashed changes
|
|
||||||
|
|
||||||
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) const;
|
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data, int index) const;
|
||||||
|
|
||||||
<<<<<<< Updated upstream
|
|
||||||
=======
|
|
||||||
virtual void setNestedData (const RefIdColumn *column, RefIdData& data, int index,
|
virtual void setNestedData (const RefIdColumn *column, RefIdData& data, int index,
|
||||||
const QVariant& value, int subRowIndex, int subColIndex) const;
|
const QVariant& value, int subRowIndex, int subColIndex) const;
|
||||||
|
|
||||||
>>>>>>> Stashed changes
|
|
||||||
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
|
virtual void setData (const RefIdColumn *column, RefIdData& data, int index,
|
||||||
const QVariant& value) const;
|
const QVariant& value) const;
|
||||||
///< If the data type does not match an exception is thrown.
|
///< If the data type does not match an exception is thrown.
|
||||||
|
|
||||||
virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const;
|
virtual int getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const;
|
||||||
|
|
||||||
virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const;
|
virtual int getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -166,6 +166,9 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_Respawn, ColumnBase::Display_Boolean));
|
mColumns.push_back (RefIdColumn (Columns::ColumnId_Respawn, ColumnBase::Display_Boolean));
|
||||||
const RefIdColumn *respawn = &mColumns.back();
|
const RefIdColumn *respawn = &mColumns.back();
|
||||||
|
|
||||||
|
mColumns.push_back(RefIdColumn (Columns::ColumnId_ContainerContent, ColumnBase::Display_Nested, ColumnBase::Flag_Dialogue, false, false));
|
||||||
|
const RefIdColumn *content = &mColumns.back();
|
||||||
|
|
||||||
CreatureColumns creatureColumns (actorsColumns);
|
CreatureColumns creatureColumns (actorsColumns);
|
||||||
|
|
||||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_CreatureType, ColumnBase::Display_CreatureType));
|
mColumns.push_back (RefIdColumn (Columns::ColumnId_CreatureType, ColumnBase::Display_CreatureType));
|
||||||
@ -305,10 +308,17 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_WeaponReach, ColumnBase::Display_Float));
|
mColumns.push_back (RefIdColumn (Columns::ColumnId_WeaponReach, ColumnBase::Display_Float));
|
||||||
weaponColumns.mReach = &mColumns.back();
|
weaponColumns.mReach = &mColumns.back();
|
||||||
|
|
||||||
for (int i=0; i<6; ++i)
|
for (int i=0; i<3; ++i)
|
||||||
{
|
{
|
||||||
mColumns.push_back (RefIdColumn (Columns::ColumnId_MinChop + i, ColumnBase::Display_Integer));
|
const RefIdColumn **column =
|
||||||
weaponColumns.mChop[i] = &mColumns.back();
|
i==0 ? weaponColumns.mChop : (i==1 ? weaponColumns.mSlash : weaponColumns.mThrust);
|
||||||
|
|
||||||
|
for (int j=0; j<2; ++j)
|
||||||
|
{
|
||||||
|
mColumns.push_back (
|
||||||
|
RefIdColumn (Columns::ColumnId_MinChop+i*2+j, ColumnBase::Display_Integer));
|
||||||
|
column[j] = &mColumns.back();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct
|
static const struct
|
||||||
@ -341,7 +351,7 @@ CSMWorld::RefIdCollection::RefIdCollection()
|
|||||||
mAdapters.insert (std::make_pair (UniversalId::Type_Clothing,
|
mAdapters.insert (std::make_pair (UniversalId::Type_Clothing,
|
||||||
new ClothingRefIdAdapter (enchantableColumns, clothingType)));
|
new ClothingRefIdAdapter (enchantableColumns, clothingType)));
|
||||||
mAdapters.insert (std::make_pair (UniversalId::Type_Container,
|
mAdapters.insert (std::make_pair (UniversalId::Type_Container,
|
||||||
new ContainerRefIdAdapter (nameColumns, weightCapacity, organic, respawn)));
|
new ContainerRefIdAdapter (nameColumns, weightCapacity, organic, respawn, content)));
|
||||||
mAdapters.insert (std::make_pair (UniversalId::Type_Creature,
|
mAdapters.insert (std::make_pair (UniversalId::Type_Creature,
|
||||||
new CreatureRefIdAdapter (creatureColumns)));
|
new CreatureRefIdAdapter (creatureColumns)));
|
||||||
mAdapters.insert (std::make_pair (UniversalId::Type_Door,
|
mAdapters.insert (std::make_pair (UniversalId::Type_Door,
|
||||||
@ -417,8 +427,6 @@ QVariant CSMWorld::RefIdCollection::getData (int index, int column) const
|
|||||||
return adaptor.getData (&mColumns.at (column), mData, localIndex.first);
|
return adaptor.getData (&mColumns.at (column), mData, localIndex.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
<<<<<<< Updated upstream
|
|
||||||
=======
|
|
||||||
QVariant CSMWorld::RefIdCollection::getNestedData (int row, int column, int subRow, int subColumn) const
|
QVariant CSMWorld::RefIdCollection::getNestedData (int row, int column, int subRow, int subColumn) const
|
||||||
{
|
{
|
||||||
RefIdData::LocalIndex localIndex = mData.globalToLocalIndex(row);
|
RefIdData::LocalIndex localIndex = mData.globalToLocalIndex(row);
|
||||||
@ -429,7 +437,6 @@ QVariant CSMWorld::RefIdCollection::getNestedData (int row, int column, int subR
|
|||||||
return adaptor.getNestedData (&mColumns.at (column), mData, localIndex.first, subRow, subColumn);
|
return adaptor.getNestedData (&mColumns.at (column), mData, localIndex.first, subRow, subColumn);
|
||||||
}
|
}
|
||||||
|
|
||||||
>>>>>>> Stashed changes
|
|
||||||
void CSMWorld::RefIdCollection::setData (int index, int column, const QVariant& data)
|
void CSMWorld::RefIdCollection::setData (int index, int column, const QVariant& data)
|
||||||
{
|
{
|
||||||
RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (index);
|
RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (index);
|
||||||
|
@ -69,6 +69,8 @@ namespace CSMWorld
|
|||||||
|
|
||||||
virtual QVariant getData (int index, int column) const;
|
virtual QVariant getData (int index, int column) const;
|
||||||
|
|
||||||
|
virtual QVariant getNestedData(int row, int column, int subRow, int subColumn) const;
|
||||||
|
|
||||||
virtual void setData (int index, int column, const QVariant& data);
|
virtual void setData (int index, int column, const QVariant& data);
|
||||||
|
|
||||||
virtual void setNestedData(int row, int column, const QVariant& data, int subRow, int subColumn);
|
virtual void setNestedData(int row, int column, const QVariant& data, int subRow, int subColumn);
|
||||||
|
@ -231,27 +231,27 @@ namespace CSMWorld
|
|||||||
|
|
||||||
void save (int index, ESM::ESMWriter& writer) const;
|
void save (int index, ESM::ESMWriter& writer) const;
|
||||||
|
|
||||||
//RECORD CONTAINERS ACCESS METHODS
|
//RECORD CONTAINERS ACCESS METHODS
|
||||||
const RefIdDataContainer<ESM::Book>& getBooks() const;
|
const RefIdDataContainer<ESM::Book>& getBooks() const;
|
||||||
const RefIdDataContainer<ESM::Activator>& getActivators() const;
|
const RefIdDataContainer<ESM::Activator>& getActivators() const;
|
||||||
const RefIdDataContainer<ESM::Potion>& getPotions() const;
|
const RefIdDataContainer<ESM::Potion>& getPotions() const;
|
||||||
const RefIdDataContainer<ESM::Apparatus>& getApparati() const;
|
const RefIdDataContainer<ESM::Apparatus>& getApparati() const;
|
||||||
const RefIdDataContainer<ESM::Armor>& getArmors() const;
|
const RefIdDataContainer<ESM::Armor>& getArmors() const;
|
||||||
const RefIdDataContainer<ESM::Clothing>& getClothing() const;
|
const RefIdDataContainer<ESM::Clothing>& getClothing() const;
|
||||||
const RefIdDataContainer<ESM::Container>& getContainers() const;
|
const RefIdDataContainer<ESM::Container>& getContainers() const;
|
||||||
const RefIdDataContainer<ESM::Creature>& getCreatures() const;
|
const RefIdDataContainer<ESM::Creature>& getCreatures() const;
|
||||||
const RefIdDataContainer<ESM::Door>& getDoors() const;
|
const RefIdDataContainer<ESM::Door>& getDoors() const;
|
||||||
const RefIdDataContainer<ESM::Ingredient>& getIngredients() const;
|
const RefIdDataContainer<ESM::Ingredient>& getIngredients() const;
|
||||||
const RefIdDataContainer<ESM::CreatureLevList>& getCreatureLevelledLists() const;
|
const RefIdDataContainer<ESM::CreatureLevList>& getCreatureLevelledLists() const;
|
||||||
const RefIdDataContainer<ESM::ItemLevList>& getItemLevelledList() const;
|
const RefIdDataContainer<ESM::ItemLevList>& getItemLevelledList() const;
|
||||||
const RefIdDataContainer<ESM::Light>& getLights() const;
|
const RefIdDataContainer<ESM::Light>& getLights() const;
|
||||||
const RefIdDataContainer<ESM::Lockpick>& getLocpicks() const;
|
const RefIdDataContainer<ESM::Lockpick>& getLocpicks() const;
|
||||||
const RefIdDataContainer<ESM::Miscellaneous>& getMiscellaneous() const;
|
const RefIdDataContainer<ESM::Miscellaneous>& getMiscellaneous() const;
|
||||||
const RefIdDataContainer<ESM::NPC>& getNPCs() const;
|
const RefIdDataContainer<ESM::NPC>& getNPCs() const;
|
||||||
const RefIdDataContainer<ESM::Weapon >& getWeapons() const;
|
const RefIdDataContainer<ESM::Weapon >& getWeapons() const;
|
||||||
const RefIdDataContainer<ESM::Probe >& getProbes() const;
|
const RefIdDataContainer<ESM::Probe >& getProbes() const;
|
||||||
const RefIdDataContainer<ESM::Repair>& getRepairs() const;
|
const RefIdDataContainer<ESM::Repair>& getRepairs() const;
|
||||||
const RefIdDataContainer<ESM::Static>& getStatics() const;
|
const RefIdDataContainer<ESM::Static>& getStatics() const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
#include "tablemimedata.hpp"
|
#include "tablemimedata.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
#include "universalid.hpp"
|
#include "universalid.hpp"
|
||||||
#include "columnbase.hpp"
|
#include "columnbase.hpp"
|
||||||
|
|
||||||
@ -11,7 +14,7 @@ mDocument(document)
|
|||||||
mObjectsFormats << QString::fromUtf8 (("tabledata/" + id.getTypeName()).c_str());
|
mObjectsFormats << QString::fromUtf8 (("tabledata/" + id.getTypeName()).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::TableMimeData::TableMimeData (std::vector< CSMWorld::UniversalId >& id, const CSMDoc::Document& document) :
|
CSMWorld::TableMimeData::TableMimeData (const std::vector< CSMWorld::UniversalId >& id, const CSMDoc::Document& document) :
|
||||||
mUniversalId (id), mDocument(document)
|
mUniversalId (id), mDocument(document)
|
||||||
{
|
{
|
||||||
for (std::vector<UniversalId>::iterator it (mUniversalId.begin()); it != mUniversalId.end(); ++it)
|
for (std::vector<UniversalId>::iterator it (mUniversalId.begin()); it != mUniversalId.end(); ++it)
|
||||||
@ -33,7 +36,8 @@ std::string CSMWorld::TableMimeData::getIcon() const
|
|||||||
{
|
{
|
||||||
if (mUniversalId.empty())
|
if (mUniversalId.empty())
|
||||||
{
|
{
|
||||||
throw ("TableMimeData holds no UniversalId");
|
qDebug()<<"TableMimeData object does not hold any records!"; //because throwing in the event loop tends to be problematic
|
||||||
|
throw("TableMimeData object does not hold any records!");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string tmpIcon;
|
std::string tmpIcon;
|
||||||
@ -50,7 +54,7 @@ std::string CSMWorld::TableMimeData::getIcon() const
|
|||||||
|
|
||||||
if (tmpIcon != mUniversalId[i].getIcon())
|
if (tmpIcon != mUniversalId[i].getIcon())
|
||||||
{
|
{
|
||||||
return ":/multitype.png"; //icon stolen from gnome
|
return ":/multitype.png"; //icon stolen from gnome TODO: get new icon
|
||||||
}
|
}
|
||||||
|
|
||||||
tmpIcon = mUniversalId[i].getIcon();
|
tmpIcon = mUniversalId[i].getIcon();
|
||||||
@ -531,4 +535,4 @@ CSMWorld::ColumnBase::Display CSMWorld::TableMimeData::convertEnums (CSMWorld::U
|
|||||||
const CSMDoc::Document* CSMWorld::TableMimeData::getDocumentPtr() const
|
const CSMDoc::Document* CSMWorld::TableMimeData::getDocumentPtr() const
|
||||||
{
|
{
|
||||||
return &mDocument;
|
return &mDocument;
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ namespace CSMWorld
|
|||||||
public:
|
public:
|
||||||
TableMimeData(UniversalId id, const CSMDoc::Document& document);
|
TableMimeData(UniversalId id, const CSMDoc::Document& document);
|
||||||
|
|
||||||
TableMimeData(std::vector<UniversalId>& id, const CSMDoc::Document& document);
|
TableMimeData(const std::vector<UniversalId>& id, const CSMDoc::Document& document);
|
||||||
|
|
||||||
~TableMimeData();
|
~TableMimeData();
|
||||||
|
|
||||||
@ -56,6 +56,7 @@ namespace CSMWorld
|
|||||||
UniversalId returnMatching(CSMWorld::ColumnBase::Display type) const;
|
UniversalId returnMatching(CSMWorld::ColumnBase::Display type) const;
|
||||||
|
|
||||||
static CSMWorld::UniversalId::Type convertEnums(CSMWorld::ColumnBase::Display type);
|
static CSMWorld::UniversalId::Type convertEnums(CSMWorld::ColumnBase::Display type);
|
||||||
|
|
||||||
static CSMWorld::ColumnBase::Display convertEnums(CSMWorld::UniversalId::Type type);
|
static CSMWorld::ColumnBase::Display convertEnums(CSMWorld::UniversalId::Type type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -18,7 +18,7 @@ namespace
|
|||||||
|
|
||||||
static const TypeData sNoArg[] =
|
static const TypeData sNoArg[] =
|
||||||
{
|
{
|
||||||
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "empty", 0 },
|
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, "-", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables", 0 },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings", 0 },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills", 0 },
|
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills", 0 },
|
||||||
@ -61,9 +61,10 @@ namespace
|
|||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", ":./spell.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Spell, "Spell", ":./spell.png" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Topic, "Topic", 0 },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Topic, "Topic", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Journal, "Journal", 0 },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Journal, "Journal", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_TopicInfo, "TopicInfo", 0 },
|
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_TopicInfo, "TopicInfo", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo", 0 },
|
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_JournalInfo, "JournalInfo", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell, "Cell", ":./cell.png" },
|
||||||
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Cell_Missing, "Cell", ":./cell.png" },
|
||||||
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables", 0 },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Referenceable, "Referenceables", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":./activator.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Activator, "Activator", ":./activator.png" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":./potion.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Potion, "Potion", ":./potion.png" },
|
||||||
@ -89,7 +90,7 @@ namespace
|
|||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Static, "Static", ":./static.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Static, "Static", ":./static.png" },
|
||||||
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":./weapon.png" },
|
{ CSMWorld::UniversalId::Class_RefRecord, CSMWorld::UniversalId::Type_Weapon, "Weapon", ":./weapon.png" },
|
||||||
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Reference", 0 },
|
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Reference, "Reference", 0 },
|
||||||
{ CSMWorld::UniversalId::Class_SubRecord, CSMWorld::UniversalId::Type_Filter, "Filter", ":./filter.png" },
|
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Filter, "Filter", ":./filter.png" },
|
||||||
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", 0 },
|
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Scene, "Scene", 0 },
|
||||||
|
|
||||||
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Preview, "Preview", 0 },
|
{ CSMWorld::UniversalId::Class_Collection, CSMWorld::UniversalId::Type_Preview, "Preview", 0 },
|
||||||
@ -100,6 +101,7 @@ namespace
|
|||||||
static const TypeData sIndexArg[] =
|
static const TypeData sIndexArg[] =
|
||||||
{
|
{
|
||||||
{ 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_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
|
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0, 0 } // end marker
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -318,6 +320,28 @@ std::vector<CSMWorld::UniversalId::Type> CSMWorld::UniversalId::listReferenceabl
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CSMWorld::UniversalId::Type CSMWorld::UniversalId::getParentType (Type type)
|
||||||
|
{
|
||||||
|
for (int i=0; sIdArg[i].mType; ++i)
|
||||||
|
if (type==sIdArg[i].mType)
|
||||||
|
{
|
||||||
|
if (sIdArg[i].mClass==Class_RefRecord)
|
||||||
|
return Type_Referenceables;
|
||||||
|
|
||||||
|
if (sIdArg[i].mClass==Class_SubRecord || sIdArg[i].mClass==Class_Record)
|
||||||
|
{
|
||||||
|
if (type==Type_Cell_Missing)
|
||||||
|
return Type_Cells;
|
||||||
|
|
||||||
|
return static_cast<Type> (type-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Type_None;
|
||||||
|
}
|
||||||
|
|
||||||
bool CSMWorld::operator== (const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right)
|
bool CSMWorld::operator== (const CSMWorld::UniversalId& left, const CSMWorld::UniversalId& right)
|
||||||
{
|
{
|
||||||
return left.isEqual (right);
|
return left.isEqual (right);
|
||||||
|
@ -32,6 +32,8 @@ namespace CSMWorld
|
|||||||
ArgumentType_Index
|
ArgumentType_Index
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \note A record list type must always be immediately followed by the matching
|
||||||
|
/// record type, if this type is of class SubRecord or Record.
|
||||||
enum Type
|
enum Type
|
||||||
{
|
{
|
||||||
Type_None = 0,
|
Type_None = 0,
|
||||||
@ -60,6 +62,7 @@ namespace CSMWorld
|
|||||||
Type_Spell,
|
Type_Spell,
|
||||||
Type_Cells,
|
Type_Cells,
|
||||||
Type_Cell,
|
Type_Cell,
|
||||||
|
Type_Cell_Missing, //For cells that does not exist yet.
|
||||||
Type_Referenceables,
|
Type_Referenceables,
|
||||||
Type_Referenceable,
|
Type_Referenceable,
|
||||||
Type_Activator,
|
Type_Activator,
|
||||||
@ -85,8 +88,8 @@ namespace CSMWorld
|
|||||||
Type_References,
|
Type_References,
|
||||||
Type_Reference,
|
Type_Reference,
|
||||||
Type_RegionMap,
|
Type_RegionMap,
|
||||||
Type_Filter,
|
|
||||||
Type_Filters,
|
Type_Filters,
|
||||||
|
Type_Filter,
|
||||||
Type_Topics,
|
Type_Topics,
|
||||||
Type_Topic,
|
Type_Topic,
|
||||||
Type_Journals,
|
Type_Journals,
|
||||||
@ -96,10 +99,11 @@ namespace CSMWorld
|
|||||||
Type_JournalInfos,
|
Type_JournalInfos,
|
||||||
Type_JournalInfo,
|
Type_JournalInfo,
|
||||||
Type_Scene,
|
Type_Scene,
|
||||||
Type_Preview
|
Type_Preview,
|
||||||
|
Type_LoadErrorLog
|
||||||
};
|
};
|
||||||
|
|
||||||
enum { NumberOfTypes = Type_Scene+1 };
|
enum { NumberOfTypes = Type_LoadErrorLog+1 };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -145,6 +149,11 @@ namespace CSMWorld
|
|||||||
///< Will return an empty string, if no icon is available.
|
///< Will return an empty string, if no icon is available.
|
||||||
|
|
||||||
static std::vector<Type> listReferenceableTypes();
|
static std::vector<Type> listReferenceableTypes();
|
||||||
|
|
||||||
|
/// If \a type is a SubRecord, RefRecord or Record type return the type of the table
|
||||||
|
/// that contains records of type \a type.
|
||||||
|
/// Otherwise return Type_None.
|
||||||
|
static Type getParentType (Type type);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool operator== (const UniversalId& left, const UniversalId& right);
|
bool operator== (const UniversalId& left, const UniversalId& right);
|
||||||
|
193
apps/opencs/view/doc/loader.cpp
Normal file
193
apps/opencs/view/doc/loader.cpp
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
|
||||||
|
#include "loader.hpp"
|
||||||
|
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QProgressBar>
|
||||||
|
#include <QCursor>
|
||||||
|
#include <QDialogButtonBox>
|
||||||
|
#include <QCloseEvent>
|
||||||
|
#include <QListWidget>
|
||||||
|
|
||||||
|
#include "../../model/doc/document.hpp"
|
||||||
|
|
||||||
|
void CSVDoc::LoadingDocument::closeEvent (QCloseEvent *event)
|
||||||
|
{
|
||||||
|
event->ignore();
|
||||||
|
cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
CSVDoc::LoadingDocument::LoadingDocument (CSMDoc::Document *document)
|
||||||
|
: mDocument (document), mAborted (false), mMessages (0)
|
||||||
|
{
|
||||||
|
setWindowTitle (("Opening " + document->getSavePath().filename().string()).c_str());
|
||||||
|
|
||||||
|
setMinimumWidth (400);
|
||||||
|
|
||||||
|
mLayout = new QVBoxLayout (this);
|
||||||
|
|
||||||
|
// file progress
|
||||||
|
mFile = new QLabel (this);
|
||||||
|
|
||||||
|
mLayout->addWidget (mFile);
|
||||||
|
|
||||||
|
mFileProgress = new QProgressBar (this);
|
||||||
|
|
||||||
|
mLayout->addWidget (mFileProgress);
|
||||||
|
|
||||||
|
int size = static_cast<int> (document->getContentFiles().size())+1;
|
||||||
|
if (document->isNew())
|
||||||
|
--size;
|
||||||
|
|
||||||
|
mFileProgress->setMinimum (0);
|
||||||
|
mFileProgress->setMaximum (size);
|
||||||
|
mFileProgress->setTextVisible (true);
|
||||||
|
mFileProgress->setValue (0);
|
||||||
|
|
||||||
|
// record progress
|
||||||
|
mLayout->addWidget (new QLabel ("Records", this));
|
||||||
|
|
||||||
|
mRecordProgress = new QProgressBar (this);
|
||||||
|
|
||||||
|
mLayout->addWidget (mRecordProgress);
|
||||||
|
|
||||||
|
mRecordProgress->setMinimum (0);
|
||||||
|
mRecordProgress->setTextVisible (true);
|
||||||
|
mRecordProgress->setValue (0);
|
||||||
|
|
||||||
|
// error message
|
||||||
|
mError = new QLabel (this);
|
||||||
|
mError->setWordWrap (true);
|
||||||
|
|
||||||
|
mLayout->addWidget (mError);
|
||||||
|
|
||||||
|
// buttons
|
||||||
|
mButtons = new QDialogButtonBox (QDialogButtonBox::Cancel, Qt::Horizontal, this);
|
||||||
|
|
||||||
|
mLayout->addWidget (mButtons);
|
||||||
|
|
||||||
|
setLayout (mLayout);
|
||||||
|
|
||||||
|
move (QCursor::pos());
|
||||||
|
|
||||||
|
show();
|
||||||
|
|
||||||
|
connect (mButtons, SIGNAL (rejected()), this, SLOT (cancel()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::LoadingDocument::nextStage (const std::string& name, int steps)
|
||||||
|
{
|
||||||
|
mFile->setText (QString::fromUtf8 (("Loading: " + name).c_str()));
|
||||||
|
|
||||||
|
mFileProgress->setValue (mFileProgress->value()+1);
|
||||||
|
|
||||||
|
mRecordProgress->setValue (0);
|
||||||
|
mRecordProgress->setMaximum (steps>0 ? steps : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::LoadingDocument::nextRecord()
|
||||||
|
{
|
||||||
|
int value = mRecordProgress->value()+1;
|
||||||
|
|
||||||
|
if (value<=mRecordProgress->maximum())
|
||||||
|
mRecordProgress->setValue (value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::LoadingDocument::abort (const std::string& error)
|
||||||
|
{
|
||||||
|
mAborted = true;
|
||||||
|
mError->setText (QString::fromUtf8 (("Loading failed: " + error).c_str()));
|
||||||
|
mButtons->setStandardButtons (QDialogButtonBox::Close);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::LoadingDocument::addMessage (const std::string& message)
|
||||||
|
{
|
||||||
|
if (!mMessages)
|
||||||
|
{
|
||||||
|
mMessages = new QListWidget (this);
|
||||||
|
mLayout->insertWidget (4, mMessages);
|
||||||
|
}
|
||||||
|
|
||||||
|
new QListWidgetItem (QString::fromUtf8 (message.c_str()), mMessages);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::LoadingDocument::cancel()
|
||||||
|
{
|
||||||
|
if (!mAborted)
|
||||||
|
emit cancel (mDocument);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
emit close (mDocument);
|
||||||
|
deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
CSVDoc::Loader::Loader() {}
|
||||||
|
|
||||||
|
CSVDoc::Loader::~Loader()
|
||||||
|
{
|
||||||
|
for (std::map<CSMDoc::Document *, LoadingDocument *>::iterator iter (mDocuments.begin());
|
||||||
|
iter!=mDocuments.end(); ++iter)
|
||||||
|
delete iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::Loader::add (CSMDoc::Document *document)
|
||||||
|
{
|
||||||
|
LoadingDocument *loading = new LoadingDocument (document);
|
||||||
|
mDocuments.insert (std::make_pair (document, loading));
|
||||||
|
|
||||||
|
connect (loading, SIGNAL (cancel (CSMDoc::Document *)),
|
||||||
|
this, SIGNAL (cancel (CSMDoc::Document *)));
|
||||||
|
connect (loading, SIGNAL (close (CSMDoc::Document *)),
|
||||||
|
this, SIGNAL (close (CSMDoc::Document *)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::Loader::loadingStopped (CSMDoc::Document *document, bool completed,
|
||||||
|
const std::string& error)
|
||||||
|
{
|
||||||
|
std::map<CSMDoc::Document *, LoadingDocument *>::iterator iter = mDocuments.begin();
|
||||||
|
|
||||||
|
for (; iter!=mDocuments.end(); ++iter)
|
||||||
|
if (iter->first==document)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (iter==mDocuments.end())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (completed || error.empty())
|
||||||
|
{
|
||||||
|
delete iter->second;
|
||||||
|
mDocuments.erase (iter);
|
||||||
|
}
|
||||||
|
else if (!completed && !error.empty())
|
||||||
|
{
|
||||||
|
iter->second->abort (error);
|
||||||
|
// Leave the window open for now (wait for the user to close it)
|
||||||
|
mDocuments.erase (iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::Loader::nextStage (CSMDoc::Document *document, const std::string& name, int steps)
|
||||||
|
{
|
||||||
|
std::map<CSMDoc::Document *, LoadingDocument *>::iterator iter = mDocuments.find (document);
|
||||||
|
|
||||||
|
if (iter!=mDocuments.end())
|
||||||
|
iter->second->nextStage (name, steps);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::Loader::nextRecord (CSMDoc::Document *document)
|
||||||
|
{
|
||||||
|
std::map<CSMDoc::Document *, LoadingDocument *>::iterator iter = mDocuments.find (document);
|
||||||
|
|
||||||
|
if (iter!=mDocuments.end())
|
||||||
|
iter->second->nextRecord();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVDoc::Loader::loadMessage (CSMDoc::Document *document, const std::string& message)
|
||||||
|
{
|
||||||
|
std::map<CSMDoc::Document *, LoadingDocument *>::iterator iter = mDocuments.find (document);
|
||||||
|
|
||||||
|
if (iter!=mDocuments.end())
|
||||||
|
iter->second->addMessage (message);
|
||||||
|
}
|
99
apps/opencs/view/doc/loader.hpp
Normal file
99
apps/opencs/view/doc/loader.hpp
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#ifndef CSV_DOC_LOADER_H
|
||||||
|
#define CSV_DOC_LOADER_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QSignalMapper>
|
||||||
|
|
||||||
|
class QLabel;
|
||||||
|
class QProgressBar;
|
||||||
|
class QDialogButtonBox;
|
||||||
|
class QListWidget;
|
||||||
|
class QVBoxLayout;
|
||||||
|
|
||||||
|
namespace CSMDoc
|
||||||
|
{
|
||||||
|
class Document;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CSVDoc
|
||||||
|
{
|
||||||
|
class LoadingDocument : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
CSMDoc::Document *mDocument;
|
||||||
|
QLabel *mFile;
|
||||||
|
QProgressBar *mFileProgress;
|
||||||
|
QProgressBar *mRecordProgress;
|
||||||
|
bool mAborted;
|
||||||
|
QDialogButtonBox *mButtons;
|
||||||
|
QLabel *mError;
|
||||||
|
QListWidget *mMessages;
|
||||||
|
QVBoxLayout *mLayout;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void closeEvent (QCloseEvent *event);
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
LoadingDocument (CSMDoc::Document *document);
|
||||||
|
|
||||||
|
void nextStage (const std::string& name, int steps);
|
||||||
|
|
||||||
|
void nextRecord();
|
||||||
|
|
||||||
|
void abort (const std::string& error);
|
||||||
|
|
||||||
|
void addMessage (const std::string& message);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void cancel();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void cancel (CSMDoc::Document *document);
|
||||||
|
///< Stop loading process.
|
||||||
|
|
||||||
|
void close (CSMDoc::Document *document);
|
||||||
|
///< Close stopped loading process.
|
||||||
|
};
|
||||||
|
|
||||||
|
class Loader : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
std::map<CSMDoc::Document *, LoadingDocument *> mDocuments;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Loader();
|
||||||
|
|
||||||
|
virtual ~Loader();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
|
||||||
|
void cancel (CSMDoc::Document *document);
|
||||||
|
|
||||||
|
void close (CSMDoc::Document *document);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
|
||||||
|
void add (CSMDoc::Document *document);
|
||||||
|
|
||||||
|
void loadingStopped (CSMDoc::Document *document, bool completed,
|
||||||
|
const std::string& error);
|
||||||
|
|
||||||
|
void nextStage (CSMDoc::Document *document, const std::string& name, int steps);
|
||||||
|
|
||||||
|
void nextRecord (CSMDoc::Document *document);
|
||||||
|
|
||||||
|
void loadMessage (CSMDoc::Document *document, const std::string& message);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user