mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-31 06:45:35 +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