Merge branch 'master' into QtOGre

Conflicts:
	apps/opencs/model/doc/document.cpp
	apps/opencs/view/render/pagedworldspacewidget.cpp
	apps/opencs/view/render/pagedworldspacewidget.hpp
	components/nif/niffile.hpp
	libs/openengine/bullet/physic.hpp
loadfix
cc9cii 10 years ago
commit 312b7cd571

1
.gitignore vendored

@ -37,6 +37,7 @@ resources
/omwlauncher /omwlauncher
/openmw /openmw
/opencs /opencs
/niftest
## generated objects ## generated objects
apps/openmw/config.hpp apps/openmw/config.hpp

@ -0,0 +1,139 @@
Adam Hogan <comrade@comrade-desktop.(none)>
Aleksandar Jovanov <ajovanov93@yahoo.com>
Alexander Olofsson <ace@haxalot.com>
Alex McKibben <mckibbenta@gmail.com>
Alex "rainChu" Haddad <alx1213@gmail.com>
Ardekantur <greystone@ardekantur.com>
Armin Preiml <b.nutzer@gmail.com>
Artem Kotsynyak <greye@carceri>
Arthur Moore <arthur@Behemoth>
Arthur Moore <Arthur.Moore.git@cd-net.net>
athile <athile@athile.net>
athile <athile.g@gmail.com>
Stefan Galowicz <bogglez@the.mind>
Bret Curtis <psi29a@gmail.com>
Britt Mathis <britt.mathis@gmail.com>
Sandy Carter <bwrsandman@gmail.com>
Sandy Carter <mr.sandy.carter@gmail.com>
Carl Maxwell <carl.maxwell@gmail.com>
cc9cii <cc9c@iinet.net.au>
Cory F. Cohen <cfcohen@verizon.net>
Chris Robinson <chris.kcat@gmail.com>
Cris Mihalache <mirceam94@hotmail.com>
darkf <lw9k123@gmail.com>
Diggory Hardy <diggory.hardy@gmail.com>
Thomas Luppi <ThomasLuppi@gmail.com>
Thomas Luppi <tluppi@thomas-GE60.(none)>
Dmitriy 'Endorph' Shkurskiy <end0rph@hotmail.com>
Dmitry Marakasov <amdmi3@amdmi3.ru>
Douglas Diniz <dgdiniz@gmail.com>
Douglas Mencken <dougmencken@gmail.com>
Edmondo Tommasina <edmondo.tommasina@gmail.com>
Eduard Cot <eduard@eduard-iMac.(none)>
Eli2 <fabian@fabian-desktop.(none)>
Emanuel Guével <guevel.emanuel@gmail.com>
Leon Saunders <LeonDavidSaunders@gmail.com>
Fil Krynicki <filipkrynicki@gmail.com>
John Blomberg <johnblo@kth.se>
Gašper Sedej <gsedej@gmail.com>
Michał Bień <michal1.bien@gmail.com>
Joel Graff <monograff76@gmail.com>
Paul McElroy <pcm1123@gmail.com>
Artem Kotsynyak <greye@carceri>
Artem Kotsynyak <greye@null.net>
gugus <gus_512@hotmail.com>
guidoj <guido@thuisbasis.net>
gus <gus_512@hotmail.com>
Hallfaer Tuilinn <gijsbertth@gmail.com>
Julian Ospald <julian.ospald@googlemail.com>
Jacob Essex <jacob@jacobessex.com>
Jan Borsodi <jborsodi@gmail.com>
Jan-Peter Nilsson <peppe@pappkartong.se>
Jason Hooks <Hooks@.(none)>
Jason Hooks <jason@Jason-ThinkPad-R61.(none)>
Jason Hooks <jhooks1@mix.wvu.edu>
Jeffrey Haines <jeffhaines@me.com>
Jeffrey Haines <jib-y@users.noreply.github.com>
Jordan Ayers <jordan.ayers@gmail.com>
Jordan Milne <jordan.milne@saynotolinux.com>
Josua Grawitter <josh@greyage.org>
Julien Voisin <pouicpouicpouic@gmail.com>
Karl-Felix Glatzer <karl.glatzer@gmx.de>
Chris Robinson <chris.kcat@gmail.com>
Kevin Poitra <pupkev@yahoo.com>
Roman Proskuryakov <humbug@deeptown.org>
Lars Söderberg <lazze_1983@hotmail.com>
lazydev <lazydev@homecomp>
lazydev <lazydev@nomail>
Lukasz Gromanowski <lgromanowski@gmail.com>
Marc Bouvier <marcrbouvier@gmail.com>
Marcin Hulist <Gohan1989@gmail.com>
Marc Zinnschlag <marc@zpages.de>
Marek Kochanowicz <herr@mikrus.pl>
Marek Kochanowicz <marek@localhost.localdomain>
Marek Kochanowicz <sirherrbatka@gmail.com>
Mark Siewert <mark.siewert@t-online.de>
Mark Siewert <ms@cerebra.localdomain>
megaton <9megaton6@gmail.com>
Michael Mc Donnell <michael@mcdonnell.dk>
Michael Papageorgiou <werdanith@yahoo.gr>
Michal Sciubidlo <michal.sciubidlo@gmail.com>
Michał Ściubidło <michal.sciubidlo@gmail.com>
Nathan Jeffords <blunted2night@gmail.com>
Nicolay Korslund <korslund@gmail.com>
Nicolay Korslund <nicolayk@met.no>
Nikolay Kasyanov <corrmage@gmail.com>
pchan3 <chantlerpeter@gmail.com>
Pieter van der Kloet <pvdkloet@gmail.com>
Mateusz Kołaczek <mateusz.kolaczek@gmail.com>
Bret Curtis <psi29a@gmail.com>
Pieter van der Kloet <pvdkloet@gmail.com>
Rohit Nirmal <rohitnirmal9@gmail.com>
Roman Melnik <kromgart@gmail.com>
Radu-Marius Popovici <rpopovici@github.com>
Sandy Carter <bwrsandman@gmail.com>
Scott Howard <showard314@gmail.com>
Jannik Heller <scrawl@baseoftrash.de>
Jannik Heller <scrawl@scrawl-laptop.(none)>
Sebastian Wick <sebastian@sebastianwick.net>
Sebastian Wick <wick.sebastian@gmail.com>
Sergey Shambir <sergey.shambir.auto@gmail.com>
sergoz <parapvr@yandex.ru>
Chris Boyce <slothlife@users.noreply.github.com>
Star-Demon <starsickle@yahoo.com>
Sylvain Thesnieres <garvek@gmail.com>
Thomas Luppi <digrules@gmail.com>
Thomas Luppi <tluppi@thomas-GE60.(none)>
Thoronador <thoronador@users.sourceforge.net>
TomKoenderink <tom_koenderink-github@omniadicta.net>
Tom Mason <wheybags@wheybags.com>
Torben Carrington <torbenlcarrington@Gmail.com>
Vincent Heuken <vincent@vincentheuken.com>
Manuel Edelmann <edelmann.manuel@gmail.com>
Manuel Edelmann <vorenon@hotmail.com>
Alexander Nadeau <wareya@gmail.com>
Michael Hogan <mr.michaelhogan@gmail.com>
Jacob Essex <github@JacobEssex.com>
Yuri Krupenin <yuri.krupenin@gmail.com>
Bret Curtis <noone@your.box>
sirherrbatka <herr@localhost.localdomain>
sirherrbatka <sirherrbatka@myopera.com>
sergei <sergei@ubuntu.(none)>
riothamus <digimars@gmail.com>
nobrakal <nobrakal@gmail.com>
nkorslund <nkorslund@ea6a568a-9f4f-0410-981a-c910a81bb256>
mrcheko <cheko@sevas.ua>
Miroslav Puda <pakanek@gmail.com>
MiroslavR <miroslavr256@gmail.com>
mckibbenta <mckibbenta@gmail.com>
jeaye <jeaye@arrownext.com>
eroen <eroen@falcon.eroen.eu>
eroen <eroen@occam.eroen.eu>
dreamer-dead <dreamer.dead@gmail.com>
crysthala <crystalsoulslayer@gmail.com>
Berulacks <beru@eml.cc>
Axujen <axujen@gmail.com>
root <root@debian>
unknown <Hooks@.(none)>

@ -10,11 +10,10 @@ before_install:
- echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse" - echo "yes" | sudo add-apt-repository "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse"
- echo "yes" | sudo apt-add-repository ppa:openmw/openmw - echo "yes" | sudo apt-add-repository ppa:openmw/openmw
- sudo apt-get update -qq - sudo apt-get update -qq
- sudo apt-get install -qq libboost-all-dev libgtest-dev google-mock - sudo apt-get install -qq libgtest-dev google-mock
- sudo apt-get install -qq libqt4-dev - sudo apt-get install -qq libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libboost-thread-dev libboost-wave-dev
- sudo apt-get install -qq libopenal-dev - sudo apt-get install -qq libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavresample-dev
- sudo apt-get install -qq libavcodec-dev libavformat-dev libavutil-dev libswscale-dev - sudo apt-get install -qq libbullet-dev libogre-1.9-dev libmygui-dev libsdl2-dev libunshield-dev libtinyxml-dev libopenal-dev libqt4-dev
- sudo apt-get install -qq libbullet-dev libogre-1.9-dev libmygui-dev libsdl2-dev libunshield-dev
- sudo mkdir /usr/src/gtest/build - sudo mkdir /usr/src/gtest/build
- cd /usr/src/gtest/build - cd /usr/src/gtest/build
- sudo cmake .. -DBUILD_SHARED_LIBS=1 - sudo cmake .. -DBUILD_SHARED_LIBS=1
@ -25,7 +24,7 @@ before_script:
- cd - - cd -
- mkdir build - mkdir build
- cd build - cd build
- cmake .. -DBUILD_WITH_CODE_COVERAGE=1 -DBUILD_UNITTESTS=1 -DBUILD_WITH_DPKG=1 - cmake .. -DBUILD_WITH_CODE_COVERAGE=1 -DBUILD_UNITTESTS=1 -DCMAKE_INSTALL_PREFIX=/usr -DBINDIR=/usr/games -DCMAKE_BUILD_TYPE="RelWithDebInfo" -DUSE_SYSTEM_TINYXML=TRUE
script: script:
- make -j4 - make -j4
after_script: after_script:

@ -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 31) set(OPENMW_VERSION_MINOR 32)
set(OPENMW_VERSION_RELEASE 0) set(OPENMW_VERSION_RELEASE 0)
set(OPENMW_VERSION_COMMITHASH "") set(OPENMW_VERSION_COMMITHASH "")
@ -54,6 +54,10 @@ endif(EXISTS ${PROJECT_SOURCE_DIR}/.git)
# Macros # Macros
include(OpenMWMacros) include(OpenMWMacros)
if (ANDROID)
set(CMAKE_FIND_ROOT_PATH ${OPENMW_DEPENDENCIES_DIR} "${CMAKE_FIND_ROOT_PATH}")
endif (ANDROID)
# doxygen main page # doxygen main page
configure_file ("${OpenMW_SOURCE_DIR}/docs/mainpage.hpp.cmake" "${OpenMW_SOURCE_DIR}/docs/mainpage.hpp") configure_file ("${OpenMW_SOURCE_DIR}/docs/mainpage.hpp.cmake" "${OpenMW_SOURCE_DIR}/docs/mainpage.hpp")
@ -66,16 +70,15 @@ option(SDL2_STATIC "Link static build of SDL into the binaries" FALSE)
option(OPENMW_UNITY_BUILD "Use fewer compilation units to speed up compile time" FALSE) option(OPENMW_UNITY_BUILD "Use fewer compilation units to speed up compile time" FALSE)
# Apps and tools # Apps and tools
option(BUILD_BSATOOL "build BSA extractor" OFF) option(BUILD_BSATOOL "build BSA extractor" ON)
option(BUILD_ESMTOOL "build ESM inspector" ON) option(BUILD_ESMTOOL "build ESM inspector" ON)
option(BUILD_LAUNCHER "build Launcher" ON) option(BUILD_LAUNCHER "build Launcher" ON)
option(BUILD_MWINIIMPORTER "build MWiniImporter" ON) option(BUILD_MWINIIMPORTER "build MWiniImporter" ON)
option(BUILD_OPENCS "build OpenMW Construction Set" ON) option(BUILD_OPENCS "build OpenMW Construction Set" ON)
option(BUILD_WITH_CODE_COVERAGE "Enable code coverage with gconv" OFF) option(BUILD_WITH_CODE_COVERAGE "Enable code coverage with gconv" OFF)
option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest ang GMock frameworks" OFF) option(BUILD_UNITTESTS "Enable Unittests with Google C++ Unittest and GMock frameworks" OFF)
option(BUILD_NIFTEST "build nif file tester" OFF)
# Sound source selection option(BUILD_MYGUI_PLUGIN "build MyGUI plugin for OpenMW resources, to use with MyGUI tools" ON)
option(USE_FFMPEG "use ffmpeg for sound" ON)
# OS X deployment # OS X deployment
option(OPENMW_OSX_DEPLOYMENT OFF) option(OPENMW_OSX_DEPLOYMENT OFF)
@ -101,33 +104,32 @@ cmake_minimum_required(VERSION 2.6)
# source directory: libs # source directory: libs
set(LIBDIR ${CMAKE_SOURCE_DIR}/libs) set(LIBS_DIR ${CMAKE_SOURCE_DIR}/libs)
set(OENGINE_OGRE set(OENGINE_OGRE
${LIBDIR}/openengine/ogre/renderer.cpp ${LIBS_DIR}/openengine/ogre/renderer.cpp
${LIBDIR}/openengine/ogre/fader.cpp ${LIBS_DIR}/openengine/ogre/lights.cpp
${LIBDIR}/openengine/ogre/lights.cpp ${LIBS_DIR}/openengine/ogre/selectionbuffer.cpp
${LIBDIR}/openengine/ogre/selectionbuffer.cpp ${LIBS_DIR}/openengine/ogre/imagerotate.cpp
${LIBDIR}/openengine/ogre/imagerotate.cpp
) )
set(OENGINE_GUI set(OENGINE_GUI
${LIBDIR}/openengine/gui/loglistener.cpp ${LIBS_DIR}/openengine/gui/loglistener.cpp
${LIBDIR}/openengine/gui/manager.cpp ${LIBS_DIR}/openengine/gui/manager.cpp
${LIBDIR}/openengine/gui/layout.hpp ${LIBS_DIR}/openengine/gui/layout.hpp
) )
set(OENGINE_BULLET set(OENGINE_BULLET
${LIBDIR}/openengine/bullet/BtOgre.cpp ${LIBS_DIR}/openengine/bullet/BtOgre.cpp
${LIBDIR}/openengine/bullet/BtOgreExtras.h ${LIBS_DIR}/openengine/bullet/BtOgreExtras.h
${LIBDIR}/openengine/bullet/BtOgreGP.h ${LIBS_DIR}/openengine/bullet/BtOgreGP.h
${LIBDIR}/openengine/bullet/BtOgrePG.h ${LIBS_DIR}/openengine/bullet/BtOgrePG.h
${LIBDIR}/openengine/bullet/physic.cpp ${LIBS_DIR}/openengine/bullet/physic.cpp
${LIBDIR}/openengine/bullet/physic.hpp ${LIBS_DIR}/openengine/bullet/physic.hpp
${LIBDIR}/openengine/bullet/BulletShapeLoader.cpp ${LIBS_DIR}/openengine/bullet/BulletShapeLoader.cpp
${LIBDIR}/openengine/bullet/BulletShapeLoader.h ${LIBS_DIR}/openengine/bullet/BulletShapeLoader.h
${LIBDIR}/openengine/bullet/trace.cpp ${LIBS_DIR}/openengine/bullet/trace.cpp
${LIBDIR}/openengine/bullet/trace.h ${LIBS_DIR}/openengine/bullet/trace.h
) )
@ -138,32 +140,24 @@ set(OPENMW_LIBS ${OENGINE_ALL})
set(OPENMW_LIBS_HEADER) set(OPENMW_LIBS_HEADER)
# Sound setup # Sound setup
set(GOT_SOUND_INPUT 0) set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE AVRESAMPLE)
set(SOUND_INPUT_INCLUDES "") unset(FFMPEG_LIBRARIES CACHE)
set(SOUND_INPUT_LIBRARY "") find_package(FFmpeg)
set(SOUND_DEFINE "") if ( NOT AVCODEC_FOUND OR NOT AVFORMAT_FOUND OR NOT AVUTIL_FOUND OR NOT SWSCALE_FOUND )
if (USE_FFMPEG) message(FATAL_ERROR "FFmpeg component required, but not found!")
set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE) endif()
find_package(FFmpeg) set(SOUND_INPUT_INCLUDES ${FFMPEG_INCLUDE_DIRS})
if (FFMPEG_FOUND) set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARIES})
set(SOUND_INPUT_INCLUDES ${SOUND_INPUT_INCLUDES} ${FFMPEG_INCLUDE_DIRS}) if( SWRESAMPLE_FOUND )
set(SOUND_INPUT_LIBRARY ${SOUND_INPUT_LIBRARY} ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARIES}) add_definitions(-DHAVE_LIBSWRESAMPLE)
set(SOUND_DEFINE ${SOUND_DEFINE} -DOPENMW_USE_FFMPEG) set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${SWRESAMPLE_LIBRARIES})
set(GOT_SOUND_INPUT 1) else()
endif (FFMPEG_FOUND) if( AVRESAMPLE_FOUND )
endif (USE_FFMPEG) set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${AVRESAMPLE_LIBRARIES})
else()
if (NOT GOT_SOUND_INPUT) message(FATAL_ERROR "Install either libswresample (FFmpeg) or libavresample (Libav).")
message(WARNING "--------------------") endif()
message(WARNING "Failed to find any sound input packages") endif()
message(WARNING "--------------------")
endif (NOT GOT_SOUND_INPUT)
if (NOT FFMPEG_FOUND)
message(WARNING "--------------------")
message(WARNING "FFmpeg not found, video playback will be disabled")
message(WARNING "--------------------")
endif (NOT FFMPEG_FOUND)
# TinyXML # TinyXML
option(USE_SYSTEM_TINYXML "Use system TinyXML library instead of internal." OFF) option(USE_SYSTEM_TINYXML "Use system TinyXML library instead of internal." OFF)
@ -227,7 +221,15 @@ IF(BOOST_STATIC)
endif() endif()
find_package(OGRE REQUIRED) find_package(OGRE REQUIRED)
if (${OGRE_VERSION} VERSION_LESS "1.9")
message(FATAL_ERROR "OpenMW requires Ogre 1.9 or later, please install the latest stable version from http://ogre3d.org")
endif()
find_package(MyGUI REQUIRED) find_package(MyGUI REQUIRED)
if (${MYGUI_VERSION} VERSION_LESS "3.2.1")
message(FATAL_ERROR "OpenMW requires MyGUI 3.2.1 or later, please install the latest version from http://mygui.info")
endif()
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS}) find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
find_package(SDL2 REQUIRED) find_package(SDL2 REQUIRED)
find_package(OpenAL REQUIRED) find_package(OpenAL REQUIRED)
@ -258,7 +260,12 @@ if(OGRE_STATIC)
list(APPEND OGRE_STATIC_PLUGINS ${Cg_LIBRARIES}) list(APPEND OGRE_STATIC_PLUGINS ${Cg_LIBRARIES})
endif(Cg_FOUND) endif(Cg_FOUND)
if (ANDROID)
add_static_ogre_plugin(RenderSystem_GLES2)
else ()
add_static_ogre_plugin(RenderSystem_GL) add_static_ogre_plugin(RenderSystem_GL)
endif ()
if(WIN32) if(WIN32)
add_static_ogre_plugin(RenderSystem_Direct3D9) add_static_ogre_plugin(RenderSystem_Direct3D9)
endif(WIN32) endif(WIN32)
@ -272,7 +279,7 @@ include_directories("."
${MYGUI_INCLUDE_DIRS} ${MYGUI_INCLUDE_DIRS}
${MYGUI_PLATFORM_INCLUDE_DIRS} ${MYGUI_PLATFORM_INCLUDE_DIRS}
${OPENAL_INCLUDE_DIR} ${OPENAL_INCLUDE_DIR}
${LIBDIR} ${LIBS_DIR}
) )
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})
@ -325,12 +332,14 @@ else ()
add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="_d") add_definitions(-DOGRE_PLUGIN_DEBUG_SUFFIX="_d")
endif() endif()
add_definitions(-DOGRE_PLUGIN_DIR_REL="${OGRE_PLUGIN_DIR_REL}")
add_definitions(-DOGRE_PLUGIN_DIR_DBG="${OGRE_PLUGIN_DIR_DBG}")
if (APPLE AND OPENMW_OSX_DEPLOYMENT) if (APPLE AND OPENMW_OSX_DEPLOYMENT)
# make it empty so plugin loading code can check this and try to find plugins inside app bundle # make it empty so plugin loading code can check this and try to find plugins inside app bundle
add_definitions(-DOGRE_PLUGIN_DIR="") add_definitions(-DOGRE_PLUGIN_DIR="")
else() else()
if (NOT DEFINED ${OGRE_PLUGIN_DIR})
set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_REL})
endif()
add_definitions(-DOGRE_PLUGIN_DIR="${OGRE_PLUGIN_DIR}") add_definitions(-DOGRE_PLUGIN_DIR="${OGRE_PLUGIN_DIR}")
endif() endif()
@ -342,8 +351,10 @@ add_subdirectory(files/mygui)
if (APPLE) if (APPLE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${APP_BUNDLE_DIR}/Contents/MacOS") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${APP_BUNDLE_DIR}/Contents/MacOS")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${APP_BUNDLE_DIR}/Contents/MacOS")
else (APPLE) else (APPLE)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${OpenMW_BINARY_DIR}") set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${OpenMW_BINARY_DIR}")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${OpenMW_BINARY_DIR}")
endif (APPLE) endif (APPLE)
# Other files # Other files
@ -377,9 +388,6 @@ endif()
if (CMAKE_COMPILER_IS_GNUCC) if (CMAKE_COMPILER_IS_GNUCC)
SET(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wno-reorder -std=c++98 -pedantic -Wno-long-long ${CMAKE_CXX_FLAGS}") SET(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-unused-parameter -Wno-reorder -std=c++98 -pedantic -Wno-long-long ${CMAKE_CXX_FLAGS}")
# Silence warnings in OGRE headers. Remove once OGRE got fixed!
SET(CMAKE_CXX_FLAGS "-Wno-ignored-qualifiers ${CMAKE_CXX_FLAGS}")
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
OUTPUT_VARIABLE GCC_VERSION) OUTPUT_VARIABLE GCC_VERSION)
if ("${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6) if ("${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6)
@ -391,11 +399,18 @@ IF(NOT WIN32 AND NOT APPLE)
# Linux building # Linux building
# Paths # Paths
SET(BINDIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Where to install binaries") SET(BINDIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Where to install binaries")
SET(LIBDIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Where to install libraries")
SET(DATAROOTDIR "${CMAKE_INSTALL_PREFIX}/share" CACHE PATH "Sets the root of data directories to a non-default location") SET(DATAROOTDIR "${CMAKE_INSTALL_PREFIX}/share" CACHE PATH "Sets the root of data directories to a non-default location")
SET(DATADIR "${DATAROOTDIR}/games/openmw" CACHE PATH "Sets the openmw data directories to a non-default location") SET(GLOBAL_DATA_PATH "${DATAROOTDIR}/games/" CACHE PATH "Set data path prefix")
SET(DATADIR "${GLOBAL_DATA_PATH}/openmw" CACHE PATH "Sets the openmw data directories to a non-default location")
SET(ICONDIR "${DATAROOTDIR}/pixmaps" CACHE PATH "Set icon dir") SET(ICONDIR "${DATAROOTDIR}/pixmaps" CACHE PATH "Set icon dir")
SET(LICDIR "${DATAROOTDIR}/licenses/openmw" CACHE PATH "Sets the openmw license directory to a non-default location.") SET(LICDIR "${DATAROOTDIR}/licenses/openmw" CACHE PATH "Sets the openmw license directory to a non-default location.")
SET(SYSCONFDIR "/etc/openmw" CACHE PATH "Set config dir") IF("${CMAKE_INSTALL_PREFIX}" STREQUAL "/usr")
SET(GLOBAL_CONFIG_PATH "/etc/" CACHE PATH "Set config dir prefix")
ELSE()
SET(GLOBAL_CONFIG_PATH "${CMAKE_INSTALL_PREFIX}/etc/" CACHE PATH "Set config dir prefix")
ENDIF()
SET(SYSCONFDIR "${GLOBAL_CONFIG_PATH}/openmw" CACHE PATH "Set config dir")
# Install binaries # Install binaries
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw" DESTINATION "${BINDIR}" ) INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw" DESTINATION "${BINDIR}" )
@ -414,6 +429,12 @@ IF(NOT WIN32 AND NOT APPLE)
IF(BUILD_OPENCS) IF(BUILD_OPENCS)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/opencs" DESTINATION "${BINDIR}" ) INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/opencs" DESTINATION "${BINDIR}" )
ENDIF(BUILD_OPENCS) ENDIF(BUILD_OPENCS)
IF(BUILD_NIFTEST)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/niftest" DESTINATION "${BINDIR}" )
ENDIF(BUILD_NIFTEST)
if(BUILD_MYGUI_PLUGIN)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Plugin_MyGUI_OpenMW_Resources.so" DESTINATION "${LIBDIR}" )
ENDIF(BUILD_MYGUI_PLUGIN)
# Install licenses # Install licenses
INSTALL(FILES "docs/license/DejaVu Font License.txt" DESTINATION "${LICDIR}" ) INSTALL(FILES "docs/license/DejaVu Font License.txt" DESTINATION "${LICDIR}" )
@ -463,6 +484,9 @@ if(WIN32)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/opencs.exe" DESTINATION ".") INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/opencs.exe" DESTINATION ".")
INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION ".") INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION ".")
ENDIF(BUILD_OPENCS) ENDIF(BUILD_OPENCS)
if(BUILD_MYGUI_PLUGIN)
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/Plugin_MyGUI_OpenMW_Resources.dll" DESTINATION ".")
ENDIF(BUILD_MYGUI_PLUGIN)
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".") INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION ".")
@ -492,8 +516,8 @@ if(WIN32)
SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.openmw.org") SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.openmw.org")
SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\www.openmw.org") SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\www.openmw.org")
SET(CPACK_NSIS_INSTALLED_ICON_NAME "omwlauncher.exe") SET(CPACK_NSIS_INSTALLED_ICON_NAME "omwlauncher.exe")
SET(CPACK_NSIS_MUI_ICON "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.ico") SET(CPACK_NSIS_MUI_ICON "${OpenMW_SOURCE_DIR}/files/windows/openmw.ico")
SET(CPACK_NSIS_MUI_UNIICON "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.ico") SET(CPACK_NSIS_MUI_UNIICON "${OpenMW_SOURCE_DIR}/files/windows/openmw.ico")
SET(CPACK_PACKAGE_ICON "${OpenMW_SOURCE_DIR}\\\\files\\\\openmw.bmp") SET(CPACK_PACKAGE_ICON "${OpenMW_SOURCE_DIR}\\\\files\\\\openmw.bmp")
SET(VCREDIST32 "${OpenMW_BINARY_DIR}/vcredist_x86.exe") SET(VCREDIST32 "${OpenMW_BINARY_DIR}/vcredist_x86.exe")
@ -530,6 +554,16 @@ add_subdirectory (extern/sdl4ogre)
# Components # Components
add_subdirectory (components) add_subdirectory (components)
# Plugins
if (BUILD_MYGUI_PLUGIN)
add_subdirectory(plugins/mygui_resource_plugin)
endif()
#Testing
if (BUILD_NIFTEST)
add_subdirectory(components/nif/tests/)
endif(BUILD_NIFTEST)
# Apps and tools # Apps and tools
add_subdirectory( apps/openmw ) add_subdirectory( apps/openmw )
@ -567,6 +601,16 @@ endif()
if (WIN32) if (WIN32)
if (MSVC) if (MSVC)
if (MULTITHREADED_BUILD)
set( MT_BUILD "/MP")
endif (MULTITHREADED_BUILD)
foreach( OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES} )
string( TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG )
set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "$(SolutionDir)$(Configuration)" )
set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "$(ProjectDir)$(Configuration)" )
endforeach( OUTPUTCONFIG )
if (USE_DEBUG_CONSOLE) if (USE_DEBUG_CONSOLE)
set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE") set_target_properties(openmw PROPERTIES LINK_FLAGS_DEBUG "/SUBSYSTEM:CONSOLE")
set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:CONSOLE") set_target_properties(openmw PROPERTIES LINK_FLAGS_RELWITHDEBINFO "/SUBSYSTEM:CONSOLE")
@ -607,6 +651,9 @@ if (WIN32)
4251 # class 'XXXX' needs to have dll-interface to be used by clients of class 'YYYY' 4251 # class 'XXXX' needs to have dll-interface to be used by clients of class 'YYYY'
4275 # non dll-interface struct 'XXXX' used as base for dll-interface class 'YYYY' 4275 # non dll-interface struct 'XXXX' used as base for dll-interface class 'YYYY'
# caused by boost
4191 # 'type cast' : unsafe conversion (1.56, thread_primitives.hpp, normally off)
# OpenMW specific warnings # OpenMW specific warnings
4099 # Type mismatch, declared class or struct is defined with other type 4099 # Type mismatch, declared class or struct is defined with other type
4100 # Unreferenced formal parameter (-Wunused-parameter) 4100 # Unreferenced formal parameter (-Wunused-parameter)
@ -630,30 +677,32 @@ if (WIN32)
# boost::wave has a few issues with signed / unsigned conversions, so we suppress those here # boost::wave has a few issues with signed / unsigned conversions, so we suppress those here
set(SHINY_WARNINGS "${WARNINGS} /wd4245") set(SHINY_WARNINGS "${WARNINGS} /wd4245")
set_target_properties(shiny PROPERTIES COMPILE_FLAGS ${SHINY_WARNINGS}) set_target_properties(shiny PROPERTIES COMPILE_FLAGS "${SHINY_WARNINGS} ${MT_BUILD}")
# there's an unreferenced local variable in the ogre platform, suppress it # there's an unreferenced local variable in the ogre platform, suppress it
set(SHINY_OGRE_WARNINGS "${WARNINGS} /wd4101") set(SHINY_OGRE_WARNINGS "${WARNINGS} /wd4101")
set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS ${SHINY_OGRE_WARNINGS}) set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS "${SHINY_OGRE_WARNINGS} ${MT_BUILD}")
set_target_properties(sdl4ogre PROPERTIES COMPILE_FLAGS ${WARNINGS}) set_target_properties(sdl4ogre PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
# oics uses tinyxml, which has an initialized but unused variable # oics uses tinyxml, which has an initialized but unused variable
set(OICS_WARNINGS "${WARNINGS} /wd4189") set(OICS_WARNINGS "${WARNINGS} /wd4189")
set_target_properties(oics PROPERTIES COMPILE_FLAGS ${OICS_WARNINGS}) set_target_properties(oics PROPERTIES COMPILE_FLAGS "${OICS_WARNINGS} ${MT_BUILD}")
set_target_properties(components PROPERTIES COMPILE_FLAGS ${WARNINGS}) set_target_properties(components PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
if (BUILD_LAUNCHER) if (BUILD_LAUNCHER)
set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS ${WARNINGS}) set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_LAUNCHER) endif (BUILD_LAUNCHER)
set_target_properties(openmw PROPERTIES COMPILE_FLAGS ${WARNINGS}) set_target_properties(openmw PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
if (BUILD_BSATOOL) if (BUILD_BSATOOL)
set_target_properties(bsatool PROPERTIES COMPILE_FLAGS ${WARNINGS}) set_target_properties(bsatool PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
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} ${MT_BUILD}")
endif (BUILD_ESMTOOL) endif (BUILD_ESMTOOL)
if (BUILD_OPENCS) if (BUILD_OPENCS)
set_target_properties(opencs PROPERTIES COMPILE_FLAGS ${WARNINGS}) # QT triggers an informational warning that the object layout may differ when compiled with /vd2
set(OPENCS_WARNINGS "${WARNINGS} ${MT_BUILD} /wd4435")
set_target_properties(opencs PROPERTIES COMPILE_FLAGS ${OPENCS_WARNINGS})
endif (BUILD_OPENCS) endif (BUILD_OPENCS)
if (BUILD_MWINIIMPORTER) if (BUILD_MWINIIMPORTER)
set_target_properties(mwiniimport PROPERTIES COMPILE_FLAGS ${WARNINGS}) set_target_properties(mwiniimport PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif (BUILD_MWINIIMPORTER) endif (BUILD_MWINIIMPORTER)
endif(MSVC) endif(MSVC)

@ -249,6 +249,9 @@ void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info)
std::cout << " Refnum: " << ref.mRefNum.mIndex << std::endl; std::cout << " Refnum: " << ref.mRefNum.mIndex << std::endl;
std::cout << " ID: '" << ref.mRefID << "'\n"; std::cout << " ID: '" << ref.mRefID << "'\n";
std::cout << " Owner: '" << ref.mOwner << "'\n"; std::cout << " Owner: '" << ref.mOwner << "'\n";
std::cout << " Global: '" << ref.mGlobalVariable << "'" << std::endl;
std::cout << " Faction: '" << ref.mFaction << "'" << std::endl;
std::cout << " Faction rank: '" << ref.mFactionRank << "'" << std::endl;
std::cout << " Enchantment charge: '" << ref.mEnchantmentCharge << "'\n"; std::cout << " Enchantment charge: '" << ref.mEnchantmentCharge << "'\n";
std::cout << " Uses/health: '" << ref.mCharge << "'\n"; std::cout << " Uses/health: '" << ref.mCharge << "'\n";
std::cout << " Gold value: '" << ref.mGoldValue << "'\n"; std::cout << " Gold value: '" << ref.mGoldValue << "'\n";

File diff suppressed because it is too large Load Diff

@ -412,7 +412,7 @@ void Record<ESM::Armor>::print()
std::cout << " Armor: " << mData.mData.mArmor << std::endl; std::cout << " Armor: " << mData.mData.mArmor << std::endl;
std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl; std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl;
std::vector<ESM::PartReference>::iterator pit; std::vector<ESM::PartReference>::iterator pit;
for (pit = mData.mParts.mParts.begin(); pit != mData.mParts.mParts.end(); pit++) for (pit = mData.mParts.mParts.begin(); pit != mData.mParts.mParts.end(); ++pit)
{ {
std::cout << " Body Part: " << bodyPartLabel(pit->mPart) std::cout << " Body Part: " << bodyPartLabel(pit->mPart)
<< " (" << (int)(pit->mPart) << ")" << std::endl; << " (" << (int)(pit->mPart) << ")" << std::endl;
@ -484,7 +484,7 @@ void Record<ESM::BirthSign>::print()
std::cout << " Texture: " << mData.mTexture << std::endl; std::cout << " Texture: " << mData.mTexture << std::endl;
std::cout << " Description: " << mData.mDescription << std::endl; std::cout << " Description: " << mData.mDescription << std::endl;
std::vector<std::string>::iterator pit; std::vector<std::string>::iterator pit;
for (pit = mData.mPowers.mList.begin(); pit != mData.mPowers.mList.end(); pit++) for (pit = mData.mPowers.mList.begin(); pit != mData.mPowers.mList.end(); ++pit)
std::cout << " Power: " << *pit << std::endl; std::cout << " Power: " << *pit << std::endl;
} }
@ -513,7 +513,7 @@ void Record<ESM::Cell>::print()
else else
std::cout << " Map Color: " << boost::format("0x%08X") % mData.mMapColor << std::endl; std::cout << " Map Color: " << boost::format("0x%08X") % mData.mMapColor << std::endl;
std::cout << " Water Level Int: " << mData.mWaterInt << std::endl; std::cout << " Water Level Int: " << mData.mWaterInt << std::endl;
std::cout << " NAM0: " << mData.mNAM0 << std::endl; std::cout << " RefId counter: " << mData.mRefNumCounter << std::endl;
} }
@ -554,7 +554,7 @@ void Record<ESM::Clothing>::print()
std::cout << " Value: " << mData.mData.mValue << std::endl; std::cout << " Value: " << mData.mData.mValue << std::endl;
std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl; std::cout << " Enchantment Points: " << mData.mData.mEnchant << std::endl;
std::vector<ESM::PartReference>::iterator pit; std::vector<ESM::PartReference>::iterator pit;
for (pit = mData.mParts.mParts.begin(); pit != mData.mParts.mParts.end(); pit++) for (pit = mData.mParts.mParts.begin(); pit != mData.mParts.mParts.end(); ++pit)
{ {
std::cout << " Body Part: " << bodyPartLabel(pit->mPart) std::cout << " Body Part: " << bodyPartLabel(pit->mPart)
<< " (" << (int)(pit->mPart) << ")" << std::endl; << " (" << (int)(pit->mPart) << ")" << std::endl;
@ -574,7 +574,7 @@ void Record<ESM::Container>::print()
std::cout << " Flags: " << containerFlags(mData.mFlags) << std::endl; std::cout << " Flags: " << containerFlags(mData.mFlags) << std::endl;
std::cout << " Weight: " << mData.mWeight << std::endl; std::cout << " Weight: " << mData.mWeight << std::endl;
std::vector<ESM::ContItem>::iterator cit; std::vector<ESM::ContItem>::iterator cit;
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); cit++) for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); ++cit)
std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount
<< " Item: " << cit->mItem.toString() << std::endl; << " Item: " << cit->mItem.toString() << std::endl;
} }
@ -619,12 +619,12 @@ void Record<ESM::Creature>::print()
std::cout << " Gold: " << mData.mData.mGold << std::endl; std::cout << " Gold: " << mData.mData.mGold << std::endl;
std::vector<ESM::ContItem>::iterator cit; std::vector<ESM::ContItem>::iterator cit;
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); cit++) for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); ++cit)
std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount
<< " Item: " << cit->mItem.toString() << std::endl; << " Item: " << cit->mItem.toString() << std::endl;
std::vector<std::string>::iterator sit; std::vector<std::string>::iterator sit;
for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); sit++) for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit)
std::cout << " Spell: " << *sit << std::endl; std::cout << " Spell: " << *sit << std::endl;
std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl; std::cout << " Artifical Intelligence: " << mData.mHasAI << std::endl;
@ -639,7 +639,7 @@ void Record<ESM::Creature>::print()
std::cout << " AI Services:" << boost::format("0x%08X") % mData.mAiData.mServices << std::endl; std::cout << " AI Services:" << boost::format("0x%08X") % mData.mAiData.mServices << std::endl;
std::vector<ESM::AIPackage>::iterator pit; std::vector<ESM::AIPackage>::iterator pit;
for (pit = mData.mAiPackage.mList.begin(); pit != mData.mAiPackage.mList.end(); pit++) for (pit = mData.mAiPackage.mList.begin(); pit != mData.mAiPackage.mList.end(); ++pit)
printAIPackage(*pit); printAIPackage(*pit);
} }
@ -706,7 +706,7 @@ void Record<ESM::Faction>::print()
<< mData.mData.mRankData[i].mFactReaction << std::endl; << mData.mData.mRankData[i].mFactReaction << std::endl;
} }
std::map<std::string, int>::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->second << " = " << rit->first << std::endl; std::cout << " Reaction: " << rit->second << " = " << rit->first << std::endl;
} }
@ -763,7 +763,7 @@ void Record<ESM::DialInfo>::print()
std::cout << " Unknown2: " << (int)mData.mData.mUnknown2 << std::endl; std::cout << " Unknown2: " << (int)mData.mData.mUnknown2 << std::endl;
std::vector<ESM::DialInfo::SelectStruct>::iterator sit; std::vector<ESM::DialInfo::SelectStruct>::iterator sit;
for (sit = mData.mSelects.begin(); sit != mData.mSelects.end(); sit++) for (sit = mData.mSelects.begin(); sit != mData.mSelects.end(); ++sit)
std::cout << " Select Rule: " << ruleString(*sit) << std::endl; std::cout << " Select Rule: " << ruleString(*sit) << std::endl;
if (mData.mResultScript != "") if (mData.mResultScript != "")
@ -835,7 +835,7 @@ void Record<ESM::CreatureLevList>::print()
std::cout << " Flags: " << creatureListFlags(mData.mFlags) << std::endl; std::cout << " Flags: " << creatureListFlags(mData.mFlags) << std::endl;
std::cout << " Number of items: " << mData.mList.size() << std::endl; std::cout << " Number of items: " << mData.mList.size() << std::endl;
std::vector<ESM::LeveledListBase::LevelItem>::iterator iit; std::vector<ESM::LeveledListBase::LevelItem>::iterator iit;
for (iit = mData.mList.begin(); iit != mData.mList.end(); iit++) for (iit = mData.mList.begin(); iit != mData.mList.end(); ++iit)
std::cout << " Creature: Level: " << iit->mLevel std::cout << " Creature: Level: " << iit->mLevel
<< " Creature: " << iit->mId << std::endl; << " Creature: " << iit->mId << std::endl;
} }
@ -847,7 +847,7 @@ void Record<ESM::ItemLevList>::print()
std::cout << " Flags: " << itemListFlags(mData.mFlags) << std::endl; std::cout << " Flags: " << itemListFlags(mData.mFlags) << std::endl;
std::cout << " Number of items: " << mData.mList.size() << std::endl; std::cout << " Number of items: " << mData.mList.size() << std::endl;
std::vector<ESM::LeveledListBase::LevelItem>::iterator iit; std::vector<ESM::LeveledListBase::LevelItem>::iterator iit;
for (iit = mData.mList.begin(); iit != mData.mList.end(); iit++) for (iit = mData.mList.begin(); iit != mData.mList.end(); ++iit)
std::cout << " Inventory: Level: " << iit->mLevel std::cout << " Inventory: Level: " << iit->mLevel
<< " Item: " << iit->mId << std::endl; << " Item: " << iit->mId << std::endl;
} }
@ -950,9 +950,9 @@ void Record<ESM::MagicEffect>::print()
std::cout << " School: " << schoolLabel(mData.mData.mSchool) std::cout << " School: " << schoolLabel(mData.mData.mSchool)
<< " (" << mData.mData.mSchool << ")" << std::endl; << " (" << mData.mData.mSchool << ")" << std::endl;
std::cout << " Base Cost: " << mData.mData.mBaseCost << std::endl; std::cout << " Base Cost: " << mData.mData.mBaseCost << std::endl;
std::cout << " Unknown 1: " << mData.mData.mUnknown1 << std::endl;
std::cout << " Speed: " << mData.mData.mSpeed << std::endl; std::cout << " Speed: " << mData.mData.mSpeed << std::endl;
std::cout << " Size: " << mData.mData.mSize << std::endl; std::cout << " Unknown 2: " << mData.mData.mUnknown2 << std::endl;
std::cout << " Size Cap: " << mData.mData.mSizeCap << std::endl;
std::cout << " RGB Color: " << "(" std::cout << " RGB Color: " << "("
<< mData.mData.mRed << "," << mData.mData.mRed << ","
<< mData.mData.mGreen << "," << mData.mData.mGreen << ","
@ -992,7 +992,6 @@ void Record<ESM::NPC>::print()
std::cout << " Level: " << mData.mNpdt12.mLevel << std::endl; std::cout << " Level: " << mData.mNpdt12.mLevel << std::endl;
std::cout << " Reputation: " << (int)mData.mNpdt12.mReputation << std::endl; std::cout << " Reputation: " << (int)mData.mNpdt12.mReputation << std::endl;
std::cout << " Disposition: " << (int)mData.mNpdt12.mDisposition << std::endl; std::cout << " Disposition: " << (int)mData.mNpdt12.mDisposition << std::endl;
std::cout << " Faction: " << (int)mData.mNpdt52.mFactionID << std::endl;
std::cout << " Rank: " << (int)mData.mNpdt12.mRank << std::endl; std::cout << " Rank: " << (int)mData.mNpdt12.mRank << std::endl;
std::cout << " Unknown1: " std::cout << " Unknown1: "
<< (unsigned int)((unsigned char)mData.mNpdt12.mUnknown1) << std::endl; << (unsigned int)((unsigned char)mData.mNpdt12.mUnknown1) << std::endl;
@ -1007,6 +1006,7 @@ void Record<ESM::NPC>::print()
std::cout << " Reputation: " << (int)mData.mNpdt52.mReputation << std::endl; std::cout << " Reputation: " << (int)mData.mNpdt52.mReputation << std::endl;
std::cout << " Disposition: " << (int)mData.mNpdt52.mDisposition << std::endl; std::cout << " Disposition: " << (int)mData.mNpdt52.mDisposition << std::endl;
std::cout << " Rank: " << (int)mData.mNpdt52.mRank << std::endl; std::cout << " Rank: " << (int)mData.mNpdt52.mRank << std::endl;
std::cout << " FactionID: " << (int)mData.mNpdt52.mFactionID << std::endl;
std::cout << " Attributes:" << std::endl; std::cout << " Attributes:" << std::endl;
std::cout << " Strength: " << (int)mData.mNpdt52.mStrength << std::endl; std::cout << " Strength: " << (int)mData.mNpdt52.mStrength << std::endl;
@ -1031,16 +1031,16 @@ void Record<ESM::NPC>::print()
} }
std::vector<ESM::ContItem>::iterator cit; std::vector<ESM::ContItem>::iterator cit;
for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); cit++) for (cit = mData.mInventory.mList.begin(); cit != mData.mInventory.mList.end(); ++cit)
std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount std::cout << " Inventory: Count: " << boost::format("%4d") % cit->mCount
<< " Item: " << cit->mItem.toString() << std::endl; << " Item: " << cit->mItem.toString() << std::endl;
std::vector<std::string>::iterator sit; std::vector<std::string>::iterator sit;
for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); sit++) for (sit = mData.mSpells.mList.begin(); sit != mData.mSpells.mList.end(); ++sit)
std::cout << " Spell: " << *sit << std::endl; std::cout << " Spell: " << *sit << std::endl;
std::vector<ESM::NPC::Dest>::iterator dit; std::vector<ESM::NPC::Dest>::iterator dit;
for (dit = mData.mTransport.begin(); dit != mData.mTransport.end(); dit++) for (dit = mData.mTransport.begin(); dit != mData.mTransport.end(); ++dit)
{ {
std::cout << " Destination Position: " std::cout << " Destination Position: "
<< boost::format("%12.3f") % dit->mPos.pos[0] << "," << boost::format("%12.3f") % dit->mPos.pos[0] << ","
@ -1066,7 +1066,7 @@ void Record<ESM::NPC>::print()
std::cout << " AI Services:" << boost::format("0x%08X") % mData.mAiData.mServices << std::endl; std::cout << " AI Services:" << boost::format("0x%08X") % mData.mAiData.mServices << std::endl;
std::vector<ESM::AIPackage>::iterator pit; std::vector<ESM::AIPackage>::iterator pit;
for (pit = mData.mAiPackage.mList.begin(); pit != mData.mAiPackage.mList.end(); pit++) for (pit = mData.mAiPackage.mList.begin(); pit != mData.mAiPackage.mList.end(); ++pit)
printAIPackage(*pit); printAIPackage(*pit);
} }
@ -1140,7 +1140,7 @@ void Record<ESM::Race>::print()
<< mData.mData.mBonus[i].mBonus << std::endl; << mData.mData.mBonus[i].mBonus << std::endl;
std::vector<std::string>::iterator sit; std::vector<std::string>::iterator sit;
for (sit = mData.mPowers.mList.begin(); sit != mData.mPowers.mList.end(); sit++) for (sit = mData.mPowers.mList.begin(); sit != mData.mPowers.mList.end(); ++sit)
std::cout << " Power: " << *sit << std::endl; std::cout << " Power: " << *sit << std::endl;
} }
@ -1164,7 +1164,7 @@ void Record<ESM::Region>::print()
if (mData.mSleepList != "") if (mData.mSleepList != "")
std::cout << " Sleep List: " << mData.mSleepList << std::endl; std::cout << " Sleep List: " << mData.mSleepList << std::endl;
std::vector<ESM::Region::SoundRef>::iterator sit; std::vector<ESM::Region::SoundRef>::iterator sit;
for (sit = mData.mSoundList.begin(); sit != mData.mSoundList.end(); sit++) for (sit = mData.mSoundList.begin(); sit != mData.mSoundList.end(); ++sit)
std::cout << " Sound: " << (int)sit->mChance << " = " << sit->mSound.toString() << std::endl; std::cout << " Sound: " << (int)sit->mChance << " = " << sit->mSound.toString() << std::endl;
} }
@ -1181,12 +1181,12 @@ void Record<ESM::Script>::print()
std::vector<std::string>::iterator vit; std::vector<std::string>::iterator vit;
for (vit = mData.mVarNames.begin(); vit != mData.mVarNames.end(); vit++) for (vit = mData.mVarNames.begin(); vit != mData.mVarNames.end(); ++vit)
std::cout << " Variable: " << *vit << std::endl; std::cout << " Variable: " << *vit << std::endl;
std::cout << " ByteCode: "; std::cout << " ByteCode: ";
std::vector<unsigned char>::iterator cit; std::vector<unsigned char>::iterator cit;
for (cit = mData.mScriptData.begin(); cit != mData.mScriptData.end(); cit++) for (cit = mData.mScriptData.begin(); cit != mData.mScriptData.end(); ++cit)
std::cout << boost::format("%02X") % (int)(*cit); std::cout << boost::format("%02X") % (int)(*cit);
std::cout << std::endl; std::cout << std::endl;

@ -15,7 +15,7 @@ set(LAUNCHER
utils/textinputdialog.cpp utils/textinputdialog.cpp
utils/lineedit.cpp utils/lineedit.cpp
${CMAKE_SOURCE_DIR}/files/launcher/launcher.rc ${CMAKE_SOURCE_DIR}/files/windows/launcher.rc
) )
if(NOT WIN32) if(NOT WIN32)
LIST(APPEND LAUNCHER unshieldthread.cpp) LIST(APPEND LAUNCHER unshieldthread.cpp)

@ -15,6 +15,7 @@ namespace bfs = boost::filesystem;
MwIniImporter::MwIniImporter() MwIniImporter::MwIniImporter()
: mVerbose(false) : mVerbose(false)
, mEncoding(ToUTF8::WINDOWS_1250)
{ {
const char *map[][2] = const char *map[][2] =
{ {
@ -709,8 +710,7 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(const std::string& filenam
continue; continue;
} }
multistrmap::iterator it; if(map.find(key) == map.end()) {
if((it = map.find(key)) == map.end()) {
map.insert( std::make_pair (key, std::vector<std::string>() ) ); map.insert( std::make_pair (key, std::vector<std::string>() ) );
} }
map[key].push_back(value); map[key].push_back(value);
@ -746,8 +746,7 @@ MwIniImporter::multistrmap MwIniImporter::loadCfgFile(const std::string& filenam
std::string key(line.substr(0,pos)); std::string key(line.substr(0,pos));
std::string value(line.substr(pos+1)); std::string value(line.substr(pos+1));
multistrmap::iterator it; if(map.find(key) == map.end()) {
if((it = map.find(key)) == map.end()) {
map.insert( std::make_pair (key, std::vector<std::string>() ) ); map.insert( std::make_pair (key, std::vector<std::string>() ) );
} }
map[key].push_back(value); map[key].push_back(value);

@ -37,6 +37,8 @@ public:
char **get() const { return const_cast<char **>(argv); } char **get() const { return const_cast<char **>(argv); }
private: private:
utf8argv(const utf8argv&);
utf8argv& operator=(const utf8argv&);
const char **argv; const char **argv;
std::vector<std::string> args; std::vector<std::string> args;

@ -1,15 +1,17 @@
set (OPENCS_SRC main.cpp) set (OPENCS_SRC main.cpp
${CMAKE_SOURCE_DIR}/files/windows/opencs.rc
)
opencs_units (. editor) opencs_units (. editor)
set (CMAKE_BUILD_TYPE DEBUG) set (CMAKE_BUILD_TYPE DEBUG)
opencs_units (model/doc opencs_units (model/doc
document operation saving documentmanager loader document operation saving documentmanager loader runner
) )
opencs_units_noqt (model/doc opencs_units_noqt (model/doc
stage savingstate savingstages stage savingstate savingstages blacklist
) )
opencs_hdrs_noqt (model/doc opencs_hdrs_noqt (model/doc
@ -24,7 +26,7 @@ opencs_units (model/world
opencs_units_noqt (model/world opencs_units_noqt (model/world
universalid record commands columnbase scriptcontext cell refidcollection universalid record commands columnbase scriptcontext cell refidcollection
refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager refidadapter refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope
) )
opencs_hdrs_noqt (model/world opencs_hdrs_noqt (model/world
@ -38,13 +40,13 @@ opencs_units (model/tools
opencs_units_noqt (model/tools opencs_units_noqt (model/tools
mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
birthsigncheck spellcheck referenceablecheck scriptcheck birthsigncheck spellcheck referenceablecheck scriptcheck bodypartcheck
) )
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 loader filewidget adjusterwidget loader globaldebugprofilemenu runlogsubview
) )
@ -69,7 +71,7 @@ opencs_units_noqt (view/world
) )
opencs_units (view/widget opencs_units (view/widget
scenetoolbar scenetool scenetoolmode pushbutton scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun
) )
opencs_units (view/render opencs_units (view/render
@ -82,6 +84,10 @@ opencs_units_noqt (view/render
lightingbright object cell lightingbright object cell
) )
opencs_hdrs_noqt (view/render
elements
)
opencs_units (view/tools opencs_units (view/tools
reportsubview reportsubview
@ -122,12 +128,8 @@ opencs_units_noqt (model/filter
node unarynode narynode leafnode booleannode parser andnode ornode notnode textnode valuenode node unarynode narynode leafnode booleannode parser andnode ornode notnode textnode valuenode
) )
opencs_hdrs_noqt (model/filter
filter
)
opencs_units (view/filter opencs_units (view/filter
filtercreator filterbox recordfilterbox editwidget filterbox recordfilterbox editwidget
) )
set (OPENCS_US set (OPENCS_US

@ -80,13 +80,17 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
boost::program_options::options_description desc("Syntax: opencs <options>\nAllowed options"); boost::program_options::options_description desc("Syntax: opencs <options>\nAllowed options");
desc.add_options() desc.add_options()
("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken()) ("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken()->composing())
("data-local", boost::program_options::value<std::string>()->default_value("")) ("data-local", boost::program_options::value<std::string>()->default_value(""))
("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false)) ("fs-strict", boost::program_options::value<bool>()->implicit_value(true)->default_value(false))
("encoding", boost::program_options::value<std::string>()->default_value("win1252")) ("encoding", boost::program_options::value<std::string>()->default_value("win1252"))
("resources", boost::program_options::value<std::string>()->default_value("resources")) ("resources", boost::program_options::value<std::string>()->default_value("resources"))
("fallback-archive", boost::program_options::value<std::vector<std::string> >()-> ("fallback-archive", boost::program_options::value<std::vector<std::string> >()->
default_value(std::vector<std::string>(), "fallback-archive")->multitoken()); default_value(std::vector<std::string>(), "fallback-archive")->multitoken())
("script-blacklist", boost::program_options::value<std::vector<std::string> >()->default_value(std::vector<std::string>(), "")
->multitoken(), "exclude specified script from the verifier (if the use of the blacklist is enabled)")
("script-blacklist-use", boost::program_options::value<bool>()->implicit_value(true)
->default_value(true), "enable script blacklisting");
boost::program_options::notify(variables); boost::program_options::notify(variables);
@ -97,6 +101,10 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi
mDocumentManager.setResourceDir (mResources = variables["resources"].as<std::string>()); mDocumentManager.setResourceDir (mResources = variables["resources"].as<std::string>());
if (variables["script-blacklist-use"].as<bool>())
mDocumentManager.setBlacklistedScripts (
variables["script-blacklist"].as<std::vector<std::string> >());
mFsStrict = variables["fs-strict"].as<bool>(); mFsStrict = variables["fs-strict"].as<bool>();
Files::PathContainer dataDirs, dataLocal; Files::PathContainer dataDirs, dataLocal;
@ -181,7 +189,7 @@ void CS::Editor::createNewFile (const boost::filesystem::path &savePath)
files.push_back(path.toUtf8().constData()); files.push_back(path.toUtf8().constData());
} }
files.push_back(mFileDialog.filename().toUtf8().constData()); files.push_back (savePath);
mDocumentManager.addDocument (files, savePath, true); mDocumentManager.addDocument (files, savePath, true);

@ -16,6 +16,8 @@
#include <components/files/multidircollection.hpp> #include <components/files/multidircollection.hpp>
#include <components/nifcache/nifcache.hpp>
#include "model/settings/usersettings.hpp" #include "model/settings/usersettings.hpp"
#include "model/doc/documentmanager.hpp" #include "model/doc/documentmanager.hpp"
@ -37,6 +39,7 @@ namespace CS
{ {
Q_OBJECT Q_OBJECT
Nif::Cache mNifCache;
Files::ConfigurationManager mCfgMgr; Files::ConfigurationManager mCfgMgr;
CSMSettings::UserSettings mUserSettings; CSMSettings::UserSettings mUserSettings;
CSMDoc::DocumentManager mDocumentManager; CSMDoc::DocumentManager mDocumentManager;

@ -0,0 +1,31 @@
#include "blacklist.hpp"
#include <algorithm>
#include <components/misc/stringops.hpp>
bool CSMDoc::Blacklist::isBlacklisted (const CSMWorld::UniversalId& id) const
{
std::map<CSMWorld::UniversalId::Type, std::vector<std::string> >::const_iterator iter =
mIds.find (id.getType());
if (iter==mIds.end())
return false;
return std::binary_search (iter->second.begin(), iter->second.end(),
Misc::StringUtils::lowerCase (id.getId()));
}
void CSMDoc::Blacklist::add (CSMWorld::UniversalId::Type type,
const std::vector<std::string>& ids)
{
std::vector<std::string>& list = mIds[type];
int size = list.size();
list.resize (size+ids.size());
std::transform (ids.begin(), ids.end(), list.begin()+size, Misc::StringUtils::lowerCase);
std::sort (list.begin(), list.end());
}

@ -0,0 +1,25 @@
#ifndef CSM_DOC_BLACKLIST_H
#define CSM_DOC_BLACKLIST_H
#include <map>
#include <vector>
#include <string>
#include "../world/universalid.hpp"
namespace CSMDoc
{
/// \brief ID blacklist sorted by UniversalId type
class Blacklist
{
std::map<CSMWorld::UniversalId::Type, std::vector<std::string> > mIds;
public:
bool isBlacklisted (const CSMWorld::UniversalId& id) const;
void add (CSMWorld::UniversalId::Type type, const std::vector<std::string>& ids);
};
}
#endif

@ -1,6 +1,7 @@
#include "document.hpp" #include "document.hpp"
#include <cassert> #include <cassert>
#include <fstream>
#include <iostream> #include <iostream>
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
@ -2206,28 +2207,32 @@ void CSMDoc::Document::createBase()
CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
const std::vector< boost::filesystem::path >& files, bool new_, const std::vector< boost::filesystem::path >& files, bool new_,
const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir,
ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager) ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager,
const std::vector<std::string>& blacklistedScripts)
: mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding, resourcesManager), : mSavePath (savePath), mContentFiles (files), mNew (new_), mData (encoding, resourcesManager),
mTools (mData), mResDir(resDir), mTools (*this), mResDir(resDir),
mProjectPath ((configuration.getUserDataPath() / "projects") / mProjectPath ((configuration.getUserDataPath() / "projects") /
(savePath.filename().string() + ".project")), (savePath.filename().string() + ".project")),
mSaving (*this, mProjectPath, encoding) mSaving (*this, mProjectPath, encoding),
mRunner (mProjectPath)
{ {
if (mContentFiles.empty()) if (mContentFiles.empty())
throw std::runtime_error ("Empty content file sequence"); throw std::runtime_error ("Empty content file sequence");
if (!boost::filesystem::exists (mProjectPath)) if (!boost::filesystem::exists (mProjectPath))
{ {
boost::filesystem::path locCustomFiltersPath (configuration.getUserDataPath()); boost::filesystem::path customFiltersPath (configuration.getUserDataPath());
locCustomFiltersPath /= "defaultfilters"; customFiltersPath /= "defaultfilters";
if (boost::filesystem::exists (locCustomFiltersPath)) std::ofstream destination (mProjectPath.string().c_str(), std::ios::binary);
if (boost::filesystem::exists (customFiltersPath))
{ {
boost::filesystem::copy_file (locCustomFiltersPath, mProjectPath); destination << std::ifstream(customFiltersPath.c_str(), std::ios::binary).rdbuf();
} }
else else
{ {
boost::filesystem::copy_file (mResDir / "defaultfilters", mProjectPath); destination << std::ifstream(std::string(mResDir.string() + "/defaultfilters").c_str(), std::ios::binary).rdbuf();
} }
} }
@ -2240,20 +2245,24 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
createBase(); createBase();
} }
mBlacklist.add (CSMWorld::UniversalId::Type_Script, blacklistedScripts);
addOptionalGmsts(); addOptionalGmsts();
addOptionalGlobals(); addOptionalGlobals();
connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool))); connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool)));
connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int))); connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
connect (&mTools, SIGNAL (done (int)), this, SLOT (operationDone (int))); connect (&mTools, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool)));
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, bool)), this, SLOT (operationDone (int, bool)));
connect ( connect (
&mSaving, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, int)), &mSaving, SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, int)),
this, SLOT (reportMessage (const CSMWorld::UniversalId&, const std::string&, int))); this, SLOT (reportMessage (const CSMWorld::UniversalId&, const std::string&, int)));
connect (&mRunner, SIGNAL (runStateChanged()), this, SLOT (runStateChanged()));
} }
CSMDoc::Document::~Document() CSMDoc::Document::~Document()
@ -2275,6 +2284,9 @@ int CSMDoc::Document::getState() const
if (mSaving.isRunning()) if (mSaving.isRunning())
state |= State_Locked | State_Saving | State_Operation; state |= State_Locked | State_Saving | State_Operation;
if (mRunner.isRunning())
state |= State_Locked | State_Running;
if (int operations = mTools.getRunningOperations()) if (int operations = mTools.getRunningOperations())
state |= State_Locked | State_Operation | operations; state |= State_Locked | State_Operation | operations;
@ -2339,7 +2351,7 @@ void CSMDoc::Document::reportMessage (const CSMWorld::UniversalId& id, const std
std::cout << message << std::endl; std::cout << message << std::endl;
} }
void CSMDoc::Document::operationDone (int type) void CSMDoc::Document::operationDone (int type, bool failed)
{ {
emit stateChanged (getState(), this); emit stateChanged (getState(), this);
} }
@ -2359,6 +2371,55 @@ CSMTools::ReportModel *CSMDoc::Document::getReport (const CSMWorld::UniversalId&
return mTools.getReport (id); return mTools.getReport (id);
} }
bool CSMDoc::Document::isBlacklisted (const CSMWorld::UniversalId& id)
const
{
return mBlacklist.isBlacklisted (id);
}
void CSMDoc::Document::startRunning (const std::string& profile,
const std::string& startupInstruction)
{
std::vector<std::string> contentFiles;
for (std::vector<boost::filesystem::path>::const_iterator iter (mContentFiles.begin());
iter!=mContentFiles.end(); ++iter)
contentFiles.push_back (iter->filename().string());
mRunner.configure (getData().getDebugProfiles().getRecord (profile).get(), contentFiles,
startupInstruction);
int state = getState();
if (state & State_Modified)
{
// need to save first
mRunner.start (true);
new SaveWatcher (&mRunner, &mSaving); // no, that is not a memory leak. Qt is weird.
if (!(state & State_Saving))
save();
}
else
mRunner.start();
}
void CSMDoc::Document::stopRunning()
{
mRunner.stop();
}
QTextDocument *CSMDoc::Document::getRunLog()
{
return mRunner.getLog();
}
void CSMDoc::Document::runStateChanged()
{
emit stateChanged (getState(), this);
}
void CSMDoc::Document::progress (int current, int max, int type) void CSMDoc::Document::progress (int current, int max, int type)
{ {
emit progress (current, max, type, 1, this); emit progress (current, max, type, 1, this);

@ -17,6 +17,8 @@
#include "state.hpp" #include "state.hpp"
#include "saving.hpp" #include "saving.hpp"
#include "blacklist.hpp"
#include "runner.hpp"
class QAbstractItemModel; class QAbstractItemModel;
@ -52,6 +54,8 @@ namespace CSMDoc
boost::filesystem::path mProjectPath; boost::filesystem::path mProjectPath;
Saving mSaving; Saving mSaving;
boost::filesystem::path mResDir; boost::filesystem::path mResDir;
Blacklist mBlacklist;
Runner mRunner;
// It is important that the undo stack is declared last, because on desctruction it fires a signal, that is connected to a slot, that is // It is important that the undo stack is declared last, because on desctruction it fires a signal, that is connected to a slot, that is
// using other member variables. Unfortunately this connection is cut only in the QObject destructor, which is way too late. // using other member variables. Unfortunately this connection is cut only in the QObject destructor, which is way too late.
@ -78,7 +82,8 @@ namespace CSMDoc
Document (const Files::ConfigurationManager& configuration, Document (const Files::ConfigurationManager& configuration,
const std::vector< boost::filesystem::path >& files, bool new_, const std::vector< boost::filesystem::path >& files, bool new_,
const boost::filesystem::path& savePath, const boost::filesystem::path& resDir, const boost::filesystem::path& savePath, const boost::filesystem::path& resDir,
ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager); ToUTF8::FromType encoding, const CSMWorld::ResourcesManager& resourcesManager,
const std::vector<std::string>& blacklistedScripts);
~Document(); ~Document();
@ -110,6 +115,15 @@ namespace CSMDoc
CSMTools::ReportModel *getReport (const CSMWorld::UniversalId& id); CSMTools::ReportModel *getReport (const CSMWorld::UniversalId& id);
///< The ownership of the returned report is not transferred. ///< The ownership of the returned report is not transferred.
bool isBlacklisted (const CSMWorld::UniversalId& id) const;
void startRunning (const std::string& profile,
const std::string& startupInstruction = "");
void stopRunning();
QTextDocument *getRunLog();
signals: signals:
void stateChanged (int state, CSMDoc::Document *document); void stateChanged (int state, CSMDoc::Document *document);
@ -123,7 +137,9 @@ namespace CSMDoc
void reportMessage (const CSMWorld::UniversalId& id, const std::string& message, void reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
int type); int type);
void operationDone (int type); void operationDone (int type, bool failed);
void runStateChanged();
public slots: public slots:

@ -52,7 +52,7 @@ CSMDoc::DocumentManager::~DocumentManager()
void 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, new_, savePath, mResDir, mEncoding, mResourcesManager); Document *document = new Document (mConfiguration, files, new_, savePath, mResDir, mEncoding, mResourcesManager, mBlacklistedScripts);
mDocuments.push_back (document); mDocuments.push_back (document);
@ -85,6 +85,11 @@ void CSMDoc::DocumentManager::setEncoding (ToUTF8::FromType encoding)
mEncoding = encoding; mEncoding = encoding;
} }
void CSMDoc::DocumentManager::setBlacklistedScripts (const std::vector<std::string>& scriptIds)
{
mBlacklistedScripts = scriptIds;
}
void CSMDoc::DocumentManager::listResources() void CSMDoc::DocumentManager::listResources()
{ {
mResourcesManager.listResources(); mResourcesManager.listResources();

@ -34,6 +34,7 @@ namespace CSMDoc
Loader mLoader; Loader mLoader;
ToUTF8::FromType mEncoding; ToUTF8::FromType mEncoding;
CSMWorld::ResourcesManager mResourcesManager; CSMWorld::ResourcesManager mResourcesManager;
std::vector<std::string> mBlacklistedScripts;
DocumentManager (const DocumentManager&); DocumentManager (const DocumentManager&);
DocumentManager& operator= (const DocumentManager&); DocumentManager& operator= (const DocumentManager&);
@ -53,6 +54,8 @@ namespace CSMDoc
void setEncoding (ToUTF8::FromType encoding); void setEncoding (ToUTF8::FromType encoding);
void setBlacklistedScripts (const std::vector<std::string>& scriptIds);
/// Ask OGRE for a list of available resources. /// Ask OGRE for a list of available resources.
void listResources(); void listResources();

@ -119,5 +119,5 @@ void CSMDoc::Operation::executeStage()
void CSMDoc::Operation::operationDone() void CSMDoc::Operation::operationDone()
{ {
emit done (mType); emit done (mType, mError);
} }

@ -54,7 +54,7 @@ namespace CSMDoc
void reportMessage (const CSMWorld::UniversalId& id, const std::string& message, void reportMessage (const CSMWorld::UniversalId& id, const std::string& message,
int type); int type);
void done (int type); void done (int type, bool failed);
public slots: public slots:

@ -0,0 +1,162 @@
#include "runner.hpp"
#include <QApplication>
#include <QDir>
#include <QTemporaryFile>
#include <QTextStream>
#include "operation.hpp"
CSMDoc::Runner::Runner (const boost::filesystem::path& projectPath)
: mRunning (false), mStartup (0), mProjectPath (projectPath)
{
connect (&mProcess, SIGNAL (finished (int, QProcess::ExitStatus)),
this, SLOT (finished (int, QProcess::ExitStatus)));
connect (&mProcess, SIGNAL (readyReadStandardOutput()),
this, SLOT (readyReadStandardOutput()));
mProcess.setProcessChannelMode (QProcess::MergedChannels);
mProfile.blank();
}
CSMDoc::Runner::~Runner()
{
if (mRunning)
{
disconnect (&mProcess, 0, this, 0);
mProcess.kill();
mProcess.waitForFinished();
}
}
void CSMDoc::Runner::start (bool delayed)
{
if (mStartup)
{
delete mStartup;
mStartup = 0;
}
if (!delayed)
{
mLog.clear();
QString path = "openmw";
#ifdef Q_OS_WIN
path.append(QString(".exe"));
#elif defined(Q_OS_MAC)
QDir dir(QCoreApplication::applicationDirPath());
dir.cdUp();
dir.cdUp();
dir.cdUp();
path = dir.absoluteFilePath(path.prepend("OpenMW.app/Contents/MacOS/"));
#else
path.prepend(QString("./"));
#endif
mStartup = new QTemporaryFile (this);
mStartup->open();
{
QTextStream stream (mStartup);
if (!mStartupInstruction.empty())
stream << QString::fromUtf8 (mStartupInstruction.c_str()) << '\n';
stream << QString::fromUtf8 (mProfile.mScriptText.c_str());
}
mStartup->close();
QStringList arguments;
arguments << "--skip-menu";
if (mProfile.mFlags & ESM::DebugProfile::Flag_BypassNewGame)
arguments << "--new-game=0";
else
arguments << "--new-game=1";
arguments << ("--script-run="+mStartup->fileName());;
arguments <<
QString::fromUtf8 (("--data="+mProjectPath.parent_path().string()).c_str());
for (std::vector<std::string>::const_iterator iter (mContentFiles.begin());
iter!=mContentFiles.end(); ++iter)
{
arguments << QString::fromUtf8 (("--content="+*iter).c_str());
}
arguments
<< QString::fromUtf8 (("--content="+mProjectPath.filename().string()).c_str());
mProcess.start (path, arguments);
}
mRunning = true;
emit runStateChanged();
}
void CSMDoc::Runner::stop()
{
delete mStartup;
mStartup = 0;
if (mProcess.state()==QProcess::NotRunning)
{
mRunning = false;
emit runStateChanged();
}
else
mProcess.kill();
}
bool CSMDoc::Runner::isRunning() const
{
return mRunning;
}
void CSMDoc::Runner::configure (const ESM::DebugProfile& profile,
const std::vector<std::string>& contentFiles, const std::string& startupInstruction)
{
mProfile = profile;
mContentFiles = contentFiles;
mStartupInstruction = startupInstruction;
}
void CSMDoc::Runner::finished (int exitCode, QProcess::ExitStatus exitStatus)
{
mRunning = false;
emit runStateChanged();
}
QTextDocument *CSMDoc::Runner::getLog()
{
return &mLog;
}
void CSMDoc::Runner::readyReadStandardOutput()
{
mLog.setPlainText (
mLog.toPlainText() + QString::fromUtf8 (mProcess.readAllStandardOutput()));
}
CSMDoc::SaveWatcher::SaveWatcher (Runner *runner, Operation *operation)
: QObject (runner), mRunner (runner)
{
connect (operation, SIGNAL (done (int, bool)), this, SLOT (saveDone (int, bool)));
}
void CSMDoc::SaveWatcher::saveDone (int type, bool failed)
{
if (failed)
mRunner->stop();
else
mRunner->start();
deleteLater();
}

@ -0,0 +1,85 @@
#ifndef CSM_DOC_RUNNER_H
#define CSM_DOC_RUNNER_H
#include <vector>
#include <string>
#include <boost/filesystem/path.hpp>
#include <QObject>
#include <QProcess>
#include <QTextDocument>
#include <components/esm/debugprofile.hpp>
class QTemporaryFile;
namespace CSMDoc
{
class Runner : public QObject
{
Q_OBJECT
QProcess mProcess;
bool mRunning;
ESM::DebugProfile mProfile;
std::vector<std::string> mContentFiles;
std::string mStartupInstruction;
QTemporaryFile *mStartup;
QTextDocument mLog;
boost::filesystem::path mProjectPath;
public:
Runner (const boost::filesystem::path& projectPath);
~Runner();
/// \param delayed Flag as running but do not start the OpenMW process yet (the
/// process must be started by another call of start with delayed==false)
void start (bool delayed = false);
void stop();
/// \note Running state is entered when the start function is called. This
/// is not necessarily identical to the moment the child process is started.
bool isRunning() const;
void configure (const ESM::DebugProfile& profile,
const std::vector<std::string>& contentFiles,
const std::string& startupInstruction);
QTextDocument *getLog();
signals:
void runStateChanged();
private slots:
void finished (int exitCode, QProcess::ExitStatus exitStatus);
void readyReadStandardOutput();
};
class Operation;
/// \brief Watch for end of save operation and restart or stop runner
class SaveWatcher : public QObject
{
Q_OBJECT
Runner *mRunner;
public:
/// *this attaches itself to runner
SaveWatcher (Runner *runner, Operation *operation);
private slots:
void saveDone (int type, bool failed);
};
}
#endif

@ -17,7 +17,14 @@ CSMDoc::Saving::Saving (Document& document, const boost::filesystem::path& proje
appendStage (new WriteHeaderStage (mDocument, mState, true)); appendStage (new WriteHeaderStage (mDocument, mState, true));
appendStage (new WriteFilterStage (mDocument, mState, CSMFilter::Filter::Scope_Project)); appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Filter> > (
mDocument.getData().getFilters(), mState, CSMWorld::Scope_Project));
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::DebugProfile> > (
mDocument.getData().getDebugProfiles(), mState, CSMWorld::Scope_Project));
appendStage (new WriteCollectionStage<CSMWorld::IdCollection<ESM::Script> > (
mDocument.getData().getScripts(), mState, CSMWorld::Scope_Project));
appendStage (new CloseSaveStage (mState)); appendStage (new CloseSaveStage (mState));

@ -201,23 +201,6 @@ void CSMDoc::WriteRefIdCollectionStage::perform (int stage, Messages& messages)
} }
CSMDoc::WriteFilterStage::WriteFilterStage (Document& document, SavingState& state,
CSMFilter::Filter::Scope scope)
: WriteCollectionStage<CSMWorld::IdCollection<CSMFilter::Filter> > (document.getData().getFilters(),
state),
mDocument (document), mScope (scope)
{}
void CSMDoc::WriteFilterStage::perform (int stage, Messages& messages)
{
const CSMWorld::Record<CSMFilter::Filter>& record =
mDocument.getData().getFilters().getRecord (stage);
if (record.get().mScope==mScope)
WriteCollectionStage<CSMWorld::IdCollection<CSMFilter::Filter> >::perform (stage, messages);
}
CSMDoc::CollectionReferencesStage::CollectionReferencesStage (Document& document, CSMDoc::CollectionReferencesStage::CollectionReferencesStage (Document& document,
SavingState& state) SavingState& state)
: mDocument (document), mState (state) : mDocument (document), mState (state)
@ -301,20 +284,6 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages)
// write references // write references
if (references!=mState.getSubRecords().end()) 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()); for (std::vector<int>::const_iterator iter (references->second.begin());
iter!=references->second.end(); ++iter) iter!=references->second.end(); ++iter)
{ {
@ -324,20 +293,7 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages)
if (ref.mState==CSMWorld::RecordBase::State_Modified || if (ref.mState==CSMWorld::RecordBase::State_Modified ||
ref.mState==CSMWorld::RecordBase::State_ModifiedOnly) ref.mState==CSMWorld::RecordBase::State_ModifiedOnly)
{ {
if (ref.get().mRefNum.mContentFile==-2) ref.get().save (mState.getWriter());
{
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) else if (ref.mState==CSMWorld::RecordBase::State_Deleted)
{ {

@ -5,8 +5,7 @@
#include "../world/record.hpp" #include "../world/record.hpp"
#include "../world/idcollection.hpp" #include "../world/idcollection.hpp"
#include "../world/scope.hpp"
#include "../filter/filter.hpp"
#include "savingstate.hpp" #include "savingstate.hpp"
@ -67,10 +66,12 @@ namespace CSMDoc
{ {
const CollectionT& mCollection; const CollectionT& mCollection;
SavingState& mState; SavingState& mState;
CSMWorld::Scope mScope;
public: public:
WriteCollectionStage (const CollectionT& collection, SavingState& state); WriteCollectionStage (const CollectionT& collection, SavingState& state,
CSMWorld::Scope scope = CSMWorld::Scope_Content);
virtual int setup(); virtual int setup();
///< \return number of steps ///< \return number of steps
@ -81,8 +82,8 @@ namespace CSMDoc
template<class CollectionT> template<class CollectionT>
WriteCollectionStage<CollectionT>::WriteCollectionStage (const CollectionT& collection, WriteCollectionStage<CollectionT>::WriteCollectionStage (const CollectionT& collection,
SavingState& state) SavingState& state, CSMWorld::Scope scope)
: mCollection (collection), mState (state) : mCollection (collection), mState (state), mScope (scope)
{} {}
template<class CollectionT> template<class CollectionT>
@ -94,16 +95,14 @@ namespace CSMDoc
template<class CollectionT> template<class CollectionT>
void WriteCollectionStage<CollectionT>::perform (int stage, Messages& messages) void WriteCollectionStage<CollectionT>::perform (int stage, Messages& messages)
{ {
if (CSMWorld::getScopeFromId (mCollection.getRecord (stage).get().mId)!=mScope)
return;
CSMWorld::RecordBase::State state = mCollection.getRecord (stage).mState; CSMWorld::RecordBase::State state = mCollection.getRecord (stage).mState;
if (state==CSMWorld::RecordBase::State_Modified || if (state==CSMWorld::RecordBase::State_Modified ||
state==CSMWorld::RecordBase::State_ModifiedOnly) state==CSMWorld::RecordBase::State_ModifiedOnly)
{ {
std::string type;
for (int i=0; i<4; ++i)
/// \todo make endianess agnostic (change ESMWriter interface?)
type += reinterpret_cast<const char *> (&mCollection.getRecord (stage).mModified.sRecordId)[i];
mState.getWriter().startRecord (mCollection.getRecord (stage).mModified.sRecordId); mState.getWriter().startRecord (mCollection.getRecord (stage).mModified.sRecordId);
mState.getWriter().writeHNCString ("NAME", mCollection.getId (stage)); mState.getWriter().writeHNCString ("NAME", mCollection.getId (stage));
mCollection.getRecord (stage).mModified.save (mState.getWriter()); mCollection.getRecord (stage).mModified.save (mState.getWriter());
@ -152,20 +151,6 @@ namespace CSMDoc
}; };
class WriteFilterStage : public WriteCollectionStage<CSMWorld::IdCollection<CSMFilter::Filter> >
{
Document& mDocument;
CSMFilter::Filter::Scope mScope;
public:
WriteFilterStage (Document& document, SavingState& state, CSMFilter::Filter::Scope scope);
virtual void perform (int stage, Messages& messages);
///< Messages resulting from this stage will be appended to \a messages.
};
class CollectionReferencesStage : public Stage class CollectionReferencesStage : public Stage
{ {
Document& mDocument; Document& mDocument;

@ -8,12 +8,13 @@ namespace CSMDoc
State_Modified = 1, State_Modified = 1,
State_Locked = 2, State_Locked = 2,
State_Operation = 4, State_Operation = 4,
State_Running = 8,
State_Saving = 8, State_Saving = 16,
State_Verifying = 16, State_Verifying = 32,
State_Compiling = 32, // not implemented yet State_Compiling = 64, // not implemented yet
State_Searching = 64, // not implemented yet State_Searching = 128, // not implemented yet
State_Loading = 128 // pseudo-state; can not be encountered in a loaded document State_Loading = 256 // pseudo-state; can not be encountered in a loaded document
}; };
} }

@ -1,25 +0,0 @@
#ifndef CSM_FILTER_FILTER_H
#define CSM_FILTER_FILTER_H
#include <vector>
#include <string>
#include <components/esm/filter.hpp>
namespace CSMFilter
{
/// \brief Wrapper for Filter record
struct Filter : public ESM::Filter
{
enum Scope
{
Scope_Project = 0, // per project
Scope_Session = 1, // exists only for one editing session; not saved
Scope_Content = 2 // embedded in the edited content file
};
Scope mScope;
};
}
#endif

@ -596,7 +596,7 @@ bool CSMFilter::Parser::parse (const std::string& filter, bool allowPredefined)
return false; return false;
} }
const CSMWorld::Record<CSMFilter::Filter>& record = mData.getFilters().getRecord (index); const CSMWorld::Record<ESM::Filter>& record = mData.getFilters().getRecord (index);
if (record.isDeleted()) if (record.isDeleted())
{ {

@ -0,0 +1,51 @@
#include "bodypartcheck.hpp"
CSMTools::BodyPartCheckStage::BodyPartCheckStage(
const CSMWorld::IdCollection<ESM::BodyPart> &bodyParts,
const CSMWorld::Resources &meshes,
const CSMWorld::IdCollection<ESM::Race> &races ) :
mBodyParts(bodyParts),
mMeshes(meshes),
mRaces(races)
{ }
int CSMTools::BodyPartCheckStage::setup()
{
return mBodyParts.getSize();
}
void CSMTools::BodyPartCheckStage::perform ( int stage, Messages &messages )
{
const CSMWorld::Record<ESM::BodyPart> &record = mBodyParts.getRecord(stage);
if ( record.isDeleted() )
return;
const ESM::BodyPart &bodyPart = record.get();
CSMWorld::UniversalId id( CSMWorld::UniversalId::Type_BodyPart, bodyPart.mId );
// Check BYDT
if (bodyPart.mData.mPart > 14 )
messages.push_back(std::make_pair( id, bodyPart.mId + " has out of range part value." ));
if (bodyPart.mData.mFlags > 3 )
messages.push_back(std::make_pair( id, bodyPart.mId + " has out of range flags value." ));
if (bodyPart.mData.mType > 2 )
messages.push_back(std::make_pair( id, bodyPart.mId + " has out of range type value." ));
// Check MODL
if ( bodyPart.mModel.empty() )
messages.push_back(std::make_pair( id, bodyPart.mId + " has no model." ));
else if ( mMeshes.searchId( bodyPart.mModel ) == -1 )
messages.push_back(std::make_pair( id, bodyPart.mId + " has invalid model." ));
// Check FNAM
if ( bodyPart.mRace.empty() )
messages.push_back(std::make_pair( id, bodyPart.mId + " has no race." ));
else if ( mRaces.searchId( bodyPart.mRace ) == -1 )
messages.push_back(std::make_pair( id, bodyPart.mId + " has invalid race." ));
}

@ -0,0 +1,35 @@
#ifndef CSM_TOOLS_BODYPARTCHECK_H
#define CSM_TOOLS_BODYPARTCHECK_H
#include <components/esm/loadbody.hpp>
#include <components/esm/loadrace.hpp>
#include "../world/resources.hpp"
#include "../world/idcollection.hpp"
#include "../doc/stage.hpp"
namespace CSMTools
{
/// \brief VerifyStage: make sure that body part records are internally consistent
class BodyPartCheckStage : public CSMDoc::Stage
{
const CSMWorld::IdCollection<ESM::BodyPart> &mBodyParts;
const CSMWorld::Resources &mMeshes;
const CSMWorld::IdCollection<ESM::Race> &mRaces;
public:
BodyPartCheckStage(
const CSMWorld::IdCollection<ESM::BodyPart> &bodyParts,
const CSMWorld::Resources &meshes,
const CSMWorld::IdCollection<ESM::Race> &races );
virtual int setup();
///< \return number of steps
virtual void perform( int stage, Messages &messages );
///< Messages resulting from this tage will be appended to \a messages.
};
}
#endif

@ -7,6 +7,8 @@
#include <components/compiler/exception.hpp> #include <components/compiler/exception.hpp>
#include <components/compiler/extensions0.hpp> #include <components/compiler/extensions0.hpp>
#include "../doc/document.hpp"
#include "../world/data.hpp" #include "../world/data.hpp"
void CSMTools::ScriptCheckStage::report (const std::string& message, const Compiler::TokenLoc& loc, void CSMTools::ScriptCheckStage::report (const std::string& message, const Compiler::TokenLoc& loc,
@ -37,8 +39,8 @@ void CSMTools::ScriptCheckStage::report (const std::string& message, Type type)
(type==ErrorMessage ? "error: " : "warning: ") + message)); (type==ErrorMessage ? "error: " : "warning: ") + message));
} }
CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMWorld::Data& data) CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMDoc::Document& document)
: mData (data), mContext (data), mMessages (0) : mDocument (document), mContext (document.getData()), mMessages (0)
{ {
/// \todo add an option to configure warning mode /// \todo add an option to configure warning mode
setWarningsMode (0); setWarningsMode (0);
@ -53,18 +55,25 @@ int CSMTools::ScriptCheckStage::setup()
mMessages = 0; mMessages = 0;
mId.clear(); mId.clear();
return mData.getScripts().getSize(); return mDocument.getData().getScripts().getSize();
} }
void CSMTools::ScriptCheckStage::perform (int stage, Messages& messages) void CSMTools::ScriptCheckStage::perform (int stage, Messages& messages)
{ {
mId = mDocument.getData().getScripts().getId (stage);
if (mDocument.isBlacklisted (
CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Script, mId)))
return;
mMessages = &messages; mMessages = &messages;
mId = mData.getScripts().getId (stage);
try try
{ {
mFile = mData.getScripts().getRecord (stage).get().mId; const CSMWorld::Data& data = mDocument.getData();
std::istringstream input (mData.getScripts().getRecord (stage).get().mScriptText);
mFile = data.getScripts().getRecord (stage).get().mId;
std::istringstream input (data.getScripts().getRecord (stage).get().mScriptText);
Compiler::Scanner scanner (*this, input, mContext.getExtensions()); Compiler::Scanner scanner (*this, input, mContext.getExtensions());

@ -8,12 +8,17 @@
#include "../world/scriptcontext.hpp" #include "../world/scriptcontext.hpp"
namespace CSMDoc
{
class Document;
}
namespace CSMTools namespace CSMTools
{ {
/// \brief VerifyStage: make sure that scripts compile /// \brief VerifyStage: make sure that scripts compile
class ScriptCheckStage : public CSMDoc::Stage, private Compiler::ErrorHandler class ScriptCheckStage : public CSMDoc::Stage, private Compiler::ErrorHandler
{ {
const CSMWorld::Data& mData; const CSMDoc::Document& mDocument;
Compiler::Extensions mExtensions; Compiler::Extensions mExtensions;
CSMWorld::ScriptContext mContext; CSMWorld::ScriptContext mContext;
std::string mId; std::string mId;
@ -28,7 +33,7 @@ namespace CSMTools
public: public:
ScriptCheckStage (const CSMWorld::Data& data); ScriptCheckStage (const CSMDoc::Document& document);
virtual int setup(); virtual int setup();
///< \return number of steps ///< \return number of steps

@ -5,6 +5,7 @@
#include "../doc/state.hpp" #include "../doc/state.hpp"
#include "../doc/operation.hpp" #include "../doc/operation.hpp"
#include "../doc/document.hpp"
#include "../world/data.hpp" #include "../world/data.hpp"
#include "../world/universalid.hpp" #include "../world/universalid.hpp"
@ -21,6 +22,7 @@
#include "spellcheck.hpp" #include "spellcheck.hpp"
#include "referenceablecheck.hpp" #include "referenceablecheck.hpp"
#include "scriptcheck.hpp" #include "scriptcheck.hpp"
#include "bodypartcheck.hpp"
CSMDoc::Operation *CSMTools::Tools::get (int type) CSMDoc::Operation *CSMTools::Tools::get (int type)
{ {
@ -44,7 +46,7 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier()
mVerifier = new CSMDoc::Operation (CSMDoc::State_Verifying, false); mVerifier = new CSMDoc::Operation (CSMDoc::State_Verifying, false);
connect (mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int))); connect (mVerifier, SIGNAL (progress (int, int, int)), this, SIGNAL (progress (int, int, int)));
connect (mVerifier, SIGNAL (done (int)), this, SIGNAL (done (int))); connect (mVerifier, SIGNAL (done (int, bool)), this, SIGNAL (done (int, bool)));
connect (mVerifier, connect (mVerifier,
SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, int)), SIGNAL (reportMessage (const CSMWorld::UniversalId&, const std::string&, int)),
this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, int))); this, SLOT (verifierMessage (const CSMWorld::UniversalId&, const std::string&, int)));
@ -78,15 +80,23 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier()
mVerifier->appendStage (new SpellCheckStage (mData.getSpells())); mVerifier->appendStage (new SpellCheckStage (mData.getSpells()));
mVerifier->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions())); mVerifier->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions()));
mVerifier->appendStage (new ScriptCheckStage (mData)); mVerifier->appendStage (new ScriptCheckStage (mDocument));
mVerifier->appendStage(
new BodyPartCheckStage(
mData.getBodyParts(),
mData.getResources(
CSMWorld::UniversalId( CSMWorld::UniversalId::Type_Meshes )),
mData.getRaces() ));
} }
return mVerifier; return mVerifier;
} }
CSMTools::Tools::Tools (CSMWorld::Data& data) : mData (data), mVerifier (0), mNextReportNumber (0) CSMTools::Tools::Tools (CSMDoc::Document& document)
: mDocument (document), mData (document.getData()), mVerifier (0), mNextReportNumber (0)
{ {
// index 0: load error log // index 0: load error log
mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel)); mReports.insert (std::make_pair (mNextReportNumber++, new ReportModel));

@ -14,6 +14,7 @@ namespace CSMWorld
namespace CSMDoc namespace CSMDoc
{ {
class Operation; class Operation;
class Document;
} }
namespace CSMTools namespace CSMTools
@ -24,6 +25,7 @@ namespace CSMTools
{ {
Q_OBJECT Q_OBJECT
CSMDoc::Document& mDocument;
CSMWorld::Data& mData; CSMWorld::Data& mData;
CSMDoc::Operation *mVerifier; CSMDoc::Operation *mVerifier;
std::map<int, ReportModel *> mReports; std::map<int, ReportModel *> mReports;
@ -44,7 +46,7 @@ namespace CSMTools
public: public:
Tools (CSMWorld::Data& data); Tools (CSMDoc::Document& document);
virtual ~Tools(); virtual ~Tools();
@ -68,7 +70,7 @@ namespace CSMTools
void progress (int current, int max, int type); void progress (int current, int max, int type);
void done (int type); void done (int type, bool failed);
}; };
} }

@ -68,6 +68,7 @@ namespace CSMWorld
Display_TopicInfo, Display_TopicInfo,
Display_JournalInfo, Display_JournalInfo,
Display_Scene, Display_Scene,
Display_GlobalVariable,
//CONCRETE TYPES ENDS HERE //CONCRETE TYPES ENDS HERE
Display_Integer, Display_Integer,
@ -99,7 +100,8 @@ namespace CSMWorld
Display_SoundRes, Display_SoundRes,
Display_Texture, Display_Texture,
Display_Video, Display_Video,
Display_Colour Display_Colour,
Display_ScriptLines // console context
}; };
int mColumnId; int mColumnId;

@ -500,6 +500,47 @@ namespace CSMWorld
} }
}; };
template<typename ESXRecordT>
struct FlagColumn2 : public Column<ESXRecordT>
{
int mMask;
bool mInverted;
FlagColumn2 (int columnId, int mask, bool inverted = false)
: Column<ESXRecordT> (columnId, ColumnBase::Display_Boolean), mMask (mask),
mInverted (inverted)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
bool flag = (record.get().mFlags & mMask)!=0;
if (mInverted)
flag = !flag;
return flag;
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
int flags = record2.mFlags & ~mMask;
if ((data.toInt()!=0)!=mInverted)
flags |= mMask;
record2.mFlags = flags;
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT> template<typename ESXRecordT>
struct WeightHeightColumn : public Column<ESXRecordT> struct WeightHeightColumn : public Column<ESXRecordT>
{ {
@ -766,8 +807,18 @@ namespace CSMWorld
template<typename ESXRecordT> template<typename ESXRecordT>
struct ScriptColumn : public Column<ESXRecordT> struct ScriptColumn : public Column<ESXRecordT>
{ {
ScriptColumn() enum Type
: Column<ESXRecordT> (Columns::ColumnId_ScriptText, ColumnBase::Display_Script, 0) {} {
Type_File, // regular script record
Type_Lines, // console context
Type_Info // dialogue context (not implemented yet)
};
ScriptColumn (Type type)
: Column<ESXRecordT> (Columns::ColumnId_ScriptText,
type==Type_File ? ColumnBase::Display_Script : ColumnBase::Display_ScriptLines,
type==Type_File ? 0 : ColumnBase::Flag_Dialogue)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {
@ -977,13 +1028,13 @@ namespace CSMWorld
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {
return record.get().mFactIndex; return record.get().mFactionRank;
} }
virtual void set (Record<ESXRecordT>& record, const QVariant& data) virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{ {
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
record2.mFactIndex = data.toInt(); record2.mFactionRank = data.toInt();
record.setModified (record2); record.setModified (record2);
} }
@ -1224,36 +1275,6 @@ namespace CSMWorld
} }
}; };
template<typename ESXRecordT>
struct ScopeColumn : public Column<ESXRecordT>
{
ScopeColumn()
: Column<ESXRecordT> (Columns::ColumnId_Scope, ColumnBase::Display_Integer, 0)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return static_cast<int> (record.get().mScope);
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mScope = static_cast<CSMFilter::Filter::Scope> (data.toInt());
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
virtual bool isUserEditable() const
{
return false;
}
};
template<typename ESXRecordT> template<typename ESXRecordT>
struct PosColumn : public Column<ESXRecordT> struct PosColumn : public Column<ESXRecordT>
@ -1870,6 +1891,97 @@ namespace CSMWorld
return true; return true;
} }
}; };
template<typename ESXRecordT>
struct OwnerGlobalColumn : public Column<ESXRecordT>
{
OwnerGlobalColumn()
: Column<ESXRecordT> (Columns::ColumnId_OwnerGlobal, ColumnBase::Display_GlobalVariable)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return QString::fromUtf8 (record.get().mGlobalVariable.c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mGlobalVariable = data.toString().toUtf8().constData();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
template<typename ESXRecordT>
struct RefNumCounterColumn : public Column<ESXRecordT>
{
RefNumCounterColumn()
: Column<ESXRecordT> (Columns::ColumnId_RefNumCounter, ColumnBase::Display_Integer, 0)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return static_cast<int> (record.get().mRefNumCounter);
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mRefNumCounter = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
virtual bool isUserEditable() const
{
return false;
}
};
template<typename ESXRecordT>
struct RefNumColumn : public Column<ESXRecordT>
{
RefNumColumn()
: Column<ESXRecordT> (Columns::ColumnId_RefNum, ColumnBase::Display_Integer, 0)
{}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return static_cast<int> (record.get().mRefNum.mIndex);
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mRefNum.mIndex = data.toInt();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
virtual bool isUserEditable() const
{
return false;
}
};
} }
#endif #endif

@ -172,7 +172,6 @@ namespace CSMWorld
{ ColumnId_Rank, "Rank" }, { ColumnId_Rank, "Rank" },
{ ColumnId_Gender, "Gender" }, { ColumnId_Gender, "Gender" },
{ ColumnId_PcRank, "PC Rank" }, { ColumnId_PcRank, "PC Rank" },
{ ColumnId_Scope, "Scope" },
{ ColumnId_ReferenceableId, "Referenceable ID" }, { ColumnId_ReferenceableId, "Referenceable ID" },
{ ColumnId_CombatState, "Combat" }, { ColumnId_CombatState, "Combat" },
{ ColumnId_MagicState, "Magic" }, { ColumnId_MagicState, "Magic" },
@ -181,6 +180,12 @@ namespace CSMWorld
{ ColumnId_Vampire, "Vampire" }, { ColumnId_Vampire, "Vampire" },
{ ColumnId_BodyPartType, "Bodypart Type" }, { ColumnId_BodyPartType, "Bodypart Type" },
{ ColumnId_MeshType, "Mesh Type" }, { ColumnId_MeshType, "Mesh Type" },
{ ColumnId_OwnerGlobal, "Owner Global" },
{ ColumnId_DefaultProfile, "Default Profile" },
{ ColumnId_BypassNewGame, "Bypass New Game" },
{ ColumnId_GlobalProfile, "Global Profile" },
{ ColumnId_RefNumCounter, "RefNum Counter" },
{ ColumnId_RefNum, "RefNum" },
{ ColumnId_UseValue1, "Use value 1" }, { ColumnId_UseValue1, "Use value 1" },
{ ColumnId_UseValue2, "Use value 2" }, { ColumnId_UseValue2, "Use value 2" },

@ -165,7 +165,6 @@ namespace CSMWorld
ColumnId_Rank = 152, ColumnId_Rank = 152,
ColumnId_Gender = 153, ColumnId_Gender = 153,
ColumnId_PcRank = 154, ColumnId_PcRank = 154,
ColumnId_Scope = 155,
ColumnId_ReferenceableId = 156, ColumnId_ReferenceableId = 156,
ColumnId_CombatState = 157, ColumnId_CombatState = 157,
ColumnId_MagicState = 158, ColumnId_MagicState = 158,
@ -174,6 +173,12 @@ namespace CSMWorld
ColumnId_Vampire = 161, ColumnId_Vampire = 161,
ColumnId_BodyPartType = 162, ColumnId_BodyPartType = 162,
ColumnId_MeshType = 163, ColumnId_MeshType = 163,
ColumnId_OwnerGlobal = 164,
ColumnId_DefaultProfile = 165,
ColumnId_BypassNewGame = 166,
ColumnId_GlobalProfile = 167,
ColumnId_RefNumCounter = 168,
ColumnId_RefNum = 169,
// 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.

@ -10,13 +10,12 @@ CSMWorld::ModifyCommand::ModifyCommand (QAbstractItemModel& model, const QModelI
const QVariant& new_, QUndoCommand* parent) const QVariant& new_, QUndoCommand* parent)
: QUndoCommand (parent), mModel (model), mIndex (index), mNew (new_) : QUndoCommand (parent), mModel (model), mIndex (index), mNew (new_)
{ {
mOld = mModel.data (mIndex, Qt::EditRole);
setText ("Modify " + mModel.headerData (mIndex.column(), Qt::Horizontal, Qt::DisplayRole).toString()); setText ("Modify " + mModel.headerData (mIndex.column(), Qt::Horizontal, Qt::DisplayRole).toString());
} }
void CSMWorld::ModifyCommand::redo() void CSMWorld::ModifyCommand::redo()
{ {
mOld = mModel.data (mIndex, Qt::EditRole);
mModel.setData (mIndex, mNew); mModel.setData (mIndex, mNew);
} }
@ -25,6 +24,13 @@ void CSMWorld::ModifyCommand::undo()
mModel.setData (mIndex, mOld); mModel.setData (mIndex, mOld);
} }
void CSMWorld::CreateCommand::applyModifications()
{
for (std::map<int, QVariant>::const_iterator iter (mValues.begin()); iter!=mValues.end(); ++iter)
mModel.setData (mModel.getModelIndex (mId, iter->first), iter->second);
}
CSMWorld::CreateCommand::CreateCommand (IdTable& model, const std::string& id, QUndoCommand* parent) CSMWorld::CreateCommand::CreateCommand (IdTable& model, const std::string& id, QUndoCommand* parent)
: QUndoCommand (parent), mModel (model), mId (id), mType (UniversalId::Type_None) : QUndoCommand (parent), mModel (model), mId (id), mType (UniversalId::Type_None)
{ {
@ -44,9 +50,7 @@ void CSMWorld::CreateCommand::setType (UniversalId::Type type)
void CSMWorld::CreateCommand::redo() void CSMWorld::CreateCommand::redo()
{ {
mModel.addRecord (mId, mType); mModel.addRecord (mId, mType);
applyModifications();
for (std::map<int, QVariant>::const_iterator iter (mValues.begin()); iter!=mValues.end(); ++iter)
mModel.setData (mModel.getModelIndex (mId, iter->first), iter->second);
} }
void CSMWorld::CreateCommand::undo() void CSMWorld::CreateCommand::undo()
@ -148,27 +152,22 @@ void CSMWorld::ReorderRowsCommand::undo()
CSMWorld::CloneCommand::CloneCommand (CSMWorld::IdTable& model, CSMWorld::CloneCommand::CloneCommand (CSMWorld::IdTable& model,
const std::string& idOrigin, const std::string& idOrigin,
const std::string& IdDestination, const std::string& idDestination,
const CSMWorld::UniversalId::Type type, const CSMWorld::UniversalId::Type type,
QUndoCommand* parent) : QUndoCommand* parent)
QUndoCommand (parent), : CreateCommand (model, idDestination, parent), mIdOrigin (idOrigin)
mModel (model),
mIdOrigin (idOrigin),
mIdDestination (Misc::StringUtils::lowerCase (IdDestination)),
mType (type)
{ {
setText ( ("Clone record " + idOrigin + " to the " + IdDestination).c_str()); setType (type);
setText ( ("Clone record " + idOrigin + " to the " + idDestination).c_str());
} }
void CSMWorld::CloneCommand::redo() void CSMWorld::CloneCommand::redo()
{ {
mModel.cloneRecord (mIdOrigin, mIdDestination, mType); mModel.cloneRecord (mIdOrigin, mId, mType);
applyModifications();
for (std::map<int, QVariant>::const_iterator iter (mValues.begin()); iter != mValues.end(); ++iter)
mModel.setData (mModel.getModelIndex (mIdDestination, iter->first), iter->second);
} }
void CSMWorld::CloneCommand::undo() void CSMWorld::CloneCommand::undo()
{ {
mModel.removeRow (mModel.getModelIndex (mIdDestination, 0).row()); mModel.removeRow (mModel.getModelIndex (mId, 0).row());
} }

@ -39,40 +39,44 @@ namespace CSMWorld
virtual void undo(); virtual void undo();
}; };
class CloneCommand : public QUndoCommand class CreateCommand : public QUndoCommand
{ {
std::map<int, QVariant> mValues;
protected:
IdTable& mModel; IdTable& mModel;
std::string mIdOrigin; std::string mId;
std::string mIdDestination;
UniversalId::Type mType; UniversalId::Type mType;
std::map<int, QVariant> mValues;
protected:
/// Apply modifications set via addValue.
void applyModifications();
public: public:
CloneCommand (IdTable& model, const std::string& idOrigin, CreateCommand (IdTable& model, const std::string& id, QUndoCommand *parent = 0);
const std::string& IdDestination,
const UniversalId::Type type, void setType (UniversalId::Type type);
QUndoCommand* parent = 0);
void addValue (int column, const QVariant& value);
virtual void redo(); virtual void redo();
virtual void undo(); virtual void undo();
}; };
class CreateCommand : public QUndoCommand class CloneCommand : public CreateCommand
{ {
IdTable& mModel; std::string mIdOrigin;
std::string mId;
UniversalId::Type mType;
std::map<int, QVariant> mValues;
public: public:
CreateCommand (IdTable& model, const std::string& id, QUndoCommand *parent = 0); CloneCommand (IdTable& model, const std::string& idOrigin,
const std::string& IdDestination,
void setType (UniversalId::Type type); const UniversalId::Type type,
QUndoCommand* parent = 0);
void addValue (int column, const QVariant& value);
virtual void redo(); virtual void redo();

@ -131,7 +131,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
mScripts.addColumn (new StringIdColumn<ESM::Script>); mScripts.addColumn (new StringIdColumn<ESM::Script>);
mScripts.addColumn (new RecordStateColumn<ESM::Script>); mScripts.addColumn (new RecordStateColumn<ESM::Script>);
mScripts.addColumn (new FixedRecordTypeColumn<ESM::Script> (UniversalId::Type_Script)); mScripts.addColumn (new FixedRecordTypeColumn<ESM::Script> (UniversalId::Type_Script));
mScripts.addColumn (new ScriptColumn<ESM::Script>); mScripts.addColumn (new ScriptColumn<ESM::Script> (ScriptColumn<ESM::Script>::Type_File));
mRegions.addColumn (new StringIdColumn<ESM::Region>); mRegions.addColumn (new StringIdColumn<ESM::Region>);
mRegions.addColumn (new RecordStateColumn<ESM::Region>); mRegions.addColumn (new RecordStateColumn<ESM::Region>);
@ -186,7 +186,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
mJournalInfos.addColumn (new StringIdColumn<Info> (true)); mJournalInfos.addColumn (new StringIdColumn<Info> (true));
mJournalInfos.addColumn (new RecordStateColumn<Info>); mJournalInfos.addColumn (new RecordStateColumn<Info>);
mJournalInfos.addColumn (new FixedRecordTypeColumn<Info> (UniversalId::Type_Journal)); mJournalInfos.addColumn (new FixedRecordTypeColumn<Info> (UniversalId::Type_JournalInfo));
mJournalInfos.addColumn (new TopicColumn<Info> (true)); mJournalInfos.addColumn (new TopicColumn<Info> (true));
mJournalInfos.addColumn (new QuestStatusTypeColumn<Info>); mJournalInfos.addColumn (new QuestStatusTypeColumn<Info>);
mJournalInfos.addColumn (new QuestIndexColumn<Info>); mJournalInfos.addColumn (new QuestIndexColumn<Info>);
@ -200,6 +200,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
mCells.addColumn (new FlagColumn<Cell> (Columns::ColumnId_InteriorWater, ESM::Cell::HasWater)); mCells.addColumn (new FlagColumn<Cell> (Columns::ColumnId_InteriorWater, ESM::Cell::HasWater));
mCells.addColumn (new FlagColumn<Cell> (Columns::ColumnId_InteriorSky, ESM::Cell::QuasiEx)); mCells.addColumn (new FlagColumn<Cell> (Columns::ColumnId_InteriorSky, ESM::Cell::QuasiEx));
mCells.addColumn (new RegionColumn<Cell>); mCells.addColumn (new RegionColumn<Cell>);
mCells.addColumn (new RefNumCounterColumn<Cell>);
mEnchantments.addColumn (new StringIdColumn<ESM::Enchantment>); mEnchantments.addColumn (new StringIdColumn<ESM::Enchantment>);
mEnchantments.addColumn (new RecordStateColumn<ESM::Enchantment>); mEnchantments.addColumn (new RecordStateColumn<ESM::Enchantment>);
@ -250,13 +251,27 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
mRefs.addColumn (new LockLevelColumn<CellRef>); mRefs.addColumn (new LockLevelColumn<CellRef>);
mRefs.addColumn (new KeyColumn<CellRef>); mRefs.addColumn (new KeyColumn<CellRef>);
mRefs.addColumn (new TrapColumn<CellRef>); mRefs.addColumn (new TrapColumn<CellRef>);
mRefs.addColumn (new OwnerGlobalColumn<CellRef>);
mFilters.addColumn (new StringIdColumn<CSMFilter::Filter>); mRefs.addColumn (new RefNumColumn<CellRef>);
mFilters.addColumn (new RecordStateColumn<CSMFilter::Filter>);
mFilters.addColumn (new FixedRecordTypeColumn<CSMFilter::Filter> (UniversalId::Type_Filter)); mFilters.addColumn (new StringIdColumn<ESM::Filter>);
mFilters.addColumn (new FilterColumn<CSMFilter::Filter>); mFilters.addColumn (new RecordStateColumn<ESM::Filter>);
mFilters.addColumn (new DescriptionColumn<CSMFilter::Filter>); mFilters.addColumn (new FixedRecordTypeColumn<ESM::Filter> (UniversalId::Type_Filter));
mFilters.addColumn (new ScopeColumn<CSMFilter::Filter>); mFilters.addColumn (new FilterColumn<ESM::Filter>);
mFilters.addColumn (new DescriptionColumn<ESM::Filter>);
mDebugProfiles.addColumn (new StringIdColumn<ESM::DebugProfile>);
mDebugProfiles.addColumn (new RecordStateColumn<ESM::DebugProfile>);
mDebugProfiles.addColumn (new FixedRecordTypeColumn<ESM::DebugProfile> (UniversalId::Type_DebugProfile));
mDebugProfiles.addColumn (new FlagColumn2<ESM::DebugProfile> (
Columns::ColumnId_DefaultProfile, ESM::DebugProfile::Flag_Default));
mDebugProfiles.addColumn (new FlagColumn2<ESM::DebugProfile> (
Columns::ColumnId_BypassNewGame, ESM::DebugProfile::Flag_BypassNewGame));
mDebugProfiles.addColumn (new FlagColumn2<ESM::DebugProfile> (
Columns::ColumnId_GlobalProfile, ESM::DebugProfile::Flag_Global));
mDebugProfiles.addColumn (new DescriptionColumn<ESM::DebugProfile>);
mDebugProfiles.addColumn (new ScriptColumn<ESM::DebugProfile> (
ScriptColumn<ESM::DebugProfile>::Type_Lines));
addModel (new IdTable (&mGlobals), UniversalId::Type_Global); addModel (new IdTable (&mGlobals), UniversalId::Type_Global);
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmst); addModel (new IdTable (&mGmsts), UniversalId::Type_Gmst);
@ -280,17 +295,18 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
UniversalId::Type_Referenceable); UniversalId::Type_Referenceable);
addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_Reference); addModel (new IdTable (&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_Reference);
addModel (new IdTable (&mFilters), UniversalId::Type_Filter); addModel (new IdTable (&mFilters), UniversalId::Type_Filter);
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Mesh)), addModel (new IdTable (&mDebugProfiles), UniversalId::Type_DebugProfile);
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Meshes)),
UniversalId::Type_Mesh); UniversalId::Type_Mesh);
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Icon)), addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Icons)),
UniversalId::Type_Icon); UniversalId::Type_Icon);
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Music)), addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Musics)),
UniversalId::Type_Music); UniversalId::Type_Music);
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_SoundRes)), addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_SoundsRes)),
UniversalId::Type_SoundRes); UniversalId::Type_SoundRes);
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Texture)), addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Textures)),
UniversalId::Type_Texture); UniversalId::Type_Texture);
addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Video)), addModel (new ResourceTable (&mResourcesManager.get (UniversalId::Type_Videos)),
UniversalId::Type_Video); UniversalId::Type_Video);
} }
@ -483,12 +499,12 @@ CSMWorld::RefCollection& CSMWorld::Data::getReferences()
return mRefs; return mRefs;
} }
const CSMWorld::IdCollection<CSMFilter::Filter>& CSMWorld::Data::getFilters() const const CSMWorld::IdCollection<ESM::Filter>& CSMWorld::Data::getFilters() const
{ {
return mFilters; return mFilters;
} }
CSMWorld::IdCollection<CSMFilter::Filter>& CSMWorld::Data::getFilters() CSMWorld::IdCollection<ESM::Filter>& CSMWorld::Data::getFilters()
{ {
return mFilters; return mFilters;
} }
@ -513,9 +529,19 @@ CSMWorld::IdCollection<ESM::BodyPart>& CSMWorld::Data::getBodyParts()
return mBodyParts; return mBodyParts;
} }
const CSMWorld::IdCollection<ESM::DebugProfile>& CSMWorld::Data::getDebugProfiles() const
{
return mDebugProfiles;
}
CSMWorld::IdCollection<ESM::DebugProfile>& CSMWorld::Data::getDebugProfiles()
{
return mDebugProfiles;
}
const CSMWorld::Resources& CSMWorld::Data::getResources (const UniversalId& id) const const CSMWorld::Resources& CSMWorld::Data::getResources (const UniversalId& id) const
{ {
return mResourcesManager.get (UniversalId::getParentType (id.getType())); return mResourcesManager.get (id.getType());
} }
QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId& id) QAbstractItemModel *CSMWorld::Data::getTableModel (const CSMWorld::UniversalId& id)
@ -582,6 +608,8 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages)
ESM::NAME n = mReader->getRecName(); ESM::NAME n = mReader->getRecName();
mReader->getRecHeader(); mReader->getRecHeader();
bool unhandledRecord = false;
switch (n.val) switch (n.val)
{ {
case ESM::REC_GLOB: mGlobals.load (*mReader, mBase); break; case ESM::REC_GLOB: mGlobals.load (*mReader, mBase); break;
@ -692,23 +720,37 @@ bool CSMWorld::Data::continueLoading (CSMDoc::Stage::Messages& messages)
case ESM::REC_FILT: case ESM::REC_FILT:
if (mProject) if (!mProject)
{ {
mFilters.load (*mReader, mBase); unhandledRecord = true;
mFilters.setData (mFilters.getSize()-1,
mFilters.findColumnIndex (CSMWorld::Columns::ColumnId_Scope),
static_cast<int> (CSMFilter::Filter::Scope_Project));
break; break;
} }
// fall through (filter record in a content file is an error with format 0) mFilters.load (*mReader, mBase);
break;
case ESM::REC_DBGP:
if (!mProject)
{
unhandledRecord = true;
break;
}
mDebugProfiles.load (*mReader, mBase);
break;
default: default:
messages.push_back (std::make_pair (UniversalId::Type_None, unhandledRecord = true;
"Unsupported record type: " + n.toString())); }
if (unhandledRecord)
{
messages.push_back (std::make_pair (UniversalId::Type_None,
"Unsupported record type: " + n.toString()));
mReader->skipRecord(); mReader->skipRecord();
} }
return false; return false;

@ -23,11 +23,11 @@
#include <components/esm/loaddial.hpp> #include <components/esm/loaddial.hpp>
#include <components/esm/loadench.hpp> #include <components/esm/loadench.hpp>
#include <components/esm/loadbody.hpp> #include <components/esm/loadbody.hpp>
#include <components/esm/debugprofile.hpp>
#include <components/esm/filter.hpp>
#include <components/to_utf8/to_utf8.hpp> #include <components/to_utf8/to_utf8.hpp>
#include "../filter/filter.hpp"
#include "../doc/stage.hpp" #include "../doc/stage.hpp"
#include "idcollection.hpp" #include "idcollection.hpp"
@ -70,12 +70,13 @@ namespace CSMWorld
IdCollection<ESM::Dialogue> mJournals; IdCollection<ESM::Dialogue> mJournals;
IdCollection<ESM::Enchantment> mEnchantments; IdCollection<ESM::Enchantment> mEnchantments;
IdCollection<ESM::BodyPart> mBodyParts; IdCollection<ESM::BodyPart> mBodyParts;
IdCollection<ESM::DebugProfile> mDebugProfiles;
InfoCollection mTopicInfos; InfoCollection mTopicInfos;
InfoCollection mJournalInfos; InfoCollection mJournalInfos;
IdCollection<Cell> mCells; IdCollection<Cell> mCells;
RefIdCollection mReferenceables; RefIdCollection mReferenceables;
RefCollection mRefs; RefCollection mRefs;
IdCollection<CSMFilter::Filter> mFilters; IdCollection<ESM::Filter> mFilters;
const ResourcesManager& mResourcesManager; const ResourcesManager& mResourcesManager;
std::vector<QAbstractItemModel *> mModels; std::vector<QAbstractItemModel *> mModels;
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex; std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
@ -178,9 +179,9 @@ namespace CSMWorld
RefCollection& getReferences(); RefCollection& getReferences();
const IdCollection<CSMFilter::Filter>& getFilters() const; const IdCollection<ESM::Filter>& getFilters() const;
IdCollection<CSMFilter::Filter>& getFilters(); IdCollection<ESM::Filter>& getFilters();
const IdCollection<ESM::Enchantment>& getEnchantments() const; const IdCollection<ESM::Enchantment>& getEnchantments() const;
@ -190,6 +191,10 @@ namespace CSMWorld
IdCollection<ESM::BodyPart>& getBodyParts(); IdCollection<ESM::BodyPart>& getBodyParts();
const IdCollection<ESM::DebugProfile>& getDebugProfiles() const;
IdCollection<ESM::DebugProfile>& getDebugProfiles();
/// Throws an exception, if \a id does not match a resources list. /// Throws an exception, if \a id does not match a resources list.
const Resources& getResources (const UniversalId& id) const; const Resources& getResources (const UniversalId& id) const;

@ -4,7 +4,5 @@
CSMWorld::CellRef::CellRef() CSMWorld::CellRef::CellRef()
{ {
mRefNum.mIndex = 0; mRefNum.mIndex = 0;
mRefNum.mContentFile = 0;
// special marker: This reference does not have a RefNum assign to it yet.
mRefNum.mContentFile = -2;
} }

@ -12,12 +12,12 @@ void CSMWorld::ResourcesManager::listResources()
{ {
static const char * const sMeshTypes[] = { "nif", 0 }; static const char * const sMeshTypes[] = { "nif", 0 };
addResources (Resources ("meshes", UniversalId::Type_Mesh, sMeshTypes)); addResources (Resources ("meshes", UniversalId::Type_Meshes, sMeshTypes));
addResources (Resources ("icons", UniversalId::Type_Icon)); addResources (Resources ("icons", UniversalId::Type_Icons));
addResources (Resources ("music", UniversalId::Type_Music)); addResources (Resources ("music", UniversalId::Type_Musics));
addResources (Resources ("sound", UniversalId::Type_SoundRes)); addResources (Resources ("sound", UniversalId::Type_SoundsRes));
addResources (Resources ("textures", UniversalId::Type_Texture)); addResources (Resources ("textures", UniversalId::Type_Textures));
addResources (Resources ("videos", UniversalId::Type_Video)); addResources (Resources ("videos", UniversalId::Type_Videos));
} }
const CSMWorld::Resources& CSMWorld::ResourcesManager::get (UniversalId::Type type) const const CSMWorld::Resources& CSMWorld::ResourcesManager::get (UniversalId::Type type) const

@ -50,7 +50,7 @@ QVariant CSMWorld::ResourceTable::headerData (int section, Qt::Orientation orien
return QVariant(); return QVariant();
if (role==ColumnBase::Role_Flags) if (role==ColumnBase::Role_Flags)
return ColumnBase::Flag_Table; return section==0 ? ColumnBase::Flag_Table : 0;
switch (section) switch (section)
{ {
@ -86,7 +86,7 @@ bool CSMWorld::ResourceTable::setData ( const QModelIndex &index, const QVariant
Qt::ItemFlags CSMWorld::ResourceTable::flags (const QModelIndex & index) const Qt::ItemFlags CSMWorld::ResourceTable::flags (const QModelIndex & index) const
{ {
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;; return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
} }
QModelIndex CSMWorld::ResourceTable::index (int row, int column, const QModelIndex& parent) QModelIndex CSMWorld::ResourceTable::index (int row, int column, const QModelIndex& parent)

@ -0,0 +1,25 @@
#include "scope.hpp"
#include <stdexcept>
#include <components/misc/stringops.hpp>
CSMWorld::Scope CSMWorld::getScopeFromId (const std::string& id)
{
// get root namespace
std::string namespace_;
std::string::size_type i = id.find ("::");
if (i!=std::string::npos)
namespace_ = Misc::StringUtils::lowerCase (id.substr (0, i));
if (namespace_=="project")
return Scope_Project;
if (namespace_=="session")
return Scope_Session;
return Scope_Content;
}

@ -0,0 +1,23 @@
#ifndef CSM_WOLRD_SCOPE_H
#define CSM_WOLRD_SCOPE_H
#include <string>
namespace CSMWorld
{
enum Scope
{
// record stored in content file
Scope_Content = 1,
// record stored in project file
Scope_Project = 2,
// record that exists only for the duration of one editing session
Scope_Session = 4
};
Scope getScopeFromId (const std::string& id);
}
#endif

@ -91,7 +91,7 @@ return ( type == CSMWorld::ColumnBase::Display_Activator
|| type == CSMWorld::ColumnBase::Display_Static || type == CSMWorld::ColumnBase::Display_Static
|| type == CSMWorld::ColumnBase::Display_Weapon); || type == CSMWorld::ColumnBase::Display_Weapon);
} }
bool CSMWorld::TableMimeData::isReferencable(CSMWorld::UniversalId::Type type) const bool CSMWorld::TableMimeData::isReferencable(CSMWorld::UniversalId::Type type)
{ {
return ( type == CSMWorld::UniversalId::Type_Activator return ( type == CSMWorld::UniversalId::Type_Activator
|| type == CSMWorld::UniversalId::Type_Potion || type == CSMWorld::UniversalId::Type_Potion
@ -222,7 +222,6 @@ namespace
{ CSMWorld::UniversalId::Type_Race, CSMWorld::ColumnBase::Display_Race }, { CSMWorld::UniversalId::Type_Race, CSMWorld::ColumnBase::Display_Race },
{ CSMWorld::UniversalId::Type_Skill, CSMWorld::ColumnBase::Display_Skill }, { CSMWorld::UniversalId::Type_Skill, CSMWorld::ColumnBase::Display_Skill },
{ CSMWorld::UniversalId::Type_Class, CSMWorld::ColumnBase::Display_Class }, { CSMWorld::UniversalId::Type_Class, CSMWorld::ColumnBase::Display_Class },
{ CSMWorld::UniversalId::Type_Class, CSMWorld::ColumnBase::Display_Class },
{ CSMWorld::UniversalId::Type_Faction, CSMWorld::ColumnBase::Display_Faction }, { CSMWorld::UniversalId::Type_Faction, CSMWorld::ColumnBase::Display_Faction },
{ CSMWorld::UniversalId::Type_Sound, CSMWorld::ColumnBase::Display_Sound }, { CSMWorld::UniversalId::Type_Sound, CSMWorld::ColumnBase::Display_Sound },
{ CSMWorld::UniversalId::Type_Region, CSMWorld::ColumnBase::Display_Region }, { CSMWorld::UniversalId::Type_Region, CSMWorld::ColumnBase::Display_Region },
@ -264,6 +263,7 @@ namespace
{ CSMWorld::UniversalId::Type_SoundRes, CSMWorld::ColumnBase::Display_SoundRes }, { CSMWorld::UniversalId::Type_SoundRes, CSMWorld::ColumnBase::Display_SoundRes },
{ CSMWorld::UniversalId::Type_Texture, CSMWorld::ColumnBase::Display_Texture }, { CSMWorld::UniversalId::Type_Texture, CSMWorld::ColumnBase::Display_Texture },
{ CSMWorld::UniversalId::Type_Video, CSMWorld::ColumnBase::Display_Video }, { CSMWorld::UniversalId::Type_Video, CSMWorld::ColumnBase::Display_Video },
{ CSMWorld::UniversalId::Type_Global, CSMWorld::ColumnBase::Display_GlobalVariable },
{ CSMWorld::UniversalId::Type_None, CSMWorld::ColumnBase::Display_None } // end marker { CSMWorld::UniversalId::Type_None, CSMWorld::ColumnBase::Display_None } // end marker
}; };

@ -59,10 +59,10 @@ namespace CSMWorld
static CSMWorld::ColumnBase::Display convertEnums(CSMWorld::UniversalId::Type type); static CSMWorld::ColumnBase::Display convertEnums(CSMWorld::UniversalId::Type type);
static bool isReferencable(CSMWorld::UniversalId::Type type);
private: private:
bool isReferencable(CSMWorld::UniversalId::Type type) const;
bool isReferencable(CSMWorld::ColumnBase::Display type) const; bool isReferencable(CSMWorld::ColumnBase::Display type) const;
}; };
} }
#endif // TABLEMIMEDATA_H #endif // TABLEMIMEDATA_H

@ -46,10 +46,12 @@ namespace
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Filters, "Filters", 0 }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Filters, "Filters", 0 },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Meshes, "Meshes", 0 }, { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Meshes, "Meshes", 0 },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Icons, "Icons", 0 }, { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Icons, "Icons", 0 },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Musics, "Musics", 0 }, { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Musics, "Music Files", 0 },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_SoundsRes, "Sound Files", 0 }, { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_SoundsRes, "Sound Files", 0 },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Textures, "Textures", 0 }, { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Textures, "Textures", 0 },
{ CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Videos, "Videos", 0 }, { CSMWorld::UniversalId::Class_ResourceList, CSMWorld::UniversalId::Type_Videos, "Videos", 0 },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_DebugProfiles, "Debug Profiles", 0 },
{ CSMWorld::UniversalId::Class_Transient, CSMWorld::UniversalId::Type_RunLog, "Run 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
}; };
@ -109,6 +111,7 @@ namespace
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_SoundRes, "Sound File", 0 }, { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_SoundRes, "Sound File", 0 },
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Texture, "Texture", 0 }, { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Texture, "Texture", 0 },
{ CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Video, "Video", 0 }, { CSMWorld::UniversalId::Class_Resource, CSMWorld::UniversalId::Type_Video, "Video", 0 },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_DebugProfile, "Debug Profile", 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
}; };

@ -119,10 +119,13 @@ namespace CSMWorld
Type_Textures, Type_Textures,
Type_Texture, Type_Texture,
Type_Videos, Type_Videos,
Type_Video Type_Video,
Type_DebugProfiles,
Type_DebugProfile,
Type_RunLog
}; };
enum { NumberOfTypes = Type_BodyPart+1 }; enum { NumberOfTypes = Type_DebugProfile+1 };
private: private:

@ -18,7 +18,7 @@
#include "adjusterwidget.hpp" #include "adjusterwidget.hpp"
CSVDoc::FileDialog::FileDialog(QWidget *parent) : CSVDoc::FileDialog::FileDialog(QWidget *parent) :
QDialog(parent), mSelector (0), mFileWidget (0), mAdjusterWidget (0) QDialog(parent), mSelector (0), mFileWidget (0), mAdjusterWidget (0), mDialogBuilt(false)
{ {
ui.setupUi (this); ui.setupUi (this);
resize(400, 400); resize(400, 400);
@ -70,11 +70,15 @@ void CSVDoc::FileDialog::showDialog (ContentAction action)
mAdjusterWidget->setFilenameCheck (mAction == ContentAction_New); mAdjusterWidget->setFilenameCheck (mAction == ContentAction_New);
//connections common to both dialog view flavors if(!mDialogBuilt)
connect (mSelector, SIGNAL (signalCurrentGamefileIndexChanged (int)), {
this, SLOT (slotUpdateAcceptButton (int))); //connections common to both dialog view flavors
connect (mSelector, SIGNAL (signalCurrentGamefileIndexChanged (int)),
this, SLOT (slotUpdateAcceptButton (int)));
connect (ui.projectButtonBox, SIGNAL (rejected()), this, SLOT (slotRejected())); connect (ui.projectButtonBox, SIGNAL (rejected()), this, SLOT (slotRejected()));
mDialogBuilt = true;
}
show(); show();
raise(); raise();
@ -85,22 +89,26 @@ void CSVDoc::FileDialog::buildNewFileView()
{ {
setWindowTitle(tr("Create a new addon")); setWindowTitle(tr("Create a new addon"));
QPushButton* createButton = ui.projectButtonBox->button (QDialogButtonBox::Ok); QPushButton* createButton = ui.projectButtonBox->button (QDialogButtonBox::Ok);
createButton->setText ("Create"); createButton->setText ("Create");
createButton->setEnabled (false); createButton->setEnabled (false);
mFileWidget = new FileWidget (this); if(!mFileWidget)
{
mFileWidget = new FileWidget (this);
mFileWidget->setType (true); mFileWidget->setType (true);
mFileWidget->extensionLabelIsVisible(true); mFileWidget->extensionLabelIsVisible(true);
ui.projectGroupBoxLayout->insertWidget (0, mFileWidget); connect (mFileWidget, SIGNAL (nameChanged (const QString&, bool)),
mAdjusterWidget, SLOT (setName (const QString&, bool)));
connect (mFileWidget, SIGNAL (nameChanged (const QString&, bool)), connect (mFileWidget, SIGNAL (nameChanged(const QString &, bool)),
mAdjusterWidget, SLOT (setName (const QString&, bool))); this, SLOT (slotUpdateAcceptButton(const QString &, bool)));
connect (mFileWidget, SIGNAL (nameChanged(const QString &, bool)), }
this, SLOT (slotUpdateAcceptButton(const QString &, bool)));
ui.projectGroupBoxLayout->insertWidget (0, mFileWidget);
connect (ui.projectButtonBox, SIGNAL (accepted()), this, SLOT (slotNewFile())); connect (ui.projectButtonBox, SIGNAL (accepted()), this, SLOT (slotNewFile()));
} }
@ -109,13 +117,18 @@ void CSVDoc::FileDialog::buildOpenFileView()
{ {
setWindowTitle(tr("Open")); setWindowTitle(tr("Open"));
ui.projectGroupBox->setTitle (QString("")); ui.projectGroupBox->setTitle (QString(""));
ui.projectButtonBox->button(QDialogButtonBox::Ok)->setText ("Open");
if(mSelector->isGamefileSelected())
ui.projectButtonBox->button(QDialogButtonBox::Ok)->setEnabled (true);
else
ui.projectButtonBox->button(QDialogButtonBox::Ok)->setEnabled (false);
ui.projectButtonBox->button(QDialogButtonBox::Ok)->setEnabled (false); if(!mDialogBuilt)
{
connect (mSelector, SIGNAL (signalAddonFileSelected (int)), this, SLOT (slotUpdateAcceptButton (int))); connect (mSelector, SIGNAL (signalAddonFileSelected (int)), this, SLOT (slotUpdateAcceptButton (int)));
connect (mSelector, SIGNAL (signalAddonFileUnselected (int)), this, SLOT (slotUpdateAcceptButton (int))); connect (mSelector, SIGNAL (signalAddonFileUnselected (int)), this, SLOT (slotUpdateAcceptButton (int)));
}
connect (ui.projectButtonBox, SIGNAL (accepted()), this, SLOT (slotOpenFile())); connect (ui.projectButtonBox, SIGNAL (accepted()), this, SLOT (slotOpenFile()));
} }
void CSVDoc::FileDialog::slotUpdateAcceptButton (int) void CSVDoc::FileDialog::slotUpdateAcceptButton (int)
@ -156,12 +169,26 @@ QString CSVDoc::FileDialog::filename() const
void CSVDoc::FileDialog::slotRejected() void CSVDoc::FileDialog::slotRejected()
{ {
emit rejected(); emit rejected();
disconnect (ui.projectButtonBox, SIGNAL (accepted()), this, SLOT (slotNewFile()));
disconnect (ui.projectButtonBox, SIGNAL (accepted()), this, SLOT (slotOpenFile()));
if(mFileWidget)
{
delete mFileWidget;
mFileWidget = NULL;
}
close(); close();
} }
void CSVDoc::FileDialog::slotNewFile() void CSVDoc::FileDialog::slotNewFile()
{ {
emit signalCreateNewFile (mAdjusterWidget->getPath()); emit signalCreateNewFile (mAdjusterWidget->getPath());
if(mFileWidget)
{
delete mFileWidget;
mFileWidget = NULL;
}
disconnect (ui.projectButtonBox, SIGNAL (accepted()), this, SLOT (slotNewFile()));
close();
} }
void CSVDoc::FileDialog::slotOpenFile() void CSVDoc::FileDialog::slotOpenFile()
@ -171,4 +198,6 @@ void CSVDoc::FileDialog::slotOpenFile()
mAdjusterWidget->setName (file->filePath(), !file->isGameFile()); mAdjusterWidget->setName (file->filePath(), !file->isGameFile());
emit signalOpenFiles (mAdjusterWidget->getPath()); emit signalOpenFiles (mAdjusterWidget->getPath());
disconnect (ui.projectButtonBox, SIGNAL (accepted()), this, SLOT (slotOpenFile()));
close();
} }

@ -37,6 +37,7 @@ namespace CSVDoc
ContentAction mAction; ContentAction mAction;
FileWidget *mFileWidget; FileWidget *mFileWidget;
AdjusterWidget *mAdjusterWidget; AdjusterWidget *mAdjusterWidget;
bool mDialogBuilt;
public: public:

@ -17,7 +17,7 @@ CSVDoc::FileWidget::FileWidget (QWidget *parent) : QWidget (parent), mAddon (fal
QHBoxLayout *layout = new QHBoxLayout (this); QHBoxLayout *layout = new QHBoxLayout (this);
mInput = new QLineEdit (this); mInput = new QLineEdit (this);
mInput->setValidator (new QRegExpValidator(QRegExp("^[a-zA-Z0-9\\s]*$"))); mInput->setValidator (new QRegExpValidator(QRegExp("^[a-zA-Z0-9_-\\s]*$")));
layout->addWidget (mInput, 1); layout->addWidget (mInput, 1);

@ -0,0 +1,93 @@
#include "globaldebugprofilemenu.hpp"
#include <vector>
#include <algorithm>
#include <QActionGroup>
#include "../../model/world/idtable.hpp"
#include "../../model/world/record.hpp"
void CSVDoc::GlobalDebugProfileMenu::rebuild()
{
clear();
delete mActions;
mActions = 0;
int idColumn = mDebugProfiles->findColumnIndex (CSMWorld::Columns::ColumnId_Id);
int stateColumn = mDebugProfiles->findColumnIndex (CSMWorld::Columns::ColumnId_Modification);
int globalColumn = mDebugProfiles->findColumnIndex (
CSMWorld::Columns::ColumnId_GlobalProfile);
int size = mDebugProfiles->rowCount();
std::vector<QString> ids;
for (int i=0; i<size; ++i)
{
int state = mDebugProfiles->data (mDebugProfiles->index (i, stateColumn)).toInt();
bool global = mDebugProfiles->data (mDebugProfiles->index (i, globalColumn)).toInt();
if (state!=CSMWorld::RecordBase::State_Deleted && global)
ids.push_back (
mDebugProfiles->data (mDebugProfiles->index (i, idColumn)).toString());
}
mActions = new QActionGroup (this);
connect (mActions, SIGNAL (triggered (QAction *)), this, SLOT (actionTriggered (QAction *)));
std::sort (ids.begin(), ids.end());
for (std::vector<QString>::const_iterator iter (ids.begin()); iter!=ids.end(); ++iter)
{
mActions->addAction (addAction (*iter));
}
}
CSVDoc::GlobalDebugProfileMenu::GlobalDebugProfileMenu (CSMWorld::IdTable *debugProfiles,
QWidget *parent)
: QMenu (parent), mDebugProfiles (debugProfiles), mActions (0)
{
rebuild();
connect (mDebugProfiles, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
this, SLOT (profileAboutToBeRemoved (const QModelIndex&, int, int)));
connect (mDebugProfiles, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
this, SLOT (profileInserted (const QModelIndex&, int, int)));
connect (mDebugProfiles, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
this, SLOT (profileChanged (const QModelIndex&, const QModelIndex&)));
}
void CSVDoc::GlobalDebugProfileMenu::updateActions (bool running)
{
if (mActions)
mActions->setEnabled (!running);
}
void CSVDoc::GlobalDebugProfileMenu::profileAboutToBeRemoved (const QModelIndex& parent,
int start, int end)
{
rebuild();
}
void CSVDoc::GlobalDebugProfileMenu::profileInserted (const QModelIndex& parent, int start,
int end)
{
rebuild();
}
void CSVDoc::GlobalDebugProfileMenu::profileChanged (const QModelIndex& topLeft,
const QModelIndex& bottomRight)
{
rebuild();
}
void CSVDoc::GlobalDebugProfileMenu::actionTriggered (QAction *action)
{
emit triggered (std::string (action->text().toUtf8().constData()));
}

@ -0,0 +1,49 @@
#ifndef CSV_DOC_GLOBALDEBUGPROFILEMENU_H
#define CSV_DOC_GLOBALDEBUGPROFILEMENU_H
#include <QMenu>
class QModelIndex;
class QActionGroup;
namespace CSMWorld
{
class IdTable;
}
namespace CSVDoc
{
class GlobalDebugProfileMenu : public QMenu
{
Q_OBJECT
CSMWorld::IdTable *mDebugProfiles;
QActionGroup *mActions;
private:
void rebuild();
public:
GlobalDebugProfileMenu (CSMWorld::IdTable *debugProfiles, QWidget *parent = 0);
void updateActions (bool running);
private slots:
void profileAboutToBeRemoved (const QModelIndex& parent, int start, int end);
void profileInserted (const QModelIndex& parent, int start, int end);
void profileChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
void actionTriggered (QAction *action);
signals:
void triggered (const std::string& profile);
};
}
#endif

@ -0,0 +1,20 @@
#include "runlogsubview.hpp"
#include <QTextEdit>
CSVDoc::RunLogSubView::RunLogSubView (const CSMWorld::UniversalId& id,
CSMDoc::Document& document)
: SubView (id)
{
QTextEdit *edit = new QTextEdit (this);
edit->setDocument (document.getRunLog());
edit->setReadOnly (true);
setWidget (edit);
}
void CSVDoc::RunLogSubView::setEditLock (bool locked)
{
// ignored since this SubView does not have editing
}

@ -0,0 +1,20 @@
#ifndef CSV_DOC_RUNLOGSUBVIEW_H
#define CSV_DOC_RUNLOGSUBVIEW_H
#include "subview.hpp"
namespace CSVDoc
{
class RunLogSubView : public SubView
{
Q_OBJECT
public:
RunLogSubView (const CSMWorld::UniversalId& id, CSMDoc::Document& document);
virtual void setEditLock (bool locked);
};
}
#endif

@ -5,6 +5,7 @@ CSVDoc::SubView::SubView (const CSMWorld::UniversalId& id) : mUniversalId (id)
/// \todo add a button to the title bar that clones this sub view /// \todo add a button to the title bar that clones this sub view
setWindowTitle (QString::fromUtf8 (mUniversalId.toString().c_str())); setWindowTitle (QString::fromUtf8 (mUniversalId.toString().c_str()));
setAttribute(Qt::WA_DeleteOnClose);
} }
CSMWorld::UniversalId CSVDoc::SubView::getUniversalId() const CSMWorld::UniversalId CSVDoc::SubView::getUniversalId() const

@ -12,6 +12,8 @@
#include "../../model/doc/document.hpp" #include "../../model/doc/document.hpp"
#include "../../model/settings/usersettings.hpp" #include "../../model/settings/usersettings.hpp"
#include "../../model/world/idtable.hpp"
#include "../world/subviews.hpp" #include "../world/subviews.hpp"
#include "../tools/subviews.hpp" #include "../tools/subviews.hpp"
@ -19,11 +21,19 @@
#include "viewmanager.hpp" #include "viewmanager.hpp"
#include "operations.hpp" #include "operations.hpp"
#include "subview.hpp" #include "subview.hpp"
#include "globaldebugprofilemenu.hpp"
#include "runlogsubview.hpp"
#include "subviewfactoryimp.hpp"
void CSVDoc::View::closeEvent (QCloseEvent *event) void CSVDoc::View::closeEvent (QCloseEvent *event)
{ {
if (!mViewManager.closeRequest (this)) if (!mViewManager.closeRequest (this))
event->ignore(); event->ignore();
else
{
// closeRequest() returns true if last document
mViewManager.removeDocAndView(mDocument);
}
} }
void CSVDoc::View::setupFileMenu() void CSVDoc::View::setupFileMenu()
@ -232,6 +242,35 @@ void CSVDoc::View::setupAssetsMenu()
assets->addAction (videos); assets->addAction (videos);
} }
void CSVDoc::View::setupDebugMenu()
{
QMenu *debug = menuBar()->addMenu (tr ("Debug"));
QAction *profiles = new QAction (tr ("Debug Profiles"), this);
connect (profiles, SIGNAL (triggered()), this, SLOT (addDebugProfilesSubView()));
debug->addAction (profiles);
debug->addSeparator();
mGlobalDebugProfileMenu = new GlobalDebugProfileMenu (
&dynamic_cast<CSMWorld::IdTable&> (*mDocument->getData().getTableModel (
CSMWorld::UniversalId::Type_DebugProfiles)), this);
connect (mGlobalDebugProfileMenu, SIGNAL (triggered (const std::string&)),
this, SLOT (run (const std::string&)));
QAction *runDebug = debug->addMenu (mGlobalDebugProfileMenu);
runDebug->setText (tr ("Run OpenMW"));
mStopDebug = new QAction (tr ("Shutdown OpenMW"), this);
connect (mStopDebug, SIGNAL (triggered()), this, SLOT (stop()));
debug->addAction (mStopDebug);
QAction *runLog = new QAction (tr ("Run Log"), this);
connect (runLog, SIGNAL (triggered()), this, SLOT (addRunLogSubView()));
debug->addAction (runLog);
}
void CSVDoc::View::setupUi() void CSVDoc::View::setupUi()
{ {
setupFileMenu(); setupFileMenu();
@ -241,6 +280,7 @@ void CSVDoc::View::setupUi()
setupMechanicsMenu(); setupMechanicsMenu();
setupCharacterMenu(); setupCharacterMenu();
setupAssetsMenu(); setupAssetsMenu();
setupDebugMenu();
} }
void CSVDoc::View::updateTitle() void CSVDoc::View::updateTitle()
@ -261,6 +301,7 @@ void CSVDoc::View::updateTitle()
void CSVDoc::View::updateActions() void CSVDoc::View::updateActions()
{ {
bool editing = !(mDocument->getState() & CSMDoc::State_Locked); bool editing = !(mDocument->getState() & CSMDoc::State_Locked);
bool running = mDocument->getState() & CSMDoc::State_Running;
for (std::vector<QAction *>::iterator iter (mEditingActions.begin()); iter!=mEditingActions.end(); ++iter) for (std::vector<QAction *>::iterator iter (mEditingActions.begin()); iter!=mEditingActions.end(); ++iter)
(*iter)->setEnabled (editing); (*iter)->setEnabled (editing);
@ -268,8 +309,11 @@ void CSVDoc::View::updateActions()
mUndo->setEnabled (editing & mDocument->getUndoStack().canUndo()); mUndo->setEnabled (editing & mDocument->getUndoStack().canUndo());
mRedo->setEnabled (editing & mDocument->getUndoStack().canRedo()); mRedo->setEnabled (editing & mDocument->getUndoStack().canRedo());
mSave->setEnabled (!(mDocument->getState() & CSMDoc::State_Saving)); mSave->setEnabled (!(mDocument->getState() & CSMDoc::State_Saving) && !running);
mVerify->setEnabled (!(mDocument->getState() & CSMDoc::State_Verifying)); mVerify->setEnabled (!(mDocument->getState() & CSMDoc::State_Verifying));
mGlobalDebugProfileMenu->updateActions (running);
mStopDebug->setEnabled (running);
} }
CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews) CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int totalViews)
@ -295,9 +339,13 @@ CSVDoc::View::View (ViewManager& viewManager, CSMDoc::Document *document, int to
setupUi(); setupUi();
updateActions();
CSVWorld::addSubViewFactories (mSubViewFactory); CSVWorld::addSubViewFactories (mSubViewFactory);
CSVTools::addSubViewFactories (mSubViewFactory); CSVTools::addSubViewFactories (mSubViewFactory);
mSubViewFactory.add (CSMWorld::UniversalId::Type_RunLog, new SubViewFactory<RunLogSubView>);
connect (mOperations, SIGNAL (abortOperation (int)), this, SLOT (abortOperation (int))); connect (mOperations, SIGNAL (abortOperation (int)), this, SLOT (abortOperation (int)));
} }
@ -543,6 +591,16 @@ void CSVDoc::View::addVideosSubView()
addSubView (CSMWorld::UniversalId::Type_Videos); addSubView (CSMWorld::UniversalId::Type_Videos);
} }
void CSVDoc::View::addDebugProfilesSubView()
{
addSubView (CSMWorld::UniversalId::Type_DebugProfiles);
}
void CSVDoc::View::addRunLogSubView()
{
addSubView (CSMWorld::UniversalId::Type_RunLog);
}
void CSVDoc::View::abortOperation (int type) void CSVDoc::View::abortOperation (int type)
{ {
mDocument->abortOperation (type); mDocument->abortOperation (type);
@ -588,3 +646,13 @@ void CSVDoc::View::loadErrorLog()
{ {
addSubView (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_LoadErrorLog, 0)); addSubView (CSMWorld::UniversalId (CSMWorld::UniversalId::Type_LoadErrorLog, 0));
} }
void CSVDoc::View::run (const std::string& profile, const std::string& startupInstruction)
{
mDocument->startRunning (profile, startupInstruction);
}
void CSVDoc::View::stop()
{
mDocument->stopRunning();
}

@ -25,6 +25,7 @@ namespace CSVDoc
{ {
class ViewManager; class ViewManager;
class Operations; class Operations;
class GlobalDebugProfileMenu;
class View : public QMainWindow class View : public QMainWindow
{ {
@ -39,10 +40,12 @@ namespace CSVDoc
QAction *mSave; QAction *mSave;
QAction *mVerify; QAction *mVerify;
QAction *mShowStatusBar; QAction *mShowStatusBar;
QAction *mStopDebug;
std::vector<QAction *> mEditingActions; std::vector<QAction *> mEditingActions;
Operations *mOperations; Operations *mOperations;
SubViewFactoryManager mSubViewFactory; SubViewFactoryManager mSubViewFactory;
QMainWindow mSubViewWindow; QMainWindow mSubViewWindow;
GlobalDebugProfileMenu *mGlobalDebugProfileMenu;
// not implemented // not implemented
@ -67,6 +70,8 @@ namespace CSVDoc
void setupAssetsMenu(); void setupAssetsMenu();
void setupDebugMenu();
void setupUi(); void setupUi();
void updateTitle(); void updateTitle();
@ -194,9 +199,17 @@ namespace CSVDoc
void addVideosSubView(); void addVideosSubView();
void addDebugProfilesSubView();
void addRunLogSubView();
void toggleShowStatusBar (bool show); void toggleShowStatusBar (bool show);
void loadErrorLog(); void loadErrorLog();
void run (const std::string& profile, const std::string& startupInstruction = "");
void stop();
}; };
} }

@ -172,7 +172,7 @@ bool CSVDoc::ViewManager::closeRequest (View *view)
{ {
std::vector<View *>::iterator iter = std::find (mViews.begin(), mViews.end(), view); std::vector<View *>::iterator iter = std::find (mViews.begin(), mViews.end(), view);
bool continueWithClose = true; bool continueWithClose = false;
if (iter!=mViews.end()) if (iter!=mViews.end())
{ {
@ -192,6 +192,24 @@ bool CSVDoc::ViewManager::closeRequest (View *view)
return continueWithClose; return continueWithClose;
} }
// NOTE: This method assumes that it is called only if the last document
void CSVDoc::ViewManager::removeDocAndView (CSMDoc::Document *document)
{
for (std::vector<View *>::iterator iter (mViews.begin()); iter!=mViews.end(); ++iter)
{
// the first match should also be the only match
if((*iter)->getDocument() == document)
{
mDocumentManager.removeDocument(document);
(*iter)->deleteLater();
mViews.erase (iter);
updateIndices();
return;
}
}
}
bool CSVDoc::ViewManager::notifySaveOnClose (CSVDoc::View *view) bool CSVDoc::ViewManager::notifySaveOnClose (CSVDoc::View *view)
{ {
bool result = true; bool result = true;
@ -210,13 +228,19 @@ bool CSVDoc::ViewManager::notifySaveOnClose (CSVDoc::View *view)
bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (CSVDoc::View *view) bool CSVDoc::ViewManager::showModifiedDocumentMessageBox (CSVDoc::View *view)
{ {
QMessageBox messageBox; emit closeMessageBox();
QMessageBox messageBox(view);
CSMDoc::Document *document = view->getDocument(); CSMDoc::Document *document = view->getDocument();
messageBox.setWindowTitle (document->getSavePath().filename().string().c_str());
messageBox.setText ("The document has been modified."); messageBox.setText ("The document has been modified.");
messageBox.setInformativeText ("Do you want to save your changes?"); messageBox.setInformativeText ("Do you want to save your changes?");
messageBox.setStandardButtons (QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel); messageBox.setStandardButtons (QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
messageBox.setDefaultButton (QMessageBox::Save); messageBox.setDefaultButton (QMessageBox::Save);
messageBox.setWindowModality (Qt::NonModal);
messageBox.hide();
messageBox.show();
bool retVal = true; bool retVal = true;
@ -341,8 +365,40 @@ void CSVDoc::ViewManager::onExitWarningHandler (int state, CSMDoc::Document *doc
} }
} }
bool CSVDoc::ViewManager::removeDocument (CSVDoc::View *view)
{
if(!notifySaveOnClose(view))
return false;
else
{
// don't bother closing views or updating indicies, but remove from mViews
CSMDoc::Document * document = view->getDocument();
std::vector<View *> remainingViews;
std::vector<View *>::const_iterator iter = mViews.begin();
for (; iter!=mViews.end(); ++iter)
{
if(document == (*iter)->getDocument())
(*iter)->setVisible(false);
else
remainingViews.push_back(*iter);
}
mDocumentManager.removeDocument(document);
mViews = remainingViews;
}
return true;
}
void CSVDoc::ViewManager::exitApplication (CSVDoc::View *view) void CSVDoc::ViewManager::exitApplication (CSVDoc::View *view)
{ {
if (notifySaveOnClose (view)) if(!removeDocument(view)) // close the current document first
QApplication::instance()->exit(); return;
while(!mViews.empty()) // attempt to close all other documents
{
mViews.back()->activateWindow();
mViews.back()->raise(); // raise the window to alert the user
if(!removeDocument(mViews.back()))
return;
}
// Editor exits (via a signal) when the last document is deleted
} }

@ -41,6 +41,7 @@ namespace CSVDoc
bool notifySaveOnClose (View *view = 0); bool notifySaveOnClose (View *view = 0);
bool showModifiedDocumentMessageBox (View *view); bool showModifiedDocumentMessageBox (View *view);
bool showSaveInProgressMessageBox (View *view); bool showSaveInProgressMessageBox (View *view);
bool removeDocument(View *view);
public: public:
@ -55,6 +56,7 @@ namespace CSVDoc
///< Return number of views for \a document. ///< Return number of views for \a document.
bool closeRequest (View *view); bool closeRequest (View *view);
void removeDocAndView (CSMDoc::Document *document);
signals: signals:

@ -1,77 +0,0 @@
#include "filtercreator.hpp"
#include <QComboBox>
#include <QLabel>
#include "../../model/filter/filter.hpp"
#include "../../model/world/data.hpp"
#include "../../model/world/commands.hpp"
#include "../../model/world/columns.hpp"
#include "../../model/world/idtable.hpp"
std::string CSVFilter::FilterCreator::getNamespace() const
{
switch (mScope->currentIndex())
{
case CSMFilter::Filter::Scope_Project: return "project::";
case CSMFilter::Filter::Scope_Session: return "session::";
}
return "";
}
void CSVFilter::FilterCreator::update()
{
mNamespace->setText (QString::fromUtf8 (getNamespace().c_str()));
GenericCreator::update();
}
std::string CSVFilter::FilterCreator::getId() const
{
return getNamespace() + GenericCreator::getId();
}
void CSVFilter::FilterCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const
{
int index =
dynamic_cast<CSMWorld::IdTable&> (*getData().getTableModel (getCollectionId())).
findColumnIndex (CSMWorld::Columns::ColumnId_Scope);
command.addValue (index, mScope->currentIndex());
}
CSVFilter::FilterCreator::FilterCreator (CSMWorld::Data& data, QUndoStack& undoStack,
const CSMWorld::UniversalId& id)
: GenericCreator (data, undoStack, id)
{
mNamespace = new QLabel ("::", this);
insertAtBeginning (mNamespace, false);
mScope = new QComboBox (this);
mScope->addItem ("Project");
mScope->addItem ("Session");
/// \todo re-enable for OpenMW 1.1
// mScope->addItem ("Content");
connect (mScope, SIGNAL (currentIndexChanged (int)), this, SLOT (setScope (int)));
insertAtBeginning (mScope, false);
QLabel *label = new QLabel ("Scope", this);
insertAtBeginning (label, false);
mScope->setCurrentIndex (1);
}
void CSVFilter::FilterCreator::reset()
{
GenericCreator::reset();
}
void CSVFilter::FilterCreator::setScope (int index)
{
update();
}

@ -1,43 +0,0 @@
#ifndef CSV_FILTER_FILTERCREATOR_H
#define CSV_FILTER_FILTERCREATOR_H
class QComboBox;
class QLabel;
#include "../world/genericcreator.hpp"
namespace CSVFilter
{
class FilterCreator : public CSVWorld::GenericCreator
{
Q_OBJECT
QComboBox *mScope;
QLabel *mNamespace;
private:
std::string getNamespace() const;
protected:
void update();
virtual std::string getId() const;
virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const;
public:
FilterCreator (CSMWorld::Data& data, QUndoStack& undoStack,
const CSMWorld::UniversalId& id);
virtual void reset();
private slots:
void setScope (int index);
};
}
#endif

@ -13,7 +13,9 @@ CSVFilter::RecordFilterBox::RecordFilterBox (CSMWorld::Data& data, QWidget *pare
layout->setContentsMargins (0, 0, 0, 0); layout->setContentsMargins (0, 0, 0, 0);
layout->addWidget (new QLabel ("Record Filter", this)); QLabel *label = new QLabel("Record Filter", this);
label->setIndent(2);
layout->addWidget (label);
mEdit = new EditWidget (data, this); mEdit = new EditWidget (data, this);

@ -0,0 +1,23 @@
#ifndef CSV_RENDER_ELEMENTS_H
#define CSV_RENDER_ELEMENTS_H
namespace CSVRender
{
/// Visual elements in a scene
enum Elements
{
// elements that are part of the actual scene
Element_Reference = 0x1,
Element_Terrain = 0x2,
Element_Water = 0x4,
Element_Pathgrid = 0x8,
Element_Fog = 0x10,
// control elements
Element_CellMarker = 0x10000,
Element_CellArrow = 0x20000,
Element_CellBorder = 0x40000
};
}
#endif

@ -11,9 +11,14 @@ float CSVRender::Navigation::getFactor (bool mouse) const
return factor; return factor;
} }
CSVRender::Navigation::Navigation()
: mFastModeFactor(1)
{
}
CSVRender::Navigation::~Navigation() {} CSVRender::Navigation::~Navigation() {}
void CSVRender::Navigation::setFastModeFactor (float factor) void CSVRender::Navigation::setFastModeFactor (float factor)
{ {
mFastModeFactor = factor; mFastModeFactor = factor;
} }

@ -20,6 +20,7 @@ namespace CSVRender
public: public:
Navigation();
virtual ~Navigation(); virtual ~Navigation();
void setFastModeFactor (float factor); void setFastModeFactor (float factor);

@ -9,6 +9,8 @@
#include "../../model/world/ref.hpp" #include "../../model/world/ref.hpp"
#include "../../model/world/refidcollection.hpp" #include "../../model/world/refidcollection.hpp"
#include "elements.hpp"
void CSVRender::Object::clearSceneNode (Ogre::SceneNode *node) void CSVRender::Object::clearSceneNode (Ogre::SceneNode *node)
{ {
for (Ogre::SceneNode::ObjectIterator iter = node->getAttachedObjectIterator(); for (Ogre::SceneNode::ObjectIterator iter = node->getAttachedObjectIterator();
@ -63,12 +65,14 @@ void CSVRender::Object::update()
{ {
Ogre::Entity* entity = mBase->getCreator()->createEntity (Ogre::SceneManager::PT_CUBE); Ogre::Entity* entity = mBase->getCreator()->createEntity (Ogre::SceneManager::PT_CUBE);
entity->setMaterialName("BaseWhite"); /// \todo adjust material according to error entity->setMaterialName("BaseWhite"); /// \todo adjust material according to error
entity->setVisibilityFlags (Element_Reference);
mBase->attachObject (entity); mBase->attachObject (entity);
} }
else else
{ {
mObject = NifOgre::Loader::createObjects (mBase, "Meshes\\" + model); mObject = NifOgre::Loader::createObjects (mBase, "Meshes\\" + model);
mObject->setVisibilityFlags (Element_Reference);
} }
} }

@ -19,6 +19,10 @@
#include "../../model/world/tablemimedata.hpp" #include "../../model/world/tablemimedata.hpp"
#include "../../model/world/idtable.hpp" #include "../../model/world/idtable.hpp"
#include "../widget/scenetooltoggle.hpp"
#include "elements.hpp"
void CSVRender::PagedWorldspaceWidget::displayCellCoord(bool display) void CSVRender::PagedWorldspaceWidget::displayCellCoord(bool display)
{ {
mDisplayCellCoord = display; mDisplayCellCoord = display;
@ -210,6 +214,20 @@ void CSVRender::PagedWorldspaceWidget::referenceAdded (const QModelIndex& parent
flagAsModified(); flagAsModified();
} }
std::string CSVRender::PagedWorldspaceWidget::getStartupInstruction()
{
Ogre::Vector3 position = getCamera()->getPosition();
std::ostringstream stream;
stream
<< "player->position "
<< position.x << ", " << position.y << ", " << position.z
<< ", 0";
return stream.str();
}
CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget* parent, CSMDoc::Document& document) CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget* parent, CSMDoc::Document& document)
: WorldspaceWidget(document, parent), mDocument(document), mWorldspace("std::default"), mDisplayCellCoord(true) : WorldspaceWidget(document, parent), mDocument(document), mWorldspace("std::default"), mDisplayCellCoord(true)
{ {
@ -283,8 +301,15 @@ std::pair< int, int > CSVRender::PagedWorldspaceWidget::getCoordinatesFromId (co
return std::make_pair(x, y); return std::make_pair(x, y);
} }
void CSVRender::PagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld::UniversalId >& data) bool CSVRender::PagedWorldspaceWidget::handleDrop (
const std::vector< CSMWorld::UniversalId >& data, DropType type)
{ {
if (WorldspaceWidget::handleDrop (data, type))
return true;
if (type!=Type_CellsExterior)
return false;
bool selectionChanged = false; bool selectionChanged = false;
for (unsigned i = 0; i < data.size(); ++i) for (unsigned i = 0; i < data.size(); ++i)
{ {
@ -301,16 +326,23 @@ void CSVRender::PagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld::
emit cellSelectionChanged(mSelection); emit cellSelectionChanged(mSelection);
} }
return true;
} }
CSVRender::WorldspaceWidget::dropRequirments CSVRender::PagedWorldspaceWidget::getDropRequirements (CSVRender::WorldspaceWidget::dropType type) const CSVRender::WorldspaceWidget::dropRequirments CSVRender::PagedWorldspaceWidget::getDropRequirements (CSVRender::WorldspaceWidget::DropType type) const
{ {
dropRequirments requirements = WorldspaceWidget::getDropRequirements (type);
if (requirements!=ignored)
return requirements;
switch (type) switch (type)
{ {
case cellsExterior: case Type_CellsExterior:
return canHandle; return canHandle;
case cellsInterior: case Type_CellsInterior:
return needUnpaged; return needUnpaged;
default: default:
@ -318,6 +350,31 @@ CSVRender::WorldspaceWidget::dropRequirments CSVRender::PagedWorldspaceWidget::g
} }
} }
unsigned int CSVRender::PagedWorldspaceWidget::getElementMask() const
{
return WorldspaceWidget::getElementMask() | mControlElements->getSelection();
}
CSVWidget::SceneToolToggle *CSVRender::PagedWorldspaceWidget::makeControlVisibilitySelector (
CSVWidget::SceneToolbar *parent)
{
mControlElements = new CSVWidget::SceneToolToggle (parent,
"Controls & Guides Visibility", ":door.png");
mControlElements->addButton (":activator.png", Element_CellMarker, ":activator.png",
"Cell marker");
mControlElements->addButton (":armor.png", Element_CellArrow, ":armor.png", "Cell arrows");
mControlElements->addButton (":armor.png", Element_CellBorder, ":armor.png", "Cell border");
mControlElements->setSelection (0xffffffff);
connect (mControlElements, SIGNAL (selectionChanged()),
this, SLOT (elementSelectionChanged()));
return mControlElements;
}
void CSVRender::PagedWorldspaceWidget::cellDataChanged (const QModelIndex& topLeft, void CSVRender::PagedWorldspaceWidget::cellDataChanged (const QModelIndex& topLeft,
const QModelIndex& bottomRight) const QModelIndex& bottomRight)
{ {

@ -18,6 +18,7 @@ namespace CSVRender
CSMWorld::CellSelection mSelection; CSMWorld::CellSelection mSelection;
std::map<CSMWorld::CellCoordinates, Cell *> mCells; std::map<CSMWorld::CellCoordinates, Cell *> mCells;
std::string mWorldspace; std::string mWorldspace;
CSVWidget::SceneToolToggle *mControlElements;
bool mDisplayCellCoord; bool mDisplayCellCoord;
private: private:
@ -42,6 +43,8 @@ namespace CSVRender
virtual void referenceAdded (const QModelIndex& index, int start, int end); virtual void referenceAdded (const QModelIndex& index, int start, int end);
virtual std::string getStartupInstruction();
public: public:
PagedWorldspaceWidget (QWidget *parent, CSMDoc::Document& document); PagedWorldspaceWidget (QWidget *parent, CSMDoc::Document& document);
@ -57,9 +60,19 @@ namespace CSVRender
void displayCellCoord(bool display); void displayCellCoord(bool display);
virtual void handleDrop(const std::vector<CSMWorld::UniversalId>& data);
virtual dropRequirments getDropRequirements(dropType type) const; /// \return Drop handled?
virtual bool handleDrop (const std::vector<CSMWorld::UniversalId>& data,
DropType type);
virtual dropRequirments getDropRequirements(DropType type) const;
/// \attention The created tool is not added to the toolbar (via addTool). Doing
/// that is the responsibility of the calling function.
virtual CSVWidget::SceneToolToggle *makeControlVisibilitySelector (
CSVWidget::SceneToolbar *parent);
virtual unsigned int getElementMask() const;
signals: signals:

@ -64,19 +64,19 @@ namespace CSVRender
CSVWidget::SceneToolMode *tool = new CSVWidget::SceneToolMode (parent, "Lighting Mode"); CSVWidget::SceneToolMode *tool = new CSVWidget::SceneToolMode (parent, "Lighting Mode");
/// \todo replace icons /// \todo replace icons
tool->addButton (":door.png", "day", tool->addButton (":scenetoolbar/day", "day",
"Day" "Day"
"<ul><li>Cell specific ambient in interiors</li>" "<ul><li>Cell specific ambient in interiors</li>"
"<li>Low ambient in exteriors</li>" "<li>Low ambient in exteriors</li>"
"<li>Strong directional light source/lir>" "<li>Strong directional light source/lir>"
"<li>This mode closely resembles day time in-game</li></ul>"); "<li>This mode closely resembles day time in-game</li></ul>");
tool->addButton (":GMST.png", "night", tool->addButton (":scenetoolbar/night", "night",
"Night" "Night"
"<ul><li>Cell specific ambient in interiors</li>" "<ul><li>Cell specific ambient in interiors</li>"
"<li>Low ambient in exteriors</li>" "<li>Low ambient in exteriors</li>"
"<li>Weak directional light source</li>" "<li>Weak directional light source</li>"
"<li>This mode closely resembles night time in-game</li></ul>"); "<li>This mode closely resembles night time in-game</li></ul>");
tool->addButton (":Info.png", "bright", tool->addButton (":scenetoolbar/bright", "bright",
"Bright" "Bright"
"<ul><li>Maximum ambient</li>" "<ul><li>Maximum ambient</li>"
"<li>Strong directional light source</li></ul>"); "<li>Strong directional light source</li></ul>");
@ -126,7 +126,9 @@ namespace CSVRender
#endif #endif
mWindow = Ogre::Root::getSingleton().createRenderWindow(windowTitle.str(), this->width(), this->height(), false, &params); mWindow = Ogre::Root::getSingleton().createRenderWindow(windowTitle.str(), this->width(), this->height(), false, &params);
mWindow->addViewport(mCamera)->setBackgroundColour(Ogre::ColourValue(0.3,0.3,0.3,1));
mViewport = mWindow->addViewport (mCamera);
mViewport->setBackgroundColour (Ogre::ColourValue (0.3,0.3,0.3,1));
Ogre::Real aspectRatio = Ogre::Real(width()) / Ogre::Real(height()); Ogre::Real aspectRatio = Ogre::Real(width()) / Ogre::Real(height());
mCamera->setAspectRatio(aspectRatio); mCamera->setAspectRatio(aspectRatio);
@ -141,6 +143,11 @@ namespace CSVRender
Ogre::Root::getSingleton().destroySceneManager (mSceneMgr); Ogre::Root::getSingleton().destroySceneManager (mSceneMgr);
} }
void SceneWidget::setVisibilityMask (unsigned int mask)
{
mViewport->setVisibilityMask (mask);
}
void SceneWidget::setNavigation (Navigation *navigation) void SceneWidget::setNavigation (Navigation *navigation)
{ {
if ((mNavigation = navigation)) if ((mNavigation = navigation))
@ -354,11 +361,6 @@ namespace CSVRender
} }
} }
int SceneWidget::getFastFactor() const
{
return mFast ? mFastFactor : 1;
}
void SceneWidget::setLighting (Lighting *lighting) void SceneWidget::setLighting (Lighting *lighting)
{ {
if (mLighting) if (mLighting)

@ -14,6 +14,7 @@ namespace Ogre
class Camera; class Camera;
class SceneManager; class SceneManager;
class RenderWindow; class RenderWindow;
class Viewport;
} }
namespace CSVWidget namespace CSVWidget
@ -42,6 +43,8 @@ namespace CSVRender
///< \attention The created tool is not added to the toolbar (via addTool). Doing that ///< \attention The created tool is not added to the toolbar (via addTool). Doing that
/// is the responsibility of the calling function. /// is the responsibility of the calling function.
virtual void setVisibilityMask (unsigned int mask);
protected: protected:
void setNavigation (Navigation *navigation); void setNavigation (Navigation *navigation);
@ -77,14 +80,13 @@ namespace CSVRender
void updateOgreWindow(); void updateOgreWindow();
int getFastFactor() const;
void setLighting (Lighting *lighting); void setLighting (Lighting *lighting);
///< \attention The ownership of \a lighting is not transferred to *this. ///< \attention The ownership of \a lighting is not transferred to *this.
Ogre::Camera* mCamera; Ogre::Camera* mCamera;
Ogre::SceneManager* mSceneMgr; Ogre::SceneManager* mSceneMgr;
Ogre::RenderWindow* mWindow; Ogre::RenderWindow* mWindow;
Ogre::Viewport *mViewport;
Navigation *mNavigation; Navigation *mNavigation;
Lighting *mLighting; Lighting *mLighting;

@ -1,7 +1,10 @@
#include "unpagedworldspacewidget.hpp" #include "unpagedworldspacewidget.hpp"
#include <sstream>
#include <OgreColourValue.h> #include <OgreColourValue.h>
#include <OgreCamera.h>
#include <QtGui/qevent.h> #include <QtGui/qevent.h>
@ -11,6 +14,10 @@
#include "../../model/world/idtable.hpp" #include "../../model/world/idtable.hpp"
#include "../../model/world/tablemimedata.hpp" #include "../../model/world/tablemimedata.hpp"
#include "../widget/scenetooltoggle.hpp"
#include "elements.hpp"
void CSVRender::UnpagedWorldspaceWidget::update() void CSVRender::UnpagedWorldspaceWidget::update()
{ {
const CSMWorld::Record<CSMWorld::Cell>& record = const CSMWorld::Record<CSMWorld::Cell>& record =
@ -25,6 +32,14 @@ void CSVRender::UnpagedWorldspaceWidget::update()
flagAsModified(); flagAsModified();
} }
void CSVRender::UnpagedWorldspaceWidget::addVisibilitySelectorButtons (
CSVWidget::SceneToolToggle *tool)
{
WorldspaceWidget::addVisibilitySelectorButtons (tool);
tool->addButton (":armor.png", Element_Fog, ":armor.png", "Fog");
}
CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document, QWidget* parent) CSVRender::UnpagedWorldspaceWidget::UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document, QWidget* parent)
: WorldspaceWidget (document, parent), mCellId (cellId) : WorldspaceWidget (document, parent), mCellId (cellId)
{ {
@ -74,13 +89,21 @@ void CSVRender::UnpagedWorldspaceWidget::cellRowsAboutToBeRemoved (const QModelI
emit closeRequest(); emit closeRequest();
} }
void CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vector< CSMWorld::UniversalId >& data) bool CSVRender::UnpagedWorldspaceWidget::handleDrop (const std::vector<CSMWorld::UniversalId>& data, DropType type)
{ {
if (WorldspaceWidget::handleDrop (data, type))
return true;
if (type!=Type_CellsInterior)
return false;
mCellId = data.begin()->getId(); mCellId = data.begin()->getId();
mCell.reset (new Cell (getDocument().getData(), getSceneManager(), mCellId));
update(); update();
emit cellChanged(*data.begin()); emit cellChanged(*data.begin());
/// \todo replace mCell return true;
} }
void CSVRender::UnpagedWorldspaceWidget::referenceableDataChanged (const QModelIndex& topLeft, void CSVRender::UnpagedWorldspaceWidget::referenceableDataChanged (const QModelIndex& topLeft,
@ -137,14 +160,33 @@ void CSVRender::UnpagedWorldspaceWidget::referenceAdded (const QModelIndex& pare
flagAsModified(); flagAsModified();
} }
CSVRender::WorldspaceWidget::dropRequirments CSVRender::UnpagedWorldspaceWidget::getDropRequirements (CSVRender::WorldspaceWidget::dropType type) const std::string CSVRender::UnpagedWorldspaceWidget::getStartupInstruction()
{ {
Ogre::Vector3 position = getCamera()->getPosition();
std::ostringstream stream;
stream
<< "player->positionCell "
<< position.x << ", " << position.y << ", " << position.z
<< ", 0, \"" << mCellId << "\"";
return stream.str();
}
CSVRender::WorldspaceWidget::dropRequirments CSVRender::UnpagedWorldspaceWidget::getDropRequirements (CSVRender::WorldspaceWidget::DropType type) const
{
dropRequirments requirements = WorldspaceWidget::getDropRequirements (type);
if (requirements!=ignored)
return requirements;
switch(type) switch(type)
{ {
case cellsInterior: case Type_CellsInterior:
return canHandle; return canHandle;
case cellsExterior: case Type_CellsExterior:
return needPaged; return needPaged;
default: default:

@ -32,14 +32,20 @@ namespace CSVRender
void update(); void update();
protected:
virtual void addVisibilitySelectorButtons (CSVWidget::SceneToolToggle *tool);
public: public:
UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document, UnpagedWorldspaceWidget (const std::string& cellId, CSMDoc::Document& document,
QWidget *parent); QWidget *parent);
virtual dropRequirments getDropRequirements(dropType type) const; virtual dropRequirments getDropRequirements(DropType type) const;
virtual void handleDrop(const std::vector<CSMWorld::UniversalId>& data); /// \return Drop handled?
virtual bool handleDrop (const std::vector<CSMWorld::UniversalId>& data,
DropType type);
private: private:
@ -56,6 +62,8 @@ namespace CSVRender
virtual void referenceAdded (const QModelIndex& index, int start, int end); virtual void referenceAdded (const QModelIndex& index, int start, int end);
virtual std::string getStartupInstruction();
private slots: private slots:
void cellDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight); void cellDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);

@ -1,6 +1,8 @@
#include "worldspacewidget.hpp" #include "worldspacewidget.hpp"
#include <algorithm>
#include <OgreSceneNode.h> #include <OgreSceneNode.h>
#include <OgreSceneManager.h> #include <OgreSceneManager.h>
#include <OgreEntity.h> #include <OgreEntity.h>
@ -8,11 +10,16 @@
#include <QtGui/qevent.h> #include <QtGui/qevent.h>
#include "../../model/world/universalid.hpp" #include "../../model/world/universalid.hpp"
#include "../../model/world/idtable.hpp"
#include "../widget/scenetoolmode.hpp" #include "../widget/scenetoolmode.hpp"
#include "../widget/scenetooltoggle.hpp"
#include "../widget/scenetoolrun.hpp"
#include "elements.hpp"
CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidget* parent) CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidget* parent)
: SceneWidget (parent), mDocument(document) : SceneWidget (parent), mDocument(document), mRun (0)
{ {
setAcceptDrops(true); setAcceptDrops(true);
@ -35,6 +42,14 @@ CSVRender::WorldspaceWidget::WorldspaceWidget (CSMDoc::Document& document, QWidg
this, SLOT (referenceAboutToBeRemoved (const QModelIndex&, int, int))); this, SLOT (referenceAboutToBeRemoved (const QModelIndex&, int, int)));
connect (references, SIGNAL (rowsInserted (const QModelIndex&, int, int)), connect (references, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
this, SLOT (referenceAdded (const QModelIndex&, int, int))); this, SLOT (referenceAdded (const QModelIndex&, int, int)));
QAbstractItemModel *debugProfiles =
document.getData().getTableModel (CSMWorld::UniversalId::Type_DebugProfiles);
connect (debugProfiles, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
this, SLOT (debugProfileDataChanged (const QModelIndex&, const QModelIndex&)));
connect (debugProfiles, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
this, SLOT (debugProfileAboutToBeRemoved (const QModelIndex&, int, int)));
} }
void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode) void CSVRender::WorldspaceWidget::selectNavigationMode (const std::string& mode)
@ -61,7 +76,7 @@ CSVWidget::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector (
/// \todo replace icons /// \todo replace icons
/// \todo consider user-defined button-mapping /// \todo consider user-defined button-mapping
tool->addButton (":door.png", "1st", tool->addButton (":scenetoolbar/1st-person", "1st",
"First Person" "First Person"
"<ul><li>Mouse-Look while holding the left button</li>" "<ul><li>Mouse-Look while holding the left button</li>"
"<li>WASD movement keys</li>" "<li>WASD movement keys</li>"
@ -70,7 +85,7 @@ CSVWidget::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector (
"<li>Camera is held upright</li>" "<li>Camera is held upright</li>"
"<li>Hold shift to speed up movement</li>" "<li>Hold shift to speed up movement</li>"
"</ul>"); "</ul>");
tool->addButton (":GMST.png", "free", tool->addButton (":scenetoolbar/free-camera", "free",
"Free Camera" "Free Camera"
"<ul><li>Mouse-Look while holding the left button</li>" "<ul><li>Mouse-Look while holding the left button</li>"
"<li>Stafing (also vertically) via WASD or by holding the left mouse button and control</li>" "<li>Stafing (also vertically) via WASD or by holding the left mouse button and control</li>"
@ -78,7 +93,7 @@ CSVWidget::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector (
"<li>Roll camera with Q and E keys</li>" "<li>Roll camera with Q and E keys</li>"
"<li>Hold shift to speed up movement</li>" "<li>Hold shift to speed up movement</li>"
"</ul>"); "</ul>");
tool->addButton (":Info.png", "orbit", tool->addButton (":scenetoolbar/orbiting-camera", "orbit",
"Orbiting Camera" "Orbiting Camera"
"<ul><li>Always facing the centre point</li>" "<ul><li>Always facing the centre point</li>"
"<li>Rotate around the centre point via WASD or by moving the mouse while holding the left button</li>" "<li>Rotate around the centre point via WASD or by moving the mouse while holding the left button</li>"
@ -94,59 +109,132 @@ CSVWidget::SceneToolMode *CSVRender::WorldspaceWidget::makeNavigationSelector (
return tool; return tool;
} }
CSVRender::WorldspaceWidget::dropType CSVRender::WorldspaceWidget::getDropType ( CSVWidget::SceneToolToggle *CSVRender::WorldspaceWidget::makeSceneVisibilitySelector (CSVWidget::SceneToolbar *parent)
{
mSceneElements= new CSVWidget::SceneToolToggle (parent,
"Scene Element Visibility", ":door.png");
addVisibilitySelectorButtons (mSceneElements);
mSceneElements->setSelection (0xffffffff);
connect (mSceneElements, SIGNAL (selectionChanged()),
this, SLOT (elementSelectionChanged()));
return mSceneElements;
}
CSVWidget::SceneToolRun *CSVRender::WorldspaceWidget::makeRunTool (
CSVWidget::SceneToolbar *parent)
{
CSMWorld::IdTable& debugProfiles = dynamic_cast<CSMWorld::IdTable&> (
*mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_DebugProfiles));
std::vector<std::string> profiles;
int idColumn = debugProfiles.findColumnIndex (CSMWorld::Columns::ColumnId_Id);
int stateColumn = debugProfiles.findColumnIndex (CSMWorld::Columns::ColumnId_Modification);
int defaultColumn = debugProfiles.findColumnIndex (
CSMWorld::Columns::ColumnId_DefaultProfile);
int size = debugProfiles.rowCount();
for (int i=0; i<size; ++i)
{
int state = debugProfiles.data (debugProfiles.index (i, stateColumn)).toInt();
bool default_ = debugProfiles.data (debugProfiles.index (i, defaultColumn)).toInt();
if (state!=CSMWorld::RecordBase::State_Deleted && default_)
profiles.push_back (
debugProfiles.data (debugProfiles.index (i, idColumn)).
toString().toUtf8().constData());
}
std::sort (profiles.begin(), profiles.end());
mRun = new CSVWidget::SceneToolRun (parent, "Run OpenMW from the current camera position",
":door.png", ":faction.png", profiles);
connect (mRun, SIGNAL (runRequest (const std::string&)),
this, SLOT (runRequest (const std::string&)));
return mRun;
}
CSVRender::WorldspaceWidget::DropType CSVRender::WorldspaceWidget::getDropType (
const std::vector< CSMWorld::UniversalId >& data) const std::vector< CSMWorld::UniversalId >& data)
{ {
dropType output = notCells; DropType output = Type_Other;
bool firstIteration = true;
for (unsigned i = 0; i < data.size(); ++i) for (std::vector<CSMWorld::UniversalId>::const_iterator iter (data.begin());
iter!=data.end(); ++iter)
{ {
if (data[i].getType() == CSMWorld::UniversalId::Type_Cell || DropType type = Type_Other;
data[i].getType() == CSMWorld::UniversalId::Type_Cell_Missing)
if (iter->getType()==CSMWorld::UniversalId::Type_Cell ||
iter->getType()==CSMWorld::UniversalId::Type_Cell_Missing)
{ {
if (*(data[i].getId().begin()) == '#') //exterior type = iter->getId().substr (0, 1)=="#" ? Type_CellsExterior : Type_CellsInterior;
{
if (firstIteration)
{
output = cellsExterior;
firstIteration = false;
continue;
}
if (output == cellsInterior)
{
output = cellsMixed;
break;
} else {
output = cellsInterior;
}
} else //interior
{
if (firstIteration)
{
output = cellsInterior;
firstIteration = false;
continue;
}
if (output == cellsExterior)
{
output = cellsMixed;
break;
} else {
output = cellsInterior;
}
}
} else {
output = notCells;
break;
} }
else if (iter->getType()==CSMWorld::UniversalId::Type_DebugProfile)
type = Type_DebugProfile;
if (iter==data.begin())
output = type;
else if (output!=type) // mixed types -> ignore
return Type_Other;
} }
return output; return output;
} }
CSVRender::WorldspaceWidget::dropRequirments
CSVRender::WorldspaceWidget::getDropRequirements (DropType type) const
{
if (type==Type_DebugProfile)
return canHandle;
return ignored;
}
bool CSVRender::WorldspaceWidget::handleDrop (const std::vector<CSMWorld::UniversalId>& data,
DropType type)
{
if (type==Type_DebugProfile)
{
if (mRun)
{
for (std::vector<CSMWorld::UniversalId>::const_iterator iter (data.begin());
iter!=data.end(); ++iter)
mRun->addProfile (iter->getId());
}
return true;
}
return false;
}
unsigned int CSVRender::WorldspaceWidget::getElementMask() const
{
return mSceneElements->getSelection();
}
void CSVRender::WorldspaceWidget::addVisibilitySelectorButtons (
CSVWidget::SceneToolToggle *tool)
{
tool->addButton (":activator.png", Element_Reference, ":activator.png", "References");
tool->addButton (":armor.png", Element_Terrain, ":armor.png", "Terrain");
tool->addButton (":armor.png", Element_Water, ":armor.png", "Water");
tool->addButton (":armor.png", Element_Pathgrid, ":armor.png", "Pathgrid");
}
CSMDoc::Document& CSVRender::WorldspaceWidget::getDocument()
{
return mDocument;
}
void CSVRender::WorldspaceWidget::dragEnterEvent (QDragEnterEvent* event) void CSVRender::WorldspaceWidget::dragEnterEvent (QDragEnterEvent* event)
{ {
event->accept(); event->accept();
@ -157,7 +245,6 @@ void CSVRender::WorldspaceWidget::dragMoveEvent(QDragMoveEvent *event)
event->accept(); event->accept();
} }
void CSVRender::WorldspaceWidget::dropEvent (QDropEvent* event) void CSVRender::WorldspaceWidget::dropEvent (QDropEvent* event)
{ {
const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData()); const CSMWorld::TableMimeData* mime = dynamic_cast<const CSMWorld::TableMimeData*> (event->mimeData());
@ -169,3 +256,61 @@ void CSVRender::WorldspaceWidget::dropEvent (QDropEvent* event)
emit dataDropped(mime->getData()); emit dataDropped(mime->getData());
} //not handling drops from different documents at the moment } //not handling drops from different documents at the moment
} }
void CSVRender::WorldspaceWidget::runRequest (const std::string& profile)
{
mDocument.startRunning (profile, getStartupInstruction());
}
void CSVRender::WorldspaceWidget::debugProfileDataChanged (const QModelIndex& topLeft,
const QModelIndex& bottomRight)
{
if (!mRun)
return;
CSMWorld::IdTable& debugProfiles = dynamic_cast<CSMWorld::IdTable&> (
*mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_DebugProfiles));
int idColumn = debugProfiles.findColumnIndex (CSMWorld::Columns::ColumnId_Id);
int stateColumn = debugProfiles.findColumnIndex (CSMWorld::Columns::ColumnId_Modification);
for (int i=topLeft.row(); i<=bottomRight.row(); ++i)
{
int state = debugProfiles.data (debugProfiles.index (i, stateColumn)).toInt();
// As of version 0.33 this case can not happen because debug profiles exist only in
// project or session scope, which means they will never be in deleted state. But we
// are adding the code for the sake of completeness and to avoid surprises if debug
// profile ever get extended to content scope.
if (state==CSMWorld::RecordBase::State_Deleted)
mRun->removeProfile (debugProfiles.data (
debugProfiles.index (i, idColumn)).toString().toUtf8().constData());
}
}
void CSVRender::WorldspaceWidget::debugProfileAboutToBeRemoved (const QModelIndex& parent,
int start, int end)
{
if (parent.isValid())
return;
if (!mRun)
return;
CSMWorld::IdTable& debugProfiles = dynamic_cast<CSMWorld::IdTable&> (
*mDocument.getData().getTableModel (CSMWorld::UniversalId::Type_DebugProfiles));
int idColumn = debugProfiles.findColumnIndex (CSMWorld::Columns::ColumnId_Id);
for (int i=start; i<=end; ++i)
{
mRun->removeProfile (debugProfiles.data (
debugProfiles.index (i, idColumn)).toString().toUtf8().constData());
}
}
void CSVRender::WorldspaceWidget::elementSelectionChanged()
{
setVisibilityMask (getElementMask());
flagAsModified();
}

@ -16,7 +16,9 @@ namespace CSMWorld
namespace CSVWidget namespace CSVWidget
{ {
class SceneToolMode; class SceneToolMode;
class SceneToolToggle;
class SceneToolbar; class SceneToolbar;
class SceneToolRun;
} }
namespace CSVRender namespace CSVRender
@ -28,15 +30,18 @@ namespace CSVRender
CSVRender::Navigation1st m1st; CSVRender::Navigation1st m1st;
CSVRender::NavigationFree mFree; CSVRender::NavigationFree mFree;
CSVRender::NavigationOrbit mOrbit; CSVRender::NavigationOrbit mOrbit;
CSVWidget::SceneToolToggle *mSceneElements;
CSVWidget::SceneToolRun *mRun;
CSMDoc::Document& mDocument;
public: public:
enum dropType enum DropType
{ {
cellsMixed, Type_CellsInterior,
cellsInterior, Type_CellsExterior,
cellsExterior, Type_Other,
notCells Type_DebugProfile
}; };
enum dropRequirments enum dropRequirments
@ -53,19 +58,35 @@ namespace CSVRender
///< \attention The created tool is not added to the toolbar (via addTool). Doing that ///< \attention The created tool is not added to the toolbar (via addTool). Doing that
/// is the responsibility of the calling function. /// is the responsibility of the calling function.
/// \attention The created tool is not added to the toolbar (via addTool). Doing
/// that is the responsibility of the calling function.
CSVWidget::SceneToolToggle *makeSceneVisibilitySelector (
CSVWidget::SceneToolbar *parent);
/// \attention The created tool is not added to the toolbar (via addTool). Doing
/// that is the responsibility of the calling function.
CSVWidget::SceneToolRun *makeRunTool (CSVWidget::SceneToolbar *parent);
void selectDefaultNavigationMode(); void selectDefaultNavigationMode();
static dropType getDropType(const std::vector<CSMWorld::UniversalId>& data); static DropType getDropType(const std::vector<CSMWorld::UniversalId>& data);
virtual dropRequirments getDropRequirements(dropType type) const = 0; virtual dropRequirments getDropRequirements(DropType type) const;
virtual void useViewHint (const std::string& hint); virtual void useViewHint (const std::string& hint);
///< Default-implementation: ignored. ///< Default-implementation: ignored.
virtual void handleDrop(const std::vector<CSMWorld::UniversalId>& data) = 0; /// \return Drop handled?
virtual bool handleDrop (const std::vector<CSMWorld::UniversalId>& data,
DropType type);
virtual unsigned int getElementMask() const;
protected: protected:
const CSMDoc::Document& mDocument; //for checking if drop comes from same document
virtual void addVisibilitySelectorButtons (CSVWidget::SceneToolToggle *tool);
CSMDoc::Document& getDocument();
private: private:
@ -75,6 +96,8 @@ namespace CSVRender
void dragMoveEvent(QDragMoveEvent *event); void dragMoveEvent(QDragMoveEvent *event);
virtual std::string getStartupInstruction() = 0;
private slots: private slots:
void selectNavigationMode (const std::string& mode); void selectNavigationMode (const std::string& mode);
@ -92,6 +115,18 @@ namespace CSVRender
virtual void referenceAdded (const QModelIndex& index, int start, int end) = 0; virtual void referenceAdded (const QModelIndex& index, int start, int end) = 0;
virtual void runRequest (const std::string& profile);
void debugProfileDataChanged (const QModelIndex& topLeft,
const QModelIndex& bottomRight);
void debugProfileAboutToBeRemoved (const QModelIndex& parent, int start, int end);
protected slots:
void elementSelectionChanged();
signals: signals:
void closeRequest(); void closeRequest();

@ -114,8 +114,20 @@ void CSVSettings::Dialog::show()
setViewValues(); setViewValues();
} }
QPoint screenCenter = QApplication::desktop()->screenGeometry().center(); QWidget *currView = QApplication::activeWindow();
if(currView)
move (screenCenter - geometry().center()); {
// place at the center of the window with focus
QSize size = currView->size();
move(currView->geometry().x()+(size.width() - frameGeometry().width())/2,
currView->geometry().y()+(size.height() - frameGeometry().height())/2);
}
else
{
// something's gone wrong, place at the center of the screen
QPoint screenCenter = QApplication::desktop()->screenGeometry().center();
move(screenCenter - QPoint(frameGeometry().width()/2,
frameGeometry().height()/2));
}
QWidget::show(); QWidget::show();
} }

@ -21,7 +21,7 @@ CSVTools::ReportSubView::ReportSubView (const CSMWorld::UniversalId& id, CSMDoc:
mTable->setSelectionMode (QAbstractItemView::ExtendedSelection); mTable->setSelectionMode (QAbstractItemView::ExtendedSelection);
mIdTypeDelegate = CSVWorld::IdTypeDelegateFactory().makeDelegate ( mIdTypeDelegate = CSVWorld::IdTypeDelegateFactory().makeDelegate (
document.getUndoStack(), this); document, this);
mTable->setItemDelegateForColumn (0, mIdTypeDelegate); mTable->setItemDelegateForColumn (0, mIdTypeDelegate);

@ -4,9 +4,9 @@
#include <QMouseEvent> #include <QMouseEvent>
#include <QKeyEvent> #include <QKeyEvent>
void CSVWidget::PushButton::setExtendedToolTip (const QString& text) void CSVWidget::PushButton::setExtendedToolTip()
{ {
QString tooltip = text; QString tooltip = mToolTip;
if (tooltip.isEmpty()) if (tooltip.isEmpty())
tooltip = "(Tool tip not implemented yet)"; tooltip = "(Tool tip not implemented yet)";
@ -20,6 +20,10 @@ void CSVWidget::PushButton::setExtendedToolTip (const QString& text)
break; break;
case Type_TopAction:
break;
case Type_Mode: case Type_Mode:
tooltip += tooltip +=
@ -27,6 +31,16 @@ void CSVWidget::PushButton::setExtendedToolTip (const QString& text)
"<br>shift-left click to activate and keep panel open)"; "<br>shift-left click to activate and keep panel open)";
break; break;
case Type_Toggle:
tooltip += "<p>(left click to ";
tooltip += isChecked() ? "disable" : "enable";
tooltip += "<p>shift-left click to ";
tooltip += isChecked() ? "disable" : "enable";
tooltip += " and keep panel open)";
break;
} }
setToolTip (tooltip); setToolTip (tooltip);
@ -42,11 +56,8 @@ void CSVWidget::PushButton::keyPressEvent (QKeyEvent *event)
void CSVWidget::PushButton::keyReleaseEvent (QKeyEvent *event) void CSVWidget::PushButton::keyReleaseEvent (QKeyEvent *event)
{ {
if (event->key()==Qt::Key_Return || event->key()==Qt::Key_Enter) if (event->key()==Qt::Key_Space)
{
mKeepOpen = event->modifiers() & Qt::ShiftModifier; mKeepOpen = event->modifiers() & Qt::ShiftModifier;
emit clicked();
}
QPushButton::keyReleaseEvent (event); QPushButton::keyReleaseEvent (event);
} }
@ -61,15 +72,15 @@ CSVWidget::PushButton::PushButton (const QIcon& icon, Type type, const QString&
QWidget *parent) QWidget *parent)
: QPushButton (icon, "", parent), mKeepOpen (false), mType (type), mToolTip (tooltip) : QPushButton (icon, "", parent), mKeepOpen (false), mType (type), mToolTip (tooltip)
{ {
setCheckable (type==Type_Mode); setCheckable (type==Type_Mode || type==Type_Toggle);
setExtendedToolTip (tooltip); setExtendedToolTip();
} }
CSVWidget::PushButton::PushButton (Type type, const QString& tooltip, QWidget *parent) CSVWidget::PushButton::PushButton (Type type, const QString& tooltip, QWidget *parent)
: QPushButton (parent), mKeepOpen (false), mType (type), mToolTip (tooltip) : QPushButton (parent), mKeepOpen (false), mType (type), mToolTip (tooltip)
{ {
setCheckable (type==Type_Mode); setCheckable (type==Type_Mode || type==Type_Toggle);
setExtendedToolTip (tooltip); setExtendedToolTip();
} }
bool CSVWidget::PushButton::hasKeepOpen() const bool CSVWidget::PushButton::hasKeepOpen() const
@ -80,4 +91,9 @@ bool CSVWidget::PushButton::hasKeepOpen() const
QString CSVWidget::PushButton::getBaseToolTip() const QString CSVWidget::PushButton::getBaseToolTip() const
{ {
return mToolTip; return mToolTip;
}
CSVWidget::PushButton::Type CSVWidget::PushButton::getType() const
{
return mType;
} }

@ -14,7 +14,9 @@ namespace CSVWidget
enum Type enum Type
{ {
Type_TopMode, // top level button for mode selector panel Type_TopMode, // top level button for mode selector panel
Type_Mode // mode button Type_TopAction, // top level button that triggers an action
Type_Mode, // mode button
Type_Toggle
}; };
private: private:
@ -25,7 +27,7 @@ namespace CSVWidget
private: private:
void setExtendedToolTip (const QString& text); void setExtendedToolTip();
protected: protected:
@ -49,6 +51,8 @@ namespace CSVWidget
/// Return tooltip used at construction (without any button-specific modifications) /// Return tooltip used at construction (without any button-specific modifications)
QString getBaseToolTip() const; QString getBaseToolTip() const;
Type getType() const;
}; };
} }

@ -1,10 +1,12 @@
#include "scenetool.hpp" #include "scenetool.hpp"
#include <QMouseEvent>
#include "scenetoolbar.hpp" #include "scenetoolbar.hpp"
CSVWidget::SceneTool::SceneTool (SceneToolbar *parent) CSVWidget::SceneTool::SceneTool (SceneToolbar *parent, Type type)
: PushButton (PushButton::Type_TopMode, "", parent) : PushButton (type, "", parent)
{ {
setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed)); setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
setIconSize (QSize (parent->getIconSize(), parent->getIconSize())); setIconSize (QSize (parent->getIconSize(), parent->getIconSize()));
@ -13,7 +15,20 @@ CSVWidget::SceneTool::SceneTool (SceneToolbar *parent)
connect (this, SIGNAL (clicked()), this, SLOT (openRequest())); connect (this, SIGNAL (clicked()), this, SLOT (openRequest()));
} }
void CSVWidget::SceneTool::activate() {}
void CSVWidget::SceneTool::mouseReleaseEvent (QMouseEvent *event)
{
if (getType()==Type_TopAction && event->button()==Qt::RightButton)
showPanel (parentWidget()->mapToGlobal (pos()));
else
PushButton::mouseReleaseEvent (event);
}
void CSVWidget::SceneTool::openRequest() void CSVWidget::SceneTool::openRequest()
{ {
showPanel (parentWidget()->mapToGlobal (pos())); if (getType()==Type_TopAction)
activate();
else
showPanel (parentWidget()->mapToGlobal (pos()));
} }

@ -14,10 +14,18 @@ namespace CSVWidget
public: public:
SceneTool (SceneToolbar *parent); SceneTool (SceneToolbar *parent, Type type = Type_TopMode);
virtual void showPanel (const QPoint& position) = 0; virtual void showPanel (const QPoint& position) = 0;
/// This function will only called for buttons of type Type_TopAction. The default
/// implementation is empty.
virtual void activate();
protected:
void mouseReleaseEvent (QMouseEvent *event);
private slots: private slots:
void openRequest(); void openRequest();

@ -0,0 +1,151 @@
#include "scenetoolrun.hpp"
#include <iterator>
#include <QFrame>
#include <QTableWidget>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QApplication>
void CSVWidget::SceneToolRun::adjustToolTips()
{
QString toolTip = mToolTip;
if (mSelected==mProfiles.end())
toolTip += "<p>No debug profile selected (function disabled)";
else
{
toolTip += "<p>Debug profile: " + QString::fromUtf8 (mSelected->c_str());
toolTip += "<p>(right click to switch to a different profile)";
}
setToolTip (toolTip);
}
void CSVWidget::SceneToolRun::updateIcon()
{
setIcon (QIcon (mSelected==mProfiles.end() ? mIconDisabled : mIcon));
}
void CSVWidget::SceneToolRun::updatePanel()
{
mTable->setRowCount (mProfiles.size());
int i = 0;
for (std::set<std::string>::const_iterator iter (mProfiles.begin()); iter!=mProfiles.end();
++iter, ++i)
{
mTable->setItem (i, 0, new QTableWidgetItem (QString::fromUtf8 (iter->c_str())));
mTable->setItem (i, 1, new QTableWidgetItem (
QApplication::style()->standardIcon (QStyle::SP_TitleBarCloseButton), ""));
}
}
CSVWidget::SceneToolRun::SceneToolRun (SceneToolbar *parent, const QString& toolTip,
const QString& icon, const QString& iconDisabled, const std::vector<std::string>& profiles)
: SceneTool (parent, Type_TopAction), mProfiles (profiles.begin(), profiles.end()),
mSelected (mProfiles.begin()), mToolTip (toolTip), mIcon (icon),
mIconDisabled (iconDisabled)
{
updateIcon();
adjustToolTips();
mPanel = new QFrame (this, Qt::Popup);
QHBoxLayout *layout = new QHBoxLayout (mPanel);
layout->setContentsMargins (QMargins (0, 0, 0, 0));
mTable = new QTableWidget (0, 2, this);
mTable->setShowGrid (false);
mTable->verticalHeader()->hide();
mTable->horizontalHeader()->hide();
mTable->horizontalHeader()->setResizeMode (0, QHeaderView::Stretch);
mTable->horizontalHeader()->setResizeMode (1, QHeaderView::ResizeToContents);
mTable->setSelectionMode (QAbstractItemView::NoSelection);
layout->addWidget (mTable);
connect (mTable, SIGNAL (clicked (const QModelIndex&)),
this, SLOT (clicked (const QModelIndex&)));
}
void CSVWidget::SceneToolRun::showPanel (const QPoint& position)
{
updatePanel();
mPanel->move (position);
mPanel->show();
}
void CSVWidget::SceneToolRun::activate()
{
if (mSelected!=mProfiles.end())
emit runRequest (*mSelected);
}
void CSVWidget::SceneToolRun::removeProfile (const std::string& profile)
{
std::set<std::string>::iterator iter = mProfiles.find (profile);
if (iter!=mProfiles.end())
{
if (iter==mSelected)
{
if (iter!=mProfiles.begin())
--mSelected;
else
++mSelected;
}
mProfiles.erase (iter);
if (mSelected==mProfiles.end())
updateIcon();
adjustToolTips();
}
}
void CSVWidget::SceneToolRun::addProfile (const std::string& profile)
{
std::set<std::string>::iterator iter = mProfiles.find (profile);
if (iter==mProfiles.end())
{
mProfiles.insert (profile);
if (mSelected==mProfiles.end())
{
mSelected = mProfiles.begin();
updateIcon();
}
adjustToolTips();
}
}
void CSVWidget::SceneToolRun::clicked (const QModelIndex& index)
{
if (index.column()==0)
{
// select profile
mSelected = mProfiles.begin();
std::advance (mSelected, index.row());
mPanel->hide();
adjustToolTips();
}
else if (index.column()==1)
{
// remove profile from list
std::set<std::string>::iterator iter = mProfiles.begin();
std::advance (iter, index.row());
removeProfile (*iter);
updatePanel();
}
}

@ -0,0 +1,64 @@
#ifndef CSV_WIDGET_SCENETOOLRUN_H
#define CSV_WIDGET_SCENETOOLRUN_H
#include <set>
#include <string>
#include "scenetool.hpp"
class QFrame;
class QTableWidget;
class QModelIndex;
namespace CSVWidget
{
class SceneToolRun : public SceneTool
{
Q_OBJECT
std::set<std::string> mProfiles;
std::set<std::string>::iterator mSelected;
QString mToolTip;
QString mIcon;
QString mIconDisabled;
QFrame *mPanel;
QTableWidget *mTable;
private:
void adjustToolTips();
void updateIcon();
void updatePanel();
public:
SceneToolRun (SceneToolbar *parent, const QString& toolTip, const QString& icon,
const QString& iconDisabled, const std::vector<std::string>& profiles);
virtual void showPanel (const QPoint& position);
virtual void activate();
/// \attention This function does not remove the profile from the profile selection
/// panel.
void removeProfile (const std::string& profile);
/// \attention This function doe not add the profile to the profile selection
/// panel. This only happens when the panel is re-opened.
///
/// \note Adding profiles that are already listed is a no-op.
void addProfile (const std::string& profile);
private slots:
void clicked (const QModelIndex& index);
signals:
void runRequest (const std::string& profile);
};
}
#endif

@ -0,0 +1,205 @@
#include "scenetooltoggle.hpp"
#include <stdexcept>
#include <QHBoxLayout>
#include <QFrame>
#include <QIcon>
#include <QPainter>
#include "scenetoolbar.hpp"
#include "pushbutton.hpp"
void CSVWidget::SceneToolToggle::adjustToolTip()
{
QString toolTip = mToolTip;
toolTip += "<p>Currently enabled: ";
bool first = true;
for (std::map<PushButton *, ButtonDesc>::const_iterator iter (mButtons.begin());
iter!=mButtons.end(); ++iter)
if (iter->first->isChecked())
{
if (!first)
toolTip += ", ";
else
first = false;
toolTip += iter->second.mName;
}
if (first)
toolTip += "none";
toolTip += "<p>(left click to alter selection)";
setToolTip (toolTip);
}
void CSVWidget::SceneToolToggle::adjustIcon()
{
unsigned int selection = getSelection();
if (!selection)
setIcon (QIcon (QString::fromUtf8 (mEmptyIcon.c_str())));
else
{
QPixmap pixmap (48, 48);
pixmap.fill (QColor (0, 0, 0, 0));
{
QPainter painter (&pixmap);
for (std::map<PushButton *, ButtonDesc>::const_iterator iter (mButtons.begin());
iter!=mButtons.end(); ++iter)
if (iter->first->isChecked())
{
painter.drawImage (getIconBox (iter->second.mIndex),
QImage (QString::fromUtf8 (iter->second.mSmallIcon.c_str())));
}
}
setIcon (pixmap);
}
}
QRect CSVWidget::SceneToolToggle::getIconBox (int index) const
{
// layout for a 3x3 grid
int xMax = 3;
int yMax = 3;
// icon size
int xBorder = 1;
int yBorder = 1;
int iconXSize = (mIconSize-xBorder*(xMax+1))/xMax;
int iconYSize = (mIconSize-yBorder*(yMax+1))/yMax;
int y = index / xMax;
int x = index % xMax;
int total = mButtons.size();
int actualYIcons = total/xMax;
if (total % xMax)
++actualYIcons;
if (actualYIcons!=yMax)
{
// space out icons vertically, if there aren't enough to populate all rows
int diff = yMax - actualYIcons;
yBorder += (diff*(yBorder+iconXSize)) / (actualYIcons+1);
}
if (y==actualYIcons-1)
{
// generating the last row of icons
int actualXIcons = total % xMax;
if (actualXIcons)
{
// space out icons horizontally, if there aren't enough to fill the last row
int diff = xMax - actualXIcons;
xBorder += (diff*(xBorder+iconXSize)) / (actualXIcons+1);
}
}
return QRect ((iconXSize+xBorder)*x+xBorder, (iconYSize+yBorder)*y+yBorder,
iconXSize, iconYSize);
}
CSVWidget::SceneToolToggle::SceneToolToggle (SceneToolbar *parent, const QString& toolTip,
const std::string& emptyIcon)
: SceneTool (parent), mEmptyIcon (emptyIcon), mButtonSize (parent->getButtonSize()),
mIconSize (parent->getIconSize()), mToolTip (toolTip), mFirst (0)
{
mPanel = new QFrame (this, Qt::Popup);
mLayout = new QHBoxLayout (mPanel);
mLayout->setContentsMargins (QMargins (0, 0, 0, 0));
mPanel->setLayout (mLayout);
}
void CSVWidget::SceneToolToggle::showPanel (const QPoint& position)
{
mPanel->move (position);
mPanel->show();
if (mFirst)
mFirst->setFocus (Qt::OtherFocusReason);
}
void CSVWidget::SceneToolToggle::addButton (const std::string& icon, unsigned int id,
const std::string& smallIcon, const QString& name, const QString& tooltip)
{
if (mButtons.size()>=9)
throw std::runtime_error ("Exceeded number of buttons in toggle type tool");
PushButton *button = new PushButton (QIcon (QPixmap (icon.c_str())),
PushButton::Type_Toggle, tooltip.isEmpty() ? name: tooltip, mPanel);
button->setSizePolicy (QSizePolicy (QSizePolicy::Fixed, QSizePolicy::Fixed));
button->setIconSize (QSize (mIconSize, mIconSize));
button->setFixedSize (mButtonSize, mButtonSize);
mLayout->addWidget (button);
ButtonDesc desc;
desc.mId = id;
desc.mSmallIcon = smallIcon;
desc.mName = name;
desc.mIndex = mButtons.size();
mButtons.insert (std::make_pair (button, desc));
connect (button, SIGNAL (clicked()), this, SLOT (selected()));
if (mButtons.size()==1)
mFirst = button;
}
unsigned int CSVWidget::SceneToolToggle::getSelection() const
{
unsigned int selection = 0;
for (std::map<PushButton *, ButtonDesc>::const_iterator iter (mButtons.begin());
iter!=mButtons.end(); ++iter)
if (iter->first->isChecked())
selection |= iter->second.mId;
return selection;
}
void CSVWidget::SceneToolToggle::setSelection (unsigned int selection)
{
for (std::map<PushButton *, ButtonDesc>::iterator iter (mButtons.begin());
iter!=mButtons.end(); ++iter)
iter->first->setChecked (selection & iter->second.mId);
adjustToolTip();
adjustIcon();
}
void CSVWidget::SceneToolToggle::selected()
{
std::map<PushButton *, ButtonDesc>::const_iterator iter =
mButtons.find (dynamic_cast<PushButton *> (sender()));
if (iter!=mButtons.end())
{
if (!iter->first->hasKeepOpen())
mPanel->hide();
adjustToolTip();
adjustIcon();
emit selectionChanged();
}
}

@ -0,0 +1,75 @@
#ifndef CSV_WIDGET_SCENETOOL_TOGGLE_H
#define CSV_WIDGET_SCENETOOL_TOGGLE_H
#include "scenetool.hpp"
#include <map>
class QHBoxLayout;
class QRect;
namespace CSVWidget
{
class SceneToolbar;
class PushButton;
///< \brief Multi-Toggle tool
class SceneToolToggle : public SceneTool
{
Q_OBJECT
struct ButtonDesc
{
unsigned int mId;
std::string mSmallIcon;
QString mName;
int mIndex;
};
std::string mEmptyIcon;
QWidget *mPanel;
QHBoxLayout *mLayout;
std::map<PushButton *, ButtonDesc> mButtons; // widget, id
int mButtonSize;
int mIconSize;
QString mToolTip;
PushButton *mFirst;
void adjustToolTip();
void adjustIcon();
QRect getIconBox (int index) const;
public:
SceneToolToggle (SceneToolbar *parent, const QString& toolTip,
const std::string& emptyIcon);
virtual void showPanel (const QPoint& position);
/// \attention After the last button has been added, setSelection must be called at
/// least once to finalise the layout.
///
/// \note The layout algorithm can not handle more than 9 buttons. To prevent this An
/// attempt to add more will result in an exception being thrown.
/// The small icons will be sized at (x-4)/3 (where x is the main icon size).
void addButton (const std::string& icon, unsigned int id,
const std::string& smallIcon, const QString& name, const QString& tooltip = "");
unsigned int getSelection() const;
/// \param or'ed button IDs. IDs that do not exist will be ignored.
void setSelection (unsigned int selection);
signals:
void selectionChanged();
private slots:
void selected();
};
}
#endif

@ -1,7 +1,16 @@
#include "creator.hpp" #include "creator.hpp"
CSVWorld::Creator:: ~Creator() {} #include <stdexcept>
CSVWorld::Creator::~Creator() {}
void CSVWorld::Creator::setScope (unsigned int scope)
{
if (scope!=CSMWorld::Scope_Content)
throw std::logic_error ("Invalid scope in creator");
}
CSVWorld::CreatorFactoryBase::~CreatorFactoryBase() {} CSVWorld::CreatorFactoryBase::~CreatorFactoryBase() {}

@ -1,9 +1,14 @@
#ifndef CSV_WORLD_CREATOR_H #ifndef CSV_WORLD_CREATOR_H
#define CSV_WORLD_CREATOR_H #define CSV_WORLD_CREATOR_H
#include <memory>
#include <QWidget> #include <QWidget>
#include "../../model/world/universalid.hpp" #include "../../model/world/universalid.hpp"
#include "../../model/world/scope.hpp"
class QUndoStack; class QUndoStack;
namespace CSMWorld namespace CSMWorld
@ -32,6 +37,9 @@ namespace CSVWorld
virtual void toggleWidgets(bool active = true) = 0; virtual void toggleWidgets(bool active = true) = 0;
/// Default implementation: Throw an exception if scope!=Scope_Content.
virtual void setScope (unsigned int scope);
signals: signals:
void done(); void done();
@ -68,7 +76,7 @@ namespace CSVWorld
/// \note The function always returns 0. /// \note The function always returns 0.
}; };
template<class CreatorT> template<class CreatorT, unsigned int scope = CSMWorld::Scope_Content>
class CreatorFactory : public CreatorFactoryBase class CreatorFactory : public CreatorFactoryBase
{ {
public: public:
@ -81,11 +89,15 @@ namespace CSVWorld
/// records should be provided. /// records should be provided.
}; };
template<class CreatorT> template<class CreatorT, unsigned int scope>
Creator *CreatorFactory<CreatorT>::makeCreator (CSMWorld::Data& data, QUndoStack& undoStack, Creator *CreatorFactory<CreatorT, scope>::makeCreator (CSMWorld::Data& data, QUndoStack& undoStack,
const CSMWorld::UniversalId& id) const const CSMWorld::UniversalId& id) const
{ {
return new CreatorT (data, undoStack, id); std::auto_ptr<CreatorT> creator (new CreatorT (data, undoStack, id));
creator->setScope (scope);
return creator.release();
} }
} }

@ -6,11 +6,11 @@
CSVWorld::DataDisplayDelegate::DataDisplayDelegate(const ValueList &values, CSVWorld::DataDisplayDelegate::DataDisplayDelegate(const ValueList &values,
const IconList &icons, const IconList &icons,
QUndoStack &undoStack, CSMDoc::Document& document,
const QString &pageName, const QString &pageName,
const QString &settingName, const QString &settingName,
QObject *parent) QObject *parent)
: EnumDelegate (values, undoStack, parent), mDisplayMode (Mode_TextOnly), : EnumDelegate (values, document, parent), mDisplayMode (Mode_TextOnly),
mIcons (icons), mIconSize (QSize(16, 16)), mIconLeftOffset(3), mIcons (icons), mIconSize (QSize(16, 16)), mIconLeftOffset(3),
mTextLeftOffset(8), mSettingKey (pageName + '/' + settingName) mTextLeftOffset(8), mSettingKey (pageName + '/' + settingName)
{ {
@ -38,7 +38,7 @@ void CSVWorld::DataDisplayDelegate::buildPixmaps ()
} }
} }
void CSVWorld::DataDisplayDelegate::setIconSize(const QSize size) void CSVWorld::DataDisplayDelegate::setIconSize(const QSize& size)
{ {
mIconSize = size; mIconSize = size;
buildPixmaps(); buildPixmaps();
@ -126,8 +126,6 @@ void CSVWorld::DataDisplayDelegate::updateDisplayMode (const QString &mode)
CSVWorld::DataDisplayDelegate::~DataDisplayDelegate() CSVWorld::DataDisplayDelegate::~DataDisplayDelegate()
{ {
mIcons.clear();
mPixmaps.clear();
} }
void CSVWorld::DataDisplayDelegateFactory::add (int enumValue, QString enumName, QString iconFilename) void CSVWorld::DataDisplayDelegateFactory::add (int enumValue, QString enumName, QString iconFilename)
@ -137,11 +135,10 @@ void CSVWorld::DataDisplayDelegateFactory::add (int enumValue, QString enumName,
} }
CSVWorld::CommandDelegate *CSVWorld::DataDisplayDelegateFactory::makeDelegate (QUndoStack& undoStack, CSVWorld::CommandDelegate *CSVWorld::DataDisplayDelegateFactory::makeDelegate (
QObject *parent) const CSMDoc::Document& document, QObject *parent) const
{ {
return new DataDisplayDelegate (mValues, mIcons, document, "", "", parent);
return new DataDisplayDelegate (mValues, mIcons, undoStack, "", "", parent);
} }

@ -40,7 +40,7 @@ namespace CSVWorld
public: public:
explicit DataDisplayDelegate (const ValueList & values, explicit DataDisplayDelegate (const ValueList & values,
const IconList & icons, const IconList & icons,
QUndoStack& undoStack, CSMDoc::Document& document,
const QString &pageName, const QString &pageName,
const QString &settingName, const QString &settingName,
QObject *parent); QObject *parent);
@ -50,7 +50,7 @@ namespace CSVWorld
virtual void paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; virtual void paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
/// pass a QSize defining height / width of icon. Default is QSize (16,16). /// pass a QSize defining height / width of icon. Default is QSize (16,16).
void setIconSize (const QSize icon); void setIconSize (const QSize& icon);
/// offset the horizontal position of the icon from the left edge of the cell. Default is 3 pixels. /// offset the horizontal position of the icon from the left edge of the cell. Default is 3 pixels.
void setIconLeftOffset (int offset); void setIconLeftOffset (int offset);
@ -82,7 +82,7 @@ namespace CSVWorld
public: public:
virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const; virtual CommandDelegate *makeDelegate (CSMDoc::Document& document, QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller. ///< The ownership of the returned CommandDelegate is transferred to the caller.
protected: protected:

@ -167,10 +167,10 @@ void CSVWorld::DialogueDelegateDispatcherProxy::tableMimeDataDropped(const std::
==============================DialogueDelegateDispatcher========================================== ==============================DialogueDelegateDispatcher==========================================
*/ */
CSVWorld::DialogueDelegateDispatcher::DialogueDelegateDispatcher(QObject* parent, CSMWorld::IdTable* table, QUndoStack& undoStack) : CSVWorld::DialogueDelegateDispatcher::DialogueDelegateDispatcher(QObject* parent, CSMWorld::IdTable* table, CSMDoc::Document& document) :
mParent(parent), mParent(parent),
mTable(table), mTable(table),
mUndoStack(undoStack), mDocument (document),
mNotEditableDelegate(table, parent) mNotEditableDelegate(table, parent)
{ {
} }
@ -182,7 +182,7 @@ CSVWorld::CommandDelegate* CSVWorld::DialogueDelegateDispatcher::makeDelegate(CS
if (delegateIt == mDelegates.end()) if (delegateIt == mDelegates.end())
{ {
delegate = CommandDelegateFactoryCollection::get().makeDelegate ( delegate = CommandDelegateFactoryCollection::get().makeDelegate (
display, mUndoStack, mParent); display, mDocument, mParent);
mDelegates.insert(std::make_pair(display, delegate)); mDelegates.insert(std::make_pair(display, delegate));
} else } else
{ {
@ -266,7 +266,6 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase::
editor = delegateIt->second->createEditor(qobject_cast<QWidget*>(mParent), QStyleOptionViewItem(), index, display); editor = delegateIt->second->createEditor(qobject_cast<QWidget*>(mParent), QStyleOptionViewItem(), index, display);
DialogueDelegateDispatcherProxy* proxy = new DialogueDelegateDispatcherProxy(editor, display); DialogueDelegateDispatcherProxy* proxy = new DialogueDelegateDispatcherProxy(editor, display);
bool skip = false;
if (qobject_cast<DropLineEdit*>(editor)) if (qobject_cast<DropLineEdit*>(editor))
{ {
connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited())); connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited()));
@ -274,27 +273,22 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase::
proxy, SLOT(tableMimeDataDropped(const std::vector<CSMWorld::UniversalId>&, const CSMDoc::Document*))); proxy, SLOT(tableMimeDataDropped(const std::vector<CSMWorld::UniversalId>&, const CSMDoc::Document*)));
connect(proxy, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)), connect(proxy, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)),
this, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*))); this, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)));
skip = true;
} }
if(!skip && qobject_cast<QCheckBox*>(editor)) else if (qobject_cast<QCheckBox*>(editor))
{ {
connect(editor, SIGNAL(stateChanged(int)), proxy, SLOT(editorDataCommited())); connect(editor, SIGNAL(stateChanged(int)), proxy, SLOT(editorDataCommited()));
skip = true;
} }
if(!skip && qobject_cast<QPlainTextEdit*>(editor)) else if (qobject_cast<QPlainTextEdit*>(editor))
{ {
connect(editor, SIGNAL(textChanged()), proxy, SLOT(editorDataCommited())); connect(editor, SIGNAL(textChanged()), proxy, SLOT(editorDataCommited()));
skip = true;
} }
if(!skip && qobject_cast<QComboBox*>(editor)) else if (qobject_cast<QComboBox*>(editor))
{ {
connect(editor, SIGNAL(currentIndexChanged (int)), proxy, SLOT(editorDataCommited())); connect(editor, SIGNAL(currentIndexChanged (int)), proxy, SLOT(editorDataCommited()));
skip = true;
} }
if(!skip && qobject_cast<QAbstractSpinBox*>(editor)) else if (qobject_cast<QAbstractSpinBox*>(editor))
{ {
connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited())); connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited()));
skip = true;
} }
connect(proxy, SIGNAL(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display)), this, SLOT(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display))); connect(proxy, SIGNAL(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display)), this, SLOT(editorDataCommited(QWidget*, const QModelIndex&, CSMWorld::ColumnBase::Display)));
@ -315,12 +309,12 @@ CSVWorld::DialogueDelegateDispatcher::~DialogueDelegateDispatcher()
=============================================================EditWidget===================================================== =============================================================EditWidget=====================================================
*/ */
CSVWorld::EditWidget::EditWidget(QWidget *parent, int row, CSMWorld::IdTable* table, QUndoStack& undoStack, bool createAndDelete) : CSVWorld::EditWidget::EditWidget(QWidget *parent, int row, CSMWorld::IdTable* table, CSMDoc::Document& document, bool createAndDelete) :
mDispatcher(this, table, undoStack), mDispatcher(this, table, document),
QScrollArea(parent), QScrollArea(parent),
mWidgetMapper(NULL), mWidgetMapper(NULL),
mMainWidget(NULL), mMainWidget(NULL),
mUndoStack(undoStack), mDocument (document),
mTable(table) mTable(table)
{ {
remake (row); remake (row);
@ -478,7 +472,7 @@ CSVWorld::DialogueSubView::DialogueSubView (const CSMWorld::UniversalId& id, CSM
mMainLayout = new QVBoxLayout(mainWidget); mMainLayout = new QVBoxLayout(mainWidget);
mEditWidget = new EditWidget(mainWidget, mRow, mTable, mUndoStack, false); mEditWidget = new EditWidget(mainWidget, mRow, mTable, document, false);
connect(mEditWidget, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)), connect(mEditWidget, SIGNAL(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)),
this, SLOT(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*))); this, SLOT(tableMimeDataDropped(QWidget*, const QModelIndex&, const CSMWorld::UniversalId&, const CSMDoc::Document*)));

@ -101,14 +101,14 @@ namespace CSVWorld
CSMWorld::IdTable* mTable; CSMWorld::IdTable* mTable;
QUndoStack& mUndoStack; CSMDoc::Document& mDocument;
NotEditableSubDelegate mNotEditableDelegate; NotEditableSubDelegate mNotEditableDelegate;
std::vector<DialogueDelegateDispatcherProxy*> mProxys; //once we move to the C++11 we should use unique_ptr std::vector<DialogueDelegateDispatcherProxy*> mProxys; //once we move to the C++11 we should use unique_ptr
public: public:
DialogueDelegateDispatcher(QObject* parent, CSMWorld::IdTable* table, QUndoStack& undoStack); DialogueDelegateDispatcher(QObject* parent, CSMWorld::IdTable* table, CSMDoc::Document& document);
~DialogueDelegateDispatcher(); ~DialogueDelegateDispatcher();
@ -145,11 +145,11 @@ namespace CSVWorld
DialogueDelegateDispatcher mDispatcher; DialogueDelegateDispatcher mDispatcher;
QWidget* mMainWidget; QWidget* mMainWidget;
CSMWorld::IdTable* mTable; CSMWorld::IdTable* mTable;
QUndoStack& mUndoStack; CSMDoc::Document& mDocument;
public: public:
EditWidget (QWidget *parent, int row, CSMWorld::IdTable* table, QUndoStack& undoStack, bool createAndDelete = false); EditWidget (QWidget *parent, int row, CSMWorld::IdTable* table, CSMDoc::Document& document, bool createAndDelete = false);
void remake(int row); void remake(int row);

@ -35,8 +35,8 @@ void CSVWorld::EnumDelegate::addCommands (QAbstractItemModel *model,
CSVWorld::EnumDelegate::EnumDelegate (const std::vector<std::pair<int, QString> >& values, CSVWorld::EnumDelegate::EnumDelegate (const std::vector<std::pair<int, QString> >& values,
QUndoStack& undoStack, QObject *parent) CSMDoc::Document& document, QObject *parent)
: CommandDelegate (undoStack, parent), mValues (values) : CommandDelegate (document, parent), mValues (values)
{ {
} }
@ -140,10 +140,10 @@ CSVWorld::EnumDelegateFactory::EnumDelegateFactory (const std::vector<std::strin
add (i, names[i].c_str()); add (i, names[i].c_str());
} }
CSVWorld::CommandDelegate *CSVWorld::EnumDelegateFactory::makeDelegate (QUndoStack& undoStack, CSVWorld::CommandDelegate *CSVWorld::EnumDelegateFactory::makeDelegate (
QObject *parent) const CSMDoc::Document& document, QObject *parent) const
{ {
return new EnumDelegate (mValues, undoStack, parent); return new EnumDelegate (mValues, document, parent);
} }
void CSVWorld::EnumDelegateFactory::add (int value, const QString& name) void CSVWorld::EnumDelegateFactory::add (int value, const QString& name)

@ -30,7 +30,7 @@ namespace CSVWorld
public: public:
EnumDelegate (const std::vector<std::pair<int, QString> >& values, EnumDelegate (const std::vector<std::pair<int, QString> >& values,
QUndoStack& undoStack, QObject *parent); CSMDoc::Document& document, QObject *parent);
virtual QWidget *createEditor(QWidget *parent, virtual QWidget *createEditor(QWidget *parent,
const QStyleOptionViewItem& option, const QStyleOptionViewItem& option,
@ -64,7 +64,7 @@ namespace CSVWorld
EnumDelegateFactory (const std::vector<std::string>& names, bool allowNone = false); EnumDelegateFactory (const std::vector<std::string>& names, bool allowNone = false);
/// \param allowNone Use value of -1 for "none selected" (empty string) /// \param allowNone Use value of -1 for "none selected" (empty string)
virtual CommandDelegate *makeDelegate (QUndoStack& undoStack, QObject *parent) const; virtual CommandDelegate *makeDelegate (CSMDoc::Document& document, QObject *parent) const;
///< The ownership of the returned CommandDelegate is transferred to the caller. ///< The ownership of the returned CommandDelegate is transferred to the caller.
void add (int value, const QString& name); void add (int value, const QString& name);

@ -7,6 +7,10 @@
#include <QPushButton> #include <QPushButton>
#include <QLineEdit> #include <QLineEdit>
#include <QUndoStack> #include <QUndoStack>
#include <QLabel>
#include <QComboBox>
#include <components/misc/stringops.hpp>
#include "../../model/world/commands.hpp" #include "../../model/world/commands.hpp"
#include "../../model/world/data.hpp" #include "../../model/world/data.hpp"
@ -46,32 +50,87 @@ std::string CSVWorld::GenericCreator::getId() const
void CSVWorld::GenericCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const {} void CSVWorld::GenericCreator::configureCreateCommand (CSMWorld::CreateCommand& command) const {}
void CSVWorld::GenericCreator::pushCommand (std::auto_ptr<CSMWorld::CreateCommand> command,
const std::string& id)
{
mUndoStack.push (command.release());
}
CSMWorld::Data& CSVWorld::GenericCreator::getData() const CSMWorld::Data& CSVWorld::GenericCreator::getData() const
{ {
return mData; return mData;
} }
QUndoStack& CSVWorld::GenericCreator::getUndoStack()
{
return mUndoStack;
}
const CSMWorld::UniversalId& CSVWorld::GenericCreator::getCollectionId() const const CSMWorld::UniversalId& CSVWorld::GenericCreator::getCollectionId() const
{ {
return mListId; return mListId;
} }
CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack, std::string CSVWorld::GenericCreator::getNamespace() const
const CSMWorld::UniversalId& id, bool relaxedIdRules): {
CSMWorld::Scope scope = CSMWorld::Scope_Content;
if (mScope)
{
scope = static_cast<CSMWorld::Scope> (mScope->itemData (mScope->currentIndex()).toInt());
}
else
{
if (mScopes & CSMWorld::Scope_Project)
scope = CSMWorld::Scope_Project;
else if (mScopes & CSMWorld::Scope_Session)
scope = CSMWorld::Scope_Session;
}
switch (scope)
{
case CSMWorld::Scope_Content: return "";
case CSMWorld::Scope_Project: return "project::";
case CSMWorld::Scope_Session: return "session::";
}
return "";
}
void CSVWorld::GenericCreator::updateNamespace()
{
std::string namespace_ = getNamespace();
mValidator->setNamespace (namespace_);
int index = mId->text().indexOf ("::");
if (index==-1)
{
// no namespace in old text
mId->setText (QString::fromUtf8 (namespace_.c_str()) + mId->text());
}
else
{
std::string oldNamespace =
Misc::StringUtils::lowerCase (mId->text().left (index).toUtf8().constData());
mData (data), if (oldNamespace=="project" || oldNamespace=="session")
mUndoStack (undoStack), mId->setText (QString::fromUtf8 (namespace_.c_str()) + mId->text().mid (index+2));
mListId (id), }
mLocked (false), }
mCloneMode(false),
mClonedType(CSMWorld::UniversalId::Type_None)
CSVWorld::GenericCreator::GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack,
const CSMWorld::UniversalId& id, bool relaxedIdRules)
: mData (data), mUndoStack (undoStack), mListId (id), mLocked (false), mCloneMode (false),
mClonedType (CSMWorld::UniversalId::Type_None), mScopes (CSMWorld::Scope_Content), mScope (0),
mScopeLabel (0)
{ {
mLayout = new QHBoxLayout; mLayout = new QHBoxLayout;
mLayout->setContentsMargins (0, 0, 0, 0); mLayout->setContentsMargins (0, 0, 0, 0);
mId = new QLineEdit; mId = new QLineEdit;
mId->setValidator (new IdValidator (relaxedIdRules, this)); mId->setValidator (mValidator = new IdValidator (relaxedIdRules, this));
mLayout->addWidget (mId, 1); mLayout->addWidget (mId, 1);
mCreate = new QPushButton ("Create"); mCreate = new QPushButton ("Create");
@ -99,22 +158,17 @@ void CSVWorld::GenericCreator::reset()
mCloneMode = false; mCloneMode = false;
mId->setText (""); mId->setText ("");
update(); update();
updateNamespace();
} }
std::string CSVWorld::GenericCreator::getErrors() const std::string CSVWorld::GenericCreator::getErrors() const
{ {
std::string errors; std::string errors;
std::string id = getId(); if (!mId->hasAcceptableInput())
errors = mValidator->getError();
if (id.empty()) else if (mData.hasId (getId()))
{
errors = "Missing ID";
}
else if (mData.hasId (id))
{
errors = "ID is already in use"; errors = "ID is already in use";
}
return errors; return errors;
} }
@ -128,29 +182,27 @@ void CSVWorld::GenericCreator::create()
{ {
if (!mLocked) if (!mLocked)
{ {
std::string id = getId();
std::auto_ptr<CSMWorld::CreateCommand> command;
if (mCloneMode) if (mCloneMode)
{ {
std::string id = getId(); command.reset (new CSMWorld::CloneCommand (
std::auto_ptr<CSMWorld::CloneCommand> command (new CSMWorld::CloneCommand (
dynamic_cast<CSMWorld::IdTable&> (*mData.getTableModel(mListId)), mClonedId, id, mClonedType)); dynamic_cast<CSMWorld::IdTable&> (*mData.getTableModel(mListId)), mClonedId, id, mClonedType));
}
else
{
command.reset (new CSMWorld::CreateCommand (
dynamic_cast<CSMWorld::IdTable&> (*mData.getTableModel (mListId)), id));
mUndoStack.push(command.release()); }
emit done();
emit requestFocus(id);
} else {
std::string id = getId();
std::auto_ptr<CSMWorld::CreateCommand> command (new CSMWorld::CreateCommand (
dynamic_cast<CSMWorld::IdTable&> (*mData.getTableModel (mListId)), id));
configureCreateCommand (*command);
mUndoStack.push (command.release()); configureCreateCommand (*command);
pushCommand (command, id);
emit done(); emit done();
emit requestFocus (id); emit requestFocus(id);
}
} }
} }
@ -165,3 +217,49 @@ void CSVWorld::GenericCreator::cloneMode(const std::string& originId,
void CSVWorld::GenericCreator::toggleWidgets(bool active) void CSVWorld::GenericCreator::toggleWidgets(bool active)
{ {
} }
void CSVWorld::GenericCreator::setScope (unsigned int scope)
{
mScopes = scope;
int count = (mScopes & CSMWorld::Scope_Content) + (mScopes & CSMWorld::Scope_Project) +
(mScopes & CSMWorld::Scope_Session);
// scope selector widget
if (count>1)
{
mScope = new QComboBox (this);
insertAtBeginning (mScope, false);
if (mScopes & CSMWorld::Scope_Content)
mScope->addItem ("Content", static_cast<int> (CSMWorld::Scope_Content));
if (mScopes & CSMWorld::Scope_Project)
mScope->addItem ("Project", static_cast<int> (CSMWorld::Scope_Project));
if (mScopes & CSMWorld::Scope_Session)
mScope->addItem ("Session", static_cast<int> (CSMWorld::Scope_Session));
connect (mScope, SIGNAL (currentIndexChanged (int)), this, SLOT (scopeChanged (int)));
mScopeLabel = new QLabel ("Scope", this);
insertAtBeginning (mScopeLabel, false);
mScope->setCurrentIndex (0);
}
else
{
delete mScope;
mScope = 0;
delete mScopeLabel;
mScopeLabel = 0;
}
updateNamespace();
}
void CSVWorld::GenericCreator::scopeChanged (int index)
{
update();
updateNamespace();
}

@ -1,14 +1,18 @@
#ifndef CSV_WORLD_GENERICCREATOR_H #ifndef CSV_WORLD_GENERICCREATOR_H
#define CSV_WORLD_GENERICCREATOR_H #define CSV_WORLD_GENERICCREATOR_H
#include <memory>
#include "../../model/world/universalid.hpp"
#include "creator.hpp"
class QString; class QString;
class QPushButton; class QPushButton;
class QLineEdit; class QLineEdit;
class QHBoxLayout; class QHBoxLayout;
class QComboBox;
#include "creator.hpp" class QLabel;
#include "../../model/world/universalid.hpp"
namespace CSMWorld namespace CSMWorld
{ {
@ -17,6 +21,8 @@ namespace CSMWorld
namespace CSVWorld namespace CSVWorld
{ {
class IdValidator;
class GenericCreator : public Creator class GenericCreator : public Creator
{ {
Q_OBJECT Q_OBJECT
@ -31,6 +37,10 @@ namespace CSVWorld
bool mLocked; bool mLocked;
std::string mClonedId; std::string mClonedId;
CSMWorld::UniversalId::Type mClonedType; CSMWorld::UniversalId::Type mClonedType;
unsigned int mScopes;
QComboBox *mScope;
QLabel *mScopeLabel;
IdValidator *mValidator;
protected: protected:
bool mCloneMode; bool mCloneMode;
@ -48,12 +58,26 @@ namespace CSVWorld
virtual std::string getId() const; virtual std::string getId() const;
/// Allow subclasses to add additional data to \a command.
virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const; virtual void configureCreateCommand (CSMWorld::CreateCommand& command) const;
/// Allow subclasses to wrap the create command together with additional commands
/// into a macro.
virtual void pushCommand (std::auto_ptr<CSMWorld::CreateCommand> command,
const std::string& id);
CSMWorld::Data& getData() const; CSMWorld::Data& getData() const;
QUndoStack& getUndoStack();
const CSMWorld::UniversalId& getCollectionId() const; const CSMWorld::UniversalId& getCollectionId() const;
std::string getNamespace() const;
private:
void updateNamespace();
public: public:
GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack, GenericCreator (CSMWorld::Data& data, QUndoStack& undoStack,
@ -65,18 +89,22 @@ namespace CSVWorld
virtual void toggleWidgets (bool active = true); virtual void toggleWidgets (bool active = true);
virtual void cloneMode(const std::string& originId, virtual void cloneMode(const std::string& originId,
const CSMWorld::UniversalId::Type type); const CSMWorld::UniversalId::Type type);
virtual std::string getErrors() const; virtual std::string getErrors() const;
///< Return formatted error descriptions for the current state of the creator. if an empty ///< Return formatted error descriptions for the current state of the creator. if an empty
/// string is returned, there is no error. /// string is returned, there is no error.
virtual void setScope (unsigned int scope);
private slots: private slots:
void textChanged (const QString& text); void textChanged (const QString& text);
void create(); void create();
void scopeChanged (int index);
}; };
} }

@ -3,8 +3,8 @@
#include "../../model/world/universalid.hpp" #include "../../model/world/universalid.hpp"
CSVWorld::IdTypeDelegate::IdTypeDelegate CSVWorld::IdTypeDelegate::IdTypeDelegate
(const ValueList &values, const IconList &icons, QUndoStack& undoStack, QObject *parent) (const ValueList &values, const IconList &icons, CSMDoc::Document& document, QObject *parent)
: DataDisplayDelegate (values, icons, undoStack, : DataDisplayDelegate (values, icons, document,
"Display Format", "Referenceable ID Type Display", "Display Format", "Referenceable ID Type Display",
parent) parent)
{} {}
@ -20,8 +20,8 @@ CSVWorld::IdTypeDelegateFactory::IdTypeDelegateFactory()
} }
} }
CSVWorld::CommandDelegate *CSVWorld::IdTypeDelegateFactory::makeDelegate (QUndoStack& undoStack, CSVWorld::CommandDelegate *CSVWorld::IdTypeDelegateFactory::makeDelegate (
QObject *parent) const CSMDoc::Document& document, QObject *parent) const
{ {
return new IdTypeDelegate (mValues, mIcons, undoStack, parent); return new IdTypeDelegate (mValues, mIcons, document, parent);
} }

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

Loading…
Cancel
Save