mirror of
				https://github.com/OpenMW/openmw.git
				synced 2025-10-29 03:26:38 +00:00 
			
		
		
		
	Merge branch 'master' into cc9cii
Conflicts: apps/opencs/view/doc/view.hpp
This commit is contained in:
		
						commit
						3b27e643b8
					
				
					 122 changed files with 1581 additions and 500 deletions
				
			
		|  | @ -38,7 +38,7 @@ before_script: | ||||||
|  - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_script.osx.sh; fi |  - if [ "${TRAVIS_OS_NAME}" = "osx" ]; then ./CI/before_script.osx.sh; fi | ||||||
| script: | script: | ||||||
|  - cd ./build |  - cd ./build | ||||||
|  - if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j4; fi |  - if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then ${ANALYZE}make -j2; fi | ||||||
|  - if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi |  - if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi | ||||||
| after_script: | after_script: | ||||||
|  - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi |  - if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi | ||||||
|  |  | ||||||
|  | @ -98,25 +98,29 @@ endif() | ||||||
| cmake_minimum_required(VERSION 2.6) | cmake_minimum_required(VERSION 2.6) | ||||||
| 
 | 
 | ||||||
| # Sound setup | # Sound setup | ||||||
| set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE AVRESAMPLE) |  | ||||||
| unset(FFMPEG_LIBRARIES CACHE) | unset(FFMPEG_LIBRARIES CACHE) | ||||||
| find_package(FFmpeg) | 
 | ||||||
|  | find_package(FFmpeg REQUIRED) | ||||||
|  | 
 | ||||||
|  | set (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARY}) | ||||||
|  | 
 | ||||||
| if ( NOT AVCODEC_FOUND OR NOT AVFORMAT_FOUND OR NOT AVUTIL_FOUND OR NOT SWSCALE_FOUND ) | if ( NOT AVCODEC_FOUND OR NOT AVFORMAT_FOUND OR NOT AVUTIL_FOUND OR NOT SWSCALE_FOUND ) | ||||||
|     message(FATAL_ERROR "FFmpeg component required, but not found!") |     message(FATAL_ERROR "FFmpeg component required, but not found!") | ||||||
| endif() | endif() | ||||||
| set(SOUND_INPUT_INCLUDES ${FFMPEG_INCLUDE_DIRS}) | set(SOUND_INPUT_INCLUDES ${FFMPEG_INCLUDE_DIRS}) | ||||||
| set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARIES}) |  | ||||||
| if( SWRESAMPLE_FOUND ) | if( SWRESAMPLE_FOUND ) | ||||||
|     add_definitions(-DHAVE_LIBSWRESAMPLE) |     add_definitions(-DHAVE_LIBSWRESAMPLE) | ||||||
|     set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${SWRESAMPLE_LIBRARIES}) |     set (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${SWRESAMPLE_LIBRARIES}) | ||||||
| else() | else() | ||||||
|     if( AVRESAMPLE_FOUND ) |     if( AVRESAMPLE_FOUND ) | ||||||
|         set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${AVRESAMPLE_LIBRARIES}) |         set (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${AVRESAMPLE_LIBRARIES}) | ||||||
|     else() |     else() | ||||||
|         message(FATAL_ERROR "Install either libswresample (FFmpeg) or libavresample (Libav).") |         message(FATAL_ERROR "Install either libswresample (FFmpeg) or libavresample (Libav).") | ||||||
|     endif() |     endif() | ||||||
| endif() | endif() | ||||||
| 
 | 
 | ||||||
|  | set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES}) | ||||||
|  | 
 | ||||||
| # 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) | ||||||
| if(USE_SYSTEM_TINYXML) | if(USE_SYSTEM_TINYXML) | ||||||
|  | @ -151,6 +155,19 @@ endif() | ||||||
| 
 | 
 | ||||||
| # Dependencies | # Dependencies | ||||||
| 
 | 
 | ||||||
|  | set(DESIRED_QT_VERSION 4 CACHE STRING "The QT version OpenMW should use (4 or 5)") | ||||||
|  | message(STATUS "Using Qt${DESIRED_QT_VERSION}") | ||||||
|  | 
 | ||||||
|  | if (DESIRED_QT_VERSION MATCHES 4) | ||||||
|  |     find_package(Qt4 REQUIRED COMPONENTS QtCore QtGui QtNetwork) | ||||||
|  | else() | ||||||
|  |     find_package(Qt5Widgets REQUIRED) | ||||||
|  |     find_package(Qt5Core REQUIRED) | ||||||
|  |     find_package(Qt5Network REQUIRED) | ||||||
|  |     # Instruct CMake to run moc automatically when needed. | ||||||
|  |     #set(CMAKE_AUTOMOC ON) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
| # Fix for not visible pthreads functions for linker with glibc 2.15 | # Fix for not visible pthreads functions for linker with glibc 2.15 | ||||||
| if (UNIX AND NOT APPLE) | if (UNIX AND NOT APPLE) | ||||||
|     find_package (Threads) |     find_package (Threads) | ||||||
|  | @ -171,7 +188,7 @@ if (HAVE_UNORDERED_MAP) | ||||||
| endif () | endif () | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| set(BOOST_COMPONENTS system filesystem program_options) | set(BOOST_COMPONENTS system filesystem program_options thread wave) | ||||||
| if(WIN32) | if(WIN32) | ||||||
|     set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale) |     set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale) | ||||||
| endif(WIN32) | endif(WIN32) | ||||||
|  |  | ||||||
|  | @ -9,7 +9,8 @@ add_executable(bsatool | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| target_link_libraries(bsatool | target_link_libraries(bsatool | ||||||
|   ${Boost_LIBRARIES} |   ${Boost_PROGRAM_OPTIONS_LIBRARY} | ||||||
|  |   ${Boost_FILESYSTEM_LIBRARY} | ||||||
|   components |   components | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -13,7 +13,7 @@ add_executable(esmtool | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| target_link_libraries(esmtool | target_link_libraries(esmtool | ||||||
|   ${Boost_LIBRARIES} |   ${Boost_PROGRAM_OPTIONS_LIBRARY} | ||||||
|   components |   components | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -119,7 +119,7 @@ std::string clothingTypeLabel(int idx) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::string armorTypeLabel(int idx) | std::string armorTypeLabel(int idx) | ||||||
| {     | { | ||||||
|     if (idx >= 0 && idx <= 10) |     if (idx >= 0 && idx <= 10) | ||||||
|     { |     { | ||||||
|         static const char *armorTypeLabels[] = { |         static const char *armorTypeLabels[] = { | ||||||
|  | @ -645,7 +645,7 @@ std::string ruleFunction(int idx) | ||||||
|     else |     else | ||||||
|         return "Invalid"; |         return "Invalid"; | ||||||
| } | } | ||||||
|     | 
 | ||||||
| // The "unused flag bits" should probably be defined alongside the
 | // The "unused flag bits" should probably be defined alongside the
 | ||||||
| // defined bits in the ESM component.  The names of the flag bits are
 | // defined bits in the ESM component.  The names of the flag bits are
 | ||||||
| // very inconsistent.
 | // very inconsistent.
 | ||||||
|  | @ -653,7 +653,7 @@ std::string ruleFunction(int idx) | ||||||
| std::string bodyPartFlags(int flags) | std::string bodyPartFlags(int flags) | ||||||
| { | { | ||||||
|     std::string properties = ""; |     std::string properties = ""; | ||||||
|     if (flags == 0) properties += "[None] ";     |     if (flags == 0) properties += "[None] "; | ||||||
|     if (flags & ESM::BodyPart::BPF_Female) properties += "Female "; |     if (flags & ESM::BodyPart::BPF_Female) properties += "Female "; | ||||||
|     if (flags & ESM::BodyPart::BPF_NotPlayable) properties += "NotPlayable "; |     if (flags & ESM::BodyPart::BPF_NotPlayable) properties += "NotPlayable "; | ||||||
|     int unused = (0xFFFFFFFF ^ |     int unused = (0xFFFFFFFF ^ | ||||||
|  | @ -667,7 +667,7 @@ std::string bodyPartFlags(int flags) | ||||||
| std::string cellFlags(int flags) | std::string cellFlags(int flags) | ||||||
| { | { | ||||||
|     std::string properties = ""; |     std::string properties = ""; | ||||||
|     if (flags == 0) properties += "[None] ";     |     if (flags == 0) properties += "[None] "; | ||||||
|     if (flags & ESM::Cell::HasWater) properties += "HasWater "; |     if (flags & ESM::Cell::HasWater) properties += "HasWater "; | ||||||
|     if (flags & ESM::Cell::Interior) properties += "Interior "; |     if (flags & ESM::Cell::Interior) properties += "Interior "; | ||||||
|     if (flags & ESM::Cell::NoSleep) properties += "NoSleep "; |     if (flags & ESM::Cell::NoSleep) properties += "NoSleep "; | ||||||
|  | @ -830,12 +830,12 @@ std::string npcFlags(int flags) | ||||||
|     std::string properties = ""; |     std::string properties = ""; | ||||||
|     if (flags == 0) properties += "[None] "; |     if (flags == 0) properties += "[None] "; | ||||||
|     // Mythicmods and the ESM component differ.  Mythicmods says
 |     // Mythicmods and the ESM component differ.  Mythicmods says
 | ||||||
|     // 0x8=None and 0x10=AutoCalc, while our code defines 0x8 as
 |     // 0x8=None and 0x10=AutoCalc, while our code previously defined
 | ||||||
|     // AutoCalc.  The former seems to be correct.  All Bethesda
 |     // 0x8 as AutoCalc.  The former seems to be correct.  All Bethesda
 | ||||||
|     // records have bit 0x8 set.  A suspiciously large portion of
 |     // records have bit 0x8 set.  Previously, suspiciously large portion
 | ||||||
|     // females have autocalc turned off.
 |     // of females had autocalc turned off.
 | ||||||
|     if (flags & ESM::NPC::Autocalc) properties += "Unknown "; |     if (flags & 0x00000008) properties += "Unknown "; | ||||||
|     if (flags & 0x00000010) properties += "Autocalc "; |     if (flags & ESM::NPC::Autocalc) properties += "Autocalc "; | ||||||
|     if (flags & ESM::NPC::Female) properties += "Female "; |     if (flags & ESM::NPC::Female) properties += "Female "; | ||||||
|     if (flags & ESM::NPC::Respawn) properties += "Respawn "; |     if (flags & ESM::NPC::Respawn) properties += "Respawn "; | ||||||
|     if (flags & ESM::NPC::Essential) properties += "Essential "; |     if (flags & ESM::NPC::Essential) properties += "Essential "; | ||||||
|  | @ -847,8 +847,8 @@ std::string npcFlags(int flags) | ||||||
|     // however the only unknown bit occurs on ALL records, and
 |     // however the only unknown bit occurs on ALL records, and
 | ||||||
|     // relatively few NPCs have this bit set.
 |     // relatively few NPCs have this bit set.
 | ||||||
|     int unused = (0xFFFFFFFF ^ |     int unused = (0xFFFFFFFF ^ | ||||||
|                   (ESM::NPC::Autocalc| |                   (0x00000008| | ||||||
|                    0x00000010| |                    ESM::NPC::Autocalc| | ||||||
|                    ESM::NPC::Female| |                    ESM::NPC::Female| | ||||||
|                    ESM::NPC::Respawn| |                    ESM::NPC::Respawn| | ||||||
|                    ESM::NPC::Essential| |                    ESM::NPC::Essential| | ||||||
|  |  | ||||||
|  | @ -33,7 +33,8 @@ add_executable(openmw-essimporter | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| target_link_libraries(openmw-essimporter | target_link_libraries(openmw-essimporter | ||||||
|     ${Boost_LIBRARIES} |     ${Boost_PROGRAM_OPTIONS_LIBRARY} | ||||||
|  |     ${Boost_FILESYSTEM_LIBRARY} | ||||||
|     components |     components | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -57,7 +57,6 @@ set(LAUNCHER_UI | ||||||
| 
 | 
 | ||||||
| source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER}) | source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER}) | ||||||
| 
 | 
 | ||||||
| find_package(Qt4 REQUIRED) |  | ||||||
| set(QT_USE_QTGUI 1) | set(QT_USE_QTGUI 1) | ||||||
| 
 | 
 | ||||||
| # Set some platform specific settings | # Set some platform specific settings | ||||||
|  | @ -66,12 +65,17 @@ if(WIN32) | ||||||
|     set(QT_USE_QTMAIN TRUE) |     set(QT_USE_QTMAIN TRUE) | ||||||
| endif(WIN32) | endif(WIN32) | ||||||
| 
 | 
 | ||||||
| QT4_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/launcher/launcher.qrc) | if (DESIRED_QT_VERSION MATCHES 4) | ||||||
| QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC}) |     include(${QT_USE_FILE}) | ||||||
| QT4_WRAP_UI(UI_HDRS ${LAUNCHER_UI}) |     QT4_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/launcher/launcher.qrc) | ||||||
|  |     QT4_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC}) | ||||||
|  |     QT4_WRAP_UI(UI_HDRS ${LAUNCHER_UI}) | ||||||
|  | else() | ||||||
|  |     QT5_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/launcher/launcher.qrc) | ||||||
|  |     QT5_WRAP_CPP(MOC_SRCS ${LAUNCHER_HEADER_MOC}) | ||||||
|  |     QT5_WRAP_UI(UI_HDRS ${LAUNCHER_UI}) | ||||||
|  | endif() | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| include(${QT_USE_FILE}) |  | ||||||
| include_directories(${CMAKE_CURRENT_BINARY_DIR}) | include_directories(${CMAKE_CURRENT_BINARY_DIR}) | ||||||
| if(NOT WIN32) | if(NOT WIN32) | ||||||
|     include_directories(${LIBUNSHIELD_INCLUDE_DIR}) |     include_directories(${LIBUNSHIELD_INCLUDE_DIR}) | ||||||
|  | @ -88,17 +92,27 @@ add_executable(openmw-launcher | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| target_link_libraries(openmw-launcher | target_link_libraries(openmw-launcher | ||||||
|     ${Boost_LIBRARIES} |  | ||||||
|     ${OGRE_LIBRARIES} |     ${OGRE_LIBRARIES} | ||||||
|     ${OGRE_STATIC_PLUGINS} |     ${OGRE_STATIC_PLUGINS} | ||||||
|     ${SDL2_LIBRARY_ONLY} |     ${SDL2_LIBRARY_ONLY} | ||||||
|     ${QT_LIBRARIES} |  | ||||||
|     components |     components | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | if (DESIRED_QT_VERSION MATCHES 4) | ||||||
|  |     target_link_libraries(openmw-launcher ${QT_QTGUI_LIBRARY} ${QT_QTCORE_LIBRARY}) | ||||||
|  |     if(WIN32) | ||||||
|  |         target_link_libraries(openmw-launcher ${QT_QTMAIN_LIBRARY}) | ||||||
|  |     endif(WIN32) | ||||||
|  | else() | ||||||
|  |     qt5_use_modules(openmw-launcher Widgets Core) | ||||||
|  |     if (WIN32) | ||||||
|  |         target_link_libraries(Qt5::WinMain) | ||||||
|  |     endif() | ||||||
|  | endif() | ||||||
| 
 | 
 | ||||||
| if (BUILD_WITH_CODE_COVERAGE) | if (BUILD_WITH_CODE_COVERAGE) | ||||||
|   add_definitions (--coverage) |   add_definitions (--coverage) | ||||||
|   target_link_libraries(openmw-launcher gcov) |   target_link_libraries(openmw-launcher gcov) | ||||||
| endif() | endif() | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  |  | ||||||
|  | @ -54,9 +54,6 @@ int main(int argc, char *argv[]) | ||||||
| 
 | 
 | ||||||
|         QDir::setCurrent(dir.absolutePath()); |         QDir::setCurrent(dir.absolutePath()); | ||||||
| 
 | 
 | ||||||
|         // Support non-latin characters
 |  | ||||||
|         QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); |  | ||||||
| 
 |  | ||||||
|         Launcher::MainDialog mainWin; |         Launcher::MainDialog mainWin; | ||||||
| 
 | 
 | ||||||
|         Launcher::FirstRunDialogResult result = mainWin.showFirstRunDialog(); |         Launcher::FirstRunDialogResult result = mainWin.showFirstRunDialog(); | ||||||
|  |  | ||||||
|  | @ -14,10 +14,16 @@ add_executable(openmw-iniimporter | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| target_link_libraries(openmw-iniimporter | target_link_libraries(openmw-iniimporter | ||||||
|     ${Boost_LIBRARIES} |     ${Boost_PROGRAM_OPTIONS_LIBRARY} | ||||||
|  |     ${Boost_FILESYSTEM_LIBRARY} | ||||||
|     components |     components | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | if (WIN32) | ||||||
|  |     target_link_libraries(openmw-iniimporter | ||||||
|  |     ${Boost_LOCALE_LIBRARY}) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
| if (MINGW) | if (MINGW) | ||||||
|   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -municode") |   set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -municode") | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
|  | @ -18,7 +18,7 @@ opencs_hdrs_noqt (model/doc | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| opencs_units (model/world | opencs_units (model/world | ||||||
|     idtable idtableproxymodel regionmap data commanddispatcher idtablebase resourcetable nestedtableproxymodel idtree |     idtable idtableproxymodel regionmap data commanddispatcher idtablebase resourcetable nestedtableproxymodel idtree infotableproxymodel | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -41,7 +41,7 @@ opencs_units (model/tools | ||||||
| opencs_units_noqt (model/tools | opencs_units_noqt (model/tools | ||||||
|     mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck |     mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck | ||||||
|     birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck |     birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck | ||||||
|     startscriptcheck search searchoperation searchstage pathgridcheck |     startscriptcheck search searchoperation searchstage pathgridcheck soundgencheck | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -70,11 +70,12 @@ opencs_units (view/world | ||||||
| opencs_units_noqt (view/world | opencs_units_noqt (view/world | ||||||
|     subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate |     subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate | ||||||
|     scripthighlighter idvalidator dialoguecreator physicssystem idcompletiondelegate |     scripthighlighter idvalidator dialoguecreator physicssystem idcompletiondelegate | ||||||
|  |     colordelegate | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
| opencs_units (view/widget | opencs_units (view/widget | ||||||
|     scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton |     scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton | ||||||
|     scenetooltoggle2 completerpopup |     scenetooltoggle2 completerpopup coloreditor colorpickerpopup | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
| opencs_units (view/render | opencs_units (view/render | ||||||
|  | @ -153,19 +154,16 @@ if(WIN32) | ||||||
|     set(QT_USE_QTMAIN TRUE) |     set(QT_USE_QTMAIN TRUE) | ||||||
| endif(WIN32) | endif(WIN32) | ||||||
| 
 | 
 | ||||||
| set(BOOST_COMPONENTS system filesystem program_options thread wave) | if (DESIRED_QT_VERSION MATCHES 4) | ||||||
| if(WIN32) |     include(${QT_USE_FILE}) | ||||||
|     set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale) |     qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI}) | ||||||
| endif(WIN32) |     qt4_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT}) | ||||||
| 
 |     qt4_add_resources(OPENCS_RES_SRC ${OPENCS_RES}) | ||||||
| find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS}) | else() | ||||||
| 
 |     qt5_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI}) | ||||||
| find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED) |     qt5_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT}) | ||||||
| include(${QT_USE_FILE}) |     qt5_add_resources(OPENCS_RES_SRC ${OPENCS_RES}) | ||||||
| 
 | endif() | ||||||
| qt4_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI}) |  | ||||||
| qt4_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT}) |  | ||||||
| qt4_add_resources(OPENCS_RES_SRC ${OPENCS_RES}) |  | ||||||
| 
 | 
 | ||||||
| # for compiled .ui files | # for compiled .ui files | ||||||
| include_directories(${CMAKE_CURRENT_BINARY_DIR}) | include_directories(${CMAKE_CURRENT_BINARY_DIR}) | ||||||
|  | @ -206,12 +204,36 @@ target_link_libraries(openmw-cs | ||||||
|     ${OGRE_Overlay_LIBRARIES} |     ${OGRE_Overlay_LIBRARIES} | ||||||
|     ${OGRE_STATIC_PLUGINS} |     ${OGRE_STATIC_PLUGINS} | ||||||
|     ${SHINY_LIBRARIES} |     ${SHINY_LIBRARIES} | ||||||
|     ${Boost_LIBRARIES} |     ${Boost_SYSTEM_LIBRARY} | ||||||
|  |     ${Boost_FILESYSTEM_LIBRARY} | ||||||
|  |     ${Boost_PROGRAM_OPTIONS_LIBRARY} | ||||||
|  |     ${Boost_WAVE_LIBRARY} | ||||||
|     ${BULLET_LIBRARIES} |     ${BULLET_LIBRARIES} | ||||||
|     ${QT_LIBRARIES} |  | ||||||
|     components |     components | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | if (DESIRED_QT_VERSION MATCHES 4) | ||||||
|  |     target_link_libraries(openmw-cs | ||||||
|  |     ${QT_QTGUI_LIBRARY} | ||||||
|  |     ${QT_QTCORE_LIBRARY} | ||||||
|  |     ${QT_QTNETWORK_LIBRARY}) | ||||||
|  | 
 | ||||||
|  |     if (WIN32) | ||||||
|  |         target_link_libraries(openmw-cs ${QT_QTMAIN_LIBRARY}) | ||||||
|  |     endif() | ||||||
|  | 
 | ||||||
|  | else() | ||||||
|  |     qt5_use_modules(openmw-cs Widgets Core Network) | ||||||
|  |     if (WIN32) | ||||||
|  |         target_link_libraries(Qt5::WinMain) | ||||||
|  |     endif() | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
|  | if (WIN32) | ||||||
|  |     target_link_libraries(openmw-cs ${Boost_LOCALE_LIBRARY}) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| if(APPLE) | if(APPLE) | ||||||
|     INSTALL(TARGETS openmw-cs BUNDLE DESTINATION OpenMW COMPONENT BUNDLE) |     INSTALL(TARGETS openmw-cs BUNDLE DESTINATION OpenMW COMPONENT BUNDLE) | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
|  | @ -98,7 +98,7 @@ void CS::Editor::setupDataFiles (const Files::PathContainer& dataDirs) | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfig() | std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfig(bool quiet) | ||||||
| { | { | ||||||
|     boost::program_options::variables_map variables; |     boost::program_options::variables_map variables; | ||||||
|     boost::program_options::options_description desc("Syntax: openmw-cs <options>\nAllowed options"); |     boost::program_options::options_description desc("Syntax: openmw-cs <options>\nAllowed options"); | ||||||
|  | @ -118,7 +118,7 @@ std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfi | ||||||
| 
 | 
 | ||||||
|     boost::program_options::notify(variables); |     boost::program_options::notify(variables); | ||||||
| 
 | 
 | ||||||
|     mCfgMgr.readConfiguration(variables, desc); |     mCfgMgr.readConfiguration(variables, desc, quiet); | ||||||
| 
 | 
 | ||||||
|     mDocumentManager.setEncoding ( |     mDocumentManager.setEncoding ( | ||||||
|         ToUTF8::calculateEncoding (variables["encoding"].as<std::string>())); |         ToUTF8::calculateEncoding (variables["encoding"].as<std::string>())); | ||||||
|  | @ -198,6 +198,11 @@ void CS::Editor::cancelCreateGame() | ||||||
| void CS::Editor::createAddon() | void CS::Editor::createAddon() | ||||||
| { | { | ||||||
|     mStartup.hide(); |     mStartup.hide(); | ||||||
|  | 
 | ||||||
|  |     mFileDialog.clearFiles(); | ||||||
|  |     std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig(/*quiet*/true); | ||||||
|  |     setupDataFiles (config.first); | ||||||
|  | 
 | ||||||
|     mFileDialog.showDialog (CSVDoc::ContentAction_New); |     mFileDialog.showDialog (CSVDoc::ContentAction_New); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -218,6 +223,11 @@ void CS::Editor::cancelFileDialog() | ||||||
| void CS::Editor::loadDocument() | void CS::Editor::loadDocument() | ||||||
| { | { | ||||||
|     mStartup.hide(); |     mStartup.hide(); | ||||||
|  | 
 | ||||||
|  |     mFileDialog.clearFiles(); | ||||||
|  |     std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig(/*quiet*/true); | ||||||
|  |     setupDataFiles (config.first); | ||||||
|  | 
 | ||||||
|     mFileDialog.showDialog (CSVDoc::ContentAction_Edit); |     mFileDialog.showDialog (CSVDoc::ContentAction_Edit); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -312,12 +322,12 @@ bool CS::Editor::makeIPCServer() | ||||||
|             mServer->close(); |             mServer->close(); | ||||||
|             fullPath.remove(QRegExp("dummy$")); |             fullPath.remove(QRegExp("dummy$")); | ||||||
|             fullPath += mIpcServerName; |             fullPath += mIpcServerName; | ||||||
|             if(boost::filesystem::exists(fullPath.toStdString().c_str())) |             if(boost::filesystem::exists(fullPath.toUtf8().constData())) | ||||||
|             { |             { | ||||||
|                 // TODO: compare pid of the current process with that in the file
 |                 // TODO: compare pid of the current process with that in the file
 | ||||||
|                 std::cout << "Detected unclean shutdown." << std::endl; |                 std::cout << "Detected unclean shutdown." << std::endl; | ||||||
|                 // delete the stale file
 |                 // delete the stale file
 | ||||||
|                 if(remove(fullPath.toStdString().c_str())) |                 if(remove(fullPath.toUtf8().constData())) | ||||||
|                     std::cerr << "ERROR removing stale connection file" << std::endl; |                     std::cerr << "ERROR removing stale connection file" << std::endl; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -64,7 +64,7 @@ namespace CS | ||||||
| 
 | 
 | ||||||
|             void setupDataFiles (const Files::PathContainer& dataDirs); |             void setupDataFiles (const Files::PathContainer& dataDirs); | ||||||
| 
 | 
 | ||||||
|             std::pair<Files::PathContainer, std::vector<std::string> > readConfig(); |             std::pair<Files::PathContainer, std::vector<std::string> > readConfig(bool quiet=false); | ||||||
|             ///< \return data paths
 |             ///< \return data paths
 | ||||||
| 
 | 
 | ||||||
|             // not implemented
 |             // not implemented
 | ||||||
|  |  | ||||||
|  | @ -2272,7 +2272,7 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration, | ||||||
| 
 | 
 | ||||||
|         if (boost::filesystem::exists (customFiltersPath)) |         if (boost::filesystem::exists (customFiltersPath)) | ||||||
|         { |         { | ||||||
|             destination << std::ifstream(customFiltersPath.c_str(), std::ios::binary).rdbuf(); |             destination << std::ifstream(customFiltersPath.string().c_str(), std::ios::binary).rdbuf(); | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|  |  | ||||||
|  | @ -244,6 +244,47 @@ void CSMSettings::UserSettings::buildSettingModelDefaults() | ||||||
|         jumpToAdded->setDeclaredValues (jumpValues); |         jumpToAdded->setDeclaredValues (jumpValues); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     declareSection ("report-input", "Report Input"); | ||||||
|  |     { | ||||||
|  |         QString none ("None"); | ||||||
|  |         QString edit ("Edit"); | ||||||
|  |         QString remove ("Remove"); | ||||||
|  |         QString editAndRemove ("Edit And Remove"); | ||||||
|  | 
 | ||||||
|  |         QStringList values; | ||||||
|  |         values << none << edit << remove << editAndRemove; | ||||||
|  | 
 | ||||||
|  |         QString toolTip = "<ul>" | ||||||
|  |             "<li>None</li>" | ||||||
|  |             "<li>Edit: Open a table or dialogue suitable for addressing the listed report</li>" | ||||||
|  |             "<li>Remove: Remove the report from the report table</li>" | ||||||
|  |             "<li>Edit and Remove: Open a table or dialogue suitable for addressing the listed report, then remove the report from the report table</li>" | ||||||
|  |             "</ul>"; | ||||||
|  | 
 | ||||||
|  |         Setting *doubleClick = createSetting (Type_ComboBox, "double", "Double Click"); | ||||||
|  |         doubleClick->setDeclaredValues (values); | ||||||
|  |         doubleClick->setDefaultValue (edit); | ||||||
|  |         doubleClick->setToolTip ("Action on double click in report table:<p>" + toolTip); | ||||||
|  | 
 | ||||||
|  |         Setting *shiftDoubleClick = createSetting (Type_ComboBox, "double-s", | ||||||
|  |             "Shift Double Click"); | ||||||
|  |         shiftDoubleClick->setDeclaredValues (values); | ||||||
|  |         shiftDoubleClick->setDefaultValue (remove); | ||||||
|  |         shiftDoubleClick->setToolTip ("Action on shift double click in report table:<p>" + toolTip); | ||||||
|  | 
 | ||||||
|  |         Setting *ctrlDoubleClick = createSetting (Type_ComboBox, "double-c", | ||||||
|  |             "Control Double Click"); | ||||||
|  |         ctrlDoubleClick->setDeclaredValues (values); | ||||||
|  |         ctrlDoubleClick->setDefaultValue (editAndRemove); | ||||||
|  |         ctrlDoubleClick->setToolTip ("Action on control double click in report table:<p>" + toolTip); | ||||||
|  | 
 | ||||||
|  |         Setting *shiftCtrlDoubleClick = createSetting (Type_ComboBox, "double-sc", | ||||||
|  |             "Shift Control Double Click"); | ||||||
|  |         shiftCtrlDoubleClick->setDeclaredValues (values); | ||||||
|  |         shiftCtrlDoubleClick->setDefaultValue (none); | ||||||
|  |         shiftCtrlDoubleClick->setToolTip ("Action on shift control double click in report table:<p>" + toolTip); | ||||||
|  |     } | ||||||
|  |      | ||||||
|     declareSection ("search", "Search & Replace"); |     declareSection ("search", "Search & Replace"); | ||||||
|     { |     { | ||||||
|         Setting *before = createSetting (Type_SpinBox, "char-before", |         Setting *before = createSetting (Type_SpinBox, "char-before", | ||||||
|  |  | ||||||
|  | @ -648,7 +648,7 @@ void CSMTools::ReferenceableCheckStage::npcCheck ( | ||||||
| 
 | 
 | ||||||
|     if (npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) //12 = autocalculated
 |     if (npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) //12 = autocalculated
 | ||||||
|     { |     { | ||||||
|         if ((npc.mFlags & ESM::NPC::Autocalc) == 0) //0x0008 = autocalculated flag
 |         if ((npc.mFlags & ESM::NPC::Autocalc) == 0) //0x0010 = autocalculated flag
 | ||||||
|         { |         { | ||||||
|             messages.push_back (std::make_pair (id, npc.mId + " mNpdtType or flags mismatch!")); //should not happend?
 |             messages.push_back (std::make_pair (id, npc.mId + " mNpdtType or flags mismatch!")); //should not happend?
 | ||||||
|             return; |             return; | ||||||
|  |  | ||||||
							
								
								
									
										53
									
								
								apps/opencs/model/tools/soundgencheck.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								apps/opencs/model/tools/soundgencheck.cpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,53 @@ | ||||||
|  | #include "soundgencheck.hpp" | ||||||
|  | 
 | ||||||
|  | #include <sstream> | ||||||
|  | 
 | ||||||
|  | #include "../world/refiddata.hpp" | ||||||
|  | #include "../world/universalid.hpp" | ||||||
|  | 
 | ||||||
|  | CSMTools::SoundGenCheckStage::SoundGenCheckStage(const CSMWorld::IdCollection<ESM::SoundGenerator> &soundGens, | ||||||
|  |                                                  const CSMWorld::IdCollection<ESM::Sound> &sounds, | ||||||
|  |                                                  const CSMWorld::RefIdCollection &referenceables) | ||||||
|  |     : mSoundGens(soundGens), | ||||||
|  |       mSounds(sounds), | ||||||
|  |       mReferenceables(referenceables) | ||||||
|  | {} | ||||||
|  | 
 | ||||||
|  | int CSMTools::SoundGenCheckStage::setup() | ||||||
|  | { | ||||||
|  |     return mSoundGens.getSize(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void CSMTools::SoundGenCheckStage::perform(int stage, CSMDoc::Messages &messages) | ||||||
|  | { | ||||||
|  |     const CSMWorld::Record<ESM::SoundGenerator> &record = mSoundGens.getRecord(stage); | ||||||
|  |     if (record.isDeleted()) | ||||||
|  |     { | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     const ESM::SoundGenerator soundGen = record.get(); | ||||||
|  |     CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_SoundGen, soundGen.mId); | ||||||
|  | 
 | ||||||
|  |     if (!soundGen.mCreature.empty()) | ||||||
|  |     { | ||||||
|  |         CSMWorld::RefIdData::LocalIndex creatureIndex = mReferenceables.getDataSet().searchId(soundGen.mCreature); | ||||||
|  |         if (creatureIndex.first == -1) | ||||||
|  |         { | ||||||
|  |             messages.push_back(std::make_pair(id, "No such creature '" + soundGen.mCreature + "'")); | ||||||
|  |         } | ||||||
|  |         else if (creatureIndex.second != CSMWorld::UniversalId::Type_Creature) | ||||||
|  |         { | ||||||
|  |             messages.push_back(std::make_pair(id, "'" + soundGen.mCreature + "' is not a creature")); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     if (soundGen.mSound.empty()) | ||||||
|  |     { | ||||||
|  |         messages.push_back(std::make_pair(id, "Sound is not specified")); | ||||||
|  |     } | ||||||
|  |     else if (mSounds.searchId(soundGen.mSound) == -1) | ||||||
|  |     { | ||||||
|  |         messages.push_back(std::make_pair(id, "No such sound '" + soundGen.mSound + "'")); | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										30
									
								
								apps/opencs/model/tools/soundgencheck.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								apps/opencs/model/tools/soundgencheck.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | ||||||
|  | #ifndef CSM_TOOLS_SOUNDGENCHECK_HPP | ||||||
|  | #define CSM_TOOLS_SOUNDGENCHECK_HPP | ||||||
|  | 
 | ||||||
|  | #include "../world/data.hpp" | ||||||
|  | 
 | ||||||
|  | #include "../doc/stage.hpp" | ||||||
|  | 
 | ||||||
|  | namespace CSMTools | ||||||
|  | { | ||||||
|  |     /// \brief VerifyStage: make sure that sound gen records are internally consistent
 | ||||||
|  |     class SoundGenCheckStage : public CSMDoc::Stage | ||||||
|  |     { | ||||||
|  |             const CSMWorld::IdCollection<ESM::SoundGenerator> &mSoundGens; | ||||||
|  |             const CSMWorld::IdCollection<ESM::Sound> &mSounds; | ||||||
|  |             const CSMWorld::RefIdCollection &mReferenceables; | ||||||
|  | 
 | ||||||
|  |         public: | ||||||
|  |             SoundGenCheckStage(const CSMWorld::IdCollection<ESM::SoundGenerator> &soundGens, | ||||||
|  |                                const CSMWorld::IdCollection<ESM::Sound> &sounds, | ||||||
|  |                                const CSMWorld::RefIdCollection &referenceables); | ||||||
|  | 
 | ||||||
|  |             virtual int setup(); | ||||||
|  |             ///< \return number of steps
 | ||||||
|  | 
 | ||||||
|  |             virtual void perform(int stage, CSMDoc::Messages &messages); | ||||||
|  |             ///< Messages resulting from this stage will be appended to \a messages.
 | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -27,6 +27,7 @@ | ||||||
| #include "startscriptcheck.hpp" | #include "startscriptcheck.hpp" | ||||||
| #include "searchoperation.hpp" | #include "searchoperation.hpp" | ||||||
| #include "pathgridcheck.hpp" | #include "pathgridcheck.hpp" | ||||||
|  | #include "soundgencheck.hpp" | ||||||
| 
 | 
 | ||||||
| CSMDoc::OperationHolder *CSMTools::Tools::get (int type) | CSMDoc::OperationHolder *CSMTools::Tools::get (int type) | ||||||
| { | { | ||||||
|  | @ -99,6 +100,10 @@ CSMDoc::OperationHolder *CSMTools::Tools::getVerifier() | ||||||
| 
 | 
 | ||||||
|         mVerifierOperation->appendStage (new PathgridCheckStage (mData.getPathgrids())); |         mVerifierOperation->appendStage (new PathgridCheckStage (mData.getPathgrids())); | ||||||
| 
 | 
 | ||||||
|  |         mVerifierOperation->appendStage (new SoundGenCheckStage (mData.getSoundGens(), | ||||||
|  |                                                                  mData.getSounds(), | ||||||
|  |                                                                  mData.getReferenceables())); | ||||||
|  | 
 | ||||||
|         mVerifier.setOperation (mVerifierOperation); |         mVerifier.setOperation (mVerifierOperation); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -694,7 +694,7 @@ namespace CSMWorld | ||||||
| 
 | 
 | ||||||
|             QColor colour = data.value<QColor>(); |             QColor colour = data.value<QColor>(); | ||||||
| 
 | 
 | ||||||
|             record2.mMapColor = colour.rgb() & 0xffffff; |             record2.mMapColor = (colour.blue() << 16) | (colour.green() << 8) | colour.red(); | ||||||
| 
 | 
 | ||||||
|             record.setModified (record2); |             record.setModified (record2); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -52,9 +52,10 @@ QModelIndex CSMWorld::IdTableProxyModel::getModelIndex (const std::string& id, i | ||||||
| 
 | 
 | ||||||
| void CSMWorld::IdTableProxyModel::setFilter (const boost::shared_ptr<CSMFilter::Node>& filter) | void CSMWorld::IdTableProxyModel::setFilter (const boost::shared_ptr<CSMFilter::Node>& filter) | ||||||
| { | { | ||||||
|  |     beginResetModel(); | ||||||
|     mFilter = filter; |     mFilter = filter; | ||||||
|     updateColumnMap(); |     updateColumnMap(); | ||||||
|     reset(); |     endResetModel(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool CSMWorld::IdTableProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const | bool CSMWorld::IdTableProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const | ||||||
|  |  | ||||||
							
								
								
									
										58
									
								
								apps/opencs/model/world/infotableproxymodel.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								apps/opencs/model/world/infotableproxymodel.cpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,58 @@ | ||||||
|  | #include "infotableproxymodel.hpp" | ||||||
|  | 
 | ||||||
|  | #include "idtablebase.hpp" | ||||||
|  | #include "columns.hpp" | ||||||
|  | 
 | ||||||
|  | CSMWorld::InfoTableProxyModel::InfoTableProxyModel(CSMWorld::UniversalId::Type type, QObject *parent) | ||||||
|  |     : IdTableProxyModel(parent), | ||||||
|  |       mType(type), | ||||||
|  |       mSourceModel(NULL) | ||||||
|  | { | ||||||
|  |     Q_ASSERT(type == UniversalId::Type_TopicInfos || type == UniversalId::Type_JournalInfos); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void CSMWorld::InfoTableProxyModel::setSourceModel(QAbstractItemModel *sourceModel) | ||||||
|  | { | ||||||
|  |     IdTableProxyModel::setSourceModel(sourceModel); | ||||||
|  |     mSourceModel = dynamic_cast<IdTableBase *>(sourceModel); | ||||||
|  |     connect(mSourceModel,  | ||||||
|  |             SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), | ||||||
|  |             this,  | ||||||
|  |             SLOT(modelDataChanged(const QModelIndex &, const QModelIndex &))); | ||||||
|  |     mFirstRowCache.clear(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool CSMWorld::InfoTableProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const | ||||||
|  | { | ||||||
|  |     QModelIndex first = mSourceModel->index(getFirstInfoRow(left.row()), left.column()); | ||||||
|  |     QModelIndex second = mSourceModel->index(getFirstInfoRow(right.row()), right.column()); | ||||||
|  |     return IdTableProxyModel::lessThan(first, second); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | int CSMWorld::InfoTableProxyModel::getFirstInfoRow(int currentRow) const | ||||||
|  | { | ||||||
|  |     Columns::ColumnId columnId = Columns::ColumnId_Topic; | ||||||
|  |     if (mType == UniversalId::Type_JournalInfos) | ||||||
|  |     { | ||||||
|  |         columnId = Columns::ColumnId_Journal; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     int column = mSourceModel->findColumnIndex(columnId); | ||||||
|  |     QString info = mSourceModel->data(mSourceModel->index(currentRow, column)).toString(); | ||||||
|  | 
 | ||||||
|  |     if (mFirstRowCache.contains(info)) | ||||||
|  |     { | ||||||
|  |         return mFirstRowCache[info]; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     while (--currentRow >= 0 && | ||||||
|  |            mSourceModel->data(mSourceModel->index(currentRow, column)) == info); | ||||||
|  | 
 | ||||||
|  |     mFirstRowCache[info] = currentRow + 1; | ||||||
|  |     return currentRow + 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void CSMWorld::InfoTableProxyModel::modelDataChanged(const QModelIndex &/*topLeft*/, const QModelIndex &/*bottomRight*/) | ||||||
|  | { | ||||||
|  |     mFirstRowCache.clear(); | ||||||
|  | } | ||||||
							
								
								
									
										38
									
								
								apps/opencs/model/world/infotableproxymodel.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								apps/opencs/model/world/infotableproxymodel.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,38 @@ | ||||||
|  | #ifndef CSM_WORLD_INFOTABLEPROXYMODEL_HPP | ||||||
|  | #define CSM_WORLD_INFOTABLEPROXYMODEL_HPP | ||||||
|  | 
 | ||||||
|  | #include <QHash> | ||||||
|  | 
 | ||||||
|  | #include "idtableproxymodel.hpp" | ||||||
|  | #include "universalid.hpp" | ||||||
|  | 
 | ||||||
|  | namespace CSMWorld | ||||||
|  | { | ||||||
|  |     class IdTableBase; | ||||||
|  | 
 | ||||||
|  |     class InfoTableProxyModel : public IdTableProxyModel | ||||||
|  |     { | ||||||
|  |             Q_OBJECT | ||||||
|  | 
 | ||||||
|  |             UniversalId::Type mType; | ||||||
|  |             IdTableBase *mSourceModel; | ||||||
|  | 
 | ||||||
|  |             mutable QHash<QString, int> mFirstRowCache; | ||||||
|  | 
 | ||||||
|  |             int getFirstInfoRow(int currentRow) const; | ||||||
|  |             ///< Finds the first row with the same topic (journal entry) as in \a currentRow
 | ||||||
|  | 
 | ||||||
|  |         public: | ||||||
|  |             InfoTableProxyModel(UniversalId::Type type, QObject *parent = 0); | ||||||
|  | 
 | ||||||
|  |             void setSourceModel(QAbstractItemModel *sourceModel); | ||||||
|  | 
 | ||||||
|  |         protected: | ||||||
|  |             virtual bool lessThan(const QModelIndex &left, const QModelIndex &right) const; | ||||||
|  | 
 | ||||||
|  |         private slots: | ||||||
|  |             void modelDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -37,10 +37,18 @@ void CSMWorld::PotionRefIdAdapter::setData (const RefIdColumn *column, RefIdData | ||||||
|     Record<ESM::Potion>& record = static_cast<Record<ESM::Potion>&> ( |     Record<ESM::Potion>& record = static_cast<Record<ESM::Potion>&> ( | ||||||
|         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Potion))); |         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Potion))); | ||||||
| 
 | 
 | ||||||
|  |     ESM::Potion potion = record.get(); | ||||||
|  | 
 | ||||||
|     if (column==mAutoCalc) |     if (column==mAutoCalc) | ||||||
|         record.get().mData.mAutoCalc = value.toInt(); |         potion.mData.mAutoCalc = value.toInt(); | ||||||
|     else |     else | ||||||
|  |     { | ||||||
|         InventoryRefIdAdapter<ESM::Potion>::setData (column, data, index, value); |         InventoryRefIdAdapter<ESM::Potion>::setData (column, data, index, value); | ||||||
|  | 
 | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     record.setModified(potion); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -71,12 +79,19 @@ void CSMWorld::ApparatusRefIdAdapter::setData (const RefIdColumn *column, RefIdD | ||||||
|     Record<ESM::Apparatus>& record = static_cast<Record<ESM::Apparatus>&> ( |     Record<ESM::Apparatus>& record = static_cast<Record<ESM::Apparatus>&> ( | ||||||
|         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Apparatus))); |         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Apparatus))); | ||||||
| 
 | 
 | ||||||
|  |     ESM::Apparatus apparatus = record.get(); | ||||||
|  | 
 | ||||||
|     if (column==mType) |     if (column==mType) | ||||||
|         record.get().mData.mType = value.toInt(); |         apparatus.mData.mType = value.toInt(); | ||||||
|     else if (column==mQuality) |     else if (column==mQuality) | ||||||
|         record.get().mData.mQuality = value.toFloat(); |         apparatus.mData.mQuality = value.toFloat(); | ||||||
|     else |     else | ||||||
|  |     { | ||||||
|         InventoryRefIdAdapter<ESM::Apparatus>::setData (column, data, index, value); |         InventoryRefIdAdapter<ESM::Apparatus>::setData (column, data, index, value); | ||||||
|  | 
 | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |     record.setModified(apparatus); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -114,14 +129,22 @@ void CSMWorld::ArmorRefIdAdapter::setData (const RefIdColumn *column, RefIdData& | ||||||
|     Record<ESM::Armor>& record = static_cast<Record<ESM::Armor>&> ( |     Record<ESM::Armor>& record = static_cast<Record<ESM::Armor>&> ( | ||||||
|         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Armor))); |         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Armor))); | ||||||
| 
 | 
 | ||||||
|  |     ESM::Armor armor = record.get(); | ||||||
|  | 
 | ||||||
|     if (column==mType) |     if (column==mType) | ||||||
|         record.get().mData.mType = value.toInt(); |         armor.mData.mType = value.toInt(); | ||||||
|     else if (column==mHealth) |     else if (column==mHealth) | ||||||
|         record.get().mData.mHealth = value.toInt(); |         armor.mData.mHealth = value.toInt(); | ||||||
|     else if (column==mArmor) |     else if (column==mArmor) | ||||||
|         record.get().mData.mArmor = value.toInt(); |         armor.mData.mArmor = value.toInt(); | ||||||
|     else |     else | ||||||
|  |     { | ||||||
|         EnchantableRefIdAdapter<ESM::Armor>::setData (column, data, index, value); |         EnchantableRefIdAdapter<ESM::Armor>::setData (column, data, index, value); | ||||||
|  | 
 | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     record.setModified(armor); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| CSMWorld::BookRefIdAdapter::BookRefIdAdapter (const EnchantableColumns& columns, | CSMWorld::BookRefIdAdapter::BookRefIdAdapter (const EnchantableColumns& columns, | ||||||
|  | @ -151,12 +174,20 @@ void CSMWorld::BookRefIdAdapter::setData (const RefIdColumn *column, RefIdData& | ||||||
|     Record<ESM::Book>& record = static_cast<Record<ESM::Book>&> ( |     Record<ESM::Book>& record = static_cast<Record<ESM::Book>&> ( | ||||||
|         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Book))); |         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Book))); | ||||||
| 
 | 
 | ||||||
|  |     ESM::Book book = record.get(); | ||||||
|  | 
 | ||||||
|     if (column==mScroll) |     if (column==mScroll) | ||||||
|         record.get().mData.mIsScroll = value.toInt(); |         book.mData.mIsScroll = value.toInt(); | ||||||
|     else if (column==mSkill) |     else if (column==mSkill) | ||||||
|         record.get().mData.mSkillID = value.toInt(); |         book.mData.mSkillID = value.toInt(); | ||||||
|     else |     else | ||||||
|  |     { | ||||||
|         EnchantableRefIdAdapter<ESM::Book>::setData (column, data, index, value); |         EnchantableRefIdAdapter<ESM::Book>::setData (column, data, index, value); | ||||||
|  | 
 | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     record.setModified(book); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| CSMWorld::ClothingRefIdAdapter::ClothingRefIdAdapter (const EnchantableColumns& columns, | CSMWorld::ClothingRefIdAdapter::ClothingRefIdAdapter (const EnchantableColumns& columns, | ||||||
|  | @ -186,10 +217,18 @@ void CSMWorld::ClothingRefIdAdapter::setData (const RefIdColumn *column, RefIdDa | ||||||
|     Record<ESM::Clothing>& record = static_cast<Record<ESM::Clothing>&> ( |     Record<ESM::Clothing>& record = static_cast<Record<ESM::Clothing>&> ( | ||||||
|         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Clothing))); |         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Clothing))); | ||||||
| 
 | 
 | ||||||
|  |     ESM::Clothing clothing = record.get(); | ||||||
|  | 
 | ||||||
|     if (column==mType) |     if (column==mType) | ||||||
|         record.get().mData.mType = value.toInt(); |         clothing.mData.mType = value.toInt(); | ||||||
|     else |     else | ||||||
|  |     { | ||||||
|         EnchantableRefIdAdapter<ESM::Clothing>::setData (column, data, index, value); |         EnchantableRefIdAdapter<ESM::Clothing>::setData (column, data, index, value); | ||||||
|  | 
 | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     record.setModified(clothing); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| CSMWorld::ContainerRefIdAdapter::ContainerRefIdAdapter (const NameColumns& columns, | CSMWorld::ContainerRefIdAdapter::ContainerRefIdAdapter (const NameColumns& columns, | ||||||
|  | @ -226,24 +265,32 @@ void CSMWorld::ContainerRefIdAdapter::setData (const RefIdColumn *column, RefIdD | ||||||
|     Record<ESM::Container>& record = static_cast<Record<ESM::Container>&> ( |     Record<ESM::Container>& record = static_cast<Record<ESM::Container>&> ( | ||||||
|         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Container))); |         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Container))); | ||||||
| 
 | 
 | ||||||
|  |     ESM::Container container = record.get(); | ||||||
|  | 
 | ||||||
|     if (column==mWeight) |     if (column==mWeight) | ||||||
|         record.get().mWeight = value.toFloat(); |         container.mWeight = value.toFloat(); | ||||||
|     else if (column==mOrganic) |     else if (column==mOrganic) | ||||||
|     { |     { | ||||||
|         if (value.toInt()) |         if (value.toInt()) | ||||||
|             record.get().mFlags |= ESM::Container::Organic; |             container.mFlags |= ESM::Container::Organic; | ||||||
|         else |         else | ||||||
|             record.get().mFlags &= ~ESM::Container::Organic; |             container.mFlags &= ~ESM::Container::Organic; | ||||||
|     } |     } | ||||||
|     else if (column==mRespawn) |     else if (column==mRespawn) | ||||||
|     { |     { | ||||||
|         if (value.toInt()) |         if (value.toInt()) | ||||||
|             record.get().mFlags |= ESM::Container::Respawn; |             container.mFlags |= ESM::Container::Respawn; | ||||||
|         else |         else | ||||||
|             record.get().mFlags &= ~ESM::Container::Respawn; |             container.mFlags &= ~ESM::Container::Respawn; | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|  |     { | ||||||
|         NameRefIdAdapter<ESM::Container>::setData (column, data, index, value); |         NameRefIdAdapter<ESM::Container>::setData (column, data, index, value); | ||||||
|  | 
 | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     record.setModified(container); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| CSMWorld::CreatureColumns::CreatureColumns (const ActorColumns& actorColumns) | CSMWorld::CreatureColumns::CreatureColumns (const ActorColumns& actorColumns) | ||||||
|  | @ -303,20 +350,22 @@ void CSMWorld::CreatureRefIdAdapter::setData (const RefIdColumn *column, RefIdDa | ||||||
|     Record<ESM::Creature>& record = static_cast<Record<ESM::Creature>&> ( |     Record<ESM::Creature>& record = static_cast<Record<ESM::Creature>&> ( | ||||||
|         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature))); |         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature))); | ||||||
| 
 | 
 | ||||||
|  |     ESM::Creature creature = record.get(); | ||||||
|  | 
 | ||||||
|     if (column==mColumns.mType) |     if (column==mColumns.mType) | ||||||
|         record.get().mData.mType = value.toInt(); |         creature.mData.mType = value.toInt(); | ||||||
|     else if (column==mColumns.mSoul) |     else if (column==mColumns.mSoul) | ||||||
|         record.get().mData.mSoul = value.toInt(); |         creature.mData.mSoul = value.toInt(); | ||||||
|     else if (column==mColumns.mScale) |     else if (column==mColumns.mScale) | ||||||
|         record.get().mScale = value.toFloat(); |         creature.mScale = value.toFloat(); | ||||||
|     else if (column==mColumns.mOriginal) |     else if (column==mColumns.mOriginal) | ||||||
|         record.get().mOriginal = value.toString().toUtf8().constData(); |         creature.mOriginal = value.toString().toUtf8().constData(); | ||||||
|     else if (column==mColumns.mCombat) |     else if (column==mColumns.mCombat) | ||||||
|         record.get().mData.mCombat = value.toInt(); |         creature.mData.mCombat = value.toInt(); | ||||||
|     else if (column==mColumns.mMagic) |     else if (column==mColumns.mMagic) | ||||||
|         record.get().mData.mMagic = value.toInt(); |         creature.mData.mMagic = value.toInt(); | ||||||
|     else if (column==mColumns.mStealth) |     else if (column==mColumns.mStealth) | ||||||
|         record.get().mData.mStealth = value.toInt(); |         creature.mData.mStealth = value.toInt(); | ||||||
|     else |     else | ||||||
|     { |     { | ||||||
|         std::map<const RefIdColumn *, unsigned int>::const_iterator iter = |         std::map<const RefIdColumn *, unsigned int>::const_iterator iter = | ||||||
|  | @ -325,13 +374,19 @@ void CSMWorld::CreatureRefIdAdapter::setData (const RefIdColumn *column, RefIdDa | ||||||
|         if (iter!=mColumns.mFlags.end()) |         if (iter!=mColumns.mFlags.end()) | ||||||
|         { |         { | ||||||
|             if (value.toInt()!=0) |             if (value.toInt()!=0) | ||||||
|                 record.get().mFlags |= iter->second; |                 creature.mFlags |= iter->second; | ||||||
|             else |             else | ||||||
|                 record.get().mFlags &= ~iter->second; |                 creature.mFlags &= ~iter->second; | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|  |         { | ||||||
|             ActorRefIdAdapter<ESM::Creature>::setData (column, data, index, value); |             ActorRefIdAdapter<ESM::Creature>::setData (column, data, index, value); | ||||||
|  | 
 | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     record.setModified(creature); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| CSMWorld::DoorRefIdAdapter::DoorRefIdAdapter (const NameColumns& columns, | CSMWorld::DoorRefIdAdapter::DoorRefIdAdapter (const NameColumns& columns, | ||||||
|  | @ -361,12 +416,20 @@ void CSMWorld::DoorRefIdAdapter::setData (const RefIdColumn *column, RefIdData& | ||||||
|     Record<ESM::Door>& record = static_cast<Record<ESM::Door>&> ( |     Record<ESM::Door>& record = static_cast<Record<ESM::Door>&> ( | ||||||
|         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Door))); |         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Door))); | ||||||
| 
 | 
 | ||||||
|  |     ESM::Door door = record.get(); | ||||||
|  | 
 | ||||||
|     if (column==mOpenSound) |     if (column==mOpenSound) | ||||||
|         record.get().mOpenSound = value.toString().toUtf8().constData(); |         door.mOpenSound = value.toString().toUtf8().constData(); | ||||||
|     else if (column==mCloseSound) |     else if (column==mCloseSound) | ||||||
|         record.get().mCloseSound = value.toString().toUtf8().constData(); |         door.mCloseSound = value.toString().toUtf8().constData(); | ||||||
|     else |     else | ||||||
|  |     { | ||||||
|         NameRefIdAdapter<ESM::Door>::setData (column, data, index, value); |         NameRefIdAdapter<ESM::Door>::setData (column, data, index, value); | ||||||
|  | 
 | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     record.setModified(door); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| CSMWorld::LightColumns::LightColumns (const InventoryColumns& columns) | CSMWorld::LightColumns::LightColumns (const InventoryColumns& columns) | ||||||
|  | @ -409,14 +472,16 @@ void CSMWorld::LightRefIdAdapter::setData (const RefIdColumn *column, RefIdData& | ||||||
|     Record<ESM::Light>& record = static_cast<Record<ESM::Light>&> ( |     Record<ESM::Light>& record = static_cast<Record<ESM::Light>&> ( | ||||||
|         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Light))); |         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Light))); | ||||||
| 
 | 
 | ||||||
|  |     ESM::Light light = record.get(); | ||||||
|  | 
 | ||||||
|     if (column==mColumns.mTime) |     if (column==mColumns.mTime) | ||||||
|         record.get().mData.mTime = value.toInt(); |         light.mData.mTime = value.toInt(); | ||||||
|     else if (column==mColumns.mRadius) |     else if (column==mColumns.mRadius) | ||||||
|         record.get().mData.mRadius = value.toInt(); |         light.mData.mRadius = value.toInt(); | ||||||
|     else if (column==mColumns.mColor) |     else if (column==mColumns.mColor) | ||||||
|         record.get().mData.mColor = value.toInt(); |         light.mData.mColor = value.toInt(); | ||||||
|     else if (column==mColumns.mSound) |     else if (column==mColumns.mSound) | ||||||
|         record.get().mSound = value.toString().toUtf8().constData(); |         light.mSound = value.toString().toUtf8().constData(); | ||||||
|     else |     else | ||||||
|     { |     { | ||||||
|         std::map<const RefIdColumn *, unsigned int>::const_iterator iter = |         std::map<const RefIdColumn *, unsigned int>::const_iterator iter = | ||||||
|  | @ -425,13 +490,19 @@ void CSMWorld::LightRefIdAdapter::setData (const RefIdColumn *column, RefIdData& | ||||||
|         if (iter!=mColumns.mFlags.end()) |         if (iter!=mColumns.mFlags.end()) | ||||||
|         { |         { | ||||||
|             if (value.toInt()!=0) |             if (value.toInt()!=0) | ||||||
|                 record.get().mData.mFlags |= iter->second; |                 light.mData.mFlags |= iter->second; | ||||||
|             else |             else | ||||||
|                 record.get().mData.mFlags &= ~iter->second; |                 light.mData.mFlags &= ~iter->second; | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|  |         { | ||||||
|             InventoryRefIdAdapter<ESM::Light>::setData (column, data, index, value); |             InventoryRefIdAdapter<ESM::Light>::setData (column, data, index, value); | ||||||
|  | 
 | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     record.setModified (light); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| CSMWorld::MiscRefIdAdapter::MiscRefIdAdapter (const InventoryColumns& columns, const RefIdColumn *key) | CSMWorld::MiscRefIdAdapter::MiscRefIdAdapter (const InventoryColumns& columns, const RefIdColumn *key) | ||||||
|  | @ -456,10 +527,18 @@ void CSMWorld::MiscRefIdAdapter::setData (const RefIdColumn *column, RefIdData& | ||||||
|     Record<ESM::Miscellaneous>& record = static_cast<Record<ESM::Miscellaneous>&> ( |     Record<ESM::Miscellaneous>& record = static_cast<Record<ESM::Miscellaneous>&> ( | ||||||
|         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Miscellaneous))); |         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Miscellaneous))); | ||||||
| 
 | 
 | ||||||
|  |     ESM::Miscellaneous misc = record.get(); | ||||||
|  | 
 | ||||||
|     if (column==mKey) |     if (column==mKey) | ||||||
|         record.get().mData.mIsKey = value.toInt(); |         misc.mData.mIsKey = value.toInt(); | ||||||
|     else |     else | ||||||
|  |     { | ||||||
|         InventoryRefIdAdapter<ESM::Miscellaneous>::setData (column, data, index, value); |         InventoryRefIdAdapter<ESM::Miscellaneous>::setData (column, data, index, value); | ||||||
|  | 
 | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     record.setModified(misc); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| CSMWorld::NpcColumns::NpcColumns (const ActorColumns& actorColumns) | CSMWorld::NpcColumns::NpcColumns (const ActorColumns& actorColumns) | ||||||
|  | @ -525,16 +604,18 @@ void CSMWorld::NpcRefIdAdapter::setData (const RefIdColumn *column, RefIdData& d | ||||||
|     Record<ESM::NPC>& record = static_cast<Record<ESM::NPC>&> ( |     Record<ESM::NPC>& record = static_cast<Record<ESM::NPC>&> ( | ||||||
|         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc))); |         data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc))); | ||||||
| 
 | 
 | ||||||
|  |     ESM::NPC npc = record.get(); | ||||||
|  | 
 | ||||||
|     if (column==mColumns.mRace) |     if (column==mColumns.mRace) | ||||||
|         record.get().mRace = value.toString().toUtf8().constData(); |         npc.mRace = value.toString().toUtf8().constData(); | ||||||
|     else if (column==mColumns.mClass) |     else if (column==mColumns.mClass) | ||||||
|         record.get().mClass = value.toString().toUtf8().constData(); |         npc.mClass = value.toString().toUtf8().constData(); | ||||||
|     else if (column==mColumns.mFaction) |     else if (column==mColumns.mFaction) | ||||||
|         record.get().mFaction = value.toString().toUtf8().constData(); |         npc.mFaction = value.toString().toUtf8().constData(); | ||||||
|     else if (column==mColumns.mHair) |     else if (column==mColumns.mHair) | ||||||
|         record.get().mHair = value.toString().toUtf8().constData(); |         npc.mHair = value.toString().toUtf8().constData(); | ||||||
|     else if (column==mColumns.mHead) |     else if (column==mColumns.mHead) | ||||||
|         record.get().mHead = value.toString().toUtf8().constData(); |         npc.mHead = value.toString().toUtf8().constData(); | ||||||
|     else |     else | ||||||
|     { |     { | ||||||
|         std::map<const RefIdColumn *, unsigned int>::const_iterator iter = |         std::map<const RefIdColumn *, unsigned int>::const_iterator iter = | ||||||
|  | @ -543,13 +624,23 @@ void CSMWorld::NpcRefIdAdapter::setData (const RefIdColumn *column, RefIdData& d | ||||||
|         if (iter!=mColumns.mFlags.end()) |         if (iter!=mColumns.mFlags.end()) | ||||||
|         { |         { | ||||||
|             if (value.toInt()!=0) |             if (value.toInt()!=0) | ||||||
|                 record.get().mFlags |= iter->second; |                 npc.mFlags |= iter->second; | ||||||
|             else |             else | ||||||
|                 record.get().mFlags &= ~iter->second; |                 npc.mFlags &= ~iter->second; | ||||||
|  | 
 | ||||||
|  |             if (iter->second == ESM::NPC::Autocalc) | ||||||
|  |                 npc.mNpdtType = (value.toInt() != 0) ? ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS | ||||||
|  |                                                      : ESM::NPC::NPC_DEFAULT; | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|  |         { | ||||||
|             ActorRefIdAdapter<ESM::NPC>::setData (column, data, index, value); |             ActorRefIdAdapter<ESM::NPC>::setData (column, data, index, value); | ||||||
|  | 
 | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     record.setModified (npc); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| CSMWorld::NpcAttributesRefIdAdapter::NpcAttributesRefIdAdapter () | CSMWorld::NpcAttributesRefIdAdapter::NpcAttributesRefIdAdapter () | ||||||
|  |  | ||||||
|  | @ -334,9 +334,9 @@ QVariant CSMWorld::RegionMap::data (const QModelIndex& index, int role) const | ||||||
|                 mColours.find (Misc::StringUtils::lowerCase (cell->second.mRegion)); |                 mColours.find (Misc::StringUtils::lowerCase (cell->second.mRegion)); | ||||||
| 
 | 
 | ||||||
|             if (iter!=mColours.end()) |             if (iter!=mColours.end()) | ||||||
|                 return QBrush ( |                 return QBrush (QColor (iter->second & 0xff,  | ||||||
|                     QColor (iter->second>>24, (iter->second>>16) & 255, (iter->second>>8) & 255, |                                        (iter->second >> 8) & 0xff,  | ||||||
|                     iter->second & 255)); |                                        (iter->second >> 16) & 0xff)); | ||||||
| 
 | 
 | ||||||
|             if (cell->second.mRegion.empty()) |             if (cell->second.mRegion.empty()) | ||||||
|                 return QBrush (Qt::Dense6Pattern); // no region
 |                 return QBrush (Qt::Dense6Pattern); // no region
 | ||||||
|  |  | ||||||
|  | @ -33,6 +33,11 @@ void CSVDoc::FileDialog::addFiles(const QString &path) | ||||||
|     mSelector->addFiles(path); |     mSelector->addFiles(path); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void CSVDoc::FileDialog::clearFiles() | ||||||
|  | { | ||||||
|  |     mSelector->clearFiles(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| QStringList CSVDoc::FileDialog::selectedFilePaths() | QStringList CSVDoc::FileDialog::selectedFilePaths() | ||||||
| { | { | ||||||
|     QStringList filePaths; |     QStringList filePaths; | ||||||
|  | @ -105,7 +110,6 @@ void CSVDoc::FileDialog::buildNewFileView() | ||||||
| 
 | 
 | ||||||
|         connect (mFileWidget, SIGNAL (nameChanged(const QString &, bool)), |         connect (mFileWidget, SIGNAL (nameChanged(const QString &, bool)), | ||||||
|                 this, SLOT (slotUpdateAcceptButton(const QString &, bool))); |                 this, SLOT (slotUpdateAcceptButton(const QString &, bool))); | ||||||
| 
 |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     ui.projectGroupBoxLayout->insertWidget (0, mFileWidget); |     ui.projectGroupBoxLayout->insertWidget (0, mFileWidget); | ||||||
|  | @ -139,7 +143,7 @@ void CSVDoc::FileDialog::slotUpdateAcceptButton(int) | ||||||
| { | { | ||||||
|     QString name = ""; |     QString name = ""; | ||||||
| 
 | 
 | ||||||
|     if (mAction == ContentAction_New) |     if (mFileWidget && mAction == ContentAction_New) | ||||||
|         name = mFileWidget->getName(); |         name = mFileWidget->getName(); | ||||||
| 
 | 
 | ||||||
|     slotUpdateAcceptButton (name, true); |     slotUpdateAcceptButton (name, true); | ||||||
|  |  | ||||||
|  | @ -45,6 +45,7 @@ namespace CSVDoc | ||||||
|         void showDialog (ContentAction action); |         void showDialog (ContentAction action); | ||||||
| 
 | 
 | ||||||
|         void addFiles (const QString &path); |         void addFiles (const QString &path); | ||||||
|  |         void clearFiles (); | ||||||
| 
 | 
 | ||||||
|         QString filename() const; |         QString filename() const; | ||||||
|         QStringList selectedFilePaths(); |         QStringList selectedFilePaths(); | ||||||
|  |  | ||||||
|  | @ -7,7 +7,7 @@ | ||||||
| #include <QMenuBar> | #include <QMenuBar> | ||||||
| #include <QMdiArea> | #include <QMdiArea> | ||||||
| #include <QDockWidget> | #include <QDockWidget> | ||||||
| #include <QtGui/QApplication> | #include <QApplication> | ||||||
| #include <QDesktopWidget> | #include <QDesktopWidget> | ||||||
| #include <QScrollArea> | #include <QScrollArea> | ||||||
| #include <QHBoxLayout> | #include <QHBoxLayout> | ||||||
|  | @ -546,6 +546,10 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if (mScroll) | ||||||
|  |         QObject::connect(mScroll->horizontalScrollBar(), | ||||||
|  |             SIGNAL(rangeChanged(int,int)), this, SLOT(moveScrollBarToEnd(int,int))); | ||||||
|  | 
 | ||||||
|     // User setting for limiting the number of sub views per top level view.
 |     // User setting for limiting the number of sub views per top level view.
 | ||||||
|     // Automatically open a new top level view if this number is exceeded
 |     // Automatically open a new top level view if this number is exceeded
 | ||||||
|     //
 |     //
 | ||||||
|  | @ -617,12 +621,6 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin | ||||||
|             mSubViewWindow.setMinimumWidth(mSubViewWindow.width()+minWidth); |             mSubViewWindow.setMinimumWidth(mSubViewWindow.width()+minWidth); | ||||||
|             move(0, y()); |             move(0, y()); | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|         // Make the new subview visible, setFocus() or raise() don't seem to work
 |  | ||||||
|         // On Ubuntu the scrollbar does not go right to the end, even if using
 |  | ||||||
|         // mScroll->horizontalScrollBar()->setValue(mScroll->horizontalScrollBar()->maximum());
 |  | ||||||
|         if (mSubViewWindow.width() > rect.width()) |  | ||||||
|             mScroll->horizontalScrollBar()->setValue(mSubViewWindow.width()); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     mSubViewWindow.addDockWidget (Qt::TopDockWidgetArea, view); |     mSubViewWindow.addDockWidget (Qt::TopDockWidgetArea, view); | ||||||
|  | @ -645,6 +643,17 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin | ||||||
|         view->useHint (hint); |         view->useHint (hint); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void CSVDoc::View::moveScrollBarToEnd(int min, int max) | ||||||
|  | { | ||||||
|  |     if (mScroll) | ||||||
|  |     { | ||||||
|  |         mScroll->horizontalScrollBar()->setValue(max); | ||||||
|  | 
 | ||||||
|  |         QObject::disconnect(mScroll->horizontalScrollBar(), | ||||||
|  |             SIGNAL(rangeChanged(int,int)), this, SLOT(moveScrollBarToEnd(int,int))); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void CSVDoc::View::newView() | void CSVDoc::View::newView() | ||||||
| { | { | ||||||
|     mViewManager.addView (mDocument); |     mViewManager.addView (mDocument); | ||||||
|  |  | ||||||
|  | @ -243,6 +243,8 @@ namespace CSVDoc | ||||||
|             void closeRequest (SubView *subView); |             void closeRequest (SubView *subView); | ||||||
| 
 | 
 | ||||||
|             void saveWindowState(); |             void saveWindowState(); | ||||||
|  | 
 | ||||||
|  |             void moveScrollBarToEnd(int min, int max); | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -6,6 +6,8 @@ | ||||||
| 
 | 
 | ||||||
| #include <QApplication> | #include <QApplication> | ||||||
| #include <QDesktopWidget> | #include <QDesktopWidget> | ||||||
|  | #include <QMessageBox> | ||||||
|  | #include <QPushButton> | ||||||
| 
 | 
 | ||||||
| #include "../../model/doc/documentmanager.hpp" | #include "../../model/doc/documentmanager.hpp" | ||||||
| #include "../../model/doc/document.hpp" | #include "../../model/doc/document.hpp" | ||||||
|  | @ -19,15 +21,12 @@ | ||||||
| #include "../world/recordstatusdelegate.hpp" | #include "../world/recordstatusdelegate.hpp" | ||||||
| #include "../world/idtypedelegate.hpp" | #include "../world/idtypedelegate.hpp" | ||||||
| #include "../world/idcompletiondelegate.hpp" | #include "../world/idcompletiondelegate.hpp" | ||||||
|  | #include "../world/colordelegate.hpp" | ||||||
| 
 | 
 | ||||||
| #include "../../model/settings/usersettings.hpp" | #include "../../model/settings/usersettings.hpp" | ||||||
| 
 | 
 | ||||||
| #include "view.hpp" | #include "view.hpp" | ||||||
| 
 | 
 | ||||||
| #include <QMessageBox> |  | ||||||
| #include <QPushButton> |  | ||||||
| #include <QtGui/QApplication> |  | ||||||
| 
 |  | ||||||
| void CSVDoc::ViewManager::updateIndices() | void CSVDoc::ViewManager::updateIndices() | ||||||
| { | { | ||||||
|     std::map<CSMDoc::Document *, std::pair<int, int> > documents; |     std::map<CSMDoc::Document *, std::pair<int, int> > documents; | ||||||
|  | @ -63,6 +62,9 @@ CSVDoc::ViewManager::ViewManager (CSMDoc::DocumentManager& documentManager) | ||||||
|     mDelegateFactories->add (CSMWorld::ColumnBase::Display_RefRecordType, |     mDelegateFactories->add (CSMWorld::ColumnBase::Display_RefRecordType, | ||||||
|         new CSVWorld::IdTypeDelegateFactory()); |         new CSVWorld::IdTypeDelegateFactory()); | ||||||
| 
 | 
 | ||||||
|  |     mDelegateFactories->add (CSMWorld::ColumnBase::Display_Colour, | ||||||
|  |         new CSVWorld::ColorDelegateFactory()); | ||||||
|  | 
 | ||||||
|     std::vector<CSMWorld::ColumnBase::Display> idCompletionColumns = CSMWorld::IdCompletionManager::getDisplayTypes(); |     std::vector<CSMWorld::ColumnBase::Display> idCompletionColumns = CSMWorld::IdCompletionManager::getDisplayTypes(); | ||||||
|     for (std::vector<CSMWorld::ColumnBase::Display>::const_iterator current = idCompletionColumns.begin(); |     for (std::vector<CSMWorld::ColumnBase::Display>::const_iterator current = idCompletionColumns.begin(); | ||||||
|          current != idCompletionColumns.end(); |          current != idCompletionColumns.end(); | ||||||
|  |  | ||||||
|  | @ -6,7 +6,7 @@ | ||||||
| #include <OgreColourValue.h> | #include <OgreColourValue.h> | ||||||
| #include <OgreCamera.h> | #include <OgreCamera.h> | ||||||
| 
 | 
 | ||||||
| #include <QtGui/qevent.h> | #include <QEvent> | ||||||
| 
 | 
 | ||||||
| #include "../../model/doc/document.hpp" | #include "../../model/doc/document.hpp" | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -7,7 +7,12 @@ | ||||||
| #include <OgreSceneManager.h> | #include <OgreSceneManager.h> | ||||||
| #include <OgreEntity.h> | #include <OgreEntity.h> | ||||||
| 
 | 
 | ||||||
| #include <QtGui/qevent.h> | #include <QEvent> | ||||||
|  | #include <QDragEnterEvent> | ||||||
|  | #include <QDragMoveEvent> | ||||||
|  | #include <QDropEvent> | ||||||
|  | #include <QMouseEvent> | ||||||
|  | #include <QKeyEvent> | ||||||
| 
 | 
 | ||||||
| #include "../../model/world/universalid.hpp" | #include "../../model/world/universalid.hpp" | ||||||
| #include "../../model/world/idtable.hpp" | #include "../../model/world/idtable.hpp" | ||||||
|  |  | ||||||
|  | @ -8,19 +8,12 @@ | ||||||
| #include <QStackedWidget> | #include <QStackedWidget> | ||||||
| #include <QtGui> | #include <QtGui> | ||||||
| #include <QSplitter> | #include <QSplitter> | ||||||
|  | #include <QDesktopWidget> | ||||||
| 
 | 
 | ||||||
| #include "../../model/settings/usersettings.hpp" | #include "../../model/settings/usersettings.hpp" | ||||||
| 
 | 
 | ||||||
| #include "page.hpp" | #include "page.hpp" | ||||||
| 
 | 
 | ||||||
| #include <QApplication> |  | ||||||
| 
 |  | ||||||
| #include <QTreeView> |  | ||||||
| #include <QListView> |  | ||||||
| #include <QTableView> |  | ||||||
| 
 |  | ||||||
| #include <QStandardItemModel> |  | ||||||
| #include <QStandardItem> |  | ||||||
| 
 | 
 | ||||||
| CSVSettings::Dialog::Dialog(QMainWindow *parent) | CSVSettings::Dialog::Dialog(QMainWindow *parent) | ||||||
|     : SettingWindow (parent), mStackedWidget (0), mDebugMode (false) |     : SettingWindow (parent), mStackedWidget (0), mDebugMode (false) | ||||||
|  |  | ||||||
|  | @ -3,7 +3,6 @@ | ||||||
| 
 | 
 | ||||||
| #include "settingwindow.hpp" | #include "settingwindow.hpp" | ||||||
| #include "resizeablestackedwidget.hpp" | #include "resizeablestackedwidget.hpp" | ||||||
| #include <QStandardItem> |  | ||||||
| 
 | 
 | ||||||
| class QStackedWidget; | class QStackedWidget; | ||||||
| class QListWidget; | class QListWidget; | ||||||
|  | @ -26,10 +25,6 @@ namespace CSVSettings { | ||||||
| 
 | 
 | ||||||
|         explicit Dialog (QMainWindow *parent = 0); |         explicit Dialog (QMainWindow *parent = 0); | ||||||
| 
 | 
 | ||||||
|         ///Enables setting debug mode.  When the dialog opens, a page is created
 |  | ||||||
|         ///which displays the SettingModel's contents in a Tree view.
 |  | ||||||
|         void enableDebugMode (bool state, QStandardItemModel *model = 0); |  | ||||||
| 
 |  | ||||||
|     protected: |     protected: | ||||||
| 
 | 
 | ||||||
|         /// Settings are written on close
 |         /// Settings are written on close
 | ||||||
|  |  | ||||||
|  | @ -9,6 +9,8 @@ | ||||||
| #include <QStyledItemDelegate> | #include <QStyledItemDelegate> | ||||||
| #include <QTextDocument> | #include <QTextDocument> | ||||||
| #include <QPainter> | #include <QPainter> | ||||||
|  | #include <QContextMenuEvent> | ||||||
|  | #include <QMouseEvent> | ||||||
| 
 | 
 | ||||||
| #include "../../model/tools/reportmodel.hpp" | #include "../../model/tools/reportmodel.hpp" | ||||||
| 
 | 
 | ||||||
|  | @ -94,21 +96,35 @@ void CSVTools::ReportTable::mouseDoubleClickEvent (QMouseEvent *event) | ||||||
|     selectionModel()->select (index, |     selectionModel()->select (index, | ||||||
|         QItemSelectionModel::Clear | QItemSelectionModel::Select | QItemSelectionModel::Rows); |         QItemSelectionModel::Clear | QItemSelectionModel::Select | QItemSelectionModel::Rows); | ||||||
| 
 | 
 | ||||||
|     switch (modifiers) |     std::map<Qt::KeyboardModifiers, DoubleClickAction>::iterator iter = | ||||||
|  |         mDoubleClickActions.find (modifiers); | ||||||
|  | 
 | ||||||
|  |     if (iter==mDoubleClickActions.end()) | ||||||
|     { |     { | ||||||
|         case 0: |         event->accept(); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |          | ||||||
|  |     switch (iter->second) | ||||||
|  |     { | ||||||
|  |         case Action_None: | ||||||
|  | 
 | ||||||
|  |             event->accept(); | ||||||
|  |             break; | ||||||
|  |              | ||||||
|  |         case Action_Edit: | ||||||
| 
 | 
 | ||||||
|             event->accept(); |             event->accept(); | ||||||
|             showSelection(); |             showSelection(); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case Qt::ShiftModifier: |         case Action_Remove: | ||||||
| 
 | 
 | ||||||
|             event->accept(); |             event->accept(); | ||||||
|             removeSelection(); |             removeSelection(); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case Qt::ControlModifier: |         case Action_EditAndRemove: | ||||||
| 
 | 
 | ||||||
|             event->accept(); |             event->accept(); | ||||||
|             showSelection(); |             showSelection(); | ||||||
|  | @ -121,7 +137,11 @@ CSVTools::ReportTable::ReportTable (CSMDoc::Document& document, | ||||||
|     const CSMWorld::UniversalId& id, bool richTextDescription, QWidget *parent) |     const CSMWorld::UniversalId& id, bool richTextDescription, QWidget *parent) | ||||||
| : CSVWorld::DragRecordTable (document, parent), mModel (document.getReport (id)) | : CSVWorld::DragRecordTable (document, parent), mModel (document.getReport (id)) | ||||||
| { | { | ||||||
|  | #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) | ||||||
|  |     horizontalHeader()->setSectionResizeMode (QHeaderView::Interactive); | ||||||
|  | #else | ||||||
|     horizontalHeader()->setResizeMode (QHeaderView::Interactive); |     horizontalHeader()->setResizeMode (QHeaderView::Interactive); | ||||||
|  | #endif | ||||||
|     horizontalHeader()->setStretchLastSection (true); |     horizontalHeader()->setStretchLastSection (true); | ||||||
|     verticalHeader()->hide(); |     verticalHeader()->hide(); | ||||||
|     setSortingEnabled (true); |     setSortingEnabled (true); | ||||||
|  | @ -149,7 +169,11 @@ CSVTools::ReportTable::ReportTable (CSMDoc::Document& document, | ||||||
| 
 | 
 | ||||||
|     mReplaceAction = new QAction (tr ("Replace"), this); |     mReplaceAction = new QAction (tr ("Replace"), this); | ||||||
|     connect (mReplaceAction, SIGNAL (triggered()), this, SIGNAL (replaceRequest())); |     connect (mReplaceAction, SIGNAL (triggered()), this, SIGNAL (replaceRequest())); | ||||||
|     addAction (mReplaceAction);     |     addAction (mReplaceAction); | ||||||
|  | 
 | ||||||
|  |     mDoubleClickActions.insert (std::make_pair (Qt::NoModifier, Action_Edit)); | ||||||
|  |     mDoubleClickActions.insert (std::make_pair (Qt::ShiftModifier, Action_Remove)); | ||||||
|  |     mDoubleClickActions.insert (std::make_pair (Qt::ControlModifier, Action_EditAndRemove));     | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::vector<CSMWorld::UniversalId> CSVTools::ReportTable::getDraggedRecords() const | std::vector<CSMWorld::UniversalId> CSVTools::ReportTable::getDraggedRecords() const | ||||||
|  | @ -170,6 +194,35 @@ std::vector<CSMWorld::UniversalId> CSVTools::ReportTable::getDraggedRecords() co | ||||||
| void CSVTools::ReportTable::updateUserSetting (const QString& name, const QStringList& list) | void CSVTools::ReportTable::updateUserSetting (const QString& name, const QStringList& list) | ||||||
| { | { | ||||||
|     mIdTypeDelegate->updateUserSetting (name, list); |     mIdTypeDelegate->updateUserSetting (name, list); | ||||||
|  | 
 | ||||||
|  |     QString base ("report-input/double"); | ||||||
|  |     if (name.startsWith (base)) | ||||||
|  |     { | ||||||
|  |         QString modifierString = name.mid (base.size()); | ||||||
|  |         Qt::KeyboardModifiers modifiers = 0; | ||||||
|  | 
 | ||||||
|  |         if (modifierString=="-s") | ||||||
|  |             modifiers = Qt::ShiftModifier; | ||||||
|  |         else if (modifierString=="-c") | ||||||
|  |             modifiers = Qt::ControlModifier; | ||||||
|  |         else if (modifierString=="-sc") | ||||||
|  |             modifiers = Qt::ShiftModifier | Qt::ControlModifier; | ||||||
|  | 
 | ||||||
|  |         DoubleClickAction action = Action_None; | ||||||
|  | 
 | ||||||
|  |         QString value = list.at (0); | ||||||
|  | 
 | ||||||
|  |         if (value=="Edit") | ||||||
|  |             action = Action_Edit; | ||||||
|  |         else if (value=="Remove") | ||||||
|  |             action = Action_Remove; | ||||||
|  |         else if (value=="Edit And Remove") | ||||||
|  |             action = Action_EditAndRemove; | ||||||
|  | 
 | ||||||
|  |         mDoubleClickActions[modifiers] = action; | ||||||
|  | 
 | ||||||
|  |         return; | ||||||
|  |     }     | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| std::vector<int> CSVTools::ReportTable::getReplaceIndices (bool selection) const | std::vector<int> CSVTools::ReportTable::getReplaceIndices (bool selection) const | ||||||
|  |  | ||||||
|  | @ -1,6 +1,8 @@ | ||||||
| #ifndef CSV_TOOLS_REPORTTABLE_H | #ifndef CSV_TOOLS_REPORTTABLE_H | ||||||
| #define CSV_TOOLS_REPORTTABLE_H | #define CSV_TOOLS_REPORTTABLE_H | ||||||
| 
 | 
 | ||||||
|  | #include <map> | ||||||
|  | 
 | ||||||
| #include "../world/dragrecordtable.hpp" | #include "../world/dragrecordtable.hpp" | ||||||
| 
 | 
 | ||||||
| class QAction; | class QAction; | ||||||
|  | @ -21,11 +23,20 @@ namespace CSVTools | ||||||
|     { |     { | ||||||
|             Q_OBJECT |             Q_OBJECT | ||||||
| 
 | 
 | ||||||
|  |             enum DoubleClickAction | ||||||
|  |             { | ||||||
|  |                 Action_None, | ||||||
|  |                 Action_Edit, | ||||||
|  |                 Action_Remove, | ||||||
|  |                 Action_EditAndRemove | ||||||
|  |             }; | ||||||
|  |              | ||||||
|             CSMTools::ReportModel *mModel; |             CSMTools::ReportModel *mModel; | ||||||
|             CSVWorld::CommandDelegate *mIdTypeDelegate; |             CSVWorld::CommandDelegate *mIdTypeDelegate; | ||||||
|             QAction *mShowAction; |             QAction *mShowAction; | ||||||
|             QAction *mRemoveAction; |             QAction *mRemoveAction; | ||||||
|             QAction *mReplaceAction; |             QAction *mReplaceAction; | ||||||
|  |             std::map<Qt::KeyboardModifiers, DoubleClickAction> mDoubleClickActions; | ||||||
| 
 | 
 | ||||||
|         private: |         private: | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										113
									
								
								apps/opencs/view/widget/coloreditor.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										113
									
								
								apps/opencs/view/widget/coloreditor.cpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,113 @@ | ||||||
|  | #include "coloreditor.hpp" | ||||||
|  | 
 | ||||||
|  | #include <QApplication> | ||||||
|  | #include <QColor> | ||||||
|  | #include <QColorDialog> | ||||||
|  | #include <QDesktopWidget> | ||||||
|  | #include <QPainter> | ||||||
|  | #include <QRect> | ||||||
|  | #include <QShowEvent> | ||||||
|  | 
 | ||||||
|  | #include "colorpickerpopup.hpp" | ||||||
|  | 
 | ||||||
|  | CSVWidget::ColorEditor::ColorEditor(const QColor &color, QWidget *parent, bool popupOnStart) | ||||||
|  |     : QPushButton(parent), | ||||||
|  |       mColor(color), | ||||||
|  |       mColorPicker(new ColorPickerPopup(this)), | ||||||
|  |       mPopupOnStart(popupOnStart) | ||||||
|  | { | ||||||
|  |     setCheckable(true); | ||||||
|  |     connect(this, SIGNAL(clicked()), this, SLOT(showPicker())); | ||||||
|  |     connect(mColorPicker, SIGNAL(hid()), this, SLOT(pickerHid())); | ||||||
|  |     connect(mColorPicker, SIGNAL(colorChanged(const QColor &)), this, SLOT(pickerColorChanged(const QColor &))); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void CSVWidget::ColorEditor::paintEvent(QPaintEvent *event) | ||||||
|  | { | ||||||
|  |     QPushButton::paintEvent(event); | ||||||
|  | 
 | ||||||
|  |     QRect buttonRect = rect(); | ||||||
|  |     QRect coloredRect(buttonRect.x() + qRound(buttonRect.width() / 4.0), | ||||||
|  |                       buttonRect.y() + qRound(buttonRect.height() / 4.0), | ||||||
|  |                       buttonRect.width() / 2, | ||||||
|  |                       buttonRect.height() / 2); | ||||||
|  |     QPainter painter(this); | ||||||
|  |     painter.fillRect(coloredRect, mColor); | ||||||
|  |     painter.setPen(Qt::black); | ||||||
|  |     painter.drawRect(coloredRect); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void CSVWidget::ColorEditor::showEvent(QShowEvent *event) | ||||||
|  | { | ||||||
|  |     QPushButton::showEvent(event); | ||||||
|  |     if (isVisible() && mPopupOnStart) | ||||||
|  |     { | ||||||
|  |         setChecked(true); | ||||||
|  |         showPicker(); | ||||||
|  |         mPopupOnStart = false; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | QColor CSVWidget::ColorEditor::color() const | ||||||
|  | { | ||||||
|  |     return mColor; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void CSVWidget::ColorEditor::setColor(const QColor &color) | ||||||
|  | { | ||||||
|  |     mColor = color; | ||||||
|  |     update(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void CSVWidget::ColorEditor::showPicker() | ||||||
|  | { | ||||||
|  |     if (isChecked()) | ||||||
|  |     { | ||||||
|  |         mColorPicker->showPicker(calculatePopupPosition(), mColor); | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         mColorPicker->hide(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void CSVWidget::ColorEditor::pickerHid() | ||||||
|  | { | ||||||
|  |     setChecked(false); | ||||||
|  |     emit pickingFinished(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void CSVWidget::ColorEditor::pickerColorChanged(const QColor &color) | ||||||
|  | { | ||||||
|  |     mColor = color; | ||||||
|  |     update(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | QPoint CSVWidget::ColorEditor::calculatePopupPosition() | ||||||
|  | { | ||||||
|  |     QRect editorGeometry = geometry(); | ||||||
|  |     QRect popupGeometry = mColorPicker->geometry(); | ||||||
|  |     QRect screenGeometry = QApplication::desktop()->screenGeometry(); | ||||||
|  | 
 | ||||||
|  |     // Center the popup horizontally relative to the editor
 | ||||||
|  |     int localPopupX = (editorGeometry.width() - popupGeometry.width()) / 2; | ||||||
|  |     // Popup position need to be specified in global coords
 | ||||||
|  |     QPoint popupPosition = mapToGlobal(QPoint(localPopupX, editorGeometry.height())); | ||||||
|  | 
 | ||||||
|  |     // Make sure that the popup isn't out of the screen
 | ||||||
|  |     if (popupPosition.x() < screenGeometry.left()) | ||||||
|  |     { | ||||||
|  |         popupPosition.setX(screenGeometry.left() + 1); | ||||||
|  |     } | ||||||
|  |     else if (popupPosition.x() + popupGeometry.width() > screenGeometry.right()) | ||||||
|  |     { | ||||||
|  |         popupPosition.setX(screenGeometry.right() - popupGeometry.width() - 1); | ||||||
|  |     } | ||||||
|  |     if (popupPosition.y() + popupGeometry.height() > screenGeometry.bottom()) | ||||||
|  |     { | ||||||
|  |         // Place the popup above the editor
 | ||||||
|  |         popupPosition.setY(popupPosition.y() - popupGeometry.height() - editorGeometry.height() - 1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return popupPosition; | ||||||
|  | } | ||||||
							
								
								
									
										44
									
								
								apps/opencs/view/widget/coloreditor.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								apps/opencs/view/widget/coloreditor.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,44 @@ | ||||||
|  | #ifndef CSV_WIDGET_COLOREDITOR_HPP | ||||||
|  | #define CSV_WIDGET_COLOREDITOR_HPP | ||||||
|  | 
 | ||||||
|  | #include <QPushButton> | ||||||
|  | 
 | ||||||
|  | class QColor; | ||||||
|  | class QPoint; | ||||||
|  | class QSize; | ||||||
|  | 
 | ||||||
|  | namespace CSVWidget | ||||||
|  | { | ||||||
|  |     class ColorPickerPopup; | ||||||
|  | 
 | ||||||
|  |     class ColorEditor : public QPushButton | ||||||
|  |     { | ||||||
|  |             Q_OBJECT | ||||||
|  | 
 | ||||||
|  |             QColor mColor; | ||||||
|  |             ColorPickerPopup *mColorPicker; | ||||||
|  |             bool mPopupOnStart; | ||||||
|  | 
 | ||||||
|  |             QPoint calculatePopupPosition(); | ||||||
|  | 
 | ||||||
|  |         public: | ||||||
|  |             ColorEditor(const QColor &color, QWidget *parent = 0, bool popupOnStart = false); | ||||||
|  | 
 | ||||||
|  |             QColor color() const; | ||||||
|  |             void setColor(const QColor &color); | ||||||
|  | 
 | ||||||
|  |         protected: | ||||||
|  |             virtual void paintEvent(QPaintEvent *event); | ||||||
|  |             virtual void showEvent(QShowEvent *event); | ||||||
|  | 
 | ||||||
|  |         private slots: | ||||||
|  |             void showPicker(); | ||||||
|  |             void pickerHid(); | ||||||
|  |             void pickerColorChanged(const QColor &color); | ||||||
|  | 
 | ||||||
|  |         signals: | ||||||
|  |             void pickingFinished(); | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
							
								
								
									
										86
									
								
								apps/opencs/view/widget/colorpickerpopup.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								apps/opencs/view/widget/colorpickerpopup.cpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,86 @@ | ||||||
|  | #include "colorpickerpopup.hpp" | ||||||
|  | 
 | ||||||
|  | #include <QColorDialog> | ||||||
|  | #include <QPushButton> | ||||||
|  | #include <QEvent> | ||||||
|  | #include <QKeyEvent> | ||||||
|  | #include <QMouseEvent> | ||||||
|  | #include <QLayout> | ||||||
|  | #include <QStyleOption> | ||||||
|  | 
 | ||||||
|  | CSVWidget::ColorPickerPopup::ColorPickerPopup(QWidget *parent)  | ||||||
|  |     : QFrame(parent) | ||||||
|  | { | ||||||
|  |     setWindowFlags(Qt::Popup); | ||||||
|  |     setFrameStyle(QFrame::Box | QFrame::Plain); | ||||||
|  |     hide(); | ||||||
|  | 
 | ||||||
|  |     mColorPicker = new QColorDialog(this); | ||||||
|  |     mColorPicker->setWindowFlags(Qt::Widget); | ||||||
|  |     mColorPicker->setOptions(QColorDialog::NoButtons | QColorDialog::DontUseNativeDialog); | ||||||
|  |     mColorPicker->installEventFilter(this); | ||||||
|  |     mColorPicker->open(); | ||||||
|  |     connect(mColorPicker, | ||||||
|  |             SIGNAL(currentColorChanged(const QColor &)), | ||||||
|  |             this, | ||||||
|  |             SIGNAL(colorChanged(const QColor &))); | ||||||
|  | 
 | ||||||
|  |     QVBoxLayout *layout = new QVBoxLayout(this); | ||||||
|  |     layout->addWidget(mColorPicker); | ||||||
|  |     layout->setAlignment(Qt::AlignTop | Qt::AlignLeft); | ||||||
|  |     layout->setContentsMargins(0, 0, 0, 0); | ||||||
|  |     setLayout(layout); | ||||||
|  |     setFixedSize(mColorPicker->size()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void CSVWidget::ColorPickerPopup::showPicker(const QPoint &position, const QColor &initialColor) | ||||||
|  | { | ||||||
|  |     QRect geometry = this->geometry(); | ||||||
|  |     geometry.moveTo(position); | ||||||
|  |     setGeometry(geometry); | ||||||
|  | 
 | ||||||
|  |     mColorPicker->setCurrentColor(initialColor); | ||||||
|  |     show(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void CSVWidget::ColorPickerPopup::mousePressEvent(QMouseEvent *event) | ||||||
|  | { | ||||||
|  |     QPushButton *button = qobject_cast<QPushButton *>(parentWidget()); | ||||||
|  |     if (button != NULL) | ||||||
|  |     { | ||||||
|  |         QStyleOptionButton option; | ||||||
|  |         option.init(button); | ||||||
|  |         QRect buttonRect = option.rect; | ||||||
|  |         buttonRect.moveTo(button->mapToGlobal(buttonRect.topLeft())); | ||||||
|  | 
 | ||||||
|  |         // If the mouse is pressed above the pop-up parent,
 | ||||||
|  |         // the pop-up will be hidden and the pressed signal won't be repeated for the parent
 | ||||||
|  |         if (buttonRect.contains(event->globalPos()) || buttonRect.contains(event->pos())) | ||||||
|  |         { | ||||||
|  |             setAttribute(Qt::WA_NoMouseReplay); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     QFrame::mousePressEvent(event); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void CSVWidget::ColorPickerPopup::hideEvent(QHideEvent *event) | ||||||
|  | { | ||||||
|  |     QFrame::hideEvent(event); | ||||||
|  |     emit hid(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | bool CSVWidget::ColorPickerPopup::eventFilter(QObject *object, QEvent *event) | ||||||
|  | { | ||||||
|  |     if (object == mColorPicker && event->type() == QEvent::KeyPress) | ||||||
|  |     { | ||||||
|  |         QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event); | ||||||
|  |         // Prevent QColorDialog from closing when Escape is pressed.
 | ||||||
|  |         // Instead, hide the popup.
 | ||||||
|  |         if (keyEvent->key() == Qt::Key_Escape) | ||||||
|  |         { | ||||||
|  |             hide(); | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return QFrame::eventFilter(object, event); | ||||||
|  | } | ||||||
							
								
								
									
										32
									
								
								apps/opencs/view/widget/colorpickerpopup.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								apps/opencs/view/widget/colorpickerpopup.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,32 @@ | ||||||
|  | #ifndef CSVWIDGET_COLORPICKERPOPUP_HPP | ||||||
|  | #define CSVWIDGET_COLORPICKERPOPUP_HPP | ||||||
|  | 
 | ||||||
|  | #include <QFrame> | ||||||
|  | 
 | ||||||
|  | class QColorDialog; | ||||||
|  | 
 | ||||||
|  | namespace CSVWidget | ||||||
|  | { | ||||||
|  |     class ColorPickerPopup : public QFrame | ||||||
|  |     { | ||||||
|  |         Q_OBJECT | ||||||
|  | 
 | ||||||
|  |         QColorDialog *mColorPicker; | ||||||
|  | 
 | ||||||
|  |     public: | ||||||
|  |         explicit ColorPickerPopup(QWidget *parent); | ||||||
|  |      | ||||||
|  |         void showPicker(const QPoint &position, const QColor &initialColor); | ||||||
|  | 
 | ||||||
|  |     protected: | ||||||
|  |         virtual void mousePressEvent(QMouseEvent *event); | ||||||
|  |         virtual void hideEvent(QHideEvent *event); | ||||||
|  |         virtual bool eventFilter(QObject *object, QEvent *event); | ||||||
|  | 
 | ||||||
|  |     signals: | ||||||
|  |         void hid(); | ||||||
|  |         void colorChanged(const QColor &color); | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -65,8 +65,13 @@ CSVWidget::SceneToolRun::SceneToolRun (SceneToolbar *parent, const QString& tool | ||||||
|     mTable->setShowGrid (false); |     mTable->setShowGrid (false); | ||||||
|     mTable->verticalHeader()->hide(); |     mTable->verticalHeader()->hide(); | ||||||
|     mTable->horizontalHeader()->hide(); |     mTable->horizontalHeader()->hide(); | ||||||
|  | #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) | ||||||
|  |     mTable->horizontalHeader()->setSectionResizeMode (0, QHeaderView::Stretch); | ||||||
|  |     mTable->horizontalHeader()->setSectionResizeMode (1, QHeaderView::ResizeToContents); | ||||||
|  | #else | ||||||
|     mTable->horizontalHeader()->setResizeMode (0, QHeaderView::Stretch); |     mTable->horizontalHeader()->setResizeMode (0, QHeaderView::Stretch); | ||||||
|     mTable->horizontalHeader()->setResizeMode (1, QHeaderView::ResizeToContents); |     mTable->horizontalHeader()->setResizeMode (1, QHeaderView::ResizeToContents); | ||||||
|  | #endif | ||||||
|     mTable->setSelectionMode (QAbstractItemView::NoSelection); |     mTable->setSelectionMode (QAbstractItemView::NoSelection); | ||||||
| 
 | 
 | ||||||
|     layout->addWidget (mTable); |     layout->addWidget (mTable); | ||||||
|  |  | ||||||
							
								
								
									
										36
									
								
								apps/opencs/view/world/colordelegate.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								apps/opencs/view/world/colordelegate.cpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,36 @@ | ||||||
|  | #include "colordelegate.hpp" | ||||||
|  | 
 | ||||||
|  | #include <QPainter> | ||||||
|  | #include <QPushButton> | ||||||
|  | 
 | ||||||
|  | #include "../widget/coloreditor.hpp" | ||||||
|  | 
 | ||||||
|  | CSVWorld::ColorDelegate::ColorDelegate(CSMWorld::CommandDispatcher *dispatcher,  | ||||||
|  |                                        CSMDoc::Document& document,  | ||||||
|  |                                        QObject *parent) | ||||||
|  |     : CommandDelegate(dispatcher, document, parent) | ||||||
|  | {} | ||||||
|  | 
 | ||||||
|  | void CSVWorld::ColorDelegate::paint(QPainter *painter,  | ||||||
|  |                                     const QStyleOptionViewItem &option, | ||||||
|  |                                     const QModelIndex &index) const | ||||||
|  | { | ||||||
|  |     QRect coloredRect(option.rect.x() + qRound(option.rect.width() / 4.0), | ||||||
|  |                       option.rect.y() + qRound(option.rect.height() / 4.0), | ||||||
|  |                       option.rect.width() / 2, | ||||||
|  |                       option.rect.height() / 2); | ||||||
|  |     painter->save(); | ||||||
|  |     painter->fillRect(coloredRect, index.data().value<QColor>()); | ||||||
|  |     painter->setPen(Qt::black); | ||||||
|  |     painter->drawRect(coloredRect); | ||||||
|  |     painter->restore(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | CSVWorld::CommandDelegate *CSVWorld::ColorDelegateFactory::makeDelegate(CSMWorld::CommandDispatcher *dispatcher,  | ||||||
|  |                                                                         CSMDoc::Document &document,  | ||||||
|  |                                                                         QObject *parent) const | ||||||
|  | { | ||||||
|  |     return new ColorDelegate(dispatcher, document, parent); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
							
								
								
									
										37
									
								
								apps/opencs/view/world/colordelegate.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								apps/opencs/view/world/colordelegate.hpp
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | ||||||
|  | #ifndef CSV_WORLD_COLORDELEGATE_HPP | ||||||
|  | #define CSV_WORLD_COLORDELEGATE_HPP | ||||||
|  | 
 | ||||||
|  | #include "util.hpp" | ||||||
|  | 
 | ||||||
|  | class QRect; | ||||||
|  | 
 | ||||||
|  | namespace CSVWidget | ||||||
|  | { | ||||||
|  |     class ColorEditButton; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | namespace CSVWorld | ||||||
|  | { | ||||||
|  |     class ColorDelegate : public CommandDelegate | ||||||
|  |     { | ||||||
|  |         public: | ||||||
|  |             ColorDelegate(CSMWorld::CommandDispatcher *dispatcher,  | ||||||
|  |                           CSMDoc::Document& document,  | ||||||
|  |                           QObject *parent); | ||||||
|  | 
 | ||||||
|  |             virtual void paint(QPainter *painter,  | ||||||
|  |                                const QStyleOptionViewItem &option, | ||||||
|  |                                const QModelIndex &index) const; | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     class ColorDelegateFactory : public CommandDelegateFactory | ||||||
|  |     { | ||||||
|  |         public: | ||||||
|  |             virtual CommandDelegate *makeDelegate(CSMWorld::CommandDispatcher *dispatcher,  | ||||||
|  |                                                   CSMDoc::Document &document,  | ||||||
|  |                                                   QObject *parent) const; | ||||||
|  |             ///< The ownership of the returned CommandDelegate is transferred to the caller.
 | ||||||
|  |     }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | #endif | ||||||
|  | @ -12,11 +12,10 @@ CSVWorld::DataDisplayDelegate::DataDisplayDelegate(const ValueList &values, | ||||||
|                                                    const QString &settingName, |                                                    const QString &settingName, | ||||||
|                                                    QObject *parent) |                                                    QObject *parent) | ||||||
|     : EnumDelegate (values, dispatcher, document, parent), mDisplayMode (Mode_TextOnly), |     : EnumDelegate (values, dispatcher, document, parent), mDisplayMode (Mode_TextOnly), | ||||||
|       mIcons (icons), mIconSize (QSize(16, 16)), mIconLeftOffset(3), |       mIcons (icons), mIconSize (QSize(16, 16)), | ||||||
|  |       mHorizontalMargin(QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1), | ||||||
|       mTextLeftOffset(8), mSettingKey (pageName + '/' + settingName) |       mTextLeftOffset(8), mSettingKey (pageName + '/' + settingName) | ||||||
| { | { | ||||||
|     mTextAlignment.setAlignment (Qt::AlignLeft | Qt::AlignVCenter ); |  | ||||||
| 
 |  | ||||||
|     buildPixmaps(); |     buildPixmaps(); | ||||||
| 
 | 
 | ||||||
|     QString value = |     QString value = | ||||||
|  | @ -45,16 +44,35 @@ void CSVWorld::DataDisplayDelegate::setIconSize(const QSize& size) | ||||||
|     buildPixmaps(); |     buildPixmaps(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CSVWorld::DataDisplayDelegate::setIconLeftOffset(int offset) |  | ||||||
| { |  | ||||||
|     mIconLeftOffset = offset; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void CSVWorld::DataDisplayDelegate::setTextLeftOffset(int offset) | void CSVWorld::DataDisplayDelegate::setTextLeftOffset(int offset) | ||||||
| { | { | ||||||
|     mTextLeftOffset = offset; |     mTextLeftOffset = offset; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | QSize CSVWorld::DataDisplayDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const | ||||||
|  | { | ||||||
|  |     QSize size = EnumDelegate::sizeHint(option, index); | ||||||
|  |      | ||||||
|  |     int valueIndex = getValueIndex(index); | ||||||
|  |     if (valueIndex != -1) | ||||||
|  |     { | ||||||
|  |         if (mDisplayMode == Mode_IconOnly) | ||||||
|  |         { | ||||||
|  |             size.setWidth(mIconSize.width() + 2 * mHorizontalMargin); | ||||||
|  |         } | ||||||
|  |         else if (mDisplayMode == Mode_IconAndText) | ||||||
|  |         { | ||||||
|  |             size.setWidth(size.width() + mIconSize.width() + mTextLeftOffset); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (mDisplayMode != Mode_TextOnly) | ||||||
|  |         { | ||||||
|  |             size.setHeight(qMax(size.height(), mIconSize.height())); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return size; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void CSVWorld::DataDisplayDelegate::paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const | void CSVWorld::DataDisplayDelegate::paint (QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const | ||||||
| { | { | ||||||
|     painter->save(); |     painter->save(); | ||||||
|  | @ -64,16 +82,11 @@ void CSVWorld::DataDisplayDelegate::paint (QPainter *painter, const QStyleOption | ||||||
|         EnumDelegate::paint(painter, option, index); |         EnumDelegate::paint(painter, option, index); | ||||||
|     else |     else | ||||||
|     { |     { | ||||||
|         unsigned int i = 0; |         int valueIndex = getValueIndex(index); | ||||||
| 
 |         if (valueIndex != -1) | ||||||
|         for (; i < mValues.size(); ++i) |  | ||||||
|         { |         { | ||||||
|             if (mValues.at(i).first == index.data().toInt()) |             paintIcon(painter, option, valueIndex); | ||||||
|                 break; |  | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|         if (i < mValues.size() ) |  | ||||||
|             paintIcon (painter, option, i); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     painter->restore(); |     painter->restore(); | ||||||
|  | @ -81,24 +94,28 @@ void CSVWorld::DataDisplayDelegate::paint (QPainter *painter, const QStyleOption | ||||||
| 
 | 
 | ||||||
| void CSVWorld::DataDisplayDelegate::paintIcon (QPainter *painter, const QStyleOptionViewItem &option, int index) const | void CSVWorld::DataDisplayDelegate::paintIcon (QPainter *painter, const QStyleOptionViewItem &option, int index) const | ||||||
| { | { | ||||||
|     //function-level statics
 |  | ||||||
|     QRect iconRect = option.rect; |     QRect iconRect = option.rect; | ||||||
|     QRect textRect = iconRect; |     QRect textRect = iconRect; | ||||||
| 
 | 
 | ||||||
|     const QString &text = mValues.at(index).second; |     iconRect.setLeft(iconRect.left() + mHorizontalMargin); | ||||||
| 
 |     iconRect.setRight(option.rect.right() - mHorizontalMargin); | ||||||
|     iconRect.setSize (mIconSize); |     if (mDisplayMode == Mode_IconAndText) | ||||||
|     iconRect.translate(mIconLeftOffset, (option.rect.height() - iconRect.height())/2); |  | ||||||
| 
 |  | ||||||
|     if (mDisplayMode == Mode_IconAndText ) |  | ||||||
|     { |     { | ||||||
|         textRect.translate (iconRect.width() + mTextLeftOffset, 0 ); |         iconRect.setWidth(mIconSize.width()); | ||||||
|         painter->drawText (textRect, text, mTextAlignment); |         textRect.setLeft(iconRect.right() + mTextLeftOffset); | ||||||
|     } |         textRect.setRight(option.rect.right() - mHorizontalMargin); | ||||||
|     else |  | ||||||
|         iconRect.translate( (option.rect.width() - iconRect.width()) / 2, 0); |  | ||||||
| 
 | 
 | ||||||
|     painter->drawPixmap (iconRect, mPixmaps.at(index).second); |         QString text = option.fontMetrics.elidedText(mValues.at(index).second,  | ||||||
|  |                                                      option.textElideMode, | ||||||
|  |                                                      textRect.width()); | ||||||
|  |         QApplication::style()->drawItemText(painter, | ||||||
|  |                                             textRect, | ||||||
|  |                                             Qt::AlignLeft | Qt::AlignVCenter, | ||||||
|  |                                             option.palette, | ||||||
|  |                                             true, | ||||||
|  |                                             text); | ||||||
|  |     } | ||||||
|  |     QApplication::style()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, mPixmaps.at(index).second); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CSVWorld::DataDisplayDelegate::updateUserSetting (const QString &name, | void CSVWorld::DataDisplayDelegate::updateUserSetting (const QString &name, | ||||||
|  |  | ||||||
|  | @ -30,9 +30,8 @@ namespace CSVWorld | ||||||
|     private: |     private: | ||||||
| 
 | 
 | ||||||
|         std::vector <std::pair <int, QPixmap> > mPixmaps; |         std::vector <std::pair <int, QPixmap> > mPixmaps; | ||||||
|         QTextOption mTextAlignment; |  | ||||||
|         QSize mIconSize; |         QSize mIconSize; | ||||||
|         int mIconLeftOffset; |         int mHorizontalMargin; | ||||||
|         int mTextLeftOffset; |         int mTextLeftOffset; | ||||||
| 
 | 
 | ||||||
|         QString mSettingKey; |         QString mSettingKey; | ||||||
|  | @ -46,12 +45,11 @@ 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; | ||||||
| 
 | 
 | ||||||
|  |         virtual QSize sizeHint(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.
 |  | ||||||
|         void setIconLeftOffset (int offset); |  | ||||||
| 
 |  | ||||||
|         /// offset the horizontal position of the text from the right edge of the icon.  Default is 8 pixels.
 |         /// offset the horizontal position of the text from the right edge of the icon.  Default is 8 pixels.
 | ||||||
|         void setTextLeftOffset (int offset); |         void setTextLeftOffset (int offset); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -33,6 +33,8 @@ | ||||||
| #include "../../model/world/commands.hpp" | #include "../../model/world/commands.hpp" | ||||||
| #include "../../model/doc/document.hpp" | #include "../../model/doc/document.hpp" | ||||||
| 
 | 
 | ||||||
|  | #include "../widget/coloreditor.hpp" | ||||||
|  | 
 | ||||||
| #include "recordstatusdelegate.hpp" | #include "recordstatusdelegate.hpp" | ||||||
| #include "util.hpp" | #include "util.hpp" | ||||||
| #include "tablebottombox.hpp" | #include "tablebottombox.hpp" | ||||||
|  | @ -331,6 +333,10 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase:: | ||||||
|         { |         { | ||||||
|             connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited())); |             connect(editor, SIGNAL(editingFinished()), proxy, SLOT(editorDataCommited())); | ||||||
|         } |         } | ||||||
|  |         else if (qobject_cast<CSVWidget::ColorEditor *>(editor)) | ||||||
|  |         { | ||||||
|  |             connect(editor, SIGNAL(pickingFinished()), proxy, SLOT(editorDataCommited())); | ||||||
|  |         } | ||||||
|         else // throw an exception because this is a coding error
 |         else // throw an exception because this is a coding error
 | ||||||
|             throw std::logic_error ("Dialogue editor type missing"); |             throw std::logic_error ("Dialogue editor type missing"); | ||||||
| 
 | 
 | ||||||
|  | @ -469,8 +475,7 @@ void CSVWorld::EditWidget::remake(int row) | ||||||
|                     mTable->data (mTable->index (row, idColumn)).toString().toUtf8().constData()); |                     mTable->data (mTable->index (row, idColumn)).toString().toUtf8().constData()); | ||||||
| 
 | 
 | ||||||
|                 NestedTable* table = new NestedTable(mDocument, id, mNestedModels.back(), this); |                 NestedTable* table = new NestedTable(mDocument, id, mNestedModels.back(), this); | ||||||
|                 // FIXME: does not work well when enum delegates are used
 |                 table->resizeColumnsToContents(); | ||||||
|                 //table->resizeColumnsToContents();
 |  | ||||||
| 
 | 
 | ||||||
|                 if(mTable->index(row, i).data().type() == QVariant::UserType) |                 if(mTable->index(row, i).data().type() == QVariant::UserType) | ||||||
|                 { |                 { | ||||||
|  |  | ||||||
|  | @ -1,4 +1,5 @@ | ||||||
| #include <QDrag> | #include <QDrag> | ||||||
|  | #include <QDragEnterEvent> | ||||||
| 
 | 
 | ||||||
| #include "../../model/world/tablemimedata.hpp" | #include "../../model/world/tablemimedata.hpp" | ||||||
| #include "dragrecordtable.hpp" | #include "dragrecordtable.hpp" | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| #define CSV_WORLD_DRAGRECORDTABLE_H | #define CSV_WORLD_DRAGRECORDTABLE_H | ||||||
| 
 | 
 | ||||||
| #include <QTableView> | #include <QTableView> | ||||||
| #include <QtGui/qevent.h> | #include <QEvent> | ||||||
| 
 | 
 | ||||||
| class QWidget; | class QWidget; | ||||||
| class QAction; | class QAction; | ||||||
|  |  | ||||||
|  | @ -10,6 +10,24 @@ | ||||||
| 
 | 
 | ||||||
| #include "../../model/world/commands.hpp" | #include "../../model/world/commands.hpp" | ||||||
| 
 | 
 | ||||||
|  | int CSVWorld::EnumDelegate::getValueIndex(const QModelIndex &index, int role) const | ||||||
|  | { | ||||||
|  |     if (index.isValid() && index.data(role).isValid()) | ||||||
|  |     { | ||||||
|  |         int value = index.data(role).toInt(); | ||||||
|  | 
 | ||||||
|  |         int size = static_cast<int>(mValues.size()); | ||||||
|  |         for (int i = 0; i < size; ++i) | ||||||
|  |         { | ||||||
|  |             if (value == mValues.at(i).first) | ||||||
|  |             { | ||||||
|  |                 return i; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return -1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void CSVWorld::EnumDelegate::setModelDataImp (QWidget *editor, QAbstractItemModel *model, | void CSVWorld::EnumDelegate::setModelDataImp (QWidget *editor, QAbstractItemModel *model, | ||||||
|     const QModelIndex& index) const |     const QModelIndex& index) const | ||||||
| { | { | ||||||
|  | @ -67,54 +85,59 @@ QWidget *CSVWorld::EnumDelegate::createEditor(QWidget *parent, const QStyleOptio | ||||||
| 
 | 
 | ||||||
| void CSVWorld::EnumDelegate::setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay) const | void CSVWorld::EnumDelegate::setEditorData (QWidget *editor, const QModelIndex& index, bool tryDisplay) const | ||||||
| { | { | ||||||
|     if (QComboBox *comboBox = dynamic_cast<QComboBox *> (editor)) |     if (QComboBox *comboBox = dynamic_cast<QComboBox *>(editor)) | ||||||
|     { |     { | ||||||
|         QVariant data = index.data (Qt::EditRole); |         int role = Qt::EditRole; | ||||||
| 
 |         if (tryDisplay && !index.data(role).isValid()) | ||||||
|         if (tryDisplay && !data.isValid()) |  | ||||||
|         { |         { | ||||||
|             data = index.data (Qt::DisplayRole); |             role = Qt::DisplayRole; | ||||||
|             if (!data.isValid()) |             if (!index.data(role).isValid()) | ||||||
|             { |             { | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         int value = data.toInt(); |         int valueIndex = getValueIndex(index, role); | ||||||
| 
 |         if (valueIndex != -1) | ||||||
|         std::size_t size = mValues.size(); |         { | ||||||
| 
 |             comboBox->setCurrentIndex(valueIndex); | ||||||
|         for (std::size_t i=0; i<size; ++i) |         } | ||||||
|             if (mValues[i].first==value) |  | ||||||
|             { |  | ||||||
|                 comboBox->setCurrentIndex (i); |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CSVWorld::EnumDelegate::paint (QPainter *painter, const QStyleOptionViewItem& option, | void CSVWorld::EnumDelegate::paint (QPainter *painter, const QStyleOptionViewItem& option, | ||||||
|     const QModelIndex& index) const |     const QModelIndex& index) const | ||||||
| { | { | ||||||
|     if (index.data().isValid()) |     int valueIndex = getValueIndex(index); | ||||||
|  |     if (valueIndex != -1) | ||||||
|     { |     { | ||||||
|         QStyleOptionViewItemV4 option2 (option); |         QStyleOptionViewItemV4 itemOption(option); | ||||||
| 
 |         itemOption.text = mValues.at(valueIndex).second; | ||||||
|         int value = index.data().toInt(); |         QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &itemOption, painter); | ||||||
| 
 |  | ||||||
|         for (std::vector<std::pair<int, QString> >::const_iterator iter (mValues.begin()); |  | ||||||
|             iter!=mValues.end(); ++iter) |  | ||||||
|             if (iter->first==value) |  | ||||||
|             { |  | ||||||
|                 option2.text = iter->second; |  | ||||||
| 
 |  | ||||||
|                 QApplication::style()->drawControl (QStyle::CE_ItemViewItem, &option2, painter); |  | ||||||
| 
 |  | ||||||
|                 break; |  | ||||||
|             } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | QSize CSVWorld::EnumDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const | ||||||
|  | { | ||||||
|  |     int valueIndex = getValueIndex(index); | ||||||
|  |     if (valueIndex != -1) | ||||||
|  |     { | ||||||
|  |         // Calculate the size hint as for a combobox.
 | ||||||
|  |         // So, the whole text is visible (isn't elided) when the editor is created
 | ||||||
|  |         QStyleOptionComboBox itemOption; | ||||||
|  |         itemOption.fontMetrics = option.fontMetrics; | ||||||
|  |         itemOption.palette = option.palette; | ||||||
|  |         itemOption.rect = option.rect; | ||||||
|  |         itemOption.state = option.state; | ||||||
|  | 
 | ||||||
|  |         const QString &valueText = mValues.at(valueIndex).second; | ||||||
|  |         QSize valueSize = QSize(itemOption.fontMetrics.width(valueText), itemOption.fontMetrics.height()); | ||||||
|  | 
 | ||||||
|  |         itemOption.currentText = valueText; | ||||||
|  |         return QApplication::style()->sizeFromContents(QStyle::CT_ComboBox, &itemOption, valueSize); | ||||||
|  |     } | ||||||
|  |     return option.rect.size(); | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| CSVWorld::EnumDelegateFactory::EnumDelegateFactory() {} | CSVWorld::EnumDelegateFactory::EnumDelegateFactory() {} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -19,6 +19,8 @@ namespace CSVWorld | ||||||
| 
 | 
 | ||||||
|             std::vector<std::pair<int, QString> > mValues; |             std::vector<std::pair<int, QString> > mValues; | ||||||
| 
 | 
 | ||||||
|  |             int getValueIndex(const QModelIndex &index, int role = Qt::DisplayRole) const; | ||||||
|  | 
 | ||||||
|         private: |         private: | ||||||
| 
 | 
 | ||||||
|             virtual void setModelDataImp (QWidget *editor, QAbstractItemModel *model, |             virtual void setModelDataImp (QWidget *editor, QAbstractItemModel *model, | ||||||
|  | @ -46,6 +48,8 @@ namespace CSVWorld | ||||||
|             virtual void paint (QPainter *painter, const QStyleOptionViewItem& option, |             virtual void paint (QPainter *painter, const QStyleOptionViewItem& option, | ||||||
|                 const QModelIndex& index) const; |                 const QModelIndex& index) const; | ||||||
| 
 | 
 | ||||||
|  |             virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; | ||||||
|  | 
 | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     class EnumDelegateFactory : public CommandDelegateFactory |     class EnumDelegateFactory : public CommandDelegateFactory | ||||||
|  |  | ||||||
|  | @ -23,7 +23,11 @@ CSVWorld::NestedTable::NestedTable(CSMDoc::Document& document, | ||||||
|     setSelectionBehavior (QAbstractItemView::SelectRows); |     setSelectionBehavior (QAbstractItemView::SelectRows); | ||||||
|     setSelectionMode (QAbstractItemView::ExtendedSelection); |     setSelectionMode (QAbstractItemView::ExtendedSelection); | ||||||
| 
 | 
 | ||||||
|  | #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) | ||||||
|  |     horizontalHeader()->setSectionResizeMode (QHeaderView::Interactive); | ||||||
|  | #else | ||||||
|     horizontalHeader()->setResizeMode (QHeaderView::Interactive); |     horizontalHeader()->setResizeMode (QHeaderView::Interactive); | ||||||
|  | #endif | ||||||
|     verticalHeader()->hide(); |     verticalHeader()->hide(); | ||||||
| 
 | 
 | ||||||
|     int columns = model->columnCount(QModelIndex()); |     int columns = model->columnCount(QModelIndex()); | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ | ||||||
| #define CSV_WORLD_NESTEDTABLE_H | #define CSV_WORLD_NESTEDTABLE_H | ||||||
| 
 | 
 | ||||||
| #include <QTableView> | #include <QTableView> | ||||||
| #include <QtGui/qevent.h> | #include <QEvent> | ||||||
| 
 | 
 | ||||||
| class QUndoStack; | class QUndoStack; | ||||||
| class QAction; | class QAction; | ||||||
|  |  | ||||||
|  | @ -68,10 +68,10 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) | ||||||
|         new CSVDoc::SubViewFactoryWithCreator<TableSubView, JournalCreatorFactory>); |         new CSVDoc::SubViewFactoryWithCreator<TableSubView, JournalCreatorFactory>); | ||||||
| 
 | 
 | ||||||
|     manager.add (CSMWorld::UniversalId::Type_TopicInfos, |     manager.add (CSMWorld::UniversalId::Type_TopicInfos, | ||||||
|         new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<InfoCreator> > (false)); |         new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<InfoCreator> >); | ||||||
| 
 | 
 | ||||||
|     manager.add (CSMWorld::UniversalId::Type_JournalInfos, |     manager.add (CSMWorld::UniversalId::Type_JournalInfos, | ||||||
|         new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<InfoCreator> > (false)); |         new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<InfoCreator> >); | ||||||
| 
 | 
 | ||||||
|     // Subviews for resources tables
 |     // Subviews for resources tables
 | ||||||
|     manager.add (CSMWorld::UniversalId::Type_Meshes, |     manager.add (CSMWorld::UniversalId::Type_Meshes, | ||||||
|  |  | ||||||
|  | @ -13,6 +13,7 @@ | ||||||
| 
 | 
 | ||||||
| #include "../../model/world/data.hpp" | #include "../../model/world/data.hpp" | ||||||
| #include "../../model/world/commands.hpp" | #include "../../model/world/commands.hpp" | ||||||
|  | #include "../../model/world/infotableproxymodel.hpp" | ||||||
| #include "../../model/world/idtableproxymodel.hpp" | #include "../../model/world/idtableproxymodel.hpp" | ||||||
| #include "../../model/world/idtablebase.hpp" | #include "../../model/world/idtablebase.hpp" | ||||||
| #include "../../model/world/idtable.hpp" | #include "../../model/world/idtable.hpp" | ||||||
|  | @ -279,13 +280,26 @@ CSVWorld::Table::Table (const CSMWorld::UniversalId& id, | ||||||
| 
 | 
 | ||||||
|     mModel = &dynamic_cast<CSMWorld::IdTableBase&> (*mDocument.getData().getTableModel (id)); |     mModel = &dynamic_cast<CSMWorld::IdTableBase&> (*mDocument.getData().getTableModel (id)); | ||||||
| 
 | 
 | ||||||
|     mProxyModel = new CSMWorld::IdTableProxyModel (this); |     bool isInfoTable = id.getType() == CSMWorld::UniversalId::Type_TopicInfos || | ||||||
|  |                        id.getType() == CSMWorld::UniversalId::Type_JournalInfos; | ||||||
|  |     if (isInfoTable) | ||||||
|  |     { | ||||||
|  |         mProxyModel = new CSMWorld::InfoTableProxyModel(id.getType(), this); | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         mProxyModel = new CSMWorld::IdTableProxyModel (this); | ||||||
|  |     } | ||||||
|     mProxyModel->setSourceModel (mModel); |     mProxyModel->setSourceModel (mModel); | ||||||
| 
 | 
 | ||||||
|     mDispatcher = new CSMWorld::CommandDispatcher (document, id, this); |     mDispatcher = new CSMWorld::CommandDispatcher (document, id, this); | ||||||
| 
 | 
 | ||||||
|     setModel (mProxyModel); |     setModel (mProxyModel); | ||||||
|  | #if QT_VERSION >= QT_VERSION_CHECK(5,0,0) | ||||||
|  |     horizontalHeader()->setSectionResizeMode (QHeaderView::Interactive); | ||||||
|  | #else | ||||||
|     horizontalHeader()->setResizeMode (QHeaderView::Interactive); |     horizontalHeader()->setResizeMode (QHeaderView::Interactive); | ||||||
|  | #endif | ||||||
|     verticalHeader()->hide(); |     verticalHeader()->hide(); | ||||||
|     setSortingEnabled (sorting); |     setSortingEnabled (sorting); | ||||||
|     setSelectionBehavior (QAbstractItemView::SelectRows); |     setSelectionBehavior (QAbstractItemView::SelectRows); | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ | ||||||
| #include <vector> | #include <vector> | ||||||
| #include <string> | #include <string> | ||||||
| 
 | 
 | ||||||
| #include <QtGui/qevent.h> | #include <QEvent> | ||||||
| 
 | 
 | ||||||
| #include "../../model/filter/node.hpp" | #include "../../model/filter/node.hpp" | ||||||
| #include "../../model/world/columnbase.hpp" | #include "../../model/world/columnbase.hpp" | ||||||
|  |  | ||||||
|  | @ -8,6 +8,7 @@ | ||||||
| #include <QHeaderView> | #include <QHeaderView> | ||||||
| #include <QApplication> | #include <QApplication> | ||||||
| #include <QDesktopWidget> | #include <QDesktopWidget> | ||||||
|  | #include <QDropEvent> | ||||||
| 
 | 
 | ||||||
| #include "../../model/doc/document.hpp" | #include "../../model/doc/document.hpp" | ||||||
| #include "../../model/world/tablemimedata.hpp" | #include "../../model/world/tablemimedata.hpp" | ||||||
|  |  | ||||||
|  | @ -17,6 +17,7 @@ | ||||||
| #include "../../model/world/commands.hpp" | #include "../../model/world/commands.hpp" | ||||||
| #include "../../model/world/tablemimedata.hpp" | #include "../../model/world/tablemimedata.hpp" | ||||||
| #include "../../model/world/commanddispatcher.hpp" | #include "../../model/world/commanddispatcher.hpp" | ||||||
|  | #include "../widget/coloreditor.hpp" | ||||||
| #include "dialoguespinbox.hpp" | #include "dialoguespinbox.hpp" | ||||||
| #include "scriptedit.hpp" | #include "scriptedit.hpp" | ||||||
| 
 | 
 | ||||||
|  | @ -123,10 +124,19 @@ void CSVWorld::CommandDelegate::setModelDataImp (QWidget *editor, QAbstractItemM | ||||||
|     if (!mCommandDispatcher) |     if (!mCommandDispatcher) | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     NastyTableModelHack hack (*model); |     QVariant new_; | ||||||
|     QStyledItemDelegate::setModelData (editor, &hack, index); |     // Color columns use a custom editor, so we need explicitly extract a data from it
 | ||||||
| 
 |     CSVWidget::ColorEditor *colorEditor = qobject_cast<CSVWidget::ColorEditor *>(editor); | ||||||
|     QVariant new_ = hack.getData(); |     if (colorEditor != NULL) | ||||||
|  |     { | ||||||
|  |         new_ = colorEditor->color(); | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         NastyTableModelHack hack (*model); | ||||||
|  |         QStyledItemDelegate::setModelData (editor, &hack, index); | ||||||
|  |         new_ = hack.getData(); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     if ((model->data (index)!=new_) && (model->flags(index) & Qt::ItemIsEditable)) |     if ((model->data (index)!=new_) && (model->flags(index) & Qt::ItemIsEditable)) | ||||||
|         mCommandDispatcher->executeModify (model, index, new_); |         mCommandDispatcher->executeModify (model, index, new_); | ||||||
|  | @ -162,6 +172,12 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO | ||||||
|     { |     { | ||||||
|         return QStyledItemDelegate::createEditor(parent, option, index); |         return QStyledItemDelegate::createEditor(parent, option, index); | ||||||
|     } |     } | ||||||
|  |     // For tables the pop-up of the color editor should appear immediately after the editor creation
 | ||||||
|  |     // (the third parameter of ColorEditor's constructor)
 | ||||||
|  |     else if (display == CSMWorld::ColumnBase::Display_Colour) | ||||||
|  |     { | ||||||
|  |         return new CSVWidget::ColorEditor(index.data().value<QColor>(), parent, true); | ||||||
|  |     } | ||||||
|     return createEditor (parent, option, index, display); |     return createEditor (parent, option, index, display); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -184,7 +200,7 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO | ||||||
|     { |     { | ||||||
|         case CSMWorld::ColumnBase::Display_Colour: |         case CSMWorld::ColumnBase::Display_Colour: | ||||||
| 
 | 
 | ||||||
|             return new QLineEdit(parent); |             return new CSVWidget::ColorEditor(index.data().value<QColor>(), parent); | ||||||
| 
 | 
 | ||||||
|         case CSMWorld::ColumnBase::Display_Integer: |         case CSMWorld::ColumnBase::Display_Integer: | ||||||
|         { |         { | ||||||
|  | @ -284,6 +300,14 @@ void CSVWorld::CommandDelegate::setEditorData (QWidget *editor, const QModelInde | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     // Color columns use a custom editor, so we need explicitly set a data for it
 | ||||||
|  |     CSVWidget::ColorEditor *colorEditor = qobject_cast<CSVWidget::ColorEditor *>(editor); | ||||||
|  |     if (colorEditor != NULL) | ||||||
|  |     { | ||||||
|  |         colorEditor->setColor(index.data().value<QColor>()); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     QByteArray n = editor->metaObject()->userProperty().name(); |     QByteArray n = editor->metaObject()->userProperty().name(); | ||||||
| 
 | 
 | ||||||
|     if (n == "dateTime") { |     if (n == "dateTime") { | ||||||
|  |  | ||||||
|  | @ -91,17 +91,6 @@ add_openmw_dir (mwbase | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
| # Main executable | # Main executable | ||||||
| if (ANDROID) |  | ||||||
|     set(BOOST_COMPONENTS system filesystem program_options thread wave atomic) |  | ||||||
| else () |  | ||||||
|     set(BOOST_COMPONENTS system filesystem program_options thread wave) |  | ||||||
| endif () |  | ||||||
| 
 |  | ||||||
| if(WIN32) |  | ||||||
|     set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale) |  | ||||||
| endif(WIN32) |  | ||||||
| 
 |  | ||||||
| find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS}) |  | ||||||
| 
 | 
 | ||||||
| if (NOT ANDROID) | if (NOT ANDROID) | ||||||
|     add_executable(openmw |     add_executable(openmw | ||||||
|  | @ -126,10 +115,14 @@ target_link_libraries(openmw | ||||||
|     ${OGRE_LIBRARIES} |     ${OGRE_LIBRARIES} | ||||||
|     ${OGRE_STATIC_PLUGINS} |     ${OGRE_STATIC_PLUGINS} | ||||||
|     ${SHINY_LIBRARIES} |     ${SHINY_LIBRARIES} | ||||||
|     ${Boost_LIBRARIES} |  | ||||||
|     ${OPENAL_LIBRARY} |     ${OPENAL_LIBRARY} | ||||||
|     ${SOUND_INPUT_LIBRARY} |     ${SOUND_INPUT_LIBRARY} | ||||||
|     ${BULLET_LIBRARIES} |     ${BULLET_LIBRARIES} | ||||||
|  |     ${Boost_SYSTEM_LIBRARY} | ||||||
|  |     ${Boost_THREAD_LIBRARY} | ||||||
|  |     ${Boost_FILESYSTEM_LIBRARY} | ||||||
|  |     ${Boost_PROGRAM_OPTIONS_LIBRARY} | ||||||
|  |     ${Boost_WAVE_LIBRARY} | ||||||
|     ${MYGUI_LIBRARIES} |     ${MYGUI_LIBRARIES} | ||||||
|     ${SDL2_LIBRARY} |     ${SDL2_LIBRARY} | ||||||
|     ${MYGUI_PLATFORM_LIBRARIES} |     ${MYGUI_PLATFORM_LIBRARIES} | ||||||
|  |  | ||||||
|  | @ -677,44 +677,32 @@ namespace MWMechanics | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     bool AiCombat::doesPathNeedRecalc(ESM::Pathgrid::Point dest, const ESM::Cell *cell) | ||||||
|  |     { | ||||||
|  |         if (!mPathFinder.getPath().empty()) | ||||||
|  |         { | ||||||
|  |             Ogre::Vector3 currPathTarget(PathFinder::MakeOgreVector3(mPathFinder.getPath().back())); | ||||||
|  |             Ogre::Vector3 newPathTarget = PathFinder::MakeOgreVector3(dest); | ||||||
|  |             float dist = (newPathTarget - currPathTarget).length(); | ||||||
|  |             float targetPosThreshold = (cell->isExterior()) ? 300.0f : 100.0f; | ||||||
|  |             return dist > targetPosThreshold; | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             // necessarily construct a new path
 | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     void AiCombat::buildNewPath(const MWWorld::Ptr& actor, const MWWorld::Ptr& target) |     void AiCombat::buildNewPath(const MWWorld::Ptr& actor, const MWWorld::Ptr& target) | ||||||
|     { |     { | ||||||
|         Ogre::Vector3 newPathTarget = Ogre::Vector3(target.getRefData().getPosition().pos); |         ESM::Pathgrid::Point newPathTarget = PathFinder::MakePathgridPoint(target.getRefData().getPosition()); | ||||||
| 
 |  | ||||||
|         float dist; |  | ||||||
| 
 |  | ||||||
|         if(!mPathFinder.getPath().empty()) |  | ||||||
|         { |  | ||||||
|             ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back(); |  | ||||||
|             Ogre::Vector3 currPathTarget(PathFinder::MakeOgreVector3(lastPt)); |  | ||||||
|             dist = (newPathTarget - currPathTarget).length(); |  | ||||||
|         } |  | ||||||
|         else dist = 1e+38F; // necessarily construct a new path
 |  | ||||||
| 
 |  | ||||||
|         float targetPosThreshold = (actor.getCell()->getCell()->isExterior())? 300.0f : 100.0f; |  | ||||||
| 
 | 
 | ||||||
|         //construct new path only if target has moved away more than on [targetPosThreshold]
 |         //construct new path only if target has moved away more than on [targetPosThreshold]
 | ||||||
|         if(dist > targetPosThreshold) |         if (doesPathNeedRecalc(newPathTarget, actor.getCell()->getCell())) | ||||||
|         { |         { | ||||||
|             ESM::Position pos = actor.getRefData().getPosition(); |             ESM::Pathgrid::Point start(PathFinder::MakePathgridPoint(actor.getRefData().getPosition())); | ||||||
| 
 |             mPathFinder.buildSyncedPath(start, newPathTarget, actor.getCell(), false); | ||||||
|             ESM::Pathgrid::Point start(PathFinder::MakePathgridPoint(pos)); |  | ||||||
| 
 |  | ||||||
|             ESM::Pathgrid::Point dest(PathFinder::MakePathgridPoint(newPathTarget)); |  | ||||||
| 
 |  | ||||||
|             if(!mPathFinder.isPathConstructed()) |  | ||||||
|                 mPathFinder.buildPath(start, dest, actor.getCell(), false); |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 PathFinder newPathFinder; |  | ||||||
|                 newPathFinder.buildPath(start, dest, actor.getCell(), false); |  | ||||||
| 
 |  | ||||||
|                 if(!mPathFinder.getPath().empty()) |  | ||||||
|                 { |  | ||||||
|                     newPathFinder.syncStart(mPathFinder.getPath()); |  | ||||||
|                     mPathFinder = newPathFinder; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -53,6 +53,9 @@ namespace MWMechanics | ||||||
| 
 | 
 | ||||||
|             virtual void writeState(ESM::AiSequence::AiSequence &sequence) const; |             virtual void writeState(ESM::AiSequence::AiSequence &sequence) const; | ||||||
| 
 | 
 | ||||||
|  |         protected: | ||||||
|  |             virtual bool doesPathNeedRecalc(ESM::Pathgrid::Point dest, const ESM::Cell *cell); | ||||||
|  | 
 | ||||||
|         private: |         private: | ||||||
| 
 | 
 | ||||||
|             int mTargetActorId; |             int mTargetActorId; | ||||||
|  |  | ||||||
|  | @ -30,9 +30,9 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po | ||||||
|     ESM::Position pos = actor.getRefData().getPosition(); //position of the actor
 |     ESM::Position pos = actor.getRefData().getPosition(); //position of the actor
 | ||||||
| 
 | 
 | ||||||
|     /// Stops the actor when it gets too close to a unloaded cell
 |     /// Stops the actor when it gets too close to a unloaded cell
 | ||||||
|  |     const ESM::Cell *cell = actor.getCell()->getCell(); | ||||||
|     { |     { | ||||||
|         MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); |         MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); | ||||||
|         const ESM::Cell *cell = actor.getCell()->getCell(); |  | ||||||
|         Movement &movement = actor.getClass().getMovementSettings(actor); |         Movement &movement = actor.getClass().getMovementSettings(actor); | ||||||
| 
 | 
 | ||||||
|         //Ensure pursuer doesn't leave loaded cells
 |         //Ensure pursuer doesn't leave loaded cells
 | ||||||
|  | @ -67,8 +67,8 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po | ||||||
|     //***********************
 |     //***********************
 | ||||||
|     if(mTimer > 0.25) |     if(mTimer > 0.25) | ||||||
|     { |     { | ||||||
|         if(distance(mPrevDest, dest) > 10) { //Only rebuild path if it's moved
 |         if (doesPathNeedRecalc(dest, cell)) { //Only rebuild path if it's moved
 | ||||||
|             mPathFinder.buildPath(start, dest, actor.getCell(), true); //Rebuild path, in case the target has moved
 |             mPathFinder.buildSyncedPath(start, dest, actor.getCell(), true); //Rebuild path, in case the target has moved
 | ||||||
|             mPrevDest = dest; |             mPrevDest = dest; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -123,3 +123,8 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po | ||||||
| 
 | 
 | ||||||
|     return false; |     return false; | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | bool MWMechanics::AiPackage::doesPathNeedRecalc(ESM::Pathgrid::Point dest, const ESM::Cell *cell) | ||||||
|  | { | ||||||
|  |     return distance(mPrevDest, dest) > 10; | ||||||
|  | } | ||||||
|  | @ -14,6 +14,7 @@ namespace MWWorld | ||||||
| 
 | 
 | ||||||
| namespace ESM | namespace ESM | ||||||
| { | { | ||||||
|  |     struct Cell; | ||||||
|     namespace AiSequence |     namespace AiSequence | ||||||
|     { |     { | ||||||
|         struct AiSequence; |         struct AiSequence; | ||||||
|  | @ -71,6 +72,8 @@ namespace MWMechanics | ||||||
|             /** \return If the actor has arrived at his destination **/ |             /** \return If the actor has arrived at his destination **/ | ||||||
|             bool pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Point dest, float duration); |             bool pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Point dest, float duration); | ||||||
| 
 | 
 | ||||||
|  |             virtual bool doesPathNeedRecalc(ESM::Pathgrid::Point dest, const ESM::Cell *cell); | ||||||
|  | 
 | ||||||
|             // TODO: all this does not belong here, move into temporary storage
 |             // TODO: all this does not belong here, move into temporary storage
 | ||||||
|             PathFinder mPathFinder; |             PathFinder mPathFinder; | ||||||
|             ObstacleCheck mObstacleCheck; |             ObstacleCheck mObstacleCheck; | ||||||
|  |  | ||||||
|  | @ -51,64 +51,31 @@ namespace MWMechanics | ||||||
| 
 | 
 | ||||||
|     bool AiTravel::execute (const MWWorld::Ptr& actor, AiState& state, float duration) |     bool AiTravel::execute (const MWWorld::Ptr& actor, AiState& state, float duration) | ||||||
|     { |     { | ||||||
|         MWBase::World *world = MWBase::Environment::get().getWorld(); |  | ||||||
|         ESM::Position pos = actor.getRefData().getPosition(); |         ESM::Position pos = actor.getRefData().getPosition(); | ||||||
|         Movement &movement = actor.getClass().getMovementSettings(actor); |  | ||||||
|         const ESM::Cell *cell = actor.getCell()->getCell(); |  | ||||||
| 
 | 
 | ||||||
|         actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, false); |         actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, false); | ||||||
| 
 |  | ||||||
|         actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing); |         actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing); | ||||||
| 
 | 
 | ||||||
|         MWWorld::Ptr player = world->getPlayerPtr(); |  | ||||||
|         if(cell->mData.mX != player.getCell()->getCell()->mData.mX) |  | ||||||
|         { |  | ||||||
|             int sideX = PathFinder::sgn(cell->mData.mX - player.getCell()->getCell()->mData.mX); |  | ||||||
|             //check if actor is near the border of an inactive cell. If so, stop walking.
 |  | ||||||
|             if(sideX * (pos.pos[0] - cell->mData.mX*ESM::Land::REAL_SIZE) > |  | ||||||
|                sideX * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) |  | ||||||
|             { |  | ||||||
|                 movement.mPosition[1] = 0; |  | ||||||
|                 return false; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         if(cell->mData.mY != player.getCell()->getCell()->mData.mY) |  | ||||||
|         { |  | ||||||
|             int sideY = PathFinder::sgn(cell->mData.mY - player.getCell()->getCell()->mData.mY); |  | ||||||
|             //check if actor is near the border of an inactive cell. If so, stop walking.
 |  | ||||||
|             if(sideY * (pos.pos[1] - cell->mData.mY*ESM::Land::REAL_SIZE) > |  | ||||||
|                sideY * (ESM::Land::REAL_SIZE/2.0f - 200.0f)) |  | ||||||
|             { |  | ||||||
|                 movement.mPosition[1] = 0; |  | ||||||
|                 return false; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if (!isWithinMaxRange(Ogre::Vector3(mX, mY, mZ), Ogre::Vector3(pos.pos))) |         if (!isWithinMaxRange(Ogre::Vector3(mX, mY, mZ), Ogre::Vector3(pos.pos))) | ||||||
|             return false; |             return false; | ||||||
| 
 | 
 | ||||||
|  |         if (pathTo(actor, ESM::Pathgrid::Point(static_cast<int>(mX), static_cast<int>(mY), static_cast<int>(mZ)), duration)) | ||||||
|  |         { | ||||||
|  |             actor.getClass().getMovementSettings(actor).mPosition[1] = 0; | ||||||
|  |             return true; | ||||||
|  |         } | ||||||
|  |         return false; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     bool AiTravel::doesPathNeedRecalc(ESM::Pathgrid::Point dest, const ESM::Cell *cell) | ||||||
|  |     { | ||||||
|         bool cellChange = cell->mData.mX != mCellX || cell->mData.mY != mCellY; |         bool cellChange = cell->mData.mX != mCellX || cell->mData.mY != mCellY; | ||||||
|         if(!mPathFinder.isPathConstructed() || cellChange) |         if (!mPathFinder.isPathConstructed() || cellChange) | ||||||
|         { |         { | ||||||
|             mCellX = cell->mData.mX; |             mCellX = cell->mData.mX; | ||||||
|             mCellY = cell->mData.mY; |             mCellY = cell->mData.mY; | ||||||
| 
 |  | ||||||
|             ESM::Pathgrid::Point dest(static_cast<int>(mX), static_cast<int>(mY), static_cast<int>(mZ)); |  | ||||||
| 
 |  | ||||||
|             ESM::Pathgrid::Point start(PathFinder::MakePathgridPoint(pos)); |  | ||||||
| 
 |  | ||||||
|             mPathFinder.buildPath(start, dest, actor.getCell(), true); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1])) |  | ||||||
|         { |  | ||||||
|             movement.mPosition[1] = 0; |  | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|         zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1]))); |  | ||||||
|         movement.mPosition[1] = 1; |  | ||||||
| 
 |  | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -34,6 +34,9 @@ namespace MWMechanics | ||||||
| 
 | 
 | ||||||
|             virtual int getTypeId() const; |             virtual int getTypeId() const; | ||||||
| 
 | 
 | ||||||
|  |         protected: | ||||||
|  |             virtual bool doesPathNeedRecalc(ESM::Pathgrid::Point dest, const ESM::Cell *cell); | ||||||
|  | 
 | ||||||
|         private: |         private: | ||||||
|             float mX; |             float mX; | ||||||
|             float mY; |             float mY; | ||||||
|  |  | ||||||
|  | @ -651,6 +651,9 @@ namespace MWMechanics | ||||||
|         if (mAllowedNodes.empty()) |         if (mAllowedNodes.empty()) | ||||||
|             return; |             return; | ||||||
| 
 | 
 | ||||||
|  |         if (actor.getClass().isPureWaterCreature(actor)) | ||||||
|  |             return; | ||||||
|  | 
 | ||||||
|         state.moveIn(new AiWanderStorage()); |         state.moveIn(new AiWanderStorage()); | ||||||
| 
 | 
 | ||||||
|         int index = OEngine::Misc::Rng::rollDice(mAllowedNodes.size()); |         int index = OEngine::Misc::Rng::rollDice(mAllowedNodes.size()); | ||||||
|  | @ -669,6 +672,9 @@ namespace MWMechanics | ||||||
|         MWBase::Environment::get().getWorld()->moveObject(actor, static_cast<float>(dest.mX),  |         MWBase::Environment::get().getWorld()->moveObject(actor, static_cast<float>(dest.mX),  | ||||||
|             static_cast<float>(dest.mY), static_cast<float>(dest.mZ)); |             static_cast<float>(dest.mY), static_cast<float>(dest.mZ)); | ||||||
|         actor.getClass().adjustPosition(actor, false); |         actor.getClass().adjustPosition(actor, false); | ||||||
|  | 
 | ||||||
|  |         // may have changed cell
 | ||||||
|  |         mStoredAvailableNodes = false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     void AiWander::getAllowedNodes(const MWWorld::Ptr& actor, const ESM::Cell* cell) |     void AiWander::getAllowedNodes(const MWWorld::Ptr& actor, const ESM::Cell* cell) | ||||||
|  |  | ||||||
|  | @ -114,8 +114,7 @@ namespace MWMechanics | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     PathFinder::PathFinder() |     PathFinder::PathFinder() | ||||||
|         : mIsPathConstructed(false), |         : mPathgrid(NULL), | ||||||
|           mPathgrid(NULL), |  | ||||||
|           mCell(NULL) |           mCell(NULL) | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
|  | @ -124,7 +123,6 @@ namespace MWMechanics | ||||||
|     { |     { | ||||||
|         if(!mPath.empty()) |         if(!mPath.empty()) | ||||||
|             mPath.clear(); |             mPath.clear(); | ||||||
|         mIsPathConstructed = false; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /*
 |     /*
 | ||||||
|  | @ -180,7 +178,6 @@ namespace MWMechanics | ||||||
|                 static_cast<float>(endPoint.mX), static_cast<float>(endPoint.mY), static_cast<float>(endPoint.mZ))) |                 static_cast<float>(endPoint.mX), static_cast<float>(endPoint.mY), static_cast<float>(endPoint.mZ))) | ||||||
|             { |             { | ||||||
|                 mPath.push_back(endPoint); |                 mPath.push_back(endPoint); | ||||||
|                 mIsPathConstructed = true; |  | ||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -197,7 +194,6 @@ namespace MWMechanics | ||||||
|         if(!mPathgrid || mPathgrid->mPoints.empty()) |         if(!mPathgrid || mPathgrid->mPoints.empty()) | ||||||
|         { |         { | ||||||
|             mPath.push_back(endPoint); |             mPath.push_back(endPoint); | ||||||
|             mIsPathConstructed = true; |  | ||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | @ -235,7 +231,6 @@ namespace MWMechanics | ||||||
|                 if(startNode == endNode.first) |                 if(startNode == endNode.first) | ||||||
|                 { |                 { | ||||||
|                     mPath.push_back(endPoint); |                     mPath.push_back(endPoint); | ||||||
|                     mIsPathConstructed = true; |  | ||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|  | @ -243,7 +238,6 @@ namespace MWMechanics | ||||||
| 
 | 
 | ||||||
|                 if(!mPath.empty()) |                 if(!mPath.empty()) | ||||||
|                 { |                 { | ||||||
|                     mIsPathConstructed = true; |  | ||||||
|                     // Add the destination (which may be different to the closest
 |                     // Add the destination (which may be different to the closest
 | ||||||
|                     // pathgrid point).  However only add if endNode was the closest
 |                     // pathgrid point).  However only add if endNode was the closest
 | ||||||
|                     // point to endPoint.
 |                     // point to endPoint.
 | ||||||
|  | @ -256,14 +250,8 @@ namespace MWMechanics | ||||||
|                     if(endNode.second) |                     if(endNode.second) | ||||||
|                         mPath.push_back(endPoint); |                         mPath.push_back(endPoint); | ||||||
|                 } |                 } | ||||||
|                 else |  | ||||||
|                     mIsPathConstructed = false; |  | ||||||
|             } |             } | ||||||
|             else |  | ||||||
|                 mIsPathConstructed = false; |  | ||||||
|         } |         } | ||||||
|         else |  | ||||||
|             mIsPathConstructed = false; |  | ||||||
| 
 | 
 | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  | @ -271,7 +259,7 @@ namespace MWMechanics | ||||||
|     float PathFinder::getZAngleToNext(float x, float y) const |     float PathFinder::getZAngleToNext(float x, float y) const | ||||||
|     { |     { | ||||||
|         // This should never happen (programmers should have an if statement checking
 |         // This should never happen (programmers should have an if statement checking
 | ||||||
|         // mIsPathConstructed that prevents this call if otherwise).
 |         // isPathConstructed that prevents this call if otherwise).
 | ||||||
|         if(mPath.empty()) |         if(mPath.empty()) | ||||||
|             return 0.; |             return 0.; | ||||||
| 
 | 
 | ||||||
|  | @ -293,7 +281,6 @@ namespace MWMechanics | ||||||
|             mPath.pop_front(); |             mPath.pop_front(); | ||||||
|             if(mPath.empty()) |             if(mPath.empty()) | ||||||
|             { |             { | ||||||
|                 mIsPathConstructed = false; |  | ||||||
|                 return true; |                 return true; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  | @ -301,23 +288,35 @@ namespace MWMechanics | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // used by AiCombat, see header for the rationale
 |     // see header for the rationale
 | ||||||
|     bool PathFinder::syncStart(const std::list<ESM::Pathgrid::Point> &path) |     void PathFinder::buildSyncedPath(const ESM::Pathgrid::Point &startPoint, | ||||||
|  |         const ESM::Pathgrid::Point &endPoint, | ||||||
|  |         const MWWorld::CellStore* cell, | ||||||
|  |         bool allowShortcuts) | ||||||
|     { |     { | ||||||
|         if (mPath.size() < 2) |         if (mPath.size() < 2) | ||||||
|             return false; //nothing to pop
 |  | ||||||
| 
 |  | ||||||
|         std::list<ESM::Pathgrid::Point>::const_iterator oldStart = path.begin(); |  | ||||||
|         std::list<ESM::Pathgrid::Point>::iterator iter = ++mPath.begin(); |  | ||||||
| 
 |  | ||||||
|         if(    (*iter).mX == oldStart->mX |  | ||||||
|             && (*iter).mY == oldStart->mY |  | ||||||
|             && (*iter).mZ == oldStart->mZ) |  | ||||||
|         { |         { | ||||||
|             mPath.pop_front(); |             // if path has one point, then it's the destination.
 | ||||||
|             return true; |             // don't need to worry about bad path for this case
 | ||||||
|  |             buildPath(startPoint, endPoint, cell, allowShortcuts); | ||||||
|  |         } | ||||||
|  |         else | ||||||
|  |         { | ||||||
|  |             const ESM::Pathgrid::Point oldStart(*getPath().begin()); | ||||||
|  |             buildPath(startPoint, endPoint, cell, allowShortcuts); | ||||||
|  |             if (mPath.size() >= 2) | ||||||
|  |             { | ||||||
|  |                 // if 2nd waypoint of new path == 1st waypoint of old, 
 | ||||||
|  |                 // delete 1st waypoint of new path.
 | ||||||
|  |                 std::list<ESM::Pathgrid::Point>::iterator iter = ++mPath.begin(); | ||||||
|  |                 if (iter->mX == oldStart.mX | ||||||
|  |                     && iter->mY == oldStart.mY | ||||||
|  |                     && iter->mZ == oldStart.mZ) | ||||||
|  |                 { | ||||||
|  |                     mPath.pop_front(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         return false; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -48,7 +48,7 @@ namespace MWMechanics | ||||||
| 
 | 
 | ||||||
|             bool isPathConstructed() const |             bool isPathConstructed() const | ||||||
|             { |             { | ||||||
|                 return mIsPathConstructed; |                 return !mPath.empty(); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|             int getPathSize() const |             int getPathSize() const | ||||||
|  | @ -63,13 +63,13 @@ namespace MWMechanics | ||||||
| 
 | 
 | ||||||
|             /** Synchronize new path with old one to avoid visiting 1 waypoint 2 times
 |             /** Synchronize new path with old one to avoid visiting 1 waypoint 2 times
 | ||||||
|             @note |             @note | ||||||
|                 If the first point is chosen as the nearest one |                 BuildPath() takes closest PathGrid point to NPC as first point of path. | ||||||
|                 the situation can occur when the 1st point of the new path is undesirable |                 This is undesireable if NPC has just passed a Pathgrid point, as this | ||||||
|                 (i.e. the 2nd point of new path == the 1st point of old path). |                 makes the 2nd point of the new path == the 1st point of old path. | ||||||
|             @param path - old path |                 Which results in NPC "running in a circle" back to the just passed waypoint. | ||||||
|             @return true if such point was found and deleted |  | ||||||
|              */ |              */ | ||||||
|             bool syncStart(const std::list<ESM::Pathgrid::Point> &path); |             void buildSyncedPath(const ESM::Pathgrid::Point &startPoint, const ESM::Pathgrid::Point &endPoint, | ||||||
|  |                 const MWWorld::CellStore* cell, bool allowShortcuts = true); | ||||||
| 
 | 
 | ||||||
|             void addPointToPath(ESM::Pathgrid::Point &point) |             void addPointToPath(ESM::Pathgrid::Point &point) | ||||||
|             { |             { | ||||||
|  | @ -96,8 +96,6 @@ namespace MWMechanics | ||||||
| 
 | 
 | ||||||
|         private: |         private: | ||||||
| 
 | 
 | ||||||
|             bool mIsPathConstructed; |  | ||||||
| 
 |  | ||||||
|             std::list<ESM::Pathgrid::Point> mPath; |             std::list<ESM::Pathgrid::Point> mPath; | ||||||
| 
 | 
 | ||||||
|             const ESM::Pathgrid *mPathgrid; |             const ESM::Pathgrid *mPathgrid; | ||||||
|  |  | ||||||
|  | @ -188,7 +188,7 @@ namespace MWWorld | ||||||
|             const T *ptr = search(id); |             const T *ptr = search(id); | ||||||
|             if (ptr == 0) { |             if (ptr == 0) { | ||||||
|                 std::ostringstream msg; |                 std::ostringstream msg; | ||||||
|                 msg << "Object '" << id << "' not found (const)"; |                 msg << T::getRecordType() << " '" << id << "' not found"; | ||||||
|                 throw std::runtime_error(msg.str()); |                 throw std::runtime_error(msg.str()); | ||||||
|             } |             } | ||||||
|             return ptr; |             return ptr; | ||||||
|  | @ -202,7 +202,7 @@ namespace MWWorld | ||||||
|             if(ptr == 0) |             if(ptr == 0) | ||||||
|             { |             { | ||||||
|                 std::ostringstream msg; |                 std::ostringstream msg; | ||||||
|                 msg << "Object starting with '"<<id<<"' not found (const)"; |                 msg << T::getRecordType() << " starting with '"<<id<<"' not found"; | ||||||
|                 throw std::runtime_error(msg.str()); |                 throw std::runtime_error(msg.str()); | ||||||
|             } |             } | ||||||
|             return ptr; |             return ptr; | ||||||
|  | @ -989,7 +989,7 @@ namespace MWWorld | ||||||
|             const T *ptr = search(index); |             const T *ptr = search(index); | ||||||
|             if (ptr == 0) { |             if (ptr == 0) { | ||||||
|                 std::ostringstream msg; |                 std::ostringstream msg; | ||||||
|                 msg << "Object with index " << index << " not found"; |                 msg << T::getRecordType() << " with index " << index << " not found"; | ||||||
|                 throw std::runtime_error(msg.str()); |                 throw std::runtime_error(msg.str()); | ||||||
|             } |             } | ||||||
|             return ptr; |             return ptr; | ||||||
|  |  | ||||||
|  | @ -81,7 +81,6 @@ endif (OPENMW_USE_UNSHIELD) | ||||||
| 
 | 
 | ||||||
| source_group(wizard FILES ${WIZARD} ${WIZARD_HEADER}) | source_group(wizard FILES ${WIZARD} ${WIZARD_HEADER}) | ||||||
| 
 | 
 | ||||||
| find_package(Qt4 REQUIRED) |  | ||||||
| set(QT_USE_QTGUI 1) | set(QT_USE_QTGUI 1) | ||||||
| 
 | 
 | ||||||
| # Set some platform specific settings | # Set some platform specific settings | ||||||
|  | @ -90,12 +89,17 @@ if(WIN32) | ||||||
|     set(QT_USE_QTMAIN TRUE) |     set(QT_USE_QTMAIN TRUE) | ||||||
| endif(WIN32) | endif(WIN32) | ||||||
| 
 | 
 | ||||||
| QT4_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/wizard/wizard.qrc) | if (DESIRED_QT_VERSION MATCHES 4) | ||||||
| QT4_WRAP_CPP(MOC_SRCS ${WIZARD_HEADER_MOC}) |     include(${QT_USE_FILE}) | ||||||
| QT4_WRAP_UI(UI_HDRS ${WIZARD_UI}) |     QT4_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/wizard/wizard.qrc) | ||||||
|  |     QT4_WRAP_CPP(MOC_SRCS ${WIZARD_HEADER_MOC}) | ||||||
|  |     QT4_WRAP_UI(UI_HDRS ${WIZARD_UI}) | ||||||
|  | else() | ||||||
|  |     QT5_ADD_RESOURCES(RCC_SRCS ${CMAKE_SOURCE_DIR}/files/wizard/wizard.qrc) | ||||||
|  |     QT5_WRAP_CPP(MOC_SRCS ${WIZARD_HEADER_MOC}) | ||||||
|  |     QT5_WRAP_UI(UI_HDRS ${WIZARD_UI}) | ||||||
|  | endif() | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| include(${QT_USE_FILE}) |  | ||||||
| include_directories(${CMAKE_CURRENT_BINARY_DIR}) | include_directories(${CMAKE_CURRENT_BINARY_DIR}) | ||||||
| 
 | 
 | ||||||
| if (OPENMW_USE_UNSHIELD) | if (OPENMW_USE_UNSHIELD) | ||||||
|  | @ -112,11 +116,24 @@ add_executable(openmw-wizard | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| target_link_libraries(openmw-wizard | target_link_libraries(openmw-wizard | ||||||
|     ${Boost_LIBRARIES} |  | ||||||
|     ${QT_LIBRARIES} |  | ||||||
|     components |     components | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | if (DESIRED_QT_VERSION MATCHES 4) | ||||||
|  |     target_link_libraries(openmw-wizard | ||||||
|  |     ${QT_QTGUI_LIBRARY} | ||||||
|  |     ${QT_QTCORE_LIBRARY}) | ||||||
|  | 
 | ||||||
|  |     if (WIN32) | ||||||
|  |         target_link_libraries(openmw-wizard ${QT_QTMAIN_LIBRARY}) | ||||||
|  |     endif() | ||||||
|  | else() | ||||||
|  |     qt5_use_modules(openmw-wizard Widgets Core) | ||||||
|  |     if (WIN32) | ||||||
|  |         target_link_libraries(Qt5::WinMain) | ||||||
|  |     endif() | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
| if (OPENMW_USE_UNSHIELD) | if (OPENMW_USE_UNSHIELD) | ||||||
|     target_link_libraries(openmw-wizard ${LIBUNSHIELD_LIBRARY}) |     target_link_libraries(openmw-wizard ${LIBUNSHIELD_LIBRARY}) | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
|  | @ -38,9 +38,6 @@ int main(int argc, char *argv[]) | ||||||
| 
 | 
 | ||||||
|     QDir::setCurrent(dir.absolutePath()); |     QDir::setCurrent(dir.absolutePath()); | ||||||
| 
 | 
 | ||||||
|     // Support non-latin characters
 |  | ||||||
|     QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); |  | ||||||
| 
 |  | ||||||
|     Wizard::MainWizard wizard; |     Wizard::MainWizard wizard; | ||||||
| 
 | 
 | ||||||
|     wizard.show(); |     wizard.show(); | ||||||
|  |  | ||||||
|  | @ -6,7 +6,6 @@ | ||||||
| #include <QWriteLocker> | #include <QWriteLocker> | ||||||
| #include <QFileDialog> | #include <QFileDialog> | ||||||
| #include <QFileInfo> | #include <QFileInfo> | ||||||
| #include <QFileInfoListIterator> |  | ||||||
| #include <QStringList> | #include <QStringList> | ||||||
| #include <QTextStream> | #include <QTextStream> | ||||||
| #include <QTextCodec> | #include <QTextCodec> | ||||||
|  |  | ||||||
|  | @ -24,7 +24,6 @@ namespace Wizard | ||||||
|     class UnshieldWorker : public QObject |     class UnshieldWorker : public QObject | ||||||
|     { |     { | ||||||
|         Q_OBJECT |         Q_OBJECT | ||||||
|         Q_ENUMS(Wizard::Component) |  | ||||||
| 
 | 
 | ||||||
|     public: |     public: | ||||||
|         UnshieldWorker(QObject *parent = 0); |         UnshieldWorker(QObject *parent = 0); | ||||||
|  |  | ||||||
|  | @ -126,32 +126,30 @@ add_component_dir (version | ||||||
| set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui | set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
| find_package(Qt4 COMPONENTS QtCore QtGui) | add_component_qt_dir (contentselector | ||||||
| if(MINGW) |     model/modelitem model/esmfile | ||||||
| find_package(Bullet REQUIRED COMPONENTS Collision) |     model/naturalsort model/contentmodel | ||||||
| endif() |     model/loadordererror | ||||||
| 
 |     view/combobox view/contentselector | ||||||
| if(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY) |     ) | ||||||
|     add_component_qt_dir (contentselector | add_component_qt_dir (config | ||||||
|         model/modelitem model/esmfile |     gamesettings | ||||||
|         model/naturalsort model/contentmodel |     launchersettings | ||||||
| 		model/loadordererror |     settingsbase | ||||||
|         view/combobox view/contentselector |  | ||||||
|         ) |  | ||||||
|     add_component_qt_dir (config |  | ||||||
|         gamesettings |  | ||||||
|         launchersettings |  | ||||||
|         settingsbase |  | ||||||
|         ) |  | ||||||
| 
 |  | ||||||
|     add_component_qt_dir (process |  | ||||||
|         processinvoker |  | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|    include(${QT_USE_FILE}) | add_component_qt_dir (process | ||||||
|  |     processinvoker | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | if (DESIRED_QT_VERSION MATCHES 4) | ||||||
|  |     include(${QT_USE_FILE}) | ||||||
|     QT4_WRAP_UI(ESM_UI_HDR ${ESM_UI}) |     QT4_WRAP_UI(ESM_UI_HDR ${ESM_UI}) | ||||||
|    QT4_WRAP_CPP(MOC_SRCS ${COMPONENT_MOC_FILES}) |     QT4_WRAP_CPP(MOC_SRCS ${COMPONENT_MOC_FILES}) | ||||||
| endif(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY) | else() | ||||||
|  |     QT5_WRAP_UI(ESM_UI_HDR ${ESM_UI}) | ||||||
|  |     QT5_WRAP_CPP(MOC_SRCS ${COMPONENT_MOC_FILES}) | ||||||
|  | endif() | ||||||
| 
 | 
 | ||||||
| if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") | if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") | ||||||
|     if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64" AND NOT APPLE) |     if("${CMAKE_SYSTEM_PROCESSOR}" STREQUAL "x86_64" AND NOT APPLE) | ||||||
|  | @ -164,19 +162,33 @@ include_directories(${BULLET_INCLUDE_DIRS} ${CMAKE_CURRENT_BINARY_DIR}) | ||||||
| add_library(components STATIC ${COMPONENT_FILES} ${MOC_SRCS} ${ESM_UI_HDR}) | add_library(components STATIC ${COMPONENT_FILES} ${MOC_SRCS} ${ESM_UI_HDR}) | ||||||
| 
 | 
 | ||||||
| target_link_libraries(components  | target_link_libraries(components  | ||||||
|     ${Boost_LIBRARIES}  |     ${Boost_SYSTEM_LIBRARY} | ||||||
|  |     ${Boost_FILESYSTEM_LIBRARY} | ||||||
|  |     ${Boost_THREAD_LIBRARY} | ||||||
|  |     ${Boost_PROGRAM_OPTIONS_LIBRARY} | ||||||
|  |     ${Boost_WAVE_LIBRARY} | ||||||
|     ${OGRE_LIBRARIES} |     ${OGRE_LIBRARIES} | ||||||
|     ${OENGINE_LIBRARY}     |     ${OENGINE_LIBRARY}     | ||||||
|  |     ${BULLET_LIBRARIES} | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | if (WIN32) | ||||||
|  |     target_link_libraries(components | ||||||
|  |     ${Boost_LOCALE_LIBRARY}) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
|  | if (DESIRED_QT_VERSION MATCHES 4) | ||||||
|  |     target_link_libraries(components | ||||||
|  |     ${QT_QTCORE_LIBRARY} | ||||||
|  |     ${QT_QTGUI_LIBRARY}) | ||||||
|  | else() | ||||||
|  |     qt5_use_modules(components Widgets Core) | ||||||
|  | endif() | ||||||
|  | 
 | ||||||
| if (GIT_CHECKOUT) | if (GIT_CHECKOUT) | ||||||
|     add_dependencies (components git-version) |     add_dependencies (components git-version) | ||||||
| endif (GIT_CHECKOUT) | endif (GIT_CHECKOUT) | ||||||
| 
 | 
 | ||||||
| if(MINGW) |  | ||||||
| target_link_libraries(components ${QT_LIBRARIES} ${BULLET_LIBRARIES}) |  | ||||||
| endif() |  | ||||||
| 
 |  | ||||||
| if (WIN32) | if (WIN32) | ||||||
| target_link_libraries(components shlwapi) | target_link_libraries(components shlwapi) | ||||||
| endif() | endif() | ||||||
|  |  | ||||||
|  | @ -174,16 +174,30 @@ bool Config::GameSettings::writeFile(QTextStream &stream) | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | bool Config::GameSettings::isOrderedLine(const QString& line) const | ||||||
|  | { | ||||||
|  |     return line.contains(QRegExp("^\\s*fallback-archive\\s*=")) | ||||||
|  |            || line.contains(QRegExp("^\\s*fallback\\s*=")) | ||||||
|  |            || line.contains(QRegExp("^\\s*data\\s*=")) | ||||||
|  |            || line.contains(QRegExp("^\\s*data-local\\s*=")) | ||||||
|  |            || line.contains(QRegExp("^\\s*resources\\s*=")) | ||||||
|  |            || line.contains(QRegExp("^\\s*content\\s*=")); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| // Policy:
 | // Policy:
 | ||||||
| //
 | //
 | ||||||
| // - Always ignore a line beginning with '#' or empty lines
 | // - Always ignore a line beginning with '#' or empty lines; added above a config
 | ||||||
|  | //   entry.
 | ||||||
| //
 | //
 | ||||||
| // - If a line in file exists with matching key and first part of value (before ',',
 | // - If a line in file exists with matching key and first part of value (before ',',
 | ||||||
| //   '\n', etc) also matches, then replace the line with that of mUserSettings.
 | //   '\n', etc) also matches, then replace the line with that of mUserSettings.
 | ||||||
| // - else remove line (TODO: maybe replace the line with '#' in front instead?)
 | // - else remove line
 | ||||||
| //
 | //
 | ||||||
| // - If there is no corresponding line in file, add at the end
 | // - If there is no corresponding line in file, add at the end
 | ||||||
| //
 | //
 | ||||||
|  | // - Removed content items are saved as comments if the item had any comments.
 | ||||||
|  | //   Content items prepended with '##' are considered previously removed.
 | ||||||
|  | //
 | ||||||
| bool Config::GameSettings::writeFileWithComments(QFile &file) | bool Config::GameSettings::writeFileWithComments(QFile &file) | ||||||
| { | { | ||||||
|     QTextStream stream(&file); |     QTextStream stream(&file); | ||||||
|  | @ -203,60 +217,124 @@ bool Config::GameSettings::writeFileWithComments(QFile &file) | ||||||
|     if (fileCopy.empty()) |     if (fileCopy.empty()) | ||||||
|         return writeFile(stream); |         return writeFile(stream); | ||||||
| 
 | 
 | ||||||
|     // Temp copy of settings to save, but with the keys appended with the first part of the value
 |     // start
 | ||||||
|  |     //   |
 | ||||||
|  |     //   |    +----------------------------------------------------------+
 | ||||||
|  |     //   |    |                                                          |
 | ||||||
|  |     //   v    v                                                          |
 | ||||||
|  |     // skip non-"ordered" lines (remove "ordered" lines)                 |
 | ||||||
|  |     //   |              ^                                                |
 | ||||||
|  |     //   |              |                                                |
 | ||||||
|  |     //   |      non-"ordered" line, write saved comments                 |
 | ||||||
|  |     //   |              ^                                                |
 | ||||||
|  |     //   v              |                                                |
 | ||||||
|  |     // blank or comment line, save in temp buffer <--------+             |
 | ||||||
|  |     //        |                |                           |             |
 | ||||||
|  |     //        |                +------- comment line ------+             |
 | ||||||
|  |     //        v                    (special processing '##')             |
 | ||||||
|  |     //  "ordered" line                                                   |
 | ||||||
|  |     //        |                                                          |
 | ||||||
|  |     //        v                                                          |
 | ||||||
|  |     // save in a separate map of comments keyed by "ordered" line        |
 | ||||||
|  |     //        |                                                          |
 | ||||||
|  |     //        +----------------------------------------------------------+
 | ||||||
|     //
 |     //
 | ||||||
|     // ATTENTION!
 |  | ||||||
|     //
 |     //
 | ||||||
|     // A hack to avoid looping through each line, makes use of the fact that fallbacks values
 |  | ||||||
|     // are comma separated.
 |  | ||||||
|     QMap<QString, QString> userSettingsCopy; |  | ||||||
|     QRegExp settingRegex("^([^=]+)\\s*=\\s*([^,]+)(.*)$"); |     QRegExp settingRegex("^([^=]+)\\s*=\\s*([^,]+)(.*)$"); | ||||||
|     QString settingLine; |     std::vector<QString> comments; | ||||||
|     QMap<QString, QString>::const_iterator settingsIter = mUserSettings.begin(); |     std::vector<QString>::iterator commentStart = fileCopy.end(); | ||||||
|     for (; settingsIter != mUserSettings.end(); ++settingsIter) |     std::map<QString, std::vector<QString> > commentsMap; | ||||||
|     { |  | ||||||
|         settingLine = settingsIter.key()+"="+settingsIter.value(); |  | ||||||
|         if (settingRegex.indexIn(settingLine) != -1) |  | ||||||
|         { |  | ||||||
|             userSettingsCopy[settingRegex.cap(1)+"="+settingRegex.cap(2)] = |  | ||||||
|                 (settingRegex.captureCount() < 3) ? "" : settingRegex.cap(3); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     QString keyVal; |  | ||||||
|     for (std::vector<QString>::iterator iter = fileCopy.begin(); iter != fileCopy.end(); ++iter) |     for (std::vector<QString>::iterator iter = fileCopy.begin(); iter != fileCopy.end(); ++iter) | ||||||
|     { |     { | ||||||
|         // skip empty or comment lines
 |         if (isOrderedLine(*iter)) | ||||||
|         if ((*iter).isEmpty() || (*iter).contains(QRegExp("^\\s*#"))) |  | ||||||
|             continue; |  | ||||||
| 
 |  | ||||||
|         // look for a key in the line
 |  | ||||||
|         if (settingRegex.indexIn(*iter) == -1 || settingRegex.captureCount() < 2) |  | ||||||
|         { |         { | ||||||
|             // no key or first part of value found in line, replace with a null string which
 |             // save in a separate map of comments keyed by "ordered" line
 | ||||||
|             // will be remved later
 |             if (!comments.empty()) | ||||||
|             *iter = QString(); |             { | ||||||
|             continue; |                 if (settingRegex.indexIn(*iter) != -1) | ||||||
|  |                 { | ||||||
|  |                     commentsMap[settingRegex.cap(1)+"="+settingRegex.cap(2)] = comments; | ||||||
|  |                     comments.clear(); | ||||||
|  |                     commentStart = fileCopy.end(); | ||||||
|  |                 } | ||||||
|  |                 // else do nothing, malformed line
 | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             *iter = QString(); // "ordered" lines to be removed later
 | ||||||
|         } |         } | ||||||
| 
 |         else if ((*iter).isEmpty() || (*iter).contains(QRegExp("^\\s*#"))) | ||||||
|         // look for a matching key in user settings
 |  | ||||||
|         keyVal = settingRegex.cap(1)+"="+settingRegex.cap(2); |  | ||||||
|         QMap<QString, QString>::iterator it = userSettingsCopy.find(keyVal); |  | ||||||
|         if (it == userSettingsCopy.end()) |  | ||||||
|         { |         { | ||||||
|             // no such key+valStart, replace with a null string which will be remved later
 |             // comment line, save in temp buffer
 | ||||||
|             *iter = QString(); |             if (comments.empty()) | ||||||
|  |                 commentStart = iter; | ||||||
|  | 
 | ||||||
|  |             // special removed content processing
 | ||||||
|  |             if ((*iter).contains(QRegExp("^##content\\s*="))) | ||||||
|  |             { | ||||||
|  |                 if (!comments.empty()) | ||||||
|  |                 { | ||||||
|  |                     commentsMap[*iter] = comments; | ||||||
|  |                     comments.clear(); | ||||||
|  |                     commentStart = fileCopy.end(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             else | ||||||
|  |                 comments.push_back(*iter); | ||||||
|  | 
 | ||||||
|  |             *iter = QString(); // assume to be deleted later
 | ||||||
|         } |         } | ||||||
|         else |         else | ||||||
|         { |         { | ||||||
|             *iter = QString(it.key()+it.value()); |             int index = settingRegex.indexIn(*iter); | ||||||
|             userSettingsCopy.erase(it); | 
 | ||||||
|  |             // blank or non-"ordered" line, write saved comments
 | ||||||
|  |             if (!comments.empty() && index != -1 && settingRegex.captureCount() >= 2 && | ||||||
|  |                 mUserSettings.find(settingRegex.cap(1)) != mUserSettings.end()) | ||||||
|  |             { | ||||||
|  |                 for (std::vector<QString>::const_iterator it = comments.begin(); it != comments.end(); ++it) | ||||||
|  |                 { | ||||||
|  |                     *commentStart = *it; | ||||||
|  |                     ++commentStart; | ||||||
|  |                 } | ||||||
|  |                 comments.clear(); | ||||||
|  |                 commentStart = fileCopy.end(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // keep blank lines and non-"ordered" lines other than comments
 | ||||||
|  | 
 | ||||||
|  |             // look for a key in the line
 | ||||||
|  |             if (index == -1 || settingRegex.captureCount() < 2) | ||||||
|  |             { | ||||||
|  |                 // no key or first part of value found in line, replace with a null string which
 | ||||||
|  |                 // will be remved later
 | ||||||
|  |                 *iter = QString(); | ||||||
|  |                 comments.clear(); | ||||||
|  |                 commentStart = fileCopy.end(); | ||||||
|  |                 continue; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             // look for a matching key in user settings
 | ||||||
|  |             *iter = QString(); // assume no match
 | ||||||
|  |             QString key = settingRegex.cap(1); | ||||||
|  |             QString keyVal = settingRegex.cap(1)+"="+settingRegex.cap(2); | ||||||
|  |             QMap<QString, QString>::const_iterator i = mUserSettings.find(key); | ||||||
|  |             while (i != mUserSettings.end() && i.key() == key) | ||||||
|  |             { | ||||||
|  |                 QString settingLine = i.key() + "=" + i.value(); | ||||||
|  |                 if (settingRegex.indexIn(settingLine) != -1) | ||||||
|  |                 { | ||||||
|  |                     if ((settingRegex.cap(1)+"="+settingRegex.cap(2)) == keyVal) | ||||||
|  |                     { | ||||||
|  |                         *iter = settingLine; | ||||||
|  |                         break; | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 ++i; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // write the new config file
 |     // comments at top of file
 | ||||||
|     QString key; |  | ||||||
|     QString value; |  | ||||||
|     for (std::vector<QString>::iterator iter = fileCopy.begin(); iter != fileCopy.end(); ++iter) |     for (std::vector<QString>::iterator iter = fileCopy.begin(); iter != fileCopy.end(); ++iter) | ||||||
|     { |     { | ||||||
|         if ((*iter).isNull()) |         if ((*iter).isNull()) | ||||||
|  | @ -264,41 +342,82 @@ bool Config::GameSettings::writeFileWithComments(QFile &file) | ||||||
| 
 | 
 | ||||||
|         // Below is based on readFile() code, if that changes corresponding change may be
 |         // Below is based on readFile() code, if that changes corresponding change may be
 | ||||||
|         // required (for example duplicates may be inserted if the rules don't match)
 |         // required (for example duplicates may be inserted if the rules don't match)
 | ||||||
|         if ((*iter).isEmpty() || (*iter).contains(QRegExp("^\\s*#"))) |         if (/*(*iter).isEmpty() ||*/ (*iter).contains(QRegExp("^\\s*#"))) | ||||||
|         { |         { | ||||||
|             stream << *iter << "\n"; |             stream << *iter << "\n"; | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|         if (settingRegex.indexIn(*iter) == -1 || settingRegex.captureCount() < 2) |  | ||||||
|             continue; |  | ||||||
| 
 |  | ||||||
|         // Quote paths with spaces
 |  | ||||||
|         key = settingRegex.cap(1); |  | ||||||
|         value = settingRegex.cap(2)+settingRegex.cap(3); |  | ||||||
|         if (key == QLatin1String("data") |  | ||||||
|             || key == QLatin1String("data-local") |  | ||||||
|             || key == QLatin1String("resources")) |  | ||||||
|         { |  | ||||||
|             if (value.contains(QChar(' '))) |  | ||||||
|             { |  | ||||||
|                 value.remove(QChar('\"')); // Remove quotes
 |  | ||||||
| 
 |  | ||||||
|                 stream << key << "=\"" << value << "\"\n"; |  | ||||||
|                 continue; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|         stream << key << "=" << value << "\n"; |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (!userSettingsCopy.empty()) |     // Iterate in reverse order to preserve insertion order
 | ||||||
|  |     QString settingLine; | ||||||
|  |     QMapIterator<QString, QString> it(mUserSettings); | ||||||
|  |     it.toBack(); | ||||||
|  | 
 | ||||||
|  |     while (it.hasPrevious()) | ||||||
|     { |     { | ||||||
|         stream << "# new entries" << "\n"; |         it.previous(); | ||||||
|         QMap<QString, QString>::const_iterator it = userSettingsCopy.begin(); | 
 | ||||||
|         for (; it != userSettingsCopy.end(); ++it) |         // Quote paths with spaces
 | ||||||
|  |         if ((it.key() == QLatin1String("data") | ||||||
|  |              || it.key() == QLatin1String("data-local") | ||||||
|  |              || it.key() == QLatin1String("resources")) && it.value().contains(QChar(' '))) | ||||||
|         { |         { | ||||||
|             stream << it.key() << it.value() << "\n"; |             QString stripped = it.value(); | ||||||
|  |             stripped.remove(QChar('\"')); // Remove quotes
 | ||||||
|  | 
 | ||||||
|  |             settingLine = it.key() + "=\"" + stripped + "\""; | ||||||
|         } |         } | ||||||
|  |         else | ||||||
|  |             settingLine = it.key() + "=" + it.value(); | ||||||
|  | 
 | ||||||
|  |         if (settingRegex.indexIn(settingLine) != -1) | ||||||
|  |         { | ||||||
|  |             std::map<QString, std::vector<QString> >::iterator i = | ||||||
|  |                 commentsMap.find(settingRegex.cap(1)+"="+settingRegex.cap(2)); | ||||||
|  | 
 | ||||||
|  |             // check if previous removed content item with comments
 | ||||||
|  |             if (i == commentsMap.end()) | ||||||
|  |                 i = commentsMap.find("##"+settingRegex.cap(1)+"="+settingRegex.cap(2)); | ||||||
|  | 
 | ||||||
|  |             if (i != commentsMap.end()) | ||||||
|  |             { | ||||||
|  |                 std::vector<QString> cLines = i->second; | ||||||
|  |                 for (std::vector<QString>::const_iterator ci = cLines.begin(); ci != cLines.end(); ++ci) | ||||||
|  |                     stream << *ci << "\n"; | ||||||
|  | 
 | ||||||
|  |                 commentsMap.erase(i); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         stream << settingLine << "\n"; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // flush any removed settings
 | ||||||
|  |     if (!commentsMap.empty()) | ||||||
|  |     { | ||||||
|  |         std::map<QString, std::vector<QString> >::const_iterator i = commentsMap.begin(); | ||||||
|  |         for (; i != commentsMap.end(); ++i) | ||||||
|  |         { | ||||||
|  |             if (i->first.contains(QRegExp("^\\s*content\\s*="))) | ||||||
|  |             { | ||||||
|  |                 std::vector<QString> cLines = i->second; | ||||||
|  |                 for (std::vector<QString>::const_iterator ci = cLines.begin(); ci != cLines.end(); ++ci) | ||||||
|  |                     stream << *ci << "\n"; | ||||||
|  | 
 | ||||||
|  |                 // mark the content line entry for future preocessing
 | ||||||
|  |                 stream << "##" << i->first << "\n"; | ||||||
|  | 
 | ||||||
|  |                 //commentsMap.erase(i);
 | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // flush any end comments
 | ||||||
|  |     if (!comments.empty()) | ||||||
|  |     { | ||||||
|  |         for (std::vector<QString>::const_iterator ci = comments.begin(); ci != comments.end(); ++ci) | ||||||
|  |             stream << *ci << "\n"; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     file.resize(file.pos()); |     file.resize(file.pos()); | ||||||
|  |  | ||||||
|  | @ -83,6 +83,8 @@ namespace Config | ||||||
|         QString mDataLocal; |         QString mDataLocal; | ||||||
| 
 | 
 | ||||||
|         static const char sContentKey[]; |         static const char sContentKey[]; | ||||||
|  | 
 | ||||||
|  |         bool isOrderedLine(const QString& line) const; | ||||||
|     }; |     }; | ||||||
| } | } | ||||||
| #endif // GAMESETTINGS_HPP
 | #endif // GAMESETTINGS_HPP
 | ||||||
|  |  | ||||||
|  | @ -30,17 +30,6 @@ ContentSelectorModel::ContentModel::~ContentModel() | ||||||
| void ContentSelectorModel::ContentModel::setEncoding(const QString &encoding) | void ContentSelectorModel::ContentModel::setEncoding(const QString &encoding) | ||||||
| { | { | ||||||
|     mEncoding = encoding; |     mEncoding = encoding; | ||||||
|     if (encoding == QLatin1String("win1252")) |  | ||||||
|         mCodec = QTextCodec::codecForName("windows-1252"); |  | ||||||
| 
 |  | ||||||
|     else if (encoding == QLatin1String("win1251")) |  | ||||||
|         mCodec = QTextCodec::codecForName("windows-1251"); |  | ||||||
| 
 |  | ||||||
|     else if (encoding == QLatin1String("win1250")) |  | ||||||
|         mCodec = QTextCodec::codecForName("windows-1250"); |  | ||||||
| 
 |  | ||||||
|     else |  | ||||||
|         return; // This should never happen;
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int ContentSelectorModel::ContentModel::columnCount(const QModelIndex &parent) const | int ContentSelectorModel::ContentModel::columnCount(const QModelIndex &parent) const | ||||||
|  | @ -484,6 +473,13 @@ void ContentSelectorModel::ContentModel::addFiles(const QString &path) | ||||||
|     sortFiles(); |     sortFiles(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void ContentSelectorModel::ContentModel::clearFiles() | ||||||
|  | { | ||||||
|  |     beginRemoveRows(QModelIndex(), 0, mFiles.count()-1); | ||||||
|  |     mFiles.clear(); | ||||||
|  |     endRemoveRows(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| QStringList ContentSelectorModel::ContentModel::gameFiles() const | QStringList ContentSelectorModel::ContentModel::gameFiles() const | ||||||
| { | { | ||||||
|     QStringList gameFiles; |     QStringList gameFiles; | ||||||
|  |  | ||||||
|  | @ -44,6 +44,7 @@ namespace ContentSelectorModel | ||||||
|         bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); |         bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); | ||||||
| 
 | 
 | ||||||
|         void addFiles(const QString &path); |         void addFiles(const QString &path); | ||||||
|  |         void clearFiles(); | ||||||
| 
 | 
 | ||||||
|         QModelIndex indexFromItem(const EsmFile *item) const; |         QModelIndex indexFromItem(const EsmFile *item) const; | ||||||
|         const EsmFile *item(const QString &name) const; |         const EsmFile *item(const QString &name) const; | ||||||
|  | @ -81,7 +82,6 @@ namespace ContentSelectorModel | ||||||
|         ContentFileList mFiles; |         ContentFileList mFiles; | ||||||
|         QHash<QString, Qt::CheckState> mCheckStates; |         QHash<QString, Qt::CheckState> mCheckStates; | ||||||
|         QSet<QString> mPluginsWithLoadOrderError; |         QSet<QString> mPluginsWithLoadOrderError; | ||||||
|         QTextCodec *mCodec; |  | ||||||
|         QString mEncoding; |         QString mEncoding; | ||||||
|         QIcon mWarningIcon; |         QIcon mWarningIcon; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -150,6 +150,11 @@ void ContentSelectorView::ContentSelector::addFiles(const QString &path) | ||||||
|     mContentModel->uncheckAll(); |     mContentModel->uncheckAll(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void ContentSelectorView::ContentSelector::clearFiles() | ||||||
|  | { | ||||||
|  |     mContentModel->clearFiles(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| QString ContentSelectorView::ContentSelector::currentFile() const | QString ContentSelectorView::ContentSelector::currentFile() const | ||||||
| { | { | ||||||
|     QModelIndex currentIdx = ui.addonView->currentIndex(); |     QModelIndex currentIdx = ui.addonView->currentIndex(); | ||||||
|  |  | ||||||
|  | @ -29,6 +29,7 @@ namespace ContentSelectorView | ||||||
|         QString currentFile() const; |         QString currentFile() const; | ||||||
| 
 | 
 | ||||||
|         void addFiles(const QString &path); |         void addFiles(const QString &path); | ||||||
|  |         void clearFiles(); | ||||||
|         void setProfileContent (const QStringList &fileList); |         void setProfileContent (const QStringList &fileList); | ||||||
| 
 | 
 | ||||||
|         void clearCheckStates(); |         void clearCheckStates(); | ||||||
|  |  | ||||||
|  | @ -12,6 +12,8 @@ class ESMWriter; | ||||||
| struct Activator | struct Activator | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "Activator"; } | ||||||
| 
 | 
 | ||||||
|     std::string mId, mName, mScript, mModel; |     std::string mId, mName, mScript, mModel; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -19,6 +19,9 @@ struct Potion | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
| 
 | 
 | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "Potion"; } | ||||||
|  | 
 | ||||||
|     struct ALDTstruct |     struct ALDTstruct | ||||||
|     { |     { | ||||||
|         float mWeight; |         float mWeight; | ||||||
|  |  | ||||||
|  | @ -16,6 +16,8 @@ class ESMWriter; | ||||||
| struct Apparatus | struct Apparatus | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "Apparatus"; } | ||||||
| 
 | 
 | ||||||
|     enum AppaType |     enum AppaType | ||||||
|     { |     { | ||||||
|  |  | ||||||
|  | @ -66,6 +66,8 @@ struct PartReferenceList | ||||||
| struct Armor | struct Armor | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "Armor"; } | ||||||
| 
 | 
 | ||||||
|     enum Type |     enum Type | ||||||
|     { |     { | ||||||
|  |  | ||||||
|  | @ -12,6 +12,8 @@ class ESMWriter; | ||||||
| struct BodyPart | struct BodyPart | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "BodyPart"; } | ||||||
| 
 | 
 | ||||||
|     enum MeshPart |     enum MeshPart | ||||||
|     { |     { | ||||||
|  |  | ||||||
|  | @ -15,6 +15,8 @@ class ESMWriter; | ||||||
| struct Book | struct Book | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "Book"; } | ||||||
| 
 | 
 | ||||||
|     struct BKDTstruct |     struct BKDTstruct | ||||||
|     { |     { | ||||||
|  |  | ||||||
|  | @ -14,6 +14,8 @@ class ESMWriter; | ||||||
| struct BirthSign | struct BirthSign | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "BirthSign"; } | ||||||
| 
 | 
 | ||||||
|     std::string mId, mName, mDescription, mTexture; |     std::string mId, mName, mDescription, mTexture; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -56,6 +56,8 @@ typedef std::list<CellRef> CellRefTracker; | ||||||
| struct Cell | struct Cell | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "Cell"; } | ||||||
| 
 | 
 | ||||||
|   enum Flags |   enum Flags | ||||||
|     { |     { | ||||||
|  |  | ||||||
|  | @ -18,6 +18,8 @@ class ESMWriter; | ||||||
| struct Class | struct Class | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "Class"; } | ||||||
| 
 | 
 | ||||||
|     enum AutoCalc |     enum AutoCalc | ||||||
|     { |     { | ||||||
|  |  | ||||||
|  | @ -18,6 +18,8 @@ class ESMWriter; | ||||||
| struct Clothing | struct Clothing | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "Clothing"; } | ||||||
| 
 | 
 | ||||||
|     enum Type |     enum Type | ||||||
|     { |     { | ||||||
|  |  | ||||||
|  | @ -36,6 +36,8 @@ struct InventoryList | ||||||
| struct Container | struct Container | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "Container"; } | ||||||
| 
 | 
 | ||||||
|     enum Flags |     enum Flags | ||||||
|     { |     { | ||||||
|  |  | ||||||
|  | @ -22,6 +22,8 @@ class ESMWriter; | ||||||
| struct Creature | struct Creature | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "Creature"; } | ||||||
| 
 | 
 | ||||||
|     // Default is 0x48?
 |     // Default is 0x48?
 | ||||||
|     enum Flags |     enum Flags | ||||||
|  |  | ||||||
|  | @ -21,6 +21,8 @@ class ESMWriter; | ||||||
| struct Dialogue | struct Dialogue | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "Dialogue"; } | ||||||
| 
 | 
 | ||||||
|     enum Type |     enum Type | ||||||
|     { |     { | ||||||
|  |  | ||||||
|  | @ -12,6 +12,8 @@ class ESMWriter; | ||||||
| struct Door | struct Door | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "Door"; } | ||||||
| 
 | 
 | ||||||
|     std::string mId, mName, mModel, mScript, mOpenSound, mCloseSound; |     std::string mId, mName, mModel, mScript, mOpenSound, mCloseSound; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -18,6 +18,8 @@ class ESMWriter; | ||||||
| struct Enchantment | struct Enchantment | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "Enchantment"; } | ||||||
| 
 | 
 | ||||||
|     enum Type |     enum Type | ||||||
|     { |     { | ||||||
|  |  | ||||||
|  | @ -30,6 +30,8 @@ struct RankData | ||||||
| struct Faction | struct Faction | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "Faction"; } | ||||||
| 
 | 
 | ||||||
|     std::string mId, mName; |     std::string mId, mName; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -18,6 +18,8 @@ class ESMWriter; | ||||||
| struct Global | struct Global | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "Global"; } | ||||||
| 
 | 
 | ||||||
|     std::string mId; |     std::string mId; | ||||||
|     Variant mValue; |     Variant mValue; | ||||||
|  |  | ||||||
|  | @ -19,6 +19,8 @@ class ESMWriter; | ||||||
| struct GameSetting | struct GameSetting | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "GameSetting"; } | ||||||
| 
 | 
 | ||||||
|     std::string mId; |     std::string mId; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -21,6 +21,8 @@ class ESMWriter; | ||||||
| struct DialInfo | struct DialInfo | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "DialInfo"; } | ||||||
| 
 | 
 | ||||||
|     enum Gender |     enum Gender | ||||||
|     { |     { | ||||||
|  |  | ||||||
|  | @ -16,6 +16,8 @@ class ESMWriter; | ||||||
| struct Ingredient | struct Ingredient | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "Ingredient"; } | ||||||
| 
 | 
 | ||||||
|     struct IRDTstruct |     struct IRDTstruct | ||||||
|     { |     { | ||||||
|  |  | ||||||
|  | @ -18,6 +18,8 @@ class ESMWriter; | ||||||
| struct Land | struct Land | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "Land"; } | ||||||
| 
 | 
 | ||||||
|     Land(); |     Land(); | ||||||
|     ~Land(); |     ~Land(); | ||||||
|  |  | ||||||
|  | @ -46,6 +46,8 @@ struct LevelledListBase | ||||||
| struct CreatureLevList: LevelledListBase | struct CreatureLevList: LevelledListBase | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "CreatureLevList"; } | ||||||
| 
 | 
 | ||||||
|     enum Flags |     enum Flags | ||||||
|     { |     { | ||||||
|  | @ -64,6 +66,8 @@ struct CreatureLevList: LevelledListBase | ||||||
| struct ItemLevList: LevelledListBase | struct ItemLevList: LevelledListBase | ||||||
| { | { | ||||||
|     static unsigned int sRecordId; |     static unsigned int sRecordId; | ||||||
|  |     /// Return a string descriptor for this record type. Currently used for debugging / error logs only.
 | ||||||
|  |     static std::string getRecordType() { return "ItemLevList"; } | ||||||
| 
 | 
 | ||||||
|     enum Flags |     enum Flags | ||||||
|     { |     { | ||||||
|  |  | ||||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
		Reference in a new issue