mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-29 06:15:32 +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
|
||||
script:
|
||||
- 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
|
||||
after_script:
|
||||
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi
|
||||
|
|
|
@ -98,25 +98,29 @@ endif()
|
|||
cmake_minimum_required(VERSION 2.6)
|
||||
|
||||
# Sound setup
|
||||
set(FFmpeg_FIND_COMPONENTS AVCODEC AVFORMAT AVUTIL SWSCALE SWRESAMPLE AVRESAMPLE)
|
||||
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 )
|
||||
message(FATAL_ERROR "FFmpeg component required, but not found!")
|
||||
endif()
|
||||
set(SOUND_INPUT_INCLUDES ${FFMPEG_INCLUDE_DIRS})
|
||||
set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${SWSCALE_LIBRARIES})
|
||||
if( SWRESAMPLE_FOUND )
|
||||
add_definitions(-DHAVE_LIBSWRESAMPLE)
|
||||
set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${SWRESAMPLE_LIBRARIES})
|
||||
set (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${SWRESAMPLE_LIBRARIES})
|
||||
else()
|
||||
if( AVRESAMPLE_FOUND )
|
||||
set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES} ${AVRESAMPLE_LIBRARIES})
|
||||
set (FFMPEG_LIBRARIES ${FFMPEG_LIBRARIES} ${AVRESAMPLE_LIBRARIES})
|
||||
else()
|
||||
message(FATAL_ERROR "Install either libswresample (FFmpeg) or libavresample (Libav).")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(SOUND_INPUT_LIBRARY ${FFMPEG_LIBRARIES})
|
||||
|
||||
# TinyXML
|
||||
option(USE_SYSTEM_TINYXML "Use system TinyXML library instead of internal." OFF)
|
||||
if(USE_SYSTEM_TINYXML)
|
||||
|
@ -151,6 +155,19 @@ endif()
|
|||
|
||||
# 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
|
||||
if (UNIX AND NOT APPLE)
|
||||
find_package (Threads)
|
||||
|
@ -171,7 +188,7 @@ if (HAVE_UNORDERED_MAP)
|
|||
endif ()
|
||||
|
||||
|
||||
set(BOOST_COMPONENTS system filesystem program_options)
|
||||
set(BOOST_COMPONENTS system filesystem program_options thread wave)
|
||||
if(WIN32)
|
||||
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale)
|
||||
endif(WIN32)
|
||||
|
|
|
@ -9,7 +9,8 @@ add_executable(bsatool
|
|||
)
|
||||
|
||||
target_link_libraries(bsatool
|
||||
${Boost_LIBRARIES}
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
${Boost_FILESYSTEM_LIBRARY}
|
||||
components
|
||||
)
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ add_executable(esmtool
|
|||
)
|
||||
|
||||
target_link_libraries(esmtool
|
||||
${Boost_LIBRARIES}
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
components
|
||||
)
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ std::string clothingTypeLabel(int idx)
|
|||
}
|
||||
|
||||
std::string armorTypeLabel(int idx)
|
||||
{
|
||||
{
|
||||
if (idx >= 0 && idx <= 10)
|
||||
{
|
||||
static const char *armorTypeLabels[] = {
|
||||
|
@ -645,7 +645,7 @@ std::string ruleFunction(int idx)
|
|||
else
|
||||
return "Invalid";
|
||||
}
|
||||
|
||||
|
||||
// The "unused flag bits" should probably be defined alongside the
|
||||
// defined bits in the ESM component. The names of the flag bits are
|
||||
// very inconsistent.
|
||||
|
@ -653,7 +653,7 @@ std::string ruleFunction(int idx)
|
|||
std::string bodyPartFlags(int flags)
|
||||
{
|
||||
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_NotPlayable) properties += "NotPlayable ";
|
||||
int unused = (0xFFFFFFFF ^
|
||||
|
@ -667,7 +667,7 @@ std::string bodyPartFlags(int flags)
|
|||
std::string cellFlags(int flags)
|
||||
{
|
||||
std::string properties = "";
|
||||
if (flags == 0) properties += "[None] ";
|
||||
if (flags == 0) properties += "[None] ";
|
||||
if (flags & ESM::Cell::HasWater) properties += "HasWater ";
|
||||
if (flags & ESM::Cell::Interior) properties += "Interior ";
|
||||
if (flags & ESM::Cell::NoSleep) properties += "NoSleep ";
|
||||
|
@ -830,12 +830,12 @@ std::string npcFlags(int flags)
|
|||
std::string properties = "";
|
||||
if (flags == 0) properties += "[None] ";
|
||||
// Mythicmods and the ESM component differ. Mythicmods says
|
||||
// 0x8=None and 0x10=AutoCalc, while our code defines 0x8 as
|
||||
// AutoCalc. The former seems to be correct. All Bethesda
|
||||
// records have bit 0x8 set. A suspiciously large portion of
|
||||
// females have autocalc turned off.
|
||||
if (flags & ESM::NPC::Autocalc) properties += "Unknown ";
|
||||
if (flags & 0x00000010) properties += "Autocalc ";
|
||||
// 0x8=None and 0x10=AutoCalc, while our code previously defined
|
||||
// 0x8 as AutoCalc. The former seems to be correct. All Bethesda
|
||||
// records have bit 0x8 set. Previously, suspiciously large portion
|
||||
// of females had autocalc turned off.
|
||||
if (flags & 0x00000008) properties += "Unknown ";
|
||||
if (flags & ESM::NPC::Autocalc) properties += "Autocalc ";
|
||||
if (flags & ESM::NPC::Female) properties += "Female ";
|
||||
if (flags & ESM::NPC::Respawn) properties += "Respawn ";
|
||||
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
|
||||
// relatively few NPCs have this bit set.
|
||||
int unused = (0xFFFFFFFF ^
|
||||
(ESM::NPC::Autocalc|
|
||||
0x00000010|
|
||||
(0x00000008|
|
||||
ESM::NPC::Autocalc|
|
||||
ESM::NPC::Female|
|
||||
ESM::NPC::Respawn|
|
||||
ESM::NPC::Essential|
|
||||
|
|
|
@ -33,7 +33,8 @@ add_executable(openmw-essimporter
|
|||
)
|
||||
|
||||
target_link_libraries(openmw-essimporter
|
||||
${Boost_LIBRARIES}
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
${Boost_FILESYSTEM_LIBRARY}
|
||||
components
|
||||
)
|
||||
|
||||
|
|
|
@ -57,7 +57,6 @@ set(LAUNCHER_UI
|
|||
|
||||
source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER})
|
||||
|
||||
find_package(Qt4 REQUIRED)
|
||||
set(QT_USE_QTGUI 1)
|
||||
|
||||
# Set some platform specific settings
|
||||
|
@ -66,12 +65,17 @@ if(WIN32)
|
|||
set(QT_USE_QTMAIN TRUE)
|
||||
endif(WIN32)
|
||||
|
||||
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})
|
||||
if (DESIRED_QT_VERSION MATCHES 4)
|
||||
include(${QT_USE_FILE})
|
||||
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})
|
||||
if(NOT WIN32)
|
||||
include_directories(${LIBUNSHIELD_INCLUDE_DIR})
|
||||
|
@ -88,17 +92,27 @@ add_executable(openmw-launcher
|
|||
)
|
||||
|
||||
target_link_libraries(openmw-launcher
|
||||
${Boost_LIBRARIES}
|
||||
${OGRE_LIBRARIES}
|
||||
${OGRE_STATIC_PLUGINS}
|
||||
${SDL2_LIBRARY_ONLY}
|
||||
${QT_LIBRARIES}
|
||||
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)
|
||||
add_definitions (--coverage)
|
||||
target_link_libraries(openmw-launcher gcov)
|
||||
endif()
|
||||
|
||||
|
||||
|
|
|
@ -54,9 +54,6 @@ int main(int argc, char *argv[])
|
|||
|
||||
QDir::setCurrent(dir.absolutePath());
|
||||
|
||||
// Support non-latin characters
|
||||
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
|
||||
|
||||
Launcher::MainDialog mainWin;
|
||||
|
||||
Launcher::FirstRunDialogResult result = mainWin.showFirstRunDialog();
|
||||
|
|
|
@ -14,10 +14,16 @@ add_executable(openmw-iniimporter
|
|||
)
|
||||
|
||||
target_link_libraries(openmw-iniimporter
|
||||
${Boost_LIBRARIES}
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
${Boost_FILESYSTEM_LIBRARY}
|
||||
components
|
||||
)
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(openmw-iniimporter
|
||||
${Boost_LOCALE_LIBRARY})
|
||||
endif()
|
||||
|
||||
if (MINGW)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -municode")
|
||||
endif()
|
||||
|
|
|
@ -18,7 +18,7 @@ opencs_hdrs_noqt (model/doc
|
|||
|
||||
|
||||
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
|
||||
mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
|
||||
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
|
||||
subviews enumdelegate vartypedelegate recordstatusdelegate idtypedelegate datadisplaydelegate
|
||||
scripthighlighter idvalidator dialoguecreator physicssystem idcompletiondelegate
|
||||
colordelegate
|
||||
)
|
||||
|
||||
opencs_units (view/widget
|
||||
scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton
|
||||
scenetooltoggle2 completerpopup
|
||||
scenetooltoggle2 completerpopup coloreditor colorpickerpopup
|
||||
)
|
||||
|
||||
opencs_units (view/render
|
||||
|
@ -153,19 +154,16 @@ if(WIN32)
|
|||
set(QT_USE_QTMAIN TRUE)
|
||||
endif(WIN32)
|
||||
|
||||
set(BOOST_COMPONENTS system filesystem program_options thread wave)
|
||||
if(WIN32)
|
||||
set(BOOST_COMPONENTS ${BOOST_COMPONENTS} locale)
|
||||
endif(WIN32)
|
||||
|
||||
find_package(Boost REQUIRED COMPONENTS ${BOOST_COMPONENTS})
|
||||
|
||||
find_package(Qt4 COMPONENTS QtCore QtGui QtNetwork REQUIRED)
|
||||
include(${QT_USE_FILE})
|
||||
|
||||
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})
|
||||
if (DESIRED_QT_VERSION MATCHES 4)
|
||||
include(${QT_USE_FILE})
|
||||
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})
|
||||
else()
|
||||
qt5_wrap_ui(OPENCS_UI_HDR ${OPENCS_UI})
|
||||
qt5_wrap_cpp(OPENCS_MOC_SRC ${OPENCS_HDR_QT})
|
||||
qt5_add_resources(OPENCS_RES_SRC ${OPENCS_RES})
|
||||
endif()
|
||||
|
||||
# for compiled .ui files
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
@ -206,12 +204,36 @@ target_link_libraries(openmw-cs
|
|||
${OGRE_Overlay_LIBRARIES}
|
||||
${OGRE_STATIC_PLUGINS}
|
||||
${SHINY_LIBRARIES}
|
||||
${Boost_LIBRARIES}
|
||||
${Boost_SYSTEM_LIBRARY}
|
||||
${Boost_FILESYSTEM_LIBRARY}
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
${Boost_WAVE_LIBRARY}
|
||||
${BULLET_LIBRARIES}
|
||||
${QT_LIBRARIES}
|
||||
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)
|
||||
INSTALL(TARGETS openmw-cs BUNDLE DESTINATION OpenMW COMPONENT BUNDLE)
|
||||
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::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);
|
||||
|
||||
mCfgMgr.readConfiguration(variables, desc);
|
||||
mCfgMgr.readConfiguration(variables, desc, quiet);
|
||||
|
||||
mDocumentManager.setEncoding (
|
||||
ToUTF8::calculateEncoding (variables["encoding"].as<std::string>()));
|
||||
|
@ -198,6 +198,11 @@ void CS::Editor::cancelCreateGame()
|
|||
void CS::Editor::createAddon()
|
||||
{
|
||||
mStartup.hide();
|
||||
|
||||
mFileDialog.clearFiles();
|
||||
std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig(/*quiet*/true);
|
||||
setupDataFiles (config.first);
|
||||
|
||||
mFileDialog.showDialog (CSVDoc::ContentAction_New);
|
||||
}
|
||||
|
||||
|
@ -218,6 +223,11 @@ void CS::Editor::cancelFileDialog()
|
|||
void CS::Editor::loadDocument()
|
||||
{
|
||||
mStartup.hide();
|
||||
|
||||
mFileDialog.clearFiles();
|
||||
std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig(/*quiet*/true);
|
||||
setupDataFiles (config.first);
|
||||
|
||||
mFileDialog.showDialog (CSVDoc::ContentAction_Edit);
|
||||
}
|
||||
|
||||
|
@ -312,12 +322,12 @@ bool CS::Editor::makeIPCServer()
|
|||
mServer->close();
|
||||
fullPath.remove(QRegExp("dummy$"));
|
||||
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
|
||||
std::cout << "Detected unclean shutdown." << std::endl;
|
||||
// delete the stale file
|
||||
if(remove(fullPath.toStdString().c_str()))
|
||||
if(remove(fullPath.toUtf8().constData()))
|
||||
std::cerr << "ERROR removing stale connection file" << std::endl;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ namespace CS
|
|||
|
||||
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
|
||||
|
||||
// not implemented
|
||||
|
|
|
@ -2272,7 +2272,7 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
|||
|
||||
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
|
||||
{
|
||||
|
|
|
@ -244,6 +244,47 @@ void CSMSettings::UserSettings::buildSettingModelDefaults()
|
|||
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");
|
||||
{
|
||||
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.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?
|
||||
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 "searchoperation.hpp"
|
||||
#include "pathgridcheck.hpp"
|
||||
#include "soundgencheck.hpp"
|
||||
|
||||
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 SoundGenCheckStage (mData.getSoundGens(),
|
||||
mData.getSounds(),
|
||||
mData.getReferenceables()));
|
||||
|
||||
mVerifier.setOperation (mVerifierOperation);
|
||||
}
|
||||
|
||||
|
|
|
@ -694,7 +694,7 @@ namespace CSMWorld
|
|||
|
||||
QColor colour = data.value<QColor>();
|
||||
|
||||
record2.mMapColor = colour.rgb() & 0xffffff;
|
||||
record2.mMapColor = (colour.blue() << 16) | (colour.green() << 8) | colour.red();
|
||||
|
||||
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)
|
||||
{
|
||||
beginResetModel();
|
||||
mFilter = filter;
|
||||
updateColumnMap();
|
||||
reset();
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
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>&> (
|
||||
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Potion)));
|
||||
|
||||
ESM::Potion potion = record.get();
|
||||
|
||||
if (column==mAutoCalc)
|
||||
record.get().mData.mAutoCalc = value.toInt();
|
||||
potion.mData.mAutoCalc = value.toInt();
|
||||
else
|
||||
{
|
||||
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>&> (
|
||||
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Apparatus)));
|
||||
|
||||
ESM::Apparatus apparatus = record.get();
|
||||
|
||||
if (column==mType)
|
||||
record.get().mData.mType = value.toInt();
|
||||
apparatus.mData.mType = value.toInt();
|
||||
else if (column==mQuality)
|
||||
record.get().mData.mQuality = value.toFloat();
|
||||
apparatus.mData.mQuality = value.toFloat();
|
||||
else
|
||||
{
|
||||
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>&> (
|
||||
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Armor)));
|
||||
|
||||
ESM::Armor armor = record.get();
|
||||
|
||||
if (column==mType)
|
||||
record.get().mData.mType = value.toInt();
|
||||
armor.mData.mType = value.toInt();
|
||||
else if (column==mHealth)
|
||||
record.get().mData.mHealth = value.toInt();
|
||||
armor.mData.mHealth = value.toInt();
|
||||
else if (column==mArmor)
|
||||
record.get().mData.mArmor = value.toInt();
|
||||
armor.mData.mArmor = value.toInt();
|
||||
else
|
||||
{
|
||||
EnchantableRefIdAdapter<ESM::Armor>::setData (column, data, index, value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
record.setModified(armor);
|
||||
}
|
||||
|
||||
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>&> (
|
||||
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Book)));
|
||||
|
||||
ESM::Book book = record.get();
|
||||
|
||||
if (column==mScroll)
|
||||
record.get().mData.mIsScroll = value.toInt();
|
||||
book.mData.mIsScroll = value.toInt();
|
||||
else if (column==mSkill)
|
||||
record.get().mData.mSkillID = value.toInt();
|
||||
book.mData.mSkillID = value.toInt();
|
||||
else
|
||||
{
|
||||
EnchantableRefIdAdapter<ESM::Book>::setData (column, data, index, value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
record.setModified(book);
|
||||
}
|
||||
|
||||
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>&> (
|
||||
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Clothing)));
|
||||
|
||||
ESM::Clothing clothing = record.get();
|
||||
|
||||
if (column==mType)
|
||||
record.get().mData.mType = value.toInt();
|
||||
clothing.mData.mType = value.toInt();
|
||||
else
|
||||
{
|
||||
EnchantableRefIdAdapter<ESM::Clothing>::setData (column, data, index, value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
record.setModified(clothing);
|
||||
}
|
||||
|
||||
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>&> (
|
||||
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Container)));
|
||||
|
||||
ESM::Container container = record.get();
|
||||
|
||||
if (column==mWeight)
|
||||
record.get().mWeight = value.toFloat();
|
||||
container.mWeight = value.toFloat();
|
||||
else if (column==mOrganic)
|
||||
{
|
||||
if (value.toInt())
|
||||
record.get().mFlags |= ESM::Container::Organic;
|
||||
container.mFlags |= ESM::Container::Organic;
|
||||
else
|
||||
record.get().mFlags &= ~ESM::Container::Organic;
|
||||
container.mFlags &= ~ESM::Container::Organic;
|
||||
}
|
||||
else if (column==mRespawn)
|
||||
{
|
||||
if (value.toInt())
|
||||
record.get().mFlags |= ESM::Container::Respawn;
|
||||
container.mFlags |= ESM::Container::Respawn;
|
||||
else
|
||||
record.get().mFlags &= ~ESM::Container::Respawn;
|
||||
container.mFlags &= ~ESM::Container::Respawn;
|
||||
}
|
||||
else
|
||||
{
|
||||
NameRefIdAdapter<ESM::Container>::setData (column, data, index, value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
record.setModified(container);
|
||||
}
|
||||
|
||||
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>&> (
|
||||
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature)));
|
||||
|
||||
ESM::Creature creature = record.get();
|
||||
|
||||
if (column==mColumns.mType)
|
||||
record.get().mData.mType = value.toInt();
|
||||
creature.mData.mType = value.toInt();
|
||||
else if (column==mColumns.mSoul)
|
||||
record.get().mData.mSoul = value.toInt();
|
||||
creature.mData.mSoul = value.toInt();
|
||||
else if (column==mColumns.mScale)
|
||||
record.get().mScale = value.toFloat();
|
||||
creature.mScale = value.toFloat();
|
||||
else if (column==mColumns.mOriginal)
|
||||
record.get().mOriginal = value.toString().toUtf8().constData();
|
||||
creature.mOriginal = value.toString().toUtf8().constData();
|
||||
else if (column==mColumns.mCombat)
|
||||
record.get().mData.mCombat = value.toInt();
|
||||
creature.mData.mCombat = value.toInt();
|
||||
else if (column==mColumns.mMagic)
|
||||
record.get().mData.mMagic = value.toInt();
|
||||
creature.mData.mMagic = value.toInt();
|
||||
else if (column==mColumns.mStealth)
|
||||
record.get().mData.mStealth = value.toInt();
|
||||
creature.mData.mStealth = value.toInt();
|
||||
else
|
||||
{
|
||||
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 (value.toInt()!=0)
|
||||
record.get().mFlags |= iter->second;
|
||||
creature.mFlags |= iter->second;
|
||||
else
|
||||
record.get().mFlags &= ~iter->second;
|
||||
creature.mFlags &= ~iter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
ActorRefIdAdapter<ESM::Creature>::setData (column, data, index, value);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
record.setModified(creature);
|
||||
}
|
||||
|
||||
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>&> (
|
||||
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Door)));
|
||||
|
||||
ESM::Door door = record.get();
|
||||
|
||||
if (column==mOpenSound)
|
||||
record.get().mOpenSound = value.toString().toUtf8().constData();
|
||||
door.mOpenSound = value.toString().toUtf8().constData();
|
||||
else if (column==mCloseSound)
|
||||
record.get().mCloseSound = value.toString().toUtf8().constData();
|
||||
door.mCloseSound = value.toString().toUtf8().constData();
|
||||
else
|
||||
{
|
||||
NameRefIdAdapter<ESM::Door>::setData (column, data, index, value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
record.setModified(door);
|
||||
}
|
||||
|
||||
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>&> (
|
||||
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Light)));
|
||||
|
||||
ESM::Light light = record.get();
|
||||
|
||||
if (column==mColumns.mTime)
|
||||
record.get().mData.mTime = value.toInt();
|
||||
light.mData.mTime = value.toInt();
|
||||
else if (column==mColumns.mRadius)
|
||||
record.get().mData.mRadius = value.toInt();
|
||||
light.mData.mRadius = value.toInt();
|
||||
else if (column==mColumns.mColor)
|
||||
record.get().mData.mColor = value.toInt();
|
||||
light.mData.mColor = value.toInt();
|
||||
else if (column==mColumns.mSound)
|
||||
record.get().mSound = value.toString().toUtf8().constData();
|
||||
light.mSound = value.toString().toUtf8().constData();
|
||||
else
|
||||
{
|
||||
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 (value.toInt()!=0)
|
||||
record.get().mData.mFlags |= iter->second;
|
||||
light.mData.mFlags |= iter->second;
|
||||
else
|
||||
record.get().mData.mFlags &= ~iter->second;
|
||||
light.mData.mFlags &= ~iter->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
InventoryRefIdAdapter<ESM::Light>::setData (column, data, index, value);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
record.setModified (light);
|
||||
}
|
||||
|
||||
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>&> (
|
||||
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Miscellaneous)));
|
||||
|
||||
ESM::Miscellaneous misc = record.get();
|
||||
|
||||
if (column==mKey)
|
||||
record.get().mData.mIsKey = value.toInt();
|
||||
misc.mData.mIsKey = value.toInt();
|
||||
else
|
||||
{
|
||||
InventoryRefIdAdapter<ESM::Miscellaneous>::setData (column, data, index, value);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
record.setModified(misc);
|
||||
}
|
||||
|
||||
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>&> (
|
||||
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc)));
|
||||
|
||||
ESM::NPC npc = record.get();
|
||||
|
||||
if (column==mColumns.mRace)
|
||||
record.get().mRace = value.toString().toUtf8().constData();
|
||||
npc.mRace = value.toString().toUtf8().constData();
|
||||
else if (column==mColumns.mClass)
|
||||
record.get().mClass = value.toString().toUtf8().constData();
|
||||
npc.mClass = value.toString().toUtf8().constData();
|
||||
else if (column==mColumns.mFaction)
|
||||
record.get().mFaction = value.toString().toUtf8().constData();
|
||||
npc.mFaction = value.toString().toUtf8().constData();
|
||||
else if (column==mColumns.mHair)
|
||||
record.get().mHair = value.toString().toUtf8().constData();
|
||||
npc.mHair = value.toString().toUtf8().constData();
|
||||
else if (column==mColumns.mHead)
|
||||
record.get().mHead = value.toString().toUtf8().constData();
|
||||
npc.mHead = value.toString().toUtf8().constData();
|
||||
else
|
||||
{
|
||||
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 (value.toInt()!=0)
|
||||
record.get().mFlags |= iter->second;
|
||||
npc.mFlags |= iter->second;
|
||||
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
|
||||
{
|
||||
ActorRefIdAdapter<ESM::NPC>::setData (column, data, index, value);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
record.setModified (npc);
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
if (iter!=mColours.end())
|
||||
return QBrush (
|
||||
QColor (iter->second>>24, (iter->second>>16) & 255, (iter->second>>8) & 255,
|
||||
iter->second & 255));
|
||||
return QBrush (QColor (iter->second & 0xff,
|
||||
(iter->second >> 8) & 0xff,
|
||||
(iter->second >> 16) & 0xff));
|
||||
|
||||
if (cell->second.mRegion.empty())
|
||||
return QBrush (Qt::Dense6Pattern); // no region
|
||||
|
|
|
@ -33,6 +33,11 @@ void CSVDoc::FileDialog::addFiles(const QString &path)
|
|||
mSelector->addFiles(path);
|
||||
}
|
||||
|
||||
void CSVDoc::FileDialog::clearFiles()
|
||||
{
|
||||
mSelector->clearFiles();
|
||||
}
|
||||
|
||||
QStringList CSVDoc::FileDialog::selectedFilePaths()
|
||||
{
|
||||
QStringList filePaths;
|
||||
|
@ -105,7 +110,6 @@ void CSVDoc::FileDialog::buildNewFileView()
|
|||
|
||||
connect (mFileWidget, SIGNAL (nameChanged(const QString &, bool)),
|
||||
this, SLOT (slotUpdateAcceptButton(const QString &, bool)));
|
||||
|
||||
}
|
||||
|
||||
ui.projectGroupBoxLayout->insertWidget (0, mFileWidget);
|
||||
|
@ -139,7 +143,7 @@ void CSVDoc::FileDialog::slotUpdateAcceptButton(int)
|
|||
{
|
||||
QString name = "";
|
||||
|
||||
if (mAction == ContentAction_New)
|
||||
if (mFileWidget && mAction == ContentAction_New)
|
||||
name = mFileWidget->getName();
|
||||
|
||||
slotUpdateAcceptButton (name, true);
|
||||
|
|
|
@ -45,6 +45,7 @@ namespace CSVDoc
|
|||
void showDialog (ContentAction action);
|
||||
|
||||
void addFiles (const QString &path);
|
||||
void clearFiles ();
|
||||
|
||||
QString filename() const;
|
||||
QStringList selectedFilePaths();
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include <QMenuBar>
|
||||
#include <QMdiArea>
|
||||
#include <QDockWidget>
|
||||
#include <QtGui/QApplication>
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QScrollArea>
|
||||
#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.
|
||||
// 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);
|
||||
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);
|
||||
|
@ -645,6 +643,17 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin
|
|||
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()
|
||||
{
|
||||
mViewManager.addView (mDocument);
|
||||
|
|
|
@ -243,6 +243,8 @@ namespace CSVDoc
|
|||
void closeRequest (SubView *subView);
|
||||
|
||||
void saveWindowState();
|
||||
|
||||
void moveScrollBarToEnd(int min, int max);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
|
||||
#include "../../model/doc/documentmanager.hpp"
|
||||
#include "../../model/doc/document.hpp"
|
||||
|
@ -19,15 +21,12 @@
|
|||
#include "../world/recordstatusdelegate.hpp"
|
||||
#include "../world/idtypedelegate.hpp"
|
||||
#include "../world/idcompletiondelegate.hpp"
|
||||
#include "../world/colordelegate.hpp"
|
||||
|
||||
#include "../../model/settings/usersettings.hpp"
|
||||
|
||||
#include "view.hpp"
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QtGui/QApplication>
|
||||
|
||||
void CSVDoc::ViewManager::updateIndices()
|
||||
{
|
||||
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,
|
||||
new CSVWorld::IdTypeDelegateFactory());
|
||||
|
||||
mDelegateFactories->add (CSMWorld::ColumnBase::Display_Colour,
|
||||
new CSVWorld::ColorDelegateFactory());
|
||||
|
||||
std::vector<CSMWorld::ColumnBase::Display> idCompletionColumns = CSMWorld::IdCompletionManager::getDisplayTypes();
|
||||
for (std::vector<CSMWorld::ColumnBase::Display>::const_iterator current = idCompletionColumns.begin();
|
||||
current != idCompletionColumns.end();
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
#include <OgreColourValue.h>
|
||||
#include <OgreCamera.h>
|
||||
|
||||
#include <QtGui/qevent.h>
|
||||
#include <QEvent>
|
||||
|
||||
#include "../../model/doc/document.hpp"
|
||||
|
||||
|
|
|
@ -7,7 +7,12 @@
|
|||
#include <OgreSceneManager.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/idtable.hpp"
|
||||
|
|
|
@ -8,19 +8,12 @@
|
|||
#include <QStackedWidget>
|
||||
#include <QtGui>
|
||||
#include <QSplitter>
|
||||
#include <QDesktopWidget>
|
||||
|
||||
#include "../../model/settings/usersettings.hpp"
|
||||
|
||||
#include "page.hpp"
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#include <QTreeView>
|
||||
#include <QListView>
|
||||
#include <QTableView>
|
||||
|
||||
#include <QStandardItemModel>
|
||||
#include <QStandardItem>
|
||||
|
||||
CSVSettings::Dialog::Dialog(QMainWindow *parent)
|
||||
: SettingWindow (parent), mStackedWidget (0), mDebugMode (false)
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
#include "settingwindow.hpp"
|
||||
#include "resizeablestackedwidget.hpp"
|
||||
#include <QStandardItem>
|
||||
|
||||
class QStackedWidget;
|
||||
class QListWidget;
|
||||
|
@ -26,10 +25,6 @@ namespace CSVSettings {
|
|||
|
||||
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:
|
||||
|
||||
/// Settings are written on close
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
#include <QStyledItemDelegate>
|
||||
#include <QTextDocument>
|
||||
#include <QPainter>
|
||||
#include <QContextMenuEvent>
|
||||
#include <QMouseEvent>
|
||||
|
||||
#include "../../model/tools/reportmodel.hpp"
|
||||
|
||||
|
@ -94,21 +96,35 @@ void CSVTools::ReportTable::mouseDoubleClickEvent (QMouseEvent *event)
|
|||
selectionModel()->select (index,
|
||||
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();
|
||||
showSelection();
|
||||
break;
|
||||
|
||||
case Qt::ShiftModifier:
|
||||
case Action_Remove:
|
||||
|
||||
event->accept();
|
||||
removeSelection();
|
||||
break;
|
||||
|
||||
case Qt::ControlModifier:
|
||||
case Action_EditAndRemove:
|
||||
|
||||
event->accept();
|
||||
showSelection();
|
||||
|
@ -121,7 +137,11 @@ CSVTools::ReportTable::ReportTable (CSMDoc::Document& document,
|
|||
const CSMWorld::UniversalId& id, bool richTextDescription, QWidget *parent)
|
||||
: 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);
|
||||
#endif
|
||||
horizontalHeader()->setStretchLastSection (true);
|
||||
verticalHeader()->hide();
|
||||
setSortingEnabled (true);
|
||||
|
@ -149,7 +169,11 @@ CSVTools::ReportTable::ReportTable (CSMDoc::Document& document,
|
|||
|
||||
mReplaceAction = new QAction (tr ("Replace"), this);
|
||||
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
|
||||
|
@ -170,6 +194,35 @@ std::vector<CSMWorld::UniversalId> CSVTools::ReportTable::getDraggedRecords() co
|
|||
void CSVTools::ReportTable::updateUserSetting (const QString& name, const QStringList& 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
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef CSV_TOOLS_REPORTTABLE_H
|
||||
#define CSV_TOOLS_REPORTTABLE_H
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "../world/dragrecordtable.hpp"
|
||||
|
||||
class QAction;
|
||||
|
@ -21,11 +23,20 @@ namespace CSVTools
|
|||
{
|
||||
Q_OBJECT
|
||||
|
||||
enum DoubleClickAction
|
||||
{
|
||||
Action_None,
|
||||
Action_Edit,
|
||||
Action_Remove,
|
||||
Action_EditAndRemove
|
||||
};
|
||||
|
||||
CSMTools::ReportModel *mModel;
|
||||
CSVWorld::CommandDelegate *mIdTypeDelegate;
|
||||
QAction *mShowAction;
|
||||
QAction *mRemoveAction;
|
||||
QAction *mReplaceAction;
|
||||
std::map<Qt::KeyboardModifiers, DoubleClickAction> mDoubleClickActions;
|
||||
|
||||
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->verticalHeader()->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 (1, QHeaderView::ResizeToContents);
|
||||
#endif
|
||||
mTable->setSelectionMode (QAbstractItemView::NoSelection);
|
||||
|
||||
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,
|
||||
QObject *parent)
|
||||
: 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)
|
||||
{
|
||||
mTextAlignment.setAlignment (Qt::AlignLeft | Qt::AlignVCenter );
|
||||
|
||||
buildPixmaps();
|
||||
|
||||
QString value =
|
||||
|
@ -45,16 +44,35 @@ void CSVWorld::DataDisplayDelegate::setIconSize(const QSize& size)
|
|||
buildPixmaps();
|
||||
}
|
||||
|
||||
void CSVWorld::DataDisplayDelegate::setIconLeftOffset(int offset)
|
||||
{
|
||||
mIconLeftOffset = offset;
|
||||
}
|
||||
|
||||
void CSVWorld::DataDisplayDelegate::setTextLeftOffset(int 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
|
||||
{
|
||||
painter->save();
|
||||
|
@ -64,16 +82,11 @@ void CSVWorld::DataDisplayDelegate::paint (QPainter *painter, const QStyleOption
|
|||
EnumDelegate::paint(painter, option, index);
|
||||
else
|
||||
{
|
||||
unsigned int i = 0;
|
||||
|
||||
for (; i < mValues.size(); ++i)
|
||||
int valueIndex = getValueIndex(index);
|
||||
if (valueIndex != -1)
|
||||
{
|
||||
if (mValues.at(i).first == index.data().toInt())
|
||||
break;
|
||||
paintIcon(painter, option, valueIndex);
|
||||
}
|
||||
|
||||
if (i < mValues.size() )
|
||||
paintIcon (painter, option, i);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
//function-level statics
|
||||
QRect iconRect = option.rect;
|
||||
QRect textRect = iconRect;
|
||||
|
||||
const QString &text = mValues.at(index).second;
|
||||
|
||||
iconRect.setSize (mIconSize);
|
||||
iconRect.translate(mIconLeftOffset, (option.rect.height() - iconRect.height())/2);
|
||||
|
||||
if (mDisplayMode == Mode_IconAndText )
|
||||
iconRect.setLeft(iconRect.left() + mHorizontalMargin);
|
||||
iconRect.setRight(option.rect.right() - mHorizontalMargin);
|
||||
if (mDisplayMode == Mode_IconAndText)
|
||||
{
|
||||
textRect.translate (iconRect.width() + mTextLeftOffset, 0 );
|
||||
painter->drawText (textRect, text, mTextAlignment);
|
||||
}
|
||||
else
|
||||
iconRect.translate( (option.rect.width() - iconRect.width()) / 2, 0);
|
||||
iconRect.setWidth(mIconSize.width());
|
||||
textRect.setLeft(iconRect.right() + mTextLeftOffset);
|
||||
textRect.setRight(option.rect.right() - mHorizontalMargin);
|
||||
|
||||
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,
|
||||
|
|
|
@ -30,9 +30,8 @@ namespace CSVWorld
|
|||
private:
|
||||
|
||||
std::vector <std::pair <int, QPixmap> > mPixmaps;
|
||||
QTextOption mTextAlignment;
|
||||
QSize mIconSize;
|
||||
int mIconLeftOffset;
|
||||
int mHorizontalMargin;
|
||||
int mTextLeftOffset;
|
||||
|
||||
QString mSettingKey;
|
||||
|
@ -46,12 +45,11 @@ namespace CSVWorld
|
|||
|
||||
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).
|
||||
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.
|
||||
void setTextLeftOffset (int offset);
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@
|
|||
#include "../../model/world/commands.hpp"
|
||||
#include "../../model/doc/document.hpp"
|
||||
|
||||
#include "../widget/coloreditor.hpp"
|
||||
|
||||
#include "recordstatusdelegate.hpp"
|
||||
#include "util.hpp"
|
||||
#include "tablebottombox.hpp"
|
||||
|
@ -331,6 +333,10 @@ QWidget* CSVWorld::DialogueDelegateDispatcher::makeEditor(CSMWorld::ColumnBase::
|
|||
{
|
||||
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
|
||||
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());
|
||||
|
||||
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)
|
||||
{
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <QDrag>
|
||||
#include <QDragEnterEvent>
|
||||
|
||||
#include "../../model/world/tablemimedata.hpp"
|
||||
#include "dragrecordtable.hpp"
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define CSV_WORLD_DRAGRECORDTABLE_H
|
||||
|
||||
#include <QTableView>
|
||||
#include <QtGui/qevent.h>
|
||||
#include <QEvent>
|
||||
|
||||
class QWidget;
|
||||
class QAction;
|
||||
|
|
|
@ -10,6 +10,24 @@
|
|||
|
||||
#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,
|
||||
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
|
||||
{
|
||||
if (QComboBox *comboBox = dynamic_cast<QComboBox *> (editor))
|
||||
if (QComboBox *comboBox = dynamic_cast<QComboBox *>(editor))
|
||||
{
|
||||
QVariant data = index.data (Qt::EditRole);
|
||||
|
||||
if (tryDisplay && !data.isValid())
|
||||
int role = Qt::EditRole;
|
||||
if (tryDisplay && !index.data(role).isValid())
|
||||
{
|
||||
data = index.data (Qt::DisplayRole);
|
||||
if (!data.isValid())
|
||||
role = Qt::DisplayRole;
|
||||
if (!index.data(role).isValid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int value = data.toInt();
|
||||
|
||||
std::size_t size = mValues.size();
|
||||
|
||||
for (std::size_t i=0; i<size; ++i)
|
||||
if (mValues[i].first==value)
|
||||
{
|
||||
comboBox->setCurrentIndex (i);
|
||||
break;
|
||||
}
|
||||
int valueIndex = getValueIndex(index, role);
|
||||
if (valueIndex != -1)
|
||||
{
|
||||
comboBox->setCurrentIndex(valueIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CSVWorld::EnumDelegate::paint (QPainter *painter, const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const
|
||||
{
|
||||
if (index.data().isValid())
|
||||
int valueIndex = getValueIndex(index);
|
||||
if (valueIndex != -1)
|
||||
{
|
||||
QStyleOptionViewItemV4 option2 (option);
|
||||
|
||||
int value = index.data().toInt();
|
||||
|
||||
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;
|
||||
}
|
||||
QStyleOptionViewItemV4 itemOption(option);
|
||||
itemOption.text = mValues.at(valueIndex).second;
|
||||
QApplication::style()->drawControl(QStyle::CE_ItemViewItem, &itemOption, painter);
|
||||
}
|
||||
}
|
||||
|
||||
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() {}
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ namespace CSVWorld
|
|||
|
||||
std::vector<std::pair<int, QString> > mValues;
|
||||
|
||||
int getValueIndex(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
|
||||
private:
|
||||
|
||||
virtual void setModelDataImp (QWidget *editor, QAbstractItemModel *model,
|
||||
|
@ -46,6 +48,8 @@ namespace CSVWorld
|
|||
virtual void paint (QPainter *painter, const QStyleOptionViewItem& option,
|
||||
const QModelIndex& index) const;
|
||||
|
||||
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
|
||||
|
||||
};
|
||||
|
||||
class EnumDelegateFactory : public CommandDelegateFactory
|
||||
|
|
|
@ -23,7 +23,11 @@ CSVWorld::NestedTable::NestedTable(CSMDoc::Document& document,
|
|||
setSelectionBehavior (QAbstractItemView::SelectRows);
|
||||
setSelectionMode (QAbstractItemView::ExtendedSelection);
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
horizontalHeader()->setSectionResizeMode (QHeaderView::Interactive);
|
||||
#else
|
||||
horizontalHeader()->setResizeMode (QHeaderView::Interactive);
|
||||
#endif
|
||||
verticalHeader()->hide();
|
||||
|
||||
int columns = model->columnCount(QModelIndex());
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define CSV_WORLD_NESTEDTABLE_H
|
||||
|
||||
#include <QTableView>
|
||||
#include <QtGui/qevent.h>
|
||||
#include <QEvent>
|
||||
|
||||
class QUndoStack;
|
||||
class QAction;
|
||||
|
|
|
@ -68,10 +68,10 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
|
|||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, JournalCreatorFactory>);
|
||||
|
||||
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,
|
||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<InfoCreator> > (false));
|
||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<InfoCreator> >);
|
||||
|
||||
// Subviews for resources tables
|
||||
manager.add (CSMWorld::UniversalId::Type_Meshes,
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "../../model/world/data.hpp"
|
||||
#include "../../model/world/commands.hpp"
|
||||
#include "../../model/world/infotableproxymodel.hpp"
|
||||
#include "../../model/world/idtableproxymodel.hpp"
|
||||
#include "../../model/world/idtablebase.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));
|
||||
|
||||
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);
|
||||
|
||||
mDispatcher = new CSMWorld::CommandDispatcher (document, id, this);
|
||||
|
||||
setModel (mProxyModel);
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
horizontalHeader()->setSectionResizeMode (QHeaderView::Interactive);
|
||||
#else
|
||||
horizontalHeader()->setResizeMode (QHeaderView::Interactive);
|
||||
#endif
|
||||
verticalHeader()->hide();
|
||||
setSortingEnabled (sorting);
|
||||
setSelectionBehavior (QAbstractItemView::SelectRows);
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include <QtGui/qevent.h>
|
||||
#include <QEvent>
|
||||
|
||||
#include "../../model/filter/node.hpp"
|
||||
#include "../../model/world/columnbase.hpp"
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include <QHeaderView>
|
||||
#include <QApplication>
|
||||
#include <QDesktopWidget>
|
||||
#include <QDropEvent>
|
||||
|
||||
#include "../../model/doc/document.hpp"
|
||||
#include "../../model/world/tablemimedata.hpp"
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "../../model/world/commands.hpp"
|
||||
#include "../../model/world/tablemimedata.hpp"
|
||||
#include "../../model/world/commanddispatcher.hpp"
|
||||
#include "../widget/coloreditor.hpp"
|
||||
#include "dialoguespinbox.hpp"
|
||||
#include "scriptedit.hpp"
|
||||
|
||||
|
@ -123,10 +124,19 @@ void CSVWorld::CommandDelegate::setModelDataImp (QWidget *editor, QAbstractItemM
|
|||
if (!mCommandDispatcher)
|
||||
return;
|
||||
|
||||
NastyTableModelHack hack (*model);
|
||||
QStyledItemDelegate::setModelData (editor, &hack, index);
|
||||
|
||||
QVariant new_ = hack.getData();
|
||||
QVariant new_;
|
||||
// Color columns use a custom editor, so we need explicitly extract a data from it
|
||||
CSVWidget::ColorEditor *colorEditor = qobject_cast<CSVWidget::ColorEditor *>(editor);
|
||||
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))
|
||||
mCommandDispatcher->executeModify (model, index, new_);
|
||||
|
@ -162,6 +172,12 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -184,7 +200,7 @@ QWidget *CSVWorld::CommandDelegate::createEditor (QWidget *parent, const QStyleO
|
|||
{
|
||||
case CSMWorld::ColumnBase::Display_Colour:
|
||||
|
||||
return new QLineEdit(parent);
|
||||
return new CSVWidget::ColorEditor(index.data().value<QColor>(), parent);
|
||||
|
||||
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();
|
||||
|
||||
if (n == "dateTime") {
|
||||
|
|
|
@ -91,17 +91,6 @@ add_openmw_dir (mwbase
|
|||
)
|
||||
|
||||
# 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)
|
||||
add_executable(openmw
|
||||
|
@ -126,10 +115,14 @@ target_link_libraries(openmw
|
|||
${OGRE_LIBRARIES}
|
||||
${OGRE_STATIC_PLUGINS}
|
||||
${SHINY_LIBRARIES}
|
||||
${Boost_LIBRARIES}
|
||||
${OPENAL_LIBRARY}
|
||||
${SOUND_INPUT_LIBRARY}
|
||||
${BULLET_LIBRARIES}
|
||||
${Boost_SYSTEM_LIBRARY}
|
||||
${Boost_THREAD_LIBRARY}
|
||||
${Boost_FILESYSTEM_LIBRARY}
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
${Boost_WAVE_LIBRARY}
|
||||
${MYGUI_LIBRARIES}
|
||||
${SDL2_LIBRARY}
|
||||
${MYGUI_PLATFORM_LIBRARIES}
|
||||
|
|
|
@ -677,44 +677,32 @@ namespace MWMechanics
|
|||
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)
|
||||
{
|
||||
Ogre::Vector3 newPathTarget = Ogre::Vector3(target.getRefData().getPosition().pos);
|
||||
|
||||
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;
|
||||
ESM::Pathgrid::Point newPathTarget = PathFinder::MakePathgridPoint(target.getRefData().getPosition());
|
||||
|
||||
//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(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;
|
||||
}
|
||||
}
|
||||
ESM::Pathgrid::Point start(PathFinder::MakePathgridPoint(actor.getRefData().getPosition()));
|
||||
mPathFinder.buildSyncedPath(start, newPathTarget, actor.getCell(), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,9 @@ namespace MWMechanics
|
|||
|
||||
virtual void writeState(ESM::AiSequence::AiSequence &sequence) const;
|
||||
|
||||
protected:
|
||||
virtual bool doesPathNeedRecalc(ESM::Pathgrid::Point dest, const ESM::Cell *cell);
|
||||
|
||||
private:
|
||||
|
||||
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
|
||||
|
||||
/// 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();
|
||||
const ESM::Cell *cell = actor.getCell()->getCell();
|
||||
Movement &movement = actor.getClass().getMovementSettings(actor);
|
||||
|
||||
//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(distance(mPrevDest, dest) > 10) { //Only rebuild path if it's moved
|
||||
mPathFinder.buildPath(start, dest, actor.getCell(), true); //Rebuild path, in case the target has moved
|
||||
if (doesPathNeedRecalc(dest, cell)) { //Only rebuild path if it's moved
|
||||
mPathFinder.buildSyncedPath(start, dest, actor.getCell(), true); //Rebuild path, in case the target has moved
|
||||
mPrevDest = dest;
|
||||
}
|
||||
|
||||
|
@ -123,3 +123,8 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po
|
|||
|
||||
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
|
||||
{
|
||||
struct Cell;
|
||||
namespace AiSequence
|
||||
{
|
||||
struct AiSequence;
|
||||
|
@ -71,6 +72,8 @@ namespace MWMechanics
|
|||
/** \return If the actor has arrived at his destination **/
|
||||
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
|
||||
PathFinder mPathFinder;
|
||||
ObstacleCheck mObstacleCheck;
|
||||
|
|
|
@ -51,64 +51,31 @@ namespace MWMechanics
|
|||
|
||||
bool AiTravel::execute (const MWWorld::Ptr& actor, AiState& state, float duration)
|
||||
{
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
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).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)))
|
||||
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;
|
||||
if(!mPathFinder.isPathConstructed() || cellChange)
|
||||
if (!mPathFinder.isPathConstructed() || cellChange)
|
||||
{
|
||||
mCellX = cell->mData.mX;
|
||||
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;
|
||||
}
|
||||
|
||||
zTurn(actor, Ogre::Degree(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1])));
|
||||
movement.mPosition[1] = 1;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,9 @@ namespace MWMechanics
|
|||
|
||||
virtual int getTypeId() const;
|
||||
|
||||
protected:
|
||||
virtual bool doesPathNeedRecalc(ESM::Pathgrid::Point dest, const ESM::Cell *cell);
|
||||
|
||||
private:
|
||||
float mX;
|
||||
float mY;
|
||||
|
|
|
@ -651,6 +651,9 @@ namespace MWMechanics
|
|||
if (mAllowedNodes.empty())
|
||||
return;
|
||||
|
||||
if (actor.getClass().isPureWaterCreature(actor))
|
||||
return;
|
||||
|
||||
state.moveIn(new AiWanderStorage());
|
||||
|
||||
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),
|
||||
static_cast<float>(dest.mY), static_cast<float>(dest.mZ));
|
||||
actor.getClass().adjustPosition(actor, false);
|
||||
|
||||
// may have changed cell
|
||||
mStoredAvailableNodes = false;
|
||||
}
|
||||
|
||||
void AiWander::getAllowedNodes(const MWWorld::Ptr& actor, const ESM::Cell* cell)
|
||||
|
|
|
@ -114,8 +114,7 @@ namespace MWMechanics
|
|||
}
|
||||
|
||||
PathFinder::PathFinder()
|
||||
: mIsPathConstructed(false),
|
||||
mPathgrid(NULL),
|
||||
: mPathgrid(NULL),
|
||||
mCell(NULL)
|
||||
{
|
||||
}
|
||||
|
@ -124,7 +123,6 @@ namespace MWMechanics
|
|||
{
|
||||
if(!mPath.empty())
|
||||
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)))
|
||||
{
|
||||
mPath.push_back(endPoint);
|
||||
mIsPathConstructed = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -197,7 +194,6 @@ namespace MWMechanics
|
|||
if(!mPathgrid || mPathgrid->mPoints.empty())
|
||||
{
|
||||
mPath.push_back(endPoint);
|
||||
mIsPathConstructed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -235,7 +231,6 @@ namespace MWMechanics
|
|||
if(startNode == endNode.first)
|
||||
{
|
||||
mPath.push_back(endPoint);
|
||||
mIsPathConstructed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -243,7 +238,6 @@ namespace MWMechanics
|
|||
|
||||
if(!mPath.empty())
|
||||
{
|
||||
mIsPathConstructed = true;
|
||||
// Add the destination (which may be different to the closest
|
||||
// pathgrid point). However only add if endNode was the closest
|
||||
// point to endPoint.
|
||||
|
@ -256,14 +250,8 @@ namespace MWMechanics
|
|||
if(endNode.second)
|
||||
mPath.push_back(endPoint);
|
||||
}
|
||||
else
|
||||
mIsPathConstructed = false;
|
||||
}
|
||||
else
|
||||
mIsPathConstructed = false;
|
||||
}
|
||||
else
|
||||
mIsPathConstructed = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -271,7 +259,7 @@ namespace MWMechanics
|
|||
float PathFinder::getZAngleToNext(float x, float y) const
|
||||
{
|
||||
// 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())
|
||||
return 0.;
|
||||
|
||||
|
@ -293,7 +281,6 @@ namespace MWMechanics
|
|||
mPath.pop_front();
|
||||
if(mPath.empty())
|
||||
{
|
||||
mIsPathConstructed = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -301,23 +288,35 @@ namespace MWMechanics
|
|||
return false;
|
||||
}
|
||||
|
||||
// used by AiCombat, see header for the rationale
|
||||
bool PathFinder::syncStart(const std::list<ESM::Pathgrid::Point> &path)
|
||||
// see header for the rationale
|
||||
void PathFinder::buildSyncedPath(const ESM::Pathgrid::Point &startPoint,
|
||||
const ESM::Pathgrid::Point &endPoint,
|
||||
const MWWorld::CellStore* cell,
|
||||
bool allowShortcuts)
|
||||
{
|
||||
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();
|
||||
return true;
|
||||
// if path has one point, then it's the destination.
|
||||
// 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
|
||||
{
|
||||
return mIsPathConstructed;
|
||||
return !mPath.empty();
|
||||
}
|
||||
|
||||
int getPathSize() const
|
||||
|
@ -63,13 +63,13 @@ namespace MWMechanics
|
|||
|
||||
/** Synchronize new path with old one to avoid visiting 1 waypoint 2 times
|
||||
@note
|
||||
If the first point is chosen as the nearest one
|
||||
the situation can occur when the 1st point of the new path is undesirable
|
||||
(i.e. the 2nd point of new path == the 1st point of old path).
|
||||
@param path - old path
|
||||
@return true if such point was found and deleted
|
||||
BuildPath() takes closest PathGrid point to NPC as first point of path.
|
||||
This is undesireable if NPC has just passed a Pathgrid point, as this
|
||||
makes the 2nd point of the new path == the 1st point of old path.
|
||||
Which results in NPC "running in a circle" back to the just passed waypoint.
|
||||
*/
|
||||
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)
|
||||
{
|
||||
|
@ -96,8 +96,6 @@ namespace MWMechanics
|
|||
|
||||
private:
|
||||
|
||||
bool mIsPathConstructed;
|
||||
|
||||
std::list<ESM::Pathgrid::Point> mPath;
|
||||
|
||||
const ESM::Pathgrid *mPathgrid;
|
||||
|
|
|
@ -188,7 +188,7 @@ namespace MWWorld
|
|||
const T *ptr = search(id);
|
||||
if (ptr == 0) {
|
||||
std::ostringstream msg;
|
||||
msg << "Object '" << id << "' not found (const)";
|
||||
msg << T::getRecordType() << " '" << id << "' not found";
|
||||
throw std::runtime_error(msg.str());
|
||||
}
|
||||
return ptr;
|
||||
|
@ -202,7 +202,7 @@ namespace MWWorld
|
|||
if(ptr == 0)
|
||||
{
|
||||
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());
|
||||
}
|
||||
return ptr;
|
||||
|
@ -989,7 +989,7 @@ namespace MWWorld
|
|||
const T *ptr = search(index);
|
||||
if (ptr == 0) {
|
||||
std::ostringstream msg;
|
||||
msg << "Object with index " << index << " not found";
|
||||
msg << T::getRecordType() << " with index " << index << " not found";
|
||||
throw std::runtime_error(msg.str());
|
||||
}
|
||||
return ptr;
|
||||
|
|
|
@ -81,7 +81,6 @@ endif (OPENMW_USE_UNSHIELD)
|
|||
|
||||
source_group(wizard FILES ${WIZARD} ${WIZARD_HEADER})
|
||||
|
||||
find_package(Qt4 REQUIRED)
|
||||
set(QT_USE_QTGUI 1)
|
||||
|
||||
# Set some platform specific settings
|
||||
|
@ -90,12 +89,17 @@ if(WIN32)
|
|||
set(QT_USE_QTMAIN TRUE)
|
||||
endif(WIN32)
|
||||
|
||||
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})
|
||||
if (DESIRED_QT_VERSION MATCHES 4)
|
||||
include(${QT_USE_FILE})
|
||||
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})
|
||||
|
||||
if (OPENMW_USE_UNSHIELD)
|
||||
|
@ -112,11 +116,24 @@ add_executable(openmw-wizard
|
|||
)
|
||||
|
||||
target_link_libraries(openmw-wizard
|
||||
${Boost_LIBRARIES}
|
||||
${QT_LIBRARIES}
|
||||
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)
|
||||
target_link_libraries(openmw-wizard ${LIBUNSHIELD_LIBRARY})
|
||||
endif()
|
||||
|
|
|
@ -38,9 +38,6 @@ int main(int argc, char *argv[])
|
|||
|
||||
QDir::setCurrent(dir.absolutePath());
|
||||
|
||||
// Support non-latin characters
|
||||
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
|
||||
|
||||
Wizard::MainWizard wizard;
|
||||
|
||||
wizard.show();
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include <QWriteLocker>
|
||||
#include <QFileDialog>
|
||||
#include <QFileInfo>
|
||||
#include <QFileInfoListIterator>
|
||||
#include <QStringList>
|
||||
#include <QTextStream>
|
||||
#include <QTextCodec>
|
||||
|
|
|
@ -24,7 +24,6 @@ namespace Wizard
|
|||
class UnshieldWorker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_ENUMS(Wizard::Component)
|
||||
|
||||
public:
|
||||
UnshieldWorker(QObject *parent = 0);
|
||||
|
|
|
@ -126,32 +126,30 @@ add_component_dir (version
|
|||
set (ESM_UI ${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui
|
||||
)
|
||||
|
||||
find_package(Qt4 COMPONENTS QtCore QtGui)
|
||||
if(MINGW)
|
||||
find_package(Bullet REQUIRED COMPONENTS Collision)
|
||||
endif()
|
||||
|
||||
if(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY)
|
||||
add_component_qt_dir (contentselector
|
||||
model/modelitem model/esmfile
|
||||
model/naturalsort model/contentmodel
|
||||
model/loadordererror
|
||||
view/combobox view/contentselector
|
||||
)
|
||||
add_component_qt_dir (config
|
||||
gamesettings
|
||||
launchersettings
|
||||
settingsbase
|
||||
)
|
||||
|
||||
add_component_qt_dir (process
|
||||
processinvoker
|
||||
add_component_qt_dir (contentselector
|
||||
model/modelitem model/esmfile
|
||||
model/naturalsort model/contentmodel
|
||||
model/loadordererror
|
||||
view/combobox view/contentselector
|
||||
)
|
||||
add_component_qt_dir (config
|
||||
gamesettings
|
||||
launchersettings
|
||||
settingsbase
|
||||
)
|
||||
|
||||
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_CPP(MOC_SRCS ${COMPONENT_MOC_FILES})
|
||||
endif(QT_QTGUI_LIBRARY AND QT_QTCORE_LIBRARY)
|
||||
QT4_WRAP_CPP(MOC_SRCS ${COMPONENT_MOC_FILES})
|
||||
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_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})
|
||||
|
||||
target_link_libraries(components
|
||||
${Boost_LIBRARIES}
|
||||
${Boost_SYSTEM_LIBRARY}
|
||||
${Boost_FILESYSTEM_LIBRARY}
|
||||
${Boost_THREAD_LIBRARY}
|
||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||
${Boost_WAVE_LIBRARY}
|
||||
${OGRE_LIBRARIES}
|
||||
${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)
|
||||
add_dependencies (components git-version)
|
||||
endif (GIT_CHECKOUT)
|
||||
|
||||
if(MINGW)
|
||||
target_link_libraries(components ${QT_LIBRARIES} ${BULLET_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
target_link_libraries(components shlwapi)
|
||||
endif()
|
||||
|
|
|
@ -174,16 +174,30 @@ bool Config::GameSettings::writeFile(QTextStream &stream)
|
|||
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:
|
||||
//
|
||||
// - 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 ',',
|
||||
// '\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
|
||||
//
|
||||
// - 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)
|
||||
{
|
||||
QTextStream stream(&file);
|
||||
|
@ -203,60 +217,124 @@ bool Config::GameSettings::writeFileWithComments(QFile &file)
|
|||
if (fileCopy.empty())
|
||||
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*([^,]+)(.*)$");
|
||||
QString settingLine;
|
||||
QMap<QString, QString>::const_iterator settingsIter = mUserSettings.begin();
|
||||
for (; settingsIter != mUserSettings.end(); ++settingsIter)
|
||||
{
|
||||
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;
|
||||
std::vector<QString> comments;
|
||||
std::vector<QString>::iterator commentStart = fileCopy.end();
|
||||
std::map<QString, std::vector<QString> > commentsMap;
|
||||
for (std::vector<QString>::iterator iter = fileCopy.begin(); iter != fileCopy.end(); ++iter)
|
||||
{
|
||||
// skip empty or comment lines
|
||||
if ((*iter).isEmpty() || (*iter).contains(QRegExp("^\\s*#")))
|
||||
continue;
|
||||
|
||||
// look for a key in the line
|
||||
if (settingRegex.indexIn(*iter) == -1 || settingRegex.captureCount() < 2)
|
||||
if (isOrderedLine(*iter))
|
||||
{
|
||||
// no key or first part of value found in line, replace with a null string which
|
||||
// will be remved later
|
||||
*iter = QString();
|
||||
continue;
|
||||
// save in a separate map of comments keyed by "ordered" line
|
||||
if (!comments.empty())
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
// 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())
|
||||
else if ((*iter).isEmpty() || (*iter).contains(QRegExp("^\\s*#")))
|
||||
{
|
||||
// no such key+valStart, replace with a null string which will be remved later
|
||||
*iter = QString();
|
||||
// comment line, save in temp buffer
|
||||
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
|
||||
{
|
||||
*iter = QString(it.key()+it.value());
|
||||
userSettingsCopy.erase(it);
|
||||
int index = settingRegex.indexIn(*iter);
|
||||
|
||||
// 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
|
||||
QString key;
|
||||
QString value;
|
||||
// comments at top of file
|
||||
for (std::vector<QString>::iterator iter = fileCopy.begin(); iter != fileCopy.end(); ++iter)
|
||||
{
|
||||
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
|
||||
// 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";
|
||||
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";
|
||||
QMap<QString, QString>::const_iterator it = userSettingsCopy.begin();
|
||||
for (; it != userSettingsCopy.end(); ++it)
|
||||
it.previous();
|
||||
|
||||
// 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());
|
||||
|
|
|
@ -83,6 +83,8 @@ namespace Config
|
|||
QString mDataLocal;
|
||||
|
||||
static const char sContentKey[];
|
||||
|
||||
bool isOrderedLine(const QString& line) const;
|
||||
};
|
||||
}
|
||||
#endif // GAMESETTINGS_HPP
|
||||
|
|
|
@ -30,17 +30,6 @@ ContentSelectorModel::ContentModel::~ContentModel()
|
|||
void ContentSelectorModel::ContentModel::setEncoding(const QString &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
|
||||
|
@ -484,6 +473,13 @@ void ContentSelectorModel::ContentModel::addFiles(const QString &path)
|
|||
sortFiles();
|
||||
}
|
||||
|
||||
void ContentSelectorModel::ContentModel::clearFiles()
|
||||
{
|
||||
beginRemoveRows(QModelIndex(), 0, mFiles.count()-1);
|
||||
mFiles.clear();
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
QStringList ContentSelectorModel::ContentModel::gameFiles() const
|
||||
{
|
||||
QStringList gameFiles;
|
||||
|
|
|
@ -44,6 +44,7 @@ namespace ContentSelectorModel
|
|||
bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent);
|
||||
|
||||
void addFiles(const QString &path);
|
||||
void clearFiles();
|
||||
|
||||
QModelIndex indexFromItem(const EsmFile *item) const;
|
||||
const EsmFile *item(const QString &name) const;
|
||||
|
@ -81,7 +82,6 @@ namespace ContentSelectorModel
|
|||
ContentFileList mFiles;
|
||||
QHash<QString, Qt::CheckState> mCheckStates;
|
||||
QSet<QString> mPluginsWithLoadOrderError;
|
||||
QTextCodec *mCodec;
|
||||
QString mEncoding;
|
||||
QIcon mWarningIcon;
|
||||
|
||||
|
|
|
@ -150,6 +150,11 @@ void ContentSelectorView::ContentSelector::addFiles(const QString &path)
|
|||
mContentModel->uncheckAll();
|
||||
}
|
||||
|
||||
void ContentSelectorView::ContentSelector::clearFiles()
|
||||
{
|
||||
mContentModel->clearFiles();
|
||||
}
|
||||
|
||||
QString ContentSelectorView::ContentSelector::currentFile() const
|
||||
{
|
||||
QModelIndex currentIdx = ui.addonView->currentIndex();
|
||||
|
|
|
@ -29,6 +29,7 @@ namespace ContentSelectorView
|
|||
QString currentFile() const;
|
||||
|
||||
void addFiles(const QString &path);
|
||||
void clearFiles();
|
||||
void setProfileContent (const QStringList &fileList);
|
||||
|
||||
void clearCheckStates();
|
||||
|
|
|
@ -12,6 +12,8 @@ class ESMWriter;
|
|||
struct Activator
|
||||
{
|
||||
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;
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@ struct Potion
|
|||
{
|
||||
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
|
||||
{
|
||||
float mWeight;
|
||||
|
|
|
@ -16,6 +16,8 @@ class ESMWriter;
|
|||
struct Apparatus
|
||||
{
|
||||
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
|
||||
{
|
||||
|
|
|
@ -66,6 +66,8 @@ struct PartReferenceList
|
|||
struct Armor
|
||||
{
|
||||
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
|
||||
{
|
||||
|
|
|
@ -12,6 +12,8 @@ class ESMWriter;
|
|||
struct BodyPart
|
||||
{
|
||||
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
|
||||
{
|
||||
|
|
|
@ -15,6 +15,8 @@ class ESMWriter;
|
|||
struct Book
|
||||
{
|
||||
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
|
||||
{
|
||||
|
|
|
@ -14,6 +14,8 @@ class ESMWriter;
|
|||
struct BirthSign
|
||||
{
|
||||
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;
|
||||
|
||||
|
|
|
@ -56,6 +56,8 @@ typedef std::list<CellRef> CellRefTracker;
|
|||
struct Cell
|
||||
{
|
||||
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
|
||||
{
|
||||
|
|
|
@ -18,6 +18,8 @@ class ESMWriter;
|
|||
struct Class
|
||||
{
|
||||
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
|
||||
{
|
||||
|
|
|
@ -18,6 +18,8 @@ class ESMWriter;
|
|||
struct Clothing
|
||||
{
|
||||
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
|
||||
{
|
||||
|
|
|
@ -36,6 +36,8 @@ struct InventoryList
|
|||
struct Container
|
||||
{
|
||||
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
|
||||
{
|
||||
|
|
|
@ -22,6 +22,8 @@ class ESMWriter;
|
|||
struct Creature
|
||||
{
|
||||
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?
|
||||
enum Flags
|
||||
|
|
|
@ -21,6 +21,8 @@ class ESMWriter;
|
|||
struct Dialogue
|
||||
{
|
||||
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
|
||||
{
|
||||
|
|
|
@ -12,6 +12,8 @@ class ESMWriter;
|
|||
struct Door
|
||||
{
|
||||
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;
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@ class ESMWriter;
|
|||
struct Enchantment
|
||||
{
|
||||
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
|
||||
{
|
||||
|
|
|
@ -30,6 +30,8 @@ struct RankData
|
|||
struct Faction
|
||||
{
|
||||
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;
|
||||
|
||||
|
|
|
@ -18,6 +18,8 @@ class ESMWriter;
|
|||
struct Global
|
||||
{
|
||||
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;
|
||||
Variant mValue;
|
||||
|
|
|
@ -19,6 +19,8 @@ class ESMWriter;
|
|||
struct GameSetting
|
||||
{
|
||||
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;
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@ class ESMWriter;
|
|||
struct DialInfo
|
||||
{
|
||||
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
|
||||
{
|
||||
|
|
|
@ -16,6 +16,8 @@ class ESMWriter;
|
|||
struct Ingredient
|
||||
{
|
||||
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
|
||||
{
|
||||
|
|
|
@ -18,6 +18,8 @@ class ESMWriter;
|
|||
struct Land
|
||||
{
|
||||
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();
|
||||
|
|
|
@ -46,6 +46,8 @@ struct LevelledListBase
|
|||
struct CreatureLevList: LevelledListBase
|
||||
{
|
||||
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
|
||||
{
|
||||
|
@ -64,6 +66,8 @@ struct CreatureLevList: LevelledListBase
|
|||
struct ItemLevList: LevelledListBase
|
||||
{
|
||||
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
|
||||
{
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue